[会员管理]-移除
This commit is contained in:
@@ -1,155 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('user.group.GroupName') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table ref="tableRef" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm ref="formRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { getUserRules } from '/@/api/backend/user/group'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import { uuid } from '/@/utils/random'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/group',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.Group/'),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.group.Group name'), prop: 'name', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('State'),
|
||||
prop: 'status',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { 0: 'danger', 1: 'success' },
|
||||
replaceValue: { 0: t('Disable'), 1: t('Enable') },
|
||||
},
|
||||
{ label: t('Update time'), prop: 'update_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
width: '130',
|
||||
render: 'buttons',
|
||||
buttons: defaultOptButtons(['edit', 'delete']),
|
||||
operator: false,
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
status: 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 利用提交前钩子重写提交操作
|
||||
baTable.before.onSubmit = ({ formEl, operate, items }) => {
|
||||
let submitCallback = () => {
|
||||
baTable.form.submitLoading = true
|
||||
baTable.api
|
||||
.postData(operate, {
|
||||
...items,
|
||||
rules: formRef.value?.getCheckeds(),
|
||||
})
|
||||
.then((res) => {
|
||||
baTable.onTableHeaderAction('refresh', {})
|
||||
baTable.form.submitLoading = false
|
||||
baTable.form.operateIds?.shift()
|
||||
if (baTable.form.operateIds!.length > 0) {
|
||||
baTable.toggleForm('Edit', baTable.form.operateIds)
|
||||
} else {
|
||||
baTable.toggleForm()
|
||||
}
|
||||
baTable.runAfter('onSubmit', { res })
|
||||
})
|
||||
.catch(() => {
|
||||
baTable.form.submitLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
if (formEl) {
|
||||
baTable.form.ref = formEl
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
submitCallback()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
submitCallback()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 打开表单后
|
||||
baTable.after.toggleForm = ({ operate }) => {
|
||||
if (operate == 'Add') {
|
||||
menuRuleTreeUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取到编辑数据后
|
||||
baTable.after.getEditData = () => {
|
||||
menuRuleTreeUpdate()
|
||||
}
|
||||
|
||||
const menuRuleTreeUpdate = () => {
|
||||
getUserRules().then((res) => {
|
||||
baTable.form.extend!.menuRules = res.data.list
|
||||
|
||||
if (baTable.form.items!.rules && baTable.form.items!.rules.length) {
|
||||
if (baTable.form.items!.rules.includes('*')) {
|
||||
let arr: number[] = []
|
||||
for (const key in baTable.form.extend!.menuRules) {
|
||||
arr.push(baTable.form.extend!.menuRules[key].id)
|
||||
}
|
||||
baTable.form.extend!.defaultCheckedKeys = arr
|
||||
} else {
|
||||
baTable.form.extend!.defaultCheckedKeys = baTable.form.items!.rules
|
||||
}
|
||||
} else {
|
||||
baTable.form.extend!.defaultCheckedKeys = []
|
||||
}
|
||||
baTable.form.extend!.treeKey = uuid()
|
||||
})
|
||||
}
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,145 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
top="10vh"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@submit.prevent=""
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
>
|
||||
<el-form-item prop="name" :label="t('user.group.Group name')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.name"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.group.Group name') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="auth" :label="t('user.group.jurisdiction')">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:key="baTable.form.extend!.treeKey"
|
||||
:default-checked-keys="baTable.form.extend!.defaultCheckedKeys"
|
||||
:default-expand-all="true"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'title', class: treeNodeClass }"
|
||||
:data="baTable.form.extend!.menuRules"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Disable'), 1: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import type { ElTree, FormItemRule } from 'element-plus'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const treeRef = useTemplateRef('treeRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
name: [buildValidatorData({ name: 'required', title: t('user.group.Group name') })],
|
||||
auth: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
let ids = getCheckeds()
|
||||
if (ids.length <= 0) {
|
||||
return callback(new Error(t('Please select field', { field: t('user.group.jurisdiction') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const getCheckeds = () => {
|
||||
return treeRef.value!.getCheckedKeys().concat(treeRef.value!.getHalfCheckedKeys())
|
||||
}
|
||||
|
||||
const treeNodeClass = (data: anyObj, node: Node) => {
|
||||
if (node.isLeaf) return ''
|
||||
let addClass = true
|
||||
for (const key in node.childNodes) {
|
||||
if (!node.childNodes[key].isLeaf) {
|
||||
addClass = false
|
||||
}
|
||||
}
|
||||
return addClass ? 'penultimate-node' : ''
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getCheckeds,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.penultimate-node) {
|
||||
.el-tree-node__children {
|
||||
padding-left: 60px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 12px;
|
||||
.el-tree-node {
|
||||
display: inline-block;
|
||||
}
|
||||
.el-tree-node__content {
|
||||
padding-left: 5px !important;
|
||||
padding-right: 5px;
|
||||
.el-tree-node__expand-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,147 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="
|
||||
t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') })
|
||||
"
|
||||
>
|
||||
<el-button v-if="!isEmpty(state.userInfo)" v-blur class="table-header-operate">
|
||||
<span class="table-header-operate-text">
|
||||
{{ state.userInfo.username + '(ID:' + state.userInfo.id + ') ' + t('user.moneyLog.balance') + ':' + state.userInfo.money }}
|
||||
</span>
|
||||
</el-button>
|
||||
</TableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { debounce, isEmpty, parseInt } from 'lodash-es'
|
||||
import { provide, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { add, url } from '/@/api/backend/user/moneyLog'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/moneyLog',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const defalutUser = (route.query.user_id ?? '') as string
|
||||
const state = reactive({
|
||||
userInfo: {} as anyObj,
|
||||
})
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi(url),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.moneyLog.User ID'), prop: 'user_id', align: 'center', width: 70 },
|
||||
{ label: t('user.moneyLog.User name'), prop: 'user.username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.moneyLog.User nickname'),
|
||||
prop: 'user.nickname',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{ label: t('user.moneyLog.Change balance'), prop: 'money', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{
|
||||
label: t('user.moneyLog.remarks'),
|
||||
prop: 'memo',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
],
|
||||
dblClickNotEditColumn: ['all'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
user_id: defalutUser,
|
||||
memo: '',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交后
|
||||
baTable.after.onSubmit = () => {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
baTable.after.onTableHeaderAction = ({ event }) => {
|
||||
// 刷新后
|
||||
if (event == 'refresh') {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
baTable.before.onTableAction = ({ event }) => {
|
||||
// 公共搜索
|
||||
if (event === 'com-search') {
|
||||
baTable.table.filter!.search = baTable.getComSearchData()
|
||||
|
||||
for (const key in baTable.table.filter!.search) {
|
||||
if (['money', 'before', 'after'].includes(baTable.table.filter!.search[key].field)) {
|
||||
const val = (baTable.table.filter!.search[key].val as string).split(',')
|
||||
const newVal: (string | number)[] = []
|
||||
for (const k in val) {
|
||||
newVal.push(isNaN(parseFloat(val[k])) ? '' : parseFloat(val[k]) * 100)
|
||||
}
|
||||
baTable.table.filter!.search[key].val = newVal.join(',')
|
||||
}
|
||||
}
|
||||
|
||||
baTable.onTableHeaderAction('refresh', { event: 'com-search', data: baTable.table.filter!.search })
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
const getUserInfo = debounce((userId: string) => {
|
||||
if (userId && parseInt(userId) > 0) {
|
||||
add(userId).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
})
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}, 300)
|
||||
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
|
||||
watch(
|
||||
() => baTable.comSearch.form.user_id,
|
||||
(newVal) => {
|
||||
baTable.form.defaultItems!.user_id = newVal
|
||||
getUserInfo(newVal)
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="user_id"
|
||||
:label="t('user.moneyLog.User ID')"
|
||||
v-model="baTable.form.items!.user_id"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
pk: 'user.id',
|
||||
field: 'nickname_text',
|
||||
remoteUrl: '/admin/user.User/index',
|
||||
onChange: getAdd,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.moneyLog.User name')">
|
||||
<el-input v-model="state.userInfo.username" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.User nickname')">
|
||||
<el-input v-model="state.userInfo.nickname" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.Current balance')">
|
||||
<el-input v-model="state.userInfo.money" disabled type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="money" :label="t('user.moneyLog.Change amount')">
|
||||
<el-input
|
||||
@input="changeMoney"
|
||||
v-model="baTable.form.items!.money"
|
||||
type="number"
|
||||
:placeholder="t('user.moneyLog.Please enter the balance change amount')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.Balance after change')">
|
||||
<el-input v-model="state.after" type="number" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="memo" :label="t('user.moneyLog.remarks')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.memo"
|
||||
type="textarea"
|
||||
:placeholder="t('user.moneyLog.Please enter change remarks / description')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds!.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { add } from '/@/api/backend/user/moneyLog'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const { t } = useI18n()
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
user_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.moneyLog.User') }) })],
|
||||
money: [
|
||||
buildValidatorData({ name: 'required', title: t('user.moneyLog.Change amount') }),
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val || parseFloat(val) == 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('user.moneyLog.Change amount') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
memo: [buildValidatorData({ name: 'required', title: t('user.moneyLog.remarks') })],
|
||||
})
|
||||
|
||||
const formRef = useTemplateRef('formRef')
|
||||
|
||||
const state: {
|
||||
userInfo: anyObj
|
||||
after: number
|
||||
} = reactive({
|
||||
userInfo: {},
|
||||
after: 0,
|
||||
})
|
||||
|
||||
const getAdd = () => {
|
||||
if (!baTable.form.items!.user_id || parseInt(baTable.form.items!.user_id) <= 0) {
|
||||
return
|
||||
}
|
||||
add(baTable.form.items!.user_id).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
state.after = res.data.user.money
|
||||
})
|
||||
}
|
||||
|
||||
const changeMoney = (value: string) => {
|
||||
if (!state.userInfo || typeof state.userInfo == 'undefined') {
|
||||
state.after = 0
|
||||
return
|
||||
}
|
||||
let newValue = value == '' ? 0 : parseFloat(value)
|
||||
state.after = parseFloat((parseFloat(state.userInfo.money) + newValue).toFixed(2))
|
||||
}
|
||||
|
||||
// 打开表单时刷新用户数据
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getAdd()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.preview-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'unfold', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('auth.rule.Rule title') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table ref="tableRef" :pagination="false" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/rule',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.Rule/'),
|
||||
{
|
||||
expandAll: false,
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('auth.rule.title'), prop: 'title', align: 'left', width: '200' },
|
||||
{ label: t('auth.rule.Icon'), prop: 'icon', align: 'center', width: '60', render: 'icon', default: 'fa fa-circle-o' },
|
||||
{ label: t('auth.rule.name'), prop: 'name', align: 'center', showOverflowTooltip: true },
|
||||
{
|
||||
label: t('auth.rule.type'),
|
||||
prop: 'type',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { menu: 'danger', menu_dir: 'success', route: 'info' },
|
||||
replaceValue: {
|
||||
menu: t('user.rule.Member center menu items'),
|
||||
menu_dir: t('user.rule.Member center menu contents'),
|
||||
route: t('user.rule.Normal routing'),
|
||||
nav: t('user.rule.Top bar menu items'),
|
||||
button: t('user.rule.Page button'),
|
||||
nav_user_menu: t('user.rule.Top bar user dropdown'),
|
||||
},
|
||||
},
|
||||
{ label: t('State'), prop: 'status', align: 'center', width: '80', render: 'switch' },
|
||||
{ label: t('Update time'), prop: 'update_time', align: 'center', width: '160', render: 'datetime' },
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', width: '160', render: 'datetime' },
|
||||
{ label: t('Operate'), align: 'center', width: '130', render: 'buttons', buttons: defaultOptButtons() },
|
||||
],
|
||||
dblClickNotEditColumn: [undefined, 'status'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
type: 'route',
|
||||
menu_type: 'tab',
|
||||
extend: 'none',
|
||||
no_login_valid: '0',
|
||||
keepalive: 0,
|
||||
status: 1,
|
||||
icon: 'fa fa-circle-o',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交前
|
||||
baTable.before.onSubmit = () => {
|
||||
if (baTable.form.items!.type == 'route') {
|
||||
baTable.form.items!.menu_type = 'tab'
|
||||
} else if (['menu', 'menu_dir', 'nav_user_menu'].includes(baTable.form.items!.type)) {
|
||||
baTable.form.items!.no_login_valid = '0'
|
||||
}
|
||||
}
|
||||
|
||||
// 取得编辑行的数据后
|
||||
baTable.after.getEditData = () => {
|
||||
if (baTable.form.items && !baTable.form.items.icon) {
|
||||
baTable.form.items.icon = 'fa fa-circle-o'
|
||||
}
|
||||
}
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getData()?.then(() => {
|
||||
baTable.dragSort()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,237 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
top="5vh"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="pid"
|
||||
:label="t('auth.rule.Superior menu rule')"
|
||||
v-model="baTable.form.items!.pid"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
params: { isTree: true },
|
||||
field: 'title',
|
||||
remoteUrl: baTable.api.actionUrl.get('index'),
|
||||
emptyValues: ['', null, undefined, 0],
|
||||
valueOnClear: 0,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('auth.rule.Rule type')">
|
||||
<el-radio-group v-model="baTable.form.items!.type">
|
||||
<el-radio class="ba-el-radio" value="route" :border="true">{{ t('user.rule.Normal routing') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="menu_dir" :border="true">{{ t('user.rule.Member center menu contents') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="menu" :border="true">{{ t('user.rule.Member center menu items') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="nav" :border="true">{{ t('user.rule.Top bar menu items') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="button" :border="true">{{ t('user.rule.Page button') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="nav_user_menu" :border="true">{{ t('user.rule.Top bar user dropdown') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="block-help">{{ t('user.rule.Type ' + baTable.form.items!.type + ' tips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item prop="title" :label="t('auth.rule.Rule title')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.title"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('auth.rule.Rule title') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name" :label="t('auth.rule.Rule name')">
|
||||
<el-input v-model="baTable.form.items!.name" type="string" :placeholder="t('user.rule.English name')"></el-input>
|
||||
<div class="block-help">
|
||||
{{ t('auth.rule.It will be registered as the web side routing name and used as the server side API authentication') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.items!.type != 'button'" prop="path" :label="t('auth.rule.Routing path')">
|
||||
<el-input v-model="baTable.form.items!.path" type="string" :placeholder="t('user.rule.Web side routing path')"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 规则图标 -->
|
||||
<FormItem
|
||||
v-if="baTable.form.items!.type != 'button'"
|
||||
type="icon"
|
||||
:label="t('auth.rule.Rule Icon')"
|
||||
v-model="baTable.form.items!.icon"
|
||||
:input-attr="{ showIconName: true }"
|
||||
/>
|
||||
<!-- 菜单类型:tab、link、iframe -->
|
||||
<FormItem
|
||||
v-if="!['menu_dir', 'button', 'route'].includes(baTable.form.items!.type)"
|
||||
:label="t('auth.rule.Menu type')"
|
||||
v-model="baTable.form.items!.menu_type"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { tab: t('auth.rule.Menu type tab'), link: t('auth.rule.Menu type link (offsite)'), iframe: 'Iframe' },
|
||||
}"
|
||||
/>
|
||||
<!-- URL -->
|
||||
<el-form-item
|
||||
prop="url"
|
||||
v-if="!['menu_dir', 'button', 'route'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type != 'tab'"
|
||||
:label="t('auth.rule.Link address')"
|
||||
>
|
||||
<el-input
|
||||
v-model="baTable.form.items!.url"
|
||||
type="string"
|
||||
:placeholder="t('auth.rule.Please enter the URL address of the link or iframe')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<!-- 组件路径 -->
|
||||
<el-form-item
|
||||
v-if="
|
||||
baTable.form.items!.type == 'route' ||
|
||||
(!['menu_dir', 'button'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type == 'tab')
|
||||
"
|
||||
:label="t('auth.rule.Component path')"
|
||||
>
|
||||
<el-input
|
||||
v-model="baTable.form.items!.component"
|
||||
type="string"
|
||||
:placeholder="t('user.rule.For example, if you add account/overview as a route only')"
|
||||
></el-input>
|
||||
<div class="block-help component-path-tips">
|
||||
{{ t('user.rule.Component path tips') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- 扩展属性 -->
|
||||
<el-form-item
|
||||
v-if="!['menu_dir', 'button'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type == 'tab'"
|
||||
:label="t('auth.rule.Extended properties')"
|
||||
>
|
||||
<el-select
|
||||
class="w100"
|
||||
v-model="baTable.form.items!.extend"
|
||||
:placeholder="t('Please select field', { field: t('auth.rule.Extended properties') })"
|
||||
>
|
||||
<el-option :label="t('auth.rule.none')" value="none"></el-option>
|
||||
<el-option :label="t('auth.rule.Add as route only')" value="add_rules_only"></el-option>
|
||||
<el-option :label="t('auth.rule.Add as menu only')" value="add_menu_only"></el-option>
|
||||
</el-select>
|
||||
<div class="block-help">
|
||||
{{ t('user.rule.Web side component path, please start with /src, such as: /src/views/frontend/index') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
v-if="!['menu_dir', 'menu', 'nav_user_menu'].includes(baTable.form.items!.type)"
|
||||
:label="t('user.rule.no_login_valid')"
|
||||
v-model="baTable.form.items!.no_login_valid"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { '0': t('user.rule.no_login_valid 0'), '1': t('user.rule.no_login_valid 1') },
|
||||
}"
|
||||
:block-help="t('user.rule.no_login_valid tips')"
|
||||
/>
|
||||
<el-form-item :label="t('auth.rule.Rule comments')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.remark"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||
:placeholder="t('Please input field', { field: t('auth.rule.Rule comments') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('auth.rule.Rule weight')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.weigh"
|
||||
type="number"
|
||||
:placeholder="t('auth.rule.Please enter the weight of menu rule (sort by)')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Disable'), 1: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
title: [buildValidatorData({ name: 'required', title: t('auth.rule.Rule title') })],
|
||||
pid: [
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val) {
|
||||
return callback()
|
||||
}
|
||||
if (parseInt(val) == parseInt(baTable.form.items!.id)) {
|
||||
return callback(new Error(t('auth.rule.The superior menu rule cannot be the rule itself')))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
name: [buildValidatorData({ name: 'required', title: t('auth.rule.Rule name') })],
|
||||
path: [buildValidatorData({ name: 'required', title: t('auth.rule.Routing path') })],
|
||||
url: [
|
||||
buildValidatorData({ name: 'required', message: t('auth.rule.Link address') }),
|
||||
buildValidatorData({ name: 'url', message: t('auth.rule.Please enter the correct URL') }),
|
||||
],
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ba-el-radio {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.component-path-tips {
|
||||
color: var(--el-color-warning);
|
||||
}
|
||||
</style>
|
||||
@@ -1,126 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="
|
||||
t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') })
|
||||
"
|
||||
>
|
||||
<el-button v-if="!isEmpty(state.userInfo)" v-blur class="table-header-operate">
|
||||
<span class="table-header-operate-text">
|
||||
{{ state.userInfo.username + '(ID:' + state.userInfo.id + ') ' + t('user.scoreLog.integral') + ':' + state.userInfo.score }}
|
||||
</span>
|
||||
</el-button>
|
||||
</TableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { debounce, isEmpty, parseInt } from 'lodash-es'
|
||||
import { provide, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { add, url } from '/@/api/backend/user/scoreLog'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/scoreLog',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const defalutUser = (route.query.user_id ?? '') as string
|
||||
const state = reactive({
|
||||
userInfo: {} as anyObj,
|
||||
})
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi(url),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.moneyLog.User ID'), prop: 'user_id', align: 'center', width: 70 },
|
||||
{ label: t('user.moneyLog.User name'), prop: 'user.username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.moneyLog.User nickname'),
|
||||
prop: 'user.nickname',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{ label: t('user.scoreLog.Change points'), prop: 'score', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{
|
||||
label: t('user.moneyLog.remarks'),
|
||||
prop: 'memo',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
],
|
||||
dblClickNotEditColumn: ['all'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
user_id: defalutUser,
|
||||
memo: '',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交后
|
||||
baTable.after.onSubmit = () => {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
baTable.after.onTableHeaderAction = ({ event }) => {
|
||||
// 刷新后
|
||||
if (event == 'refresh') {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
const getUserInfo = debounce((userId: string) => {
|
||||
if (userId && parseInt(userId) > 0) {
|
||||
add(userId).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
})
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}, 300)
|
||||
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
|
||||
watch(
|
||||
() => baTable.comSearch.form.user_id,
|
||||
(newVal) => {
|
||||
baTable.form.defaultItems!.user_id = newVal
|
||||
getUserInfo(newVal)
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="user_id"
|
||||
:label="t('user.moneyLog.User ID')"
|
||||
v-model="baTable.form.items!.user_id"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
pk: 'user.id',
|
||||
field: 'nickname_text',
|
||||
remoteUrl: '/admin/user.User/index',
|
||||
onChange: getAdd,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.moneyLog.User name')">
|
||||
<el-input v-model="state.userInfo.username" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.User nickname')">
|
||||
<el-input v-model="state.userInfo.nickname" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.scoreLog.Current points')">
|
||||
<el-input v-model="state.userInfo.score" disabled type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="score" :label="t('user.moneyLog.Change amount')">
|
||||
<el-input
|
||||
@input="changeScore"
|
||||
v-model="baTable.form.items!.score"
|
||||
type="number"
|
||||
:placeholder="t('user.scoreLog.Please enter the change amount of points')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.scoreLog.Points after change')">
|
||||
<el-input v-model="state.after" type="number" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="memo" :label="t('user.moneyLog.remarks')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.memo"
|
||||
type="textarea"
|
||||
:placeholder="t('user.scoreLog.Please enter change remarks / description')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds!.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { add } from '/@/api/backend/user/scoreLog'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const { t } = useI18n()
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
user_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.moneyLog.User') }) })],
|
||||
score: [
|
||||
buildValidatorData({ name: 'required', title: t('user.moneyLog.Change amount') }),
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val || parseInt(val) == 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('user.moneyLog.Change amount') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
memo: [buildValidatorData({ name: 'required', title: t('user.moneyLog.remarks') })],
|
||||
})
|
||||
|
||||
const formRef = useTemplateRef('formRef')
|
||||
|
||||
const state: {
|
||||
userInfo: anyObj
|
||||
after: number
|
||||
} = reactive({
|
||||
userInfo: {},
|
||||
after: 0,
|
||||
})
|
||||
|
||||
const getAdd = () => {
|
||||
if (!baTable.form.items!.user_id || parseInt(baTable.form.items!.user_id) <= 0) {
|
||||
return
|
||||
}
|
||||
add(baTable.form.items!.user_id).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
state.after = res.data.user.score
|
||||
})
|
||||
}
|
||||
|
||||
const changeScore = (value: string) => {
|
||||
if (!state.userInfo || typeof state.userInfo == 'undefined') {
|
||||
state.after = 0
|
||||
return
|
||||
}
|
||||
let newValue = value == '' ? 0 : parseFloat(value)
|
||||
state.after = parseFloat(state.userInfo.score) + newValue
|
||||
}
|
||||
|
||||
// 打开表单时刷新用户数据
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getAdd()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.preview-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('user.user.User name') + '/' + t('user.user.nickname') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/user',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.User/'),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.user.User name'), prop: 'username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('user.user.nickname'), prop: 'nickname', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.user.group'),
|
||||
prop: 'userGroup.name',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
render: 'tag',
|
||||
},
|
||||
{ label: t('user.user.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false },
|
||||
{
|
||||
label: t('user.user.Gender'),
|
||||
prop: 'gender',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { '0': 'info', '1': '', '2': 'success' },
|
||||
replaceValue: { '0': t('Unknown'), '1': t('user.user.male'), '2': t('user.user.female') },
|
||||
},
|
||||
{ label: t('user.user.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.user.Last login IP'),
|
||||
prop: 'last_login_ip',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
render: 'tag',
|
||||
},
|
||||
{
|
||||
label: t('user.user.Last login'),
|
||||
prop: 'last_login_time',
|
||||
align: 'center',
|
||||
render: 'datetime',
|
||||
sortable: 'custom',
|
||||
operator: 'RANGE',
|
||||
width: 160,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
label: t('State'),
|
||||
prop: 'status',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { disable: 'danger', enable: 'success' },
|
||||
replaceValue: { disable: t('Disable'), enable: t('Enable') },
|
||||
},
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
width: '100',
|
||||
render: 'buttons',
|
||||
buttons: defaultOptButtons(['edit', 'delete']),
|
||||
operator: false,
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
gender: 0,
|
||||
money: '0',
|
||||
score: '0',
|
||||
status: 'enable',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,238 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:destroy-on-close="true"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<el-form-item prop="username" :label="t('user.user.User name')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.username"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.User name') + '(' + t('user.user.Login account') + ')' })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="nickname" :label="t('user.user.nickname')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.nickname"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.nickname') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
:label="t('user.user.group')"
|
||||
v-model="baTable.form.items!.group_id"
|
||||
prop="group_id"
|
||||
:placeholder="t('user.user.group')"
|
||||
:input-attr="{
|
||||
params: { isTree: true, search: [{ field: 'status', val: '1', operator: 'eq' }] },
|
||||
field: 'name',
|
||||
remoteUrl: '/admin/user.Group/index',
|
||||
}"
|
||||
/>
|
||||
<FormItem :label="t('user.user.avatar')" type="image" v-model="baTable.form.items!.avatar" />
|
||||
<el-form-item prop="email" :label="t('user.user.email')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.email"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.email') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="mobile" :label="t('user.user.mobile')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.mobile"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.mobile') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('user.user.Gender')"
|
||||
v-model="baTable.form.items!.gender"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Unknown'), 1: t('user.user.male'), 2: t('user.user.female') },
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.user.birthday')">
|
||||
<el-date-picker
|
||||
class="w100"
|
||||
value-format="YYYY-MM-DD"
|
||||
v-model="baTable.form.items!.birthday"
|
||||
type="date"
|
||||
:placeholder="t('Please select field', { field: t('user.user.birthday') })"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.operate == 'Edit'" :label="t('user.user.balance')">
|
||||
<el-input v-model="baTable.form.items!.money" readonly>
|
||||
<template #append>
|
||||
<el-button @click="changeAccount('money')">{{ t('user.user.Adjustment balance') }}</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.operate == 'Edit'" :label="t('user.user.integral')">
|
||||
<el-input v-model="baTable.form.items!.score" readonly>
|
||||
<template #append>
|
||||
<el-button @click="changeAccount('score')">{{ t('user.user.Adjust integral') }}</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password" :label="t('user.user.password')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.password"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
:placeholder="
|
||||
baTable.form.operate == 'Add'
|
||||
? t('Please input field', { field: t('user.user.password') })
|
||||
: t('user.user.Please leave blank if not modified')
|
||||
"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="motto" :label="t('user.user.Personal signature')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.motto"
|
||||
type="textarea"
|
||||
:placeholder="t('Please input field', { field: t('user.user.Personal signature') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { disable: t('Disable'), enable: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { regularPassword } from '/@/utils/validate'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import router from '/@/router/index'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
username: [buildValidatorData({ name: 'required', title: t('user.user.User name') }), buildValidatorData({ name: 'account' })],
|
||||
nickname: [buildValidatorData({ name: 'required', title: t('user.user.nickname') })],
|
||||
group_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.user.group') }) })],
|
||||
email: [buildValidatorData({ name: 'email', title: t('user.user.email') })],
|
||||
mobile: [buildValidatorData({ name: 'mobile' })],
|
||||
password: [
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (baTable.form.operate == 'Add') {
|
||||
if (!val) {
|
||||
return callback(new Error(t('Please input field', { field: t('user.user.password') })))
|
||||
}
|
||||
} else {
|
||||
if (!val) {
|
||||
return callback()
|
||||
}
|
||||
}
|
||||
if (!regularPassword(val)) {
|
||||
return callback(new Error(t('validate.Please enter the correct password')))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const changeAccount = (type: string) => {
|
||||
baTable.toggleForm()
|
||||
router.push({
|
||||
name: type == 'money' ? 'user/moneyLog' : 'user/scoreLog',
|
||||
query: {
|
||||
user_id: baTable.form.items!.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newVal) => {
|
||||
rules.password![0].required = newVal == 'Add'
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border-radius: var(--el-border-radius-small);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
border: 1px dashed var(--el-border-color);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
}
|
||||
.avatar-uploader:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.avatar {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
display: block;
|
||||
}
|
||||
.image-slot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user