feat:角色管理添加app端

main
黄伟杰 2 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 })
}
// 修改菜单
export const updateMenu = (data: MenuVO) => {
export const updateMenu = (data: Partial<MenuVO>) => {
return request.put({ url: '/system/menu/update', data })
}

@ -17,8 +17,11 @@ export interface PermissionAssignRoleDataScopeReqVO {
}
// 查询角色拥有的菜单权限
export const getRoleMenuList = async (roleId: number) => {
return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId })
export const getRoleMenuList = async (roleId: number, clientType?: number) => {
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-input-number v-model="formData.sort" :min="0" clearable controls-position="right" />
</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-radio-group v-model="formData.status">
<el-radio
@ -162,15 +152,13 @@ const formData = ref({
visible: true,
keepAlive: true,
alwaysShow: true,
clientType: 1,
terminalType: 1
clientType: 1
})
const formRules = computed(() => ({
name: [{ required: true, message: t('SystemManagement.Menu.nameRequired'), trigger: 'blur' }],
sort: [{ required: true, message: t('SystemManagement.Menu.sortRequired'), trigger: 'blur' }],
path: [{ required: clientType.value === 1, message: t('SystemManagement.Menu.pathRequired'), 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' }]
status: [{ required: true, message: t('SystemManagement.Menu.statusRequired'), trigger: 'blur' }]
}))
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.terminalType = clientType.value === 2 && formData.value.type === SystemMenuTypeEnum.DIR
? formData.value.terminalType
: undefined
if (formType.value === 'create') {
await MenuApi.createMenu(data)
await MenuApi.createMenu(data as unknown as MenuApi.MenuVO)
message.success(t('common.createSuccess'))
} else {
await MenuApi.updateMenu(data)
await MenuApi.updateMenu(data as unknown as MenuApi.MenuVO)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
@ -272,8 +257,7 @@ const resetForm = () => {
visible: true,
keepAlive: true,
alwaysShow: true,
clientType: 1,
terminalType: 1
clientType: 1
}
formRef.value?.resetFields()
}

@ -88,16 +88,6 @@
</template>
</el-table-column>
<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.component')" prop="component" />
<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()
}
const getTerminalTypeLabel = (value?: number) => {
if (Number(value) === 2) return t('SystemManagement.Menu.terminalTypeScanner')
return t('SystemManagement.Menu.terminalTypeMobile')
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()

@ -16,6 +16,12 @@
<el-form-item :label="t('SystemManagement.Role.menuPermission')">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<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') }}:
<el-switch
v-model="treeNodeAll"
@ -32,6 +38,8 @@
inline-prompt
@change="handleCheckedTreeExpand"
/>
</div>
</div>
</template>
<el-tree
ref="treeRef"
@ -58,12 +66,19 @@ import * as PermissionApi from '@/api/system/permission'
defineOptions({ name: 'SystemRoleAssignMenuForm' })
interface RoleAssignMenuFormData {
id: number | undefined
name: string
code: string
menuIds: number[]
}
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = reactive({
const formData = reactive<RoleAssignMenuFormData>({
id: undefined,
name: '',
code: '',
@ -74,30 +89,80 @@ const menuOptions = ref<any[]>([]) // 菜单树形结构
const menuExpand = ref(false) // /
const treeRef = ref() // Ref
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) => {
dialogVisible.value = true
resetForm()
// Menu setChecked
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList())
//
formData.id = row.id
formData.name = row.name
formData.code = row.code
formLoading.value = true
try {
formData.menuIds = await PermissionApi.getRoleMenuList(row.id)
//
formData.menuIds.forEach((menuId: number) => {
treeRef.value.setChecked(menuId, true, false)
})
await loadRoleMenus(row.id)
} finally {
formLoading.value = false
}
}
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 submitForm = async () => {
@ -105,15 +170,18 @@ const submitForm = async () => {
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
if (formData.id === undefined) return
saveCurrentClientMenuIds()
//
formLoading.value = true
try {
await Promise.all([1, 2].map((clientType) => ensureRoleMenuIdsLoaded(formData.id as number, clientType)))
const data = {
roleId: formData.id,
menuIds: [
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), //
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) //
]
menuIds: Array.from(new Set([
...roleMenuIdsByClientType[1],
...roleMenuIdsByClientType[2]
]))
}
await PermissionApi.assignRoleMenu(data)
message.success(t('common.updateSuccess'))
@ -128,6 +196,8 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
//
activeClientType.value = 1
currentTreeClientType.value = 1
treeNodeAll.value = false
menuExpand.value = false
//
@ -135,6 +205,10 @@ const resetForm = () => {
formData.name = ''
formData.code = ''
formData.menuIds = []
roleMenuIdsByClientType[1] = []
roleMenuIdsByClientType[2] = []
loadedClientTypes[1] = false
loadedClientTypes[2] = false
treeRef.value?.setCheckedNodes([])
formRef.value?.resetFields()
}
@ -160,4 +234,22 @@ const handleCheckedTreeExpand = () => {
.role-assign-menu-form :deep(.el-form-item__label) {
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>

Loading…
Cancel
Save