index.vue 18 KB

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