Эх сурвалжийг харах

需求详情页优化排期锁定

qinzhipeng_v@didiglobal.com 4 жил өмнө
parent
commit
7bb332c200

+ 113 - 19
src/views/projectManage/components/demand.vue

@@ -10,6 +10,7 @@
       <el-table-column prop="seperateDaysNoHoliday" label="排期" min-width="160" />
       <el-table-column prop="dayLength" label="时长" min-width="50" />
       <el-table-column prop="peopleList" label="参与人员" min-width="150" />
+      <el-table-column prop="dayLength" label="关联任务" min-width="100" />
       <el-table-column label="操作" width="120" />
     </el-table>
     <div v-if="tableHeader === true" class="Layout_space_between" style="height: 40px;;border: 1px solid #EBEEF5;">
@@ -27,26 +28,45 @@
       <el-table-column v-if="locking" type="selection" width="50" align="center" />
       <el-table-column label="任务" width="300" align="left">
         <template slot-scope="scope">
-          <div v-if="!scope.row.vsInput">
+          <div v-if="!scope.row.vsInput" @mouseover="scope.row.vVisible = true" @mouseout="scope.row.vVisible = false">
             <div class="templatName">
+              <div v-if="scope.row.involveAppString !== null" class="involveApp-top-bottom">
+                <span class="el-involveApp">{{ scope.row.involveAppString }}</span>
+              </div>
               <el-tooltip class="item" effect="dark" :content="scope.row.moduleInfoName" placement="top">
-                <span>{{ scope.row.moduleInfoName === null ? "" : scope.row.moduleInfoName.substring(0,9) }}</span>
+                <span v-if="scope.row.moduleInfoName !== null">{{ scope.row.moduleInfoName.length >= 24 ? scope.row.moduleInfoName.substring(0,25) + '...' : scope.row.moduleInfoName }}</span>
               </el-tooltip>
-              <span v-if="scope.row.involveAppString !== null" class="el-involveApp">{{ scope.row.involveAppString }}</span>
             </div>
 
-            <div class="Layout_space_between" @mouseover="scope.row.vVisible = true" @mouseout="scope.row.vVisible = false">
-              <div class="Layout_flex_start">
-                <div class="templatTaskName cursorPo" @click="clickTemplatTaskName(scope.row.id)">{{ scope.row.name }}</div>
-                <el-tooltip v-if="locking" class="item" effect="dark" :content="scope.row.isScheduleLocked === 1? '点击解锁排期' : '点击锁定排期'" placement="top">
+            <div class="templatTaskName cursorPo" @click="clickTemplatTaskName(scope.row.id)">{{ scope.row.name }}</div>
+
+            <div class="templatCreator">
+              <el-tooltip class="item" effect="dark" content="点击修改" placement="top">
+                <el-popover placement="bottom" title="开发负责人" width="400" trigger="click">
+                  <div class="blueStr" />
+                  <search-people :value.sync="form_query.rqmtProposer" :clearable="false" :multiple="false" style="width: 100%;" @change="changeArea" />
+                  <span slot="reference" class="cursorPo">开发负责人:{{ scope.row.rdObject.name !== null? scope.row.rdObject.name: '无' }}</span>
+                </el-popover>
+              </el-tooltip>
+              <el-tooltip class="item" effect="dark" content="点击修改" placement="top">
+                <el-popover placement="bottom" title="测试负责人" width="400" class="iconPadding" trigger="click">
+                  <div class="blueStr" />
+                  <search-people :value.sync="form_query.rqmtProposer" :clearable="false" :multiple="false" style="width: 100%;" @change="changeArea" />
+                  <span slot="reference" class="cursorPo">测试负责人: {{ scope.row.qaObject.name !== null ? scope.row.qaObject.name: '无' }}</span>
+                </el-popover>
+              </el-tooltip>
+            </div>
+
+            <div class="Layout_space_between">
+              <div>望月</div>
+              <div v-if="locking" v-show="scope.row.vVisible" class="iconEdit">
+                <el-tooltip class="item cursorPo" effect="dark" :content="scope.row.isScheduleLocked === 1? '点击解锁排期' : '点击锁定排期'" placement="top">
                   <div :class="scope.row.isScheduleLocked === 1 ? 'el-icon-lock' : 'el-icon-unlock'" @click="changeSchedule(scope.row)" />
                 </el-tooltip>
