Browse Source

Merge branches 'http_test' and 'http_test' of git.xiaojukeji.com:jacklijiajia/thoth-frontend into http_test

qinzhipeng_v 5 years ago
parent
commit
551109262b

+ 7 - 0
src/api/requirement.js

@@ -131,3 +131,10 @@ export function iterationList(data) {
     data
   })
 }
+// 获取统计数据
+export function getRequireSumData(id) {
+  return request({
+    url: requestIp + `/requirement/getRequireSumData?id=` + id,
+    method: 'get'
+  })
+}

+ 0 - 1
src/components/chart/normalEchart.vue

@@ -25,7 +25,6 @@ export default {
   watch: {
     option: {
       handler(newValue, oldValue) {
-        console.log(newValue)
         const myChart = echarts.init(document.getElementById(this.chartId))
         myChart.clear()
         this.drawLine()

+ 1 - 1
src/components/input/textArea.vue

@@ -80,7 +80,7 @@ export default {
   },
   computed: {
     isEmpty() {
-      return this.inputValue === ''
+      return this.inputValue === null || this.inputValue.replace(/\s+/g, '') === ''
     }
   },
   watch: {

+ 3 - 5
src/components/select/searchPeople.vue

@@ -40,11 +40,6 @@ export default {
       default: 'small',
       required: false
     },
-    multiple: {
-      type: Boolean,
-      default: false,
-      required: false
-    },
     disabled: {
       type: Boolean,
       default: false,
@@ -53,6 +48,7 @@ export default {
   },
   data() {
     return {
+      multiple: false, // 是否多选
       searchValue: this.value,
       loading: false,
       options: [],
@@ -65,8 +61,10 @@ export default {
         this.searchValue = newV
         const type = Object.prototype.toString.call(this.searchValue)
         if (type.indexOf('Array') < 0) {
+          this.multiple = false
           this.remoteMethod(newV)
         } else if (type.indexOf('Array') > 0 && newV.length > 0 && this.firstGetArr) {
+          this.multiple = true
           this.initMore(this.searchValue)
           this.firstGetArr = false
         }

+ 5 - 3
src/views/projectManage/projectList/components/dataStatistics.vue

@@ -91,9 +91,11 @@ export default {
         this.requireData = res.data.requireData
         this.taskData = res.data.taskData
         this.bugData = res.data.bugData
-        this.setDataChart(this.requireData.detail, 'echartsOption1')
-        this.setDataChart(this.taskData.detail, 'echartsOption2')
-        this.setDataChart(this.bugData.detail, 'echartsOption3')
+        this.$nextTick(() => {
+          this.setDataChart(this.requireData.detail, 'echartsOption1')
+          this.setDataChart(this.taskData.detail, 'echartsOption2')
+          this.setDataChart(this.bugData.detail, 'echartsOption3')
+        })
       }
     },
     setDataChart(data, obj) {

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

@@ -71,7 +71,7 @@
     </el-table>
     <div class="bottom-detail">
       <el-row>排期总汇:{{ scheduleDetail.startTime | handlerDate }} ~ {{ scheduleDetail.endTime | handlerDate }}</el-row>
-      <el-row v-if="scheduleDetail.preOnlineVersion.length>0">预计上线版本:{{ scheduleDetail.preOnlineVersion }}</el-row>
+      <el-row v-if="scheduleDetail.preOnlineVersion && scheduleDetail.preOnlineVersion.length>0">预计上线版本:{{ scheduleDetail.preOnlineVersion }}</el-row>
       <el-row v-else>预计上线版本:</el-row>
     </div>
     <modify-schedule

+ 1 - 0
src/views/projectManage/projectList/projectViewDetails.vue

@@ -36,6 +36,7 @@
             <el-dropdown-menu slot="dropdown">
               <el-dropdown-item @click.native="need_open = true">新建需求</el-dropdown-item>
               <el-dropdown-item @click.native="reated_task()">新建任务</el-dropdown-item>
+              <el-dropdown-item @click.native="created_bug()">新建缺陷</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
           <div class="line" />

+ 336 - 0
src/views/projectManage/requirement/components/bugsList.vue

@@ -0,0 +1,336 @@
+<template>
+  <div>
+    <el-table
+      ref="planTable"
+      :data="bugsDataList"
+      style="width: 100%;"
+      size="mini"
+      row-key="id"
+      :header-cell-style="{ color: '#4A4A4A', fontSize: '14px', fontWeight: '550', textAlign: 'center' }"
+      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 prop="bugName" label="缺陷标题" width="200" align="center" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span style=" color: #A7AEBC; font-size: 10px;">{{ 'BUG-' + scope.row.id }}</span>
+          <br>
+          <span class="bug-title" @click="getToDetails(scope.row.id)">{{ scope.row.bugName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" width="115" align="center">
+        <template slot-scope="scope">
+          <el-select
+            v-model="scope.row.status"
+            :class="['status'+scope.row.status]"
+            class="btns"
+            size="mini"
+            @change="statusChange(scope.row)"
+          >
+            <el-option v-for="item in allStatus" :key="item.code" :label="item.name" :value="item.code" />
+          </el-select>
+        </template>
+      </el-table-column>
+      <el-table-column prop="priorityName" label="缺陷等级" align="center" />
+      <el-table-column prop="taskName" label="所属任务" align="center" width="200" show-overflow-tooltip />
+      <el-table-column prop="creatorList" label="提报人" width="100" align="center" />
+      <el-table-column prop="assignerList" label="责任人" width="100" align="center" show-overflow-tooltip />
+      <el-table-column prop="currentHandlerList" label="修复人" width="100" align="center" show-overflow-tooltip />
+      <el-table-column prop="gmtCreate" label="创建日期" width="150" align="center">
+        <template slot-scope="scope">{{ scope.row.gmtCreate | naspOut }}</template>
+      </el-table-column>
+    </el-table>
+    <el-col :span="24">
+      <div align="right">
+        <el-pagination
+          :page-sizes="[10, 20, 30, total]"
+          :current-page="curIndex"
+          :page-size="pageSize"
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="total"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </el-col>
+    <normal-dialog
+      :show-dialog.sync="statusDialog"
+      :title="statusDialogTitle"
+      :width="'50%'"
+      :is-default-close="false"
+      @confirm="confirmStatus()"
+      @cancel="bugsList()"
+    >
+      <el-form
+        v-if="statusDialogTitle !== '删除确认'"
+        ref="ruleForm"
+        label-width="110px"
+        label-position="left"
+        :model="nowTaskDetail"
+        :rules="rules"
+      >
+        <el-form-item
+          v-if="statusDialogTitle === '待测试' || statusDialogTitle === '已完成'"
+          label="缺陷原因"
+          prop="bugReason"
+        >
+          <el-select v-model="nowTaskDetail.bugReason" style="width: 100%">
+            <el-option
+              v-for="item in bugReasonEnumList"
+              :key="item.code"
+              :label="item.name"
+              :value="item.code"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          v-if="statusDialogTitle === '待测试'"
+          label="修复方式"
+          class="bug_manage_dialog bug_manage_dialog_fixMethod"
+        >
+          <el-input
+            v-model="nowTaskDetail.reasonOrDesc"
+            type="textarea"
+            placeholder="请输入具体原因和修复方式"
+            maxlength="300"
+            show-word-limit
+            rows="4"
+          />
+        </el-form-item>
+        <el-form-item
+          v-if="statusDialogTitle === '已完成'"
+          label="修复结果"
+          prop="repairResult"
+          class="bug_manage_dialog"
+        >
+          <el-select
+            v-model="nowTaskDetail.repairResult"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in repairResultEnumList"
+              :key="item.code"
+              :label="item.name"
+              :value="item.code"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="statusDialogTitle === 'Reopen'" label="Reopen原因" prop="reasonOrDesc">
+          <el-input
+            v-model="nowTaskDetail.reasonOrDesc"
+            type="textarea"
+            placeholder="请输入Reopen"
+            maxlength="300"
+            show-word-limit
+            rows="4"
+          />
+        </el-form-item>
+      </el-form>
+    </normal-dialog>
+  </div>
+</template>
+<script>
+import { bugList, bugGetEnum, bugUpdate } from '@/api/defectManage'
+import normalDialog from '@/components/dialog/normalDialog'
+export default {
+  components: { normalDialog },
+  filters: {
+    naspOut(value) {
+      if (!value) return ''
+      var da = value.split(/\s+/)
+      return da[0]
+    }
+  },
+  data() {
+    return {
+      bugsDataList: [],
+      allStatus: [], // 所有状态列表
+      bugReasonEnumList: [], // 所有bug原因列表
+      repairResultEnumList: [], // 修复原因列表
+      pageSize: 10,
+      curIndex: 1,
+      total: 0,
+      nowTaskDetail: null, // 当前需要改变任务的详情
+      statusDialog: false, // 状态修改弹框
+      statusDialogTitle: '',
+      rules: {
+        assigner: [
+          { required: true, message: '责任人不可为空', trigger: 'change' }
+        ],
+        currentHandler: [
+          { required: true, message: '修复人不可为空', trigger: 'change' }
+        ],
+        bugName: [
+          { required: true, message: '标题不可为空', trigger: 'blur' }
+        ],
+        bugReason: [
+          { required: true, message: '请选择缺陷原因', trigger: 'change' }
+        ],
+        repairResult: [
+          { required: true, message: '请选择修复结果', trigger: 'change' }
+        ],
+        reasonOrDesc: [
+          { required: true, message: '请输入Reopen原因', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getBugGetEnum()
+    this.bugsList()
+  },
+  methods: {
+    async getBugGetEnum() {
+      const res = await bugGetEnum()
+      if (res.code === 200) {
+        this.allStatus = res.data.bugEnumList
+        this.bugReasonEnumList = res.data.bugReasonEnumList
+        this.repairResultEnumList = res.data.repairResultEnumList
+      }
+    },
+    async bugsList() {
+      const params = {
+        bizId: Number(localStorage.getItem('bizId')),
+        pageSize: this.pageSize,
+        curIndex: this.curIndex,
+        requireId: this.$route.query.id
+      }
+      const res = await bugList(params)
+      if (res.code === 200) {
+        this.bugsDataList = res.data
+        this.total = res.total
+      }
+    },
+    handleSizeChange(e) {
+      this.pageSize = e
+      this.bugsList()
+    },
+    handleCurrentChange(e) {
+      this.curIndex = e
+      this.bugsList()
+    },
+    getToDetails(id) { // 详情页跳转
+      this.$router.push({ name: '缺陷详情', params: { id: id }})
+    },
+    statusChange(row) { // 状态改变
+      this.nowTaskDetail = row
+      const nowStatusObj = this.allStatus.find(item => item.code === row.status)
+      if (['待修复', '修复中', 'Hold'].some(item => item === nowStatusObj.name)) {
+        this.bugUpdate()
+      } else {
+        this.statusDialogTitle = nowStatusObj.name
+        this.statusDialog = true
+      }
+    },
+    confirmStatus() { // 确认更改状态
+      this.$refs['ruleForm'].validate((valid) => {
+        if (valid) {
+          this.bugUpdate()
+          this.statusDialog = false
+        }
+      })
+    },
+    async bugUpdate() { // 更改状态请求
+      const userData = {
+        id: '',
+        ename: localStorage.getItem('username'),
+        name: localStorage.getItem('realname')
+      }
+      const res = await bugUpdate({ bugBaseInfo: this.nowTaskDetail, user: userData })
+      if (res.code === 200) {
+        this.$message({ message: '状态修改成功', type: 'success', duration: 1000, offset: 150 })
+      }
+    }
+  }
+}
+</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;
+}
+.bug-title {
+  cursor: pointer;
+}
+.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(#69B3FF)
+}
+.status1 {
+  @include setStatus(#FF8952)
+}
+.status2 {
+  @include setStatus(#2F54EB)
+}
+.status3 {
+  @include setStatus(#61D3B8)
+}
+.status4 {
+  @include setStatus(#F56C6C)
+}
+.status5 {
+  @include setStatus(#7ED321)
+}
+.div_priority {
+  text-align: center;
+  color: #ffffff;
+  padding: inherit;
+  border-radius: 4px;
+  width: 40px;
+  display: inline-block;
+}
+.table-project-name {
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+  b {
+    color: #A7AEBC;
+    font-size: 10px;
+  }
+  span {
+    font-size: 14px;
+  }
+}
+</style>

+ 165 - 0
src/views/projectManage/requirement/components/dataStatistics.vue

@@ -0,0 +1,165 @@
+<template>
+  <div class="data-main">
+    <article>
+      <div class="data-num">
+        <div class="data-add green" @click="reated_task()" />
+        <div class="data-detail">
+          <b v-if="taskData">{{ taskData.total }}</b>
+          <span>任务数量</span>
+        </div>
+      </div>
+      <div class="data-line" />
+      <div class="data-chart">
+        <normal-echart :chart-id="'chartSecond'" :option="echartsOption2" />
+      </div>
+    </article>
+    <article>
+      <div class="data-num">
+        <div class="data-add red" @click="created_bug()" />
+        <div class="data-detail">
+          <b v-if="bugData">{{ bugData.total }}</b>
+          <span>缺陷数量</span>
+        </div>
+      </div>
+      <div class="data-line" />
+      <div class="data-chart">
+        <normal-echart :chart-id="'chartThird'" :option="echartsOption3" />
+      </div>
+    </article>
+    <openDialog v-if="task_open" ref="task_createdUpdata" />
+    <createdBug v-if="bug_open" ref="createdBug" />
+  </div>
+</template>
+<script>
+import normalEchart from '@/components/chart/normalEchart'
+import openDialog from '@/views/projectManage/dialog_vue'
+import createdBug from '@/views/projectManage/bugList/file/createdBug'
+import { getRequireSumData } from '@/api/requirement'
+export default {
+  components: {
+    normalEchart,
+    openDialog,
+    createdBug
+  },
+  data() {
+    return {
+      edit: false,
+      dataChart1: false,
+      echartsOption2: {},
+      echartsOption3: {},
+      requirement: {},
+      task_open: false, // 新建任务
+      bug_open: false, // 新建缺陷
+      taskData: null, // 任务数据
+      bugData: null // 缺陷数据
+    }
+  },
+  created() {
+    this.getProjectSumData()
+  },
+  methods: {
+    async getProjectSumData() { // 获取数据
+      const res = await getRequireSumData(this.$route.query.id)
+      if (res.code === 200) {
+        this.taskData = res.data.taskData
+        this.bugData = res.data.bugData
+        this.$nextTick(() => {
+          this.setDataChart(this.taskData.detail, 'echartsOption2')
+          this.setDataChart(this.bugData.detail, 'echartsOption3')
+        })
+      }
+    },
+    setDataChart(data, obj) {
+      this[obj] = {
+        color: ['#3AA1FF'],
+        tooltip: { trigger: 'axis', axisPointer: { type: 'line' }}, // 默认为直线,可选为:'line' | 'shadow'
+        grid: { left: '15%', right: '15%', top: '15%', bottom: '10%', containLabel: true },
+        xAxis: [{ type: 'category', data: data.xaxis, axisTick: { alignWithLabel: true }}],
+        yAxis: [{ type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { type: 'dashed' }}}],
+        series: [
+          {
+            name: data.yaxis[0].name, type: 'bar', barWidth: '20px', data: data.yaxis[0].data || [],
+            itemStyle: { normal: { label: { show: true, formatter: '{c}', position: 'top' }}}
+          }
+        ]
+      }
+    },
+    reated_task(e) { // 建任务
+      this.task_open = true
+      this.$nextTick(() => {
+        this.$refs.task_createdUpdata.init(2)
+      })
+    },
+    created_bug() { // 缺陷创建
+      this.bug_open = true
+      this.$nextTick(() => {
+        this.$refs.createdBug.init(1)
+      })
+    },
+    change() {
+      this.$emit('change')
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.data-main {
+  padding: 61px 0 41px 0;
+}
+article{
+  width: 85%;
+  height: 260px;
+  min-width: 1043px;
+  margin: 0 auto 20px auto;
+  box-shadow:0px 0px 11px rgba(238,240,245,1);
+  border-radius:7px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .data-num {
+    width: 41%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 127px 0 62px;
+    .data-add {
+      height: 92px;
+      width: 92px;
+      border-radius: 50%;
+    }
+    .blue {
+      background-color:rgba(64,158,255,0.15);
+    }
+    .green {
+      background-color:rgba(126,211,33,0.15);
+    }
+    .red {
+      background-color: rgba(245,108,108, 0.15);
+    }
+    .data-detail {
+      color: #333333;
+      display: flex;
+      width: 70px;
+      flex-direction: column;
+      align-items: center;
+      b{
+        font-size: 75px;
+      }
+      span {
+        font-size: 16px;
+      }
+    }
+  }
+  .data-line {
+    width:0px;
+    height:156px;
+    border:1px solid rgba(112,112,112,1);
+    opacity:0.15;
+  }
+  .data-chart {
+    width: 58%;
+    height: 100%;
+  }
+}
+</style>

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

@@ -8,7 +8,7 @@
           </el-select>
         </el-form-item>
         <el-form-item label="参与人员" prop="peopleList">
-          <search-people :value.sync="form.peopleList" :multiple="true" style="width: 100%" :size="'medium'" :disabled="disabled" />
+          <search-people :value.sync="form.peopleList" style="width: 100%" :size="'medium'" :disabled="disabled" />
         </el-form-item>
         <el-form-item label="排期" prop="dayList">
           <div v-show="form.dayList.length > 0 ">{{ schedule }}(用时<span class="blue">{{ detailDayList.length }}</span>天)</div>

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

@@ -71,7 +71,7 @@
     </el-table>
     <div class="bottom-detail">
       <el-row>排期总汇:{{ scheduleDetail.startTime | handlerDate }} ~ {{ scheduleDetail.endTime | handlerDate }}</el-row>
-      <el-row v-if="scheduleDetail.preOnlineVersion.length>0">预计上线版本:{{ scheduleDetail.preOnlineVersion }}</el-row>
+      <el-row v-if="scheduleDetail.preOnlineVersion && scheduleDetail.preOnlineVersion.length>0">预计上线版本:{{ scheduleDetail.preOnlineVersion }}</el-row>
       <el-row v-else>预计上线版本:</el-row>
     </div>
     <modify-schedule

+ 1 - 2
src/views/projectManage/requirement/details/index.vue

@@ -543,10 +543,9 @@ export default {
         this.$message.warning('评论不能为空')
         return
       }
-      const user = localStorage.getItem('username')
       addComment({
         commentInfo: { joinId: this.id, type: 4, content: this.commentContent },
-        user: { ename: user }
+        user: { ename: localStorage.getItem('username') }
       }).then(res => {
         if (res.code === 200) {
           this.getCommentList()

+ 135 - 17
src/views/projectManage/requirement/requirementDetail.vue

@@ -35,6 +35,7 @@
             <el-dropdown-menu slot="dropdown">
               <el-dropdown-item @click.native="createVisible = true">新建需求</el-dropdown-item>
               <el-dropdown-item @click.native="reated_task()">新建任务</el-dropdown-item>
+              <el-dropdown-item @click.native="created_bug()">新建缺陷</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
           <div class="line" />
@@ -70,13 +71,30 @@
             </el-form>
             <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
               <el-form-item label="需求来源:">
-                {{ form_query.sourceTypeName }}
+                <el-select v-model="form_query.sourceType" size="small" filterable placeholder="请选择" @change="changeArea">
+                  <el-option v-for="(item,index) in sourceTypeList" :key="item.msg + index" :label="item.msg" :value="item.code" />
+                </el-select>
               </el-form-item>
               <el-form-item label="优先级:">
-                <el-select v-model="form_query.priority" size="small" clearable filterable placeholder="请选择" @change="changeArea">
-                  <el-option v-for="item in priorityList" :key="item.msg" :label="item.msg" :value="item.code" />
+                <el-select v-model="form_query.priority" size="small" filterable placeholder="请选择" @change="changeArea">
+                  <el-option v-for="(item,index) in priorityList" :key="item.msg + index" :label="item.msg" :value="item.code" />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="是否跟版:">
+                <el-select v-model="form_query.dependOnRelease" size="small" filterable placeholder="请选择" @change="changeArea">
+                  <el-option v-for="(item,index) in dependList" :key="item.msg + index" :label="item.msg" :value="item.code" />
+                </el-select>
+              </el-form-item>
+            </el-form>
+            <el-form :inline="true" :model="form_query" class="demo-form-inline" label-position="right" label-width="100px">
+              <el-form-item label="跟版客户端:">
+                <el-select v-model="form_query.referredClientType" size="small" :disabled="!form_query.dependOnRelease" multiple filterable placeholder="请选择" @change="changeArea">
+                  <el-option v-for="(item,index) in appClient" :key="item.msg + index" :label="item.msg" :value="item.code" />
                 </el-select>
               </el-form-item>
+              <el-form-item label="PRD链接:" prop="mrdUrl">
+                <span class="PRD-link">{{ form_query.mrdUrl }}</span>
+              </el-form-item>
             </el-form>
           </div>
         </section>
@@ -94,8 +112,26 @@
             <div class="title-left-icon" />
             <div class="title-left-name">评论</div>
           </div>
-          <div>
-            <text-area :id="'pro-target'" :value.sync="form_query.target" :empty-text="'点击'" :input-button="'添加评论'" @change="changeArea" />
+          <div class="detail-info">
+            <ul class="comment-main">
+              <li v-for="(item,index) in comments" :key="'comment'+index">
+                <span class="comment-name">{{ item.commentInfo.name }}</span>
+                <span class="comment-gmtCreater">{{ item.commentInfo.gmtCreater }}</span>
+                <span class="comment-content">{{ item.commentInfo.content }}</span>
+              </li>
+            </ul>
+            <el-input
+              v-model="commentContent"
+              type="textarea"
+              placeholder="请输入评论内容"
+              maxlength="300"
+              show-word-limit
+              :autosize="{ minRows: 3, maxRows: 5}"
+              style="margin-bottom: 20px"
+            />
+            <el-row>
+              <el-col :span="2" :offset="22"><el-button type="primary" size="small" @click="addComment">发表评论</el-button></el-col>
+            </el-row>
           </div>
         </section>
       </el-container>
@@ -109,12 +145,16 @@
       <!-- 任务 -->
       <!-- 缺陷 -->
       <el-container v-show="activeName === '3'" class="is-vertical">
-        <section class="main-section" />
+        <section class="main-section">
+          <bugs-list />
+        </section>
       </el-container>
       <!-- 缺陷 -->
       <!-- 统计 -->
       <el-container v-show="activeName === '4'" class="is-vertical">
-        <section class="main-section" />
+        <section class="main-section">
+          <data-statistics @change="getRequirementById" />
+        </section>
       </el-container>
       <!-- 统计 -->
       <!-- 新建 -->
@@ -144,6 +184,7 @@
       </el-dialog>
       <!-- 删除 -->
       <openDialog v-if="task_open" ref="task_createdUpdata" />
+      <createdBug v-if="bug_open" ref="createdBug" />
       <drawer
         ref="drawer"
         title="项目成员"
@@ -169,7 +210,9 @@ import {
   deleteRequirement,
   showRequirementEnum,
   projectListProject,
-  iterationList
+  iterationList,
+  getCommentList,
+  addComment
 } from '@/api/requirement.js'
 import searchPeople from '@/components/select/searchPeople'
 import textArea from '@/components/input/textArea'
@@ -177,7 +220,10 @@ import drawer from '@/views/projectManage/Drawer'
 import createRequirement from '@/views/projectManage/requirement/list/create.vue'
 import openDialog from '@/views/projectManage/dialog_vue'
 import image_url from '@/assets/home_images/home_u.png'
+import createdBug from '@/views/projectManage/bugList/file/createdBug'
 import tasksList from './components/taskList'
+import bugsList from './components/bugsList'
+import dataStatistics from './components/dataStatistics'
 export default {
   components: {
     searchPeople,
@@ -185,7 +231,10 @@ export default {
     drawer,
     createRequirement,
     openDialog,
-    tasksList
+    createdBug,
+    tasksList,
+    bugsList,
+    dataStatistics
   },
   filters: {
     ellipsis(value, num) {
@@ -205,6 +254,9 @@ export default {
       requirementId: Number(this.$route.query.id), // 需求id
       statusList: [], // 状态列表
       priorityList: [], // 优先级列表
+      sourceTypeList: [], // 需求来源列表
+      appClient: [], // 跟版客户端列表
+      dependList: [{ msg: '否', code: 0 }, { msg: '是', code: 1 }], // 是否跟版
       form_query: {},
       display: false, // 设置成员弹框
       num: 0, // 成员数量
@@ -213,8 +265,11 @@ export default {
       updateVisible: false, // 编辑需求弹框
       deleteVisible: false, // 删除需求弹框
       task_open: false, // 新建任务弹框
+      bug_open: false, // 新建缺陷弹框
       belongProjectList: [], // 所属项目列表
-      iterationList: [] // 所属迭代列表
+      iterationList: [], // 所属迭代列表
+      commentContent: null, // 评论内容
+      comments: [] // 评论列表
     }
   },
   computed: {
@@ -227,6 +282,7 @@ export default {
     this.getRequirementById()
     this.getBelongProject()
     this.getIterationList()
+    this.getCommentList()
     this.$store.state.data.status = true
     this.$store.state.data.bizId = true
   },
@@ -242,6 +298,7 @@ export default {
       if (res.code === 200) {
         this.$message({ message: res.msg, type: 'success', duration: 1000, offset: 150 })
       }
+      this.getRequirementById()
     },
     async getBelongProject() { // 获取所属项目列表
       const res = await projectListProject({ bizId: Number(localStorage.getItem('bizId')) })
@@ -258,16 +315,15 @@ export default {
       if (res.code === 200) {
         this.iterationList = res.data.list
       }
-      this.iterationList.unshift({
-        id: -1,
-        name: '无'
-      })
+      this.iterationList.unshift({ id: -1, name: '无' })
     },
-    async showRequirementEnum() { // 获取需求状态列表,优先级列表
+    async showRequirementEnum() { // 获取需求状态列表,优先级列表,需求来源
       const res = await showRequirementEnum()
       if (res.code === 200) {
         this.statusList = res.data.requirementStatus
         this.priorityList = res.data.priority
+        this.sourceTypeList = res.data.sourceType
+        this.appClient = res.data.appClient
       }
     },
     async getRequirementById() { // 获取需求详情
@@ -276,6 +332,29 @@ export default {
         this.form_query = res.data
       }
     },
+    async getCommentList() { // 获取需求评论
+      const res = await getCommentList({ type: 4, joinId: this.$route.query.id })
+      if (res.code === 200) {
+        this.comments = res.data
+        this.commentContent = ''
+      }
+    },
+    async addComment() { // 发表需求评论
+      if (this.commentContent.replace(/\s+/g, '') === '' || this.commentContent === null) {
+        this.$message.warning('评论不能为空')
+        return
+      }
+      const user = localStorage.getItem('username')
+      const res = await addComment({
+        commentInfo: { joinId: this.$route.query.id, type: 4, content: this.commentContent },
+        user: { ename: user }
+      })
+      if (res.code === 200) {
+        this.getCommentList()
+      } else {
+        this.$message.warning(res.msg)
+      }
+    },
     async updateStatus(status) { // 修改状态
       const res = await updateRequirementStatus({
         id: this.$route.query.id,
@@ -285,6 +364,7 @@ export default {
       if (res.code === 200) {
         this.$message({ message: '状态修改成功', type: 'success', duration: 1000, offset: 150 })
       }
+      this.getRequirementById()
     },
     childVal(val) {
       this.num = val
@@ -301,11 +381,17 @@ export default {
         this.$message({ message: '删除成功', type: 'warning', duration: 1000, offset: 150 })
       }
     },
-    reated_task(e) { // 新建任务
+    reated_task() { // 新建任务
       this.task_open = true
       this.$nextTick(() => {
         this.$refs.task_createdUpdata.init(2)
       })
+    },
+    created_bug() { // 缺陷创建
+      this.bug_open = true
+      this.$nextTick(() => {
+        this.$refs.createdBug.init(1)
+      })
     }
   }
 }
@@ -328,7 +414,7 @@ export default {
 .main-section {
   @include main-section;
   .detail-info {
-    padding: 20px 34px;
+    padding: 0 34px 20px 34px;
     /deep/.el-input__inner{
       border: 1px solid rgba(220,223,230,0)
     }
@@ -354,6 +440,38 @@ export default {
         margin-right: 0;
       }
     }
+    .comment-main {
+      list-style: none;
+      padding: 0px;
+      margin: 0 0 20px 0;
+      li {
+        list-style: none;
+        padding: 0px;
+        margin: 0px;
+      }
+      .comment-name {
+        font-size:14px;
+        color:#333B4A;
+      }
+      .comment-gmtCreater {
+        margin-left:20px;
+        color: #9B9B9B;
+        font-size:12px
+      }
+      .comment-content {
+        margin-left:20px;
+        font-size:14px;
+        color:#333B4A;
+        margin-top: 10px;
+        white-space: pre-line;
+      }
+    }
+    .PRD-link {
+      width: 50%;
+      overflow: hidden;
+      text-overflow:ellipsis;
+      white-space: nowrap;
+    }
   }
 }
 </style>