index.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <template>
  2. <div class="device-manager-box">
  3. <!--引用表格-->
  4. <BasicTable
  5. @register="registerTable"
  6. :rowSelection="rowSelection"
  7. :expandedRowKeys="expandedRowKeys"
  8. @expand="handleExpand"
  9. @fetch-success="onFetchSuccess"
  10. >
  11. <!--插槽:table标题-->
  12. <template #tableTitle>
  13. <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
  14. <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
  15. <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
  16. <a-dropdown v-if="selectedRowKeys.length > 0">
  17. <template #overlay>
  18. <a-menu>
  19. <a-menu-item key="1" @click="batchHandleDelete">
  20. <Icon icon="ant-design:delete-outlined" />
  21. 删除
  22. </a-menu-item>
  23. </a-menu>
  24. </template>
  25. <a-button
  26. >批量操作
  27. <Icon icon="ant-design:down-outlined" />
  28. </a-button>
  29. </a-dropdown>
  30. </template>
  31. <!--操作栏-->
  32. <template #action="{ record }">
  33. <TableAction :actions="getTableAction(record)" />
  34. </template>
  35. </BasicTable>
  36. <!--字典弹窗-->
  37. <CategoryModal @register="registerModal" @success="handleSuccess" />
  38. </div>
  39. </template>
  40. <script lang="ts" name="system-category" setup>
  41. //ts语法
  42. import { ref, computed, unref, toRaw, nextTick } from 'vue';
  43. import { BasicTable, useTable, TableAction } from '/src/components/Table';
  44. import { useDrawer } from '/src/components/Drawer';
  45. import CategoryModal from './components/CategoryModal.vue';
  46. import { useModal } from '/src/components/Modal';
  47. import { useMethods } from '/src/hooks/system/useMethods';
  48. import { columns, searchFormSchema } from './category.data';
  49. import { list, deleteCategory, batchDeleteCategory, getExportUrl, getImportUrl, getChildList, getChildListBatch } from './category.api';
  50. import { useListPage } from '/@/hooks/system/useListPage';
  51. const expandedRowKeys = ref([]);
  52. const { handleExportXls, handleImportXls } = useMethods();
  53. //字典model
  54. const [registerModal, { openModal }] = useModal();
  55. // 列表页面公共参数、方法
  56. const { prefixCls, onExportXls, onImportXls, tableContext } = useListPage({
  57. designScope: 'category-template',
  58. tableProps: {
  59. title: '分类字典',
  60. api: list,
  61. columns: columns,
  62. actionColumn: {
  63. width: 180,
  64. },
  65. formConfig: {
  66. schemas: searchFormSchema,
  67. },
  68. isTreeTable: true,
  69. },
  70. exportConfig: {
  71. name: '分类字典列表',
  72. url: getExportUrl,
  73. },
  74. importConfig: {
  75. url: getImportUrl,
  76. },
  77. });
  78. //注册table数据
  79. const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
  80. tableContext;
  81. /**
  82. * 新增事件
  83. */
  84. function handleCreate() {
  85. openModal(true, {
  86. isUpdate: false,
  87. });
  88. }
  89. /**
  90. * 编辑事件
  91. */
  92. async function handleEdit(record) {
  93. openModal(true, {
  94. record,
  95. isUpdate: true,
  96. });
  97. }
  98. /**
  99. * 详情
  100. */
  101. async function handleDetail(record) {
  102. openModal(true, {
  103. record,
  104. isUpdate: true,
  105. hideFooter: true,
  106. });
  107. }
  108. /**
  109. * 删除事件
  110. */
  111. async function handleDelete(record) {
  112. await deleteCategory({ id: record.id }, importSuccess);
  113. }
  114. /**
  115. * 批量删除事件
  116. */
  117. async function batchHandleDelete() {
  118. const ids = selectedRowKeys.value.filter((item) => !item.includes('loading'));
  119. await batchDeleteCategory({ ids: ids }, importSuccess);
  120. }
  121. /**
  122. * 导入
  123. */
  124. function importSuccess() {
  125. //update-begin---author:wangshuai ---date:20220530 for:[issues/54]树字典,勾选,然后批量删除,系统错误------------
  126. (selectedRowKeys.value = []) && reload();
  127. //update-end---author:wangshuai ---date:20220530 for:[issues/54]树字典,勾选,然后批量删除,系统错误--------------
  128. }
  129. /**
  130. * 添加下级
  131. */
  132. function handleAddSub(record) {
  133. openModal(true, {
  134. record,
  135. isUpdate: false,
  136. });
  137. }
  138. /**
  139. * 成功回调
  140. */
  141. async function handleSuccess({ isUpdate,isSubAdd, values, expandedArr }) {
  142. if (isUpdate) {
  143. //编辑回调
  144. updateTableDataRecord(values.id, values);
  145. } else {
  146. if (!values['pid']) {
  147. //新增根节点
  148. reload();
  149. } else {
  150. //新增子集
  151. //update-begin-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长---
  152. if(isSubAdd){
  153. await expandTreeNode(values.pid);
  154. //update-end-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长---
  155. }else{
  156. expandedRowKeys.value = [];
  157. for (let key of unref(expandedArr)) {
  158. await expandTreeNode(key);
  159. }
  160. }
  161. }
  162. }
  163. }
  164. /**
  165. * 接口请求成功后回调
  166. */
  167. function onFetchSuccess(result) {
  168. getDataByResult(result.items) && loadDataByExpandedRows();
  169. }
  170. /**
  171. * 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
  172. */
  173. async function loadDataByExpandedRows() {
  174. if (unref(expandedRowKeys).length > 0) {
  175. const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',') });
  176. if (res.success && res.result.records.length > 0) {
  177. //已展开的数据批量子节点
  178. let records = res.result.records;
  179. const listMap = new Map();
  180. for (let item of records) {
  181. let pid = item['pid'];
  182. if (unref(expandedRowKeys).includes(pid)) {
  183. let mapList = listMap.get(pid);
  184. if (mapList == null) {
  185. mapList = [];
  186. }
  187. mapList.push(item);
  188. listMap.set(pid, mapList);
  189. }
  190. }
  191. let childrenMap = listMap;
  192. let fn = (list) => {
  193. if (list) {
  194. list.forEach((data) => {
  195. if (unref(expandedRowKeys).includes(data.id)) {
  196. data.children = getDataByResult(childrenMap.get(data.id));
  197. fn(data.children);
  198. }
  199. });
  200. }
  201. };
  202. fn(getDataSource());
  203. }
  204. }
  205. }
  206. /**
  207. * 处理数据集
  208. */
  209. function getDataByResult(result) {
  210. if (result && result.length > 0) {
  211. return result.map((item) => {
  212. //判断是否标记了带有子节点
  213. if (item['hasChild'] == '1') {
  214. let loadChild = { id: item.id + '_loadChild', name: 'loading...', isLoading: true };
  215. item.children = [loadChild];
  216. }
  217. return item;
  218. });
  219. }
  220. }
  221. /**
  222. *树节点展开合并
  223. * */
  224. async function handleExpand(expanded, record) {
  225. // 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
  226. if (expanded) {
  227. expandedRowKeys.value.push(record.id);
  228. if (record.children.length > 0 && !!record.children[0].isLoading) {
  229. let result = await getChildList({ pid: record.id });
  230. if (result && result.length > 0) {
  231. record.children = getDataByResult(result);
  232. } else {
  233. record.children = null;
  234. record.hasChild = '0';
  235. }
  236. }
  237. } else {
  238. let keyIndex = expandedRowKeys.value.indexOf(record.id);
  239. if (keyIndex >= 0) {
  240. expandedRowKeys.value.splice(keyIndex, 1);
  241. }
  242. }
  243. }
  244. /**
  245. *操作表格后处理树节点展开合并
  246. * */
  247. async function expandTreeNode(key) {
  248. let record:any = findTableDataRecord(key);
  249. //update-begin-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长,显示“接口请求超时,请刷新页面重试!”---
  250. if(!expandedRowKeys.value.includes(key)){
  251. expandedRowKeys.value.push(key);
  252. }
  253. //update-end-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长,显示“接口请求超时,请刷新页面重试!”---
  254. let result = await getChildList({ pid: key });
  255. if (result && result.length > 0) {
  256. record.children = getDataByResult(result);
  257. } else {
  258. record.children = null;
  259. record.hasChild = '0';
  260. }
  261. updateTableDataRecord(key, record);
  262. }
  263. /**
  264. * 操作栏
  265. */
  266. function getTableAction(record) {
  267. return [
  268. {
  269. label: '编辑',
  270. onClick: handleEdit.bind(null, record),
  271. },
  272. {
  273. label: '删除',
  274. popConfirm: {
  275. title: '确定删除吗?',
  276. confirm: handleDelete.bind(null, record),
  277. },
  278. },
  279. {
  280. label: '添加下级',
  281. onClick: handleAddSub.bind(null, { pid: record.id }),
  282. },
  283. ];
  284. }
  285. </script>
  286. <style scoped></style>