reedliuqing_i преди 5 години
родител
ревизия
eedac40326

+ 2 - 1
package.json

@@ -15,10 +15,11 @@
     "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
   },
   "dependencies": {
+    "animate.css": "^3.7.2",
     "axios": "0.18.0",
     "dayjs": "^1.8.17",
     "echarts": "^4.2.1",
-    "element-ui": "^2.9.1",
+    "element-ui": "^2.13.0",
     "file-saver": "^2.0.2",
     "html2canvas": "^1.0.0-rc.3",
     "jodit": "^3.2.58",

+ 58 - 1
src/api/requirement.js

@@ -33,6 +33,30 @@ export function createRequirement(data) {
   })
 }
 
+export function updateRequirement(data) {
+  return request({
+    url: requestIp + '/requirement/updateRequirement',
+    method: 'post',
+    data
+  })
+}
+
+export function updateRequirementStatus(data) {
+  return request({
+    url: requestIp + '/requirement/updateRequirementStatus',
+    method: 'post',
+    data
+  })
+}
+
+export function deleteRequirement(data) {
+  return request({
+    url: requestIp + '/requirement/deleteRequirementById',
+    method: 'post',
+    data
+  })
+}
+
 export function getRequirementById(data) {
   return request({
     url: requestIp + '/requirement/queryOneRequirementDetail',
@@ -41,10 +65,43 @@ export function getRequirementById(data) {
   })
 }
 
-export function getRequirementStatistics(data) {
+export function getTaskStatusMapInfo(data) {
   return request({
     url: requestIp + '/task/getTaskStatusMapInfo',
     method: 'post',
     data
   })
 }
+
+export function getBugStatusMapInfo(data) {
+  return request({
+    url: requestIp + '/bug/getBugStatusMapInfo',
+    method: 'post',
+    data
+  })
+}
+
+export function getTaskByRequireId(data) {
+  return request({
+    url: requestIp + '/task/list',
+    method: 'post',
+    data
+  })
+}
+
+export function getCommentList(data) {
+  return request({
+    url: requestIp + '/comment/list',
+    method: 'post',
+    data
+  })
+}
+
+export function addComment(data) {
+  return request({
+    url: requestIp + '/comment/create',
+    method: 'post',
+    data
+  })
+}
+

+ 1 - 1
src/components/chart/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :id="chartId" style="width: 420px;height: 160px" />
+  <div :id="chartId" style="width: 100%;height: 160px" />
 </template>
 
 <script>

+ 2 - 0
src/main.js

@@ -17,6 +17,8 @@ import '@/icons' // icon
 import htmlToPdf from '@/utils/htmlToPdf'
 Vue.use(htmlToPdf)
 
+import animated from 'animate.css'
+Vue.use(animated)
 /**
  * If you don't want to use mock-server
  * you want to use MockJs for mock api

+ 6 - 0
src/router/index.js

@@ -158,6 +158,12 @@ export const constantRoutes = [
             props: true,
             component: () => import('@/views/projectManage/requirement/details/index.vue'),
             meta: { title: '需求详情' }
+          },
+          {
+            path: 'version',
+            name: '版本',
+            component: () => import('@/views/projectManage/version/list/index.vue'),
+            meta: { title: '版本' }
           }
         ]
       },

+ 397 - 105
src/views/projectManage/requirement/details/index.vue

@@ -1,91 +1,233 @@
 <template>
   <el-container>
-    <el-header style="margin: 2%">
+    <el-header style="margin: 2%;" class="layout_header">
       <div>
-        <span>{{ '项目名称:' }}</span>
+        <span style="font-size: 16px;color:#333333">{{ '需求:' + requirement.name }}</span>
+        <el-dropdown
+          size="mini"
+          split-button
+          style="margin-left: 10px"
+          @command="updateRequirementStatus"
+        >
+          <span class="el-dropdown-link">{{ getStatusName() }}</span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item
+              v-for="(item,index) in searchInfo.requirementStatus"
+              :key="index"
+              :command="item"
+            >{{ item.msg }}</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
         <div style="display: inline-block;float: right">
-          <el-dropdown size="mini" split-button @command="handleCommand">
-            <span class="el-dropdown-link">{{ status.msg }}</span>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item
-                v-for="(item,index) in searchInfo.requirementStatus"
-                :key="index"
-                :command="item"
-              >{{ item.msg }}</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
           <el-button size="mini" style="margin-left: 10px" @click="deleteRequirement">删除需求</el-button>
-          <el-button type="primary" size="mini" @click="createRequirement">新建</el-button>
+          <el-button type="primary" size="mini" @click="createTask">新建</el-button>
         </div>
       </div>
     </el-header>
     <el-container>
-      <el-aside width="52%" style="margin: 0% 2% 2% 2%;padding: 1%">
+      <el-aside width="52%" style="margin: 0% 2% 2% 2%;" class="layout_aside">
         <div style="font-size: 18px">
           <b style="color: #409EFF">I</b>数据统计
         </div>
-        <div style="margin: 1%;padding: 0">
-          <div style="border-bottom: 1px solid #444">
-            <div
-              style="display: inline-block;width: 30%;text-align: center;margin: 0;border-right: 2px solid #444"
-            >
-              <div style="font-size: 16px;margin-top: 26px">任务数量</div>
-              <div style="font-size: 72px">{{ statistics.totalCount }}</div>
-              <div
-                style="font-size: 14px;color: rgba(245,108,108,1);margin-bottom: 16px"
-              >{{ '已延期0天' }}</div>
-            </div>
-            <div style="display: inline-block;width: 69%;text-align: center;">
+        <div v-loading="loading.task || loading.bug" class="div_statistics" style="margin: 2%">
+          <el-container style="border-bottom: 1px solid #D8D8D8">
+            <el-aside width="30%" style="border-right: 2px solid #BBBBBB">
+              <div style="width:100%;text-align: center;">
+                <div style="font-size: 16px;margin-top: 26px">任务数量</div>
+                <div style="font-size: 72px">{{ statistics.task.totalCount }}</div>
+                <div
+                  style="font-size: 14px;color: rgba(245,108,108,1);margin-bottom: 16px"
+                >{{ '已延期'+statistics.task.delayCount+'个' }}</div>
+              </div>
+            </el-aside>
+            <el-aside width="70%">
               <requirement-chart
                 :chart-id="'taskCount'"
                 :option="taskOption"
-                style="position: absolute;top: 27%"
+                style="position: relative;bottom: 30px"
               />
-            </div>
-          </div>
-          <div>
-            <div
-              style="display: inline-block;width: 30%;text-align: center;margin: 0;border-right: 2px solid #444"
-            >
-              <div style="font-size: 16px;margin-top: 26px">任务数量</div>
-              <div style="font-size: 72px">{{ statistics.totalCount }}</div>
-              <div
-                style="font-size: 14px;color: rgba(245,108,108,1);margin-bottom: 16px"
-              >{{ '已延期0天' }}</div>
-            </div>
-            <div style="display: inline-block;width: 69%;text-align: center;">
+            </el-aside>
+          </el-container>
+          <el-container>
+            <el-aside width="30%" style="border-right: 2px solid #BBBBBB">
+              <div style="width:100%;text-align: center;">
+                <div style="font-size: 16px;margin-top: 26px">任务数量</div>
+                <div style="font-size: 72px">{{ statistics.bug.totalCount }}</div>
+                <div
+                  style="font-size: 14px;color: rgba(245,108,108,1);margin-bottom: 16px"
+                >{{ '以后修复'+statistics.bug.fixInFutureCount+'个' }}</div>
+              </div>
+            </el-aside>
+            <el-aside width="70%">
               <requirement-chart
                 :chart-id="'bugCount'"
                 :option="bugOption"
-                style="position: absolute;top: 48%"
+                style="position: relative;bottom: 30px"
               />
-            </div>
-          </div>
+            </el-aside>
+          </el-container>
         </div>
       </el-aside>
-      <el-aside width="42%" style="margin: 0% 2% 2% 0;padding: 1%">
+      <el-aside width="42%" style="margin: 0% 2% 2% 0;" class="layout_aside">
         <div style="font-size: 18px">
           <b style="color: #409EFF;">I</b>基础信息
         </div>
-        <div style="line-height: 38px;margin: 2%">
-          <div><div class="div_label">归属的项目:</div><div class="div_content">{{ requirement.belongingProjectName }}</div><el-button style="float: right" type="primary" size="mini">修改</el-button></div>
-          <div><div class="div_label">业务线:</div><div class="div_content">{{ requirement.bizName }}</div></div>
-          <div><div class="div_label">优先级:</div><div class="div_content">{{ requirement.priorityName }}</div></div>
-          <div><div class="div_label">需求来源:</div><div class="div_content">{{ requirement.sourceTypeName }}</div></div>
-          <div><div class="div_label">PM:</div><div class="div_content">{{ getPmName() }}</div></div>
-          <div><div class="div_label">PRD链接:</div><div class="div_content">{{ requirement.mrdUrl }}</div></div>
-          <div><div class="div_label">是否跟版:</div><div class="div_content">{{ requirement.dependOnRelease? '是':'否' }}</div></div>
-          <div v-if="requirement.dependOnRelease"><div class="div_label">涉及的客户端:</div><div class="div_content">{{ getClientTypeName() }}</div></div>
+        <div
+          v-loading="loading.info"
+          style="font-size: 14px;color: #666666;margin-top: 4%"
+          class="div_requirment_info"
+        >
+          <el-row>
+            <el-col :span="8">归属的项目:</el-col>
+            <el-col :span="16">
+              <div
+                style="display: inline-block;color: #409EFF"
+              >{{ requirement.belongingProjectName }}</div>
+              <el-button
+                style="float: right"
+                type="primary"
+                size="mini"
+                @click="updateDialogVisible = true"
+              >修改</el-button>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">业务线:</el-col>
+            <el-col :span="16">{{ requirement.bizName }}</el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">优先级:</el-col>
+            <el-col :span="16">{{ requirement.priorityName }}</el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">需求来源:</el-col>
+            <el-col :span="16">{{ requirement.sourceTypeName }}</el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">PM:</el-col>
+            <el-col :span="16">{{ getPmName() }}</el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">PRD链接:</el-col>
+            <el-col :span="16">
+              <el-link type="primary" :href="requirement.mrdUrl">{{ requirement.mrdUrl }}</el-link>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="8">是否跟版:</el-col>
+            <el-col :span="16">{{ requirement.dependOnRelease? '是':'否' }}</el-col>
+          </el-row>
+          <el-row v-if="requirement.dependOnRelease">
+            <el-col :span="8">涉及的客户端:</el-col>
+            <el-col :span="16">
+              {{ getAppClientName() }}
+            </el-col>
+          </el-row>
         </div>
       </el-aside>
     </el-container>
-    <el-main style="margin: 0 2% 0 2%">
-      <div style="font-size: 18px">
+    <el-main id="requirement_details" style="margin: 0 2% 0 2%;" class="layout_main">
+      <div style="font-size: 18px;margin-bottom: 2%">
         <b style="color: #409EFF;">I</b>任务
       </div>
-
+      <el-radio-group v-model="radio" size="mini" style="float: right;margin-bottom: 1%">
+        <el-radio-button label="列表" />
+        <el-radio-button label="甘特图" />
+      </el-radio-group>
+      <el-table
+        v-if="radio === '列表'"
+        v-loading="loading.table"
+        :data="tableData"
+        style="width: 100%;"
+        highlight-current-row
+        :header-cell-style="{ background: '#6AB4FF', color: '#FFFFFF',textAlign: 'center'}"
+        :cell-style="{textAlign: 'center'}"
+        @current-change="handleCurrentRowChange"
+      >
+        <el-table-column prop="name" label="任务名" min-width="20%" />
+        <el-table-column prop="beginTime" label="排期" min-width="15%">
+          <template
+            v-slot="scope"
+          >{{ scope.row.beginTime.substring(2,10).replace(/-/g,'/') + ' ~ ' +scope.row.endTime.substring(2,10).replace(/-/g,'/') }}</template>
+        </el-table-column>
+        <el-table-column prop="statusString" label="状态" min-width="10%">
+          <template v-slot="scope">
+            <div style="color: #FF9500">{{ scope.row.statusString }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="stageString" label="任务健康状态" min-width="12%">
+          <template v-slot="scope">{{ scope.row.stageString }}</template>
+        </el-table-column>
+        <el-table-column prop="rate" label="任务进展" min-width="15%">
+          <template v-slot="scope">
+            <el-progress :percentage="Number(scope.row.rate.replace(/%/g,''))" />
+          </template>
+        </el-table-column>
+        <el-table-column prop="rdObject" label="开发负责人" min-width="10%">
+          <template v-slot="scope">{{ scope.row.rdObject?scope.row.rdObject.name:'空' }}</template>
+        </el-table-column>
+        <el-table-column prop="qaObject" label="测试负责人" min-width="10%">
+          <template v-slot="scope">{{ scope.row.qaObject?scope.row.qaObject.name:'空' }}</template>
+        </el-table-column>
+        <el-table-column prop="rdList" label="开发" min-width="10%">
+          <template v-slot="scope">{{ getQaOrRdNameList(scope.row.rdList) }}</template>
+        </el-table-column>
+        <el-table-column prop="qaList" label="测试" min-width="10%">
+          <template v-slot="scope">{{ getQaOrRdNameList(scope.row.qaList) }}</template>
+        </el-table-column>
+      </el-table>
+      <el-container style="margin-top: 2%;font-size: 14px;color: #333333">
+        <el-aside width="30%">
+          <div>预期上线版本:123</div>
+          <div>
+            <span style="visibility: hidden">预期上线版本:</span>123
+          </div>
+        </el-aside>
+        <el-aside width="70%">
+          <div>实际上线版本:123</div>
+          <div>
+            <span style="visibility: hidden">实际上线版本:</span>123
+          </div>
+        </el-aside>
+      </el-container>
     </el-main>
-    <el-footer style="margin: 2%">123</el-footer>
+    <el-main style="margin: 2%;" class="layout_main">
+      <div style="font-size: 18px;margin-bottom: 2%">
+        <b style="color: #409EFF;">I</b>评论
+      </div>
+      <div>
+        <div v-for="(item,index) in comments" :key="index" class="animated bounceInRight">
+          <div
+            style="font-size:14px;color:#333B4A;display: inline-block;"
+          >{{ item.commentInfo.name }}</div>
+          <div
+            style="margin-left:20px;display: inline-block;color: #9B9B9B;font-size:12px"
+          >{{ item.commentInfo.gmtCreater }}</div>
+          <p
+            style="font-size:14px;color:#333B4A;margin-top: 10px;white-space: pre-line;"
+          >{{ item.commentInfo.content }}</p>
+          <br>
+        </div>
+        <el-input
+          v-model="commentContent"
+          type="textarea"
+          placeholder="请输入评论内容"
+          maxlength="300"
+          show-word-limit
+          :autosize="{ minRows: 3, maxRows: 5}"
+          style="margin: 2% 0;"
+        />
+        <el-button type="primary" size="small" style="float: right" @click="addComment">发表评论</el-button>
+      </div>
+    </el-main>
+    <requirement-update
+      title="编辑需求"
+      :data="requirement"
+      :visible="updateDialogVisible"
+      :info="searchInfo"
+      @cancel="updateDialogVisible=false"
+      @confirm="getRequirementById();updateDialogVisible=false"
+    />
   </el-container>
 </template>
 
@@ -93,13 +235,21 @@
 import {
   getRequirementById,
   getSearchInfo,
-  getRequirementStatistics
+  getTaskStatusMapInfo,
+  getBugStatusMapInfo,
+  getTaskByRequireId,
+  deleteRequirement,
+  updateRequirementStatus,
+  getCommentList,
+  addComment
 } from '@/api/requirement.js'
 import RequirementChart from '@/components/chart/index.vue'
+import RequirementUpdate from '@/views/projectManage/requirement/list/create.vue'
 
 export default {
   components: {
-    RequirementChart
+    RequirementChart,
+    RequirementUpdate
   },
   props: {
     id: {
@@ -109,14 +259,34 @@ export default {
   },
   data() {
     return {
-      form: null,
-      statistics: {},
+      loading: {
+        table: true,
+        info: true,
+        task: true,
+        bug: true
+      },
+      radio: '列表',
+      updateDialogVisible: false,
+      tableData: null,
+      statistics: {
+        task: {
+          totalCount: 0,
+          delayCount: 0
+        },
+        bug: {
+          totalCount: 0,
+          fixInFutureCount: 0
+        }
+      },
       belongingProject: { msg: '不存在' },
       status: {},
-      requirement: {},
+      requirement: {
+        name: ''
+      },
       projectOb: {},
       bizTypeOb: {},
-      clientTypeOb: {},
+      appClientOb: {},
+      requirementStatusOb: {},
       searchInfo: {
         belongingProject: [],
         sourceType: [],
@@ -183,7 +353,7 @@ export default {
               show: true,
               position: 'inside'
             },
-            data: [4, 12, 6, 20]
+            data: []
           }
         ]
       },
@@ -246,35 +416,100 @@ export default {
               show: true,
               position: 'inside'
             },
-            data: [4, 12, 6, 20, 50]
+            data: []
           }
         ]
-      }
+      },
+      comments: [],
+      commentContent: null
     }
   },
-  created() {
+  mounted() {
     this.getSearchInfo().then(res => {
+      this.getRequirementById()
+    })
+    this.getTaskStatusMapInfo()
+    this.getBugStatusMapInfo()
+    this.getTaskByRequireId()
+    this.getCommentList()
+  },
+  methods: {
+    getCommentList() {
+      getCommentList({ type: 4, joinId: this.id }).then(res => {
+        this.comments = res.data
+      })
+    },
+    addComment() {
+      if (!this.commentContent) {
+        this.$message.warning('评论不能为空')
+        return
+      }
+      const user = localStorage.getItem('username')
+      addComment({
+        commentInfo: { joinId: this.id, type: 4, content: this.commentContent },
+        user: { ename: user }
+      }).then(res => {
+        if (res.code === 200) {
+          this.getCommentList()
+        } else {
+          this.$message.warning(res.msg)
+        }
+      })
+    },
+    getStatusName() {
+      return this.requirementStatusOb[this.requirement.status]
+    },
+    getRequirementById() {
+      this.loading.info = true
       getRequirementById({
         id: this.id
       }).then(res => {
         this.requirement = res.data
-        for (const i in this.searchInfo.requirementStatus) {
-          if (
-            this.requirement.status ===
-            this.searchInfo.requirementStatus[i].code
-          ) {
-            this.status = this.searchInfo.requirementStatus[i]
-          }
+        this.loading.info = false
+      })
+    },
+    getTaskStatusMapInfo() {
+      getTaskStatusMapInfo({
+        requireId: this.id
+      }).then(res => {
+        const name = []
+        const data = []
+        for (const i in res.data.statusInfoList) {
+          name.push(res.data.statusInfoList[i].statusString)
+          data.push(res.data.statusInfoList[i].count)
         }
+        this.statistics.task = res.data
+        this.taskOption.xAxis[0].data = name
+        this.taskOption.series[0].data = data
+        this.taskOption = JSON.parse(JSON.stringify(this.taskOption))
+        this.loading.task = false
       })
-      getRequirementStatistics({
+    },
+    getBugStatusMapInfo() {
+      getBugStatusMapInfo({
         requireId: this.id
       }).then(res => {
-        this.statistics = res.data
+        const name = []
+        const data = []
+        for (const i in res.data.statusInfoList) {
+          name.push(res.data.statusInfoList[i].statusString)
+          data.push(res.data.statusInfoList[i].count)
+        }
+        this.statistics.bug = res.data
+        this.bugOption.xAxis[0].data = name
+        this.bugOption.series[0].data = data
+        this.bugOption = JSON.parse(JSON.stringify(this.bugOption))
+        this.loading.bug = false
       })
-    })
-  },
-  methods: {
+    },
+    getTaskByRequireId() {
+      getTaskByRequireId({
+        requireId: this.id
+      }).then(res => {
+        this.tableData = res.data
+        this.loading.table = false
+      })
+    },
     getPmName() {
       const names = []
       for (const i in this.requirement.pm) {
@@ -282,56 +517,113 @@ export default {
       }
       return names.join(',')
     },
-    getClientTypeName() {
+    getAppClientName() {
       const names = []
       for (const i in this.requirement.referredClientType) {
-        names.push(this.clientTypeOb[this.requirement.referredClientType[i]])
+        names.push(this.appClientOb[this.requirement.referredClientType[i]])
       }
-      return names.join(',')
-    },
-    handleCommand(command) {
-      this.status = command
+      return names.join('\n')
     },
     getSearchInfo() {
       return getSearchInfo().then(res => {
         this.searchInfo = res.data
         for (const i in this.searchInfo.belongingProject) {
-          this.projectOb[this.searchInfo.belongingProject[i].code] = this.searchInfo.belongingProject[i].msg
+          this.projectOb[
+            this.searchInfo.belongingProject[i].code
+          ] = this.searchInfo.belongingProject[i].msg
         }
         for (const i in this.searchInfo.bizType) {
-          this.bizTypeOb[this.searchInfo.bizType[i].code] = this.searchInfo.bizType[i].msg
+          this.bizTypeOb[
+            this.searchInfo.bizType[i].code
+          ] = this.searchInfo.bizType[i].msg
         }
-        for (const i in this.searchInfo.clientType) {
-          this.clientTypeOb[this.searchInfo.clientType[i].code] = this.searchInfo.clientType[i].msg
+        for (const i in this.searchInfo.appClient) {
+          this.appClientOb[
+            this.searchInfo.appClient[i].code
+          ] = this.searchInfo.appClient[i].msg
         }
+        for (const i in this.searchInfo.requirementStatus) {
+          this.requirementStatusOb[
+            this.searchInfo.requirementStatus[i].code
+          ] = this.searchInfo.requirementStatus[i].msg
+        }
+      })
+    },
+    deleteRequirement() {
+      const user = localStorage.getItem('username')
+      this.$confirm('此操作将永久删除该需求, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
       })
+        .then(() => {
+          deleteRequirement({
+            id: this.id,
+            modifier: user
+          }).then(res => {
+            if (res.code === 200) {
+              this.$router.push({ name: '需求' })
+            } else {
+              this.$message.warning(res.msg)
+            }
+          })
+        })
+        .catch(() => {})
+    },
+    createTask() {},
+    updateRequirementStatus(status) {
+      updateRequirementStatus({ id: this.id, status: status.code }).then(
+        res => {
+          if (res.code === 200) {
+            this.getRequirementById()
+          } else {
+            this.$message.warning(res.msg)
+          }
+        }
+      )
     },
-    deleteRequirement() {},
-    createRequirement() {}
+    getQaOrRdNameList(list) {
+      const arr = []
+      for (const i in list) {
+        arr.push(list[i].name)
+      }
+      return arr.join(',')
+    },
+    handleCurrentRowChange(val) {
+      this.$router.push({ name: '任务', params: { id: val.id + '' }})
+    }
   }
 }
 </script>
 
 <style scoped>
-.el-header,
-.el-footer,
-.el-aside,
-.el-main {
+.div_requirment_info .el-row {
+  line-height: 35px;
+}
+.layout_header,
+.layout_aside,
+.layout_main {
   border-radius: 8px;
   background-color: #ffffff;
 }
-.el-header {
-  line-height: 60px;
+.div_statistics > .el-container {
+  margin: 0;
 }
-.div_label,.div_content {
-  display: inline-block;
-  font-size: 14px;
+.layout_aside,
+.layout_main {
+  padding: 2%;
 }
-.div_label {
-  color: #666666;
-  width: 120px;
+.layout_header {
+  line-height: 60px;
 }
-.div_content {
-  color: #409EFF;
+.requirement_info::before {
+  height: 0px;
 }
 </style>
+
+<style>
+.layout_main .el-table__body tr:hover td {
+  color: #409eff;
+  background: #eef0f5;
+} /*hover时字体, 背景颜色*/
+</style>

+ 53 - 9
src/views/projectManage/requirement/list/create.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog title="新建需求" :visible.sync="isVisible" width="60%">
+  <el-dialog :title="title" :visible.sync="isVisible" width="60%">
     <el-form :model="form" :rules="rules" label-position="right" label-width="120px">
       <el-form-item label="需求名称" prop="name">
         <el-input v-model="form.name" placeholder="请输入需求名称" />
@@ -84,7 +84,7 @@
           <el-form-item v-show="form.dependOnRelease" label="涉及的客户端" prop="referredClientType">
             <el-select v-model="form.referredClientType" multiple placeholder="请选择">
               <el-option
-                v-for="item in info.clientType"
+                v-for="item in info.appClient"
                 :key="item.code"
                 :label="item.msg"
                 :value="item.code"
@@ -97,16 +97,20 @@
     {{ form }}
     <template v-slot:footer>
       <el-button @click="cancel">取 消</el-button>
-      <el-button type="primary" @click="confirm">创 建</el-button>
+      <el-button type="primary" @click="confirm">确 认</el-button>
     </template>
   </el-dialog>
 </template>
 
 <script>
-import { getMemberInfo, createRequirement } from '@/api/requirement.js'
+import { getMemberInfo, createRequirement, updateRequirement } from '@/api/requirement.js'
 
 export default {
   props: {
+    title: {
+      type: String,
+      default: '标题'
+    },
     visible: {
       type: Boolean,
       default: false
@@ -121,6 +125,12 @@ export default {
           priority: []
         }
       }
+    },
+    data: {
+      type: Object,
+      default() {
+        return null
+      }
     }
   },
   data() {
@@ -169,11 +179,20 @@ export default {
     },
     isVisible: function(newIsVisible, oldIsVisible) {
       if (newIsVisible === false) {
-        for (const i in this.form) {
-          this.form[i] = null
+        if (this.title === '新建需求') {
+          for (const i in this.form) {
+            this.form[i] = null
+          }
         }
         this.$emit('cancel', false)
       }
+    },
+    data: function(newData, oldData) {
+      if (newData) {
+        this.form = JSON.parse(JSON.stringify(this.data))
+        this.form.pm = this.form.pm[0].idap
+        this.init()
+      }
     }
   },
   methods: {
@@ -218,10 +237,30 @@ export default {
           }
         }
       }
+      if (this.form.referredClientType && this.form.dependOnRelease === 1 && this.form.referredClientType.length === 0) {
+        this.$message.warning('请选择客户端')
+        return
+      }
       this.form.creator = localStorage.getItem('username')
-      createRequirement(this.form).then(res => {
-        this.$emit('confirm', false)
-      })
+      if (this.title === '新建需求') {
+        createRequirement(this.form)
+          .then(res => {
+            if (res.code === 200) {
+              this.$emit('confirm', this.form)
+            } else {
+              this.$message.warning(res.msg)
+            }
+          })
+      } else {
+        updateRequirement(this.form)
+          .then(res => {
+            if (res.code === 200) {
+              this.$emit('confirm', this.form)
+            } else {
+              this.$message.warning(res.msg)
+            }
+          })
+      }
     },
     searchUser(query) {
       this.userLoading = true
@@ -229,6 +268,11 @@ export default {
         this.options = res.data
         this.userLoading = false
       })
+    },
+    init() {
+      if (this.form.pm) {
+        this.searchUser(this.form.pm)
+      }
     }
   }
 }