+                <i class="el-icon-edit-outline cursorPo" @click="editTask(scope.row)" />
+                <i v-show="scope.row.isScheduleLocked === 0" class="el-icon-circle-plus-outline cursorPo" @click="clickAddScheduling(2,scope.row)" />
+                <i class="el-icon-sort cursorPo deg" @click="clickAddScheduling(2,scope.row)" />
               </div>
-              <div v-if="locking" v-show="scope.row.vVisible" class="iconEdit"><i class="el-icon-edit-outline iconPadding cursorPo" @click="editTask(scope.row)" /> <i v-show="scope.row.isScheduleLocked === 0" class="el-icon-circle-plus-outline cursorPo" @click="clickAddScheduling(2,scope.row)" /></div>
-            </div>
-
-            <div class="templatCreator">
-              开发负责人:{{ scope.row.rdObject.name !== null? scope.row.rdObject.name: '无' }} 测试负责人: {{ scope.row.qaObject.name !== null?scope.row.qaObject.name: '无' }}
             </div>
           </div>
           <el-input v-if="scope.row.vsInput" ref="taskName" v-model="taskName" type="textarea" rows="4" placeholder="请输入内容" maxlength="150" show-word-limit @blur="changeTaskName(scope.row)" />
@@ -66,6 +86,7 @@
               'public_btn3':scope.row.status===20 || scope.row.status===30
             }"
             size="mini"
+            @change="changeStatus(scope.row)"
           >
             <el-option v-for="item in scope.row.availableStatusList" :key="item.code" :label="item.name" :value="item.code" />
           </el-select>
@@ -90,19 +111,26 @@
 
     <!-- 排期锁定弹窗 -->
     <schedule ref="ScheduleEvent" :visible.sync="scheduleVisble" :name="'任务'" :is-schedule-locked="isScheduleLocked" :require-id="Number(taskId)" @updataData="listByTask(requirementId)" />
-  <!-- 排期锁定弹窗 -->
+    <!-- 排期锁定弹窗 -->
+
+    <task-dialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskIdObject.id" :status-name="taskIdObject.statusString" @getList="listByTask(requirementId)" />
   </div>
 </template>
 <script>
+import searchPeople from '@/components/select/searchPeople'
 import { listByRequire } from '@/api/requirement.js'
 import scheduleList from '@/views/projectManage/components/scheduleList.vue'
 import '@/styles/PublicStyle/index.scss' // 通用css
+import { configShowTaskStatusEnum } from '@/api/taskIndex'
 import { taskUpdate } from '@/api/taskIndex'
 import schedule from '@/views/projectManage/schedule' // 排期锁定弹窗
