|
|
@@ -1,9 +1,10 @@
|
|
|
import { defineStore } from 'pinia';
|
|
|
+import { ref, computed } from 'vue';
|
|
|
|
|
|
import { getEnfMineTree } from '/@/api/sys/menu';
|
|
|
import { getUserMinePermissionData } from '/@/components/Form/src/jeecg/components/MineCascader/mineData.api';
|
|
|
-import { findNode, findPath, listToTree } from '/@/utils/helper/treeHelper';
|
|
|
-import { isEmpty, isNil } from 'lodash';
|
|
|
+import { findNode, findNodeAll, findPath, listToTree, treeToList } from '/@/utils/helper/treeHelper';
|
|
|
+import { isArray, isEmpty, isNil } from 'lodash';
|
|
|
|
|
|
export interface MineDepartment {
|
|
|
/** 唯一标识 */
|
|
|
@@ -12,100 +13,197 @@ export interface MineDepartment {
|
|
|
departName: string;
|
|
|
/** 父部门ID */
|
|
|
parentId: string | null;
|
|
|
- /** 是否为叶子节点 */
|
|
|
+ /** 是否为叶子节点(矿井是叶子节点) */
|
|
|
isLeaf: boolean;
|
|
|
/** 子部门列表 */
|
|
|
childDepart: MineDepartment[];
|
|
|
- /** 传真,用作矿井编号 */
|
|
|
+ /** 传真,用作矿井编号(矿井编码) */
|
|
|
fax: string | null;
|
|
|
}
|
|
|
|
|
|
-export interface MineState {
|
|
|
- mine?: MineDepartment;
|
|
|
- /** 当前选中的矿井ID,可能为空 */
|
|
|
- mineId?: MineDepartment['id'];
|
|
|
- /** 当前选中的矿井编号,可能为空 */
|
|
|
- // mineCode?: MineDepartment['fax'];
|
|
|
- /** 当前选中的矿井在组织树中的访问路径 */
|
|
|
- minePath: MineDepartment[];
|
|
|
- /** 矿井组织树 */
|
|
|
- mineTree: MineDepartment[];
|
|
|
-}
|
|
|
-
|
|
|
const DEFAULT_CONFIG = {
|
|
|
id: 'id',
|
|
|
pid: 'parentId',
|
|
|
children: 'childDepart',
|
|
|
};
|
|
|
|
|
|
-export const useMineStore = defineStore({
|
|
|
- id: 'mine-store',
|
|
|
- state: (): MineState => ({
|
|
|
- mine: undefined,
|
|
|
- mineId: undefined,
|
|
|
- // mineCode: undefined,
|
|
|
- minePath: [],
|
|
|
- mineTree: [],
|
|
|
- }),
|
|
|
- getters: {
|
|
|
- getMine(): MineState['mine'] {
|
|
|
- return this.mine;
|
|
|
- },
|
|
|
- getMineId(): MineState['mineId'] {
|
|
|
- return this.getMine?.id;
|
|
|
- },
|
|
|
- // getMineCode(): MineState['mineCode'] {
|
|
|
- // return this.getMine?.fax;
|
|
|
- // },
|
|
|
- getMineTree(): MineState['mineTree'] {
|
|
|
- return this.mineTree;
|
|
|
- },
|
|
|
- getMinePath(): MineState['minePath'] {
|
|
|
- return this.minePath;
|
|
|
- },
|
|
|
- },
|
|
|
- actions: {
|
|
|
- /** 设置当前选中的矿井,并更新path项 */
|
|
|
- setMine(mine?: MineDepartment) {
|
|
|
- if (isNil(mine) || isEmpty(mine)) return;
|
|
|
- this.mine = mine;
|
|
|
- const path = findPath(this.getMineTree, (item) => item.id === mine.id, DEFAULT_CONFIG);
|
|
|
- this.setMinePath(path);
|
|
|
- },
|
|
|
- /** 根据传入的id设置当前选中的矿井,更新id、code、path三项 */
|
|
|
- setMineById(id: string = '') {
|
|
|
- const node = findNode(this.getMineTree, (item) => item.id === id, DEFAULT_CONFIG);
|
|
|
- this.setMine(node);
|
|
|
- },
|
|
|
- /** 根据传入的code设置当前选中的矿井,更新id、code、path三项 */
|
|
|
- // setMineByCode(code: string = '') {
|
|
|
- // const node = findNode(this.getMineTree, (item) => item.fax === code, DEFAULT_CONFIG);
|
|
|
- // this.setMine(node);
|
|
|
- // },
|
|
|
- setMinePath(path: any[] = []) {
|
|
|
- this.minePath = path;
|
|
|
- },
|
|
|
- setMineTree(tree: any[] = []) {
|
|
|
- this.mineTree = tree;
|
|
|
- },
|
|
|
- async fetchMineTree() {
|
|
|
- const r1 = await getEnfMineTree();
|
|
|
- const r2 = await getUserMinePermissionData({});
|
|
|
- r1.forEach((e) => (e.isLeaf = false));
|
|
|
- r2.forEach((e) => {
|
|
|
- e.isLeaf = true;
|
|
|
- e.id = e.fax;
|
|
|
+export const useMineStore = defineStore('mine-store', () => {
|
|
|
+ // ==================== State 定义 ====================
|
|
|
+
|
|
|
+ /** 当前选中的部门,可能是执法处、区或者具体到矿井 */
|
|
|
+ const depart = ref<MineDepartment>();
|
|
|
+
|
|
|
+ /** 当前选中的部门ID,可能为空 */
|
|
|
+ const departId = ref<string>();
|
|
|
+
|
|
|
+ /** 组织树(经过过滤等处理后的树) */
|
|
|
+ const departTree = ref<MineDepartment[]>([]);
|
|
|
+
|
|
|
+ /** 原始组织树(保存原始数据,用于恢复或重新过滤) */
|
|
|
+ const rawTree = ref<MineDepartment[]>([]);
|
|
|
+
|
|
|
+ // ==================== Getter 计算属性 ====================
|
|
|
+
|
|
|
+ /** 获取当前选中的部门 */
|
|
|
+ const getDepart = computed(() => depart.value);
|
|
|
+
|
|
|
+ /** 获取当前选中的部门ID */
|
|
|
+ const getDepartId = computed(() => depart.value?.id);
|
|
|
+
|
|
|
+ /** 获取组织树 */
|
|
|
+ const getDepartTree = computed(() => departTree.value);
|
|
|
+
|
|
|
+ /** 获取当前选中的部门在组织树中的访问路径 */
|
|
|
+ const getDepartPath = computed(() => {
|
|
|
+ return findPath(departTree.value, (item) => item.id === departId.value, DEFAULT_CONFIG) || [];
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前选中的矿井编号集合
|
|
|
+ * - 如果选择了具体的矿井节点,返回该矿井的编码
|
|
|
+ * - 如果选择了上级部门(如执法处),返回该部门下所有矿井的编码集合,用逗号分隔
|
|
|
+ * - 如果未选择任何节点,返回空字符串
|
|
|
+ */
|
|
|
+ const getMineCode = computed(() => {
|
|
|
+ const target = departId.value ? [depart.value] : departTree.value;
|
|
|
+ const list = treeToList(target, DEFAULT_CONFIG);
|
|
|
+
|
|
|
+ if (isArray(list)) {
|
|
|
+ return list
|
|
|
+ .filter((item) => item.isLeaf && item.fax) // 只取叶子节点(矿井)且fax不为空
|
|
|
+ .map((item) => item.fax!) // 提取矿井编码
|
|
|
+ .join(','); // 用逗号分隔多个矿井编码
|
|
|
+ }
|
|
|
+ return '';
|
|
|
+ });
|
|
|
+
|
|
|
+ // ==================== Action 方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置当前选中的部门
|
|
|
+ * @param dep - 部门对象
|
|
|
+ */
|
|
|
+ function setDepart(dep: MineDepartment) {
|
|
|
+ if (isNil(dep) || isEmpty(dep)) return;
|
|
|
+ depart.value = dep;
|
|
|
+ departId.value = dep.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据部门ID设置当前选中的部门
|
|
|
+ * @param id - 部门ID,默认为空字符串
|
|
|
+ */
|
|
|
+ function setDepartById(id: string = '') {
|
|
|
+ const node = findNode(departTree.value, (item) => item.id === id, DEFAULT_CONFIG);
|
|
|
+ setDepart(node);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置组织树并保存原始数据副本
|
|
|
+ * @param tree - 组织树数据
|
|
|
+ */
|
|
|
+ function setDepartTree(tree: MineDepartment[] = []) {
|
|
|
+ departTree.value = tree;
|
|
|
+ // 深拷贝保存原始数据,用于过滤后恢复
|
|
|
+ rawTree.value = JSON.parse(JSON.stringify(tree));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取组织树数据(异步)
|
|
|
+ * 从两个接口获取数据:
|
|
|
+ * 1. getEnfMineTree: 获取执法处、区等非叶子节点
|
|
|
+ * 2. getUserMinePermissionData: 获取矿井(叶子节点)数据
|
|
|
+ */
|
|
|
+ async function fetchDepartTree() {
|
|
|
+ try {
|
|
|
+ // 并行请求两个接口
|
|
|
+ const [r1, r2] = await Promise.all([
|
|
|
+ getEnfMineTree(), // 非叶子节点(执法处、区)
|
|
|
+ getUserMinePermissionData({}), // 叶子节点(矿井)
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 标记节点类型
|
|
|
+ r1.forEach((node) => (node.isLeaf = false)); // 非叶子节点
|
|
|
+ r2.forEach((node) => {
|
|
|
+ node.isLeaf = true; // 叶子节点(矿井)
|
|
|
+ node.id = node.fax || node.id; // 使用矿井编码作为ID
|
|
|
});
|
|
|
+
|
|
|
+ // 合并数据并转换为树形结构
|
|
|
const tree = listToTree([...r1, ...r2], DEFAULT_CONFIG);
|
|
|
- // 使用查找方法而不是选中r2中第一个“叶节点”是因为:
|
|
|
- // r2返回的矿名不具备权限控制,r1返回的父节点才有权限控制
|
|
|
|
|
|
- this.setMineTree(tree);
|
|
|
+ setDepartTree(tree);
|
|
|
+
|
|
|
+ // 如果需要自动选中第一个叶子节点(矿井),可以取消注释以下代码
|
|
|
+ /*
|
|
|
+ if (!depart.value) {
|
|
|
+ const firstLeaf = findNode(
|
|
|
+ tree,
|
|
|
+ (item) => item.isLeaf,
|
|
|
+ DEFAULT_CONFIG
|
|
|
+ );
|
|
|
+ if (firstLeaf) {
|
|
|
+ setDepart(firstLeaf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取组织树数据失败:', error);
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 过滤组织树
|
|
|
+ * @param fn - 过滤函数,返回true表示保留该节点
|
|
|
+ */
|
|
|
+ function filterDepartTree(fn: (node: MineDepartment) => boolean) {
|
|
|
+ // 只有在有原始数据时才进行过滤
|
|
|
+ if (rawTree.value.length > 0) {
|
|
|
+ departTree.value = findNodeAll(rawTree.value, fn, DEFAULT_CONFIG);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复原始组织树(取消过滤)
|
|
|
+ */
|
|
|
+ function restoreDepartTree() {
|
|
|
+ if (rawTree.value.length > 0) {
|
|
|
+ departTree.value = JSON.parse(JSON.stringify(rawTree.value));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除选中的部门
|
|
|
+ */
|
|
|
+ function clearDepart() {
|
|
|
+ depart.value = undefined;
|
|
|
+ departId.value = undefined;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 暴露的属性和方法 ====================
|
|
|
+
|
|
|
+ return {
|
|
|
+ // --- State(可修改)---
|
|
|
+ depart,
|
|
|
+ departId,
|
|
|
+ departTree,
|
|
|
+ rawTree,
|
|
|
|
|
|
- if (this.getMine) return;
|
|
|
+ // --- Getter(只读计算属性)---
|
|
|
+ getDepart,
|
|
|
+ getDepartId,
|
|
|
+ getDepartTree,
|
|
|
+ getDepartPath,
|
|
|
+ getMineCode,
|
|
|
|
|
|
- const leaf = findNode(tree, (item) => item.isLeaf, DEFAULT_CONFIG);
|
|
|
- this.setMine(leaf);
|
|
|
- },
|
|
|
- },
|
|
|
+ // --- Action(操作方法)---
|
|
|
+ setDepart,
|
|
|
+ setDepartById,
|
|
|
+ // setDepartTree,
|
|
|
+ fetchDepartTree,
|
|
|
+ filterDepartTree,
|
|
|
+ restoreDepartTree,
|
|
|
+ clearDepart,
|
|
|
+ };
|
|
|
});
|