feat:角色管理添加app端

main
黄伟杰 3 weeks ago
parent e1886d0ebb
commit ca007733bf

@ -37,12 +37,12 @@ export const getMenu = (id: number) => {
} }
// 新增菜单 // 新增菜单
export const createMenu = (data: MenuVO) => { export const createMenu = (data: Partial<MenuVO>) => {
return request.post({ url: '/system/menu/create', data }) return request.post({ url: '/system/menu/create', data })
} }
// 修改菜单 // 修改菜单
export const updateMenu = (data: MenuVO) => { export const updateMenu = (data: Partial<MenuVO>) => {
return request.put({ url: '/system/menu/update', data }) return request.put({ url: '/system/menu/update', data })
} }

@ -17,8 +17,11 @@ export interface PermissionAssignRoleDataScopeReqVO {
} }
// 查询角色拥有的菜单权限 // 查询角色拥有的菜单权限
export const getRoleMenuList = async (roleId: number) => { export const getRoleMenuList = async (roleId: number, clientType?: number) => {
return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId }) return await request.get({
url: '/system/permission/list-role-menus',
params: { roleId, clientType }
})
} }
// 赋予角色菜单权限 // 赋予角色菜单权限

@ -66,16 +66,6 @@
<el-form-item :label="t('SystemManagement.Menu.sort')" prop="sort"> <el-form-item :label="t('SystemManagement.Menu.sort')" prop="sort">
<el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" /> <el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" />
</el-form-item> </el-form-item>
<el-form-item
v-if="clientType === 2 && formData.type === SystemMenuTypeEnum.DIR"
:label="t('SystemManagement.Menu.terminalType')"
prop="terminalType"
>
<el-radio-group v-model="formData.terminalType">
<el-radio :value="1">{{ t('SystemManagement.Menu.terminalTypeMobile') }}</el-radio>
<el-radio :value="2">{{ t('SystemManagement.Menu.terminalTypeScanner') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('SystemManagement.Menu.status')" prop="status"> <el-form-item :label="t('SystemManagement.Menu.status')" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
<el-radio <el-radio
@ -162,15 +152,13 @@ const formData = ref({
visible: true, visible: true,
keepAlive: true, keepAlive: true,
alwaysShow: true, alwaysShow: true,
clientType: 1, clientType: 1
terminalType: 1
}) })
const formRules = computed(() => ({ const formRules = computed(() => ({
name: [{ required: true, message: t('SystemManagement.Menu.nameRequired'), trigger: 'blur' }], name: [{ required: true, message: t('SystemManagement.Menu.nameRequired'), trigger: 'blur' }],
sort: [{ required: true, message: t('SystemManagement.Menu.sortRequired'), trigger: 'blur' }], sort: [{ required: true, message: t('SystemManagement.Menu.sortRequired'), trigger: 'blur' }],
path: [{ required: clientType.value === 1, message: t('SystemManagement.Menu.pathRequired'), trigger: 'blur' }], path: [{ required: clientType.value === 1, message: t('SystemManagement.Menu.pathRequired'), trigger: 'blur' }],
status: [{ required: true, message: t('SystemManagement.Menu.statusRequired'), trigger: 'blur' }], status: [{ required: true, message: t('SystemManagement.Menu.statusRequired'), trigger: 'blur' }]
terminalType: [{ required: clientType.value === 2 && formData.value.type === SystemMenuTypeEnum.DIR, message: t('SystemManagement.Menu.terminalTypeRequired'), trigger: 'change' }]
})) }))
const formRef = ref() // Ref const formRef = ref() // Ref
@ -222,16 +210,13 @@ const submitForm = async () => {
} }
} }
} }
const data = formData.value as unknown as MenuApi.MenuVO & { terminalType?: number } const { terminalType: _terminalType, ...data } = formData.value as typeof formData.value & { terminalType?: number }
data.clientType = clientType.value data.clientType = clientType.value
data.terminalType = clientType.value === 2 && formData.value.type === SystemMenuTypeEnum.DIR
? formData.value.terminalType
: undefined
if (formType.value === 'create') { if (formType.value === 'create') {
await MenuApi.createMenu(data) await MenuApi.createMenu(data as unknown as MenuApi.MenuVO)
message.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await MenuApi.updateMenu(data) await MenuApi.updateMenu(data as unknown as MenuApi.MenuVO)
message.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
dialogVisible.value = false dialogVisible.value = false
@ -272,8 +257,7 @@ const resetForm = () => {
visible: true, visible: true,
keepAlive: true, keepAlive: true,
alwaysShow: true, alwaysShow: true,
clientType: 1, clientType: 1
terminalType: 1
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }

@ -88,16 +88,6 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="t('SystemManagement.Menu.sort')" prop="sort" width="80" /> <el-table-column :label="t('SystemManagement.Menu.sort')" prop="sort" width="80" />
<el-table-column
v-if="activeClientType === 2"
:label="t('SystemManagement.Menu.terminalType')"
prop="terminalType"
width="120"
>
<template #default="scope">
{{ getTerminalTypeLabel(scope.row.terminalType) }}
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.permission')" prop="permission" /> <el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.permission')" prop="permission" />
<el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.component')" prop="component" /> <el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.component')" prop="component" />
<el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.componentName')" prop="componentName" sortable /> <el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.componentName')" prop="componentName" sortable />
@ -197,11 +187,6 @@ const handleClientTypeChange = (val: number | string) => {
getList() getList()
} }
const getTerminalTypeLabel = (value?: number) => {
if (Number(value) === 2) return t('SystemManagement.Menu.terminalTypeScanner')
return t('SystemManagement.Menu.terminalTypeMobile')
}
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value.resetFields()

