Răsfoiți Sursa

Merge branch 'http_test' into pern

qinzhipeng_v 5 ani în urmă
părinte
comite
fbe07e38b5

+ 16 - 0
src/api/defectStatistics.js

@@ -25,6 +25,14 @@ export function getRepairTimeSumData(data) {
     data
   })
 }
+// 去除节假日平均平均修复时长头部数据
+export function getRepairTimePurgeNhSumData(data) {
+  return request({
+    url: TeamManagement + '/bug/getRepairTimePurgeNhSumData',
+    method: 'post',
+    data
+  })
+}
 // 平均修复时长表数据
 export function getRepairTimeDetailData(data) {
   return request({
@@ -33,6 +41,14 @@ export function getRepairTimeDetailData(data) {
     data
   })
 }
+// 去除平均修复时长表数据
+export function getRepairTimePurgeNhDetailData(data) {
+  return request({
+    url: TeamManagement + '/bug/getRepairTimePurgeNhDetailData',
+    method: 'post',
+    data
+  })
+}
 // 获取模块数据
 export function getModuleDistributeData(data) {
   return request({

+ 54 - 0
src/api/workSchedule.js

@@ -104,3 +104,57 @@ export function queryTeamWorkList(data) {
     data
   })
 }
+
+// 获取个人项目
+export function projectSelfList(data) {
+  return request({
+    url: TeamManagement + `/project/selfList`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取团队项目
+export function projectTeamList(data) {
+  return request({
+    url: TeamManagement + `/project/teamList`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取个人需求
+export function requirementSelfList(data) {
+  return request({
+    url: TeamManagement + `/requirement/selfList`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取团队需求
+export function requirementTeamList(data) {
+  return request({
+    url: TeamManagement + `/requirement/teamList`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取个人任务
+export function taskSelfList(data) {
+  return request({
+    url: TeamManagement + `/task/selfList`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取团队任务
+export function taskTeamList(data) {
+  return request({
+    url: TeamManagement + `/task/teamList`,
+    method: 'post',
+    data
+  })
+}

+ 0 - 148
src/api/workbench.js

@@ -1,148 +0,0 @@
-import request from '@/utils/request'
-import { workbenchUrl } from '@/apiConfig/api'
-// ================================== Interface ======================================
-
-export default {
-  createSelfSchedule,
-  updateSelfSchedule,
-  getSelfSchedule,
-  deleteSelfSchedule,
-  queryTeamInfoList,
-  showTeamAndMemberEnum,
-  queryWorkListByTime,
-  queryWorkList,
-  queryIdleList,
-  queryTeamWorkList,
-  queryTeamIdleList
-}
-
-// 创建个人日程
-export function createSelfSchedule(data) {
-  return request({
-    url: workbenchUrl + '/selfSchedule/create',
-    method: 'post',
-    data
-  })
-}
-
-// 更新个人日程
-export function updateSelfSchedule(data) {
-  return request({
-    url: workbenchUrl + '/selfSchedule/update',
-    method: 'post',
-    data
-  })
-}
-
-// 获取个人日程
-export function getSelfSchedule(data) {
-  return request({
-    url: workbenchUrl + '/selfSchedule/get',
-    method: 'get',
-    params: data
-  })
-}
-
-// 删除个人日程
-export function deleteSelfSchedule(id) {
-  return request({
-    url: workbenchUrl + '/selfSchedule/delete?id=' + id,
-    method: 'post'
-  })
-}
-
-// 获取指定时间段用户日程信息
-export function queryWorkListByTime(data) {
-  return request({
-    url: workbenchUrl + '/workbench/personal/queryWorkListByTime',
-    method: 'post',
-    data
-  })
-}
-
-// 获取用户日程信息
-export function queryWorkList(data) {
-  return request({
-    url: workbenchUrl + '/workbench/personal/queryWorkList',
-    method: 'post',
-    data
-  })
-}
-
-// 获取个人空闲日程列表
-export function queryIdleList(data) {
-  return request({
-    url: workbenchUrl + '/workbench/personal/queryIdleList',
-    method: 'post',
-    data
-  })
-}
-
-// 获取团队用户日程信息
-export function queryTeamWorkList(data) {
-  return request({
-    url: workbenchUrl + '/workbench/personal/queryTeamWorkList',
-    method: 'post',
-    data
-  })
-}
-
-// 获取团队用户空闲信息
-export function queryTeamIdleList(data) {
-  return request({
-    url: workbenchUrl + '/workbench/personal/queryTeamIdleList',
-    method: 'post',
-    data
-  })
-}
-
-// 获取用户团队列表
-export function queryTeamInfoList(data) {
-  return request({
-    url: workbenchUrl + '/team/queryTeamInfoList',
-    method: 'post',
-    data
-  })
-}
-
-// 角色信息枚举类
-export function showTeamAndMemberEnum(data) {
-  return request({
-    url: workbenchUrl + '/config/showTeamAndMemberEnum',
-    method: 'get',
-    data
-  })
-}
-
-// 创建文件夹
-export function personalworkstationQueryBackLog(data) {
-  return request({
-    url: workbenchUrl + '/personalworkstation/queryBackLog',
-    method: 'post',
-    data
-  })
-}
-
-export function personalworkstationQueryBackLogBugAndTask(data) {
-  return request({
-    url: workbenchUrl + '/personalworkstation/queryBackLogBugAndTask',
-    method: 'post',
-    data
-  })
-}
-
-export function personalworkstationQueryStatusAndPriority(data) {
-  return request({
-    url: workbenchUrl + '/personalworkstation/queryStatusAndPriority',
-    method: 'post',
-    data
-  })
-}
-
-export function personalworkstationQueryPeriodBugAndTask(data) {
-  return request({
-    url: workbenchUrl + '/personalworkstation/queryPeriodBugAndTask',
-    method: 'post',
-    data
-  })
-}

+ 2 - 2
src/styles/detail-pages.scss

@@ -44,10 +44,9 @@
     font-size:20px;
     font-family: MicrosoftYaHei;
     color: rgb(51, 59, 74);
-    margin-right:8%;
     display: flex;
     flex-direction: column;
-    width: 190px;
+    width: 250px;
     .title-id{
       color:rgba(51,59,74,0.5);
       font-size: 12px;
@@ -103,6 +102,7 @@
   min-height: 99%;
   margin: 0 10px 10px 10px;
   background-color: #ffffff;
+  border-radius: 5px;
   .el-main-title {
     display: flex;
     align-items: center;

+ 1 - 1
src/views/projectManage/dialog_vue.vue

@@ -138,7 +138,7 @@ export default {
       userNames: localStorage.getItem('realname'),
       task_rulesForm: {
         name: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
-        moduleIds: [{ required: true, message: '请选择模块', trigger: 'blur' }],
+        // moduleIds: [{ required: true, message: '请选择模块', trigger: 'blur' }],
         priority: [{ required: true, message: '请选择优先级', trigger: 'blur' }],
         bizId: [{ required: true, message: '请选择业务线', trigger: 'blur' }],
         source: [{ required: true, message: '请输入直接归属', trigger: 'blur' }],

+ 6 - 6
src/views/projectManage/projectList/components/modifySchedule.vue

@@ -287,25 +287,25 @@ export default {
       const res = await scheduleCreate(params)
       if (res.code === 200) {
         this.$message({ message: '添加成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleUpdate(params) { // 更新排期
       const res = await scheduleUpdate(params)
       if (res.code === 200) {
         this.$message({ message: '更新成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleDelete() { // 删除排期
       const res = await scheduleDelete(this.form.id)
       if (res.code === 200) {
         this.$message({ message: '删除成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     confirmForm() { // 确认提交表单
       if (this.isDeleteStatus) {

+ 6 - 11
src/views/projectManage/projectList/components/needsList.vue

@@ -48,10 +48,10 @@
         <template slot-scope="scope">{{ scope.row.sourceTypeName }}</template>
       </el-table-column>
       <el-table-column label="跟版客户端" width="150" align="center" show-overflow-tooltip>
-        <template slot-scope="scope">{{ scope.row.app }}</template>
+        <template slot-scope="scope">{{ scope.row.referredClientTypeName }}</template>
       </el-table-column>
       <el-table-column label="PRD连接" width="180" align="center" show-overflow-tooltip>
-        <template slot-scope="scope"><a :href="scope.row.mrdUrl" /></template>
+        <template slot-scope="scope"><a :href="scope.row.mrdUrl">{{ scope.row.mrdUrl }}</a></template>
       </el-table-column>
       <el-table-column label="任务数量" align="center">
         <template slot-scope="scope">{{ scope.row.taskCount }}</template>
@@ -81,14 +81,12 @@ export default {
       const res = await showRequirementEnum()
       if (res.code === 200) {
         this.allStatus = res.data.requirementStatus
-        console.log(res.data)
       }
     },
     async getNeedsList() {
       const res = await requirementQueryRequirementInfoList({ belongingProject: this.$route.query.id })
       if (res.code === 200) {
         this.needsDataList = res.data.list
-        console.log(res.data)
       }
     },
     async changeStatus(e) { // 状态改变
@@ -148,19 +146,16 @@ export default {
 .status0 {
   @include setStatus(#409EFF)
 }
-.status5 {
-  @include setStatus(#FF8952)
-}
-.status10 {
+.status1 {
   @include setStatus(#FF8952)
 }
-.status15 {
+.status3 {
   @include setStatus(#FF8952)
 }
-.status20 {
+.status5 {
   @include setStatus(#FF8952)
 }
-.status25 {
+.status9 {
   @include setStatus(#7ED321)
 }
 .div_priority {

+ 9 - 18
src/views/projectManage/projectList/components/taskList.vue

@@ -135,7 +135,6 @@ export default {
       allChange: false, // 是否全展开
       expandArr: [], // 展开行数组
       showTaskDialog: false, // 状态弹窗
-      inputValue: '',
       all_task: [], // 任务列表
       allStatus: [], // 任务所有状态
       taskScheduleEvent: [], // 排期类型
@@ -155,14 +154,6 @@ export default {
       selectTaskList: [] // 已选任务的id
     }
   },
-  watch: {
-    value: {
-      handler(newV, oldV) {
-        this.inputValue = newV
-      },
-      immediate: true
-    }
-  },
   created() {
     this.getTaskStatus()
     this.get_allTask()
@@ -221,15 +212,15 @@ export default {
         }
       }
     },
-    // async confirmStatus() { // 确认更改状态
-    //   const user = { name: localStorage.getItem('username'), ename: localStorage.getItem('realname'), id: '' }
-    //   const taskInfoDO = this.nowChangeTask
-    //   taskInfoDO.onlineRealTime = this.changeStatusDate
-    //   const resTask = await taskUpdate({ taskInfoDO, user })
-    //   if (resTask.code === 200) {
-    //     this.$message({ message: resTask.msg, type: 'success', offset: 150 })
-    //   }
-    // },
+    async confirmStatus() { // 确认更改状态
+      const user = { name: localStorage.getItem('username'), ename: localStorage.getItem('realname'), id: '' }
+      const taskInfoDO = this.nowChangeTask
+      taskInfoDO.onlineRealTime = this.changeStatusDate
+      const resTask = await taskUpdate({ taskInfoDO, user })
+      if (resTask.code === 200) {
+        this.$message({ message: resTask.msg, type: 'success', offset: 150 })
+      }
+    },
     handleSelectionChange(val) { // 任务列表删选操作
       val.length > 0 ? this.showHeader = false : this.showHeader = true
       this.curcentChecked = val.length

+ 6 - 6
src/views/projectManage/requirement/components/modifySchedule.vue

@@ -288,25 +288,25 @@ export default {
       const res = await scheduleCreate(params)
       if (res.code === 200) {
         this.$message({ message: '添加成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleUpdate(params) { // 更新排期
       const res = await scheduleUpdate(params)
       if (res.code === 200) {
         this.$message({ message: '修改成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleDelete() { // 删除排期
       const res = await scheduleDelete(this.form.id)
       if (res.code === 200) {
         this.$message({ message: '删除成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     confirmForm() { // 确认提交表单
       if (this.isDeleteStatus) {

+ 0 - 10
src/views/projectManage/requirement/components/taskList.vue

@@ -128,11 +128,9 @@ export default {
   data() {
     return {
       imgUrl: imgUrl,
-      changeData: new Map(),
       allChange: false, // 是否全展开
       expandArr: [], // 展开行数组
       showTaskDialog: false, // 状态弹窗
-      inputValue: '',
       all_task: [], // 任务列表
       allStatus: [], // 任务所有状态
       taskScheduleEvent: [], // 排期类型
@@ -152,14 +150,6 @@ export default {
       selectTaskList: [] // 已选任务的id
     }
   },
-  watch: {
-    value: {
-      handler(newV, oldV) {
-        this.inputValue = newV
-      },
-      immediate: true
-    }
-  },
   created() {
     this.getTaskStatus()
     this.get_allTask()

+ 6 - 3
src/views/projectManage/requirement/requirementDetail.vue

@@ -67,7 +67,7 @@
                 </el-select>
               </el-form-item>
               <el-form-item label="PM:">
-                <search-people v-if="form_query.pm" :value.sync="form_query.pm.idap" :clearable="false" @change="changeArea" />
+                <search-people :value.sync="form_query.pm.idap" :clearable="false" @change="changeArea" />
               </el-form-item>
             </el-form>
             <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
@@ -96,7 +96,7 @@
             </el-form>
             <el-form :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
               <el-form-item label="PRD链接:" prop="mrdUrl" class="PRD">
-                <span class="PRD-link">{{ form_query.mrdUrl }}</span>
+                <span class="PRD-link"><a :href="form_query.mrdUrl" target="_blank">{{ form_query.mrdUrl }}</a></span>
               </el-form-item>
             </el-form>
           </div>
@@ -322,7 +322,7 @@ export default {
       appClient: [], // 跟版客户端列表
       taskScheduleEvent: [], // 排期类型列表
       dependList: [{ msg: '否', code: 0 }, { msg: '是', code: 1 }], // 是否跟版
-      form_query: {},
+      form_query: { pm: {}},
       display: false, // 设置成员弹框
       num: 0, // 成员数量
       image_url: image_url, // 成员icon
@@ -601,6 +601,9 @@ export default {
       text-overflow:ellipsis;
       white-space: nowrap;
     }
+    .PRD-link:hover{
+      color:#409EFF;
+    }
   }
 }
 >>>.module .el-form-item__content {

+ 6 - 6
src/views/projectManage/taskList/components/modifySchedule.vue

@@ -273,25 +273,25 @@ export default {
       const res = await scheduleCreate(params)
       if (res.code === 200) {
         this.$message({ message: '添加成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleUpdate(params) { // 更新排期
       const res = await scheduleUpdate(params)
       if (res.code === 200) {
         this.$message({ message: '更新成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     async scheduleDelete() { // 删除排期
       const res = await scheduleDelete(this.form.id)
       if (res.code === 200) {
         this.$message({ message: '删除成功', type: 'success', duration: 1000, offset: 150 })
+        this.$emit('update')
+        this.cancel()
       }
-      this.$emit('update')
-      this.cancel()
     },
     confirmForm() { // 确认提交表单
       if (this.isDeleteStatus) {

+ 2 - 2
src/views/projectManage/taskList/taskViewDetail.vue

@@ -85,10 +85,10 @@
             </el-form>
             <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
               <el-form-item label="开发负责人:">
-                <search-people :value.sync="form_query.rdOwner || ''" @change="changeArea" />
+                <search-people :value.sync="form_query.rdOwner" @change="changeArea" />
               </el-form-item>
               <el-form-item label="测试负责人:">
-                <search-people :value.sync="form_query.qaOwner || ''" @change="changeArea" />
+                <search-people :value.sync="form_query.qaOwner" @change="changeArea" />
               </el-form-item>
               <el-form-item label="是否跟版:">
                 <el-select v-model="form_query.followVersion" size="small" filterable placeholder="请选择" @change="changeArea">

+ 112 - 11
src/views/quality/defectStatistics.vue

@@ -114,7 +114,7 @@
               />
             </el-select>
           </el-col>
-          <el-col :span="4" :offset="16" class="col-flex">
+          <el-col :span="4" :offset="16" class="col-flex-end">
             <div class="bar-pie" :class="[barOrPie==='bar'?'active':'']" @click="changeBarOrPie('bar')">柱状图</div>
             <div class="bar-pie" :class="[barOrPie==='pie'?'active':'']" @click="changeBarOrPie('pie')">环状图</div>
           </el-col>
@@ -141,8 +141,25 @@
             </div>
           </div>
         </el-row>
+        <h3>去除节假日的修复时长</h3>
         <el-row type="flex" align="middle">
-          <el-col :span="4" :offset="20" class="col-flex">
+          <div class="repair-list">
+            <div v-for="(item, index) in repairTimeListNoHoliday" :key="'time'+index" class="repair-item" :class="[Number(item.relativeRatio)<0?'repair-slow':'repair-rise']">
+              <div class="repair-item-point" :class="['point'+index]" />
+              <span>{{ item.label }}</span>
+              <div class="repair-time">{{ item.total }}</div>
+              <div v-show="Number(item.relativeRatio)>=0" class="repair-up">环比:<i class="el-icon-caret-top" /><span>{{ item.relativeRatio }}%</span></div>
+              <div v-show="Number(item.relativeRatio)<0" class="repair-down">环比:<i class="el-icon-caret-bottom" /><span>{{ item.relativeRatio.substring(1,item.relativeRatio.length) }}%</span></div>
+              <div v-show="item.relativeRatio === '--'" class="repair-up">环比:<span>{{ item.relativeRatio }}%</span></div>
+            </div>
+          </div>
+        </el-row>
+        <el-row type="flex" align="middle">
+          <el-col :span="4" class="col-flex-start">
+            <div class="off-holiday" :class="[offOnholiday==='off'?'selected':'']" @click="changeHoliday('off')">去除节假日</div>
+            <div class="on-holiday" :class="[offOnholiday==='on'?'selected':'']" @click="changeHoliday('on')">不去除节假日</div>
+          </el-col>
+          <el-col :span="4" :offset="16" class="col-flex-end">
             <div class="bar-line" :class="[barOrLine==='line'?'active':'']" @click="changeBarOrLine('line')">折线图</div>
             <div class="bar-line" :class="[barOrLine==='bar'?'active':'']" @click="changeBarOrLine('bar')">柱状图</div>
           </el-col>
@@ -190,10 +207,17 @@
               <span class="repair-span">{{ scope.row.repairTimeAvgData.detail[1].label }}:{{ scope.row.repairTimeAvgData.detail[1].total }}</span>
             </template>
           </el-table-column>
+          <el-table-column prop="time" label="平均修复时长(去除节假日)">
+            <template slot-scope="scope">
+              <span class="table-repair-item4 repair-span">{{ scope.row.repairTimeAvgPurgeNhData.total }}</span>/
+              <span class="repair-span">{{ scope.row.repairTimeAvgPurgeNhData.detail[0].label }}:{{ scope.row.repairTimeAvgData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.repairTimeAvgPurgeNhData.detail[1].label }}:{{ scope.row.repairTimeAvgData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
         </el-table>
       </div>
       <div class="chart-item">
-        <h3>责任人</h3>
+        <h3>责任人分布</h3>
         <el-table
           :data="memberData"
           style="width: 100%;margin-bottom: 20px;"
@@ -227,6 +251,13 @@
               <span class="repair-span">{{ scope.row.repairTimeAvgData.detail[1].label }}:{{ scope.row.repairTimeAvgData.detail[1].total }}</span>
             </template>
           </el-table-column>
+          <el-table-column prop="time" label="平均修复时长(去除节假日)">
+            <template slot-scope="scope">
+              <span class="table-repair-item4 repair-span">{{ scope.row.repairTimeAvgPurgeNhData.total }}</span>/
+              <span class="repair-span">{{ scope.row.repairTimeAvgPurgeNhData.detail[0].label }}:{{ scope.row.repairTimeAvgData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.repairTimeAvgPurgeNhData.detail[1].label }}:{{ scope.row.repairTimeAvgData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
         </el-table>
       </div>
     </el-main>
@@ -237,7 +268,16 @@ import moment from 'moment'
 moment.locale('zh-cn')
 import { settingQueryBizModuleList } from '@/api/defectManage'
 import { teamQueryTeamInfoList } from '@/api/configure'
-import { getSummary, getDistributeData, getRepairTimeSumData, getRepairTimeDetailData, getModuleDistributeData, getMemberDistributeData } from '@/api/defectStatistics'
+import {
+  getSummary,
+  getDistributeData,
+  getRepairTimeSumData,
+  getRepairTimePurgeNhSumData,
+  getRepairTimeDetailData,
+  getRepairTimePurgeNhDetailData,
+  getModuleDistributeData,
+  getMemberDistributeData
+} from '@/api/defectStatistics'
 import normalEchart from '@/components/chart/normalEchart'
 export default {
   components: { normalEchart },
@@ -257,6 +297,7 @@ export default {
       defectStatus: 1, // 缺陷状态
       barOrPie: 'bar', // 柱状图or饼图
       barOrLine: 'line', // 柱状图or折线
+      offOnholiday: 'off', // 是否去除节假日
       defectStatusList: [ // 缺陷状态列表
         { code: 1, label: '缺陷状态' },
         { code: 2, label: '缺陷等级' },
@@ -266,8 +307,11 @@ export default {
         { code: 6, label: '发现阶段' },
         { code: 7, label: '缺陷类型' }
       ],
-      repairTimeList: [],
+      repairTimeList: [], // 修复时长头部列表
+      repairTimeListNoHoliday: [], // 去除节假日修复时长头部列表
       Summary: [], // 顶部数据
+      onHoliday: [], // 有假期数据
+      offHoliday: [], // 无假期数据
       chart1Data: null, // 图表1数据
       chart2Data: null, // 图表2数据
       moduleSort: 2, // 模块数据排序
@@ -288,8 +332,9 @@ export default {
     onSubmit() {
       this.getSummary()
       this.defectStatusChange()
-      this.getRepairTimeSumData()
+      this.getSumData()
       this.getRepairTimeDetailData()
+      this.getRepairTimePurgeNhDetailData()
       this.getModuleDistributeData()
       this.getMemberDistributeData()
     },
@@ -343,8 +388,9 @@ export default {
       }
       this.activeName === 'first' ? this.activeTab = 1 : this.activeTab = 2
       this.defectStatusChange()
-      this.getRepairTimeSumData()
+      this.getSumData()
       this.getRepairTimeDetailData()
+      this.getRepairTimePurgeNhDetailData()
       this.getModuleDistributeData()
       this.getMemberDistributeData()
     },
@@ -412,7 +458,7 @@ export default {
         }
       }
     },
-    async getRepairTimeSumData() { // 平均修复时长头部数据
+    async getSumData() { // 头部数据
       const moduleIds = this.defectForm.moduleIds
       const params = {
         startTime: this.stratAndEnd[0] || null,
@@ -422,9 +468,31 @@ export default {
         type: this.activeTab,
         moduleIds: moduleIds && moduleIds.length > 0 ? moduleIds : null
       }
+      this.getRepairTimeSumData(params)
+      this.getRepairTimePurgeNhSumData(params)
+    },
+    async getRepairTimeSumData(params) { // 平均修复时长头部数据
       const res = await getRepairTimeSumData(params)
       this.repairTimeList = res.data || []
     },
+    async getRepairTimePurgeNhSumData(params) { // 去除平均修复时长头部数据
+      const res = await getRepairTimePurgeNhSumData(params)
+      this.repairTimeListNoHoliday = res.data || []
+    },
+    async getRepairTimePurgeNhDetailData() { // 去除平均修复时长表数据
+      const moduleIds = this.defectForm.moduleIds
+      const params = {
+        startTime: this.stratAndEnd[0] || null,
+        endTime: this.stratAndEnd[1] || null,
+        bizId: Number(localStorage.getItem('bizId')),
+        teamIds: this.defectForm.team || null,
+        type: this.activeTab,
+        moduleIds: moduleIds && moduleIds.length > 0 ? moduleIds : null
+      }
+      const res = await getRepairTimePurgeNhDetailData(params)
+      this.offHoliday = res.data || []
+      this.changeHoliday(this.offOnholiday)
+    },
     async getRepairTimeDetailData() { // 平均修复时长表数据
       const moduleIds = this.defectForm.moduleIds
       const params = {
@@ -436,7 +504,12 @@ export default {
         moduleIds: moduleIds && moduleIds.length > 0 ? moduleIds : null
       }
       const res = await getRepairTimeDetailData(params)
-      this.chart2Data = res.data || []
+      this.onHoliday = res.data || []
+      this.changeHoliday(this.offOnholiday)
+    },
+    changeHoliday(type) {
+      this.offOnholiday = type
+      type === 'off' ? this.chart2Data = this.offHoliday : this.chart2Data = this.onHoliday
       this.changeBarOrLine(this.barOrLine)
     },
     changeBarOrLine(type) { // 柱状图折线图切换
@@ -668,7 +741,11 @@ export default {
     }
     .chart-item {
       padding: 0 20px;
-      .col-flex {
+      .col-flex-start {
+        display: flex;
+        justify-content: flex-start;
+      }
+      .col-flex-end {
         display: flex;
         justify-content: flex-end;
       }
@@ -744,6 +821,30 @@ export default {
         text-align: center;
         cursor: pointer;
       }
+      .off-holiday, .on-holiday{
+        width: 90px;
+        height: 30px;
+        font-size: 14px;
+        border:1px solid #D9D9D9;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        cursor: pointer;
+      }
+      .off-holiday {
+        border-right: none;
+        border-top-left-radius: 4px;
+        border-bottom-left-radius: 4px;
+      }
+      .on-holiday{
+        border-left: none;
+        border-top-right-radius: 4px;
+        border-bottom-right-radius: 4px;
+      }
+      .selected {
+        color:#4089FF;
+        border:1px solid #4089FF;
+      }
       .active {
         color: #ffffff;
         background: #50A6FF;
@@ -751,7 +852,7 @@ export default {
       .repair-span {
         padding-right: 5px;
       }
-      .table-repair-item1 {
+      .table-repair-item1,.table-repair-item4 {
         color:#4089FF;
       }
       .table-repair-item2 {

+ 28 - 3
src/views/workbench/person/index.vue

@@ -9,9 +9,9 @@
         <div class="top-tabs">
           <el-tabs v-model="activeName" @tab-click="handleClick">
             <el-tab-pane label="个人日程" name="1" />
-            <!-- <el-tab-pane label="概览" name="2" />
+            <el-tab-pane label="项目" name="2" />
             <el-tab-pane label="需求" name="3" />
-            <el-tab-pane label="任务" name="4" /> -->
+            <el-tab-pane label="任务" name="4" />
             <el-tab-pane label="缺陷" name="5" />
           </el-tabs>
         </div>
@@ -45,6 +45,21 @@
           </div>
         </section>
       </el-container>
+      <el-container v-if="activeName === '2'">
+        <section class="main-section">
+          <project-list :search-form="searchForm" type="person" />
+        </section>
+      </el-container>
+      <el-container v-if="activeName === '3'">
+        <section class="main-section">
+          <needs-list :search-form="searchForm" type="person" />
+        </section>
+      </el-container>
+      <el-container v-if="activeName === '4'">
+        <section class="main-section">
+          <task-list :search-form="searchForm" type="person" />
+        </section>
+      </el-container>
       <el-container v-show="activeName === '5'">
         <section class="main-section">
           <bugTableList ref="bugTableDialog" :name="'个人'" />
@@ -174,6 +189,9 @@ import calenderList from './components/calenderList'
 import MyFullCalendar from '@/views/workbench/person/components/myFullCalendar'
 import calenderDetail from '@/views/workbench/person/components/calenderDetail'
 import calendarDialog from '@/views/workbench/person/components/calendarFormDialog'
+import projectList from '@/views/workbench/team/components/projectList'
+import needsList from '@/views/workbench/team/components/needsList'
+import taskList from '@/views/workbench/team/components/taskList'
 import bugTableList from '@/views/workbench/bugTableList.vue'
 
 export default {
@@ -183,7 +201,10 @@ export default {
     modifySchedule,
     calenderList,
     calenderDetail,
-    bugTableList
+    bugTableList,
+    projectList,
+    needsList,
+    taskList
   },
   provide() {
     return {
@@ -215,6 +236,10 @@ export default {
         visible: false,
         data: null
       },
+      searchForm: { // 搜索条件
+        teamId: null,
+        bizId: null
+      },
       DialogTitle: '新建排期', // 排期弹框标题
       isDelete: false, // 删除排期操作
       teamAndMemberEnum: {},

+ 272 - 0
src/views/workbench/team/components/needsList.vue

@@ -0,0 +1,272 @@
+<template>
+  <div>
+    <div class="search-control">
+      <span :class="{'color-blue': status===null}" @click="setStatus(null)">全部</span>
+      <span :class="{'color-blue': status===1}" @click="setStatus(1)">进行中的需求</span>
+      <span :class="{'color-blue': status===0}" @click="setStatus(0)">未开始的需求</span>
+      <span :class="{'color-blue': status===2}" @click="setStatus(2)">已上线的需求</span>
+    </div>
+    <el-table
+      ref="planTable"
+      :data="needsDataList"
+      style="width: 100%;"
+      size="mini"
+      row-key="id"
+      :header-cell-style="{ color: 'rgb(74, 74, 74)', fontSize: '14px', fontWeight: '500'}"
+      :row-style="{ fontSize: '14px' }"
+      show-overflow-tooltip="true"
+      :header-row-style="{height: '50px'}"
+    >
+      <el-table-column label="优先级" prop="priority" width="100" sortable align="center">
+        <template slot-scope="scope" style="text-align: center;">
+          <span class="div_priority" :class="scope.row.priorityName">
+            {{ scope.row.priorityName }}
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="需求名称" min-width="250" align="left" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <div class="table-project-name" @click="needs_link(scope.row.id)">
+            <span class="id">{{ scope.row.requirementDisplayId }}</span>
+            <span class="name">{{ scope.row.name }}</span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="业务线" width="150" align="center" prop="bizName" show-overflow-tooltip />
+      <el-table-column label="状态" width="105" align="center">
+        <template slot-scope="scope">
+          <el-select
+            v-model="scope.row.status"
+            :class="['status'+scope.row.status]"
+            class="btns"
+            size="mini"
+            @change="changeStatus(scope.row)"
+          >
+            <el-option v-for="item in allStatus" :key="item.code" :label="item.msg" :value="item.code" />
+          </el-select>
+        </template>
+      </el-table-column>
+      <el-table-column label="需求来源" width="200" align="center" prop="sourceTypeName" show-overflow-tooltip />
+      <el-table-column label="所属项目" width="250" align="center" prop="belongingProjectName" show-overflow-tooltip />
+      <el-table-column label="跟版客户端" width="150" align="center" prop="referredClientTypeName" show-overflow-tooltip />
+      <el-table-column label="PM" width="150" align="center" show-overflow-tooltip>
+        <template v-if="scope.row.pm" slot-scope="scope">
+          <span>{{ scope.row.pm.name }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div align="right">
+      <el-pagination
+        :page-sizes="[15, 30, 45, total]"
+        :current-page.sync="pages.curIndex"
+        :page-size="pages.pageSize"
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import {
+  requirementSelfList,
+  requirementTeamList
+} from '@/api/workSchedule'
+import { showRequirementEnum, updateRequirementStatus } from '@/api/requirement'
+export default {
+  props: {
+    searchForm: {
+      type: Object,
+      default: () => {
+        return {
+          teamId: null,
+          bizId: null
+        }
+      },
+      required: true
+    },
+    type: {
+      type: String,
+      default: 'person',
+      required: true
+    }
+  },
+  data() {
+    return {
+      needsDataList: [], // 需求列表
+      allStatus: [], // 状态列表
+      pages: {
+        pageSize: 15,
+        curIndex: 1
+      },
+      total: 0,
+      status: null // 列表状态
+    }
+  },
+  watch: {
+    searchForm: {
+      handler(newV) {
+        this.getNeedsList()
+      },
+      deep: true
+    },
+    type: {
+      handler(newV) {
+        this.getNeedsList()
+      }
+    }
+  },
+  created() {
+    this.getTaskStatus()
+    this.getNeedsList()
+  },
+  methods: {
+    setStatus(val) {
+      this.status = val
+      this.pages.curIndex = 1
+      this.getNeedsList()
+    },
+    handleSizeChange(val) {
+      this.pages.pageSize = val
+      this.getNeedsList()
+    },
+    handleCurrentChange(val) {
+      this.pages.curIndex = val
+      this.getNeedsList()
+    },
+    async getTaskStatus() { // 获取需求的所有状态
+      const res = await showRequirementEnum()
+      if (res.code === 200) {
+        this.allStatus = res.data.requirementStatus
+      }
+    },
+    async getNeedsList() { // 获取需求列表
+      const params = {
+        teamSearchInfo: this.searchForm,
+        status: this.status,
+        pageInfoDO: this.pages
+      }
+      let res = null
+      if (this.type === 'person') {
+        res = await requirementSelfList(params)
+      } else if (this.type === 'team') {
+        res = await requirementTeamList(params)
+      }
+      if (res && res.code === 200) {
+        this.needsDataList = res.data
+        this.total = res.total
+      }
+    },
+    async changeStatus(e) { // 状态改变
+      const modifier = localStorage.getItem('username')
+      const res = await updateRequirementStatus({ id: e.id, status: e.status, modifier: modifier })
+      if (res.code === 200) {
+        this.$message({ message: '修改成功', type: 'success', offset: 150 })
+        this.getNeedsList()
+      }
+    },
+    needs_link(id) {
+      this.$router.push({ name: '需求详情', query: { id: id }})
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+@mixin setStatus($color) {
+  input {
+    color:$color;
+    border: 1px solid $color;
+  }
+  >>> .el-select__caret{
+    color:$color;
+  }
+  >>> .el-input__inner{
+    color:$color;
+    border-color: $color;
+  }
+  >>> .el-input__inner:focus {
+    border-color: $color;
+  }
+}
+>>>.el-row .el-col {
+  margin: 10px 0;
+}
+.color-blue {
+	color:#409EFF;
+}
+.P0 {
+  background-color: #F56C6C;
+}
+.P1 {
+  background-color: #FF8952;
+}
+.P2 {
+  background-color: #F5E300;
+}
+.P3 {
+  background-color: #7ED321;
+}
+.P4 {
+  background-color: #61D3B8;
+}
+.P5 {
+  background-color: #69B3FF;
+}
+.P6 {
+  background-color: #BDBDBD;
+}
+.status0 {
+  @include setStatus(#409EFF)
+}
+.status5 {
+  @include setStatus(#FF8952)
+}
+.status10 {
+  @include setStatus(#FF8952)
+}
+.status15 {
+  @include setStatus(#FF8952)
+}
+.status20 {
+  @include setStatus(#FF8952)
+}
+.status25 {
+  @include setStatus(#7ED321)
+}
+.search-control {
+	padding: 30px 17px 0;
+	color: #333B4A;
+	font-size: 14px;
+	span {
+		margin-right: 35px;
+		cursor: pointer;
+	}
+}
+.div_priority {
+  text-align: center;
+  color: #ffffff;
+  padding: inherit;
+  border-radius: 4px;
+  width: 40px;
+  display: inline-block;
+}
+.table-project-name {
+  cursor: pointer;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  .id {
+    color: #A7AEBC;
+    font-size: 10px;
+  }
+  .name {
+    font-size: 14px;
+    color: #666666;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}
+</style>

+ 259 - 0
src/views/workbench/team/components/projectList.vue

@@ -0,0 +1,259 @@
+<template>
+  <div>
+    <div class="search-control">
+      <span :class="{'color-blue': status===null}" @click="setStatus(null)">全部</span>
+      <span :class="{'color-blue': status===1}" @click="setStatus(1)">进行中的项目</span>
+      <span :class="{'color-blue': status===0}" @click="setStatus(0)">未开始的项目</span>
+      <span :class="{'color-blue': status===2}" @click="setStatus(2)">已完成的项目</span>
+    </div>
+    <el-table
+      ref="planTable"
+      :data="projectList"
+      style="width: 100%;"
+      size="mini"
+      row-key="id"
+      :header-cell-style="{ color: 'rgb(74, 74, 74)', fontSize: '14px', fontWeight: '500'}"
+      :row-style="{ fontSize: '14px' }"
+      show-overflow-tooltip="true"
+      :header-row-style="{height: '50px'}"
+    >
+      <el-table-column label="优先级" prop="priority" width="100" sortable align="center">
+        <template slot-scope="scope" style="text-align: center;">
+          <span class="div_priority" :class="scope.row.priorityStr">
+            {{ scope.row.priorityStr }}
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="项目名称" min-width="250" align="left" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <div class="table-project-name" @click="project_link(scope.row.id)">
+            <span class="id">PROJECT-{{ scope.row.id }}</span>
+            <span class="name">{{ scope.row.name }}</span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="业务线" width="250" align="center" prop="bizStr" show-overflow-tooltip />
+      <el-table-column label="状态" width="250" align="center">
+        <template slot-scope="scope">
+          <el-select
+            v-model="scope.row.status"
+            :class="['status'+scope.row.status]"
+            class="btns"
+            size="mini"
+            @change="changeStatus(scope.row)"
+          >
+            <el-option v-for="item in allStatus" :key="'status'+item.value" :label="item.name" :value="item.value" />
+          </el-select>
+        </template>
+      </el-table-column>
+      <el-table-column label="项目类型" width="200" align="center" prop="projectTypeStr" show-overflow-tooltip />
+      <el-table-column label="项目负责人" width="200" align="center" prop="projectOwnerZh" show-overflow-tooltip />
+    </el-table>
+    <div align="right">
+      <el-pagination
+        :page-sizes="[15, 30, 45, total]"
+        :current-page.sync="pages.curIndex"
+        :page-size="pages.pageSize"
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import {
+  projectSelfList,
+  projectTeamList
+} from '@/api/workSchedule'
+import { projectUpdate } from '@/api/projectIndex'
+export default {
+  props: {
+    searchForm: {
+      type: Object,
+      default: () => {
+        return {
+          teamId: null,
+          bizId: null
+        }
+      },
+      required: true
+    },
+    type: {
+      type: String,
+      default: 'person',
+      required: true
+    }
+  },
+  data() {
+    return {
+      projectList: [], // 需求列表
+      allStatus: [ // 状态列表
+        { value: 0, name: '未开始' },
+        { value: 1, name: '进行中' },
+        { value: 2, name: '已完成' }
+      ],
+      pages: {
+        pageSize: 15,
+        curIndex: 1
+      },
+      total: 0,
+      status: null // 列表状态
+    }
+  },
+  watch: {
+    searchForm: {
+      handler(newV) {
+        this.getProjectList()
+      },
+      deep: true
+    },
+    type: {
+      handler(newV) {
+        this.getProjectList()
+      }
+    }
+  },
+  created() {
+    this.getProjectList()
+  },
+  methods: {
+    setStatus(val) {
+      this.status = val
+      this.pages.curIndex = 1
+      this.getProjectList()
+    },
+    handleSizeChange(val) {
+      this.pages.pageSize = val
+      this.getProjectList()
+    },
+    handleCurrentChange(val) {
+      this.pages.curIndex = val
+      this.getProjectList()
+    },
+    async getProjectList() { // 获取需求列表
+      const params = {
+        teamSearchInfo: this.searchForm,
+        status: this.status,
+        pageInfoDO: this.pages
+      }
+      let res = null
+      if (this.type === 'person') {
+        res = await projectSelfList(params)
+      } else if (this.type === 'team') {
+        res = await projectTeamList(params)
+      }
+      if (res && res.code === 200) {
+        this.projectList = res.data
+        this.total = res.total
+      }
+    },
+    async changeStatus(e) { // 状态改变
+      const user = {
+        name: localStorage.getItem('realname'),
+        ename: localStorage.getItem('username'),
+        id: ''
+      }
+      const projectInfo = e
+      const res = await projectUpdate({ projectInfo, user })
+      if (res.code === 200) {
+        this.$message({ message: '修改成功', type: 'success', duration: 1000, offset: 150 })
+        this.getProjectList()
+      }
+    },
+    project_link(id) {
+      this.$router.push({ name: '项目详情', query: { id: id }})
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+@mixin setStatus($color) {
+  input {
+    color:$color;
+    border: 1px solid $color;
+  }
+  >>> .el-select__caret{
+    color:$color;
+  }
+  >>> .el-input__inner{
+    color:$color;
+    border-color: $color;
+  }
+  >>> .el-input__inner:focus {
+    border-color: $color;
+  }
+}
+>>>.el-row .el-col {
+  margin: 10px 0;
+}
+.color-blue {
+	color:#409EFF;
+}
+.P0 {
+  background-color: #F56C6C;
+}
+.P1 {
+  background-color: #FF8952;
+}
+.P2 {
+  background-color: #F5E300;
+}
+.P3 {
+  background-color: #7ED321;
+}
+.P4 {
+  background-color: #61D3B8;
+}
+.P5 {
+  background-color: #69B3FF;
+}
+.P6 {
+  background-color: #BDBDBD;
+}
+.status0 {
+  @include setStatus(#409EFF)
+}
+.status1 {
+  @include setStatus(#FF8952)
+}
+.status2 {
+  @include setStatus(#7ED321)
+}
+.search-control {
+	padding: 30px 17px 0;
+	color: #333B4A;
+	font-size: 14px;
+	span {
+		margin-right: 35px;
+		cursor: pointer;
+	}
+}
+.div_priority {
+  text-align: center;
+  color: #ffffff;
+  padding: inherit;
+  border-radius: 4px;
+  width: 40px;
+  display: inline-block;
+}
+.table-project-name {
+  cursor: pointer;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  .id {
+    color: #A7AEBC;
+    font-size: 10px;
+  }
+  .name {
+    font-size: 14px;
+    color: #666666;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}
+</style>

+ 582 - 0
src/views/workbench/team/components/taskList.vue

@@ -0,0 +1,582 @@
+<template>
+  <div>
+    <div class="search-control">
+      <span :class="{'color-blue': status===null}" @click="setStatus(null)">全部</span>
+      <span :class="{'color-blue': status===1}" @click="setStatus(1)">进行中的任务</span>
+      <span :class="{'color-blue': status===0}" @click="setStatus(0)">未开始的任务</span>
+      <span :class="{'color-blue': status===2}" @click="setStatus(2)">已上线的任务</span>
+    </div>
+    <el-row v-if="!showHeader" class="select-main" type="flex" align="center">
+      <el-col :span="1" class="flex-align-center">
+        <el-checkbox v-model="planChecked" class="plan-checked" @change="changeCheck" />
+      </el-col>
+      <el-col :span="3" class="item-checked">已选择<span style="color: #409EFF">{{ curcentChecked }}</span>个</el-col>
+      <el-col :span="1" class="item-line">|</el-col>
+      <el-col :span="2" class="item-click" @click.native="addSechedule()"><img :src="imgUrl">添加排期</el-col>
+      <el-col :span="2" class="item-click" @click.native="handlePlan('test')"><img :src="imgUrl">提测</el-col>
+      <el-col :span="2" class="item-click" @click.native="handlePlan('allow')"><img :src="imgUrl">准出</el-col>
+      <el-col :span="4" class="item-click" @click.native="handlePlan('daily')"><img :src="imgUrl">建立测试日报</el-col>
+      <el-col :span="4" class="item-click" @click.native="handlePlan('cancel')">取消选择</el-col>
+    </el-row>
+    <el-table
+      ref="planTable"
+      :data="all_task"
+      style="width: 100%;"
+      size="mini"
+      row-key="id"
+      :header-cell-style="{ color: 'rgb(74, 74, 74)', fontSize: '14px', fontWeight: '500'}"
+      :row-style="{ fontSize: '14px' }"
+      show-overflow-tooltip="true"
+      :show-header="showHeader"
+      :header-row-style="{height: '50px'}"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="优先级" prop="priority" width="90" sortable align="center">
+        <template slot-scope="scope" style="text-align: center;">
+          <span class="div_priority" :class="scope.row.priorityString">
+            {{ scope.row.priorityString }}
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="任务名称" min-width="250" align="left" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <div class="task-main">
+            <span class="task-id">TASK-{{ scope.row.id }}</span>
+            <span class="task-title" @click="link_task(scope.row.id)">{{ scope.row.name }}</span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="业务线" width="150" align="center" show-overflow-tooltip prop="bizIdString" />
+      <el-table-column label="状态" width="105" align="center">
+        <template slot-scope="scope">
+          <el-select
+            v-model="scope.row.status"
+            :class="'status'+scope.row.status"
+            class="btns"
+            size="mini"
+            @change="changeStatus(scope.row)"
+          >
+            <el-option v-for="item in allStatus" :key="item.code" :label="item.msg" :value="item.code" />
+          </el-select>
+        </template>
+      </el-table-column>
+      <el-table-column label="所属需求" width="250" align="center" show-overflow-tooltip>
+        <template slot-scope="scope">{{ scope.row.requireName }}</template>
+      </el-table-column>
+      <el-table-column label="开发负责人" width="100" align="center" show-overflow-tooltip>
+        <template slot-scope="scope">{{ scope.row.rdObject ? scope.row.rdObject.name : '' }}</template>
+      </el-table-column>
+      <el-table-column label="测试负责人" width="100" align="center" show-overflow-tooltip>
+        <template slot-scope="scope">{{ scope.row.qaObject ? scope.row.qaObject.name : '' }}</template>
+      </el-table-column>
+      <el-table-column label="任务进度" width="200" align="center">
+        <template slot-scope="scope">
+          <el-progress :percentage="Number(scope.row.rate && scope.row.rate.substring(0,4))" color="#409eff" />
+        </template>
+      </el-table-column>
+    </el-table>
+    <div align="right">
+      <el-pagination
+        :page-sizes="[15, 30, 45, total]"
+        :current-page.sync="pages.curIndex"
+        :page-size="pages.pageSize"
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+    <TestReport v-if="dialogTestReport" ref="TestReport" />
+    <DailyReport v-if="dialogDailyReport" ref="DailyReport" />
+    <ClientReport v-if="dialogClientReport" ref="ClientReport" />
+    <taskDialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskId.id" :status-name="taskId.statusString" @getList="get_allTask" />
+    <normal-dialog :show-dialog.sync="statusDialog" :title="'状态变更:已上线'" :width="'50%'" @confirm="confirmStatus()">
+      <div class="dialog-change-status">
+        <span>实际上线时间:</span>
+        <el-date-picker v-model="changeStatusDate" type="date" style="width:100%;" placeholder="选择日期" format="yyyy-MM-dd HH:mm:ss" />
+      </div>
+    </normal-dialog>
+    <!-- 批量排期 -->
+    <modify-schedule
+      v-if="visibleSchedule"
+      :visible.sync="visibleSchedule"
+      :select-task-list="selectTaskList"
+      title="新建排期"
+      @update="get_allTask()"
+    />
+  </div>
+</template>
+<script>
+import imgUrl from '@/assets/建立档案@2x.png'
+import '@/styles/PublicStyle/index.scss'
+import TestReport from '@/views/Platform/presentation/Templates/TestReport' // 提测
+import DailyReport from '@/views/Platform/presentation/Templates/DailyReport' // 日报
+import ClientReport from '@/views/Platform/presentation/Templates/ClientReport' // 准出
+import { taskSelfList, taskTeamList } from '@/api/workSchedule'
+import { taskUpdate } from '@/api/projectViewDetails'
+import { configShowTaskEnum } from '@/api/taskIndex'
+import modifySchedule from '@/views/projectManage/projectList/components/modifySchedule'
+import normalDialog from '@/components/dialog/normalDialog'
+import taskDialog from '@/views/projectManage/taskList/dialog/taskDialog' // 任务状态修改(已上线/已提测/已准出)
+export default {
+  components: {
+    normalDialog,
+    TestReport,
+    DailyReport,
+    ClientReport,
+    taskDialog,
+    modifySchedule
+  },
+  props: {
+    searchForm: {
+      type: Object,
+      default: () => {
+        return {
+          teamId: null,
+          bizId: null
+        }
+      },
+      required: true
+    },
+    type: {
+      type: String,
+      default: 'person',
+      required: true
+    }
+  },
+  data() {
+    return {
+      imgUrl: imgUrl,
+      showTaskDialog: false, // 状态弹窗
+      all_task: [], // 任务列表
+      allStatus: [], // 任务所有状态
+      taskScheduleEvent: [], // 排期类型
+      showHeader: true, // 任务列表的表头是否显示
+      curcentList: [], // 当前已选择的列表
+      curcentChecked: 0, // 当前已选择的数量
+      planChecked: false,
+      planHandleType: '', // 任务列表操作类型
+      dialogTestReport: false, // 提测
+      dialogDailyReport: false, // 日报
+      dialogClientReport: false, // 准出
+      statusDialog: false, // 修改状态弹框
+      changeStatusDate: null, // 状态改变时间
+      nowChangeTask: null, // 当前正在改变的任务对象
+      taskId: '', // 将要修改状态的任务id
+      visibleSchedule: false, // 排期弹框
+      selectTaskList: [], // 已选任务的id
+      total: 0,
+      status: null, // 列表状态
+      pages: {
+        pageSize: 15,
+        curIndex: 1
+      }
+    }
+  },
+  watch: {
+    searchForm: {
+      handler(newV) {
+        this.get_allTask()
+      },
+      deep: true
+    },
+    type: {
+      handler(newV) {
+        this.get_allTask()
+      }
+    }
+  },
+  created() {
+    this.getTaskStatus()
+    this.get_allTask()
+  },
+  methods: {
+    setStatus(val) {
+      this.status = val
+      this.pages.curIndex = 1
+      this.get_allTask()
+    },
+    handleSizeChange(val) {
+      this.pageSize = val
+      this.get_allTask()
+    },
+    handleCurrentChange(val) {
+      this.curIndex = val
+      this.get_allTask()
+    },
+    async get_allTask() { // 获取全部任务
+      const params = {
+        teamSearchInfo: this.searchForm,
+        status: this.status,
+        pageInfoDO: this.pages
+      }
+      let res = null
+      if (this.type === 'person') {
+        res = await taskSelfList(params)
+      } else if (this.type === 'team') {
+        res = await taskTeamList(params)
+      }
+      if (res && res.code === 200) {
+        this.all_task = res.data
+        this.total = res.total
+      }
+    },
+    async getTaskStatus() { // 获取任务状态列表
+      const res = await configShowTaskEnum()
+      if (res.code === 200) {
+        this.allStatus = res.data.taskStatus
+        this.taskScheduleEvent = res.data.taskScheduleEvent || []
+      }
+    },
+    changeCheck(val) {
+      if (val) {
+        this.all_task.forEach(row => {
+          this.$refs.planTable.toggleRowSelection(row, true)
+        })
+      } else {
+        this.$refs.planTable.clearSelection()
+      }
+    },
+    async changeStatus(e) { // 状态改变
+      if (e.status === 2 || e.status === 4 || e.status === 5) {
+        this.taskId = e
+        this.allStatus.map(item => {
+          item.code === e.status ? this.taskId.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.$message({ message: resTask.msg, type: 'success', offset: 150 })
+          this.get_allTask()
+        }
+      }
+    },
+    async confirmStatus() { // 确认更改状态
+      const user = { name: localStorage.getItem('username'), ename: localStorage.getItem('realname'), id: '' }
+      const taskInfoDO = this.nowChangeTask
+      taskInfoDO.onlineRealTime = this.changeStatusDate
+      const resTask = await taskUpdate({ taskInfoDO, user })
+      if (resTask.code === 200) {
+        this.$message({ message: resTask.msg, type: 'success', offset: 150 })
+      }
+    },
+    handleSelectionChange(val) { // 任务列表删选操作
+      val.length > 0 ? this.showHeader = false : this.showHeader = true
+      this.curcentChecked = val.length
+      this.curcentList = val
+      if (val.length === this.all_task.length) {
+        this.planChecked = true
+      }
+    },
+    handlePlan(type) { // 任务列表操作
+      this.planHandleType = type
+      switch (type) {
+        case 'test':
+          this.filtrateTest()
+          break
+        case 'allow':
+          this.filtrateAllow()
+          break
+        case 'daily':
+          this.filtrateDaily()
+          break
+        case 'cancel':
+          this.$refs.planTable.clearSelection()
+          break
+      }
+    },
+    addSechedule() { // 添加排期
+      this.visibleSchedule = true
+      this.selectTaskList = this.curcentList
+    },
+    filtrateTest() { // 提测筛选
+      this.dialogTestReport = true
+      this.$nextTick(() => {
+        this.$refs.TestReport.init(7, this.curcentList.map(item => { return item.id }))
+      })
+    },
+    filtrateAllow() { // 准出筛选
+      this.dialogClientReport = true
+      this.$nextTick(() => {
+        this.$refs.ClientReport.init(7, this.curcentList.map(item => { return item.id }))
+      })
+    },
+    filtrateDaily() { // 建立日报
+      this.dialogDailyReport = true
+      this.$nextTick(() => {
+        this.$refs.DailyReport.init(7, this.curcentList.map(item => { return item.id }))
+      })
+    },
+    link_task(id) { // 跳转到任务详情页
+      this.$router.push({ name: '任务详情', query: { id: id }})
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+@mixin setStatus($color) {
+  input {
+    color:$color;
+    border: 1px solid $color;
+  }
+  >>> .el-select__caret{
+    color:$color;
+  }
+  >>> .el-input__inner{
+    color:$color;
+    border-color: $color;
+  }
+  >>> .el-input__inner:focus {
+    border-color: $color;
+  }
+}
+>>>.el-row .el-col {
+  margin: 10px 0;
+}
+.task-main {
+  display: flex;
+  flex-direction: column;
+  .task-title {
+    cursor: pointer;
+    color: #666666;
+    font-size: 14px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+  .task-id {
+    color: #A7AEBC;
+    font-size: 10px;
+  }
+}
+.color-blue {
+	color:#409EFF;
+}
+.P0 {
+  background-color: #F56C6C;
+}
+.P1 {
+  background-color: #FF8952;
+}
+.P2 {
+  background-color: #F5E300;
+}
+.P3 {
+  background-color: #7ED321;
+}
+.P4 {
+  background-color: #61D3B8;
+}
+.P5 {
+  background-color: #69B3FF;
+}
+.P6 {
+  background-color: #BDBDBD;
+}
+.status0 {
+  @include setStatus(#409EFF)
+}
+.status1, .status2, .status3, .status4{
+  @include setStatus(#FF8952)
+}
+.status5 {
+  @include setStatus(#7ED321)
+}
+.search-control {
+	padding: 30px 17px 0;
+	color: #333B4A;
+	font-size: 14px;
+	span {
+		margin-right: 35px;
+		cursor: pointer;
+	}
+}
+.expand i {
+  border:1px solid #DCDFE6;
+}
+>>>.el-table__expand-icon{
+  font-size: 14px;
+  .el-icon{
+    margin: 0;
+    transform: translate(-50%, -50%);
+    border:1px solid #DCDFE6;
+  }
+}
+>>>.el-table__expand-icon .el-icon-arrow-right::before{
+  content: "\E6D9";
+}
+>>>.el-table__expand-icon--expanded .el-icon-arrow-right::before{
+  content: "\E6D8";
+}
+>>>.el-table__expand-icon--expanded {
+  transform: rotate(180deg);
+}
+>>>.el-table__expanded-cell {
+  background-color: #FFFFFF;
+  padding: 0;
+}
+>>>.el-table__expanded-cell:hover {
+  background-color: #FFFFFF !important;
+}
+.div_priority {
+  text-align: center;
+  color: #ffffff;
+  padding: inherit;
+  border-radius: 4px;
+  width: 40px;
+  display: inline-block;
+}
+.plan-checked {
+  padding-left: 21px;
+}
+.select-main {
+  height: 50px;
+  border-bottom: 1px solid #DCDFE6;
+  .flex-align-center {
+    display: flex;
+    align-items: center;
+  }
+  .item-checked {
+    width: auto;
+    margin-right: 28px;
+    color: #606266;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: left;
+    cursor: pointer;
+  }
+  .item-click,.item-line{
+    margin: 0;
+    width: auto;
+    color: #666666;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+    margin-right: 28px;
+    img {
+      height: 13.5px;
+      widows: 13.5px;
+      margin-right: 5px;
+    }
+  }
+  .item-line {
+    color:rgba(102,102,102,0.6);
+  }
+  .cancel {
+    position: absolute;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+  }
+}
+.descr {
+  display: flex;
+  justify-content: flex-start;
+}
+.planList >>> .el-table th>.cell {
+  padding-left: 14px;
+  padding-right: 14px;
+}
+.dialog-change-status {
+  margin: 2% 3%;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  white-space:nowrap;
+}
+</style>
+<style lang="scss">
+.btns .el-input--suffix .el-input__inner {
+  padding-right: 10px;
+  padding-left: 10px;
+  width: 73px;
+}
+.item{
+  /deep/ input {
+    color: rgb(126, 211, 33);
+    border: 1px solid rgb(126, 211, 33);
+     border-color: rgb(126, 211, 33) !important;
+         font-weight: 900;
+  }
+  /deep/ .el-input__suffix {
+    color: rgb(126, 211, 33) !important;
+    right: 1px;
+  }
+  /deep/ .el-select__caret {
+    color: rgb(126, 211, 33) !important;
+  }
+}
+.item1 {
+  /deep/ input {
+    color: rgb(255, 204, 102);
+     border: 1px solid rgb(255, 204, 102);
+     border-color: rgb(255, 204, 102) !important;
+         font-weight: 900;
+  }
+  /deep/ .el-input__suffix {
+    color: rgb(255, 204, 102) !important;
+    right: 1px;
+  }
+  /deep/ .el-select__caret {
+    color: rgb(255, 204, 102) !important;
+  }
+}
+.item2 {
+  /deep/ input {
+    color: rgb(245, 108, 108);
+    border: 1px solid rgb(245, 108, 108);
+    border-color: rgb(245, 108, 108) !important;
+        font-weight: 900;
+  }
+   /deep/ .el-input__suffix {
+    color: rgb(245, 108, 108) !important;
+    right: 1px;
+  }
+  /deep/ .el-select__caret {
+   color: rgb(245, 108, 108) !important;
+  }
+}
+.item3 {
+  /deep/ input {
+    color: #D675F0;
+    border: 1px solid #D675F0;
+    border-color: #D675F0 !important;
+        font-weight: 900;
+  }
+    /deep/ .el-input__suffix {
+    color: #D675F0 !important;
+    right: 1px;
+  }
+   /deep/ .el-select__caret {
+   color: #D675F0 !important;
+  }
+}
+.item-color {
+  /deep/ input {
+    color: rgb(106, 180, 255);
+    border: 1px solid rgb(106, 180, 255);
+    border-color: rgb(106, 180, 255) !important;
+        font-weight: 900;
+  }
+    /deep/ .el-input__suffix {
+    color: rgb(106, 180, 255) !important;
+    right: 1px;
+  }
+   /deep/ .el-select__caret {
+   color: rgb(106, 180, 255) !important;
+  }
+}
+</style>

+ 26 - 5
src/views/workbench/team/index.vue

@@ -31,15 +31,15 @@
       <div class="top-tabs">
         <el-tabs v-model="activeName" @tab-click="handleClick">
           <el-tab-pane label="团队日程" name="1" />
-          <!-- <el-tab-pane label="概览" name="2" />
+          <el-tab-pane label="项目" name="2" />
           <el-tab-pane label="需求" name="3" />
-          <el-tab-pane label="任务" name="4" /> -->
+          <el-tab-pane label="任务" name="4" />
           <el-tab-pane label="缺陷" name="5" />
         </el-tabs>
       </div>
     </el-header>
     <!-- 顶部导航栏 -->
-    <el-container v-show="activeName === '1'">
+    <el-container v-if="activeName === '1'">
       <section class="main-section">
         <el-tabs v-model="activeSchedule" class="tabs-change">
           <el-tab-pane label="日历视图" name="1" />
@@ -80,6 +80,21 @@
         </div>
       </section>
     </el-container>
+    <el-container v-if="activeName === '2'">
+      <section class="main-section">
+        <project-list :search-form="searchForm" type="team" />
+      </section>
+    </el-container>
+    <el-container v-if="activeName === '3'">
+      <section class="main-section">
+        <needs-list :search-form="searchForm" type="team" />
+      </section>
+    </el-container>
+    <el-container v-if="activeName === '4'">
+      <section class="main-section">
+        <task-list :search-form="searchForm" type="team" />
+      </section>
+    </el-container>
     <el-container v-show="activeName === '5'">
       <section class="main-section">
         <bugTableList ref="bugTableDialog" :name="'团队'" :team-id="searchForm.teamId" :biz-id="searchForm.bizId" />
@@ -123,6 +138,9 @@ import ganntViews from './components/ganntViews'
 import MyFullCalendar from '@/views/workbench/person/components/myFullCalendar'
 import calenderDetail from '@/views/workbench/person/components/calenderDetail'
 import calendarDialog from '@/views/workbench/person/components/calendarFormDialog'
+import projectList from '@/views/workbench/team/components/projectList'
+import needsList from '@/views/workbench/team/components/needsList'
+import taskList from '@/views/workbench/team/components/taskList'
 import bugTableList from '@/views/workbench/bugTableList.vue'
 
 export default {
@@ -132,7 +150,10 @@ export default {
     calenderDetail,
     calendarDialog,
     modifySchedule,
-    bugTableList
+    bugTableList,
+    projectList,
+    needsList,
+    taskList
   },
   data() {
     return {
@@ -163,7 +184,7 @@ export default {
       showDetail: false, // 显示详情弹框
       nowDetailData: {}, // 当前选中日程的数据
       detailXY: [0, 0], // 详情弹框位置
-      origin: [0, 1],
+      origin: [0, 1], // 日程,排期
       createSchedule: { // 新建日程
         visible: false,
         data: null