task.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  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 :info="item" :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">
  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 :info="item.fileVO" :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: 0,
  238. color: '#D7D7D7',
  239. checked: true
  240. },
  241. {
  242. title: '进行中',
  243. value: 1,
  244. color: '#47A6EA',
  245. checked: false
  246. },
  247. {
  248. title: '已提交',
  249. value: 2,
  250. color: '#ECAB56',
  251. checked: false
  252. },
  253. {
  254. title: '已完成',
  255. value: 3,
  256. color: '#80B336',
  257. checked: false
  258. },
  259. {
  260. title: '已取消',
  261. value: 4,
  262. color: '#C72A29',
  263. checked: false
  264. }
  265. ],
  266. level: [
  267. {
  268. title: 'P1',
  269. value: 0,
  270. color: '#C72A29',
  271. checked: true
  272. },
  273. {
  274. title: 'P2',
  275. value: 1,
  276. color: '#E89D42',
  277. checked: false
  278. },
  279. {
  280. title: 'P3',
  281. value: 2,
  282. color: '#47A6EA',
  283. checked: false
  284. },
  285. {
  286. title: 'P4',
  287. value: 3,
  288. color: '#A0A0A0',
  289. checked: false
  290. }
  291. ]
  292. }
  293. },
  294. methods: {
  295. init() {
  296. this.form = this.task
  297. console.log(this.task)
  298. if (this.task.users !== undefined) {
  299. this.executeUser = [...this.task.users]
  300. }
  301. this.canEdit = this.form.createUser === this.user.info.userId
  302. if (this.task.taskStatus > 1) {
  303. this.canEdit = false
  304. }
  305. if (this.task.files !== undefined && this.task.files.length > 0) {
  306. this.fileList = this.task.files
  307. console.log(this.fileList)
  308. }
  309. this.resultFileInfo()
  310. },
  311. fetchIndex(list, key) {
  312. const index = list.findIndex(ele => ele.value === key)
  313. if (index > -1) {
  314. list.map(ele => {
  315. ele.checked = false
  316. return ele
  317. })
  318. list[index].checked = true
  319. }
  320. return list
  321. },
  322. /**
  323. *
  324. * @param type = 1 新增 2 查看
  325. */
  326. show(type) {
  327. if (type !== 1) {
  328. this.form = this.task
  329. if (this.task.taskStatus === 3 || this.task.taskStatus === 4) {
  330. this.isFinish = true
  331. }
  332. this.init(this.task)
  333. } else {
  334. this.form.taskStatus = 0
  335. this.form.level = 0
  336. this.canEdit = true
  337. }
  338. this.showDialog = true
  339. },
  340. /**
  341. * 获取成果文件info
  342. */
  343. resultFileInfo() {
  344. if (this.task.id !== undefined) {
  345. this.$api.task.taskFileInfo({ id: this.task.id }).then(res => {
  346. if (res.code === 200) {
  347. this.resultFiles = res.data
  348. }
  349. })
  350. }
  351. },
  352. changeStatus(res, type) {
  353. if (type === 1) {
  354. this.form.taskStatus = res.value
  355. } else {
  356. this.form.level = res.value
  357. }
  358. },
  359. submit() {
  360. if (this.form.taskStatus === 2 && this.resultFiles.length === 0) {
  361. this.$message.error('请上传成果文件')
  362. return
  363. } else {
  364. this.saveResultFile()
  365. }
  366. if (
  367. this.form.taskStatus === 3 &&
  368. this.isMove === false &&
  369. this.isFinish === false
  370. ) {
  371. // 已完成 需要转移文件
  372. this.$refs.move.showDialog()
  373. return
  374. }
  375. if (this.isFinish) {
  376. this.showDialog = false
  377. return
  378. }
  379. // 从项目详情,添加任务
  380. if (this.projectId !== undefined && this.projectId.length > 0) {
  381. this.form.projectId = this.projectId
  382. }
  383. this.form.relatedIds = this.fileList.map(ele => ele.id).join(',')
  384. this.$api.task.addTask(this.form).then(res => {
  385. this.showDialog = false
  386. if (res.code === 200) {
  387. this.$message.success(res.msg)
  388. } else {
  389. this.$message.error(res.msg)
  390. }
  391. this.$emit('success')
  392. })
  393. },
  394. saveResultFile() {
  395. if (this.editResult === false) {
  396. return
  397. }
  398. this.$api.task
  399. .taskFile({
  400. taskId: this.form.id,
  401. ids: this.resultFiles.map(ele => ele.id).join(',')
  402. })
  403. .then(res => {
  404. if (res.code === 200) {
  405. console.log(res)
  406. }
  407. })
  408. },
  409. selection(list, extra) {
  410. this.fileList = list.map(ele => {
  411. return ele
  412. })
  413. },
  414. selected(list) {
  415. this.form.executeUser = list.map(ele => ele.id).join(',')
  416. },
  417. handleTags(tags) {
  418. this.form.tags = tags
  419. },
  420. /**
  421. * 成果文件上传成果
  422. * @param list
  423. */
  424. uploadResult(list) {
  425. this.editResult = true
  426. this.resultFiles = list.map(ele => {
  427. return {
  428. id: ele.id,
  429. fileVO: ele,
  430. createUserName: this.user.info.nickName
  431. }
  432. })
  433. },
  434. close() {
  435. this.form = {
  436. title: '',
  437. taskStatus: -1,
  438. level: -1,
  439. remark: '',
  440. startTime: '',
  441. endTime: '',
  442. executeUser: '',
  443. tags: '',
  444. taskProcess: ''
  445. }
  446. this.resultFiles.length = 0
  447. this.executeUser.length = 0
  448. this.fileList.length = 0
  449. this.showDialog = false
  450. this.editResult = false
  451. this.isMove = false
  452. this.isFinish = false
  453. },
  454. /**
  455. * 文件移动成功
  456. */
  457. moveSucc() {
  458. this.isMove = true
  459. },
  460. goProject() {
  461. const routeData = this.$router.resolve({
  462. path: '/home/pro_detail',
  463. query: { id: this.task.projectId }
  464. })
  465. window.open(routeData.href, '_blank')
  466. }
  467. }
  468. }
  469. </script>
  470. <style lang="scss" scoped>
  471. .title {
  472. min-width: 60px;
  473. }
  474. :deep(.el-input__wrapper) {
  475. box-shadow: none;
  476. font-weight: bold;
  477. font-size: 16px;
  478. background-color: #eeeeee;
  479. }
  480. :deep(.el-input__wrapper:hover) {
  481. box-shadow: none;
  482. background-color: #eeeeee;
  483. }
  484. </style>