+ 24 - 19
src/views/projectManage/requirement/list/index.vue

@@ -94,8 +94,8 @@
       </div>
     </el-header>
     <el-main class="requirement-main">
-      <div style="margin: 1.5%; font-weight: 600; white-space: nowrap;">
-        <b style="color: #409EFF;margin: 0 0.5%; font-size: 20px; ">I</b>需求列表
+      <div style="font-size: 18px;margin: 2%">
+        <b style="color: #409EFF;">I</b>版本列表
         <el-button
           type="primary"
           size="mini"
@@ -109,7 +109,8 @@
         :data="tableData"
         style="width: 100%"
         highlight-current-row
-        :header-cell-style="{ background: '#6AB4FF', color: '#FFFFFF' }"
+        :header-cell-style="{ background: '#6AB4FF', color: '#FFFFFF',textAlign: 'center'}"
+        :cell-style="{textAlign: 'center'}"
         @current-change="handleCurrentRowChange"
       >
         <el-table-column prop="priority" label="优先级" sortable min-width="8%">
@@ -117,22 +118,22 @@
             <el-tag size="mini" :type="getType(scope.row.priority)">{{ 'P'+scope.row.priority }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="name" label="需求名称" sortable min-width="15%" />
-        <el-table-column prop="belongingProject" label="归属的项目" sortable min-width="10%">
+        <el-table-column prop="name" label="需求名称" min-width="15%" />
+        <el-table-column prop="belongingProject" label="归属的项目" min-width="10%">
           <template v-slot="scope">
             {{ getProjectName(scope.row.belongingProject) }}
           </template>
         </el-table-column>
-        <el-table-column prop="bizId" label="业务线" sortable min-width="10%">
+        <el-table-column prop="bizId" label="业务线" min-width="10%">
           <template v-slot="scope">
             {{ getBizName(scope.row.belongingProject) }}
           </template>
         </el-table-column>
-        <el-table-column prop="pm" label="产品" sortable min-width="10%" />
-        <el-table-column prop="taskCount" label="任务总数" sortable min-width="8%" />
-        <el-table-column prop="bugCount" label="bug总数" sortable min-width="8%" />
-        <el-table-column prop="creator" label="创建人" sortable min-width="10%" />
-        <el-table-column prop="createTime" label="创建时间" sortable min-width="10%">
+        <el-table-column prop="pm" label="产品" min-width="10%" />
+        <el-table-column prop="taskCount" label="任务总数" min-width="8%" />
+        <el-table-column prop="bugCount" label="bug总数" min-width="8%" />
+        <el-table-column prop="creator" label="创建人" min-width="10%" />
+        <el-table-column prop="createTime" label="创建时间" min-width="10%">
           <template v-slot="scope">{{ getcreateTime(scope.row.createTime) }}</template>
         </el-table-column>
       </el-table>
@@ -148,10 +149,11 @@
       />
     </el-main>
     <requirement-create
+      title="新建需求"
       :visible="createDialogVisible"
       :info="searchInfo"
       @cancel="createDialogVisible=false"
-      @confirm="createDialogVisible=false"
+      @confirm="getTableData();createDialogVisible=false"
     />
   </div>
 </template>
@@ -343,7 +345,7 @@ export default {
 }
 </script>
 
-<style>
+<style scoped>
 .el-dropdown-link {
   cursor: pointer;
   color: #333333;
@@ -365,6 +367,15 @@ export default {
   border-radius: 8px;
   padding: 0%;
 }
+.priority_div {
+  width: fit-content;
+  width: -webkit-fit-content;
+  width: -moz-fit-content;
+  color: #ffffff;
+}
+</style>
+
+<style>
 .requirement-header .el-input__inner {
   border: none;
 }
@@ -377,11 +388,5 @@ export default {
 #basicName3::-webkit-input-placeholder {
   color: #333333;
 }
-.priority_div {
-  width: fit-content;
-  width: -webkit-fit-content;
-  width: -moz-fit-content;
-  color: #ffffff;
-}
 .requirement-main .el-table .el-table__body tr:hover td { color: #409EFF; background: #EEF0F5; } /*hover时字体, 背景颜色*/
 </style>

+ 157 - 0
src/views/projectManage/version/list/index.vue

@@ -0,0 +1,157 @@
+<template>
+  <el-container>
+    <el-header class="layout_header">
+      <el-dropdown @command="handleCommand">
+        <span class="el-dropdown-link">
+          {{ searchTitle.client }}
+          <i class="el-icon-arrow-down el-icon--right" />
+        </span>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item
+            v-for="(item,index) in searchInfo.clients"
+            :key="index"
+            :command="{value: item,flag: 1}"
+          >{{ item.msg }}</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+      <el-dropdown style="margin-left: 60px" @command="handleCommand">
+        <span class="el-dropdown-link">
+          {{ searchTitle.version }}
+          <i class="el-icon-arrow-down el-icon--right" />
+        </span>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item
+            v-for="(item,index) in searchInfo.versions"
+            :key="index"
+            :command="{value: item,flag: 2}"
+          >{{ item.msg }}</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </el-header>
+    <el-main class="layout_main">
+      <div style="font-size: 18px;margin: 2%">
+        <b style="color: #409EFF;">I</b>版本列表
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="tableData"
+        style="width: 100%;"
+        highlight-current-row
+        :header-cell-style="{ background: '#6AB4FF', color: '#FFFFFF',textAlign: 'center'}"
+        :cell-style="{textAlign: 'center'}"
+        @current-change="handleCurrentRowChange"
+      >
+        <el-table-column prop="name" label="优先级" min-width="20%" />
+        <el-table-column prop="name" label="需求名称" min-width="20%" />
+        <el-table-column prop="name" label="业务线" min-width="20%" />
+        <el-table-column prop="name" label="PM" min-width="20%" />
+        <el-table-column prop="name" label="状态" min-width="20%" />
+        <el-table-column prop="name" label="任务" min-width="20%" />
+        <el-table-column prop="name" label="任务健康分布" min-width="20%" />
+      </el-table>
+      <el-pagination
+        background
+        layout="->,total, sizes, prev, pager, next, jumper"
+        :current-page="searchForm.curIndex"
+        :page-size="searchForm.pageSize"
+        :page-sizes="[15,30,45,total]"
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </el-main>
+  </el-container>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      tableData: null,
+      loading: false,
+      searchInfo: {
+        clients: [
+          {
+            code: 0,
+            msg: '代驾'
+          },
+          {
+            code: 1,
+            msg: '黑马'
+          }
+        ],
+        versions: [
+          {
+            code: 0,
+            msg: '1.1.1'
+          },
+          {
+            code: 1,
+            msg: '2.2.2'
+          }
+        ]
+      },
+      searchTitle: {
+        client: '选择客户端',
+        version: '版本'
+      },
+      total: 0,
+      searchForm: {
+        client: null,
+        version: null,
+        curIndex: 1,
+        pageSize: 15
+      }
+    }
+  },
+  methods: {
+    getTableData() {
+
+    },
+    handleCommand(command) {
+      switch (command.flag) {
+        case 1:
+          this.searchForm.client = command.value.code
+          this.searchTitle.client = command.value.msg
+          break
+        case 2:
+          this.searchForm.version = command.value.code
+          this.searchTitle.version = command.value.msg
+          break
+      }
+    },
+    handleCurrentRowChange(val) {
+      this.$router.push({ name: '版本详情', params: { id: val.id + '' }})
+    },
+    // 分页pageSize选择
+    handleSizeChange(pageSize) {
+      this.searchForm.pageSize = pageSize
+      this.getTableData()
+    },
+    // 当前页选择
+    handleCurrentChange(currentPage) {
+      this.searchForm.curIndex = currentPage
+      this.getTableData()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.el-dropdown-link {
+  cursor: pointer;
+  color: #333333;
+}
+.layout_header,
+.layout_main {
+  border-radius: 8px;
+  background-color: #ffffff;
+}
+.layout_header {
+  margin: 2%;
+  line-height: 60px;
+}
+.layout_main {
+  margin: 0 2% 2% 2%
+}
+</style>