@ -16,6 +16,12 @@
<el-form-item :label="t('SystemManagement.Role.menuPermission')"> <el-form-item :label="t('SystemManagement.Role.menuPermission')">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never"> <el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<template #header> <template #header>
<div class="role-assign-menu-form__header">
<el-tabs v-model="activeClientType" @tab-change="handleClientTypeChange">
<el-tab-pane :label="t('SystemManagement.Menu.clientTypeWeb')" :name="1" />
<el-tab-pane :label="t('SystemManagement.Menu.clientTypeApp')" :name="2" />
</el-tabs>
<div class="role-assign-menu-form__actions">
{{ t('SystemManagement.Role.selectAll') }}: {{ t('SystemManagement.Role.selectAll') }}:
<el-switch <el-switch
v-model="treeNodeAll" v-model="treeNodeAll"
@ -32,6 +38,8 @@
inline-prompt inline-prompt
@change="handleCheckedTreeExpand" @change="handleCheckedTreeExpand"
/> />
</div>
</div>
</template> </template>
<el-tree <el-tree
ref="treeRef" ref="treeRef"
@ -58,12 +66,19 @@ import * as PermissionApi from '@/api/system/permission'
defineOptions({ name: 'SystemRoleAssignMenuForm' }) defineOptions({ name: 'SystemRoleAssignMenuForm' })
interface RoleAssignMenuFormData {
id: number | undefined
name: string
code: string
menuIds: number[]
}
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const formLoading = ref(false) // 12 const formLoading = ref(false) // 12
const formData = reactive({ const formData = reactive<RoleAssignMenuFormData>({
id: undefined, id: undefined,
name: '', name: '',
code: '', code: '',
@ -74,30 +89,80 @@ const menuOptions = ref<any[]>([]) // 菜单树形结构
const menuExpand = ref(false) // / const menuExpand = ref(false) // /
const treeRef = ref() // Ref const treeRef = ref() // Ref
const treeNodeAll = ref(false) // / const treeNodeAll = ref(false) // /
const activeClientType = ref(1) // 1=Web2=APP
const currentTreeClientType = ref(1) //
const roleMenuIdsByClientType = reactive<Record<number, number[]>>({
1: [],
2: []
})
const loadedClientTypes = reactive<Record<number, boolean>>({
1: false,
2: false
})
const getCurrentTreeMenuIds = () => {
if (!treeRef.value) return []
return Array.from(new Set([
...(treeRef.value.getCheckedKeys(false) as Array<number>),
...(treeRef.value.getHalfCheckedKeys() as Array<number>)
]))
}
const saveCurrentClientMenuIds = () => {
if (!dialogVisible.value) return
roleMenuIdsByClientType[currentTreeClientType.value] = getCurrentTreeMenuIds()
}
const ensureRoleMenuIdsLoaded = async (roleId: number, clientType: number) => {
if (loadedClientTypes[clientType]) return
roleMenuIdsByClientType[clientType] = await PermissionApi.getRoleMenuList(roleId, clientType)
loadedClientTypes[clientType] = true
}
const loadRoleMenus = async (roleId: number) => {
currentTreeClientType.value = activeClientType.value
treeNodeAll.value = false
menuExpand.value = false
treeRef.value?.setCheckedNodes([])
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList(currentTreeClientType.value))
await ensureRoleMenuIdsLoaded(roleId, currentTreeClientType.value)
await nextTick()
formData.menuIds = roleMenuIdsByClientType[currentTreeClientType.value] ?? []
formData.menuIds.forEach((menuId: number) => {
treeRef.value.setChecked(menuId, true, false)
})
}
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (row: RoleApi.RoleVO) => { const open = async (row: RoleApi.RoleVO) => {
dialogVisible.value = true dialogVisible.value = true
resetForm() resetForm()
// Menu setChecked
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList())
// //
formData.id = row.id formData.id = row.id
formData.name = row.name formData.name = row.name
formData.code = row.code formData.code = row.code
formLoading.value = true formLoading.value = true
try { try {
formData.menuIds = await PermissionApi.getRoleMenuList(row.id) await loadRoleMenus(row.id)
//
formData.menuIds.forEach((menuId: number) => {
treeRef.value.setChecked(menuId, true, false)
})
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
} }
defineExpose({ open }) // open defineExpose({ open }) // open
/** 切换客户端类型 */
const handleClientTypeChange = async (val: number | string) => {
saveCurrentClientMenuIds()
activeClientType.value = Number(val)
if (!dialogVisible.value || !formData.id) return
formLoading.value = true
try {
await loadRoleMenus(formData.id)
} finally {
formLoading.value = false
}
}
/** 提交表单 */ /** 提交表单 */
const emit = defineEmits(['success']) // success const emit = defineEmits(['success']) // success
const submitForm = async () => { const submitForm = async () => {
@ -105,15 +170,18 @@ const submitForm = async () => {
if (!formRef) return if (!formRef) return
const valid = await formRef.value.validate() const valid = await formRef.value.validate()
if (!valid) return if (!valid) return
if (formData.id === undefined) return
saveCurrentClientMenuIds()
// //
formLoading.value = true formLoading.value = true
try { try {
await Promise.all([1, 2].map((clientType) => ensureRoleMenuIdsLoaded(formData.id as number, clientType)))
const data = { const data = {
roleId: formData.id, roleId: formData.id,
menuIds: [ menuIds: Array.from(new Set([
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // ...roleMenuIdsByClientType[1],
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // ...roleMenuIdsByClientType[2]
] ]))
} }
await PermissionApi.assignRoleMenu(data) await PermissionApi.assignRoleMenu(data)
message.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
@ -128,6 +196,8 @@ const submitForm = async () => {
/** 重置表单 */ /** 重置表单 */
const resetForm = () => { const resetForm = () => {
// //
activeClientType.value = 1
currentTreeClientType.value = 1
treeNodeAll.value = false treeNodeAll.value = false
menuExpand.value = false menuExpand.value = false
// //
@ -135,6 +205,10 @@ const resetForm = () => {
formData.name = '' formData.name = ''
formData.code = '' formData.code = ''
formData.menuIds = [] formData.menuIds = []
roleMenuIdsByClientType[1] = []
roleMenuIdsByClientType[2] = []
loadedClientTypes[1] = false
loadedClientTypes[2] = false
treeRef.value?.setCheckedNodes([]) treeRef.value?.setCheckedNodes([])
formRef.value?.resetFields() formRef.value?.resetFields()
} }
@ -160,4 +234,22 @@ const handleCheckedTreeExpand = () => {
.role-assign-menu-form :deep(.el-form-item__label) { .role-assign-menu-form :deep(.el-form-item__label) {
min-width: 80px; min-width: 80px;
} }
.role-assign-menu-form__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.role-assign-menu-form__header :deep(.el-tabs__header) {
margin: 0;
}
.role-assign-menu-form__actions {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
</style> </style>

Loading…
Cancel
Save