taskViewDetail.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. <template>
  2. <div class="bg-project" @click="display = false">
  3. <el-container>
  4. <el-header class="main-header">
  5. <div class="top-page-title">
  6. <div v-if="form_query.stage === 1 || form_query.stage === 2 || form_query.stage === 3" class="task-stage">
  7. <div class="task-stage-main">
  8. <img v-if="form_query.stage === 1" :src="normalImg">
  9. <img v-if="form_query.stage === 2" :src="stageImg">
  10. <img v-if="form_query.stage === 3" :src="warningImg">
  11. <el-tooltip class="item" effect="dark" :disabled="form_query.lateMsg===null" :content="form_query.stageString + ':' + form_query.lateMsg" placement="bottom">
  12. <div class="task-stage-title">
  13. {{ form_query.stageString }}
  14. </div>
  15. </el-tooltip>
  16. </div>
  17. </div>
  18. <div class="header-title">
  19. <span class="title-id">TASK-{{ form_query.id }}</span>
  20. <el-tooltip class="item" effect="dark" :content="form_query.name" placement="bottom">
  21. <span class="title-name">{{ form_query.name }}</span>
  22. </el-tooltip>
  23. </div>
  24. <el-dropdown placement="bottom" @command="updateStatus">
  25. <el-button size="mini" plainclass="el-dropdown-link drop_down">
  26. {{ getStatus.msg }}
  27. <i class="el-icon-arrow-down el-icon--right" />
  28. </el-button>
  29. <el-dropdown-menu slot="dropdown" align="center">
  30. <el-dropdown-item
  31. v-for="item in allStatus"
  32. :key="item.msg"
  33. :command="{status:item.code,label:item.msg}"
  34. :disabled="form_query.status === item.code? true: false"
  35. >{{ item.msg }}</el-dropdown-item>
  36. </el-dropdown-menu>
  37. </el-dropdown>
  38. </div>
  39. <div class="top-tabs">
  40. <el-tabs v-model="activeName">
  41. <el-tab-pane label="概览" name="1" />
  42. <el-tab-pane label="缺陷" name="2" />
  43. <el-tab-pane label="报告" name="3" />
  44. <el-tab-pane label="统计" name="4" />
  45. </el-tabs>
  46. </div>
  47. <div class="top-control">
  48. <el-dropdown placement="bottom">
  49. <i class="el-icon-circle-plus icon-add" />
  50. <el-dropdown-menu slot="dropdown">
  51. <el-dropdown-item @click.native="created_bug()">新建缺陷</el-dropdown-item>
  52. <el-dropdown-item @click.native="createReport(1, form_query)">新建提测报告</el-dropdown-item>
  53. <el-dropdown-item @click.native="createReport(2, form_query)">新建测试日报</el-dropdown-item>
  54. <el-dropdown-item @click.native="createReport(3, form_query)">新建准出报告</el-dropdown-item>
  55. </el-dropdown-menu>
  56. </el-dropdown>
  57. <div class="line" />
  58. <span style="vertical-align: bottom; cursor: pointer; color: #6F7C93;" @click.stop="setChild(), display = true"><img style="width: 20px; display: inline-block;" :src="image_url">&nbsp; {{ num }} &nbsp;</span>
  59. <div class="line" />
  60. <i class="el-icon-setting icon-delete" @click="open_created" />
  61. <div class="line" />
  62. <i class="el-icon-delete icon-delete" @click="deleteVisible = true" />
  63. </div>
  64. </el-header>
  65. <!-- 概览 -->
  66. <el-container v-if="activeName === '1'" class="is-vertical">
  67. <section class="main-section">
  68. <div class="el-main-title">
  69. <div class="title-left-icon" />
  70. <div class="title-left-name">基础信息</div>
  71. </div>
  72. <div class="detail-info">
  73. <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
  74. <el-form-item label="所属项目:" class="module">
  75. <div v-if="form_query.projectId !== -1" @click="jump('项目详情',form_query.projectId)">{{ form_query.projectName }}</div>
  76. <template v-else>{{ form_query.projectName }}</template>
  77. </el-form-item>
  78. <el-form-item label="所属需求:" class="module">
  79. <div v-if="form_query.requireId !== -1" @click="jump('需求详情',form_query.requireId)">{{ form_query.requireName }}</div>
  80. <template v-else>{{ form_query.requireName }}</template>
  81. </el-form-item>
  82. <el-form-item label="所属模块:" class="module">
  83. <div>{{ form_query.moduleInfoName }}</div>
  84. </el-form-item>
  85. </el-form>
  86. <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
  87. <el-form-item label="开发负责人:">
  88. <search-people :value.sync="form_query.rdOwner" @change="changeArea" />
  89. </el-form-item>
  90. <el-form-item label="测试负责人:">
  91. <search-people :value.sync="form_query.qaOwner" @change="changeArea" />
  92. </el-form-item>
  93. <el-form-item label="是否跟版:">
  94. <el-select v-model="form_query.followVersion" size="small" filterable placeholder="请选择" @change="changeArea">
  95. <el-option v-for="(item,index) in dependList" :key="item.msg + index" :label="item.msg" :value="item.code" />
  96. </el-select>
  97. </el-form-item>
  98. </el-form>
  99. <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
  100. <el-form-item label="跟版客户端:">
  101. <el-select v-if="form_query.followVersion === 1" v-model="form_query.involveApp" size="small" filterable placeholder="请选择" @change="changeArea">
  102. <el-option v-for="(item,index) in appClient" :key="item.msg + index" :label="item.msg" :value="item.code" />
  103. </el-select>
  104. </el-form-item>
  105. <el-form-item label="任务进度:">
  106. <div class="form-progress">
  107. <el-progress :percentage="Number(form_query.rate && form_query.rate.substring(0,4)) || 0" color="#409eff" />
  108. </div>
  109. </el-form-item>
  110. </el-form>
  111. <el-form :inline="true" :model="form_query" class="demo-form-inline" style="white-space: nowrap;" label-position="right" label-width="100px">
  112. <el-form-item label="技术文档:">
  113. <span class="PRD-link"><a :href="form_query.devUrl" target="_blank">{{ form_query.devUrl }}</a></span>
  114. </el-form-item>
  115. </el-form>
  116. </div>
  117. </section>
  118. <section class="main-section">
  119. <div class="el-main-title">
  120. <div class="title-left-icon" />
  121. <div class="title-left-name">
  122. <div>任务计划
  123. <el-tooltip class="item" effect="dark" :content="isScheduleLocked === 1? '点击解锁排期' : '点击锁定排期'" placement="top">
  124. <span class="titleStatus" :class="isScheduleLocked === 1 ? 'el-icon-lock' : 'el-icon-unlock'" @click="changeSchedule"> {{ isScheduleLocked === 1 ? '已锁定' : '未锁定' }}</span>
  125. </el-tooltip>
  126. </div>
  127. </div>
  128. </div>
  129. <section class="main-section">
  130. <div class="allTips">
  131. <div class="tips">
  132. <i class="el-icon-warning-outline" /> 每个任务仅支持一次提测和一次准出,请合理拆解后任务再排期<br>
  133. <i v-if="tips" class="el-icon-warning-outline" style="color:#e88792;" />
  134. <span v-if="tips" style="color:#e88792;">当前任务归属的需求计划排期呈锁定状态,当前任务的排期无法同步到需求计划中去,请将归属需求的排期解锁!</span>
  135. </div>
  136. <div class="Layout_space_between">
  137. <div v-show="BackToTheLatest === false" class="Scheduling" style="margin-right: 20px;" @click="clickBackToTheLatest"><i class="el-icon-refresh" /> 回到最新</div>
  138. <div v-show="isScheduleLocked === 0">
  139. <div v-show="BackToTheLatest === true" class="Scheduling" style="margin-right: 20px;" @click="clickAddScheduling()"><i class="el-icon-circle-plus-outline" /> 添加排期</div>
  140. </div>
  141. <div v-show="BackToTheLatest === true" align="left" class="Scheduling" @click="scheduleHiHide"><div class="el-icon-document" /> 排期变更记录</div>
  142. <download :id="taskId" :name="'任务'" />
  143. </div>
  144. </div>
  145. </section>
  146. <el-container>
  147. <el-main style="padding: 0;">
  148. <schedule-list :id="taskId" ref="taskSchedule" :showunlock="showunlock" :type-list="taskScheduleEvent" class-name="white" @updataData="getSchedule" />
  149. </el-main>
  150. <el-aside v-if="lockHide" class="SchedulingAside">
  151. <div v-for="(item, index) in SchedulingContent" :key="index" class="SchedulingDiv" @click="clickScheduling(item)">
  152. <i v-show="index < SchedulingContent.length - 1" />
  153. <div class="timeline">
  154. <div class="SchedulingTow" :class="{'vss' : item.id === ScheduId}">
  155. <div v-if="item.operationType === 0" class="el-icon-unlock image" />
  156. <div v-if="item.operationType === 1" class="el-icon-lock image" />
  157. </div>
  158. <div class="modifyTime">{{ item.modifyTime }}</div>
  159. <div>{{ item.operatorObject.name !== null ? item.operatorObject.name : '' }} <span class="btn">{{ item.operation }}</span></div>
  160. <div v-if="item.remarkTypeName"><span class="modifyTime">{{ '解锁原因 : ' }}</span>{{ item.remarkTypeName }}</div>
  161. <div v-if="item.remark"><span class="modifyTime">{{ '具体描述 : ' }}</span>{{ item.remark }}</div>
  162. </div>
  163. </div>
  164. <div v-if="SchedulingContent.length === 0" style="width: 270px; margin: 50% 20px; text-align: center;"> 暂无排期变更记录!</div>
  165. </el-aside>
  166. </el-container>
  167. </section>
  168. <section class="main-section">
  169. <div class="el-main-title">
  170. <div class="title-left-icon" />
  171. <div class="title-left-name">任务描述</div>
  172. </div>
  173. <div>
  174. <text-area :id="'pro-desc'" :value.sync="form_query.description" :empty-text="'点击'" :input-button="'添加描述'" @change="changeArea" />
  175. </div>
  176. </section>
  177. <section class="main-section">
  178. <div class="el-main-title">
  179. <div class="title-left-icon" />
  180. <div class="title-left-name">评论</div>
  181. </div>
  182. <div class="detail-info">
  183. <ul class="comment-main">
  184. <li v-for="(item,index) in comments" :key="'comment'+index">
  185. <span class="comment-name">{{ item.commentInfo.name }}</span>
  186. <span class="comment-gmtCreater">{{ item.commentInfo.gmtCreater }}</span><br>
  187. <span class="comment-content">{{ item.commentInfo.content }}</span>
  188. </li>
  189. </ul>
  190. <el-input
  191. v-model="commentContent"
  192. type="textarea"
  193. placeholder="请输入评论内容"
  194. maxlength="300"
  195. show-word-limit
  196. :autosize="{ minRows: 3, maxRows: 5}"
  197. style="margin-bottom: 20px"
  198. />
  199. <el-row>
  200. <el-col :span="2" :offset="22"><el-button type="primary" size="small" @click="addComment">发表评论</el-button></el-col>
  201. </el-row>
  202. </div>
  203. </section>
  204. </el-container>
  205. <!-- 概览 -->
  206. <!-- 缺陷 -->
  207. <el-container v-if="activeName === '2'" class="is-vertical">
  208. <section class="main-section contain">
  209. <bugTableDialog ref="bugTableDialog" no-show="taskName" :obj-id="{ taskId: Number(this.$route.query.id) }" />
  210. </section>
  211. </el-container>
  212. <!-- 缺陷 -->
  213. <!-- 报告 -->
  214. <el-container v-if="activeName === '3'" class="is-vertical">
  215. <report-list />
  216. </el-container>
  217. <!-- 报告 -->
  218. <!-- 统计 -->
  219. <el-container v-if="activeName === '4'" class="is-vertical">
  220. <section class="main-section contain">
  221. <data-statistics ref="data-statistics" />
  222. </section>
  223. </el-container>
  224. <!-- 统计 -->
  225. <!-- 新建(bug) -->
  226. <createdBug v-if="bug_open" ref="createdBug" @reloadList="reloadList" />
  227. <Test-report v-if="dialogTest" ref="TestReport" />
  228. <Daily-report v-if="dialogDaily" ref="DailyReport" />
  229. <Client-report v-if="dialogClient" ref="ClientReport" />
  230. <!-- 新建 -->
  231. <!-- 编辑 -->
  232. <open-dialog v-if="updateVisible" ref="task_createdUpdata" />
  233. <!-- 编辑 -->
  234. <!-- 删除 -->
  235. <el-dialog :visible.sync="deleteVisible" title="删除确认" class="public_task" width="30%" :close-on-click-modal="false">
  236. <div class="blueStripe" />
  237. <div align="center">确定要删除此 {{ form_query.name }} 任务吗?</div>
  238. <span slot="footer" class="dialog-footer">
  239. <el-button size="mini" @click="deleteVisible = false">关 闭</el-button>
  240. <el-button size="mini" type="primary" @click="taskDelete()">确 定</el-button>
  241. </span>
  242. </el-dialog>
  243. <!-- 删除 -->
  244. <task-dialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskIds.id" :status-name="taskIds.statusString" @getList="taskGet" />
  245. <!-- 排期锁定 -->
  246. <schedule ref="ScheduleEvent" :visible.sync="scheduleVisble" :name="'任务'" :is-schedule-locked="isScheduleLocked" :require-id="taskId" @updataData="getScheduleGetTaskScheduleHistory" />
  247. <!-- 排期锁定 -->
  248. <drawer
  249. ref="drawer"
  250. title="任务成员"
  251. center
  252. :display.sync="display"
  253. width="28%"
  254. :delete="form_query"
  255. :types="false"
  256. :inner="true"
  257. :mask="false"
  258. @childValInput="childVal"
  259. @click.stop
  260. />
  261. </el-container>
  262. </div>
  263. </template>
  264. <script>
  265. const _ = require('lodash')
  266. import {
  267. taskGet,
  268. configShowTaskEnum,
  269. tasktaskDelete,
  270. taskUpdate,
  271. commentCreate,
  272. commentList,
  273. configShowRequirementVersionEnum,
  274. scheduleGetTaskScheduleHistory
  275. } from '@/api/taskIndex'
  276. import '@/styles/PublicStyle/index.scss'
  277. import { listByTask } from '@/api/projectViewDetails'
  278. import { projectListProject, scheduleGetHistoryScheduleById } from '@/api/requirement.js'
  279. import searchPeople from '@/components/select/searchPeople'
  280. import textArea from '@/components/input/textArea'
  281. import drawer from '@/views/projectManage/Drawer'
  282. import image_url from '@/assets/home_images/home_u.png'
  283. import createdBug from '@/views/projectManage/bugList/file/createdBug'
  284. // import normalDialog from '@/components/dialog/normalDialog'
  285. import openDialog from '@/views/projectManage/dialog_vue'
  286. import scheduleList from './components/scheduleList'
  287. import reportList from './components/reportList'
  288. import dataStatistics from './components/dataStatistics'
  289. import TestReport from '@/views/Platform/presentation/Templates/TestReport' // 提测
  290. import DailyReport from '@/views/Platform/presentation/Templates/DailyReport' // 日报
  291. import ClientReport from '@/views/Platform/presentation/Templates/ClientReport' // 准出
  292. import stage from '@/assets/detailPage/风险状态.png'
  293. import stage1 from '@/assets/detailPage/正常状态.png'
  294. import stage2 from '@/assets/detailPage/延期状态.png'
  295. import taskDialog from '@/views/projectManage/taskList/dialog/taskDialog' // 任务状态修改(已上线/已提测/已准出)
  296. import bugTableDialog from '@/views/projectManage/bugList/details/bugTableDialog' // 缺陷表格
  297. import '@/styles/PublicStyle/index.scss'
  298. import schedule from '@/views/projectManage/schedule' // 排期锁定弹窗
  299. import download from '@/views/projectManage/components/export.vue'
  300. export default {
  301. components: {
  302. searchPeople,
  303. // normalDialog,
  304. textArea,
  305. drawer,
  306. createdBug,
  307. openDialog,
  308. scheduleList,
  309. reportList,
  310. dataStatistics,
  311. TestReport,
  312. DailyReport,
  313. ClientReport,
  314. taskDialog,
  315. bugTableDialog,
  316. schedule,
  317. download
  318. },
  319. filters: {
  320. ellipsis(value, num) {
  321. if (!value) return ''
  322. if (value.length > num) {
  323. return value.slice(0, num) + '...'
  324. }
  325. return value
  326. }
  327. },
  328. data() {
  329. return {
  330. showunlock: true,
  331. ScheduId: '', // 排期ID
  332. LockState: {}, // 锁定状态
  333. tips: '', // 后加入需求的任务排期提示
  334. scheduleVisble: false, // 排期锁定
  335. isParentRequireScheduleLocked: '',
  336. BackToTheLatest: true, // 显示添加排期按钮
  337. lockHide: false, // 隐藏排期变更记录
  338. SchedulingContent: [], // 排期历史变更记录
  339. stageImg: stage,
  340. normalImg: stage1,
  341. warningImg: stage2,
  342. activeName: '1', // 顶部tab切换
  343. userInformation: localStorage.getItem('username'),
  344. userNames: localStorage.getItem('realname'),
  345. textarea: '', // 评论
  346. showTaskDialog: false, // 状态弹窗
  347. taskId: Number(this.$route.query.id), // 任务id
  348. allStatus: [], // 任务所有状态
  349. belongProjectList: [], // 所属项目列表
  350. requireList: [], // 所属需求列表
  351. appClient: [], // 跟版客户端列表
  352. taskScheduleEvent: [], // 排期类型
  353. dependList: [{ msg: '否', code: 2 }, { msg: '是', code: 1 }], // 是否跟版
  354. form_query: {},
  355. display: false, // 设置成员弹框
  356. isScheduleLocked: '', // 锁定状态1锁定0未锁定
  357. num: 0, // 成员数量
  358. image_url: image_url, // 成员icon
  359. updateVisible: false, // 编辑任务弹框
  360. deleteVisible: false, // 删除任务弹框
  361. bug_open: false, // 新建缺陷弹框
  362. dialogTest: false, // 新建提测报告
  363. dialogDaily: false, // 新建测试日报
  364. dialogClient: false, // 新建准出报告
  365. iterationList: [], // 所属迭代列表
  366. commentContent: null, // 评论内容
  367. comments: [], // 评论列表
  368. taskIds: '' // 将要修改状态的任务id
  369. }
  370. },
  371. computed: {
  372. getStatus() {
  373. return this.allStatus.find(item => item.code === this.form_query.status) || { msg: null }
  374. }
  375. },
  376. created() {
  377. this.taskGet()
  378. this.getTaskStatus()
  379. this.getBelongProject()
  380. this.getRequireList()
  381. this.getCommentList()
  382. this.getScheduleGetTaskScheduleHistory()
  383. this.$store.state.data.status = true
  384. this.$store.state.data.bizId = true
  385. },
  386. destroyed() {
  387. this.$store.state.data.status = false
  388. this.$store.state.data.bizId = false
  389. },
  390. methods: {
  391. async getScheduleGetTaskScheduleHistory() {
  392. this.scheduleVisble = false
  393. const res = await scheduleGetTaskScheduleHistory(this.taskId)
  394. this.SchedulingContent = res.data
  395. const res1 = await listByTask(this.taskId)
  396. this.isScheduleLocked = res1.data.isScheduleLocked
  397. this.tips = res1.data.tips
  398. this.isParentRequireScheduleLocked = res1.data.isParentRequireScheduleLocked
  399. this.$refs.taskSchedule.listByTask(this.taskId)
  400. this.taskGet()
  401. },
  402. async getSchedule() {
  403. this.scheduleVisble = false
  404. const res = await scheduleGetTaskScheduleHistory(this.taskId)
  405. this.SchedulingContent = res.data
  406. const res1 = await listByTask(this.taskId)
  407. this.isScheduleLocked = res1.data.isScheduleLocked
  408. this.tips = res1.data.tips
  409. this.isParentRequireScheduleLocked = res1.data.isParentRequireScheduleLocked
  410. },
  411. async clickScheduling(ele) {
  412. this.showunlock = false
  413. this.ScheduId = ele.id
  414. const res = await scheduleGetHistoryScheduleById(ele.id)
  415. this.taskScheduleEvent = res.data.scheduleDetailRespons
  416. this.BackToTheLatest = false
  417. },
  418. clickBackToTheLatest() {
  419. this.showunlock = true
  420. this.BackToTheLatest = true
  421. this.lockHide = false
  422. this.$refs.taskSchedule.listByTask(this.taskId)
  423. },
  424. changeSchedule() { // 修改锁定状态
  425. if (this.isParentRequireScheduleLocked === 1) {
  426. this.$message({ message: '无法解锁,请先变更归属需求的排期状态为未锁定状态!', type: 'error', duration: 3000, offset: 150 })
  427. } else {
  428. this.scheduleVisble = true
  429. }
  430. },
  431. async changeArea(e) { // area修改
  432. const taskInfoDO = _.cloneDeep(this.form_query)
  433. const user = {
  434. name: localStorage.getItem('username'),
  435. ename: localStorage.getItem('realname'),
  436. id: ''
  437. }
  438. const res = await taskUpdate({ taskInfoDO, user })
  439. if (res.code === 200) {
  440. this.$message({ message: '修改成功', type: 'success', duration: 1000, offset: 150 })
  441. }
  442. this.taskGet()
  443. },
  444. async getBelongProject() { // 获取所属项目列表
  445. const res = await projectListProject({ bizId: Number(localStorage.getItem('bizId')) })
  446. if (res.code === 200) {
  447. this.belongProjectList = res.data
  448. }
  449. },
  450. async getRequireList() { // 获取所属需求列表
  451. const res = await configShowRequirementVersionEnum({ bizId: Number(localStorage.getItem('bizId')) })
  452. if (res.code === 200) {
  453. this.requireList = res.data
  454. }
  455. },
  456. async getTaskStatus() { // 获取任务状态列表,跟版客户端列表
  457. const res = await configShowTaskEnum()
  458. if (res.code === 200) {
  459. this.allStatus = res.data.taskStatus
  460. this.taskScheduleEvent = res.data.taskScheduleEvent || []
  461. this.appClient = res.data.appClient.map(item => {
  462. return {
  463. ...item,
  464. code: `${item.code}`
  465. }
  466. })
  467. }
  468. },
  469. async taskGet() { // 获取任务详情
  470. const res = await taskGet(this.$route.query.id)
  471. if (res.code === 200) {
  472. this.form_query = res.data
  473. }
  474. },
  475. async getCommentList() { // 获取任务评论
  476. const res = await commentList({ type: 3, joinId: this.taskId })
  477. if (res.code === 200) {
  478. this.comments = res.data
  479. this.commentContent = ''
  480. }
  481. },
  482. async addComment() { // 发表任务评论
  483. if (this.commentContent.replace(/\s+/g, '') === '' || this.commentContent === null) {
  484. this.$message.warning('评论不能为空')
  485. return
  486. }
  487. const commentInfo = {
  488. joinId: this.taskId,
  489. content: this.commentContent,
  490. type: 3,
  491. fatherId: 0,
  492. name: this.userNames,
  493. email: this.userInformation
  494. }
  495. const user = { name: this.userNames, ename: this.userInformation, id: '' }
  496. const res = await commentCreate({ commentInfo, user })
  497. if (res.code === 200) {
  498. this.$message({ message: '评论成功', type: 'success', duration: 1000, offset: 150 })
  499. this.getCommentList()
  500. } else {
  501. this.$message.warning(res.msg)
  502. }
  503. },
  504. async updateStatus(e) { // 状态改变
  505. if (e.status === 70 || e.status === 90 || e.status === 100) {
  506. this.taskIds = this.form_query
  507. this.allStatus.map(item => {
  508. item.code === e.status ? this.taskIds.statusString = e.label : ''
  509. })
  510. this.showTaskDialog = true
  511. this.taskIds.status = e.status
  512. return
  513. } else {
  514. const user = {
  515. name: localStorage.getItem('username'),
  516. ename: localStorage.getItem('realname'),
  517. id: ''
  518. }
  519. const taskInfoDO = this.form_query
  520. taskInfoDO.status = e.status
  521. const resTask = await taskUpdate({ taskInfoDO, user })
  522. if (resTask.code === 200) {
  523. this.$message({ message: '修改成功', type: 'success', offset: 150 })
  524. }
  525. }
  526. },
  527. clickAddScheduling() { // 模拟调用自组件方法
  528. this.$refs.taskSchedule.addSchedule()
  529. },
  530. scheduleHiHide() { // 排期变更显示隐藏
  531. this.lockHide = !this.lockHide
  532. this.BackToTheLatest = true
  533. this.showunlock = true
  534. this.ScheduId = ''
  535. },
  536. childVal(val) {
  537. this.num = val
  538. },
  539. setChild() { // 设置成员
  540. this.$refs.drawer.getRoleList()
  541. },
  542. open_created() { // 编辑任务
  543. // 打开弹窗
  544. this.updateVisible = true
  545. this.$nextTick(() => {
  546. this.$refs.task_createdUpdata.init(3, [null, this.taskId])
  547. })
  548. },
  549. async taskDelete() { // 删除任务
  550. const user = { name: this.userNames, ename: this.userInformation, id: '' }
  551. const res = await tasktaskDelete(user, this.taskId)
  552. if (res.code === 200) {
  553. this.$message({ message: '删除成功', type: 'success', duration: 1000, offset: 150 })
  554. this.$router.push({ name: '任务', query: {}})
  555. }
  556. },
  557. created_bug() { // 缺陷创建
  558. this.bug_open = true
  559. this.$nextTick(() => {
  560. this.$refs.createdBug.init(1, { id: this.taskId })
  561. })
  562. },
  563. createReport(e, ele) { // 创建报告
  564. switch (e) {
  565. case 1: // 提测
  566. this.dialogTest = true
  567. this.$nextTick(() => { this.$refs.TestReport.init(1, ele) })
  568. break
  569. case 2: // 日报
  570. this.dialogDaily = true
  571. this.$nextTick(() => { this.$refs.DailyReport.init(1) })
  572. break
  573. case 3:
  574. this.dialogClient = true
  575. this.$nextTick(() => { this.$refs.ClientReport.init(1, ele) })
  576. break
  577. }
  578. },
  579. jump(page, id) { // 跳转
  580. this.$router.push({ name: page, query: { id: id }})
  581. },
  582. reloadList() {
  583. this.taskGet()
  584. if (this.$refs['bugTableDialog']) {
  585. this.$refs['bugTableDialog'].bugGetTableList()
  586. }
  587. if (this.$refs['data-statistics']) {
  588. this.$refs['data-statistics'].getRequireSumData()
  589. }
  590. }
  591. }
  592. }
  593. </script>
  594. <style scoped lang="scss">
  595. @import '@/styles/detail-pages.scss';
  596. /deep/.el-button {
  597. cursor: pointer;
  598. }
  599. @include hide-open-header;
  600. .bg-project {
  601. @include bg-project;
  602. }
  603. .main-header {
  604. @include main-header;
  605. }
  606. .main-header::after {
  607. @include main-header-after;
  608. }
  609. .contain {
  610. height: calc(100vh - 140px);
  611. overflow: scroll;
  612. }
  613. .main-section {
  614. @include main-section;
  615. .require-plan {
  616. display: flex;
  617. align-items: center;
  618. span {
  619. margin-left: 20px;
  620. color: #E6A23C;
  621. font-size: 12px;
  622. }
  623. }
  624. .detail-info {
  625. padding: 0 34px 20px 34px;
  626. /deep/.el-input__inner{
  627. border: 1px solid rgba(220,223,230,0)
  628. }
  629. /deep/.el-input__inner:hover{
  630. border: 1px solid rgba(220,223,230,1)
  631. }
  632. /deep/.is-focus .el-input__inner {
  633. border: 1px solid #409EFF;
  634. }
  635. /deep/.el-select{
  636. .el-input__suffix-inner {
  637. visibility: hidden;
  638. }
  639. }
  640. /deep/.el-select:hover{
  641. .el-input__suffix-inner {
  642. visibility: visible;
  643. }
  644. }
  645. .demo-form-inline {
  646. .el-form-item {
  647. width: 33%;
  648. margin-right: 0;
  649. }
  650. }
  651. .comment-main {
  652. list-style: none;
  653. padding: 15px 0 0 0;
  654. margin: 0 0 20px 0;
  655. li {
  656. list-style: none;
  657. padding: 0px;
  658. margin: 0px 0px 25px 0;
  659. }
  660. .comment-name {
  661. font-size:14px;
  662. color:#333B4A;
  663. }
  664. .comment-gmtCreater {
  665. margin-left:20px;
  666. color: #9B9B9B;
  667. font-size:12px
  668. }
  669. .comment-content {
  670. font-size:14px;
  671. color:#333B4A;
  672. margin-top: 10px;
  673. white-space: pre-line;
  674. }
  675. }
  676. .PRD-link:hover{
  677. color:#409EFF;
  678. }
  679. .PRD-link {
  680. width: 50%;
  681. overflow: hidden;
  682. text-overflow:ellipsis;
  683. white-space: nowrap;
  684. }
  685. }
  686. }
  687. .task-stage {
  688. position: absolute;
  689. left: 5px;
  690. top: 0px;
  691. z-index: 999;
  692. .task-stage-main {
  693. position: relative;
  694. height: 52px;
  695. width: 15.5px;
  696. img{
  697. height: 52px;
  698. width: 15.5px;
  699. }
  700. .task-stage-title{
  701. position: absolute;
  702. left: 0;
  703. right: 0;
  704. top: 0;
  705. bottom: 0;
  706. color: #ffffff;
  707. font-size: 10px;
  708. text-align: center;
  709. }
  710. }
  711. }
  712. >>>.module .el-form-item__content {
  713. display: inline-block;
  714. width: calc(100% - 100px);
  715. div {
  716. line-height: 18px;
  717. padding-top: 12px;
  718. cursor: pointer;
  719. }
  720. div:hover{
  721. color: #409EFF;
  722. }
  723. }
  724. .form-progress {
  725. width: 200px;
  726. padding-top: 12px;
  727. }
  728. >>>.el-input--small {
  729. font-size: 14px;
  730. }
  731. .vss {
  732. border:1px solid #409EFF !important;
  733. color:#409EFF !important;
  734. }
  735. </style>