index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. <template>
  2. <div class="ele-body">
  3. <el-card shadow="never" v-loading="loading">
  4. <ele-split-layout
  5. width="230px"
  6. allow-collapse
  7. :right-style="{ overflow: 'hidden' }"
  8. >
  9. <div>
  10. <div class="ele-border-lighter sys-organization-list">
  11. <div
  12. class="add"
  13. style="
  14. display: flex;
  15. justify-content: flex-end;
  16. margin-bottom: 10px;
  17. "
  18. >
  19. <el-button type="primary" @click="openEditType('add')"
  20. >添 加</el-button
  21. >
  22. </div>
  23. <el-tree
  24. :data="typeTree"
  25. default-expand-all
  26. @node-click="handleNodeClick"
  27. highlight-current
  28. ref="treeRef"
  29. node-key="id"
  30. :expand-on-click-node="false"
  31. >
  32. <span class="custom-tree-node" slot-scope="{ node, data }">
  33. <div>
  34. <span>{{ data.type == 'templateStyle' ? '模板-' : '' }}</span>
  35. {{ node.label }}</div
  36. >
  37. <span>
  38. <div class="edit-box">
  39. <!-- <i
  40. v-if="node.type == 'templateStyle'"
  41. @click.stop="openEditType('edit', node)"
  42. class="el-icon-edit"
  43. ></i> -->
  44. <el-popconfirm
  45. title="确定删除吗?"
  46. @confirm="deleteTypeNode(node)"
  47. >
  48. <i
  49. slot="reference"
  50. @click.stop
  51. class="el-icon-delete"
  52. style="color: #f56c6c"
  53. ></i>
  54. </el-popconfirm>
  55. </div>
  56. </span>
  57. </span>
  58. </el-tree>
  59. </div>
  60. </div>
  61. <template v-slot:content>
  62. <search @search="reload" />
  63. <ele-pro-table
  64. ref="table"
  65. :columns="columns"
  66. :datasource="datasource"
  67. :cache-key="cacheKeyUrl"
  68. row-key="id"
  69. >
  70. <template v-slot:toolbar>
  71. <el-button
  72. size="small"
  73. type="primary"
  74. icon="el-icon-plus"
  75. class="ele-btn-icon"
  76. @click="addPermit(null, 'add', '新增记录规则')"
  77. >
  78. 新建
  79. </el-button>
  80. </template>
  81. <!-- <template v-slot:status="{ row }"> </template> -->
  82. <template v-slot:action="{ row }">
  83. <el-link
  84. type="primary"
  85. :underline="false"
  86. icon="el-icon-document-copy"
  87. @click="addPermit(row, 'clone', '克隆记录规则')"
  88. >
  89. 克隆
  90. </el-link>
  91. <el-link
  92. v-if="row.publishStatus === 1 && !row.isUpdatedVersion"
  93. type="success"
  94. :underline="false"
  95. icon="el-icon-finished"
  96. @click="addPermit(row, 'change', '变更记录规则')"
  97. >
  98. 变更
  99. </el-link>
  100. <!-- <el-popconfirm
  101. v-if="row.publishStatus == 1"
  102. class="ele-action"
  103. title="确定要撤销此条数据吗?"
  104. @confirm="recordrulesRevokePublish(row)"
  105. >
  106. <template v-slot:reference>
  107. <el-link type="warning" :underline="false" icon="el-icon-delete">
  108. 撤销
  109. </el-link>
  110. </template>
  111. </el-popconfirm> -->
  112. <el-link
  113. v-if="row.publishStatus != 1"
  114. type="primary"
  115. :underline="false"
  116. icon="el-icon-edit"
  117. @click="addPermit(row, 'edit', '修改记录规则')"
  118. >
  119. 修改
  120. </el-link>
  121. <el-popconfirm
  122. v-if="row.publishStatus != 1"
  123. class="ele-action"
  124. title="确定要发布此条数据吗?"
  125. @confirm="publish(row)"
  126. >
  127. <template v-slot:reference>
  128. <el-link
  129. type="primary"
  130. :underline="false"
  131. icon="el-icon-position"
  132. >
  133. 发布
  134. </el-link>
  135. </template>
  136. </el-popconfirm>
  137. <el-link
  138. v-if="row.publishStatus == 1"
  139. type="primary"
  140. :underline="false"
  141. icon="el-icon-tickets"
  142. @click="openHistory(row)"
  143. >
  144. 历史版本
  145. </el-link>
  146. <el-popconfirm
  147. v-if="row.publishStatus != 1"
  148. class="ele-action"
  149. title="确定要删除此条数据吗?"
  150. @confirm="remove(row)"
  151. >
  152. <template v-slot:reference>
  153. <el-link
  154. type="danger"
  155. :underline="false"
  156. icon="el-icon-delete"
  157. >
  158. 删除
  159. </el-link>
  160. </template>
  161. </el-popconfirm>
  162. </template>
  163. <template v-slot:code="{ row }">
  164. <el-link
  165. type="primary"
  166. :underline="false"
  167. @click="addPermit(row, 'detail', '记录规则详情')"
  168. >{{ row.code }}</el-link
  169. >
  170. </template>
  171. </ele-pro-table>
  172. </template>
  173. </ele-split-layout>
  174. </el-card>
  175. <permitAdd
  176. ref="permitAddRef"
  177. @reload="reload"
  178. :typeInfo="treeNode"
  179. @reloadTypeList="getTypeList"
  180. />
  181. <historyModal ref="historyModalRef" />
  182. <editTypeModal ref="editTypeModalRef" @reload="getTypeList"></editTypeModal>
  183. </div>
  184. </template>
  185. <script>
  186. import search from './components/search.vue';
  187. import permitAdd from './components/permitAdd.vue';
  188. import {
  189. recordrulesPage,
  190. recordrulesDeletes,
  191. recordrulesPublish,
  192. recordrulesRevokePublish,
  193. recordrulesTypePage,
  194. recordrulesTypeDeletes,
  195. } from '@/api/recordrules/index';
  196. import tabMixins from '@/mixins/tableColumnsMixin';
  197. import dictMixins from '@/mixins/dictMixins';
  198. import historyModal from './components/historyModal.vue';
  199. import editTypeModal from './components/editTypeModal.vue';
  200. export default {
  201. components: { search, permitAdd, historyModal, editTypeModal },
  202. mixins: [tabMixins, dictMixins],
  203. computed: {
  204. columns() {
  205. return [
  206. {
  207. columnKey: 'index',
  208. label: '序号',
  209. type: 'index',
  210. width: 55,
  211. align: 'center',
  212. showOverflowTooltip: true,
  213. fixed: 'left'
  214. },
  215. {
  216. prop: 'code',
  217. label: '记录规则编码',
  218. align: 'center',
  219. showOverflowTooltip: true,
  220. minWidth: 110,
  221. slot: 'code'
  222. },
  223. {
  224. prop: 'name',
  225. label: '记录规则名称',
  226. align: 'center',
  227. showOverflowTooltip: true,
  228. minWidth: 110
  229. },
  230. {
  231. prop: 'industryType',
  232. label: '行业类别',
  233. align: 'center',
  234. showOverflowTooltip: true,
  235. minWidth: 110,
  236. formatter: (row) => {
  237. return this.getDictValue('行业类别', row.industryType);
  238. }
  239. },
  240. {
  241. prop: 'businessType',
  242. label: '业务分类',
  243. align: 'center',
  244. showOverflowTooltip: true,
  245. minWidth: 110,
  246. formatter: (row) => {
  247. return this.getDictValue('业务类型', row.businessType);
  248. }
  249. },
  250. {
  251. prop: 'reportWorkType',
  252. label: '模块划分',
  253. align: 'center',
  254. showOverflowTooltip: true,
  255. minWidth: 110,
  256. formatter: (row) => {
  257. return this.getDictValue('记录规则报工类型', row.reportWorkType);
  258. }
  259. },
  260. {
  261. prop: 'classify',
  262. label: '应用场景',
  263. align: 'center',
  264. showOverflowTooltip: true,
  265. minWidth: 110,
  266. formatter: (row) => {
  267. return this.getDictValue('记录规则类型', row.classify);
  268. }
  269. },
  270. {
  271. prop: 'recordTemplateStyle',
  272. label: '模板样式',
  273. align: 'center',
  274. showOverflowTooltip: true,
  275. minWidth: 110,
  276. formatter: (row) => {
  277. return this.getDictValue(
  278. '记录表模板样式',
  279. row.recordTemplateStyle
  280. );
  281. }
  282. },
  283. {
  284. prop: 'executeMethodName',
  285. label: '执行方式',
  286. align: 'center',
  287. showOverflowTooltip: true,
  288. minWidth: 110
  289. },
  290. {
  291. prop: 'produceTaskName',
  292. label: '工序名称',
  293. align: 'center',
  294. showOverflowTooltip: true,
  295. minWidth: 110
  296. },
  297. {
  298. prop: 'version',
  299. label: '版本号',
  300. align: 'center',
  301. showOverflowTooltip: true,
  302. minWidth: 110,
  303. formatter: (row) => {
  304. return `${row.versionSymbol}${row.bigVersion}${row.versionMark}${row.smallVersion}`;
  305. }
  306. },
  307. {
  308. prop: 'fromName',
  309. label: '来源版本',
  310. align: 'center',
  311. showOverflowTooltip: true,
  312. minWidth: 150
  313. },
  314. {
  315. prop: 'startDate',
  316. label: '启用日期',
  317. align: 'center',
  318. showOverflowTooltip: true,
  319. minWidth: 110,
  320. formatter: (row) => {
  321. return this.$util.toDateString(row.startDate, 'yyyy-MM-dd');
  322. }
  323. },
  324. {
  325. prop: 'stopDate',
  326. label: '停用日期',
  327. align: 'center',
  328. showOverflowTooltip: true,
  329. minWidth: 110,
  330. formatter: (row) => {
  331. return this.$util.toDateString(row.stopDate, 'yyyy-MM-dd');
  332. }
  333. },
  334. {
  335. prop: '',
  336. label: '周期',
  337. align: 'center',
  338. showOverflowTooltip: true,
  339. formatter: (row) => {
  340. return (
  341. row.frequencyValue +
  342. this.getDictValue('规则周期', row.frequencyUnit)
  343. );
  344. }
  345. },
  346. {
  347. prop: 'createUserName',
  348. label: '创建人',
  349. align: 'center',
  350. showOverflowTooltip: true,
  351. minWidth: 110
  352. },
  353. {
  354. prop: 'createTime',
  355. label: '创建时间',
  356. align: 'center',
  357. showOverflowTooltip: true,
  358. minWidth: 110
  359. },
  360. {
  361. prop: 'enable',
  362. label: '是否启用',
  363. align: 'center',
  364. showOverflowTooltip: true,
  365. minWidth: 110,
  366. formatter: (row) => {
  367. return row.enable ? '启用' : '停用';
  368. }
  369. },
  370. {
  371. prop: 'publishStatus',
  372. label: '状态',
  373. align: 'center',
  374. showOverflowTooltip: true,
  375. minWidth: 110,
  376. formatter: (row) => {
  377. switch (row.publishStatus) {
  378. case 0:
  379. return '草稿';
  380. case 1:
  381. return '已发布';
  382. case 2:
  383. return '已撤销';
  384. default:
  385. return '';
  386. }
  387. }
  388. },
  389. {
  390. columnKey: 'action',
  391. label: '操作',
  392. width: 260,
  393. align: 'center',
  394. resizable: false,
  395. slot: 'action',
  396. fixed: 'right'
  397. }
  398. ];
  399. }
  400. },
  401. data() {
  402. return {
  403. loading: false,
  404. cacheKeyUrl: 'maindata-25922-recordrules-index',
  405. typeTree: [],
  406. treeNode: null
  407. };
  408. },
  409. created() {
  410. this.getTypeList();
  411. },
  412. methods: {
  413. addPermit(row, type, title) {
  414. if (type == 'add') {
  415. if (!this.treeNode) {
  416. return this.$message.warning('请先选择类型节点!');
  417. }
  418. if (this.treeNode.type != 'templateStyle') {
  419. return this.$message.warning('请先选择左侧模板样式节点!');
  420. }
  421. }
  422. this.$refs.permitAddRef.open(row, type, title);
  423. },
  424. async remove(row) {
  425. try {
  426. console.log('row', row);
  427. await recordrulesDeletes([row.id]);
  428. this.$message.success('删除成功');
  429. this.reload();
  430. } catch (error) {
  431. this.$message.error('删除失败');
  432. }
  433. },
  434. /* 表格数据源 */
  435. datasource({ page, limit, where, order }) {
  436. const typeWhere = {};
  437. console.log('this.treeNode~~~~~~~~~~~~~~~', this.treeNode);
  438. if (this.treeNode && this.treeNode.item) {
  439. if (this.treeNode.type === 'industry') {
  440. typeWhere.industryType = this.treeNode.item.industryType;
  441. } else if (this.treeNode.type === 'business') {
  442. typeWhere.industryType = this.treeNode.item.industryType;
  443. typeWhere.businessType = this.treeNode.item.businessType;
  444. } else if (this.treeNode.type === 'reportWork') {
  445. typeWhere.industryType = this.treeNode.item.industryType;
  446. typeWhere.businessType = this.treeNode.item.businessType;
  447. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  448. } else if (this.treeNode.type === 'scene') {
  449. typeWhere.industryType = this.treeNode.item.industryType;
  450. typeWhere.businessType = this.treeNode.item.businessType;
  451. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  452. typeWhere.classify = this.treeNode.item.sceneType;
  453. } else {
  454. typeWhere.industryType = this.treeNode.item.industryType;
  455. typeWhere.businessType = this.treeNode.item.businessType;
  456. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  457. typeWhere.classify = this.treeNode.item.sceneType;
  458. typeWhere.recordTemplateStyle =
  459. this.treeNode.item.templateStyleType;
  460. }
  461. }
  462. return recordrulesPage({
  463. pageNum: page,
  464. size: limit,
  465. ...where,
  466. ...typeWhere
  467. });
  468. },
  469. /* 刷新表格 */
  470. reload(where) {
  471. const typeWhere = {};
  472. if (this.treeNode && this.treeNode.item) {
  473. if (this.treeNode.type === 'industry') {
  474. typeWhere.industryType = this.treeNode.item.industryType;
  475. } else if (this.treeNode.type === 'business') {
  476. typeWhere.industryType = this.treeNode.item.industryType;
  477. typeWhere.businessType = this.treeNode.item.businessType;
  478. } else if (this.treeNode.type === 'reportWork') {
  479. typeWhere.industryType = this.treeNode.item.industryType;
  480. typeWhere.businessType = this.treeNode.item.businessType;
  481. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  482. } else if (this.treeNode.type === 'scene') {
  483. typeWhere.industryType = this.treeNode.item.industryType;
  484. typeWhere.businessType = this.treeNode.item.businessType;
  485. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  486. typeWhere.classify = this.treeNode.item.sceneType;
  487. } else {
  488. typeWhere.industryType = this.treeNode.item.industryType;
  489. typeWhere.businessType = this.treeNode.item.businessType;
  490. typeWhere.reportWorkType = this.treeNode.item.reportWorkType;
  491. typeWhere.classify = this.treeNode.item.sceneType;
  492. typeWhere.recordTemplateStyle =
  493. this.treeNode.item.templateStyleType;
  494. }
  495. }
  496. this.$refs.table.reload({ page: 1, where, ...typeWhere });
  497. },
  498. // 发布
  499. async publish(row) {
  500. // 判断时间
  501. const startDate = new Date(row.startDate);
  502. const stopDate = new Date(row.stopDate);
  503. if (startDate >= stopDate) {
  504. return this.$message.warning('请先修改规则停用时间!');
  505. }
  506. try {
  507. await recordrulesPublish(row.id);
  508. this.$message.success('发布成功');
  509. this.reload();
  510. } catch (error) {
  511. this.$message.error('发布失败');
  512. }
  513. },
  514. // 撤销
  515. async recordrulesRevokePublish(row) {
  516. try {
  517. await recordrulesRevokePublish(row.id);
  518. this.$message.success('撤销成功');
  519. this.reload();
  520. } catch (error) {
  521. this.$message.error('撤销失败');
  522. }
  523. },
  524. // 历史版本
  525. openHistory(row) {
  526. this.$refs.historyModalRef.open(row.id);
  527. },
  528. // 类型列表
  529. async getTypeList() {
  530. const { list = [] } = await recordrulesTypePage({
  531. pageNum: 1,
  532. size: 99999
  533. });
  534. console.log('type list', list);
  535. const industryMap = new Map();
  536. list.forEach((item) => {
  537. // industry
  538. let industryNode = industryMap.get(item.industryType);
  539. if (!industryNode) {
  540. industryNode = {
  541. id: 'industry-' + item.industryType,
  542. type: 'industry',
  543. value: item.industryType,
  544. label: item.industryName,
  545. children: [],
  546. item,
  547. _businessMap: new Map()
  548. };
  549. industryMap.set(item.industryType, industryNode);
  550. }
  551. // business
  552. let businessNode = industryNode._businessMap.get(item.businessType);
  553. if (!businessNode) {
  554. businessNode = {
  555. id: `business-${item.industryType}-${item.businessType}`,
  556. type: 'business',
  557. value: item.businessType,
  558. label: item.businessName,
  559. children: [],
  560. item,
  561. _reportMap: new Map()
  562. };
  563. industryNode._businessMap.set(item.businessType, businessNode);
  564. industryNode.children.push(businessNode);
  565. }
  566. // reportWork
  567. let reportNode = businessNode._reportMap.get(item.reportWorkType);
  568. if (!reportNode) {
  569. reportNode = {
  570. id: `report-${item.industryType}-${item.businessType}-${item.reportWorkType}`,
  571. type: 'reportWork',
  572. value: item.reportWorkType,
  573. label: item.reportWorkName,
  574. children: [],
  575. item,
  576. _sceneMap: new Map()
  577. };
  578. businessNode._reportMap.set(item.reportWorkType, reportNode);
  579. businessNode.children.push(reportNode);
  580. }
  581. // scene
  582. let sceneNode = reportNode._sceneMap.get(item.sceneType);
  583. if (!sceneNode) {
  584. sceneNode = {
  585. id: `scene-${item.industryType}-${item.businessType}-${item.reportWorkType}-${item.sceneType}`,
  586. type: 'scene',
  587. value: item.sceneType,
  588. label: item.sceneName,
  589. children: [],
  590. item,
  591. _templateMap: new Map()
  592. };
  593. reportNode._sceneMap.set(item.sceneType, sceneNode);
  594. reportNode.children.push(sceneNode);
  595. }
  596. // template style
  597. let templateNode = sceneNode._templateMap.get(item.templateStyleType);
  598. if (!templateNode) {
  599. templateNode = {
  600. id: `template-${item.industryType}-${item.businessType}-${item.reportWorkType}-${item.sceneType}-${item.templateStyleType}`,
  601. type: 'templateStyle',
  602. value: item.templateStyleType,
  603. label: item.templateStyleName,
  604. item,
  605. children: []
  606. };
  607. sceneNode._templateMap.set(item.templateStyleType, templateNode);
  608. sceneNode.children.push(templateNode);
  609. }
  610. // 原始数据
  611. templateNode.item = item;
  612. });
  613. const clean = (node) => {
  614. delete node._businessMap;
  615. delete node._reportMap;
  616. delete node._sceneMap;
  617. delete node._templateMap;
  618. node.children && node.children.forEach(clean);
  619. };
  620. const tree = Array.from(industryMap.values());
  621. tree.forEach(clean);
  622. this.typeTree = tree; // 结果树
  623. if (!this.treeNode) {
  624. // 默认选中第一个节点
  625. this.treeNode = this.typeTree.length > 0 ? this.typeTree[0] : null;
  626. // console.log('this.treeNode`1111111111111111111111`', this.treeNode);
  627. if (this.treeNode) {
  628. // 默认选中节点
  629. this.$nextTick(() => {
  630. this.$refs.treeRef.setCurrentKey(this.treeNode.id);
  631. this.reload();
  632. });
  633. }
  634. }
  635. console.log('typeTree', this.typeTree);
  636. },
  637. // 打开新增类型
  638. openEditType(type = 'add', data = null) {
  639. this.$refs.editTypeModalRef.open(type, type == 'add' ? this.treeNode : data);
  640. },
  641. async deleteTypeNode(node) {
  642. console.log('delete node', node);
  643. // 删除类型节点
  644. await recordrulesTypeDeletes([node.data.item.id]);
  645. this.$message.success('删除成功');
  646. this.getTypeList();
  647. },
  648. handleNodeClick(data) {
  649. console.log('data', data);
  650. this.treeNode = data;
  651. this.reload();
  652. }
  653. }
  654. };
  655. </script>
  656. <style lang="scss" scoped>
  657. .sys-organization-list {
  658. height: calc(100vh - 264px);
  659. box-sizing: border-box;
  660. border-width: 1px;
  661. border-style: solid;
  662. overflow: auto;
  663. padding: 10px 5px;
  664. }
  665. .sys-organization-list :deep(.el-tree-node__content) {
  666. height: 30px;
  667. & > .el-tree-node__expand-icon {
  668. // margin-left: 10px;
  669. }
  670. }
  671. .custom-tree-node {
  672. flex: 1;
  673. display: flex;
  674. align-items: center;
  675. justify-content: space-between;
  676. font-size: 14px;
  677. padding-right: 8px;
  678. .edit-box {
  679. display: none;
  680. gap: 2px;
  681. cursor: pointer;
  682. }
  683. &:hover .edit-box {
  684. display: flex;
  685. }
  686. }
  687. </style>