task.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="10">
  4. <el-col :span="5" style="position:relative;z-index: 20">
  5. <project ref="pjTree" @selectProject="selectProject"></project>
  6. </el-col>
  7. <el-col :span="19">
  8. <div class="query-container">
  9. <el-form :model="queryParams" ref="queryForm" size="mini" :inline="true">
  10. <el-form-item prop="executors">
  11. <dept-user-tree ref="dut" :userList="userList" :multiple="true"
  12. @selected="(val)=>queryParams.executors=val"></dept-user-tree>
  13. </el-form-item>
  14. <el-form-item prop="startDate">
  15. <el-date-picker
  16. v-model="queryParams.startDate"
  17. type="date"
  18. value-format="yyyy-MM-dd"
  19. placeholder="开始日期"
  20. clearable
  21. style="width: 135px">
  22. </el-date-picker>
  23. </el-form-item>
  24. <el-form-item prop="endDate">
  25. <el-date-picker
  26. v-model="queryParams.endDate"
  27. type="date"
  28. value-format="yyyy-MM-dd"
  29. placeholder="结束日期"
  30. clearable
  31. style="width: 135px">
  32. </el-date-picker>
  33. </el-form-item>
  34. <el-form-item prop="status">
  35. <el-select
  36. v-model="queryParams.status"
  37. placeholder="任务状态"
  38. style="width: 85px">
  39. <el-option
  40. v-for="dict in dict.type.task_status"
  41. :key="dict.value"
  42. :label="dict.label"
  43. :value="dict.value">
  44. <el-tag :type="statusMap[dict.value].type">
  45. {{ dict.label }}
  46. </el-tag>
  47. </el-option>
  48. </el-select>
  49. </el-form-item>
  50. <el-form-item prop="priority">
  51. <el-select
  52. v-model="queryParams.priority"
  53. placeholder="优先级"
  54. style="width: 85px">
  55. <el-option
  56. v-for="dict in dict.type.task_priority"
  57. :key="dict.value"
  58. :label="dict.label"
  59. :value="dict.value">
  60. <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
  61. {{ dict.label }}
  62. </el-tag>
  63. </el-option>
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item>
  67. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  68. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  69. </el-form-item>
  70. </el-form>
  71. <el-row :gutter="10" style="margin-bottom:8px">
  72. <el-col :span="1.5">
  73. <el-button
  74. type="primary"
  75. plain
  76. icon="el-icon-plus"
  77. size="mini"
  78. @click="handleAdd"
  79. v-hasPermi="['task:task:add']"
  80. >新增任务
  81. </el-button>
  82. </el-col>
  83. </el-row>
  84. </div>
  85. <el-table :data="taskList"
  86. ref="taskList"
  87. height="calc(100vh - 150px)"
  88. @cell-mouse-enter="cellMouseEnter"
  89. @cell-mouse-leave="cellMouseLeave"
  90. @cell-click="cellClick"
  91. @sort-change="sortChange"
  92. row-key="id"
  93. :indent="10"
  94. :tree-props="{children: 'children'}">
  95. <el-table-column label="任务编号" prop="id"/>
  96. <el-table-column label="任务名称" prop="taskName" min-width="150" :show-overflow-tooltip="true"/>
  97. <el-table-column label="执行(负责)人" prop="executorName" width="100"/>
  98. <el-table-column label="进度" prop="progressValue" width="70">
  99. <template slot-scope="scope">
  100. <span>{{ (scope.row.progressValue ? scope.row.progressValue : 0) + '%' }}</span>
  101. </template>
  102. </el-table-column>
  103. <el-table-column label="状态" align="center" width="80">
  104. <template slot-scope="scope">
  105. <el-tag size="mini" :type="statusMap[scope.row.status].type">{{
  106. statusMap[scope.row.status].name
  107. }}
  108. </el-tag>
  109. </template>
  110. </el-table-column>
  111. <el-table-column label="优先级" prop="priority" align="center" width="80">
  112. <template slot-scope="scope">
  113. <el-tag v-if="scope.row.priority==='1'" color="#fa8888" effect="dark" :hit="false">
  114. {{ getTaskPriority(scope.row.priority) }}
  115. </el-tag>
  116. <el-tag v-else-if="scope.row.priority==='2'" color="#fb7fb7" effect="dark" :hit="false">
  117. {{ getTaskPriority(scope.row.priority) }}
  118. </el-tag>
  119. <el-tag v-else-if="scope.row.priority==='3'" color="#40e0c3" effect="dark" :hit="false">
  120. {{ getTaskPriority(scope.row.priority) }}
  121. </el-tag>
  122. <el-tag v-else color="#5dcfff" effect="dark" :hit="false">{{
  123. getTaskPriority(scope.row.priority)
  124. }}
  125. </el-tag>
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="开始时间" prop="beginDate" sortable="custom" width="100"/>
  129. <el-table-column label="结束时间" prop="endDate" sortable="custom" width="100"/>
  130. <el-table-column label="操作" width="120">
  131. <template slot-scope="scope">
  132. <el-button size="mini"
  133. type="text"
  134. icon="el-icon-coordinate"
  135. @click="handleAudit(scope.row)"
  136. :disabled="scope.row.status!='6'"
  137. v-hasPermi="['task:task:audit']"
  138. >审核
  139. </el-button>
  140. <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)"
  141. v-hasPermi="['task:task:edit','task:task:split', 'task:task:delete']">
  142. <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
  143. <el-dropdown-menu slot="dropdown">
  144. <el-dropdown-item command="handleSplit" icon="el-icon-tickets"
  145. v-hasPermi="['task:task:split']"
  146. >分解
  147. </el-dropdown-item>
  148. <el-dropdown-item command="handleUpdate" icon="el-icon-edit-outline"
  149. v-hasPermi="['task:task:edit']"
  150. >终止
  151. </el-dropdown-item>
  152. <el-dropdown-item command="handleEdit" icon="el-icon-edit"
  153. v-hasPermi="['task:task:edit']"
  154. >修改
  155. </el-dropdown-item>
  156. <el-dropdown-item command="handleDelete" icon="el-icon-delete"
  157. v-hasPermi="['task:task:delete']"
  158. >删除
  159. </el-dropdown-item>
  160. </el-dropdown-menu>
  161. </el-dropdown>
  162. </template>
  163. </el-table-column>
  164. </el-table>
  165. <div style="margin-top: 10px;text-align: center">
  166. <el-pagination
  167. background
  168. @size-change="handleSizeChange"
  169. @current-change="handleCurrentChange"
  170. :current-page="queryParams.pageNum"
  171. :page-sizes="[10, 20, 50]"
  172. :page-size="queryParams.pageSize"
  173. layout="total, sizes, prev, pager, next, jumper"
  174. :total="total">
  175. </el-pagination>
  176. </div>
  177. </el-col>
  178. </el-row>
  179. <!-- 添加或修改任务配置对话框 -->
  180. <el-dialog :title="title" :visible.sync="open" width="800px" class="add-dialog" append-to-body @close="cancel">
  181. <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="115px">
  182. <el-form-item label="任务名称" prop="taskName">
  183. <el-input v-model="form.taskName" placeholder="请输入任务名称"/>
  184. </el-form-item>
  185. <el-row>
  186. <el-col :span="12">
  187. <el-form-item label="所属项目" prop="projectId" class="mini-treeselect">
  188. <treeselect v-model="form.projectId" :options="projectOptions"
  189. :open-on-click="true"
  190. :normalizer="normalizer"
  191. :flat="true"
  192. style="width: 220px"
  193. placeholder="请选择"/>
  194. </el-form-item>
  195. </el-col>
  196. <el-col :span="12">
  197. <el-form-item label="执行(负责)人" prop="executor">
  198. <dept-user-tree ref="dut2" :userList="userList"
  199. style="width: 220px"
  200. @selected="selectExecutor"/>
  201. </el-form-item>
  202. </el-col>
  203. </el-row>
  204. <el-row>
  205. <el-col :span="12">
  206. <el-form-item label="开始时间" prop="beginDate">
  207. <el-date-picker
  208. v-model="form.beginDate"
  209. type="date"
  210. value-format="yyyy-MM-dd"
  211. @change="checkDates(form.beginDate,form.endDate)"
  212. style="width: 220px"
  213. placeholder="开始日期">
  214. </el-date-picker>
  215. </el-form-item>
  216. </el-col>
  217. <el-col :span="12">
  218. <el-form-item label="结束时间" prop="endDate">
  219. <el-date-picker
  220. v-model="form.endDate"
  221. @change="checkDates(form.beginDate,form.endDate)"
  222. type="date"
  223. value-format="yyyy-MM-dd"
  224. style="width: 220px"
  225. placeholder="开始日期">
  226. </el-date-picker>
  227. </el-form-item>
  228. </el-col>
  229. </el-row>
  230. <el-row>
  231. <el-col :span="12">
  232. <el-form-item label="优先级">
  233. <el-select
  234. v-model="form.priority"
  235. style="width: 220px"
  236. placeholder="任务优先级">
  237. <el-option
  238. v-for="dict in dict.type.task_priority"
  239. :key="dict.value"
  240. :label="dict.label"
  241. :value="dict.value">
  242. <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
  243. {{ dict.label }}
  244. </el-tag>
  245. </el-option>
  246. </el-select>
  247. </el-form-item>
  248. </el-col>
  249. <el-col :span="12">
  250. <el-form-item label="任务附件">
  251. <file-upload ref="fu" :files="form.fileList" @getFileUrl="getFileUrl"
  252. @removeFile="removeFile"></file-upload>
  253. </el-form-item>
  254. </el-col>
  255. </el-row>
  256. <el-form-item label="任务描述" prop="description">
  257. <rich-text-editor ref="rtEditor" v-model="form.description" v-if="open"></rich-text-editor>
  258. </el-form-item>
  259. </el-form>
  260. <div slot="footer" class="dialog-footer">
  261. <el-button type="primary" size="mini" @click="submitForm">确 定</el-button>
  262. <el-button size="mini" @click="cancel">取 消</el-button>
  263. </div>
  264. </el-dialog>
  265. <!-- 任务详情对话框 -->
  266. <el-dialog :title="detailForm.taskName" :visible.sync="detailOpen" width="900px" class="add-dialog" append-to-body
  267. :close-on-click-modal="true">
  268. <task-detail :detail-form="detailForm"></task-detail>
  269. </el-dialog>
  270. <!-- 审核任务对话框 -->
  271. <el-dialog :title="detailForm.taskName" :visible.sync="auditOpen" width="900px" class="add-dialog" append-to-body
  272. @close="auditCancel">
  273. <task-detail :detail-form="detailForm"></task-detail>
  274. <el-form ref="auditForm" :model="auditForm" :rules="auditRules" size="mini" label-width="100px">
  275. <el-row>
  276. <el-col :span="12">
  277. <el-form-item label="审核意见" prop="auditResult">
  278. <el-radio-group v-model="auditForm.auditResult">
  279. <el-radio label="1">确认完成</el-radio>
  280. <el-radio label="0">驳回</el-radio>
  281. </el-radio-group>
  282. </el-form-item>
  283. </el-col>
  284. <el-col :span="12">
  285. <el-form-item v-if="auditForm.auditResult==='0'" label="进度(%)" prop="value">
  286. <el-input-number v-model="auditForm.value" :min="1" :max="99"></el-input-number>
  287. </el-form-item>
  288. </el-col>
  289. </el-row>
  290. <el-form-item label="审核备注" prop="auditOpinion">
  291. <el-input v-model="auditForm.auditOpinion" type="textarea"/>
  292. </el-form-item>
  293. </el-form>
  294. <div slot="footer" class="dialog-footer">
  295. <el-button type="primary" size="mini" @click="submitAudit">确 定</el-button>
  296. <el-button size="mini" @click="auditCancel">取 消</el-button>
  297. </div>
  298. </el-dialog>
  299. <!-- 分解任务对话框 -->
  300. <el-dialog :visible.sync="splitOpen" width="900px" class="add-dialog" append-to-body @close="splitCancel">
  301. <task-split ref="split" :split-form="splitForm" :user-list="userList"></task-split>
  302. <div slot="footer" class="dialog-footer">
  303. <el-button size="mini" @click="splitCancel">取 消</el-button>
  304. <el-button type="primary" size="mini" @click="submitSplit">确 定</el-button>
  305. </div>
  306. </el-dialog>
  307. <el-dialog title="该时间段内有人员安排冲突,是否继续保存?" :visible.sync="confirmOpen" append-to-body :close-on-click-modal="false">
  308. <el-table :data="conflictTasks" size="mini">
  309. <el-table-column label="任务名称" prop="taskName" min-width="150" :show-overflow-tooltip="true"/>
  310. <el-table-column label="执行(负责)人" prop="executorName"/>
  311. <el-table-column label="任务起止时间" width="170">
  312. <template slot-scope="scope">
  313. <span>{{ scope.row.beginDate + ' 至 ' + scope.row.endDate }}</span>
  314. </template>
  315. </el-table-column>
  316. </el-table>
  317. <div slot="footer" class="dialog-footer">
  318. <el-button type="primary" size="mini" @click="submitConfirm">确 定</el-button>
  319. <el-button size="mini" @click="cancelConfirm">取 消</el-button>
  320. </div>
  321. </el-dialog>
  322. </div>
  323. </template>
  324. <script>
  325. import {
  326. listTask,
  327. getTask,
  328. delTask,
  329. addTask,
  330. updateTask,
  331. auditTask,
  332. splitTask
  333. } from "@/api/task/task";
  334. import {listProject} from "@/api/task/project";
  335. import {getDeptUserTree} from "@/api/system/user";
  336. import Treeselect from "@riophae/vue-treeselect";
  337. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  338. import DeptUserTree from "@/components/DeptUserTree"
  339. import FileUpload from "@/components/FileUpload"
  340. import Project from "@/views/task/components/project";
  341. import TaskDetail from "@/views/task/components/taskDetail"
  342. import TaskSplit from "@/views/task/components/taskSplit"
  343. import RichTextEditor from '@/components/RichTextEditor'
  344. import {mapGetters} from "vuex";
  345. import task from "@/views/mixins/task";
  346. import DateUtil from "@/utils/date";
  347. export default {
  348. name: "Task",
  349. components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect, RichTextEditor, TaskSplit},
  350. dicts: ['task_status', 'task_priority'],
  351. mixins: [task],
  352. computed: {
  353. ...mapGetters(['userId'])
  354. },
  355. data() {
  356. return {
  357. projectOptions: [],
  358. selectProjectId: undefined,
  359. userList: [],
  360. // 总条数
  361. total: 0,
  362. // 项目表格数据
  363. taskList: [],
  364. // 弹出层标题
  365. title: "",
  366. // 是否显示弹出层
  367. open: false,
  368. // 查询参数
  369. queryParams: {
  370. pageNum: 1,
  371. pageSize: 20,
  372. executors: [],
  373. projectId: undefined,
  374. startDate: undefined,
  375. endDate: undefined,
  376. status: '0',
  377. priority: undefined,
  378. sortField: undefined,
  379. order: undefined
  380. },
  381. // 表单参数
  382. form: {},
  383. detailTitle: "",
  384. detailOpen: false,
  385. detailForm: {},
  386. auditOpen: false,
  387. auditForm: {},
  388. splitOpen: false,
  389. splitForm: {},
  390. // 表单校验
  391. rules: {
  392. taskName: [
  393. {required: true, message: "任务名称不能为空", trigger: "blur"}
  394. ],
  395. projectId: [
  396. {required: true, message: "所属项目不能为空", trigger: "blur"}
  397. ],
  398. beginDate: [
  399. {required: true, message: "开始时间不能为空", trigger: "change"}
  400. ],
  401. endDate: [
  402. {required: true, message: "结束时间不能为空", trigger: "change"}
  403. ],
  404. planHours: [
  405. {required: true, message: "计划工时不能为空", trigger: "blur"}
  406. ],
  407. executor: [
  408. {required: true, message: "执行人不能为空", trigger: 'change'}
  409. ]
  410. },
  411. auditRules: {
  412. auditResult: [
  413. {required: true, message: "审核意见不能为空", trigger: "change"}
  414. ],
  415. value: [
  416. {required: true, message: "进度不能为空", trigger: "blur"}
  417. ]
  418. },
  419. confirmOpen: false,
  420. conflictTasks: []
  421. };
  422. },
  423. created() {
  424. this.initData();
  425. },
  426. methods: {
  427. initData() {
  428. this.getList();
  429. getDeptUserTree('1').then(res => {
  430. this.userList = res.data
  431. })
  432. },
  433. /** 查询项目列表 */
  434. getList() {
  435. if (DateUtil.unix(this.queryParams.startDate) > DateUtil.unix(this.queryParams.endDate)) {
  436. this.$message.warning("开始时间不能超过结束时间")
  437. return
  438. }
  439. listTask(this.queryParams).then(res => {
  440. this.taskList = res.data.records;
  441. this.total = res.data.total;
  442. }
  443. );
  444. },
  445. selectProject(data) {
  446. this.selectProjectId = data
  447. this.queryParams.projectId = data;
  448. this.handleQuery()
  449. },
  450. /** 搜索按钮操作 */
  451. handleQuery() {
  452. this.queryParams.pageNum = 1;
  453. this.getList();
  454. },
  455. /** 重置按钮操作 */
  456. resetQuery() {
  457. this.resetForm("queryForm");
  458. this.$refs.taskList.clearSort();
  459. this.queryParams.sortField = undefined
  460. this.queryParams.order = undefined
  461. this.$refs.pjTree.clear()
  462. this.$refs.dut.clearText()
  463. this.handleQuery();
  464. },
  465. handleSizeChange(val) {
  466. this.queryParams.pageSize = val;
  467. this.getList();
  468. },
  469. handleCurrentChange(val) {
  470. this.queryParams.pageNum = val;
  471. this.getList();
  472. },
  473. // 取消按钮
  474. cancel() {
  475. this.$refs.dut2.clearText()
  476. // this.$refs.rtEditor.clear()
  477. this.$refs.fu.clear()
  478. this.reset()
  479. this.open = false;
  480. },
  481. reset() {
  482. this.form = {
  483. id: undefined,
  484. taskName: undefined,
  485. projectId: undefined,
  486. executor: undefined,
  487. planHours: undefined,
  488. beginDate: undefined,
  489. endDate: undefined,
  490. description: undefined
  491. };
  492. this.resetForm("form");
  493. },
  494. // 审核取消按钮
  495. auditCancel() {
  496. this.detailForm = {};
  497. this.auditForm = {
  498. taskId: undefined,
  499. auditResult: undefined,
  500. value: undefined,
  501. auditOpinion: undefined
  502. }
  503. this.resetForm("auditForm");
  504. this.auditOpen = false;
  505. },
  506. // 取消按钮(分解任务)
  507. async splitCancel() {
  508. await this.$refs.split.reset();
  509. // this.splitForm = {}
  510. this.splitOpen = false;
  511. },
  512. /** 查看任务详情*/
  513. cellClick(row, column, event) {
  514. if (!column.property || column.property != 'taskName') {
  515. return
  516. }
  517. getTask(row.id).then(res => {
  518. this.detailForm = res.data;
  519. this.detailOpen = true;
  520. this.detailTitle = "任务详情";
  521. })
  522. },
  523. sortChange({column, prop, order}) {
  524. this.queryParams.sortField = prop
  525. if (order) {
  526. this.queryParams.order = order.replace('ending', '')
  527. }
  528. this.getList()
  529. },
  530. /** 转换项目数据结构 */
  531. normalizer(node) {
  532. if (node.children && !node.children.length) {
  533. delete node.children;
  534. }
  535. let newVar = {
  536. id: node.id,
  537. label: node.projectName,
  538. children: node.children,
  539. isDisabled: node.type === '1'
  540. };
  541. return newVar;
  542. },
  543. /** 新增按钮操作 */
  544. handleAdd() {
  545. this.reset();
  546. this.open = true;
  547. this.title = "添加任务";
  548. listProject('1').then(response => {
  549. this.projectOptions = this.handleTree(response.data, "id");
  550. if (this.selectProjectId && this.projectOptions.length > 0) {
  551. let ids = this.projectOptions.map(item => item.id);
  552. if (ids.indexOf(this.selectProjectId) < 0) {
  553. this.form.projectId = this.selectProjectId
  554. }
  555. }
  556. this.$set(this.form, 'priority', '4')
  557. });
  558. },
  559. async handleEdit(row) {
  560. this.open = true;
  561. this.title = "修改任务";
  562. let arr = []
  563. arr.push(getTask(row.id).then(res => {
  564. this.form = res.data;
  565. this.form['files'] = this.form.files || []
  566. this.form.files = this.form.fileList
  567. if (this.form.fileList.length > 0) {
  568. this.form.files = this.form.fileList.map(item => {
  569. return {name: item.name, url: item.fileUrl}
  570. })
  571. }
  572. }
  573. ))
  574. arr.push(listProject().then(response => {
  575. this.projectOptions = this.handleTree(response.data, "id");
  576. }))
  577. await Promise.all(arr)
  578. this.$set(this.form, 'rangeDate', [row.beginDate, row.endDate])
  579. this.$refs.dut2.setCheckedNode(this.form.executor)
  580. },
  581. selectExecutor(val) {
  582. this.$set(this.form, 'executor', val)
  583. },
  584. getFileUrl(val) {
  585. this.form.files = val
  586. },
  587. removeFile(val) {
  588. this.form.files = val
  589. },
  590. /** 更多操作触发 */
  591. handleCommand(command, row) {
  592. switch (command) {
  593. case 'handleSplit':
  594. this.handleSplit(row)
  595. break
  596. case 'handleUpdate':
  597. this.handleUpdate(row)
  598. break
  599. case 'handleEdit':
  600. this.handleEdit(row)
  601. break
  602. case 'handleDelete':
  603. this.handleDelete(row)
  604. break
  605. default:
  606. break
  607. }
  608. },
  609. /** 审核按钮操作 */
  610. handleAudit(row) {
  611. getTask(row.id).then(res => {
  612. this.detailForm = res.data;
  613. this.auditForm = {
  614. taskId: row.id,
  615. auditResult: undefined,
  616. value: undefined,
  617. auditOpinion: undefined
  618. }
  619. this.auditOpen = true;
  620. })
  621. },
  622. /** 分解按钮操作 */
  623. handleSplit(row) {
  624. if (row.status === '4' || row.status === '5') {
  625. this.$message.info("任务已完成/终止,请勿再分解")
  626. return
  627. }
  628. getTask(row.id).then(res => {
  629. this.splitForm = res.data
  630. this.splitForm['parentId'] = row.id
  631. this.splitForm['children'] = []
  632. let child = {
  633. taskName: undefined,
  634. executor: undefined,
  635. beginDate: row.beginDate,
  636. endDate: row.endDate,
  637. planHours: undefined,
  638. description: undefined
  639. }
  640. this.splitForm.children.push(child)
  641. this.splitOpen = true
  642. })
  643. },
  644. /** 提交按钮 */
  645. submitForm() {
  646. if (this.projectOptions.length > 0) {
  647. let ids = this.projectOptions.map(item => item.id);
  648. if (ids.indexOf(this.form.projectId) > -1) {
  649. this.$message.warning("所属项目不可选择分类")
  650. return
  651. }
  652. }
  653. if (DateUtil.unix(this.form.beginDate) > DateUtil.unix(this.form.endDate)) {
  654. this.$message.warning("开始时间不能超过结束时间")
  655. return
  656. }
  657. this.$refs["form"].validate(valid => {
  658. if (valid) {
  659. if (this.form.files && this.form.files.length > 0) {
  660. let tempFiles = this.form.files.map(item => item.name);
  661. this.form.fileUrl = JSON.stringify(tempFiles)
  662. }
  663. this.form.checkTaskConflict = true;
  664. if (!this.form.id) {
  665. addTask(this.form).then(res => {
  666. if (res.code === 'S.F-2001') {
  667. this.conflictTasks = res.data
  668. this.confirmOpen = true
  669. } else {
  670. this.$message.success("新增成功");
  671. this.open = false;
  672. this.reset();
  673. this.getList();
  674. }
  675. });
  676. } else {
  677. updateTask(this.form).then(res => {
  678. this.$message.success("操作成功");
  679. this.open = false;
  680. this.reset();
  681. this.getList();
  682. })
  683. }
  684. }
  685. });
  686. },
  687. submitConfirm() {
  688. if (this.open) {
  689. this.form.checkTaskConflict = false;
  690. addTask(this.form).then(res => {
  691. this.$message.success("新增成功");
  692. this.open = false;
  693. this.confirmOpen = false;
  694. this.reset();
  695. this.getList();
  696. });
  697. }
  698. if (this.splitOpen) {
  699. this.splitForm.checkTaskConflict = false;
  700. splitTask(this.splitForm).then(res => {
  701. this.resetForm("splitForm");
  702. this.getList()
  703. this.splitOpen = false
  704. this.confirmOpen = false;
  705. this.$message.success("操作成功");
  706. })
  707. }
  708. },
  709. cancelConfirm() {
  710. this.confirmOpen = false;
  711. // this.open = false;
  712. // this.splitOpen = false;
  713. // this.$refs.dut2.clearText()
  714. // let dutSplit = this.$refs.dutSplit || [];
  715. // for (let key in dutSplit) {
  716. // dutSplit[key].clearText()
  717. // }
  718. // this.resetForm("splitForm");
  719. },
  720. /** 审核任务提交按钮 */
  721. submitAudit() {
  722. this.$refs["auditForm"].validate(valid => {
  723. if (valid) {
  724. auditTask(this.auditForm).then(res => {
  725. this.$message.success("操作成功");
  726. this.getList()
  727. this.auditCancel()
  728. })
  729. }
  730. });
  731. },
  732. /** 分解任务提交按钮 */
  733. submitSplit() {
  734. let data = this.$refs.split.submit();
  735. if (!data) {
  736. return
  737. }
  738. this.splitForm = data;
  739. this.$set(this.splitForm, 'checkTaskConflict', true)
  740. splitTask(this.splitForm).then(res => {
  741. if (res.code === 'S.F-2001') {
  742. this.conflictTasks = res.data
  743. this.confirmOpen = true
  744. } else {
  745. this.resetForm("splitForm");
  746. this.getList()
  747. this.splitOpen = false
  748. this.$message.success("操作成功");
  749. }
  750. })
  751. },
  752. /** 终止按钮操作 */
  753. handleUpdate(row) {
  754. this.$confirm('是否确认终止任务编号为"' + row.id + '"的任务?').then(() => {
  755. return updateTask({id: row.id, status: '5'});
  756. }).then(() => {
  757. this.getList();
  758. this.$message.success("终止成功");
  759. }).catch(() => {
  760. });
  761. },
  762. /** 删除按钮操作 */
  763. handleDelete(row) {
  764. this.$confirm('是否确认删除任务编号为"' + row.id + '"的数据项?').then(() => {
  765. return delTask(row.id);
  766. }).then(() => {
  767. this.getList();
  768. this.$message.success("删除成功");
  769. }).catch(() => {
  770. });
  771. }
  772. }
  773. };
  774. </script>
  775. <style scoped lang="scss">
  776. .split-form {
  777. ::v-deep .el-form-item__label {
  778. font-size: 13px;
  779. }
  780. ::v-deep.el-form-item {
  781. margin-bottom: 8px;
  782. }
  783. ::v-deep.el-card__header {
  784. padding: 5px 10px;
  785. }
  786. ::v-deep.el-card__body {
  787. padding: 5px;
  788. }
  789. }
  790. .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
  791. margin-bottom: 10px;
  792. }
  793. .mini-treeselect {
  794. ::v-deep.vue-treeselect__control {
  795. height: 28px;
  796. }
  797. ::v-deep.vue-treeselect__placeholder, .vue-treeselect__single-value {
  798. padding-left: 10px;
  799. line-height: 28px;
  800. }
  801. }
  802. .card-header {
  803. display: flex;
  804. justify-content: space-between
  805. }
  806. .add-dialog ::v-deep .el-dialog__body {
  807. padding: 0 20px 10px 20px;
  808. }
  809. .split-card {
  810. width: 49%;
  811. padding: 5px 10px;
  812. margin: 5px;
  813. }
  814. .el-tag--dark {
  815. border-color: white;
  816. }
  817. </style>