task.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <template>
  2. <el-dialog v-model="showDialog" width="800" @close="close">
  3. <template #header>
  4. <div class="full-width flex flex-center flex-justify-between">
  5. <h4>任务详情</h4>
  6. </div>
  7. </template>
  8. <div>
  9. <el-input
  10. v-model="form.title"
  11. maxlength="20"
  12. clearable
  13. :disabled="!canEdit"
  14. style="height: 50px"
  15. class="font-16 bold"
  16. placeholder="请输入任务名称(最大20个字符)"
  17. ></el-input>
  18. <div
  19. class="full-width flex flex-justify-between flex-center padding-top mt-10"
  20. @click="goProject"
  21. v-if="task && task.projectId"
  22. >
  23. <span class="flex-center flex-justify-start title"
  24. >所属项目:{{ task.projectName }}</span
  25. >
  26. <el-icon>
  27. <ArrowRight />
  28. </el-icon>
  29. </div>
  30. <div class="mt-20">
  31. <div class="flex flex-center flex-justify-start">
  32. <span class="mr-10 title flex flex-justify-start">状态:</span>
  33. <wt-tag
  34. :data="status"
  35. :status="form.taskStatus"
  36. @change="changeStatus($event, 1)"
  37. :disabled="isFinish"
  38. />
  39. </div>
  40. <div class="mt-20 flex flex-center flex-justify-start">
  41. <span class="mr-10 title flex flex-justify-start">优先级:</span>
  42. <wt-tag
  43. :data="level"
  44. :disabled="!canEdit"
  45. :status="form.level"
  46. @change="changeStatus($event, 2)"
  47. />
  48. </div>
  49. <div class="mt-20 flex flex-center flex-justify-start">
  50. <span class="mr-10 title flex flex-justify-start">时间:</span>
  51. <div class="flex flex-center">
  52. <el-date-picker
  53. v-model="form.startTime"
  54. type="date"
  55. :disabled="!canEdit"
  56. placeholder="设置开始日期"
  57. format="YYYY-MM-DD"
  58. value-format="YYYY-MM-DD"
  59. >
  60. </el-date-picker>
  61. <div class="ml-5 mr-5">至</div>
  62. <el-date-picker
  63. v-model="form.endTime"
  64. type="date"
  65. :disabled="!canEdit"
  66. placeholder="设置截止日期"
  67. format="YYYY-MM-DD"
  68. value-format="YYYY-MM-DD"
  69. >
  70. </el-date-picker>
  71. </div>
  72. </div>
  73. <div class="mt-20 flex lex-align-start flex-justify-start">
  74. <span class="mr-10 title flex flex-justify-start">标签:</span>
  75. <div>
  76. <wt-label
  77. @submit="handleTags"
  78. :ids="form.tags.split(',')"
  79. :disabled="!canEdit"
  80. />
  81. </div>
  82. </div>
  83. <div class="mt-20 flex lex-align-start flex-justify-start">
  84. <span class="mr-10 title flex flex-justify-start">执行者:</span>
  85. <div>
  86. <tasker
  87. :data="executeUser === null ? [] : executeUser"
  88. :disabled="!canEdit"
  89. @success="selected"
  90. />
  91. </div>
  92. </div>
  93. <div class="mt-20 flex flex-align-start flex-justify-start">
  94. <span class="mr-10 title flex flex-justify-start">备注:</span>
  95. <el-input
  96. type="textarea"
  97. :rows="5"
  98. v-model="form.remark"
  99. :disabled="!canEdit"
  100. ></el-input>
  101. </div>
  102. <div class="mt-20 flex flex-align-start flex-justify-start flex-col">
  103. <div class="flex flex-center flex-justify-start">
  104. <span class="mr-10 title flex flex-justify-start">关联附件:</span>
  105. <filepicker
  106. :project-id="projectId"
  107. @submit="selection"
  108. v-if="canEdit"
  109. />
  110. </div>
  111. <div class="flex flex-center flex-justify-start full-width mt-10">
  112. <div class="title mr-10"></div>
  113. <div>
  114. <div v-for="item in fileList" :key="item.id">
  115. <div class="flex flex-center">
  116. {{ item.title }}
  117. <preview :id="item.fileId" :show-action="true" />
  118. </div>
  119. </div>
  120. </div>
  121. </div>
  122. </div>
  123. <div class="flex flex-justify-start full-width flex-col">
  124. <div class="mt-10 flex flex-align-start flex-justify-start">
  125. <span class="mr-10 title flex flex-justify-start">任务进展:</span>
  126. <el-input
  127. type="textarea"
  128. :rows="5"
  129. v-model="form.taskProcess"
  130. :disabled="isFinish"
  131. ></el-input>
  132. </div>
  133. <div class="flex flex-justify-start mt-10 full-width">
  134. <div class="title mr-10">成果文件:</div>
  135. <upload-office
  136. @success="uploadResult"
  137. :max="1"
  138. v-if="isFinish === false"
  139. />
  140. </div>
  141. <div class="full-width flex flex-justify-start flex-center">
  142. <div class="title mr-10" />
  143. <div v-for="item in resultFiles" :key="item.id">
  144. <div class="flex flex-justify-start flex-center">
  145. {{ item.fileVO.originalFileName }}
  146. ({{ item.createUserName }})
  147. <preview :id="item.fileVO.id" :show-action="true"></preview>
  148. </div>
  149. </div>
  150. </div>
  151. </div>
  152. </div>
  153. <div class="flex flex-justify-end full-width">
  154. <el-button type="primary" plain @click="showDialog = false"
  155. >取 消
  156. </el-button>
  157. <el-button type="primary" @click="submit">确 定</el-button>
  158. </div>
  159. <move
  160. ref="move"
  161. :file-id="resultFiles.map(ele => ele.fileId).join(',')"
  162. :project-id="form.projectId"
  163. @on-success="moveSucc"
  164. />
  165. </div>
  166. </el-dialog>
  167. </template>
  168. <script>
  169. import WtTag from '@/views/task/component/wt-tag.vue'
  170. import Tasker from '@/views/task/component/tasker.vue'
  171. import filepicker from '@/components/filepicker/index.vue'
  172. import WtLabel from '@/views/task/component/wt-label.vue'
  173. import { useStore } from '@/store/user.js'
  174. import Preview from '@/views/resource/component/preview.vue'
  175. import api from '@/api/index.js'
  176. import uploadOffice from '@/components/upload-office/index.vue'
  177. import move from '@/views/task/component/move.vue'
  178. export default {
  179. /**
  180. * 任务添加、查看
  181. */
  182. computed: {
  183. api() {
  184. return api
  185. }
  186. },
  187. components: {
  188. Preview,
  189. WtLabel,
  190. Tasker,
  191. WtTag,
  192. filepicker,
  193. uploadOffice,
  194. move
  195. },
  196. props: {
  197. projectId: {
  198. type: String,
  199. default: ''
  200. },
  201. task: {
  202. type: Object,
  203. default: () => {
  204. return null
  205. }
  206. }
  207. },
  208. setup() {
  209. const user = useStore()
  210. return { user }
  211. },
  212. data() {
  213. return {
  214. isFinish: false,
  215. showDialog: false,
  216. fileList: [],
  217. loading: false,
  218. canEdit: true,
  219. executeUser: [],
  220. resultFiles: [],
  221. editResult: false,
  222. isMove: false,
  223. form: {
  224. title: '',
  225. taskStatus: -1,
  226. level: -1,
  227. remark: '',
  228. startTime: '',
  229. endTime: '',
  230. executeUser: '',
  231. tags: '',
  232. taskProcess: ''
  233. },
  234. status: [
  235. {
  236. title: '待确认',
  237. value: 1,
  238. color: '#D7D7D7',
  239. checked: true
  240. },
  241. {
  242. title: '进行中',
  243. value: 2,
  244. color: '#47A6EA',
  245. checked: false
  246. },
  247. {
  248. title: '已提交',
  249. value: 3,
  250. color: '#ECAB56',
  251. checked: false
  252. },
  253. {
  254. title: '已完成',
  255. value: 4,
  256. color: '#80B336',
  257. checked: false
  258. },
  259. {
  260. title: '已取消',
  261. value: 5,
  262. color: '#C72A29',
  263. checked: false
  264. }
  265. ],
  266. level: [
  267. {
  268. title: 'P1',
  269. value: 1,
  270. color: '#C72A29',
  271. checked: true
  272. },
  273. {
  274. title: 'P2',
  275. value: 2,
  276. color: '#E89D42',
  277. checked: false
  278. },
  279. {
  280. title: 'P3',
  281. value: 3,
  282. color: '#47A6EA',
  283. checked: false
  284. },
  285. {
  286. title: 'P4',
  287. value: 4,
  288. color: '#A0A0A0',
  289. checked: false
  290. }
  291. ]
  292. }
  293. },
  294. methods: {
  295. init() {
  296. this.form = this.task
  297. if (this.task.users !== undefined) {
  298. this.executeUser = [...this.task.users]
  299. }
  300. this.canEdit = this.form.createUser === this.user.info.userId
  301. if (this.task.taskStatus > 2) {
  302. this.canEdit = false
  303. }
  304. if (this.task.files !== undefined && this.task.files.length > 0) {
  305. this.fileList = this.task.files
  306. }
  307. this.resultFileInfo()
  308. },
  309. fetchIndex(list, key) {
  310. const index = list.findIndex(ele => ele.value === key)
  311. if (index > -1) {
  312. list.map(ele => {
  313. ele.checked = false
  314. return ele
  315. })
  316. list[index].checked = true
  317. }
  318. return list
  319. },
  320. /**
  321. *
  322. * @param type = 1 新增 2 查看
  323. */
  324. show(type) {
  325. if (type !== 1) {
  326. this.form = this.task
  327. if (this.task.taskStatus === 4 || this.task.taskStatus === 5) {
  328. this.isFinish = true
  329. }
  330. this.init(this.task)
  331. } else {
  332. this.form.taskStatus = 1
  333. this.form.level = 1
  334. this.canEdit = true
  335. }
  336. this.showDialog = true
  337. },
  338. /**
  339. * 获取成果文件info
  340. */
  341. resultFileInfo() {
  342. if (this.task.id !== undefined) {
  343. this.$api.task.taskFileInfo({ id: this.task.id }).then(res => {
  344. if (res.code === 200) {
  345. this.resultFiles = res.data
  346. }
  347. })
  348. }
  349. },
  350. changeStatus(res, type) {
  351. if (type === 1) {
  352. this.form.taskStatus = res.value
  353. } else {
  354. this.form.level = res.value
  355. }
  356. },
  357. submit() {
  358. if (this.form.taskStatus === 3 && this.resultFiles.length === 0) {
  359. this.$message.error('请上传成果文件')
  360. return
  361. } else {
  362. this.saveResultFile()
  363. }
  364. if (
  365. this.form.taskStatus === 4 &&
  366. this.isMove === false &&
  367. this.isFinish === false
  368. ) {
  369. // 已完成 需要转移文件
  370. this.$refs.move.showDialog()
  371. return
  372. }
  373. if (this.isFinish) {
  374. this.showDialog = false
  375. return
  376. }
  377. // 从项目详情,添加任务
  378. if (this.projectId !== undefined && this.projectId.length > 0) {
  379. this.form.projectId = this.projectId
  380. }
  381. this.form.relatedIds = this.fileList.map(ele => ele.id).join(',')
  382. this.$api.task.addTask(this.form).then(res => {
  383. this.showDialog = false
  384. if (res.code === 200) {
  385. this.$message.success(res.msg)
  386. } else {
  387. this.$message.error(res.msg)
  388. }
  389. this.$emit('success')
  390. })
  391. },
  392. saveResultFile() {
  393. if (this.editResult === false) {
  394. return
  395. }
  396. this.$api.task
  397. .taskFile({
  398. taskId: this.form.id,
  399. ids: this.resultFiles.map(ele => ele.id).join(',')
  400. })
  401. .then(res => {
  402. if (res.code === 200) {
  403. console.log(res)
  404. }
  405. })
  406. },
  407. selection(list, extra) {
  408. this.fileList = list.map(ele => {
  409. return ele
  410. })
  411. },
  412. selected(list) {
  413. this.form.executeUser = list.map(ele => ele.id).join(',')
  414. },
  415. handleTags(tags) {
  416. this.form.tags = tags
  417. },
  418. /**
  419. * 成果文件上传成果
  420. * @param list
  421. */
  422. uploadResult(list) {
  423. this.editResult = true
  424. this.resultFiles = list.map(ele => {
  425. return {
  426. id: ele.id,
  427. fileVO: ele,
  428. createUserName: this.user.info.nickName
  429. }
  430. })
  431. },
  432. close() {
  433. this.form = {
  434. title: '',
  435. taskStatus: -1,
  436. level: -1,
  437. remark: '',
  438. startTime: '',
  439. endTime: '',
  440. executeUser: '',
  441. tags: '',
  442. taskProcess: ''
  443. }
  444. this.resultFiles.length = 0
  445. this.executeUser.length = 0
  446. this.fileList.length = 0
  447. this.showDialog = false
  448. this.editResult = false
  449. this.isMove = false
  450. this.isFinish = false
  451. },
  452. /**
  453. * 文件移动成功
  454. */
  455. moveSucc() {
  456. this.isMove = true
  457. },
  458. goProject() {
  459. const routeData = this.$router.resolve({
  460. path: '/home/pro_detail',
  461. query: { id: this.task.projectId }
  462. })
  463. window.open(routeData.href, '_blank')
  464. }
  465. }
  466. }
  467. </script>
  468. <style lang="scss" scoped>
  469. .title {
  470. min-width: 60px;
  471. }
  472. :deep(.el-input__wrapper) {
  473. box-shadow: none;
  474. font-weight: bold;
  475. font-size: 16px;
  476. background-color: #eeeeee;
  477. }
  478. :deep(.el-input__wrapper:hover) {
  479. box-shadow: none;
  480. background-color: #eeeeee;
  481. }
  482. </style>