2025-06-10 09:31:15 +08:00
|
|
|
<template>
|
|
|
|
<el-dialog
|
|
|
|
v-model="visible"
|
|
|
|
:title="type === 'edit' ? '修改' : '新增'"
|
|
|
|
:before-close="fnClose"
|
|
|
|
>
|
|
|
|
<el-form ref="formRef" :rules="rules" :model="form" label-width="110px">
|
|
|
|
<el-form-item label="名称" prop="roleName">
|
|
|
|
<el-input v-model="form.roleName" placeholder="请输入名称" />
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="备注" prop="remark">
|
|
|
|
<el-input
|
|
|
|
v-model="form.remark"
|
|
|
|
type="textarea"
|
|
|
|
:autosize="{ minRows: 1 }"
|
|
|
|
placeholder="请输入备注"
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
2025-06-27 14:01:42 +08:00
|
|
|
<el-form-item v-if="form.parentId !== '0'" label="菜单" prop="menuIdList">
|
2025-06-10 09:31:15 +08:00
|
|
|
<el-tree
|
|
|
|
ref="treeRef"
|
|
|
|
node-key="menuId"
|
|
|
|
:data="menusAll"
|
|
|
|
:props="{
|
|
|
|
label: 'name',
|
|
|
|
children: 'list',
|
|
|
|
}"
|
|
|
|
show-checkbox
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
|
|
<el-button @click="fnClose">关闭</el-button>
|
|
|
|
<el-button type="primary" @click="fnSubmit">确定</el-button>
|
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
import { debounce } from "throttle-debounce";
|
2025-06-27 14:01:42 +08:00
|
|
|
import useForm from "@/hooks/useForm.js";
|
2025-06-10 09:31:15 +08:00
|
|
|
import { ElMessage } from "element-plus";
|
|
|
|
import { nextTick, ref, watchEffect } from "vue";
|
|
|
|
import {
|
|
|
|
getRouteList,
|
|
|
|
setRoleAdd,
|
|
|
|
setRoleEdit,
|
|
|
|
} from "@/request/system_management.js";
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
type: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const emits = defineEmits(["getData"]);
|
|
|
|
const visible = defineModel("visible", { type: Boolean, required: true });
|
|
|
|
const form = defineModel("form", { type: Object, required: true });
|
2025-06-27 14:01:42 +08:00
|
|
|
const { formRef, validate, reset } = useForm();
|
2025-06-10 09:31:15 +08:00
|
|
|
const treeRef = ref(null);
|
|
|
|
const menusAll = ref([]);
|
|
|
|
const rules = {
|
|
|
|
roleName: [
|
|
|
|
{ required: true, message: "名称不能为空", trigger: "blur" },
|
|
|
|
{ min: 2, max: 30, message: "长度在2到30个字符", trigger: "blur" },
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const fnGetData = async () => {
|
|
|
|
const resData = await getRouteList({ parentId: 0 });
|
|
|
|
menusAll.value = fnConversion(resData.menuList);
|
|
|
|
};
|
|
|
|
const fnConversion = (menuList) => {
|
|
|
|
for (let i = 0; i < menuList.length; i++) {
|
|
|
|
menuList[i].meta = JSON.parse(menuList[i].meta);
|
|
|
|
if (menuList[i].type === 1) {
|
2025-06-27 14:01:42 +08:00
|
|
|
menuList[i].name = (menuList[i].name || "首页") + "(页面)";
|
2025-06-10 09:31:15 +08:00
|
|
|
}
|
|
|
|
if (menuList[i].type === 2) {
|
|
|
|
menuList[i].name = menuList[i].name + "(按钮)";
|
|
|
|
}
|
|
|
|
if (menuList[i].list.length > 0) {
|
|
|
|
fnConversion(menuList[i].list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return menuList;
|
|
|
|
};
|
|
|
|
const fnClose = () => {
|
2025-06-27 14:01:42 +08:00
|
|
|
reset();
|
2025-06-10 09:31:15 +08:00
|
|
|
visible.value = false;
|
2025-06-27 14:01:42 +08:00
|
|
|
treeRef.value?.setCheckedKeys([]);
|
2025-06-10 09:31:15 +08:00
|
|
|
};
|
|
|
|
watchEffect(async () => {
|
|
|
|
if (visible.value) {
|
|
|
|
await fnGetData();
|
|
|
|
await nextTick();
|
|
|
|
let checkedKeys = [];
|
|
|
|
form.value.menuIdList.forEach((item) => {
|
|
|
|
checkedKeys = fnGetChecked(item, menusAll.value, checkedKeys);
|
|
|
|
});
|
2025-06-27 14:01:42 +08:00
|
|
|
treeRef.value?.setCheckedKeys(checkedKeys);
|
2025-06-10 09:31:15 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
const fnGetChecked = (menuId, menusAll, checkedKeys) => {
|
|
|
|
for (let i = 0; i < menusAll.length; i++) {
|
|
|
|
if (menuId === menusAll[i].menuId) {
|
|
|
|
if (menusAll[i].list.length === 0) {
|
|
|
|
checkedKeys.push(menusAll[i].menuId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (menusAll[i].list.length > 0) {
|
|
|
|
fnGetChecked(menuId, menusAll[i].list, checkedKeys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return checkedKeys;
|
|
|
|
};
|
|
|
|
const fnSubmit = debounce(
|
|
|
|
1000,
|
|
|
|
async () => {
|
|
|
|
await validate();
|
2025-06-27 14:01:42 +08:00
|
|
|
const checkedKeys = treeRef.value?.getCheckedKeys() || [];
|
|
|
|
const halfCheckedKeys = treeRef.value?.getHalfCheckedKeys() || [];
|
2025-06-10 09:31:15 +08:00
|
|
|
if (props.type === "add") {
|
|
|
|
await setRoleAdd({
|
|
|
|
...form.value,
|
|
|
|
menuIdList: [...checkedKeys, ...halfCheckedKeys],
|
|
|
|
roleId: undefined,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (props.type === "edit")
|
|
|
|
await setRoleEdit({
|
|
|
|
...form.value,
|
|
|
|
menuIdList: [...checkedKeys, ...halfCheckedKeys],
|
|
|
|
});
|
|
|
|
ElMessage.success("操作成功");
|
|
|
|
fnClose();
|
|
|
|
emits("getData");
|
|
|
|
},
|
|
|
|
{ atBegin: true }
|
|
|
|
);
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
:deep(.el-tree) {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
</style>
|