+import taskDialog from '@/views/projectManage/taskList/dialog/taskDialog' // 任务状态修改(已上线/已提测/已准出)
 export default {
   components: {
     scheduleList,
-    schedule
+    schedule,
+    searchPeople,
+    taskDialog
   },
   props: {
     requiredList: {
@@ -114,8 +142,11 @@ export default {
   data() {
     return {
       requirementId: Number(this.$route.query.id),
+      allStatus: [], // task状态
       tableData: [],
       checkAlls: false,
+      taskIdObject: {},
+      showTaskDialog: false,
       taskScheduleList: [],
       scheduleList: [],
       datas: [{
@@ -126,6 +157,8 @@ export default {
         dayLength: '',
         peopleList: ''
       }],
+      form_query: {},
+      nowChangeTask: null, // 当前正在改变的任务对象
       isScheduleLocked: '', //  当前排期的状态
       taskId: '', // taskID
       scheduleVisble: false, // 排期锁定
@@ -169,6 +202,9 @@ export default {
       immediate: true
     }
   },
+  created() {
+    this.configShowTaskStatusEnum()
+  },
   methods: {
     async listByTask(id) { // 获取排期列表
       this.taskList = []
@@ -191,8 +227,39 @@ export default {
       }
     },
 
+    async configShowTaskStatusEnum() {
+      const res = await configShowTaskStatusEnum(localStorage.getItem('bizId'))
+      if (res.code === 200) {
+        this.allStatus = res.data.taskStatus
+      }
+    },
+
+    async changeStatus(e) { // 状态改变
+      if (e.status === 70 || e.status === 90 || e.status === 100) {
+        this.taskIdObject = e
+        this.allStatus.map(item => {
+          item.code === e.status ? this.taskIdObject.statusString = item.msg : ''
+        })
+        this.showTaskDialog = true
+        this.nowChangeTask = e
+        return
+      } else {
+        const user = {
+          name: localStorage.getItem('username'),
+          ename: localStorage.getItem('realname'),
+          id: ''
+        }
+        const taskInfoDO = e
+        const resTask = await taskUpdate({ taskInfoDO, user })
+        if (resTask.code === 200) {
+          this.listByTask(this.requirementId)
+          this.$message({ message: '修改成功', type: 'success', offset: 150 })
+        }
+      }
+    },
+
     addClass({ row, column, rowIndex, columnIndex }) {
-      if (columnIndex === 2) {
+      if (columnIndex === 3) {
         return 'cell-grey'
       }
     },
@@ -247,6 +314,9 @@ export default {
         this.$refs.taskName.focus()
       })
     },
+    changeArea(value) {
+      console.log(value, 'cdsncjds')
+    },
     changeCheckout(rows) {
       if (rows) {
         this.tableData.forEach(row => {
@@ -328,10 +398,10 @@ export default {
   opacity:1;
 }
 .iconEdit {
-  width:67px;
+  width:100px;
   background:rgba(245,245,245,1);
   opacity:1;
-  padding: 0 10px;
+  padding: 2px 10px;
   border-radius:20px;
   display: flex;
   justify-content: space-between;
@@ -341,8 +411,13 @@ export default {
     display: none;
   }
 }
+
+.involveApp-top-bottom {
+ margin: 10px 0;
+}
+
 .iconPadding {
-  margin-right: 5px;
+  margin-left: 5px;
 }
 .schedule-list {
  /deep/ .el-table td {
@@ -363,7 +438,6 @@ export default {
   font-family:MicrosoftYaHei;
   line-height:12px;
   padding: 0 5px;
-  margin-left: 5px;
   color:rgba(64,158,255,1);
   opacity:1;
 }
@@ -401,8 +475,28 @@ export default {
 .status2 {
   @include setStatus(#7ED321)
 }
+.deg {
+  transform:rotate(90deg);
+  -ms-transform:rotate(-90deg); /* Internet Explorer 9*/
+  -moz-transform:rotate(-90deg); /* Firefox */
+  -webkit-transform:rotate(-90deg); /* Safari 和 Chrome */
+  -o-transform:rotate(-90deg); /* Opera */
+}
+.blueStr {
+  width:4px;
+  height:17px;
+  background:#409EFF;
+  border-radius:1px;
+  position: absolute;
+  top: 12px;
+  left: 10px;
+}
 </style>
 <style>
+ .el-popover__title {
+    color: #333333;
+    padding-left: 10px;
+}
  .cell-grey .cell {
    padding: 0 !important;
  }

+ 33 - 1
src/views/projectManage/components/scheduleList.vue

@@ -8,7 +8,7 @@
       :cell-class-name="addClass"
       row-key="id"
       border
-      style="min-height: 90px;"
+      style="min-height: 125px;"
       size="mini"
       :class="{'ignore-elements': dondrop }"
     >
@@ -26,6 +26,19 @@
           <span v-for="(item, index) in scope.row.peopleObjectList" :key="index">{{ item.name }} {{ ' ' }}</span>
         </template>
       </el-table-column>
+      <el-table-column prop="dayLength" class="popover-blue" label="关联任务" min-width="100">
+        <template slot-scope="scope">
+          <el-popover placement="bottom" title="关联任务" width="500" trigger="click">
+            <div class="blueStr" />
+            <div v-for="(item, index) in scope.row.taskObjectList" :key="index" class="Layout_space_between" style="max-height: 300px" align="center">
+              <span>TASK-{{ item.id }}</span>
+              <span class="public_Jump" @click="Task_Jump(item.id)">{{ item.name }}</span>
+              <span>{{ item.moduleInfoName.length > 10 ? item.moduleInfoName.substring(0,10) + '...' : item.moduleInfoName }}</span>
+            </div>
+            <el-button slot="reference" type="text">{{ scope.row.taskObjectList.length }}</el-button>
+          </el-popover>
+        </template>
+      </el-table-column>
       <el-table-column label="操作" width="120">
         <template slot-scope="scope">
           <div class="btn-style">
@@ -144,6 +157,10 @@ export default {
     async listByTask(id) { // 获取排期列表
       this.$emit('listByTask')
     },
+    Task_Jump(id) {
+      const routeData = this.$router.push({ name: '任务详情', query: { id: id }})
+      window.open(routeData.href, '_blank')
+    },
     addSchedule() {
       this.detailData = null
       this.DialogTitle = '新建排期'
@@ -208,6 +225,16 @@ export default {
     background: #ffffff !important;
   }
 }
+
+.blueStr {
+  width:4px;
+  height:17px;
+  background:#409EFF;
+  border-radius:1px;
+  position: absolute;
+  top: 12px;
+  left: 10px;
+}
 .sortable-tip {
   height: 26px;
   width: 15px;
@@ -221,6 +248,11 @@ export default {
 }
 </style>
 <style>
+ .el-popover__title {
+    color: #333333;
+    padding-left: 10px;
+}
+
  .cell-greys .cell {
    margin-left: 10px !important;
  }

+ 15 - 0
src/views/projectManage/requirement/requirementDetail.vue

@@ -175,6 +175,14 @@
             </div><br>
           </div>
           <section class="main-section">
+            <div class="required-tips">
+              <i class="el-icon-question" />
+              <span> 帮助提示</span><br>
+              .需求排期是对任务排期的汇总,给需求排期请优先拆解任务;每个任务仅支持一次提测和一次准出,请合理拆解任务后再排期。<br>
+              .需求状态未变更【已排期】前,排期不可锁定;状态变更为【已排期】时,需求排期将被系统自动锁定。<br>
+              .需求排期锁定时,任务排期将全部被锁定;所有任务锁定时,需求排期将被系统自动锁定。<br>
+              .任务锁定时,系统会自动将任务排期及交付时间同步至望岳。若多个任务关联同一个望岳任务,同步时排期会汇总一并同步到望岳,交付时间则按最晚日期同步至望岳。
+            </div>
             <div class="allTips">
               <el-radio-group v-model="listOrGannt" size="small" style="margin-left: 10px">
                 <el-radio-button label="列表" />
@@ -830,6 +838,13 @@ export default {
 }
 </script>
 <style scoped lang="scss">
+.required-tips {
+  border: 1px solid #e0eefd;
+  border-radius: 4px;
+  background: #edf5fe;
+  margin: 0 20px 10px;
+  padding: 10px;
+}
 @import '@/styles/detail-pages.scss';
 /deep/.el-button {
   cursor: pointer;