智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

461 lines
13 KiB

<template>
<el-dialog
v-model="showDialog"
:title="popTitle"
width="500px"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="90px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('roleName')" prop="role_name">
<el-input
v-model.trim="formData.role_name"
:placeholder="t('roleNamePlaceholder')"
clearable
:disabled="formData.uid"
class="input-width"
maxlength="10"
:show-word-limit="true"
/>
</el-form-item>
<el-form-item label="类型">
<el-radio-group v-model="formData.role_key">
<span v-for="(item,index) in roleKeyList" class="mr-2">
<el-radio :label="item.value">{{ item.name }}</el-radio>
</span>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('status')">
<el-radio-group v-model="formData.status">
<el-radio :label="1">{{ t('startUsing') }}</el-radio>
<el-radio :label="0">{{ t('statusDeactivate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="部门" >
<el-select
class="input-width"
v-model="formData.dept_id"
clearable
placeholder="请选择部门"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in parentDepartmentIdList"
:key="index"
:label="item['department_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('permission')" prop="rules">
<el-tabs v-model="activePermissionTab" class="w-full">
<!-- PC端权限 -->
<el-tab-pane label="PC端权限" name="pc">
<div class="flex items-center justify-between w-11/12">
<div>
<el-checkbox v-model="selectAllPC" :label="t('selectAll')"/>
<el-checkbox v-model="checkStrictlyPC" :label="t('checkStrictly')"/>
</div>
<el-button link type="primary" @click="menuActionPC()">{{
t('foldText')
}}
</el-button>
</div>
<el-scrollbar height="35vh" class="w-full">
<el-tree
:data="menus"
:props="{ label: 'menu_name' }"
:default-checked-keys="formData.rules"
:check-strictly="checkStrictlyPC"
show-checkbox
default-expand-all
@check-change="handleCheckChangePC"
node-key="menu_key"
ref="treeRefPC"
/>
</el-scrollbar>
</el-tab-pane>
<!-- 移动端权限 -->
<el-tab-pane label="移动端权限" name="mobile">
<div class="flex items-center justify-between w-11/12">
<div>
<el-checkbox v-model="selectAllMobile" :label="t('selectAll')"/>
<el-checkbox v-model="checkStrictlyMobile" :label="t('checkStrictly')"/>
</div>
<el-button link type="primary" @click="menuActionMobile()">{{
t('foldText')
}}
</el-button>
</div>
<el-scrollbar height="35vh" class="w-full">
<el-tree
:data="mobileMenus"
:props="{ label: 'menu_name' }"
:default-checked-keys="formData.mobile_rules"
:check-strictly="checkStrictlyMobile"
show-checkbox
default-expand-all
@check-change="handleCheckChangeMobile"
node-key="menu_key"
ref="treeRefMobile"
/>
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup async>
import {ref, reactive, computed, watch, toRaw} from 'vue'
import {t} from '@/lang'
import {
getWithDepartmentsList} from '@/app/api/departments'
import type {FormInstance} from 'element-plus'
import {addRole, editRole, getRoleInfo} from '@/app/api/sys'
import {getAuthMenus, getUniappMenus, getRoleUniappMenus, setRoleUniappMenus} from '@/app/api/auth'
import {useDictionary} from '@/app/api/dict'
import {debounce} from '@/utils/common'
const showDialog = ref(false)
const loading = ref(false)
const isOpen = ref(true)
let popTitle: string = ''
// 获取权限数据
const menus = ref<Record<string, any>[]>([])
const mobileMenus = ref<Record<string, any>[]>([])
// 获取PC端菜单
getAuthMenus({is_button: 0}).then((res) => {
menus.value = res.data
})
// 获取移动端菜单(UniApp菜单权限)
const getMobileMenus = async () => {
try {
const res = await getUniappMenus()
if (res.data) {
mobileMenus.value = res.data.map(item => ({
menu_key: item.menu_key,
menu_name: item.menu_name,
id: item.id,
children: []
}))
}
} catch (error) {
console.error('获取移动端菜单失败:', error)
// 如果获取失败,设置一个空数组
mobileMenus.value = []
}
}
getMobileMenus()
// 当前活动的权限标签页
const activePermissionTab = ref('pc')
// PC端权限相关
const selectAllPC = ref(false)
const checkStrictlyPC = ref(false)
const treeRefPC: Record<string, any> | null = ref(null)
watch(selectAllPC, () => {
if (treeRefPC.value) {
if (selectAllPC.value) {
treeRefPC.value.setCheckedNodes(toRaw(menus.value))
} else {
treeRefPC.value.setCheckedNodes([])
}
}
})
// 移动端权限相关
const selectAllMobile = ref(false)
const checkStrictlyMobile = ref(false)
const treeRefMobile: Record<string, any> | null = ref(null)
watch(selectAllMobile, () => {
if (treeRefMobile.value) {
if (selectAllMobile.value) {
treeRefMobile.value.setCheckedNodes(toRaw(mobileMenus.value))
} else {
treeRefMobile.value.setCheckedNodes([])
}
}
})
const parentDepartmentIdList = ref([] as any[])
const setParentDepartmentIdList = async () => {
parentDepartmentIdList.value = await (await getWithDepartmentsList({})).data
}
setParentDepartmentIdList()
const roleKeyList = ref([])
const getRolekeyDictList = async () => {
roleKeyList.value = await (
await useDictionary('role_key')
).data.dictionary
}
getRolekeyDictList()
// PC端权限处理函数
const handleCheckChangePC = debounce((e) => {
if (treeRefPC.value) {
formData.rules = treeRefPC.value.getCheckedKeys()
}
})
const menuActionPC = () => {
if (isOpen.value) {
collapseAllPC(menus.value)
isOpen.value = false
} else {
unFoldAllPC(menus.value)
isOpen.value = true
}
}
// 移动端权限处理函数
const handleCheckChangeMobile = debounce((e) => {
if (treeRefMobile.value) {
formData.mobile_rules = treeRefMobile.value.getCheckedKeys()
}
})
const menuActionMobile = () => {
if (isOpen.value) {
collapseAllMobile(mobileMenus.value)
isOpen.value = false
} else {
unFoldAllMobile(mobileMenus.value)
isOpen.value = true
}
}
// PC端全部展开
const unFoldAllPC = (data: any) => {
if (treeRefPC.value && treeRefPC.value.store) {
Object.keys(data).forEach((key: string | any) => {
if (treeRefPC.value.store.nodesMap[data[key].menu_key]) {
treeRefPC.value.store.nodesMap[data[key].menu_key].expanded = true
}
if (data[key].children && data[key].children.length > 0)
unFoldAllPC(data[key].children)
})
}
}
// PC端全部折叠
const collapseAllPC = (data: any) => {
if (treeRefPC.value && treeRefPC.value.store) {
Object.keys(data).forEach((key: string | any) => {
if (treeRefPC.value.store.nodesMap[data[key].menu_key]) {
treeRefPC.value.store.nodesMap[data[key].menu_key].expanded = false
}
if (data[key].children && data[key].children.length > 0)
collapseAllPC(data[key].children)
})
}
}
// 移动端全部展开
const unFoldAllMobile = (data: any) => {
if (treeRefMobile.value && treeRefMobile.value.store) {
Object.keys(data).forEach((key: string | any) => {
if (treeRefMobile.value.store.nodesMap[data[key].menu_key]) {
treeRefMobile.value.store.nodesMap[data[key].menu_key].expanded = true
}
if (data[key].children && data[key].children.length > 0)
unFoldAllMobile(data[key].children)
})
}
}
// 移动端全部折叠
const collapseAllMobile = (data: any) => {
if (treeRefMobile.value && treeRefMobile.value.store) {
Object.keys(data).forEach((key: string | any) => {
if (treeRefMobile.value.store.nodesMap[data[key].menu_key]) {
treeRefMobile.value.store.nodesMap[data[key].menu_key].expanded = false
}
if (data[key].children && data[key].children.length > 0)
collapseAllMobile(data[key].children)
})
}
}
/**
* 表单数据
*/
const initialFormData = {
role_id: 0,
role_name: '',
status: 1,
role_key: '',
dept_id:'',
rules: [],
mobile_rules: [], // 新增移动端权限字段
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
// 表单验证规则
const formRules = computed(() => {
return {
role_name: [
{required: true, message: t('roleNamePlaceholder'), trigger: 'blur'},
],
rules: [
{
validator: (rule: any, value: string, callback: any) => {
if (!value.length) callback(new Error(t('rulesPlaceholder')))
else callback()
},
trigger: 'blur',
},
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
const save = formData.role_id ? editRole : addRole
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
const data = Object.assign({}, formData)
// PC端权限处理
if (treeRefPC.value) {
data.rules = data.rules.concat(treeRefPC.value.getHalfCheckedKeys())
}
// 移动端权限处理
if (treeRefMobile.value) {
data.mobile_rules = data.mobile_rules.concat(treeRefMobile.value.getHalfCheckedKeys())
// 调用UniApp权限设置API
if (data.role_id && data.mobile_rules.length >= 0) {
try {
await setRoleUniappMenus(data.role_id, data.mobile_rules)
} catch (error) {
console.error('设置移动端权限失败:', error)
}
}
}
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch(() => {
loading.value = false
// showDialog.value = false
})
}
})
}
const setFormData = async (row: any = null) => {
loading.value = true
selectAllPC.value = false
selectAllMobile.value = false
Object.assign(formData, initialFormData)
popTitle = t('addRole')
if (row) {
popTitle = t('updateRole')
const data = await (await getRoleInfo(row.role_id)).data
// 获取移动端权限数据
let mobileRulesData = []
try {
const mobileRes = await getRoleUniappMenus(row.role_id)
if (mobileRes.data) {
mobileRulesData = mobileRes.data.map(item => item.menu_key)
}
} catch (error) {
console.error('获取移动端权限失败:', error)
}
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) {
if (key == 'rules') {
const arr = data.rules
const newArr: any = []
Object.keys(data.rules).forEach((i) => {
checked(data.rules[i], menus.value, newArr)
})
formData[key] = newArr
} else if (key == 'mobile_rules') {
formData[key] = mobileRulesData
} else {
formData[key] = data[key]
}
}
})
// 设置移动端权限数据
formData.mobile_rules = mobileRulesData
}
loading.value = false
}
function checked(menuKey: string, data: any, newArr: any) {
Object.keys(data).forEach((key: string) => {
const item = data[key]
if (item.menu_key == menuKey) {
if (!item.children || item.children.length == 0) {
newArr.push(item.menu_key)
}
} else {
if (item.children && item.children.length > 0) {
checked(menuKey, item.children, newArr)
}
}
})
}
defineExpose({
showDialog,
setFormData,
})
</script>
<style lang="scss" scoped></style>