mine.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import { defineStore } from 'pinia';
  2. import { ref, computed } from 'vue';
  3. import { getEnfMineTree } from '/@/api/sys/menu';
  4. import { getUserMinePermissionData } from '/@/components/Form/src/jeecg/components/MineCascader/mineData.api';
  5. import { findNode, findNodeAll, findPath, listToTree, treeToList } from '/@/utils/helper/treeHelper';
  6. import { isArray } from 'lodash';
  7. export interface MineDepartment {
  8. /** 唯一标识 */
  9. id: string;
  10. /** 部门名称 */
  11. departName: string;
  12. /** 父部门ID */
  13. parentId: string | null;
  14. /** 是否为叶子节点(矿井是叶子节点) */
  15. isLeaf: boolean;
  16. /** 子部门列表 */
  17. childDepart: MineDepartment[];
  18. /** 传真,用作矿井编号(矿井编码) */
  19. fax: string | null;
  20. }
  21. const DEFAULT_CONFIG = {
  22. id: 'id',
  23. pid: 'parentId',
  24. children: 'childDepart',
  25. };
  26. export const useMineDepartmentStore = defineStore('mine-department-store', () => {
  27. // ==================== State 定义 ====================
  28. /** 当前选中的部门,可能是执法处、区或者具体到矿井 */
  29. const depart = ref<MineDepartment>();
  30. /** 组织树(经过过滤等处理后的树) */
  31. const departTree = ref<MineDepartment[]>([]);
  32. /** 原始组织树(保存原始数据,用于恢复或重新过滤) */
  33. const rawTree = ref<MineDepartment[]>([]);
  34. // ==================== Getter 计算属性 ====================
  35. /** 获取当前选中的部门 */
  36. const getDepart = computed(() => depart.value);
  37. /** 获取当前选中的部门ID */
  38. const getDepartId = computed(() => depart.value?.id);
  39. /** 获取组织树 */
  40. const getDepartTree = computed(() => departTree.value);
  41. /** 获取当前选中的部门在组织树中的访问路径 */
  42. const getDepartPath = computed(() => {
  43. return findPath(departTree.value, (item) => item.id === getDepartId.value, DEFAULT_CONFIG) || [];
  44. });
  45. /**
  46. * 获取当前选中的矿井编号集合
  47. * - 如果选择了具体的矿井节点,返回该矿井的编码
  48. * - 如果选择了上级部门(如执法处),返回该部门下所有矿井的编码集合,用逗号分隔
  49. * - 如果未选择任何节点,返回空字符串
  50. */
  51. const getMineCode = computed(() => {
  52. const target = getDepartId.value ? [depart.value] : departTree.value;
  53. const list = treeToList(target, DEFAULT_CONFIG);
  54. if (isArray(list)) {
  55. return list
  56. .filter((item) => item.isLeaf && item.fax) // 只取叶子节点(矿井)且fax不为空
  57. .map((item) => item.fax!) // 提取矿井编码
  58. .join(','); // 用逗号分隔多个矿井编码
  59. }
  60. return '';
  61. });
  62. // ==================== Action 方法 ====================
  63. /**
  64. * 设置当前选中的部门
  65. * @param dep - 部门对象
  66. */
  67. function setDepart(dep: MineDepartment) {
  68. // if (isNil(dep) || isEmpty(dep)) return;
  69. depart.value = dep;
  70. }
  71. /**
  72. * 根据部门ID设置当前选中的部门
  73. * @param id - 部门ID,默认为空字符串
  74. */
  75. function setDepartById(id: string = '') {
  76. const node = findNode(departTree.value, (item) => item.id === id, DEFAULT_CONFIG);
  77. setDepart(node);
  78. }
  79. /**
  80. * 获取组织树数据(异步)
  81. * 从两个接口获取数据:
  82. * 1. getEnfMineTree: 获取执法处、区等非叶子节点
  83. * 2. getUserMinePermissionData: 获取矿井(叶子节点)数据
  84. */
  85. async function fetchDepartTree() {
  86. try {
  87. // 并行请求两个接口
  88. const [r1, r2] = await Promise.all([
  89. getEnfMineTree(), // 非叶子节点(执法处、区)
  90. getUserMinePermissionData({}), // 叶子节点(矿井)
  91. ]);
  92. // 标记节点类型
  93. r1.forEach((node) => (node.isLeaf = false)); // 非叶子节点
  94. r2.forEach((node) => {
  95. node.isLeaf = true; // 叶子节点(矿井)
  96. node.id = node.fax || node.id; // 使用矿井编码作为ID
  97. });
  98. // 合并数据并转换为树形结构
  99. const tree = listToTree([...r1, ...r2], DEFAULT_CONFIG);
  100. departTree.value = tree;
  101. // 深拷贝保存原始数据,用于过滤后恢复
  102. rawTree.value = JSON.parse(JSON.stringify(tree));
  103. // 如果需要自动选中第一个叶子节点(矿井),可以取消注释以下代码
  104. /*
  105. if (!depart.value) {
  106. const firstLeaf = findNode(
  107. tree,
  108. (item) => item.isLeaf,
  109. DEFAULT_CONFIG
  110. );
  111. if (firstLeaf) {
  112. setDepart(firstLeaf);
  113. }
  114. }
  115. */
  116. } catch (error) {
  117. console.error('获取组织树数据失败:', error);
  118. throw error;
  119. }
  120. }
  121. /**
  122. * 过滤组织树
  123. * @param fn - 过滤函数,返回true表示保留该节点
  124. */
  125. function filterDepartTree(fn: (node: MineDepartment) => boolean) {
  126. // 只有在有原始数据时才进行过滤
  127. if (rawTree.value.length > 0) {
  128. departTree.value = findNodeAll(rawTree.value, fn, DEFAULT_CONFIG);
  129. }
  130. }
  131. /**
  132. * 恢复原始组织树(取消过滤)
  133. */
  134. function restoreDepartTree() {
  135. if (rawTree.value.length > 0) {
  136. departTree.value = JSON.parse(JSON.stringify(rawTree.value));
  137. }
  138. }
  139. /**
  140. * 清除选中的部门
  141. */
  142. function clearDepart() {
  143. depart.value = undefined;
  144. }
  145. // ==================== 暴露的属性和方法 ====================
  146. return {
  147. // --- State(可修改)---
  148. depart,
  149. departTree,
  150. rawTree,
  151. // --- Getter(只读计算属性)---
  152. getDepart,
  153. getDepartId,
  154. getDepartTree,
  155. getDepartPath,
  156. getMineCode,
  157. // --- Action(操作方法)---
  158. setDepart,
  159. setDepartById,
  160. // setDepartTree,
  161. fetchDepartTree,
  162. filterDepartTree,
  163. restoreDepartTree,
  164. clearDepart,
  165. };
  166. });