useTreeBiz.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import type { Ref } from 'vue';
  2. import { inject, reactive, ref, computed, unref, watch, nextTick } from 'vue';
  3. import { TreeActionType } from '/@/components/Tree';
  4. import { listToTree } from '/@/utils/common/compUtils';
  5. export function useTreeBiz(treeRef, getList, props) {
  6. //接收下拉框选项
  7. const selectOptions = inject('selectOptions', ref<Array<object>>([]));
  8. //接收已选择的值
  9. const selectValues = <object>inject('selectValues', reactive({}));
  10. // 是否正在加载回显
  11. const loadingEcho = inject<Ref<boolean>>('loadingEcho', ref(false));
  12. //数据集
  13. const treeData = ref<Array<object>>([]);
  14. //已选择的值
  15. const checkedKeys = ref<Array<string | number>>([]);
  16. //选则的行记录
  17. const selectRows = ref<Array<object>>([]);
  18. //是否是打开弹框模式
  19. const openModal = ref(false);
  20. // 是否开启父子关联,如果不可以多选,就始终取消父子关联
  21. const getCheckStrictly = computed(() => (props.multiple ? props.checkStrictly : true));
  22. // 是否是首次加载回显,只有首次加载,才会显示 loading
  23. let isFirstLoadEcho = true;
  24. /**
  25. * 监听selectValues变化
  26. */
  27. watch(
  28. selectValues,
  29. ({ value: values }: Recordable) => {
  30. if (openModal.value == false && values.length > 0) {
  31. loadingEcho.value = isFirstLoadEcho;
  32. isFirstLoadEcho = false;
  33. onLoadData(null, values.join(',')).finally(() => {
  34. loadingEcho.value = false;
  35. });
  36. }
  37. },
  38. { immediate: true }
  39. );
  40. /**
  41. * 获取树实例
  42. */
  43. function getTree() {
  44. const tree = unref(treeRef);
  45. if (!tree) {
  46. throw new Error('tree is null!');
  47. }
  48. return tree;
  49. }
  50. /**
  51. * 设置树展开级别
  52. */
  53. function expandTree() {
  54. nextTick(() => {
  55. if (props.defaultExpandLevel && props.defaultExpandLevel > 0) {
  56. getTree().filterByLevel(props.defaultExpandLevel);
  57. }
  58. //设置列表默认选中
  59. checkedKeys.value = selectValues['value'];
  60. }).then();
  61. }
  62. /**
  63. * 树节点选择
  64. */
  65. function onSelect(keys, info) {
  66. if (props.checkable == false) {
  67. checkedKeys.value = props.checkStrictly ? keys.checked : keys;
  68. const { selectedNodes } = info;
  69. let rows = <any[]>[];
  70. selectedNodes.forEach((item) => {
  71. rows.push(item.props.node);
  72. });
  73. selectRows.value = rows;
  74. }
  75. }
  76. /**
  77. * 树节点选择
  78. */
  79. function onCheck(keys, info) {
  80. if (props.checkable == true) {
  81. // 如果不能多选,就只保留最后一个选中的
  82. if (!props.multiple) {
  83. if (info.checked) {
  84. //update-begin-author:taoyan date:20220408 for: 单选模式下,设定rowKey,无法选中数据-
  85. checkedKeys.value = [info.node.eventKey];
  86. let temp = info.checkedNodes.find((n) => n.key === info.node.eventKey);
  87. selectRows.value = [temp.props.node];
  88. //update-end-author:taoyan date:20220408 for: 单选模式下,设定rowKey,无法选中数据-
  89. } else {
  90. checkedKeys.value = [];
  91. selectRows.value = [];
  92. }
  93. return;
  94. }
  95. checkedKeys.value = props.checkStrictly ? keys.checked : keys;
  96. const { checkedNodes } = info;
  97. let rows = <any[]>[];
  98. checkedNodes.forEach((item) => {
  99. rows.push(item.props.node);
  100. });
  101. selectRows.value = rows;
  102. }
  103. }
  104. /**
  105. * 勾选全部
  106. */
  107. function checkALL(checkAll) {
  108. getTree().checkAll(checkAll);
  109. }
  110. /**
  111. * 展开全部
  112. */
  113. function expandAll(expandAll) {
  114. getTree().expandAll(expandAll);
  115. }
  116. /**
  117. * 加载树数据
  118. */
  119. async function onLoadData(treeNode, ids) {
  120. let params = {};
  121. let startPid = '';
  122. if (treeNode) {
  123. startPid = treeNode.eventKey;
  124. //update-begin---author:wangshuai ---date:20220407 for:rowkey不设置成id,sync开启异步的时候,点击上级下级不显示------------
  125. params['pid'] = treeNode.value;
  126. //update-end---author:wangshuai ---date:20220407 for:rowkey不设置成id,sync开启异步的时候,点击上级下级不显示------------
  127. }
  128. if (ids) {
  129. startPid = '';
  130. params['ids'] = ids;
  131. }
  132. let record = await getList(params);
  133. let optionData = record;
  134. if (!props.serverTreeData) {
  135. //前端处理数据为tree结构
  136. record = listToTree(record, props, startPid);
  137. if (record.length == 0 && treeNode) {
  138. checkHasChild(startPid, treeData.value);
  139. }
  140. }
  141. if (openModal.value == true) {
  142. //弹框模式下加载全部数据
  143. if (!treeNode) {
  144. treeData.value = record;
  145. } else {
  146. return new Promise((resolve: (value?: unknown) => void) => {
  147. if (!treeNode.children) {
  148. resolve();
  149. return;
  150. }
  151. const asyncTreeAction: TreeActionType | null = unref(treeRef);
  152. if (asyncTreeAction) {
  153. asyncTreeAction.updateNodeByKey(treeNode.eventKey, { children: record });
  154. asyncTreeAction.setExpandedKeys([treeNode.eventKey, ...asyncTreeAction.getExpandedKeys()]);
  155. }
  156. resolve();
  157. return;
  158. });
  159. }
  160. expandTree();
  161. } else {
  162. const options = <any[]>[];
  163. optionData.forEach((item) => {
  164. //update-begin-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
  165. options.push({ label: item[props.titleKey], value: item[props.rowKey] });
  166. //update-end-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑,查看数据应该显示部门名称,不是部门代码
  167. });
  168. selectOptions.value = options;
  169. }
  170. }
  171. /**
  172. * 异步加载时检测是否含有下级节点
  173. * @param pid 父节点
  174. * @param treeArray tree数据
  175. */
  176. function checkHasChild(pid, treeArray) {
  177. if (treeArray && treeArray.length > 0) {
  178. for (let item of treeArray) {
  179. if (item.key == pid) {
  180. if (!item.child) {
  181. item.isLeaf = true;
  182. }
  183. break;
  184. } else {
  185. checkHasChild(pid, item.children);
  186. }
  187. }
  188. }
  189. }
  190. /**
  191. * 获取已选择数据
  192. */
  193. function getSelectTreeData(success) {
  194. const options = <any[]>[];
  195. const values = <any[]>[];
  196. selectRows.value.forEach((item) => {
  197. options.push({ label: item[props.labelKey], value: item[props.rowKey] });
  198. });
  199. checkedKeys.value.forEach((item) => {
  200. values.push(item);
  201. });
  202. selectOptions.value = options;
  203. success && success(options, values);
  204. }
  205. /**
  206. * 弹出框显示隐藏触发事件
  207. */
  208. async function visibleChange(visible) {
  209. if (visible) {
  210. //弹出框打开时加载全部数据
  211. openModal.value = true;
  212. await onLoadData(null, null);
  213. } else {
  214. openModal.value = false;
  215. }
  216. }
  217. return [
  218. {
  219. visibleChange,
  220. selectOptions,
  221. selectValues,
  222. onLoadData,
  223. onCheck,
  224. onSelect,
  225. checkALL,
  226. expandAll,
  227. checkedKeys,
  228. selectRows,
  229. treeData,
  230. getCheckStrictly,
  231. getSelectTreeData,
  232. },
  233. ];
  234. }