1.优化后台管理员管理页面的权限设置,新增zihuaadmin账号
This commit is contained in:
@@ -3,6 +3,7 @@ export default {
|
||||
nickname: 'Nickname',
|
||||
group: 'Group',
|
||||
channel: 'Channel',
|
||||
channel_inherit_from_parent: 'Channel is inherited from the selected parent agent and cannot be changed separately.',
|
||||
parent_admin: 'Parent agent',
|
||||
commission_share_rate: 'Commission share (%)',
|
||||
avatar: 'Avatar',
|
||||
@@ -16,7 +17,7 @@ export default {
|
||||
'Personal signature': 'Personal Signature',
|
||||
'Administrator login': 'Administrator Login Name',
|
||||
'Manage subordinate agents here':
|
||||
'Manage your subordinate agents here. You can only see yourself and your downline, not sub-agents under other agents.',
|
||||
'Manage administrators within your role-group scope (all accounts in your groups and child groups, plus agents in your downline).',
|
||||
'Parent admin placeholder': 'Leave empty for top-level channel agent',
|
||||
'Top level group parent hint':
|
||||
'The selected role group is top-level; no parent agent is required. Settlement uses the channel commission share configured here.',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
nickname: '昵称',
|
||||
group: '角色组',
|
||||
channel: '渠道',
|
||||
channel_inherit_from_parent: '渠道继承自所选上级代理,不可单独修改',
|
||||
parent_admin: '上级代理',
|
||||
commission_share_rate: '分红比例(%)',
|
||||
avatar: '头像',
|
||||
@@ -15,7 +16,8 @@ export default {
|
||||
'Please leave blank if not modified': '不修改请留空',
|
||||
'Personal signature': '个性签名',
|
||||
'Administrator login': '管理员登录名',
|
||||
'Manage subordinate agents here': '在此管理您下级代理管理员;仅显示您本人及所有下级,无法查看其他代理线下的子代理。',
|
||||
'Manage subordinate agents here':
|
||||
'在此管理您角色组管理范围内的管理员(本人所在角色组及其下级组内的全部账号,并含您代理线下的下级)。',
|
||||
'Parent admin placeholder': '留空表示渠道顶级代理',
|
||||
'Top level group parent hint': '当前角色组为顶级角色组,无需绑定上级代理;系统将按渠道分红比例直接结算至该管理员。',
|
||||
'Top level share formula hint':
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
:placeholder="t('Please input field', { field: t('auth.admin.nickname') })"
|
||||
/>
|
||||
<FormItem
|
||||
v-if="showChannelField"
|
||||
v-if="showChannelEditable"
|
||||
:label="t('auth.admin.channel')"
|
||||
v-model="baTable.form.items!.channel_id"
|
||||
type="remoteSelect"
|
||||
@@ -53,6 +53,12 @@
|
||||
placeholder: t('Click select'),
|
||||
}"
|
||||
/>
|
||||
<el-form-item v-else-if="showChannelReadonly" :label="t('auth.admin.channel')">
|
||||
<el-input :model-value="channelDisplayName" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showChannelReadonly && hasParentAdmin" label=" ">
|
||||
<el-alert :title="t('auth.admin.channel_inherit_from_parent')" type="info" :closable="false" show-icon />
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('auth.admin.group')"
|
||||
v-model="singleGroupValue"
|
||||
@@ -184,6 +190,7 @@ import FormItem from '/@/components/formItem/index.vue'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import createAxios from '/@/utils/axios'
|
||||
import { auth } from '/@/utils/common'
|
||||
|
||||
const config = useConfig()
|
||||
const adminInfo = useAdminInfo()
|
||||
@@ -198,14 +205,52 @@ const isTopLevelGroup = ref(false)
|
||||
|
||||
const isSelfEdit = computed(() => baTable.form.operate === 'Edit' && adminInfo.id == baTable.form.items?.id)
|
||||
|
||||
const showChannelField = computed(() => adminInfo.super && !isSelfEdit.value)
|
||||
const hasChannelIndexAuth = computed(
|
||||
() =>
|
||||
adminInfo.super ||
|
||||
auth({ name: '/admin/channel', subNodeName: '/admin/channel/index' }) ||
|
||||
auth({ name: '/admin/Channel', subNodeName: '/admin/Channel/index' })
|
||||
)
|
||||
|
||||
const hasParentAdmin = computed(() => {
|
||||
const pid = baTable.form.items?.parent_admin_id
|
||||
return pid !== null && pid !== undefined && pid !== '' && Number(pid) > 0
|
||||
})
|
||||
|
||||
const showChannelEditable = computed(
|
||||
() => hasChannelIndexAuth.value && isTopLevelGroup.value && !hasParentAdmin.value && !isSelfEdit.value
|
||||
)
|
||||
|
||||
const channelDisplayName = computed(() => {
|
||||
const row = baTable.form.items
|
||||
if (!row) return ''
|
||||
const name = row['channel_name']
|
||||
if (typeof name === 'string' && name !== '') {
|
||||
return name
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
const showChannelReadonly = computed(() => {
|
||||
if (isSelfEdit.value) return false
|
||||
if (showChannelEditable.value) return false
|
||||
if (hasParentAdmin.value) return true
|
||||
if (!isTopLevelGroup.value && hasChannelForShare.value) return true
|
||||
return channelDisplayName.value !== ''
|
||||
})
|
||||
|
||||
const showParentField = computed(() => adminInfo.super && !isSelfEdit.value)
|
||||
|
||||
const hasChannelForShare = computed(() => {
|
||||
const cid = baTable.form.items?.channel_id
|
||||
return cid !== null && cid !== undefined && cid !== '' && Number(cid) > 0
|
||||
})
|
||||
|
||||
const showShareRateField = computed(() => {
|
||||
if (isSelfEdit.value) return false
|
||||
if (isTopLevelGroup.value) {
|
||||
return adminInfo.super || baTable.form.operate === 'Add'
|
||||
if (!hasChannelForShare.value) return false
|
||||
return hasChannelIndexAuth.value || baTable.form.operate === 'Add'
|
||||
}
|
||||
if (adminInfo.super) {
|
||||
const pid = baTable.form.items?.parent_admin_id
|
||||
@@ -273,24 +318,40 @@ const loadGroupMeta = async (groupId: unknown) => {
|
||||
isTopLevelGroup.value = !!res.data.is_top_level
|
||||
if (isTopLevelGroup.value && baTable.form.items) {
|
||||
baTable.form.items.parent_admin_id = null
|
||||
const metaChannelId = res.data.channel_id
|
||||
if (
|
||||
adminInfo.super &&
|
||||
(baTable.form.items.channel_id === null ||
|
||||
baTable.form.items.channel_id === undefined ||
|
||||
baTable.form.items.channel_id === '') &&
|
||||
metaChannelId !== null &&
|
||||
metaChannelId !== undefined &&
|
||||
metaChannelId !== ''
|
||||
) {
|
||||
baTable.form.items.channel_id = metaChannelId
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
isTopLevelGroup.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadParentChannelMeta = async (parentId: unknown) => {
|
||||
const items = baTable.form.items
|
||||
if (!items) return
|
||||
if (parentId === null || parentId === undefined || parentId === '' || Number(parentId) <= 0) {
|
||||
if (!isTopLevelGroup.value) {
|
||||
items['channel_name'] = ''
|
||||
}
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await createAxios({
|
||||
url: '/admin/auth.Admin/parentMeta',
|
||||
method: 'get',
|
||||
params: { parent_admin_id: parentId },
|
||||
})
|
||||
const cid = res.data.channel_id
|
||||
const cname = res.data.channel_name
|
||||
if (cid !== null && cid !== undefined && cid !== '') {
|
||||
items.channel_id = cid
|
||||
} else {
|
||||
items.channel_id = null
|
||||
}
|
||||
items['channel_name'] = typeof cname === 'string' ? cname : ''
|
||||
} catch {
|
||||
items['channel_name'] = ''
|
||||
}
|
||||
}
|
||||
|
||||
const loadShareRemainder = async () => {
|
||||
if (!showShareRateField.value) {
|
||||
shareHint.value = ''
|
||||
@@ -380,6 +441,15 @@ watch(
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => baTable.form.items?.parent_admin_id,
|
||||
(parentId) => {
|
||||
if (isTopLevelGroup.value) return
|
||||
void loadParentChannelMeta(parentId)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => [
|
||||
baTable.form.items?.parent_admin_id,
|
||||
|
||||
@@ -60,12 +60,6 @@ const baTable: baTableClass = new baTableClass(
|
||||
align: 'left',
|
||||
minWidth: '180',
|
||||
},
|
||||
{
|
||||
label: t('auth.group.channel_name'),
|
||||
prop: 'channel_name',
|
||||
align: 'center',
|
||||
minWidth: '140',
|
||||
},
|
||||
{ label: t('auth.group.jurisdiction'), prop: 'rules', align: 'center' },
|
||||
{
|
||||
label: t('State'),
|
||||
@@ -91,7 +85,6 @@ const baTable: baTableClass = new baTableClass(
|
||||
{
|
||||
defaultItems: {
|
||||
status: 1,
|
||||
channel_id: null,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -101,14 +94,9 @@ baTable.before.onSubmit = ({ formEl, operate, items }) => {
|
||||
let submitCallback = () => {
|
||||
baTable.form.submitLoading = true
|
||||
const postItems: anyObj = { ...items }
|
||||
const pid = Number(postItems.pid ?? 0)
|
||||
if (pid !== 0) {
|
||||
delete postItems.channel_id
|
||||
delete postItems.channel_name
|
||||
delete postItems.channel_admin_username
|
||||
} else if (!adminInfo.super) {
|
||||
delete postItems.channel_id
|
||||
}
|
||||
delete postItems.channel_id
|
||||
delete postItems.channel_name
|
||||
delete postItems.channel_admin_username
|
||||
baTable.api
|
||||
.postData(operate, {
|
||||
...postItems,
|
||||
@@ -168,10 +156,6 @@ baTable.after.toggleForm = ({ operate }) => {
|
||||
|
||||
// 编辑请求完成后钩子
|
||||
baTable.after.getEditData = () => {
|
||||
const pid = Number(baTable.form.items?.pid ?? 0)
|
||||
if (pid !== 0 && baTable.form.items) {
|
||||
delete baTable.form.items.channel_id
|
||||
}
|
||||
menuRuleTreeUpdate()
|
||||
}
|
||||
|
||||
|
||||
@@ -41,43 +41,6 @@
|
||||
valueOnClear: 0,
|
||||
}"
|
||||
/>
|
||||
<p
|
||||
v-if="!isRootGroup"
|
||||
class="group-channel-inherit-hint"
|
||||
:style="{ paddingLeft: (baTable.form.labelWidth ?? 120) + 'px' }"
|
||||
>
|
||||
{{ t('auth.group.channel_inherit_hint') }}
|
||||
</p>
|
||||
|
||||
<!-- 顶级+超管:可选渠道;展示只读渠道名称(channel_id 仅由表单传给后端) -->
|
||||
<FormItem
|
||||
v-if="isRootGroup && adminInfo.super"
|
||||
:label="t('auth.group.channel_id')"
|
||||
v-model="baTable.form.items!.channel_id"
|
||||
type="remoteSelect"
|
||||
prop="channel_id"
|
||||
:input-attr="{
|
||||
pk: 'id',
|
||||
field: 'name',
|
||||
remoteUrl: '/admin/channel/index',
|
||||
placeholder: t('Click select'),
|
||||
emptyValues: ['', null, undefined, 0],
|
||||
valueOnClear: null,
|
||||
}"
|
||||
/>
|
||||
<template v-if="isRootGroup && adminInfo.super && channelPreviewName">
|
||||
<el-form-item :label="t('auth.group.channel_name')">
|
||||
<el-input :model-value="channelPreviewName" readonly />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 子级:只读展示上级对应渠道名称,不提交 channel_id(由后端按父级写入) -->
|
||||
<template v-if="!isRootGroup && channelPreviewName">
|
||||
<el-form-item :label="t('auth.group.channel_name')">
|
||||
<el-input :model-value="channelPreviewName" readonly />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item prop="name" :label="t('auth.group.Group name')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.name"
|
||||
@@ -122,7 +85,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, useTemplateRef, computed, watch } from 'vue'
|
||||
import { reactive, inject, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
@@ -130,105 +93,13 @@ import type { ElTree, FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
import createAxios from '/@/utils/axios'
|
||||
|
||||
const config = useConfig()
|
||||
const adminInfo = useAdminInfo()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const treeRef = useTemplateRef('treeRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
const isRootGroup = computed(() => {
|
||||
const p = baTable.form.items?.pid
|
||||
if (p === undefined || p === null || p === '') {
|
||||
return true
|
||||
}
|
||||
return Number(p) === 0
|
||||
})
|
||||
|
||||
const strFromRow = (key: string): string => {
|
||||
const row = baTable.form.items
|
||||
if (!row) return ''
|
||||
const v = row[key]
|
||||
return typeof v === 'string' ? v : ''
|
||||
}
|
||||
|
||||
const channelPreviewName = computed(() => strFromRow('channel_name'))
|
||||
|
||||
/**
|
||||
* 子角色组:选择上级分组后,只拉取展示用渠道名;channel_id 由后端按父级保存,不在此写入提交字段。
|
||||
*/
|
||||
watch(
|
||||
() => baTable.form.items?.pid,
|
||||
async (pid, oldPid) => {
|
||||
const items = baTable.form.items
|
||||
if (!items || !baTable.form.operate || !['Add', 'Edit'].includes(baTable.form.operate)) {
|
||||
return
|
||||
}
|
||||
const pidNum = Number(pid ?? 0)
|
||||
const oldNum = oldPid === undefined || oldPid === null || oldPid === '' ? null : Number(oldPid)
|
||||
|
||||
if (pidNum === 0) {
|
||||
if (adminInfo.super && oldNum !== null && oldNum !== 0) {
|
||||
items.channel_id = null
|
||||
items['channel_name'] = ''
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
delete items.channel_id
|
||||
|
||||
try {
|
||||
const res = await createAxios(
|
||||
{
|
||||
url: '/admin/auth.Group/edit',
|
||||
method: 'get',
|
||||
params: { id: pidNum },
|
||||
},
|
||||
{ showErrorMessage: false, showCodeMessage: false }
|
||||
)
|
||||
const row = res.data.row
|
||||
if (row) {
|
||||
items['channel_name'] = typeof row.channel_name === 'string' ? row.channel_name : ''
|
||||
}
|
||||
} catch {
|
||||
items['channel_name'] = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/** 顶级+超管:所选渠道变更时刷新只读渠道名 */
|
||||
watch(
|
||||
() => baTable.form.items?.channel_id,
|
||||
async (cid) => {
|
||||
const items = baTable.form.items
|
||||
if (!items || !baTable.form.operate || !['Add', 'Edit'].includes(baTable.form.operate)) {
|
||||
return
|
||||
}
|
||||
if (!isRootGroup.value || !adminInfo.super) {
|
||||
return
|
||||
}
|
||||
if (cid === null || cid === undefined || cid === '') {
|
||||
items['channel_name'] = ''
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await createAxios(
|
||||
{
|
||||
url: '/admin/auth.Group/channelBindPreview',
|
||||
method: 'get',
|
||||
params: { channel_id: cid },
|
||||
},
|
||||
{ showErrorMessage: false, showCodeMessage: false }
|
||||
)
|
||||
items['channel_name'] = typeof res.data.channel_name === 'string' ? res.data.channel_name : ''
|
||||
} catch {
|
||||
items['channel_name'] = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
name: [buildValidatorData({ name: 'required', title: t('auth.group.Group name') })],
|
||||
@@ -281,14 +152,6 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.group-channel-inherit-hint {
|
||||
margin: -6px 0 14px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: var(--el-text-color-secondary);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(.penultimate-node) {
|
||||
.el-tree-node__children {
|
||||
padding-left: 60px;
|
||||
|
||||
Reference in New Issue
Block a user