<template>
|
<el-drawer v-model="drawerVisible" :destroy-on-close="true" size="450px" :title="`${drawerProps.title}`">
|
<el-form
|
ref="ruleFormRef"
|
label-width="100px"
|
label-suffix=" :"
|
:rules="rules"
|
:disabled="drawerProps.isView"
|
:model="drawerProps.row"
|
:hide-required-asterisk="drawerProps.isView"
|
>
|
<el-form-item :label="t('role.roleName')" prop="name">
|
<el-input v-model="drawerProps.row!.name" :placeholder="t('role.inputRoleName')" clearable></el-input>
|
</el-form-item>
|
<el-form-item :label="t('role.operationPermission')" prop="">
|
<el-switch
|
v-model="drawerProps.row.addrole"
|
:active-text="t('Config.add')"
|
:active-action-icon="CirclePlus"
|
/>
|
<el-switch
|
v-model="drawerProps.row.editrole"
|
:active-text="t('Config.update')"
|
:active-action-icon="EditPen"
|
/>
|
<el-switch v-model="drawerProps.row.deleterole" :active-text="t('Config.delete')" :active-action-icon="Delete" />
|
</el-form-item>
|
<el-form-item :label="t('role.menuPermission')" prop="">
|
<div>
|
<!-- 展开/折叠 -->
|
<el-checkbox v-model="expandAll" @change="handleExpand">{{ t("role.expandCollapse") }}</el-checkbox>
|
<!-- 全选/全不选 -->
|
<el-checkbox v-model="checkAll" @change="handleCheckAll">{{ t("role.selectAllNone") }}</el-checkbox>
|
</div>
|
<el-tree
|
ref="treeRef"
|
style="
|
width: 400px;
|
max-width: 600px;
|
height: auto;
|
padding: 20px;
|
margin-top: 20px;
|
overflow: auto;
|
font-size: 14px;
|
border-radius: 4px;
|
box-shadow: 0 0 12px rgb(0 0 0 / 12%);
|
"
|
:props="treeProps"
|
:data="data"
|
node-key="id"
|
show-checkbox
|
:check-strictly="checkStrictly"
|
:default-checked-keys="defaultCheckedKeys"
|
/>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<el-button @click="drawerVisible = false">{{ t("Config.cancel") }}</el-button>
|
<el-button v-show="!drawerProps.isView" type="primary" @click="handleSubmit">{{ t("Config.sure") }}</el-button>
|
</template>
|
</el-drawer>
|
</template>
|
|
<script setup lang="ts" name="UserDrawer">
|
import { ref, reactive, nextTick, computed } from "vue";
|
import { useI18n } from "vue-i18n";
|
import { ElMessage, FormInstance } from "element-plus";
|
import { ElTree } from "element-plus";
|
import { Delete, EditPen, CirclePlus } from "@element-plus/icons-vue";
|
import { MenuAll, RoleMentAll } from "@/api/modules/hxzk/user/menu";
|
|
const { t, locale } = useI18n();
|
|
interface Tree {
|
id: any;
|
label: string;
|
entitle?: string; // 英文标题
|
children?: Tree[];
|
meta?: {
|
entitle: string;
|
};
|
}
|
|
let data = ref<Tree[]>([]);
|
const defaultCheckedKeys = ref(); // 默认勾选的节点ID数组
|
|
// 根据当前语言动态计算树节点的标签
|
const treeProps = computed(() => {
|
return {
|
children: "children",
|
label: (data: Tree) => {
|
// 如果是英文环境且存在英文标题,则显示英文标题
|
if (locale.value === "en" && data.meta?.entitle) {
|
return data.meta.entitle;
|
}
|
// 如果是英文环境且存在 entitle 字段,则显示 entitle
|
if (locale.value === "en" && data.entitle) {
|
return data.entitle;
|
}
|
// 否则显示中文标签
|
return data.label;
|
},
|
id: "id"
|
};
|
});
|
|
// 处理数据,确保包含中英文信息
|
const processData = (rawData: Tree[]) => {
|
// 清空现有数据
|
data.value.splice(0, data.value.length);
|
|
// 处理数据,递归处理子节点
|
const processNode = (node: Tree): Tree => {
|
return {
|
...node,
|
label: node.label,
|
entitle: node.meta?.entitle || node.entitle,
|
children: node.children ? node.children.map(processNode) : undefined
|
};
|
};
|
|
// 处理所有节点
|
for (let i = 0; i < rawData.length; i++) {
|
const item = rawData[i];
|
data.value.push(processNode(item));
|
}
|
};
|
|
// 展开/折叠状态
|
const expandAll = ref(false);
|
|
// 全选/全不选状态
|
const checkAll = ref(false);
|
|
// 父子联动状态
|
const checkStrictly = ref(false);
|
|
// 树组件引用
|
const treeRef = ref();
|
|
// 展开/折叠树节点
|
const handleExpand = (value: boolean) => {
|
if (treeRef.value) {
|
const nodesMap = treeRef.value.store.nodesMap;
|
Object.values(nodesMap).forEach((node: any) => {
|
node.expanded = value;
|
});
|
}
|
};
|
|
// 全选/全不选
|
const handleCheckAll = (value: boolean) => {
|
if (treeRef.value) {
|
if (value) {
|
// 全选
|
setCheckedRecursively(treeRef.value.root.childNodes, true);
|
} else {
|
// 全不选
|
treeRef.value.setCheckedNodes([]);
|
}
|
}
|
};
|
|
function setCheckedRecursively(nodes: any[], checked: boolean) {
|
nodes.forEach(node => {
|
treeRef.value.setChecked(node.key, checked);
|
if (node.childNodes && node.childNodes.length > 0) {
|
setCheckedRecursively(node.childNodes, checked);
|
}
|
});
|
}
|
|
const rules = reactive({
|
name: [{ required: true, message: t("role.validation.nameRequired") }],
|
menu: [{ required: true, message: t("role.validation.menuRequired") }]
|
});
|
|
interface DrawerProps {
|
title: string;
|
isView: boolean;
|
row: Partial<User.ResUserList>;
|
api?: (params: any) => Promise<any>;
|
getTableList?: () => void;
|
initParam?: any;
|
}
|
|
const drawerVisible = ref(false);
|
const drawerProps = ref<DrawerProps>({
|
isView: false,
|
title: "",
|
row: {}
|
});
|
|
const acceptParams = (params: DrawerProps) => {
|
drawerProps.value = params;
|
if (params.title == t("Config.add")) {
|
MenuAll()
|
.then(menulAll => {
|
const responseData = menulAll.data as Tree[];
|
processData(responseData); // 处理数据
|
})
|
.catch(error => {
|
console.error("Error:", error);
|
});
|
} else {
|
// 回显被设置的导航
|
MenuAll()
|
.then(menulAll => {
|
const responseData = menulAll.data as Tree[];
|
processData(responseData); // 处理数据
|
nextTick(async () => {
|
const checkedKeys = await RoleMentAll(params.row.id);
|
defaultCheckedKeys.value = checkedKeys;
|
treeRef.value.setCheckedKeys(defaultCheckedKeys.value);
|
});
|
})
|
.catch(error => {
|
console.error("Error:", error);
|
});
|
}
|
drawerVisible.value = true;
|
};
|
|
// 提交数据(新增/编辑)
|
const ruleFormRef = ref<FormInstance>();
|
const handleSubmit = () => {
|
ruleFormRef.value!.validate(async valid => {
|
if (!valid) return;
|
try {
|
const checkedNodes = treeRef.value.getCheckedNodes();
|
drawerProps.value.row.rolist = checkedNodes;
|
drawerProps.value.row.companyid = drawerProps.value.initParam.departmentId;
|
const res = await drawerProps.value.api!(drawerProps.value.row);
|
ElMessage.success({ message: `${res.msg}` });
|
drawerProps.value.getTableList!();
|
drawerVisible.value = false;
|
} catch (error) {
|
console.log(error);
|
}
|
});
|
};
|
|
defineExpose({
|
acceptParams
|
});
|
</script>
|