index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <template>
  2. <div class="ele-body">
  3. <el-card shadow="never">
  4. <!-- 搜索表单 -->
  5. <index-search @search="reload" />
  6. <!-- 数据表格 -->
  7. <ele-pro-table
  8. ref="table"
  9. row-key="id"
  10. :columns="columns"
  11. :datasource="datasource"
  12. height="calc(100vh - 340px)"
  13. full-height="calc(100vh - 116px)"
  14. cache-key="project-initiationTable"
  15. :selection.sync="selection"
  16. :tree-props="{ children: 'children' }"
  17. @row-click="handlePlanTableNodeClick"
  18. >
  19. <!-- 表头工具栏 -->
  20. <template v-slot:toolbar>
  21. <!-- <el-button
  22. size="small"
  23. type="primary"
  24. icon="el-icon-plus"
  25. class="ele-btn-icon"
  26. @click="openEdit2('', 'add')"
  27. >
  28. 新建2
  29. </el-button> -->
  30. <el-button
  31. size="small"
  32. type="primary"
  33. icon="el-icon-plus"
  34. class="ele-btn-icon"
  35. @click="openEdit('', 'add')"
  36. >
  37. 新建
  38. </el-button>
  39. <el-button
  40. size="small"
  41. type="danger"
  42. icon="el-icon-delete"
  43. class="ele-btn-icon"
  44. @click="allDelBtn"
  45. >
  46. 删除
  47. </el-button>
  48. <!-- <el-button-->
  49. <!-- size="small"-->
  50. <!-- type="danger"-->
  51. <!-- icon="el-icon-remove-outline"-->
  52. <!-- class="ele-btn-icon"-->
  53. <!-- @click="handleStatus('4')"-->
  54. <!-- >-->
  55. <!-- 终止-->
  56. <!-- </el-button>-->
  57. <!-- <el-button-->
  58. <!-- size="small"-->
  59. <!-- type="warning"-->
  60. <!-- icon="el-icon-video-play"-->
  61. <!-- class="ele-btn-icon"-->
  62. <!-- @click="handleStatus('2')"-->
  63. <!-- >-->
  64. <!-- 暂停-->
  65. <!-- </el-button>-->
  66. <!-- <el-button-->
  67. <!-- size="small"-->
  68. <!-- type="primary"-->
  69. <!-- icon="el-icon-video-pause"-->
  70. <!-- class="ele-btn-icon"-->
  71. <!-- @click="handleStatus('1')"-->
  72. <!-- >-->
  73. <!-- 启动-->
  74. <!-- </el-button>-->
  75. <!-- <el-button class="el-icon-sort" size="small" @click="expandAll">-->
  76. <!-- 展开/折叠-->
  77. <!-- </el-button>-->
  78. <!-- <div class="el-button--primary">122222</div> -->
  79. </template>
  80. <template v-slot:code="{ row }">
  81. <el-button type="text" @click="openDetail(row)">{{
  82. row.code
  83. }}</el-button>
  84. </template>
  85. <template v-slot:isOverTime="{ row }">
  86. <el-tag v-if="row.isOverTime == 0" type="success">正常</el-tag>
  87. <el-tag v-else type="danger">超时</el-tag>
  88. </template>
  89. <template v-slot:speedPercent="{ row }">
  90. <el-progress
  91. :stroke-width="20"
  92. text-color="#606266"
  93. :text-inside="true"
  94. :percentage="row.speedPercent || 0"
  95. :color="customColorMethod"
  96. ></el-progress>
  97. </template>
  98. <!-- 操作列 -->
  99. <template v-slot:action="{ row }">
  100. <el-link
  101. type="primary"
  102. :underline="false"
  103. icon="el-icon-plus"
  104. @click="processSubmit(row)"
  105. v-if="[0, 3].includes(row.processStatus)"
  106. >
  107. 提交
  108. </el-link>
  109. <el-link
  110. type="primary"
  111. :underline="false"
  112. icon="el-icon-edit"
  113. v-if="[0, 3].includes(row.processStatus)"
  114. @click="openEdit(row, 'edit')"
  115. >
  116. 修改
  117. </el-link>
  118. <el-popconfirm
  119. class="ele-action"
  120. title="确定要删除吗?"
  121. v-if="[0, 3].includes(row.processStatus)"
  122. @confirm="remove([row.id])"
  123. >
  124. <template v-slot:reference>
  125. <el-link type="danger" :underline="false" icon="el-icon-delete">
  126. 删除
  127. </el-link>
  128. </template>
  129. </el-popconfirm>
  130. <el-dropdown trigger="click">
  131. <span class="el-dropdown-link">
  132. 操作菜单<i class="el-icon-arrow-down el-icon--right"></i>
  133. </span>
  134. <el-dropdown-menu slot="dropdown">
  135. <el-dropdown-item
  136. v-if="
  137. [2].includes(row.processStatus) && [1].includes(row.status)
  138. "
  139. >
  140. <el-link
  141. icon="el-icon-success"
  142. type="success"
  143. :underline="false"
  144. @click="handleStatus(planFinishAPI, '完成', row)"
  145. >完成
  146. </el-link>
  147. </el-dropdown-item>
  148. <el-dropdown-item
  149. v-if="
  150. [2].includes(row.processStatus) && [0, 1].includes(row.status)
  151. "
  152. >
  153. <el-link
  154. icon="el-icon-video-pause"
  155. type="warning"
  156. :underline="false"
  157. @click="handleStatus(planPauseAPI, '暂停', row)"
  158. >暂停
  159. </el-link>
  160. </el-dropdown-item>
  161. <el-dropdown-item
  162. v-if="
  163. [2].includes(row.processStatus) && [2].includes(row.status)
  164. "
  165. >
  166. <el-link
  167. icon="el-icon-video-play"
  168. type="success"
  169. :underline="false"
  170. @click="handleStatus(planStartupAPI, '启动', row)"
  171. >启动
  172. </el-link>
  173. </el-dropdown-item>
  174. <el-dropdown-item
  175. v-if="
  176. [2].includes(row.processStatus) &&
  177. [0, 1, 2].includes(row.status)
  178. "
  179. >
  180. <el-link
  181. icon="el-icon-error"
  182. type="danger"
  183. :underline="false"
  184. @click="handleStatus(planTerminationAPI, '终止', row)"
  185. >终止</el-link
  186. >
  187. </el-dropdown-item>
  188. <el-dropdown-item>
  189. <el-link
  190. icon="el-icon-info"
  191. type="primary"
  192. :underline="false"
  193. @click="handelBOMConstructDetail(row)"
  194. >
  195. 计划信息
  196. </el-link>
  197. </el-dropdown-item>
  198. <el-dropdown-item
  199. divided
  200. v-if="
  201. [0, 1, 2, 3].includes(row.processStatus) &&
  202. [0, 1].includes(row.status)
  203. "
  204. >
  205. <el-link
  206. type="primary"
  207. :underline="false"
  208. icon="el-icon-plus"
  209. @click="openEdit({ ...row, parentPlanId: row.id }, 'add')"
  210. >
  211. 新增子计划
  212. </el-link>
  213. </el-dropdown-item>
  214. <el-dropdown-item
  215. divided
  216. v-if="
  217. [0, 1, 2, 3].includes(row.processStatus) &&
  218. [0, 1].includes(row.status)
  219. "
  220. >
  221. <el-link
  222. type="primary"
  223. :underline="false"
  224. icon="el-icon-plus"
  225. @click="handleAddTask(row)"
  226. >
  227. 新增任务
  228. </el-link>
  229. </el-dropdown-item>
  230. </el-dropdown-menu>
  231. </el-dropdown>
  232. </template>
  233. </ele-pro-table>
  234. </el-card>
  235. <!-- 编辑弹窗 -->
  236. <add-or-edit-dialog
  237. v-if="addOrEditDialogFlag"
  238. @reload="reload"
  239. :addOrEditDialogFlag.sync="addOrEditDialogFlag"
  240. ref="addOrEditDialogRef"
  241. ></add-or-edit-dialog>
  242. <add-dialog
  243. v-if="addDialogFlag"
  244. @reload="reload"
  245. :addDialogFlag.sync="addDialogFlag"
  246. ref="addDialogRef"
  247. ></add-dialog>
  248. <detail-dialog
  249. v-if="detailDialogFlag"
  250. :detailDialogFlag.sync="detailDialogFlag"
  251. ref="detailDialogRef"
  252. ></detail-dialog>
  253. <!-- 新增任务 -->
  254. <add-task-dialog
  255. v-if="addTaskDialogFlag"
  256. @reload="reload"
  257. :addOrEditDialogFlag.sync="addTaskDialogFlag"
  258. ref="addTaskDialogRef"
  259. ></add-task-dialog>
  260. <!-- 多选删除弹窗 -->
  261. <pop-modal
  262. :visible.sync="delVisible"
  263. content="是否确定删除?"
  264. @done="commitBtn"
  265. />
  266. <process-submit-dialog
  267. :processSubmitDialogFlag.sync="processSubmitDialogFlag"
  268. v-if="processSubmitDialogFlag"
  269. ref="processSubmitDialogRef"
  270. @reload="reload"
  271. ></process-submit-dialog>
  272. </div>
  273. </template>
  274. <script>
  275. import indexSearch from './components/index-search.vue';
  276. import addOrEditDialog from './components/addOrEditDialog.vue';
  277. import detailDialog from './components/detailDialog.vue';
  278. import addDialog from '@/views/project-manage/planManage/components/addDialog.vue';
  279. import {
  280. projectsPlanDeleteAPI,
  281. projectsPlanPageAPI,
  282. myProjectsPlanPageAPI,
  283. submit,
  284. planFinishAPI,
  285. planPauseAPI,
  286. planStartupAPI,
  287. planTerminationAPI
  288. } from '@/api/project-manage/plan';
  289. import { proStatusEnum, reviewStatusEnum } from '@/enum/dict';
  290. import { mapGetters } from 'vuex';
  291. import { getByCode } from '@/api/system/dictionary-data';
  292. import popModal from '@/components/pop-modal/index.vue';
  293. import addTaskDialog from '../task-manage/components/addOrEditDialog.vue';
  294. import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
  295. export default {
  296. name: 'index',
  297. components: {
  298. processSubmitDialog,
  299. popModal,
  300. addOrEditDialog,
  301. detailDialog,
  302. indexSearch,
  303. addDialog,
  304. addTaskDialog
  305. },
  306. props: {
  307. projectType: {
  308. type: Number,
  309. default: 0
  310. },
  311. ids: {
  312. type: String,
  313. default: ''
  314. }
  315. },
  316. watch: {
  317. $route(){
  318. this.reload&&this.reload()
  319. }
  320. },
  321. computed: {
  322. ...mapGetters(['getDictValue']),
  323. columns() {
  324. return [
  325. {
  326. width: 45,
  327. type: 'selection',
  328. columnKey: 'selection',
  329. align: 'center'
  330. },
  331. {
  332. columnKey: 'index',
  333. label: '序号',
  334. type: 'index',
  335. width: 55,
  336. align: 'center',
  337. showOverflowTooltip: true
  338. },
  339. {
  340. prop: 'code',
  341. label: '计划编码',
  342. align: 'center',
  343. showOverflowTooltip: true,
  344. slot: 'code',
  345. minWidth: 200
  346. },
  347. {
  348. prop: 'name',
  349. label: '计划名称',
  350. align: 'center',
  351. showOverflowTooltip: true,
  352. minWidth: 120
  353. },
  354. {
  355. prop: 'projectName',
  356. label: '关联项目',
  357. align: 'center',
  358. showOverflowTooltip: true,
  359. minWidth: 120
  360. },
  361. {
  362. prop: 'projectStageName',
  363. label: '关联项目阶段',
  364. align: 'center',
  365. showOverflowTooltip: true,
  366. minWidth: 120
  367. },
  368. // {
  369. // prop: 'responsibleDeptName',
  370. // label: '负责部门',
  371. // align: 'center',
  372. // showOverflowTooltip: true,
  373. // minWidth: 100
  374. // },
  375. {
  376. prop: 'responsibleUserName',
  377. label: '负责人',
  378. align: 'center',
  379. showOverflowTooltip: true,
  380. minWidth: 120,
  381. formatter: (_row, _column, cellValue) => {
  382. return !_row.responsibleUserList.length
  383. ? ''
  384. : _row.responsibleUserList.map((i) => i.userName).join(',');
  385. }
  386. },
  387. {
  388. prop: 'planStartDate',
  389. label: '计划开始日期',
  390. align: 'center',
  391. showOverflowTooltip: true,
  392. minWidth: 140
  393. },
  394. {
  395. prop: 'planEndDate',
  396. label: '计划完成日期',
  397. align: 'center',
  398. showOverflowTooltip: true,
  399. minWidth: 140
  400. },
  401. {
  402. prop: 'realStartTime',
  403. label: '实际开始日期',
  404. align: 'center',
  405. showOverflowTooltip: true,
  406. minWidth: 140
  407. },
  408. {
  409. prop: 'realEndTime',
  410. label: '实际完成日期',
  411. align: 'center',
  412. showOverflowTooltip: true,
  413. minWidth: 140
  414. },
  415. {
  416. prop: 'cost',
  417. label: '费用(元)',
  418. align: 'center',
  419. showOverflowTooltip: true,
  420. minWidth: 140
  421. },
  422. {
  423. prop: 'status',
  424. label: '计划状态',
  425. align: 'center',
  426. showOverflowTooltip: true,
  427. minWidth: 100,
  428. formatter: (_row, _column, cellValue) => {
  429. return proStatusEnum[_row.status].label;
  430. }
  431. },
  432. {
  433. prop: 'processStatus',
  434. label: '审核状态',
  435. align: 'center',
  436. showOverflowTooltip: true,
  437. minWidth: 100,
  438. formatter: (_row, _column, cellValue) => {
  439. return reviewStatusEnum[_row.processStatus].label;
  440. }
  441. },
  442. {
  443. prop: 'isOverTime',
  444. label: '是否超时',
  445. align: 'center',
  446. showOverflowTooltip: true,
  447. minWidth: 100,
  448. slot: 'isOverTime'
  449. },
  450. {
  451. prop: 'speedPercent',
  452. label: '计划进度',
  453. align: 'center',
  454. showOverflowTooltip: true,
  455. minWidth: 150,
  456. slot: 'speedPercent'
  457. },
  458. {
  459. columnKey: 'action',
  460. label: '操作',
  461. width: 290,
  462. align: 'center',
  463. resizable: false,
  464. slot: 'action',
  465. showOverflowTooltip: true
  466. }
  467. ];
  468. }
  469. },
  470. data() {
  471. return {
  472. planFinishAPI: planFinishAPI,
  473. planPauseAPI: planPauseAPI,
  474. planStartupAPI: planStartupAPI,
  475. planTerminationAPI: planTerminationAPI,
  476. selection: [],
  477. dictList: [],
  478. // 表格列配置
  479. // 是否显示编辑弹窗
  480. addOrEditDialogFlag: false,
  481. addDialogFlag: false,
  482. detailDialogFlag: false,
  483. delVisible: false,
  484. addTaskDialogFlag: false,
  485. processSubmitDialogFlag: false,
  486. // 展开折叠
  487. expandAllFlag: false
  488. };
  489. },
  490. async created() {},
  491. methods: {
  492. handlePlanTableNodeClick(row) {
  493. this.$emit('handlePlanTableNodeClick', row);
  494. },
  495. getDictV(code, val) {
  496. if (!this.dictList[code]) return '';
  497. return this.dictList[code].find((item) => item.value == val)?.label;
  498. },
  499. async getDictList(code) {
  500. let { data: res } = await getByCode(code);
  501. this.dictList[code] = res.map((item) => {
  502. let values = Object.keys(item);
  503. return {
  504. value: values[0],
  505. label: item[values[0]]
  506. };
  507. });
  508. },
  509. customColorMethod(percentage) {
  510. if (percentage < 30) {
  511. return '#909399';
  512. } else if (percentage < 70) {
  513. return '#e6a23c';
  514. } else {
  515. return '#67c23a';
  516. }
  517. },
  518. /* 表格数据源 */
  519. async datasource({ page, limit, where, parent }) {
  520. await this.getDictList('pro_projects_status');
  521. await this.getDictList('pro_projects_type');
  522. const api=this.$route.path=='/planManage'?projectsPlanPageAPI:myProjectsPlanPageAPI
  523. let paramAttr = '';
  524. switch (this.projectType) {
  525. case 1:
  526. paramAttr = 'projectBomId';
  527. break;
  528. case 2:
  529. paramAttr = 'projectStageId';
  530. break;
  531. default:
  532. paramAttr = 'projectId';
  533. }
  534. return api({
  535. pageNum: page,
  536. size: limit,
  537. ...where,
  538. [paramAttr]: this.ids
  539. });
  540. },
  541. /* 刷新表格 */
  542. reload(where) {
  543. this.$refs.table.reload({ where, size: 1, pageNum: 10 });
  544. },
  545. /* 显示编辑 */
  546. openEdit2(row = {}, type) {
  547. this.addDialogFlag = true;
  548. this.$nextTick(() => {
  549. this.$refs.addDialogRef.init(row, type);
  550. });
  551. },
  552. /* 显示编辑 */
  553. openEdit(row = {}, type) {
  554. this.addOrEditDialogFlag = true;
  555. this.$nextTick(() => {
  556. this.$refs.addOrEditDialogRef.init(row, type);
  557. });
  558. },
  559. openDetail(row = {}) {
  560. this.detailDialogFlag = true;
  561. this.$nextTick(() => {
  562. this.$refs.detailDialogRef.init(row);
  563. });
  564. },
  565. handleAddTask(row) {
  566. this.addTaskDialogFlag = true;
  567. this.$nextTick(() => {
  568. row.targetPlanId = row.id;
  569. this.$refs.addTaskDialogRef.init(row, 'add');
  570. });
  571. },
  572. handelBOMConstructDetail(row) {
  573. this.$router.push({
  574. path: '/project-manage/planManage/components/details',
  575. query: {
  576. row: JSON.stringify(row)
  577. }
  578. });
  579. },
  580. //流程提交
  581. processSubmit(row) {
  582. this.processSubmitDialogFlag = true;
  583. this.$nextTick(() => {
  584. let params = {
  585. businessId: row.id,
  586. businessKey: 'pro_plan_approve_basic',
  587. callBackMethodType: '1',
  588. callBackMethod:
  589. 'proTargetPlanApproveApiImpl.updatePlanApprovalStatus',
  590. pcHandle:
  591. '/bpm/handleTask/components/project-manage/plan-manage/submit.vue',
  592. pcView:
  593. '/bpm/handleTask/components/project-manage/plan-manage/detailDialog.vue',
  594. miniHandle: '',
  595. miniView: '',
  596. formCreateUserId: row.createUserId
  597. };
  598. this.$refs.processSubmitDialogRef.init(params);
  599. });
  600. // submit({
  601. // planId: row.id
  602. // }).then((res) => {
  603. // this.$message.success('提交成功');
  604. // this.reload();
  605. // });
  606. },
  607. //批量删除
  608. allDelBtn() {
  609. if (this.selection.length === 0) return;
  610. let flag = this.selection.some((item) =>
  611. [1, 2].includes(item.processStatus)
  612. );
  613. if (flag)
  614. return this.$message.warning(
  615. '抱歉已审核、审核中的数据不能删除,请检查'
  616. );
  617. this.delVisible = true;
  618. },
  619. //删除弹框确定
  620. commitBtn() {
  621. const dataId = this.selection.map((v) => v.id);
  622. this.remove(dataId);
  623. },
  624. /* 删除 */
  625. remove(ids) {
  626. const loading = this.$loading({ lock: true });
  627. projectsPlanDeleteAPI(ids)
  628. .then((res) => {
  629. loading.close();
  630. this.$message.success('删除成功');
  631. this.reload();
  632. })
  633. .catch((e) => {
  634. loading.close();
  635. // this.$message.error(e.message);
  636. });
  637. },
  638. async handleStatus(API, msg, row) {
  639. let message = '确定' + msg + '该计划吗';
  640. this.$confirm(message, '提示', {
  641. type: 'warning'
  642. })
  643. .then(async () => {
  644. await API(row.id);
  645. this.$message.success('操作成功');
  646. this.reload();
  647. })
  648. .catch(() => {});
  649. },
  650. /* 展开/折叠全部 */
  651. expandAll() {
  652. this.expandAllFlag = !this.expandAllFlag;
  653. this.$refs.table.toggleRowExpansionAll(this.expandAllFlag);
  654. }
  655. }
  656. };
  657. </script>
  658. <style lang="scss" scoped>
  659. .el-dropdown-link {
  660. cursor: pointer;
  661. color: #188ffd;
  662. }
  663. ::v-deep .el-dropdown-link {
  664. cursor: pointer;
  665. color: #188ffd;
  666. }
  667. ::v-deep .el-dropdown-menu__item {
  668. .el-link {
  669. width: 100%;
  670. display: flex;
  671. flex: 1;
  672. justify-content: flex-start;
  673. }
  674. }
  675. ::v-deep .ele-table-tool-default {
  676. display: flex !important;
  677. }
  678. </style>