Files
school-developer/src/views/admin/system/dept/tree-view.vue
吴红兵 1f645dad3e init
2025-12-02 10:37:49 +08:00

199 lines
4.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div style="height: 100%">
<vue3-tree-org
ref="treeOrgRef"
:props="props"
:data="data"
:label-style="style"
:define-menus="defineMenus"
:default-expand-level="expandLevel"
center
:horizontal="horizontal"
:collapsable="collapsable"
:only-one-node="onlyOneNode"
:filter-node-method="filterNodeMethod"
:clone-node-drag="cloneNodeDrag"
:node-add="addNode"
:node-delete="delNode"
:node-edit="editNode"
@on-node-click="onNodeClick"
/>
</div>
<dept-form ref="deptDialogRef" @refresh="getOrgData()" />
</template>
<script lang="ts" name="treeView" setup>
import { useMessage, useMessageBox } from '/@/hooks/message';
import { delObj, deptTree } from '/@/api/admin/dept';
import { getObj } from '/@/api/admin/tenant';
import { Session } from '/@/utils/storage';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
const DeptForm = defineAsyncComponent(() => import('./form.vue'));
const { t } = useI18n();
// 定义org组件key-value定义
const props = reactive({ id: 'id', pid: 'parentId', label: 'name', expand: 'expand', children: 'children' });
const data = reactive({});
// 定义org组件右键定义
const defineMenus = reactive([
{ name: t('sysdept.addNodeText'), command: 'add' },
{ name: t('sysdept.editNodeText'), command: 'edit' },
{ name: t('sysdept.delNodeText'), command: 'delete' },
]);
const cloneNodeDrag = ref(true);
const collapsable = ref(false);
const expandLevel = ref(2); //默认展开层级
const horizontal = ref(false);
const onlyOneNode = ref(false);
const treeOrgRef = ref();
const deptDialogRef = ref();
// 添加主题配置
const themeConfig = useThemeConfig();
const { themeConfig: theme } = storeToRefs(themeConfig);
// 添加 style 定义
const style = computed(() => ({
background: theme.value.isDark ? 'var(--el-bg-color-overlay)' : 'var(--el-bg-color-page)',
color: theme.value.isDark ? 'var(--el-text-color-primary)' : '#5e6d82',
}));
/**
* 过滤节点
*/
const filter = (deptName: string) => {
treeOrgRef.value.filter(deptName);
};
/**
* 节点过滤方法
* @param {string} value 过滤条件
* @param {object} data 节点数据
* @returns {boolean} 返回过滤结果
*/
const filterNodeMethod = (value, data) => {
if (!value) return true;
return data.label.indexOf(value) !== -1;
};
/**
* 处理展开/折叠树
*/
const handleExpand = async () => {
collapsable.value = !collapsable.value;
};
/**
* 检查节点是否是根租户节点
* @param {object} node 节点对象
* @returns {boolean} 如果节点是根租户节点返回true否则返回false
*/
const checkNode = (node) => {
if (node?.id === '0') {
useMessage().error(t('sysdept.tenantNodeErrorText'));
return false;
}
return true;
};
/**
* 当用户左键点击节点,模拟触发组件的右键事件
* @param e
*/
const onNodeClick = (e: any) => {
const { clientX, clientY } = e;
const rightFun = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: false,
view: window,
button: 2,
buttons: 0,
clientX,
clientY,
});
e.target.dispatchEvent(rightFun);
};
/**
* 添加部门
* @param {object} node 节点对象
*/
const addNode = (node) => {
deptDialogRef.value.openDialog('add', node?.id);
};
/**
* 编辑部门
* @param {object} node 节点对象
*/
const editNode = (node) => {
if (!checkNode(node)) {
return;
}
deptDialogRef.value.openDialog('edit', node?.id);
};
/**
* 删除部门
* @param {object} node 节点对象
*/
const delNode = async (node) => {
if (!checkNode(node)) {
return;
}
try {
await useMessageBox().confirm(t('common.delConfirmText'));
} catch {
return;
}
try {
await delObj(node.id);
await getOrgData();
useMessage().success(t('common.delSuccessText'));
} catch (err: any) {
useMessage().error(err.msg);
}
};
/**
* 查询部门数据
*/
const getOrgData = async () => {
// 查询当前租户信息
const tenant = await getObj(Session.getTenant());
deptTree().then((res) => {
Object.assign(data, { id: '0', name: tenant.data.name });
data.children = res.data;
});
};
onMounted(() => {
getOrgData();
});
// 暴露变量
defineExpose({
getOrgData,
handleExpand,
filter,
});
</script>
<style lang="scss" scoped>
:deep(.zm-tree-org) {
height: 100%;
padding: 15px;
position: relative;
background: var(--el-bg-color);
box-sizing: border-box;
}
</style>