Forráskód Böngészése

Merge branch 'http_test' into pern

qinzhipeng_v 5 éve
szülő
commit
3ed51cc0c4
55 módosított fájl, 6695 hozzáadás és 2211 törlés
  1. 14 0
      src/api/httprule.js
  2. 301 0
      src/api/reportTemplate.js
  3. 3 2
      src/apiConfig/mock.js
  4. 4 0
      src/components/chart/normalEchart.vue
  5. 54 0
      src/components/dialog/clickHidden.vue
  6. 38 13
      src/router/index.js
  7. 5 0
      src/styles/PublicStyle/index.scss
  8. 0 240
      src/views/Platform/presentation/Templates/DailyReport.vue
  9. 0 408
      src/views/Platform/presentation/testPresentation.vue
  10. 19 7
      src/views/ToConfigure/components/modifyNotice.vue
  11. 20 8
      src/views/ToConfigure/components/noticeConfig.vue
  12. 0 67
      src/views/apiManagement/apiList.vue
  13. 28 0
      src/views/apiManagement/automatic.vue
  14. 0 40
      src/views/apiManagement/css/index.css
  15. 0 713
      src/views/apiManagement/index.vue
  16. 0 237
      src/views/apiManagement/vue/index.vue
  17. 305 223
      src/views/mock/httprule.vue
  18. 28 16
      src/views/projectManage/bugList/bugindex.vue
  19. 1 0
      src/views/projectManage/bugList/css/index.css
  20. 15 1
      src/views/projectManage/bugList/details/bugTableDialog.vue
  21. 54 53
      src/views/projectManage/bugList/details/index.vue
  22. 16 5
      src/views/projectManage/bugList/details/statusChange.vue
  23. 26 7
      src/views/projectManage/bugList/file/createdBug.vue
  24. 151 86
      src/views/projectManage/projectList/components/mileStone.vue
  25. 5 5
      src/views/projectManage/projectList/components/taskList.vue
  26. 5 5
      src/views/projectManage/requirement/components/taskList.vue
  27. 1 1
      src/views/projectManage/taskList/components/reportList.vue
  28. 10 8
      src/views/projectManage/taskList/taskViewDetail.vue
  29. 7 3
      src/views/projectManage/taskList/versionsCalendar.vue
  30. 1 1
      src/views/projectManage/version/components/taskList.vue
  31. 126 0
      src/views/quality/components/childCharts.vue
  32. 119 43
      src/views/quality/defectStatistics.vue
  33. 394 0
      src/views/reportManagement/ReleaseReport/components/ResultPageyL.vue
  34. 154 0
      src/views/reportManagement/ReleaseReport/components/iconDisplay.vue
  35. 313 0
      src/views/reportManagement/ReleaseReport/components/releaseDetails.vue
  36. 314 0
      src/views/reportManagement/ReleaseReport/newReleaeTemplate.vue
  37. 190 0
      src/views/reportManagement/ReleaseReport/releaePreview.vue
  38. 210 0
      src/views/reportManagement/Testing/TestingPreview.vue
  39. 247 0
      src/views/reportManagement/Testing/components/acceptTheReport.vue
  40. 361 0
      src/views/reportManagement/Testing/components/deliverDetails.vue
  41. 71 0
      src/views/reportManagement/Testing/components/iconDisplay.vue
  42. 327 0
      src/views/reportManagement/Testing/newTestingTemplate.vue
  43. 373 0
      src/views/reportManagement/components/DailyReport.vue
  44. 369 0
      src/views/reportManagement/components/ReleaseReport.vue
  45. 356 0
      src/views/reportManagement/components/TestingReport.vue
  46. 245 0
      src/views/reportManagement/daily/components/DailyDetails.vue
  47. 150 0
      src/views/reportManagement/daily/components/iconDisplay.vue
  48. 155 0
      src/views/reportManagement/daily/components/testPresenyL.vue
  49. 125 0
      src/views/reportManagement/daily/dailyPreview.vue
  50. 220 0
      src/views/reportManagement/daily/dailyTemplate.vue
  51. 171 0
      src/views/reportManagement/daily/newReportTemplate.vue
  52. 543 0
      src/views/reportManagement/testPresentation.vue
  53. 15 1
      src/views/workbench/bugTableList.vue
  54. 31 13
      src/views/workbench/person/components/calenderDetail.vue
  55. 5 5
      src/views/workbench/team/components/taskList.vue

+ 14 - 0
src/api/httprule.js

@@ -10,6 +10,20 @@ export function fetchRuleById(data) {
   })
 }
 
+export function queryById(id) { // 单一查询
+  return request({
+    url: mockUrl + '/api/mock/mockRule/queryById/' + id,
+    method: 'get'
+  })
+}
+
+export function callbackQuery(name) { // 回调接口信息
+  return request({
+    url: mockUrl + '/api/mock/mockRule/callback/query?name=' + name,
+    method: 'get'
+  })
+}
+
 export function fetchRuleList(data) {
   return request({
     url: mockUrl + '/api/mock/mockRule/query',

+ 301 - 0
src/api/reportTemplate.js

@@ -0,0 +1,301 @@
+import request from '@/utils/request'
+import { Presentation } from '@/apiConfig/api'
+
+// 报告模块部分
+
+// 获取模板列表,分业务线和类型
+export function settingQueryReportModuleList(data) {
+  return request({
+    url: Presentation + '/setting/queryReportModuleList',
+    method: 'post',
+    data
+  })
+}
+
+// 创建模板,需校验名称是否重复
+export function settingAddReportModule(data) {
+  return request({
+    url: Presentation + '/setting/addReportModule',
+    method: 'post',
+    data
+  })
+}
+
+// 修改模板,需校验名称是否重复
+export function settingUpdateReportModule(data) {
+  return request({
+    url: Presentation + '/setting/updateReportModule',
+    method: 'post',
+    data
+  })
+}
+
+// 删除模板,需校验权限
+export function settingDeleteReportModule(data, id) {
+  return request({
+    url: Presentation + `/setting/deleteReportModule?id=${id}`,
+    method: 'post',
+    data
+  })
+}
+
+// 获取单个模板内容
+export function settingGetReportModuleById(id) {
+  return request({
+    url: Presentation + `/setting/getReportModuleById?id=${id}`,
+    method: 'get'
+  })
+}
+
+// 根据任务idList获取P0P1缺陷类别
+export function bugGetReportHighPriData(data) {
+  return request({
+    url: Presentation + '/bug/getReportHighPriData',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取缺陷统计数据
+export function bugGetReportSumData(data) {
+  return request({
+    url: Presentation + '/bug/getReportSumData',
+    method: 'post',
+    data
+  })
+}
+
+// 删除
+export function dailyReportDelete(data, id) {
+  return request({
+    url: Presentation + '/dailyReport/delete?id=' + id,
+    method: 'post',
+    data
+  })
+}
+
+// 报告创建
+export function dailyReportCreate(data) {
+  return request({
+    url: Presentation + '/dailyReport/create',
+    method: 'post',
+    data
+  })
+}
+
+// 更新创建
+export function dailyReportUpdate(data) {
+  return request({
+    url: Presentation + '/dailyReport/update',
+    method: 'post',
+    data
+  })
+}
+
+// 获取缺陷责任人分布
+export function bugGetReportDisDataByMember(data) {
+  return request({
+    url: Presentation + '/bug/getReportDisDataByMember',
+    method: 'post',
+    data
+  })
+}
+
+// 获取缺陷等级分布
+export function bugGetReportDisDataByPri(data) {
+  return request({
+    url: Presentation + '/bug/getReportDisDataByPri',
+    method: 'post',
+    data
+  })
+}
+
+// 报告查看(需区分已发送或未发送)
+export function dailyReportGetV2(id) {
+  return request({
+    url: Presentation + `/dailyReport/getV2?id=${id}`,
+    method: 'get'
+  })
+}
+
+// 查看所有日报列表 (新)
+export function dailyReportListV2(data) {
+  return request({
+    url: Presentation + '/dailyReport/listV2',
+    method: 'post',
+    data
+  })
+}
+
+// 查看所有老日报列表
+export function dailyReportList(data) {
+  return request({
+    url: Presentation + '/dailyReport/list',
+    method: 'post',
+    data
+  })
+}
+
+// 获取缺陷按日期分布数据
+export function bugGetReportDisDataByDate(data) {
+  return request({
+    url: Presentation + '/bug/getReportDisDataByDate',
+    method: 'post',
+    data
+  })
+}
+
+// 准出报告部分
+
+// 新版准出报告list
+export function reportreleaseList(data) {
+  return request({
+    url: Presentation + '/reportrelease/list',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取缺陷统计数据
+export function bugGetReportOutSumData(data) {
+  return request({
+    url: Presentation + '/bug/getReportOutSumData',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取遗留缺陷列表
+export function bugGetReportNotResolveData(data) {
+  return request({
+    url: Presentation + '/bug/getReportNotResolveData',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取报告的初始数据(计划准出时间,计划开发周期,计划测试周期,实际测试周期,开发人员,测试人员)
+export function reportreleaseInitReportRelease(data) {
+  return request({
+    url: Presentation + '/reportrelease/initReportRelease',
+    method: 'post',
+    data
+  })
+}
+
+// 创建准出报告
+export function reportreleaseCreate(data) {
+  return request({
+    url: Presentation + '/reportrelease/create',
+    method: 'post',
+    data
+  })
+}
+
+// 编辑准出报告
+export function reportreleaseUpdate(data) {
+  return request({
+    url: Presentation + '/reportrelease/update',
+    method: 'post',
+    data
+  })
+}
+
+// 删除准出报告
+export function reportreleaseDelete(data, id) {
+  return request({
+    url: Presentation + `/reportrelease/delete?id=${id}`,
+    method: 'post',
+    data
+  })
+}
+
+// 报告查看(需区分已发送或未发送--状态区分)
+export function reportreleaseGetReportById(id) {
+  return request({
+    url: Presentation + `/reportrelease/getReportById?id=${id}`,
+    method: 'get'
+  })
+}
+
+// 报告发送(存储发件人、抄送人、图表数据)准出
+export function reportreleaseSendmail(data) {
+  return request({
+    url: Presentation + `/reportrelease/sendmail`,
+    method: 'post',
+    data
+  })
+}
+
+// 提测报告部分
+
+// 新版提测报告list
+export function reportdelivertestList(data) {
+  return request({
+    url: Presentation + '/reportdelivertest/list',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取报告的初始数据(计划提测时间、计划开发时间、是否跟版、跟版客户端)
+export function reportdelivertestInitReportRelease(data) {
+  return request({
+    url: Presentation + '/reportdelivertest/initReportDeliverTest',
+    method: 'post',
+    data
+  })
+}
+
+// 根据任务idList获取需求列表
+export function reportdelivertestGetRequiresByTaskIds(data) {
+  return request({
+    url: Presentation + '/reportdelivertest/getRequiresByTaskIds',
+    method: 'post',
+    data
+  })
+}
+
+// 报告创建
+export function reportdelivertestCreate(data) {
+  return request({
+    url: Presentation + '/reportdelivertest/create',
+    method: 'post',
+    data
+  })
+}
+
+// 更新创建
+export function reportdelivertestUpdate(data) {
+  return request({
+    url: Presentation + '/reportdelivertest/update',
+    method: 'post',
+    data
+  })
+}
+
+// 提测报告查看(需区分已发送或未发送)
+export function reportdelivertestGetReportById(id) {
+  return request({
+    url: Presentation + `/reportdelivertest/getReportById?id=${id}`,
+    method: 'get'
+  })
+}
+
+// 报告发送(存储发件人、抄送人、图表数据)
+export function reportdelivertestSendmail(data) {
+  return request({
+    url: Presentation + `/reportdelivertest/sendmail`,
+    method: 'post',
+    data
+  })
+}
+
+// 报告删除
+export function reportdelivertestDelete(data, id) {
+  return request({
+    url: Presentation + `/reportdelivertest/delete?id=${id}`,
+    method: 'post',
+    data
+  })
+}

+ 3 - 2
src/apiConfig/mock.js

@@ -1,4 +1,5 @@
 /*eslint-disable*/   //规避eslint的检查,如没有eslint可不写
 // export const mockUrl = 'http://10.179.88.110:8089' // stable
-export const mockUrl = 'http://mock.Intra.xiaojukeji.com' // 线上
-// export const mockUrl = 'http://10.179.101.226:8089' // test
+// export const mockUrl = 'http://mock.Intra.xiaojukeji.com' // 线上
+export const mockUrl = 'http://10.179.101.226:8089' // test
+// export const mockUrl = 'http://172.23.145.20:8089'//local

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

@@ -41,6 +41,10 @@ export default {
     drawLine() {
       const myChart = echarts.init(document.getElementById(this.chartId))
       myChart.setOption(this.option)
+      myChart.off('click')// 在渲染点击事件之前先清除点击事件
+      myChart.on('click', params => {
+        this.$emit('onClick', params)
+      })
     }
   }
 }

+ 54 - 0
src/components/dialog/clickHidden.vue

@@ -0,0 +1,54 @@
+<template>
+  <section v-show="visible" :id="id" class="click-hidden">
+    <div class="inner-contain">
+      <slot />
+    </div>
+  </section>
+</template>
+<script>
+export default {
+  name: 'ClickHidden',
+  props: {
+    show: {
+      type: Boolean,
+      default: false,
+      required: true
+    },
+    id: {
+      type: String,
+      default: 'click-hidden',
+      required: false
+    }
+  },
+  data() {
+    return {
+      visible: this.show
+    }
+  },
+  watch: {
+    show: {
+      handler(newV) {
+        this.visible = newV
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    window.addEventListener('click', this.hiddenDetail, true)
+  },
+  destroyed() {
+    window.removeEventListener('click', this.hiddenDetail)
+  },
+  methods: {
+    hiddenDetail(e) { // 点击外部元素,隐藏
+      const parent = document.querySelector(`#${this.id}`)
+      if (!parent) return
+      const isInner = parent.contains(e.target) // 点击的元素是否在容器内部
+      if (!isInner) {
+        this.visible = false
+        this.$emit('update:show', this.visible)
+      }
+    }
+  }
+}
+</script>

+ 38 - 13
src/router/index.js

@@ -187,14 +187,35 @@ export const constantRoutes = [{
     path: '/Platform/presentation',
     name: '报告',
     component: (resolve) => require(['@/views/Platform/presentation/testa'], resolve),
-    redirect: '/Platform/presentation/testPresentation',
+    redirect: '/reportManagement/testPresentation',
     meta: { title: '报告' },
     children: [{
-      path: 'testPresentation',
+      path: 'reportManagement',
       name: '报告',
-      component: (resolve) => require(['@/views/Platform/presentation/testPresentation'], resolve),
+      component: (resolve) => require(['@/views/reportManagement/testPresentation'], resolve),
       meta: { title: '报告' }
     },
+    {
+      path: 'dailyDetails',
+      name: '日报详情',
+      hidden: true,
+      component: (resolve) => require(['@/views/reportManagement/daily/components/dailyDetails'], resolve),
+      meta: { title: '报告详情' }
+    },
+    {
+      path: 'releaseDetails',
+      name: '准出详情',
+      hidden: true,
+      component: (resolve) => require(['@/views/reportManagement/ReleaseReport/components/releaseDetails'], resolve),
+      meta: { title: '报告详情' }
+    },
+    {
+      path: 'deliverDetails',
+      name: '提测详情',
+      hidden: true,
+      component: (resolve) => require(['@/views/reportManagement/Testing/components/deliverDetails'], resolve),
+      meta: { title: '报告详情' }
+    },
     {
       path: 'DailyNewsAdded',
       name: '新增测试日报',
@@ -580,8 +601,7 @@ export const constantRoutes = [{
   },
   {
     path: '/apiManagement',
-    hidden: true,
-    component: (resolve) => require(['@/views/apiManagement/index'], resolve),
+    component: (resolve) => require(['@/views/apiManagement/automatic'], resolve),
     name: '接口管理',
     meta: { title: '接口管理' }
   },
@@ -595,7 +615,6 @@ export const constantRoutes = [{
   {
     path: '/automation',
     component: (resolve) => require(['@/views/automation/index'], resolve),
-    // redirect: '/newWeb/index',
     name: '自动化',
     meta: { title: '自动化' },
     children: [{
@@ -605,15 +624,11 @@ export const constantRoutes = [{
       meta: { title: '扁鹊' }
     },
     {
-      path: '/apiManagemet',
+      path: '/apiManagement',
       name: 'api管理'
+      // component: (resolve) => require(['@/views/apiManagement/automatic.vue'], resolve),
+      // meta: { title: 'api管理' }
     }
-    // {
-    //   path: '/apiManagement',
-    //   name: 'api管理',
-    //   component: (resolve) => require(['@/views/apiManagement/index'], resolve),
-    //   meta: { title: 'api管理' }
-    // }
     ]
   }
   ]
@@ -641,6 +656,16 @@ const createRouter = () => new Router({
   routes: constantRoutes
 })
 const router = createRouter()
+router.beforeEach((to, from, next) => {
+  console.log(this)
+  if (to.name !== '接口管理') {
+    next()
+  } else {
+    window.open('http://zhihui-api.intra.didichuxing.com/', '_blank')
+    next({ path: from.path })
+    history.go(0)
+  }
+})
 
 // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
 export function resetRouter() {

+ 5 - 0
src/styles/PublicStyle/index.scss

@@ -407,6 +407,11 @@
         color:#409EFF !important;
       }
   }
+
+  .didi-hover:hover {
+    color:#409EFF;
+    cursor: pointer;
+  }
   .titleStatus {
     font-size:14px;
     font-family:MicrosoftYaHei;

+ 0 - 240
src/views/Platform/presentation/Templates/DailyReport.vue

@@ -1,240 +0,0 @@
-<template>
-  <el-dialog :visible.sync="dialogDaliy" width="70vw" class="public_task" title="测试日报" :close-on-click-modal="false" :destroy-on-close="true" :before-close="handleClose">
-    <div class="blueStripe" />
-    <div style="margin: 2% 0%; font-size: 16pt; color: #333B4A;">
-      <el-steps :active="active" align-center finish-status="success">
-        <el-step title="选择模版" />
-        <el-step title="填写报告" />
-        <el-step title="发送报告" />
-      </el-steps>
-    </div>
-    <div v-if="showOne" style="margin: 0 5%;">
-      <el-radio v-model="radio" style="margin: 0% 36%;" class="_radio" label="1">测试日报模版</el-radio>
-      <div style="margin: 1% 35%; height: 410px;" class="Layout">
-        <el-image style="display: inline-block; width: 80%;" :src="src" />
-      </div>
-      <div align="center">
-        <el-button size="small" type="primary" @click="NextStep()">下一步</el-button>
-      </div>
-    </div>
-    <div v-if="showTow">
-      <div class="descr" style=" margin-bottom: 2%; height: 435px; overflow:scroll; overflow-x: hidden">
-        <DailyReport ref="DailyReport" :message="dailyNewData" @daily="daily" />
-      </div>
-      <div align="center">
-        <el-button size="small" type="primary" @click="handleClose1()">上一步</el-button>
-        <el-button size="small" type="primary" @click="created_out()">保存,下一步</el-button>
-      </div>
-    </div>
-    <div v-if="showThree">
-      <div style="margin: 0% 5%;font-size:18px; font-family:PingFangSC-Medium,PingFang SC; font-weight:500; color:rgba(51,59,74,1); line-height:29px;">
-        邮件列表
-      </div>
-      <div style="margin: 1% 5% 3%;">
-        <div class="Layout" style="margin-bottom: 10px;"><div class="div1">收件人</div><searchTeam :value.sync="form.name" :clearable="true" :multiple="true" style="width:100%" /></div>
-        <div class="Layout"><div class="div1">抄送</div><searchTeam :value.sync="form.names" :clearable="true" :multiple="true" style="width:100%" /></div>
-      </div>
-      <div style="margin: 0 5%; font-size:18px; font-family:PingFangSC-Medium,PingFang SC; font-weight:500; color:rgba(51,59,74,1); line-height:29px;">
-        报告预览
-      </div>
-      <div class="descr" style=" margin-bottom: 2%; height: 300px; overflow:scroll; overflow-x: hidden">
-        <testPresenyL id="Gambol" :message="preview" style="width: 100%" />
-      </div>
-      <div align="center">
-        <el-button size="small" type="primary" @click="gou_out()">上一步</el-button>
-        <el-button :disabled="send" :loading="send" size="small" type="primary" @click="sendReport(form)">发送</el-button>
-      </div>
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-import '@/views/projectManage/publicCss/index.css'
-import '@/styles/PublicStyle/index.scss'
-import DailyReport from '@/views/Platform/presentation/DailyNewsAdded.vue'
-import testPresenyL from '@/views/Platform/presentation/testPresenyL.vue'
-import { dailyReportSendmail } from '@/api/ResultPage'
-import html2canvas from 'html2canvas'
-import daily from '@/assets/daily.png'
-import searchTeam from '@/components/select/searchTeam'
-
-export default {
-  components: {
-    DailyReport,
-    testPresenyL,
-    searchTeam
-  },
-  data() {
-    return {
-      send: false,
-      form: {},
-      preview: {},
-      dailyNewData: {},
-      dialogDaliy: false,
-      showOne: true,
-      showTow: false,
-      showThree: false,
-      radio: '1',
-      newIndex: '',
-      active: 1,
-      daily_task: [],
-      src: daily,
-      dailys: this.$route.query.id
-    }
-  },
-  destroyed() {
-    this.showThree = false
-  },
-  methods: {
-    init(index, newData) {
-      this.dialogDaliy = true
-      var url = location.href // 获取url中"?"符后的字串
-      var arr = url.split('=')
-      switch (index) {
-        case 1:
-          this.daily_task = [Number(arr[1])]
-          this.showOne = true
-          this.showTow = false
-          this.showThree = false
-          this.active = 1
-          break
-        case 2:
-          this.dailyNewData = newData
-          this.dailyNewData.creatask = '编辑'
-          this.newIndex = 2
-          this.showOne = false
-          this.showTow = true
-          this.showThree = false
-          this.active = 2
-          break
-        case 3:
-          this.showOne = false
-          this.showTow = false
-          this.showThree = true
-          this.form = {}
-          this.preview = newData
-          this.active = 3
-          break
-        case 4:
-          this.daily_task = [Number(arr[1])]
-          this.dailyNewData = newData
-          this.dailyNewData.creatask = '复制'
-          this.newIndex = 1
-          this.showOne = false
-          this.showTow = true
-          this.showThree = false
-          this.active = 2
-          break
-        case 7:
-          this.daily_task = newData
-          this.dailyNewData.taskIds = newData
-          this.showOne = true
-          this.showTow = false
-          this.showThree = false
-          this.active = 1
-          break
-      }
-    },
-    handleClose() {
-      this.dialogDaliy = false
-      this.showThree = false
-      this.showOne = false
-      this.showTow = false
-      this.radio = '1'
-    },
-    handleClose1() {
-      this.active = 1
-      this.showOne = true
-      this.showTow = false
-    },
-    created_out() {
-      this.$refs.DailyReport.parentHandleclick(this.newIndex, this.daily_task, this.dailys)
-    },
-    gou_out() {
-      this.dailyNewData = this.preview
-      this.dailyNewData.creatask = '编辑'
-      this.active = 2
-      this.newIndex = 2
-      this.showOne = false
-      this.showTow = true
-      this.showThree = false
-    },
-    daily(e) {
-      this.preview = e
-      this.dailys = e.id
-      this.showOne = false
-      this.showTow = false
-      this.showThree = true
-      this.form = {}
-      this.active = 3
-    },
-    NextStep() {
-      switch (Number(this.radio)) {
-        case 1:
-          this.dailyNewData = {}
-          this.dailyNewData.taskIds = this.daily_task
-          this.dailyNewData.creatask = '新建'
-          this.showOne = false
-          this.showTow = true
-          this.active = 2
-          this.newIndex = 1
-          break
-        case 2:
-          this.$message({ message: '请选择要创建的‘模版’', type: 'error', duration: 1000, offset: 150 })
-          break
-      }
-    },
-    sendReport(e) {
-      if (e.name !== undefined) {
-        this.send = true
-        var ele = this.preview
-        setTimeout(() => {
-          html2canvas(document.getElementsByClassName('reportContent')[0], { useCORS: true }).then(canvas => {
-            var url = canvas.toDataURL('image/png', 1)
-            url = url.toString().substring(url.indexOf(',') + 1)
-            var postData = { 'reportId': ele.id, 'imgStr': url, 'url': window.location.href, 'emailUser': e.name ? e.name.join(',') : null, 'copyTo': e.names ? e.names.join(',') : null }
-            dailyReportSendmail(postData).then(res => {
-              res.code === 200 ? this.$message({ type: 'success', message: '报告发送中,请稍后进行邮件查收!' }) : this.$message({ type: 'error', message: '发送测试日报失败,请联系管理员!' })
-              this.send = false
-              this.handleClose()
-            })
-          })
-        }, 500)
-      } else {
-        this.$message({ message: '请填写邮箱', type: 'error', offset: 150 })
-      }
-    }
-  }
-}
-</script>
-
-<style scoped>
-._radio {
-  margin: 3% 0;
-  color: #333B4A;
-  font-size: 16pt
-}
-.descr {
-  width: 94%;
-  margin: auto;
-}
-.descr::-webkit-scrollbar{
-  width:0;
-}
-.div1 {
-  width: 60px;
-  font-size: 14px;
-  font-family: MicrosoftYaHei;
-  color: rgba(51,51,51,1);
-  line-height: 19px;
-}
-.titIcon {
-  width:4px;
-  height:17px;
-  background:#409EFF;
-  border-radius:1px;
-}
-.el-dialog__header {
-    padding: 0 !important;
-}
-</style>

+ 0 - 408
src/views/Platform/presentation/testPresentation.vue

@@ -1,408 +0,0 @@
-<template>
-  <div class="eleStyle">
-    <div class="header_sty">
-      <el-tabs v-model="activeName" style="margin: 2%; min-height: 84vh; font-size: 14px;" @tab-click="handleClick">
-        <el-tab-pane label="测试日报" name="first">
-          <div style="margin: 30px 0;">测试日报
-            <el-input v-model="state" size="medium" filterable placeholder="报告名称搜索" style="width:20%;margin: 0 10px;" @change="getList(state)" />
-            <el-button type="primary" size="medium" @click="getQueryData(1), centerDialogVisible = true">新建测试日报</el-button>
-          </div>
-          <template>
-            <el-table :data="tableData" size="mini" :header-cell-style="{ background: '#F2F3F6' }" fit border style="width: 100%">
-              <el-table-column label="报告名称" min-width="280" align="center">
-                <template slot-scope="scope">
-                  <a href="javascript:void(0)" style="color:#20a0ff" @click="toReportView(scope.row, 0)">{{ scope.row.reportName }}</a>
-                </template>
-              </el-table-column>
-              <el-table-column label="报告人" min-width="180" align="center">
-                <template slot-scope="scope">{{ scope.row.ownner }}</template>
-              </el-table-column>
-              <el-table-column label="创建时间" min-width="280" align="center">
-                <template slot-scope="scope">{{ scope.row.gmtCreate }}</template>
-              </el-table-column>
-              <el-table-column label="操作" align="center" fixed="right" min-width="230">
-                <template slot-scope="scope">
-                  <el-button size="mini" type="primary" plain @click="queryPresentation(scope.row)">更新</el-button>
-                  <el-button size="mini" type="danger" plain @click="delePresentation(scope.row.id, 0)">删除</el-button>
-                  <el-tooltip content="功能正在实现中···" placement="top">
-                    <el-button size="mini" type="info" plain>权限</el-button>
-                  </el-tooltip>
-                </template>
-              </el-table-column>
-            </el-table>
-          </template>
-          <el-pagination style="margin-top:30px;" align="center" :current-page="curIndex" :page-sizes="[5, 10, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
-        </el-tab-pane>
-        <el-tab-pane label="准出报告" name="second">
-          <div style="margin: 30px 0;">准出报告
-            <el-input v-model="state" size="medium" filterable placeholder="报告名称搜索" style="width:20%; margin: 0 10px;" @change="getListPern(state)" />
-            <el-button type="primary" size="medium" @click="getQueryData(2), centerDialogVisible = true">新建准出报告</el-button>
-          </div>
-          <template>
-            <el-table :data="tableData1" size="mini" :header-cell-style="{ background: '#F2F3F6' }" fit border style="width: 100%">
-              <el-table-column label="报告名称" min-width="150" align="center">
-                <template slot-scope="scope">
-                  <a href="javascript:void(0)" style="color:#20a0ff" @click="toReportView(scope.row, 1)">{{ scope.row.reportName }}</a>
-                </template>
-              </el-table-column>
-              <el-table-column label="报告人" min-width="150" align="center">
-                <template slot-scope="scope">{{ scope.row.ownner }}</template>
-              </el-table-column>
-              <el-table-column label="日期" min-width="150" align="center">
-                <template slot-scope="scope">{{ scope.row.gmtCreate }}</template>
-              </el-table-column>
-              <el-table-column label="状态" min-width="150" align="center">
-                <template slot-scope="scope">{{ scope.row.statusString }}</template>
-              </el-table-column>
-              <el-table-column label="操作" align="center" fixed="right" min-width="230">
-                <template slot-scope="scope">
-                  <el-button size="mini" plain type="primary" @click="queryPresentation1(scope.row)">更新</el-button>
-                  <el-button size="mini" type="danger" plain @click="delePresentation(scope.row.id, 1)">删除</el-button>
-                  <el-tooltip content="功能正在实现中···" placement="top">
-                    <el-button size="mini" type="info" plain>权限</el-button>
-                  </el-tooltip>
-                </template>
-              </el-table-column>
-            </el-table>
-          </template>
-          <el-pagination style="margin-top:30px;" align="center" :current-page="curIndex" :page-sizes="[5, 10, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total1" @size-change="handleSizeChange" @current-change="handleCurrentChangePern" />
-        </el-tab-pane>
-        <el-tab-pane label="提测报告" name="third">
-          <div style="margin: 30px 0;">提测报告
-            <el-input v-model="state" size="medium" filterable placeholder="报告名称搜索" style="width:20%; margin: 0 10px;" @change="getListTest(state)" />
-            <el-button type="primary" size="medium" @click="getQueryData(3), centerDialogVisible = true">新建提测报告</el-button>
-          </div>
-          <template>
-            <el-table :data="tableData2" size="mini" :header-cell-style="{ background: '#F2F3F6' }" fit border style="width: 100%">
-              <el-table-column label="报告名称" min-width="230" align="center">
-                <template slot-scope="scope">
-                  <a href="javascript:void(0)" style="color:#20a0ff" @click="toReportView(scope.row, 2)">{{ scope.row.name }}</a>
-                </template>
-              </el-table-column>
-              <el-table-column label="报告人" min-width="150" align="center">
-                <template slot-scope="scope">{{ scope.row.submitter }}</template>
-              </el-table-column>
-              <el-table-column label="日期" min-width="280" align="center">
-                <template slot-scope="scope">{{ scope.row.gmtCreate }}</template>
-              </el-table-column>
-              <el-table-column label="状态" min-width="150" align="center">
-                <template slot-scope="scope">{{ scope.row.statusString }}</template>
-              </el-table-column>
-              <el-table-column label="操作" align="center" fixed="right" min-width="230">
-                <template slot-scope="scope">
-                  <el-button size="mini" type="primary" plain @click="queryPresentation2(scope.row)">更新</el-button>
-                  <el-button size="mini" type="danger" plain @click="delePresentation(scope.row.id, 2)">删除</el-button>
-                  <el-tooltip content="功能正在实现中···" placement="top"><el-button type="info" plain size="mini">权限</el-button></el-tooltip>
-                </template>
-              </el-table-column>
-            </el-table>
-          </template>
-          <el-pagination style="margin-top:30px;" align="center" :current-page="curIndex" :page-sizes="[5, 10, 20, total]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total2" @size-change="handleSizeChange" @current-change="handleCurrentChangeTest" />
-        </el-tab-pane>
-      </el-tabs>
-      <!-- 日报/准出/提测选择任务 -->
-      <el-dialog title="选择任务" :visible.sync="centerDialogVisible" width="30%" center>
-        <div style="display: flex; align-items: center; justify-content: space-between; ">
-          <div style="width:100px;">选择任务 :</div>
-          <el-select v-model="queryData.code" filterable placeholder="请选择任务" size="mini" style="width:100%;">
-            <el-option v-for="item in restaurants" :key="item.id" :label="item.name" :value="item.id" />
-          </el-select>
-        </div>
-        <span slot="footer" class="dialog-footer">
-          <el-button type="primary" size="mini" @click="createPresentation(queryData.code)">创建</el-button>
-        </span>
-      </el-dialog>
-    </div>
-    <TestReport v-if="dialogVisible1" ref="TestReport" />
-    <DailyReport v-if="dialogDaily" ref="DailyReport" />
-    <ClientReport v-if="dialogClient" ref="ClientReport" />
-  </div>
-</template>
-
-<script>
-import { dailyReportList, dailyReportDelete } from '@/api/testPresentetion' // 日报
-import { projectTestReportList, projectTestReportDelete } from '@/api/ResultPage' // 准出
-import { launchTestList, launchTestDelete, taskListCreate } from '@/api/InterfaceReport' // 提测
-import TestReport from '@/views/Platform/presentation/Templates/TestReport' // 提测
-import DailyReport from '@/views/Platform/presentation/Templates/DailyReport' // 日报
-import ClientReport from '@/views/Platform/presentation/Templates/ClientReport' // 准出
-
-export default {
-  name: 'TestPresentation',
-  components: {
-    TestReport,
-    DailyReport,
-    ClientReport
-  },
-  data() {
-    return {
-      activeName: 'first',
-      nowType: 0, // 当前报告类型
-      userInformation: localStorage.getItem('username'),
-      userNames: localStorage.getItem('realname'),
-      bizJson: localStorage.getItem('bizId'),
-      centerDialogVisible: false,
-      getListAllData: [],
-      pageSize: 5,
-      curIndex: 1,
-      total: 0,
-      state: '',
-      restaurants: [],
-      queryData: {
-        state: ''
-      },
-      tableData: [],
-      tableData2: [], // 提测报告
-      total2: 0,
-      z_name: '',
-      state2: '',
-      restaurants2: [],
-      arrCode: {
-        id: '',
-        name: ''
-      },
-      data_type: {},
-      total1: 0, // 准出
-      ins: '',
-      dialogVisible1: false, // 提测弹窗
-      dialogDaily: false,
-      dialogClient: false,
-      indexPage: {
-        pageSize: 5,
-        curIndex: 1
-      },
-      tableData1: [{}]
-    }
-  },
-  destroyed() {
-    this.$store.state.data.status = false
-  },
-  created() {
-    this.getList()
-    this.getListTest()
-    this.getListPern()
-    this.$store.state.data.status = true
-  },
-  mounted() {
-    this.getQueryData()
-  },
-  methods: {
-    handleClick(tab, event) {
-      this.curIndex = 1
-      switch (Number(tab.index)) {
-        case 0:
-          this.nowType = 0
-          this.getList()
-          break
-        case 1:
-          this.nowType = 1
-          this.getListPern()
-          break
-        case 2:
-          this.nowType = 2
-          this.getListTest()
-          break
-      }
-    },
-    getList(e) { // 日报list
-      this.z_name = e
-      var indexPage = { reportName: e, bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
-      dailyReportList(indexPage).then(res => {
-        if (res.code === 200) {
-          this.tableData = res.data
-          this.total = res.total
-        } else {
-          this.$message({ message: res.msg, type: 'error', duration: 1000, offset: 150 })
-        }
-      })
-    },
-    getListTest(ele) { // 提测list
-      this.z_name = ele
-      var indexPage = { name: ele, bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
-      launchTestList(indexPage).then(res => {
-        if (res.code === 200) {
-          this.tableData2 = res.data
-          this.total2 = res.total
-        } else {
-          this.$message({ message: res.msg, type: 'error', duration: 1000, offset: 150 })
-        }
-      })
-    },
-    getListPern(e) { // 准出list
-      this.z_name = e
-      this.indexPage = { reportName: e, bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
-      projectTestReportList(this.indexPage).then(res => {
-        if (res.code === 200) {
-          this.tableData1 = res.data
-          this.total1 = res.total
-        } else {
-          this.$message({ message: res.msg, type: 'error', duration: 1000, offset: 150 })
-        }
-      })
-    },
-    delePresentation(e, index) { // 日报/准出/提测/删除报告
-      this.$confirm('是否确认删除', '确认信息', {
-        distinguishCancelAndClose: true,
-        confirmButtonText: '确定',
-        cancelButtonText: '取消'
-      }).then(() => {
-        this.userData = { id: '', ename: this.userInformation, name: this.userNames }
-        switch (index) {
-          case 0:
-            dailyReportDelete(this.userData, e).then(res => {
-              this.getList()
-            })
-            break
-          case 1:
-            projectTestReportDelete(this.userData, e).then(res => {
-              this.getListPern()
-            })
-            break
-          case 2:
-            launchTestDelete(this.userData, e).then(res => {
-              this.getListTest()
-            })
-            break
-        }
-        this.$message({ type: 'success', message: '已删除' })
-      }).catch(action => {
-        this.$message({ type: 'success', message: '已取消' })
-      })
-    },
-    queryPresentation(data) { // 日报编辑
-      this.dialogDaily = true
-      this.$nextTick(() => {
-        this.$refs.DailyReport.init(2, data)
-      })
-    },
-    queryPresentation1(data) { // 准出编辑
-      this.dialogClient = true
-      this.$nextTick(() => {
-        this.$refs.ClientReport.init(2, data)
-      })
-    },
-    queryPresentation2(data) { // 提测编辑
-      this.dialogVisible1 = true
-      this.$nextTick(() => {
-        this.$refs.TestReport.init(2, data)
-      })
-    },
-    // 获取任务数据
-    getQueryData(e) {
-      this.ins = e
-      this.$set(this.queryData, 'TestReport', '')
-      this.$set(this.queryData, 'ClientReport', '')
-      this.$set(this.queryData, 'code', '')
-      this.restaurants = []
-      taskListCreate({ bizId: localStorage.getItem('bizId') }).then(res => {
-        this.restaurants = res.data.taskInfoList
-      })
-    },
-
-    createPresentation(e) {
-      if (e !== '') {
-        switch (this.ins) {
-          case 1:
-            this.dialogDaily = true
-            this.$nextTick(() => {
-              this.$refs.DailyReport.init(7, [e])
-            })
-            break
-          case 2:
-            this.dialogClient = true
-            this.$nextTick(() => {
-              this.$refs.ClientReport.init(7, [e])
-            })
-            break
-          case 3:
-            this.dialogVisible1 = true
-            this.$nextTick(() => {
-              this.$refs.TestReport.init(7, [e])
-            })
-            break
-        }
-        this.$set(this.queryData, 'code', '')
-        this.centerDialogVisible = false
-      } else {
-        this.$message({ message: '提示,请选择要添加的任务ID', type: 'warning' })
-      }
-    },
-    createFilter(queryString) {
-      return (restaurant) => {
-        return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
-      }
-    },
-
-    // 日报/准出/提测
-    toReportView(ele, index) {
-      switch (index) {
-        case 0:
-          this.dialogDaily = true
-          this.$nextTick(() => {
-            this.$refs.DailyReport.init(3, ele)
-          })
-          break
-        case 1:
-          this.dialogClient = true
-          this.$nextTick(() => {
-            this.$refs.ClientReport.init(3, ele)
-          })
-          break
-        case 2:
-          this.dialogVisible1 = true
-          this.$nextTick(() => {
-            this.$refs.TestReport.init(3, ele)
-          })
-          break
-      }
-    },
-    handleSizeChange(size) {
-      this.pageSize = size
-      switch (this.nowType) {
-        case 0:
-          this.getList(this.z_name)
-          break
-        case 1:
-          this.getListPern(this.z_name)
-          break
-        case 2:
-          this.getListTest(this.z_name)
-          break
-      }
-    },
-    handleCurrentChange(curIndex) {
-      this.curIndex = curIndex
-      this.getList(this.z_name)
-    },
-    handleCurrentChangeTest(curIndex) {
-      this.curIndex = curIndex
-      this.getListTest(this.z_name)
-    },
-    handleCurrentChangePern(curIndex) {
-      this.curIndex = curIndex
-      this.getListPern(this.z_name)
-    }
-  }
-}
-</script>
-<style scoped>
-  .eleStyle {
-    width: 100%;
-    height:100%;
-    background:#F2F3F6;
-    display: inline-block;
-  }
-  .header_sty {
-    height:100%;
-    width:98%;
-    background:#ffffff;
-    margin: 1%;
-    border-radius: 4px;
-    overflow: hidden;
-  }
-</style>
-<style lang="stylus">
-.el-tabs__nav-wrap::after {
-    background-color: #FFF !important;
-    }
-</style>

+ 19 - 7
src/views/ToConfigure/components/modifyNotice.vue

@@ -22,6 +22,7 @@
             placeholder="请选择"
             clearable
             :disabled="disabled"
+            class="input-width"
           />
         </el-form-item>
         <el-form-item v-if="type === 'task'" label="技术模块">
@@ -34,17 +35,18 @@
             placeholder="请选择"
             clearable
             :disabled="disabled"
+            class="input-width"
           />
         </el-form-item>
       </el-form>
       <el-form ref="form" :model="formData" label-width="100px" label-position="left" :inline="true">
         <el-form-item label="跟版客户端">
-          <el-select v-model="formData.clientId" placeholder="请选择" size="small" :disabled="disabled">
+          <el-select v-model="formData.clientId" placeholder="请选择" size="small" :disabled="disabled" clearable>
             <el-option v-for="item in appClientList" :key="'app'+item.code" :label="item.msg" :value="item.code" />
           </el-select>
         </el-form-item>
         <el-form-item>
-          <el-select v-model="formData.clientVersionId" placeholder="请选择" size="small" :disabled="disabled">
+          <el-select v-model="formData.clientVersionId" placeholder="请选择" size="small" :disabled="disabled" clearable>
             <el-option v-for="item in clientList" :key="'client'+item.code" :label="item.msg" :value="item.code" />
           </el-select>
         </el-form-item>
@@ -309,11 +311,15 @@ export default {
       },
       immediate: true
     },
-    // 'formData.clientId': { // 客户端改变,版本默认取第一个版本
-    //   handler(newV) {
-    //     this.formData.clientVersionId = (this.clientList[0] && this.clientList[0].code) || null
-    //   }
-    // },
+    'formData.clientId': { // 客户端改变,版本默认取第一个版本
+      handler(newV) {
+        // this.formData.clientVersionId = (this.clientList[0] && this.clientList[0].code) || null
+        console.log(newV)
+        if (newV === null || newV === '' || newV === undefined) {
+          this.formData.clientVersionId = null
+        }
+      }
+    },
     'noticeList.Email': {
       handler(newV, oldV) {
         if (newV) {
@@ -351,6 +357,7 @@ export default {
   methods: {
     initData(data) {
       this.formData = {
+        type: data.type,
         id: data.id,
         bizId: data.bizId,
         requireOrientIdList: data.requireOrientIdList, // 需求方向
@@ -615,6 +622,11 @@ article{
     font-size: 14px;
     margin-left: 5px;
   }
+  .input-width {
+    /deep/.el-input {
+      width: 402px;
+    }
+  }
 }
 .group-form {
   width: 280px;

+ 20 - 8
src/views/ToConfigure/components/noticeConfig.vue

@@ -41,7 +41,9 @@
               placement="bottom"
               popper-class="item-span-tooltip"
             >
-              <span>{{ item.copywriter.requirementArea || item.copywriter.taskArea }}</span>
+              <div class="detail-contain">
+                {{ item.copywriter.requirementArea || item.copywriter.taskArea }}
+              </div>
             </el-tooltip>
           </div>
           <div class="item-span">
@@ -52,7 +54,9 @@
               placement="bottom"
               popper-class="item-span-tooltip"
             >
-              <span>{{ item.copywriter.noticeConditionList.join(';') }}</span>
+              <div class="detail-contain">
+                {{ item.copywriter.noticeConditionList.join(';') }}
+              </div>
             </el-tooltip>
           </div>
           <div class="item-span">
@@ -379,18 +383,25 @@ ul,li{
       font-size: 12px;
       margin: 9px 0;
       width: 100%;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
+      display: flex;
+      flex-shrink: 0;
       label{
         color: #666666;
         font-weight: 200;
+        min-width: 70px;
       }
-      span {
-        color:#333333;
-        cursor: pointer;
+      .el-tooltip {
+        width: 100%;
       }
     }
+    .detail-contain {
+      color:#333333;
+      cursor: pointer;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      display: inline-block;
+    }
     .item-link {
       color:#409EFF;
       border: 1px solid #409EFF;
@@ -457,6 +468,7 @@ ul,li{
 .item-span-tooltip {
   background-color: rgba(121,132,150,0.8) !important;
   position: relative;
+  max-width: 300px !important;
 }
 .item-span-tooltip::before{
   content: '';

+ 0 - 67
src/views/apiManagement/apiList.vue

@@ -1,67 +0,0 @@
-<template>
-  <div>
-    <div v-if="isDetail == false" class="column">
-      <div class="titDiv">
-        <div class="titIcon" />
-        <div class="titSonName">{{ arr[0] }}</div>
-      </div>
-      {{ arr[1] }}
-      <el-table :data="tableData" :header-cell-style="{ background: '#F0F2F4', color: '#333B4A' }" size="mini" width="80%" border show-overflow-tooltip="true">
-        <el-table-column label="接口名称" prop="date" align="center" min-width="120">
-          <template slot-scope="scope">
-            <a href="javascript:void(0)" style="color:#20a0ff" @click="apiDetails(scope.row)">{{ scope.row.methodName }}</a>
-          </template>
-        </el-table-column>
-        <el-table-column label="接口路径" min-width="120" align="center">
-          <template slot-scope="scope">
-            {{ scope.row.methodPath }}
-          </template>
-        </el-table-column>
-      </el-table>
-    </div>
-    <apiDetails v-if="isDetail" :list-id="Number(listId)" />
-  </div>
-</template>
-
-<script>
-import '@/views/apiManagement/css/index.css'
-import apiDetails from '@/views/apiManagement/vue/index'
-import { getDocList } from '@/api/apiManagerment.js'
-export default {
-  components: {
-    apiDetails
-  },
-  props: {
-    orderId: { type: Number, default: null }
-  },
-  data() {
-    return {
-      isDetail: false,
-      listId: '',
-      tableData: [],
-      arr: ['乘客远程服务接口共 10 个', 'OrderVoucherRemoteService 代金券远程服务', 'PedestrianVehicleSepRemoteService 人车分离远程服务', 'SmoothMoveRemoteService 平滑移动远程服务', 'Vehicle2BOrderRemoteService B端商户远程服务', 'DriverOrderQueryRemoteService 司机订单查询远程服务']
-    }
-  },
-  watch: {
-    orderId: {
-      immediate: true,
-      handler(ele) {
-        ele === 0 ? this.getList(1) : this.getList(ele)
-      }
-    },
-    methods: {
-      apiDetails(val) {
-        this.listId = val.id
-        this.isDetail = true
-      },
-      async getList(data) {
-        const res = await getDocList(data)
-        if (res.code === 200) {
-          this.tableData = res.data
-        } else {
-          this.$notify({ title: 'Failed', message: res.msg, type: 'error', duration: 3000 })
-        }
-      }
-    }
-  }}
-</script>

+ 28 - 0
src/views/apiManagement/automatic.vue

@@ -0,0 +1,28 @@
+<template>
+  <div>
+    <!-- <iframe :src="envUrl" style="width:100%;" scrolling="no" frameborder="0" :height="iframeHeight" /> -->
+  </div>
+</template>
+
+<script>
+// import { host } from '@/apiConfig/requestIP.js'
+export default {
+  name: 'ENV',
+  data() {
+    return {
+      show: true
+      // iframeHeight: '720px'
+    }
+  },
+  computed: {
+    envUrl() {
+      return 'http://zhihui-api.intra.didichuxing.com/'
+    }
+  },
+  mounted() {
+    window.open('http://zhihui-api.intra.didichuxing.com/', '_blank')
+    // var height = window.innerHeight > document.body.clientHeight ? window.innerHeight : document.body.clientHeight
+    // this.iframeHeight = height + 'px'
+  }
+}
+</script>

+ 0 - 40
src/views/apiManagement/css/index.css

@@ -1,40 +0,0 @@
-.Management .el-divider--horizontal {
-  display: block;
-  height: 1px;
-  width: 100%;
-  margin: 0%;
-}
-
-.titDiv {
-  display: flex;
-  align-items: center;
-  margin: 20px 0;
-}
-
-.titIcon {
-  width: 4px;
-  height: 17px;
-  background: #409EFF;
-  border-radius: 1px;
-}
-
-.titSonName {
-  width: 268px;
-  height: 20px;
-  font-size: 16px;
-  font-weight: 500;
-  color: rgba(51, 59, 74, 1);
-  margin-left: 6px
-}
-
-.choice:hover {
-  color: #00A0FF;
-}
-
-.column .el-dialog__header {
-  padding: 0px;
-}
-
-.column .el-input--small .el-input__inner {
-  border-color: #ffffff;
-}

+ 0 - 713
src/views/apiManagement/index.vue

@@ -1,713 +0,0 @@
-<template>
-  <el-container style=" background: #F2F3F6;">
-    <el-aside class="ApiLeft">
-      <div class="Api_space_evenly">
-        <div :class="{'Api_Interface_list' : Interface_list === '接口列表'}" class="Api_cursor" @click="InterfaceLeft('接口列表')">接口列表</div>
-        <div :class="{'Api_Interface_list' : Interface_list === '接口分类'}" class="Api_cursor" @click="InterfaceLeft('接口分类')">接口分类</div>
-      </div>
-      <div class="Api_search">
-        <el-input v-model="filterText" style="width: 55%;margin-left:4%" size="mini" prefix-icon="el-icon-search" clearable filterable placeholder="请搜索接口" />
-        <el-button v-if="Interface_list === '接口列表'" style="margin-left:4%" type="primary" size="mini">查询</el-button>
-        <el-button v-if="Interface_list === '接口分类'" style="margin-left:4%" type="primary" size="mini" @click="addType()">添加分类</el-button>
-      </div>
-      <div>
-        <el-tree
-          v-if="Interface_list === '接口分类'"
-          ref="tree"
-          class="filter-tree"
-          :data="list"
-          node-key="id"
-          :props="defaultProps"
-          empty-text="无相关接口,请确定搜索内容"
-          default-expand-all
-          :default-expanded-keys="key_arr"
-          :expand-on-click-node="false"
-          :filter-node-method="filterNode"
-          @node-click="handleNodeClick"
-        >
-          <!-- eslint-disable-next-line vue/no-template-shadow -->
-          <span slot-scope="{ node, data }" style="width:100%;display: flex; align-items: center; justify-content: space-between;" class="custom-tree-node" @mouseenter="mouseenter(data)" @mouseleave="mouseleave(data)">
-            <span>{{ node.label }}</span>
-            <span v-show="data.parentId === 0 && data.del === true">
-              <el-tooltip class="item" effect="dark" content="添加接口" placement="top">
-                <span v-if="Interface_list === '接口分类'" class="el-icon-plus Api_btn" @click="() => append(data)" />
-              </el-tooltip>
-              <el-tooltip class="item" effect="dark" content="删除文档" placement="top">
-                <span v-if="Interface_list === '接口分类'" class="el-icon-delete Api_btn" @click="() => remove(data)" />
-              </el-tooltip>
-            </span>
-          </span>
-        </el-tree>
-        <el-tree
-          v-if="Interface_list === '接口列表'"
-          :data="list1"
-          node-key="id"
-          empty-text="无相关接口,请确定搜索内容"
-          :default-expanded-keys="key_arr"
-          :expand-on-click-node="false"
-          @node-click="handleNodeClick1"
-        /></div>
-      <div align="center" style="margin: 2% 0 10%;"><el-input v-if="ElMenu" v-model="filterText" style="width: 90%;" size="mini" prefix-icon="el-icon-search" clearable filterable placeholder="请搜索接口" /></div>
-    </el-aside>
-    <el-main class="ApiRight">
-      <div v-if="home" class="ApiRightContent">
-        <div class="Layout">
-          <div class="titFont" style="padding: 15px 0; font-size: 22px; font-family:PingFangSC-Medium,PingFang SC;font-weight:500; color:rgba(51,59,74,1); line-height:35px;">API </div>
-        </div>
-        <el-divider style="color: #EEF0F5; margin: 0 !important" />
-        <div style="font-size:18px; padding: 8% 0 1%; font-family:PingFangSC-Medium,PingFang SC; font-weight:500; color:rgba(51,59,74,1); line-height:35px;">API接口管理平台介绍及接入文档</div>
-        <div style="font-size:14px; width: 80%; font-family:PingFangSC-Regular,PingFang SC; font-weight:400; color:rgba(102,102,102,1); line-height:20px;">计划与EMC合作建设公司级反馈平台,覆盖所有内外部反馈,内部大区、客服等渠道反馈,专项工作组case反馈跟踪等场景,项目较大,处于立项阶段,期望收集更多信息和建议。</div>
-      </div>
-
-      <!-- 接口分类的列表 -->
-      <div v-if="isList" class="ApiRight">
-        <div class="ApiRightContent" style="overflow:scroll; overflow-x: hidden;margin-left:-11px;margin-top:-10px;">
-          <div>
-            <div class="column">
-              <div class="titDiv">
-                <div class="titIcon" />
-                <div class="titSonName">{{ clickData.docName }}</div>
-              </div>
-              <el-table :data="typeListData" :header-cell-style="{ background: '#F0F2F4', color: '#333B4A' }" size="mini" width="80%" border show-overflow-tooltip="true">
-                <el-table-column label="接口名称" prop="date" align="center" min-width="120">
-                  <template slot-scope="scope">
-                    <a href="javascript:void(0)" style="color:#20a0ff" @click="clickDetail(scope.row.id)">{{ scope.row.methodName }}</a>
-                  </template>
-                </el-table-column>
-                <el-table-column label="接口路径" min-width="120" align="center">
-                  <template slot-scope="scope">
-                    {{ scope.row.methodPath }}
-                  </template>
-                </el-table-column>
-              </el-table>
-            </div>
-          </div>
-        </div>
-      </div>
-      <!-- 接口列表的列表 -->
-      <div v-if="isList1" class="ApiRight">
-        <div class="ApiRightContent" style="overflow:scroll; overflow-x: hidden;margin-left:-11px;margin-top:-10px;">
-          <div>
-            <div class="column">
-              <div class="titDiv">
-                <div class="titIcon" />
-                <div class="titSonName">{{ clickData.docName }}</div>
-              </div>
-              <el-table :data="tableData1" :header-cell-style="{ background: '#F0F2F4', color: '#333B4A' }" size="mini" width="80%" border show-overflow-tooltip="true">
-                <el-table-column label="方法名称" prop="prettyshortprint" align="center" min-width="120">
-                  <template slot-scope="scope">
-                    <a href="javascript:void(0)" style="color:#20a0ff" @click="clickDetail(scope.row.id)">{{ scope.row.prettyShortPrint }}</a>
-                  </template>
-                </el-table-column>
-              </el-table>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 接口详情 -->
-      <div v-if="detail" class="ApiRight">
-        <div class="ApiRightContent" style="overflow:scroll; overflow-x: hidden;margin-left:-11px;margin-top:-10px;">
-          <div class="column">
-            <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
-              <el-menu-item index="1">预览</el-menu-item>
-              <el-menu-item index="2" disabled>编辑</el-menu-item>
-              <el-menu-item index="3" disabled>运行</el-menu-item>
-            </el-menu>
-
-            <div class="titDiv">
-              <div class="titIcon" />
-              <div class="titSonName">基本信息</div>
-            </div>
-
-            <div style="display:flex;justify-content:space-between;width:65%;margin-left:3%;margin-top:4%">
-              <div class="searchName">接口名称 :
-                {{ baseData.methodName }}
-              </div>
-              <div class="searchName">创建人 :
-                {{ clickData.creator }}
-              </div>
-            </div>
-            <div style="display:flex;justify-content:space-between;width:65%;margin-left:3%;margin-top:3%">
-              <div class="searchName">更新时间 :
-                {{ baseData.gmtModify | formatDate }}
-              </div>
-              <div class="searchName">api版本号 :
-                {{ baseData.currentVersion }}
-              </div>
-            </div>
-            <div style="display:flex;justify-content:space-between;width:100%;margin-left:3%;margin-top:3%">
-              <div class="searchName">接口路径 : {{ baseData.methodPath }}</div>
-            </div>
-
-            <div class="titDiv" style="margin-top:40px">
-              <div class="titIcon" />
-              <div class="titSonName">备注</div>
-            </div>
-            <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-              {{ baseData.memo }}
-            </div>
-
-            <div class="titDiv" style="margin-top:40px">
-              <div class="titIcon" />
-              <div class="titSonName">请求参数</div>
-            </div>
-            <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-              <div class="searchName">Query : </div>
-            </div>
-
-            <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-              <el-table
-                :data="paramData"
-                style="width: 100%;margin-top:10px"
-                row-key="id"
-                border
-                stripe
-                lazy
-                :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
-                :header-cell-style="{ background: '#cccccc', color: '#606266' }"
-              >
-                <el-table-column prop="fieldName" label="参数名称" />
-                <el-table-column prop="fieldType" label="参数类型" />
-              </el-table>
-            </div>
-            <div class="titDiv" style="margin-top:40px">
-              <div class="titIcon" />
-              <div class="titSonName">返回数据</div>
-            </div>
-            <div class="Layout">
-              <el-input
-                v-model="didi"
-                style="color:#333B4A"
-                type="textarea"
-                :autosize="{ minRows: 15, maxRows: 15}"
-                :placeholder="didi"
-              />
-            </div>
-          </div>
-        </div>
-      </div>
-    </el-main>
-
-    <!-- 新建分类 -->
-    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogAddTypeVisible" width="40%">
-      <div style="margin-left:60px">
-        <el-form ref="addDeviceForms" :rules="addTreeTypeRules" :model="addTreeType">
-          <el-form-item label="分类名" prop="docName" label-width="80px">
-            <el-input v-model="addTreeType.docName" size="small" clearable style="width:75%;" placeholder="请填写" />
-          </el-form-item>
-          <el-form-item label="备注" label-width="80px">
-            <el-input v-model="addTreeType.text" size="small" clearable style="width:75%;" placeholder="请填写" />
-          </el-form-item>
-        </el-form>
-      </div>
-      <div slot="footer" class="dialog-footer">
-        <el-button size="small" @click="dialogAddTypeVisible = false">取消</el-button>
-        <el-button size="small" type="primary" @click="addTreeTpye(addTreeType)">确定</el-button>
-      </div>
-    </el-dialog>
-
-    <!--添加接口-->
-    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogAddPortVisible" width="60%">
-      <div style="margin-left:60px">
-        <el-form ref="addTreeTypeForms" :rules="addTreeTypeRules" :model="addTreeType">
-          <el-form-item label="接口名称" prop="docName" label-width="120px">
-            <el-input v-model="addTreeType.docName" size="small" style="width:75%;" clearable placeholder="请填写" />
-          </el-form-item>
-          <el-form-item label="项目" prop="projectName" label-width="120px">
-            <el-select v-model="addTreeType.projectName" size="small" class="filter-item" filterable clearable placeholder="请填写" style="width:75%;" @change="getModuleOpt()">
-              <el-option v-for="item in projectOpt" :key="item.key" :label="item.value" :value="item.value" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="模块" prop="projectModule" label-width="120px">
-            <el-select v-model="addTreeType.projectModule" size="small" class="filter-item" filterable clearable placeholder="请填写" style="width:75%;" @change="getVersionOpt()">
-              <el-option v-for="item in moduleOpt" :key="item.key" :label="item.value" :value="item.value" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="版本" prop="version" label-width="120px">
-            <el-select v-model="addTreeType.version" size="small" class="filter-item" filterable clearable placeholder="请填写" style="width:75%;" @change="getApiOpt()">
-              <el-option v-for="item in versionOpt" :key="item.key" :label="item.value" :value="item.value" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="接口类名" prop="interfaceId" label-width="120px">
-            <el-select v-model="addTreeType.interfaceId" size="small" class="filter-item" filterable clearable placeholder="请填写" style="width:75%;" @change="getMethodOpt()">
-              <el-option v-for="item in apiOpt" :key="item.id" :label="item.interfacePath" :value="item.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="方法名" prop="methodId" label-width="120px">
-            <el-select v-model="addTreeType.methodId" size="small" class="filter-item" filterable clearable placeholder="请填写" style="width:75%;">
-              <el-option v-for="item in methodsOpt" :key="item.id" :label="item.prettyShortPrint" :value="item.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="备注" label-width="120px">
-            <el-input v-model="addTreeType.text" size="small" style="width:75%;" clearable placeholder="请填写" />
-          </el-form-item>
-        </el-form>
-      </div>
-      <div slot="footer" class="dialog-footer">
-        <el-button size="small" @click="dialogAddPortVisible = false">取消</el-button>
-        <el-button size="small" type="primary" @click="addPortTpye(addTreeType)">确定</el-button>
-      </div>
-      <div style="margin-top:5%" />
-    </el-dialog>
-  </el-container>
-
-</template>
-
-<script>
-import '@/views/projectManage/publicCss/index.css'
-import '@/views/apiManagement/css/index.css'
-import dayjs from 'dayjs'
-import { getParam, getReturn, getApiDetail, getPortDoc, getDocList, createType, getInterfaceInfoListByBizLineId, getProject, getModule, getVersion, getApi, delProject, getMethod, getMethodList } from '@/api/apiManagerment.js'
-
-export default {
-  filters: {
-    formatDate(e) {
-      return dayjs(e).format('YYYY-MM-DD HH:mm:ss')
-    }
-  },
-  data() {
-    return {
-      id: '',
-      label: '',
-      key_arr: [],
-      Interface_list: '接口列表',
-      value: '',
-      home: true,
-      ElMenu: false,
-      detail: false,
-      isList: false,
-      isList1: false,
-      defaultProps: {
-        children: 'children',
-        label: 'label'
-      },
-      docName: '',
-      parentId: '',
-      dialogAddPortVisible: false,
-      dialogAddTypeVisible: false,
-      userInformation: localStorage.getItem('username'),
-      userNames: localStorage.getItem('realname'),
-      textMap: {
-        addType: '添加分类',
-        addPort: '添加接口',
-        editPort: '编辑接口'
-      },
-      dialogStatus: '',
-      addTreeType: {},
-      data: {},
-      bizLineId: {},
-      addTreeTypeRules: {
-        docName: [{ required: true, message: '不能为空', trigger: 'change' }],
-        projectName: [{ required: true, message: '不能为空', trigger: 'change' }],
-        projectModule: [{ required: true, message: '不能为空', trigger: 'change' }],
-        version: [{ required: true, message: '不能为空', trigger: 'change' }],
-        interfaceId: [{ required: true, message: '不能为空', trigger: 'change' }],
-        methodId: [{ required: true, message: '不能为空', trigger: 'change' }]
-
-      },
-      list: [],
-      list1: [],
-      portTreeList: [],
-      projectOpt: [],
-      moduleOpt: [],
-      versionOpt: [],
-      apiOpt: [],
-      filterText: '',
-      typeListData: [],
-      typeListData1: [],
-      clickData: {}, // 点击树获取到的数据
-      methodsOpt: [],
-      didi: '{"code":200,"data":[{"id":6,"docName":"86979","parentId":0,"fileType":1,"children":[]},{"id":1,"docName":"测试文档","parentId":0,"fileType":0,"children":[{"id":3,"docName":"测试文档2","parentId":1,"fileType":1,"children":[{"id":4,"docName":"测试文档3","parentId":3,"fileType":1,"children":[]},{"id":5,"docName":"测试文档4","parentId":3,"fileType":1,"children":[]}]},{"id":2,"docName":"测试小文档","parentId":1,"fileType":2,"methodId":1,"children":[]}]}],"msg":"OK"}',
-      paramData: [],
-      activeIndex: '1',
-      baseData: {},
-      tableData1: [],
-      lastChildrens: [],
-      name: [],
-      all_bizId: [] // 业务线
-    }
-  },
-  watch: {
-    filterText(val) {
-      this.$refs.tree.filter(val)
-    }
-  },
-  created() {
-    this.$store.state.data.status = true
-    this.getPortTree()
-    this.getListTree()
-    this.getProjectOpt()
-  },
-  destroyed() {
-    this.$store.state.data.status = false
-  },
-
-  methods: {
-    InterfaceLeft(vel) {
-      vel === '接口分类' ? this.Interface_list = '接口分类' : this.Interface_list = '接口列表'
-    },
-    append(data) { // 添加节点
-      this.dialogAddPortVisible = true
-      this.dialogStatus = 'addPort'
-      this.parentId = data.id
-      // this.$refs.addTreeTypeForms.resetFields()
-    },
-    mouseenter(data) { // 导航栏显示新建/删除/编辑
-      this.$set(data, 'del', true)
-    },
-    mouseleave(data) { // 导航栏隐藏新建/删除/编辑
-      this.$set(data, 'del', false)
-    },
-
-    // 根据方法id获取详情
-    clickDetail(data) {
-      this.detail = true
-      this.isList1 = false
-      this.isList = false
-      this.getapiDetails(data)
-    },
-    getapiDetails(data) {
-      getApiDetail(data).then(response => {
-        this.baseData = response.data
-        this.getParams(data)
-        this.getReturns(data)
-      })
-    },
-    handlerData(arr) {
-      return arr.map((item, index) => {
-        return {
-          key: index,
-          value: item
-        }
-      })
-    },
-    // 获取新增接口里的枚举值
-    getProjectOpt() {
-      getProject(Number(localStorage.getItem('bizId'))).then(response => {
-        this.projectOpt = this.handlerData(response.data)
-      })
-    },
-    getModuleOpt(bizLineId, projectName) {
-      getModule(Number(localStorage.getItem('bizId')), this.addTreeType.projectName).then(response => {
-        this.moduleOpt = this.handlerData(response.data)
-      })
-    },
-    getVersionOpt(bizLineId, projectName, projectModule) {
-      getVersion(Number(localStorage.getItem('bizId')), this.addTreeType.projectName, this.addTreeType.projectModule).then(response => {
-        this.versionOpt = this.handlerData(response.data)
-      })
-    },
-    getApiOpt() {
-      getApi(this.addTreeType.projectName, this.addTreeType.projectModule, this.addTreeType.version).then(response => {
-        this.apiOpt = response.data
-      })
-    },
-    getMethodOpt(data) {
-      getMethod(this.addTreeType.interfaceId).then(response => {
-        this.methodsOpt = response.data
-      })
-    },
-    // 根据ID获取分类列表
-    getTypeList() {
-      getDocList(this.clickData.id).then(response => {
-        this.typeListData = response.data
-      })
-    },
-
-    // 根据ID获取接口列表
-    getApiList(data) {
-      getMethodList(data).then(response => {
-        this.typeListData1 = response.data
-      })
-    },
-    // 获取接口分类树
-    getPortTree() {
-      getPortDoc(Number(localStorage.getItem('bizId'))).then(response => {
-        this.list = response.data
-        this.list = this.list.map(item => ({
-          ...item,
-          label: item.docName,
-          children: item.children ? item.children.map(item => ({
-            ...item,
-            label: item.docName,
-            children: item.children ? item.children.map(item => ({
-              ...item,
-              label: item.docName,
-              children: item.children ? item.children.map(item => ({
-                ...item,
-                label: item.docName
-              })) : ''
-            })) : ''
-          })) : ''
-        }))
-        this.portTreeList = []
-      })
-    },
-    // 获取接口列表树
-    getListTree() {
-      getInterfaceInfoListByBizLineId(Number(localStorage.getItem('bizId'))).then(response => {
-        this.list1 = response.data
-        this.list1 = this.list1.map(item => ({
-          ...item,
-          label: item.docName,
-          parentId: item.children ? 0 : 1,
-          children: item.children ? item.children.map(item => ({
-            ...item,
-            label: item.docName,
-            children: item.children ? item.children.map(item => ({
-              ...item,
-              label: item.docName,
-              children: item.children ? item.children.map(item => ({
-                ...item,
-                label: item.docName
-              })) : ''
-            })) : ''
-          })) : ''
-        }))
-        this.portTreeList = []
-        this.list1.map(item => {
-          this.findLastChildren(item.children)
-        })
-      })
-    },
-
-    // 添加接口
-    addPortTpye(data) {
-      this.$refs['addTreeTypeForms'].validate((valid) => {
-        if (valid) {
-          this.addTreeType.bizLineId = Number(localStorage.getItem('bizId'))
-          this.addTreeType.fileType = 2
-          this.addTreeType.parentId = this.parentId
-          this.addTreeType.creator = this.userNames
-          createType(this.addTreeType).then(response => {
-            if (response.code === 200) {
-              this.getPortTree()
-              this.getTypeList()
-              this.dialogAddPortVisible = false
-              this.$notify({ title: 'Success', message: response.msg, type: 'success', duration: 3000 })
-            } else {
-              this.$notify({ title: 'Failed', message: response.msg, type: 'error', duration: 3000 })
-            }
-          })
-        }
-      })
-    },
-
-    // 添加分类
-    addTreeTpye(data) {
-      this.addTreeType.docName = data.docName
-      this.addTreeType.fileType = 1
-      this.addTreeType.creator = this.userNames
-      this.addTreeType.bizLineId = Number(localStorage.getItem('bizId'))
-      createType(this.addTreeType).then(response => {
-        if (response.code === 200) {
-          this.getPortTree()
-          this.dialogAddTypeVisible = false
-          this.$notify({ title: 'Success', message: response.msg, type: 'success', duration: 3000 })
-        } else {
-          this.$notify({ title: 'Failed', message: response.msg, type: 'error', duration: 3000 })
-        }
-      })
-    },
-    // 删除节点
-    remove(node, data) {
-      this.$confirm('是否确认?', '删除接口', {
-        distinguishCancelAndClose: true,
-        confirmButtonText: '确定',
-        cancelButtonText: '取消'
-      })
-        .then(() => {
-          delProject(this.clickData.id).then(response => {
-            if (response.code === 200) {
-              this.getPortTree()
-              this.$notify({ title: 'Success', message: response.msg, type: 'success', duration: 3000 })
-            } else {
-              this.$notify({ title: 'Failed', message: response.msg, type: 'error', duration: 3000 })
-            }
-          })
-        })
-        .catch(action => {
-          this.$message({ type: 'success', message: '已取消' })
-        })
-    },
-    // 接口分类点击节点
-    handleNodeClick(data) {
-      this.clickData = data
-      if (data.parentId === 0) {
-        this.isList = true
-        this.home = false
-        this.detail = false
-        this.isList1 = false
-        this.getTypeList(this.clickData.id)
-      }
-      if (data.parentId !== 0) {
-        this.detail = true
-        this.home = false
-        this.isList = false
-        this.isList1 = false
-        this.getapiDetails(this.clickData.methodId)
-      }
-    },
-    // 接口列表点击节点
-    handleNodeClick1(data) {
-      this.clickData = data
-      this.clickData = data
-      if (data.children) {
-        this.isList = false
-        this.isList1 = false
-        this.home = true
-        this.detail = false
-        this.findLastChildren(data.children)
-      }
-      if (!data.children) {
-        this.isList1 = true
-        this.home = false
-        this.isList = false
-        this.detail = false
-        this.getMethodListById(this.clickData.id)
-      }
-    },
-    // 找到树最后的子节点
-    findLastChildren(arr) {
-      arr.map(item => {
-        if (item.children) {
-          this.findLastChildren(item.children)
-        } else {
-          this.name = (item.label).split('.')
-          item.label = this.name[this.name.length - 1]
-          this.lastChildrens.push(item)
-        }
-      })
-    },
-    // 添加方法
-    addPort() {
-      this.dialogAddPortVisible = true
-      this.dialogStatus = 'addPort'
-    },
-    // 添加分类
-    addType() {
-      this.dialogAddTypeVisible = true
-      this.dialogStatus = 'addType'
-    },
-
-    handleSelect(key, keyPath) {
-      console.log(key, keyPath)
-    },
-    // 转成json
-    getLsit: function(jsonStr) {
-      var res = ''
-      for (var i = 0, j = 0, k = 0, ii, ele; i < jsonStr.length; i++) { // k:缩进,j:""个数
-        ele = jsonStr.charAt(i)
-        if (j % 2 === 0 && ele === '}') {
-          k--
-          for (ii = 0; ii < k; ii++) ele = '    ' + ele
-          ele = '\n' + ele
-        } else if (j % 2 === 0 && ele === '{') {
-          ele += '\n'
-          k++
-          for (ii = 0; ii < k; ii++) ele += '    '
-        } else if (j % 2 === 0 && ele === ',') {
-          ele += '\n'
-          for (ii = 0; ii < k; ii++) ele += '    '
-        } else if (ele === '"') j++
-        res += ele
-      }
-      // eslint-disable-next-line no-return-assign
-      return this.didi = res
-    },
-    // 点击接口列表方法
-    getMethodListById(ele) {
-      getMethodList(ele).then(response => {
-        this.tableData1 = response.data
-      })
-    },
-    // 获取接口详情页请求参数
-    getParams(ele) {
-      getParam(ele).then(response => {
-        this.paramData = response.data
-      })
-    },
-    // 获取接口详情页返回参数
-    getReturns(ele) {
-      getReturn(ele).then(response => {
-        this.didi = JSON.stringify(response.data)
-        this.getLsit(this.didi)
-      })
-    },
-    // 过滤树
-    filterNode(value, data) {
-      if (!value) return true
-      return data.label.indexOf(value) !== -1
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-  .ApiLeft {
-    padding: 10px 0px 0px 10px;
-    background: #FFF;
-    color: #333B4A;
-    margin: 10px 0px 10px 10px;
-    min-height: calc(100vh - 76px);
-    .Api_search {
-      margin: 10px 0;
-    }
-    .Api_btn {
-      margin: 0 5px;
-      cursor: pointer;
-    }
-    .Api_btn:hover {
-      color: #409EFF;
-    }
-  }
-  .ApiRight {
-    padding: 10px;
-    background: #F2F3F6;
-    color: #333B4A;
-    min-height: calc(100vh - 65px);
-    .ApiRightContent {
-      background: #FFF;
-      min-height: calc(100vh - 75px);
-      padding: 0.5% 3%;
-      border-radius: 4px;
-      .Layout_space_between{
-        /deep/ .el-table--striped .el-table__body tr.el-table__row--striped td {
-        background: #cccccc;}
-      }
-      .searchName {
-        font-size:14px;
-        font-family:MicrosoftYaHei;
-        line-height:17px;
-        color:#909399;
-        opacity:1;
-        font-weight: 600;}
-      }
-  }
-  .custom-tree-node {
-    flex: 1;
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    font-size: 14px;
-    padding-right: 8px;
-  }
-
-  .Api_space_evenly {  // 布局
-    display: flex;
-    align-items: center;
-    justify-content: space-evenly;
-  }
-
-  .Api_Interface_list { // 接口列表和接口分类按钮颜色
-    color: #409EFF;
-    border-bottom: 2px solid #409EFF;
-    padding-bottom: 3px;
-  }
-
-  .Api_cursor { // 小手
-    cursor: pointer;
-  }
-
-</style>

+ 0 - 237
src/views/apiManagement/vue/index.vue

@@ -1,237 +0,0 @@
-<template>
-  <div class="column">
-    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
-      <el-menu-item index="1">预览</el-menu-item>
-      <el-menu-item index="2" disabled>编辑</el-menu-item>
-      <el-menu-item index="3" disabled>运行</el-menu-item>
-    </el-menu>
-
-    <div class="titDiv">
-      <div class="titIcon" />
-      <div class="titSonName">基本信息</div>
-    </div>
-
-    <div class="Layout_space_between" style="margin-left: 20px">
-      <div style="flex:1;margin-top:20px" class="Layout_flex_start">
-        <div class="searchName">接口名称 : </div>
-        <span style="margin-left: 8px;color:#606266">
-          {{ baseData.methodName }}
-        </span>
-      </div>
-      <div style="flex:1;margin-top:20px" class="Layout_flex_start">
-        <div class="searchName">创建人 : </div>
-        <span style="margin-left: 8px;color:#606266">
-          {{ baseData.name }}
-        </span>
-      </div>
-    </div>
-    <div class="Layout_flex_start" style="margin-left: 20px">
-      <div style="flex:1;;margin-top:20px" class="Layout_flex_start">
-        <div class="searchName">更新时间 : </div>
-        <span style="margin-left: 8px;color:#606266">
-          {{ baseData.gmtModify | formatDate }}
-        </span>
-      </div>
-      <div style="flex:1;margin-top:20px" class="Layout_flex_start">
-        <div class="searchName">api版本号 : </div>
-        <span style="margin-left: 8px;color:#606266">
-          {{ baseData.currentVersion }}
-        </span>
-      </div>
-    </div>
-
-    <div class="Layout_flex_start" style="margin-left: 20px">
-      <div class="Layout_space_between" style="margin-top:20px">
-        <div class="searchName">接口路径 : </div>
-        <span style="margin-left: 8px;color:#606266">
-          {{ baseData.methodPath }}
-        </span>
-      </div>
-    </div>
-
-    <div class="titDiv" style="margin-top:40px">
-      <div class="titIcon" />
-      <div class="titSonName">备注</div>
-    </div>
-    <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-      {{ baseData.memo }}
-    </div>
-
-    <div class="titDiv" style="margin-top:40px">
-      <div class="titIcon" />
-      <div class="titSonName">请求参数</div>
-    </div>
-    <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-      <div class="searchName">Query : </div>
-    </div>
-
-    <div class="Layout_space_between" style="margin-left: 20px;color:#606266">
-      <el-table
-        :data="paramData"
-        style="width: 100%;margin-top:10px"
-        row-key="id"
-        border
-        stripe
-        lazy
-        :load="load"
-        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
-        :header-cell-style="{ background: '#cccccc', color: '#606266' }"
-      >
-        <el-table-column prop="fieldName" label="参数名称" />
-        <el-table-column prop="fieldType" label="参数类型" />
-      </el-table>
-    </div>
-    <div class="titDiv" style="margin-top:40px">
-      <div class="titIcon" />
-      <div class="titSonName">返回数据</div>
-    </div>
-    <div class="Layout">
-      <el-input
-        v-model="didi"
-        style="color:#333B4A"
-        type="textarea"
-        :autosize="{ minRows: 15, maxRows: 15}"
-        :placeholder="didi"
-      />
-    </div>
-  </div>
-</template>
-
-<script>
-import '@/views/apiManagement/css/index.css'
-import '@/styles/PublicStyle/index.scss'
-import dayjs from 'dayjs'
-import { getMethodList, getParam, getReturn } from '@/api/apiManagerment.js'
-
-export default {
-  filters: {
-    formatDate(e) {
-      return dayjs(e).format('YYYY-MM-DD HH:mm:ss')
-    }
-  },
-  props: {
-    orderId: { type: Number, default: null },
-    listId: { type: Number, default: null }
-  },
-  data() {
-    return {
-      didi: '{"code":200,"data":[{"id":6,"docName":"86979","parentId":0,"fileType":1,"children":[]},{"id":1,"docName":"测试文档","parentId":0,"fileType":0,"children":[{"id":3,"docName":"测试文档2","parentId":1,"fileType":1,"children":[{"id":4,"docName":"测试文档3","parentId":3,"fileType":1,"children":[]},{"id":5,"docName":"测试文档4","parentId":3,"fileType":1,"children":[]}]},{"id":2,"docName":"测试小文档","parentId":1,"fileType":2,"methodId":1,"children":[]}]}],"msg":"OK"}',
-      value: '',
-      derId: this.orderId,
-      paramData: [],
-      centerDialogVisible: false,
-      describe: '',
-      textarea2: '',
-      activeIndex: '1',
-      baseData: {},
-      tableData: [],
-      tableData1: [],
-      arr: ['PassRemoteService 乘客远程服务', 'OrderVoucherRemoteService 代金券远程服务', 'PedestrianVehicleSepRemoteService 人车分离远程服务', 'SmoothMoveRemoteService 平滑移动远程服务', 'Vehicle2BOrderRemoteService B端商户远程服务', 'DriverOrderQueryRemoteService 司机订单查询远程服务']
-    }
-  },
-  watch: {
-    orderId: {
-      immediate: true,
-      handler(ele) {
-        ele === 0 ? this.getParams(1) : this.getParams(ele)
-        ele === 0 ? this.getReturns(1) : this.getReturns(ele)
-        ele === 0 ? this.getMethodListById(1) : this.getMethodListById(ele)
-      }
-    },
-    listId: {
-      immediate: true,
-      handler(show) {
-        show === 0 ? this.getParams(1) : this.getParams(show)
-        show === 0 ? this.getReturns(1) : this.getReturns(show)
-        show === 0 ? this.getMethodListById(1) : this.getMethodListById(show)
-      }
-    }
-  },
-  created() {
-    this.getLsit(this.didi)
-    // this.getParams()
-    // this.getMethodListById()
-  },
-  methods: {
-    init(e, ele) {
-      console.log(e)
-    },
-    handleSelect(key, keyPath) {
-      console.log(key, keyPath)
-    },
-    getLsit: function(jsonStr) {
-      var res = ''
-      for (var i = 0, j = 0, k = 0, ii, ele; i < jsonStr.length; i++) { // k:缩进,j:""个数
-        ele = jsonStr.charAt(i)
-        if (j % 2 === 0 && ele === '}') {
-          k--
-          for (ii = 0; ii < k; ii++) ele = '    ' + ele
-          ele = '\n' + ele
-        } else if (j % 2 === 0 && ele === '{') {
-          ele += '\n'
-          k++
-          for (ii = 0; ii < k; ii++) ele += '    '
-        } else if (j % 2 === 0 && ele === ',') {
-          ele += '\n'
-          for (ii = 0; ii < k; ii++) ele += '    '
-        } else if (ele === '"') j++
-        res += ele
-      }
-      // eslint-disable-next-line no-return-assign
-      return this.didi = res
-    },
-    getMethodListById(ele) {
-      getMethodList(ele).then(response => {
-        this.baseData = response.data
-      })
-    },
-
-    getParams(ele) {
-      getParam(ele).then(response => {
-        this.paramData = response.data
-      })
-    },
-
-    getReturns(ele) {
-      getReturn(ele).then(response => {
-        this.didi = JSON.stringify(response.data)
-        this.getLsit(this.didi)
-      })
-    },
-
-    load(tree, treeNode, resolve) {
-      setTimeout(() => {
-        resolve([
-          {
-            id: 31,
-            date: '2016-05-01',
-            name: '王小虎',
-            address: '上海市普陀区金沙江路 1519 弄'
-          }, {
-            id: 32,
-            date: '2016-05-01',
-            name: '王小虎',
-            address: '上海市普陀区金沙江路 1519 弄'
-          }
-        ])
-      }, 1000)
-    }
-  }
-}
-</script>
-<style lang="scss" scoped>
-.searchName {
-  font-size:14px;
-  font-family:MicrosoftYaHei;
-  line-height:17px;
-  color:#909399;
-  opacity:1;
-  font-weight: 600;
-}
-.Layout_space_between{
-  /deep/ .el-table--striped .el-table__body tr.el-table__row--striped td {
-    background: #cccccc;
-}
-}
-
-</style>

+ 305 - 223
src/views/mock/httprule.vue

@@ -88,9 +88,9 @@
 
       <el-table-column label="操作" align="center" min-width="370" class-name="small-padding fixed-width" fixed="right">
         <template slot-scope="{row}">
-          <el-button type="primary" size="mini" @click="handleCheck(row)"> 查看 </el-button>
-          <el-button type="primary" size="mini" @click="handleUpdate(row)"> 编辑 </el-button>
-          <el-button type="primary" size="mini" @click="handleCopy(row)"> 复制 </el-button>
+          <el-button type="primary" size="mini" @click="handleUpdate(row,'show')"> 查看 </el-button>
+          <el-button type="primary" size="mini" @click="handleUpdate(row,'edit')"> 编辑 </el-button>
+          <el-button type="primary" size="mini" @click="handleUpdate(row,'copy')"> 复制 </el-button>
           <el-button type="primary" size="mini"> 测试 </el-button>
           <el-button v-if="row.status!=1" size="mini" type="success" @click="handleModifyStatus(row, 1)"> 开启 </el-button>
           <el-button v-if="row.status!=0" size="mini" type="danger" @click="handleModifyStatus(row, 0)"> 关闭 </el-button>
@@ -100,54 +100,134 @@
 
     <pagination v-show="total>0" :total="total" :page.sync="listQuery.curIndex" :limit.sync="listQuery.pageSize" @pagination="getList" />
 
-    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%" @open="isNotAnyRequest">
+    <el-dialog v-if="dialogFormVisible" :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="65%">
+      <main class="dialog-style">
+        <el-form ref="ruleForm" :rules="rulesCheck" :model="ruleForm" label-width="100px" label-position="left">
+          <el-row v-if="isNotAnyRequest" class="set-Width">
+            <el-col :span="4">
+              <el-form-item label="条件" prop="expression1">
+                <el-select v-model="ruleForm.expression1" clearable placeholder="请选择表达式" style="width: 8vw;" fiterable size="medium" @change="chooseTest1">
+                  <el-option v-for="item in expressOptions" :key="item.desc" :label="item.descChn" :value="item.desc" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="4">
+              <el-form-item label="" prop="expression2">
+                <el-input v-model="ruleForm.expression2" clearable placeholder="请输入参数" style="width: 8vw;" filterable size="medium" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="4">
+              <el-form-item label="" prop="judgeType">
+                <el-select v-model="ruleForm.judgeType" clearable placeholder="请选择运算方式" style="width: 8vw;" filterable size="medium">
+                  <el-option v-for="item1 in operatorOptions" :key="item1.character" :label="item1.desc" :value="item1.character" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="4">
+              <el-form-item label="" prop="judgeValue">
+                <el-input v-model="ruleForm.judgeValue" clearable placeholder="请输入值" style="width: 8vw;" filterable size="medium" />
+              </el-form-item>
+            </el-col>
+          </el-row>
 
-      <el-form ref="ruleForm" :rules="rulesCheck" :model="ruleForm" label-width="150px" style="width: 83%;">
-        <el-row v-if="isNotAnyRequest" class="set-Width">
-          <el-col :span="4">
-            <el-form-item label="条件" prop="expression1">
-              <el-select v-model="ruleForm.expression1" clearable placeholder="请选择表达式" style="width: 8vw;" fiterable size="medium" @change="chooseTest1">
-                <el-option v-for="item in expressOptions" :key="item.desc" :label="item.descChn" :value="item.desc" />
-              </el-select>
+          <el-form-item v-if="showguiz" label="条件" prop="whenScript">
+            <el-select v-model="ruleForm.whenScript" clearable placeholder="请选择表达式" fiterable @change="chooseTest1">
+              <el-option v-for="item1 in expressOptions" :key="item1.d6sc" :label="item1.descChn" :value="item1.desc" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="描述" prop="ruleDesc">
+            <el-input v-model="ruleForm.ruleDesc" placeholder="请输入描述" />
+          </el-form-item>
+          <el-form-item label="优先级" prop="execSort">
+            <el-tooltip class="item" effect="light" content="值越大,优先级越高" placement="right">
+              <el-input-number v-model="ruleForm.execSort" label="优先级" :min="1" :max="100" />
+            </el-tooltip>
+          </el-form-item>
+          <el-form-item label="返回值" prop="returnMessage">
+            <el-input v-model="ruleForm.returnMessage" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" :placeholder="jsonTit" />
+          </el-form-item>
+
+          <section>
+            <el-checkbox v-model="ruleForm.isCallback" class="callback-titile">添加回调接口</el-checkbox>
+            <el-form-item v-if="ruleForm.isCallback" label="回调接口" prop="callbackInfo.name">
+              <el-autocomplete
+                v-model="ruleForm.callbackInfo.name"
+                :fetch-suggestions="searchCallback"
+                placeholder="请输入"
+                style="width: 100%"
+                :hide-loading="true"
+                @select="handleSelect"
+              />
             </el-form-item>
-          </el-col>
-          <el-col :span="4">
-            <el-form-item label="" prop="expression2">
-              <el-input v-model="ruleForm.expression2" clearable placeholder="请输入参数" style="width: 8vw;" filterable size="medium" />
+            <el-form-item v-if="ruleForm.isCallback" label="回调延迟" prop="callbackInfo.delayTime">
+              <el-input-number
+                v-model="ruleForm.callbackInfo.delayTime"
+                controls-position="right"
+                :min="0"
+              /><span style="margin-left: 10px">毫秒</span>
             </el-form-item>
-          </el-col>
-          <el-col :span="4">
-            <el-form-item label="" prop="judgeType">
-              <el-select v-model="ruleForm.judgeType" clearable placeholder="请选择运算方式" style="width: 8vw;" filterable size="medium">
-                <el-option v-for="item1 in operatorOptions" :key="item1.character" :label="item1.desc" :value="item1.character" />
-              </el-select>
+            <h2 v-if="ruleForm.isCallback">Basic</h2>
+            <el-form-item v-if="ruleForm.isCallback" label="接口名称" prop="callbackInfo.name">
+              <el-input
+                v-model="ruleForm.callbackInfo.name"
+                placeholder="请输入"
+              />
             </el-form-item>
-          </el-col>
-          <el-col :span="4">
-            <el-form-item label="" prop="judgeValue">
-              <el-input v-model="ruleForm.judgeValue" clearable placeholder="请输入值" style="width: 8vw;" filterable size="medium" />
+            <el-form-item v-if="ruleForm.isCallback" label="请求地址" prop="callbackInfo.host">
+              <el-input
+                v-model="ruleForm.callbackInfo.host"
+                placeholder="请输入"
+              />
             </el-form-item>
-          </el-col>
-        </el-row>
-
-        <el-form-item v-if="showguiz" label="条件" prop="whenScript">
-          <el-select v-model="ruleForm.whenScript" clearable placeholder="请选择表达式" fiterable @change="chooseTest1">
-            <el-option v-for="item1 in expressOptions" :key="item1.d6sc" :label="item1.descChn" :value="item1.desc" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="描述" prop="ruleDesc" style="width:52vw; white-space:nowrap;">
-          <el-input v-model="ruleForm.ruleDesc" placeholder="请输入描述" />
-        </el-form-item>
-        <el-form-item label="优先级" prop="execSort">
-          <el-tooltip class="item" effect="light" content="值越大,优先级越高" placement="right">
-            <el-input-number v-model="ruleForm.execSort" label="优先级" :min="1" :max="100" />
-          </el-tooltip>
-        </el-form-item>
-        <el-form-item label="返回值" prop="returnMessage" style="width:52vw;margin-top: 4%;">
-          <el-input v-model="ruleForm.returnMessage" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" :placeholder="jsonTit" />
-        </el-form-item>
-      </el-form>
-
+            <el-form-item v-if="ruleForm.isCallback" label="请求路径" prop="callbackInfo.url">
+              <el-input
+                v-model="ruleForm.callbackInfo.url"
+                placeholder="请输入"
+              />
+            </el-form-item>
+            <el-form-item v-if="ruleForm.isCallback" label="请求方式" prop="callbackInfo.method">
+              <el-select v-model="ruleForm.callbackInfo.method" placeholder="请选择">
+                <el-option
+                  v-for="item in [{ value: 'GET' }, { value: 'POST' }, { value: 'PUT' }, { value: 'DELETE' }]"
+                  :key="item.value"
+                  :label="item.value"
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+            <h2 v-if="ruleForm.isCallback">Request</h2>
+            <el-radio-group v-if="ruleForm.isCallback" v-model="selectType" size="small">
+              <el-radio-button label="header" />
+              <el-radio-button label="params" />
+              <el-radio-button label="body" />
+            </el-radio-group>
+            <div v-show="selectType==='header' && ruleForm.isCallback">
+              <div v-for="(item,index) in headerList" :key="'header'+index" class="header-list-item">
+                <div>配置:</div>
+                <div><el-input v-model="item.key" placeholder="key" size="small" /></div>
+                <div><el-input v-model="item.value" placeholder="value" size="small" /></div>
+                <div><el-input v-model="item.desc" placeholder="描述信息" size="small" /></div>
+                <i class="el-icon-remove-outline" @click="removeMoules(selectType,index)" />
+              </div>
+            </div>
+            <div v-show="selectType==='params' && ruleForm.isCallback">
+              <div v-for="(item,index) in paramsList" :key="'params'+index" class="header-list-item">
+                <div>配置:</div>
+                <div><el-input v-model="item.key" placeholder="key" size="small" /></div>
+                <div><el-input v-model="item.value" placeholder="value" size="small" /></div>
+                <div><el-input v-model="item.desc" placeholder="描述信息" size="small" /></div>
+                <i class="el-icon-remove-outline" @click="removeMoules(selectType,index)" />
+              </div>
+            </div>
+            <div v-show="selectType==='body' && ruleForm.isCallback" class="request-body">
+              <el-input v-model="bodyObj" :autosize="{ minRows: 3, maxRows: 10}" type="textarea" placeholder="{id:1}" />
+            </div>
+            <div v-if="ruleForm.isCallback" class="add-button">
+              <el-button v-show="selectType!=='body'" type="primary" icon="el-icon-plus" size="small" @click="addMoules(selectType)">新增配置</el-button>
+            </div>
+          </section>
+        </el-form>
+      </main>
       <div slot="footer" class="dialog-footer">
         <el-button @click="dialogFormVisible = false"> 取消 </el-button>
         <el-button v-if="showSubmit" type="primary" @click=" dialogStatus === 'create'?createData(ruleForm):updateData(ruleForm)"> 确定 </el-button>
@@ -157,7 +237,8 @@
 </template>
 
 <script>
-import { fetchEnvInfo, fetchRuleById, fetchRuleList, createRule, updateRule, changeStatus, getHttpOp, getExpress } from '@/api/httprule'
+const _ = require('lodash')
+import { fetchEnvInfo, queryById, fetchRuleList, createRule, updateRule, changeStatus, getHttpOp, getExpress, callbackQuery } from '@/api/httprule'
 import waves from '@/directive/waves' // waves directive
 import { parseTime } from '@/utils'
 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
@@ -196,7 +277,9 @@ export default {
         minPrior: 100,
         execSort: 1,
         ruleDesc: '',
-        metaRuleList: [{ operator: '', expression1: '', expression2: '', judgeType: '', judgeValue: '', and: '', or: '', prior: '', bracket: '' }]
+        metaRuleList: [{ operator: '', expression1: '', expression2: '', judgeType: '', judgeValue: '', and: '', or: '', prior: '', bracket: '' }],
+        isCallback: false,
+        callbackInfo: {}
       },
       rulesCheck: {
         metaRuleList: [{ required: true, message: '条件不能为空', trigger: 'change' }],
@@ -207,7 +290,12 @@ export default {
         expression1: [{ required: true, message: '请输入方法', trigger: 'change' }],
         expression2: [{ required: true, message: '请输入运算符', trigger: 'change' }],
         judgeType: [{ required: true, message: '请选择匹配规则', trigger: 'change' }],
-        judgeValue: [{ required: true, message: '请选择参数', trigger: 'change' }]
+        judgeValue: [{ required: true, message: '请选择参数', trigger: 'change' }],
+        'callbackInfo.name': [{ required: true, message: '请填写回调接口名', trigger: 'change' }],
+        'callbackInfo.delayTime': [{ required: true, message: '请填写回调延迟', trigger: 'change' }],
+        'callbackInfo.host': [{ required: true, message: '请填写请求地址', trigger: 'change' }],
+        'callbackInfo.url': [{ required: true, message: '请填写请求路径', trigger: 'change' }],
+        'callbackInfo.method': [{ required: true, message: '请填写请求方式', trigger: 'change' }]
       },
       tableKey: 0,
       list: null,
@@ -248,7 +336,11 @@ export default {
         create: '新增'
       },
       desc: true,
-      dataFrom: {}
+      dataFrom: {},
+      selectType: 'header', // 当前选择的类型
+      headerList: [], // header配置列表
+      paramsList: [], // params配置列表
+      bodyObj: null // body配置对象
     }
   },
   created() {
@@ -258,13 +350,47 @@ export default {
     this.getExpress()
   },
   methods: {
-    // getExpressOpt(index) {
-    //   if (index === 0) {
-    //     return this.expressOptions
-    //   } else {
-    //     return this.expressOptionWithutAny
-    //   }
-    // },
+    searchCallback: _.debounce(async(e, cb) => {
+      if (!e)e = ''
+      const res = await callbackQuery(e)
+      if (res.code === 200) {
+        cb(res.data.map(item => {
+          return {
+            ...item,
+            value: item.name
+          }
+        }))
+      }
+    }, 500),
+    handleSelect(callbackInfo) { // 处理选择的回调接口
+      if (callbackInfo && callbackInfo.header) {
+        this.headerList = JSON.parse(callbackInfo.header)
+        delete callbackInfo.header
+      }
+      if (callbackInfo && callbackInfo.params) {
+        this.paramsList = JSON.parse(callbackInfo.params)
+        delete callbackInfo.params
+      }
+      if (callbackInfo && callbackInfo.body) {
+        this.bodyObj = callbackInfo.body
+        delete callbackInfo.body
+      }
+      this.ruleForm.callbackInfo = callbackInfo
+    },
+    addMoules(type) { // 新增配置
+      if (type === 'header') {
+        this.headerList.push({ key: '', value: '', desc: '' })
+      } else if (type === 'params') {
+        this.paramsList.push({ key: '', value: '', desc: '' })
+      }
+    },
+    removeMoules(type, index) { // 移除配置
+      if (type === 'header') {
+        this.headerList.splice(index, 1)
+      } else if (type === 'params') {
+        this.paramsList.splice(index, 1)
+      }
+    },
     chooseTest1(val) {
       if (val === 'any') {
         this.$set(this.ruleForm, 'whenScript', val)
@@ -277,26 +403,7 @@ export default {
         this.isNotAnyRequest = true
         this.showguiz = false
       }
-      // if (this.ruleForm.metaRuleList[0].expression1 === 'any request') {
-      //   this.isNotAnyRequest = false
-      //   this.isAnyshow = true
-      // } else {
-      //   this.isNotAnyRequest = true
-
-      // this.paramOptions.push(0,0,{ name: 'any', value: 0 })
-      // }
     },
-
-    // chooseTest2(val) {
-    //   this.expression2 = val
-    // },
-    // chooseTest3(val) {
-    //   this.ruleForm.metaRuleList.judgeType = val
-    // },
-    // chooseTest4(val) {
-    //   this.ruleForm.metaRuleList.judgeValue = val
-    // },
-
     // 获取运算符
     getHttpOp() {
       getHttpOp().then(response => {
@@ -307,12 +414,6 @@ export default {
     getExpress() {
       getExpress().then(response => {
         this.expressOptions = response.data
-        // this.expressOptions.forEach((opt, index) => {
-        //   if (opt.desc === 'any request') {
-        //     return true
-        //   }
-        //   this.expressOptionWithutAny.push(opt)
-        // })
       })
     },
     prev() {
@@ -390,25 +491,13 @@ export default {
       this.listQuery.methodStatus = this.listQuery.value
       this.getList()
     },
-    // sortChange(data) {
-    //   const { prop, order } = data
-    //   if (prop === 'id') {
-    //     this.sortByID(order)
-    //   }
-    // },
-    // sortByID(order) {
-    //   if (order === 'ascending') {
-    //     this.listQuery.sort = '+id'
-    //   } else {
-    //     this.listQuery.sort = '-id'
-    //   }
-    //   this.handleFilter()
-    // },
     handleCreate() {
       this.dialogStatus = 'create'
       this.dialogFormVisible = true
       this.showSubmit = true
-      this.ruleForm = {}
+      this.ruleForm = {
+        callbackInfo: { name: null, delayTime: 0, method: 'GET' }
+      }
       this.isNotAnyRequest = false
       this.showguiz = true
       this.$set(this.ruleForm, 'whenScript', 'any')
@@ -419,20 +508,17 @@ export default {
         this.$refs['ruleForm'].clearValidate()
       })
     },
-
     // 新增Data
     createData(vel) {
       if (typeof vel.returnMessage === 'string') {
         this.$refs['ruleForm'].validate((valid) => {
           if (valid) {
-            this.dataFrom = vel
+            this.dataFrom = _.cloneDeep(vel)
             this.dataFrom.creator = this.userNames
             this.dataFrom.creatorEn = this.username
             this.dataFrom.updator = ''
             this.dataFrom.methodId = parseInt(this.$route.path.split('/')[4])
             this.dataFrom.methodProtocol = 'http'
-            this.dataFrom = vel
-            this.dataFrom = vel
 
             this.showguiz === false ? this.dataFrom.whenScript = '' : ''
             this.isNotAnyRequest === false ? this.dataFrom.metaRuleList = [] : this.dataFrom.metaRuleList = [{ 'operator': '', 'expression': vel.expression1 + '.' + vel.expression2, 'judgeType': vel.judgeType, 'judgeValue': vel.judgeValue }]
@@ -441,46 +527,75 @@ export default {
             delete this.dataFrom.judgeType
             delete this.dataFrom.judgeValue
             delete this.dataFrom.id
-
-            createRule(this.dataFrom).then(response => {
-              if (response.code === 200) {
-                this.dialogFormVisible = false
-                this.getList()
-                this.$notify({ title: 'Success', message: response.msg, type: 'success', duration: 2000 })
-              } else {
-                this.$notify({ title: 'Failed', message: response.msg, type: 'error', duration: 2000 })
-              }
-            })
+            if (this.headerList.length > 0) {
+              this.dataFrom.callbackInfo.header = JSON.stringify(this.headerList)
+            }
+            if (this.paramsList.length > 0) {
+              this.dataFrom.callbackInfo.params = JSON.stringify(this.paramsList)
+            }
+            if (this.bodyObj !== null && this.bodyObj !== '') {
+              this.dataFrom.callbackInfo.body = this.bodyObj
+            }
+            if (!this.ruleForm.isCallback) {
+              this.dataFrom.callbackInfo = null
+            }
+            this.createRule()
           }
         })
       }
     },
-
+    async createRule() {
+      const response = await createRule(this.dataFrom)
+      if (response.code === 200) {
+        this.dialogFormVisible = false
+        this.getList()
+        this.$notify({ title: 'Success', message: response.msg, type: 'success', duration: 2000 })
+      } else {
+        this.$notify({ title: 'Failed', message: response.msg, type: 'error', duration: 2000 })
+      }
+    },
     // 编辑Data
-    handleUpdate(row) {
-      var queryData = { id: row.id }
-      fetchRuleById(queryData).then(response => {
-        this.ruleForm = response.data.mockRuleList[0]
-        if (this.ruleForm.whenScript !== '') {
-          this.isNotAnyRequest = false
-          this.showguiz = true
-        }
-        if (this.ruleForm.metaRuleList.length !== 0) {
-          this.isNotAnyRequest = true
-          this.showguiz = false
-          for (var a of this.ruleForm.metaRuleList) {
-            this.ruleForm.expression1 = a.expression.split('.')[0]
-            this.ruleForm.expression2 = a.expression.split('.')[1]
-            this.ruleForm.judgeType = a.judgeType
-            this.ruleForm.judgeValue = a.judgeValue
-          }
+    async handleUpdate(row, type) {
+      const response = await queryById(row.id)
+      this.ruleForm = response.data
+      if (this.ruleForm.whenScript !== '') {
+        this.isNotAnyRequest = false
+        this.showguiz = true
+      }
+      if (this.ruleForm.metaRuleList.length !== 0) {
+        this.isNotAnyRequest = true
+        this.showguiz = false
+        for (const a of this.ruleForm.metaRuleList) {
+          this.ruleForm.expression1 = a.expression.split('.')[0]
+          this.ruleForm.expression2 = a.expression.split('.')[1]
+          this.ruleForm.judgeType = a.judgeType
+          this.ruleForm.judgeValue = a.judgeValue
         }
-        this.dialogStatus = 'update'
-        this.dialogFormVisible = true
-        this.showSubmit = true
-        this.$nextTick(() => {
-          this.$refs['ruleForm'].clearValidate()
-        })
+      }
+      const callbackInfo = this.ruleForm.callbackInfo
+      if (!this.ruleForm.callbackInfo) {
+        this.ruleForm.callbackInfo = {}
+      }
+      if (!this.ruleForm.isCallback) {
+        this.ruleForm.isCallback = false
+      }
+      if (callbackInfo && callbackInfo.header) {
+        this.headerList = JSON.parse(callbackInfo.header)
+        delete callbackInfo.header
+      }
+      if (callbackInfo && callbackInfo.params) {
+        this.paramsList = JSON.parse(callbackInfo.params)
+        delete callbackInfo.params
+      }
+      if (callbackInfo && callbackInfo.body) {
+        this.bodyObj = callbackInfo.body
+        delete callbackInfo.body
+      }
+      this.dialogStatus = type === 'copy' ? 'create' : 'update'
+      this.dialogFormVisible = true
+      this.showSubmit = type !== 'show'
+      this.$nextTick(() => {
+        this.$refs['ruleForm'].clearValidate()
       })
     },
     handleModifyStatus(row, status) {
@@ -498,34 +613,6 @@ export default {
       })
     },
 
-    // 复制Data
-    handleCopy(row) {
-      var queryData = { id: row.id }
-      fetchRuleById(queryData).then(response => {
-        this.ruleForm = response.data.mockRuleList[0]
-        if (this.ruleForm.whenScript !== '') {
-          this.isNotAnyRequest = false
-          this.showguiz = true
-        }
-        if (this.ruleForm.metaRuleList.length !== 0) {
-          this.isNotAnyRequest = true
-          this.showguiz = false
-          for (var a of this.ruleForm.metaRuleList) {
-            this.$set(this.ruleForm, 'expression1', a.expression.split('.')[0])
-            this.$set(this.ruleForm, 'expression2', a.expression.split('.')[1])
-            this.$set(this.ruleForm, 'judgeType', a.judgeType)
-            this.$set(this.ruleForm, 'judgeValue', a.judgeValue)
-          }
-        }
-        this.dialogStatus = 'create'
-        this.dialogFormVisible = true
-        this.showSubmit = true
-        this.$nextTick(() => {
-          this.$refs['ruleForm'].clearValidate()
-        })
-      })
-    },
-
     // 编辑提交
     updateData(vel) {
       if (typeof vel.returnMessage === 'string') {
@@ -547,28 +634,31 @@ export default {
             delete this.dataFrom.expression2
             delete this.dataFrom.judgeType
             delete this.dataFrom.judgeValue
-            //   const tempData = Object.assign({}, this.ruleData)
-            // const tempData = {
-            //   id: this.ruleForm.id,
-            //   methodId: parseInt(this.$route.path.split('/')[4]),
-            //   updator: '',
-            //   execSort: this.ruleForm.execSort,
-            //   whenScript: this.ruleForm.whenScript,
-            //   returnMessage: this.ruleForm.returnMessage,
-            //   mehtodName: this.$route.query.methodName,
-            //   methodProtocol: this.$route.query.methodProtocol,
-            //   metaRuleList: [],
-            //   ruleDesc: this.ruleForm.ruleDesc
-            // }
-            updateRule(this.dataFrom).then(() => {
-              this.getList()
-              this.dialogFormVisible = false
-              this.$notify({ title: 'Success', message: 'Update Successfully', type: 'success', duration: 2000 })
-            })
+            if (this.headerList.length > 0) {
+              this.dataFrom.callbackInfo.header = JSON.stringify(this.headerList)
+            }
+            if (this.paramsList.length > 0) {
+              this.dataFrom.callbackInfo.params = JSON.stringify(this.paramsList)
+            }
+            if (this.bodyObj !== null && this.bodyObj !== '') {
+              this.dataFrom.callbackInfo.body = this.bodyObj
+            }
+            if (!this.ruleForm.isCallback) {
+              this.dataFrom.callbackInfo = null
+            }
+            this.updateRule()
           }
         })
       }
     },
+    async updateRule() {
+      const res = await updateRule(this.dataFrom)
+      if (res.code === 200) {
+        this.getList()
+        this.dialogFormVisible = false
+        this.$notify({ title: 'Success', message: 'Update Successfully', type: 'success', duration: 2000 })
+      }
+    },
     formatJson(filterVal, jsonData) {
       return jsonData.map(v => filterVal.map(j => {
         if (j === 'timestamp') {
@@ -577,53 +667,45 @@ export default {
           return v[j]
         }
       }))
-    },
-
-    // 查看
-    handleCheck(row) {
-      var queryData = { id: row.id }
-      fetchRuleById(queryData).then(response => {
-        var row_data = response.data.mockRuleList
-        this.ruleForm = Object.assign({}, row_data[0])
-        if (this.ruleForm.whenScript !== '') {
-          this.isNotAnyRequest = false
-          this.showguiz = true
-        }
-        if (this.ruleForm.metaRuleList.length !== 0) {
-          this.isNotAnyRequest = true
-          this.showguiz = false
-          for (var a of this.ruleForm.metaRuleList) {
-            this.ruleForm.expression1 = a.expression.split('.')[0]
-            this.ruleForm.expression2 = a.expression.split('.')[1]
-            this.ruleForm.judgeType = a.judgeType
-            this.ruleForm.judgeValue = a.judgeValue
-          }
-        }
-        this.dialogStatus = 'update'
-        this.dialogFormVisible = true
-        this.showSubmit = false
-        this.$nextTick(() => {
-          this.$refs['ruleForm'].clearValidate()
-        })
-      })
     }
-    // descEnter(index, row) {
-    //   this.listQuery.ruleDescSeen = true
-    //   this.desc = false
-    // },
-    // descLeave(row) {
-    //   this.listQuery.ruleDescSeen = false
-    //   this.desc = true
-    // }
   }
 }
 </script>
 
-<style>
-.el-notification.right{
+<style lang="scss" scoped>
+/deep/.el-notification.right{
   position: fixed;
-  right: 38.5%;}
-  .set-Width .el-form-item__error {
-    width: 90px;
+  right: 38.5%;
+  }
+.set-Width .el-form-item__error {
+  width: 90px;
+}
+.dialog-style {
+  padding: 20px 80px 20px 20px;
+  max-height: 500px;
+  overflow: scroll;
+  .callback-titile {
+    color: #333333;
+    margin-bottom: 20px;
+  }
+  .header-list-item {
+    display: grid;
+    grid-template-columns: 7% 30% 30% 30% 3%;
+    align-items: center;
+    margin: 10px 0;
+    div{
+      padding-left: 10px;
+    }
+    i {
+      margin: auto;
+    }
+  }
+  .request-body {
+    margin-top: 10px;
   }
+  .add-button {
+    margin-top: 20px;
+  }
+}
+.dialog-style::-webkit-scrollbar {display:none}
 </style>

+ 28 - 16
src/views/projectManage/bugList/bugindex.vue

@@ -143,24 +143,23 @@
                   <div style="margin: 1.5% 0;" class="flex_start">
                     <div class="Layout">
                       <div class="queryName">缺陷类型</div>
-                      <el-select
-                        v-model="formInline.theBugType"
-                        size="small"
+                      <el-cascader
+                        v-model="formInline.theBugTypes"
+                        :options="theBugTypeEnumList"
+                        :props="{
+                          value:'code',
+                          label:'name',
+                          children: 'childrenEnums',
+                          multiple: true,
+                          emitPath: false
+                        }"
                         clearable
-                        filterable
                         placeholder="请选择"
-                        @change="changeSelect()"
-                      >
-                        <el-option
-                          v-for="item in bugTypeEnumList"
-                          :key="item.code"
-                          :label="item.name"
-                          :value="item.code"
-                        />
-                      </el-select>
+                        size="small"
+                      />
                     </div>
                     <div class="Layout marginLeft">
-                      <div class="queryName">Reopen</div>
+                      <div class="queryName">是否发生Reopen</div>
                       <el-select
                         v-model="formInline.reopenTimes"
                         size="small"
@@ -320,7 +319,7 @@ export default {
       Editionlist: [], // 版本
       bizIdEnumList: [], // bug业务线
       taskEnumList: [], // 所属任务
-      bugTypeEnumList: [], // bug类型
+      theBugTypeEnumList: [], // 缺陷类型
       priorityEnumList: [], // 缺陷等级
       clientTypeEnumList: [], // 版本
       repairResultEnumList: [], // 修复结果
@@ -438,7 +437,6 @@ export default {
       })
       bugGetEnum().then(res => {
         this.bugEnumList = res.data.bugEnumList // status
-        this.bugTypeEnumList = res.data.theBugTypeEnumList // bug类型
         this.bugStageEnumList = res.data.bugStageEnumList // 发现阶段
         this.sysTypeEnumList = res.data.sysTypeEnumList // 端类型
         this.discoveryMethEnumList = res.data.discoveryMethEnumList // 发现方式
@@ -448,11 +446,25 @@ export default {
         this.clientTypeEnumList = res.data.clientTypeEnumList // 版本
         this.sysTypeEnumList = res.data.sysTypeEnumList // 客户端
         this.bugDevRepairTimeList = res.data.bugDevRepairTimeList // 开发修复时长
+        this.theBugTypeEnumList = this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
       })
       releaseList().then(res => {
         this.appClient = res.data.appClient // 客户端
       })
     },
+    deleteChild(arr) { // 删除无用子属性
+      const bfs = arr => {
+        arr.forEach(item => {
+          if (!item.childrenEnums || item.childrenEnums.length === 0) {
+            delete item.childrenEnums
+          } else {
+            this.deleteChild(item.childrenEnums)
+          }
+        })
+      }
+      bfs(arr)
+      return arr
+    },
     bugDataGet() {
       // 所属模块
       settingQueryBizModuleList(Number(localStorage.getItem('bizId'))).then(

+ 1 - 0
src/views/projectManage/bugList/css/index.css

@@ -200,6 +200,7 @@
   width: 86px;
   color: #333333;
   font-size: 14px;
+  flex-shrink: 0;
 }
 .download {
   position: absolute;

+ 15 - 1
src/views/projectManage/bugList/details/bugTableDialog.vue

@@ -138,10 +138,24 @@ export default {
         this.statusObj = {
           bugEnumList: res.data.bugEnumList, // status
           repairResultEnumList: res.data.repairResultEnumList, // 修复结果
-          bugReasonEnumList: res.data.bugReasonEnumList // 缺陷原因
+          bugReasonEnumList: res.data.bugReasonEnumList, // 缺陷原因
+          theBugTypeEnumList: this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
         }
       }
     },
+    deleteChild(arr) { // 删除无用子属性
+      const bfs = arr => {
+        arr.forEach(item => {
+          if (!item.childrenEnums || item.childrenEnums.length === 0) {
+            delete item.childrenEnums
+          } else {
+            this.deleteChild(item.childrenEnums)
+          }
+        })
+      }
+      bfs(arr)
+      return arr
+    },
     bugGetTableList(e, index) {
       this.queryData = e
       this.data = {}

+ 54 - 53
src/views/projectManage/bugList/details/index.vue

@@ -140,12 +140,15 @@
                       />
                     </el-select>
                   </el-form-item>
-                  <el-form-item label="缺陷原因">
+                  <!-- <el-form-item label="缺陷原因">
                     <div v-if="map.bugReasonEnumList && bug" class="bug_manage_div">{{ map.bugReasonEnumList[bug.bugReason]?map.bugReasonEnumList[bug.bugReason]:'尚未知' }}</div>
-                  </el-form-item>
+                  </el-form-item> -->
                   <el-form-item label="Reopen次数">
                     <div class="bug_manage_div">{{ bug.reopenTimes }}</div>
                   </el-form-item>
+                  <el-form-item label="Hold次数">
+                    <div class="bug_manage_div">{{ bug.holdCount }}</div>
+                  </el-form-item>
                 </el-form>
               </el-aside>
               <el-aside width="49%">
@@ -178,14 +181,18 @@
                     </el-select>
                   </el-form-item>
                   <el-form-item label="缺陷类型">
-                    <el-select v-model="bug.theBugType" @change="bugUpdate(bug,'details')">
-                      <el-option
-                        v-for="item in enums.theBugTypeEnumList"
-                        :key="item.code"
-                        :label="item.name"
-                        :value="item.code"
-                      />
-                    </el-select>
+                    <el-cascader
+                      v-model="bug.theBugType"
+                      :options="theBugTypeEnumList"
+                      :props="{
+                        value:'code',
+                        label:'name',
+                        children: 'childrenEnums',
+                        emitPath: false
+                      }"
+                      placeholder="请选择"
+                      @change="bugUpdate(bug,'details')"
+                    />
                   </el-form-item>
                   <el-form-item label="修复结果">
                     <div
@@ -193,10 +200,6 @@
                       class="bug_manage_div"
                     >{{ map.repairResultEnumList[bug.repairResult]?map.repairResultEnumList[bug.repairResult]:'未修复' }}</div>
                   </el-form-item>
-                  <el-form-item label="Hold次数">
-                    <div class="bug_manage_div">{{ bug.holdCount }}</div>
-                  </el-form-item>
-
                 </el-form>
               </el-aside>
             </el-container>
@@ -299,43 +302,18 @@
                   <div class="bug_manage_div"> :{{ bug.gmtCreate }} <span v-if="bug.gmtCreateIsHoliday === 1" class="bug_date">{{ '节假日提报' }}</span></div>
                 </el-form-item>
                 <el-form-item label="待测试时间">
-                  <div class="tips">
-                    <el-tooltip class="item" effect="dark" content="最后一次改成待测试状态的时间" placement="bottom-start">
-                      <i class="el-icon-warning" />
-                    </el-tooltip>
-                  </div>
                   <div class="bug_manage_div"> :{{ bug.waitTestTime }}</div>
                 </el-form-item>
                 <el-form-item label="已完成时间">
-                  <div class="tips">
-                    <el-tooltip class="item" effect="dark" content="最后一次改成已完成状态的时间" placement="bottom-start">
-                      <i class="el-icon-warning" />
-                    </el-tooltip>
-                  </div>
                   <div class="bug_manage_div"> :{{ bug.finishTime }} <span v-if="bug.finishTimeIsHoliday === 1" class="bug_date">{{ '节假日关闭' }}</span></div>
                 </el-form-item>
                 <el-form-item label="开发修复时长">
-                  <div class="tips">
-                    <el-tooltip class="item" effect="dark" content="待测试时间-提报时间" placement="bottom-start">
-                      <i class="el-icon-warning" />
-                    </el-tooltip>
-                  </div>
                   <div class="bug_manage_div"> :{{ bug.devFixTime }} <br> :{{ bug.devFixTimePurgeNH }} <span v-if="bug.devFixTimePurgeNH !== null" class="bug_removeDate">{{ '去除节假日' }}</span></div>
                 </el-form-item>
                 <el-form-item label="测试验收时长">
-                  <div class="tips">
-                    <el-tooltip class="item" effect="dark" content="已完成时间-待测试时间" placement="bottom-start">
-                      <i class="el-icon-warning" />
-                    </el-tooltip>
-                  </div>
                   <div class="bug_manage_div"> :{{ bug.testCheckTime }} <br> :{{ bug.testCheckTimePurgeNH }} <span v-if="bug.testCheckTimePurgeNH !== null" class="bug_removeDate">{{ '去除节假日' }}</span></div>
                 </el-form-item>
                 <el-form-item label="总修复时长">
-                  <div class="tips">
-                    <el-tooltip class="item" effect="dark" content="已完成时间-提报时间" placement="bottom-start">
-                      <i class="el-icon-warning" />
-                    </el-tooltip>
-                  </div>
                   <div class="bug_manage_div"> :{{ bug.fixTime }} <br> :{{ bug.fixTimePurgeNH }} <span v-if="bug.fixTimePurgeNH !== null" class="bug_removeDate">{{ '去除节假日' }}</span></div>
                 </el-form-item>
               </el-form>
@@ -703,7 +681,8 @@ export default {
           { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
         ]
       },
-      statusObj: null // 状态对象
+      statusObj: null, // 状态对象
+      theBugTypeEnumList: [] // 缺陷类型
     }
   },
   watch: {
@@ -759,10 +738,24 @@ export default {
         this.statusObj = {
           bugEnumList: res.data.bugEnumList, // status
           repairResultEnumList: res.data.repairResultEnumList, // 修复结果
-          bugReasonEnumList: res.data.bugReasonEnumList // 缺陷原因
+          bugReasonEnumList: res.data.bugReasonEnumList, // 缺陷原因
+          theBugTypeEnumList: this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
         }
       }
     },
+    deleteChild(arr) { // 删除无用子属性
+      const bfs = arr => {
+        arr.forEach(item => {
+          if (!item.childrenEnums || item.childrenEnums.length === 0) {
+            delete item.childrenEnums
+          } else {
+            this.deleteChild(item.childrenEnums)
+          }
+        })
+      }
+      bfs(arr)
+      return arr
+    },
     handleClick(tab) {
       if (tab.label === '变更记录') {
         operationLogBug(this.id).then(res => {
@@ -813,21 +806,23 @@ export default {
     beforeUpload(file) {
       const reg = new RegExp(/.*(zip|xlsx|text|csv|xls|mov|mp4|m4a|avi|amr|mp3|wav|3gpp|gif|jpeg|png|jpg)/i)
       const isUpload = file.type.match(reg)
-      if (!isUpload) {
+      const isName = file.name.match(reg)
+      if (isUpload || isName) {
+        const isLt200M = (file.size / 1024 / 1024) < 200
+        if (!isLt200M) {
+          this.$message({
+            message: '上传文件大小不能超过 200MB!',
+            type: 'warning'
+          })
+          return false
+        }
+      } else {
         this.$message({
           message: '不支持上传此文件格式',
           type: 'warning'
         })
         return false
       }
-      const isLt200M = (file.size / 1024 / 1024) < 200
-      if (!isLt200M) {
-        this.$message({
-          message: '上传文件大小不能超过 200MB!',
-          type: 'warning'
-        })
-        return false
-      }
     },
     beforeRemove(file, fileList) {
       let a = true
@@ -1069,6 +1064,7 @@ export default {
             }
           }
         }
+        this.theBugTypeEnumList = this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
         return res
       })
     },
@@ -1285,7 +1281,7 @@ export default {
 }
 </script>
 
-<style>
+<style lang="scss">
 .el-tooltip__popper.is-dark {
   background-color: rgba(121,132,150, 0.8);
 }
@@ -1436,6 +1432,12 @@ border-color: #DCDFE6;
 </style>
 
 <style scoped lang="scss">
+/deep/.el-form-item__content {
+  span {
+    display: inline-block;
+    line-height: 20px;
+  }
+}
 .str-task-name {
  margin-left: 14px;
  color: #666666;
@@ -1484,7 +1486,6 @@ border-color: #DCDFE6;
 }
 
 .bug_removeDate {
- width:46px;
   height:16px;
   background:rgba(64,158,255,0.1);
   border:1px solid #409EFF;
@@ -1492,7 +1493,7 @@ border-color: #DCDFE6;
   border-radius:2px;
   font-size:8px;
   font-family:MicrosoftYaHei;
-  line-height:10px;
+  line-height:14px !important;
   color:#409EFF;
 }
 

+ 16 - 5
src/views/projectManage/bugList/details/statusChange.vue

@@ -32,10 +32,18 @@
             <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 === '待测试' || statusDialogTitle === '已完成'" label="缺陷原因" prop="bugReason" class="bug_manage_dialog">
-          <el-select v-model="statusDialogForm.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 v-if="statusDialogTitle === '待测试'" label="缺陷类型" prop="theBugType" class="bug_manage_dialog">
+          <el-cascader
+            v-model="statusDialogForm.theBugType"
+            :options="theBugTypeEnumList"
+            :props="{
+              value:'code',
+              label:'name',
+              children: 'childrenEnums',
+              emitPath: false
+            }"
+            placeholder="请选择"
+          />
         </el-form-item>
         <el-form-item v-if="statusDialogTitle === '待测试'" label="修复方式" class="bug_manage_dialog bug_manage_dialog_fixMethod">
           <el-input v-model="statusDialogForm.reasonOrDesc" type="textarea" placeholder="请输入具体原因,得出结论的过程,具体修复过程或方式" maxlength="300" show-word-limit rows="4" />
@@ -83,8 +91,9 @@ export default {
       statusDialogTitle: '', // 当前状态name值
       repairResultEnumList: [], // 修复结果
       bugReasonEnumList: [], // 缺陷原因
+      theBugTypeEnumList: [], // 缺陷类型
       rules: { // 状态表单验证
-        bugReason: [{ required: true, message: '请选择缺陷原因', trigger: ['blur', 'change'] }],
+        theBugType: [{ required: true, message: '请选择缺陷原因', trigger: ['blur', 'change'] }],
         repairResult: [{ required: true, message: '请选择修复结果', trigger: ['blur', 'change'] }]
       }
     }
@@ -102,6 +111,7 @@ export default {
           this.bugEnumList = newV.bugEnumList || []// status
           this.repairResultEnumList = newV.repairResultEnumList || []// 修复结果
           this.bugReasonEnumList = newV.bugReasonEnumList || []// 缺陷原因
+          this.theBugTypeEnumList = newV.theBugTypeEnumList || []// 缺陷类型
           this.bugStatusList(this.status)
         }
       },
@@ -122,6 +132,7 @@ export default {
           data.reasonOrDesc = this.statusDialogForm.reasonOrDesc
           data.repairResult = this.statusDialogForm.repairResult
           data.bugReason = this.statusDialogForm.bugReason
+          data.theBugType = this.statusDialogForm.theBugType
           const objData = { bugBaseInfo: data, user: this.userData }
           bugUpdate(objData).then(res => {
             if (res.code === 200) {

+ 26 - 7
src/views/projectManage/bugList/file/createdBug.vue

@@ -43,9 +43,18 @@
                   </el-select>
                 </el-form-item>
                 <el-form-item label="缺陷类型" prop="theBugType">
-                  <el-select v-model="formInline.theBugType" filterable placeholder="请选择" style="width:100%;">
-                    <el-option v-for="item in theBugTypeEnumList" :key="item.code" :label="item.name" :value="item.code" />
-                  </el-select>
+                  <el-cascader
+                    v-model="formInline.theBugType"
+                    :options="theBugTypeEnumList"
+                    :props="{
+                      value:'code',
+                      label:'name',
+                      children: 'childrenEnums',
+                      emitPath: false
+                    }"
+                    placeholder="请选择"
+                    clearable
+                  />
                 </el-form-item>
 
                 <el-form-item label="责任人" style="width:100%;" prop="assigner">
@@ -278,10 +287,8 @@ export default {
         sysType: [{ required: true, message: '端类型不能为空', trigger: 'change' }],
         priority: [{ required: true, message: '缺陷等级不能为空', trigger: 'change' }],
         discoveryStage: [{ required: true, message: '发现阶段不能为空', trigger: 'change' }],
-        theBugType: [{ required: true, message: '缺陷类型不能为空', trigger: 'change' }],
         creatorList: [{ required: true, message: '提报人不能为空', trigger: 'change' }],
         currentHandler: [{ required: true, message: '修复人不能为空', trigger: 'change' }]
-
       },
       bugEnumList: [], // bug状态
       appClient: [], // 客户端
@@ -484,13 +491,25 @@ export default {
         this.clientTypeEnumList = res.data.clientTypeEnumList // 版本
         this.sysTypeEnumList = res.data.sysTypeEnumList // 客户端
         this.networkTypeEnumList = res.data.networkTypeEnumList // 网络
-        this.theBugTypeEnumList = res.data.theBugTypeEnumList // 缺陷类型
+        this.theBugTypeEnumList = this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
       })
       releaseList().then(res => {
         this.appClient = res.data.appClient // 客户端
       })
     },
-
+    deleteChild(arr) { // 删除无用子属性
+      const bfs = arr => {
+        arr.forEach(item => {
+          if (!item.childrenEnums || item.childrenEnums.length === 0) {
+            delete item.childrenEnums
+          } else {
+            this.deleteChild(item.childrenEnums)
+          }
+        })
+      }
+      bfs(arr)
+      return arr
+    },
     bugDataGet() { // 所属模块
       settingQueryBizModuleList(Number(localStorage.getItem('bizId'))).then(res => {
         this.business_platform_Modular = res.data.map(item => ({

+ 151 - 86
src/views/projectManage/projectList/components/mileStone.vue

@@ -1,37 +1,36 @@
 <template>
   <div>
-    <div style="margin-top: 14%;">
-      <el-divider content-position="right">
-        <el-tooltip class="item" effect="dark" content="温馨提示:点击添加可以新建里程碑" placement="bottom-end">
-          <el-button style="z-index: 999999;" size="mini" type="primary" icon="el-icon-plus" circle @click="details_projectMilepost" />
-        </el-tooltip>
-      </el-divider>
-      <ul class="time-line">
-        <li v-for="(item, index) in valuesList" :key="index">
-          <i>
-            <div>
-              <el-popover class="popover" placement="top" width="200" trigger="click" style="border-radius: 10px;">
-                <p style="text-align: center">
-                  <el-button size="mini" @click="dalete_Milepost = true">删除</el-button>
-                  <el-button size="mini" type="primary" @click="query_date">编辑</el-button>
-                </p>
-                <b slot="reference" @click="get_Milepost(item)">一&nbsp;</b>
-              </el-popover>
-            </div>
-          </i>
-          <div>
-            <p style="white-space:pre-line;"><pre class="description">{{ item.description }}</pre></p>
-            <span style="font-size: 16px; color: #333B4A; font-weight: 500;">{{ item.title | ellipsis(20) }}</span><br>
-            <span style="font-size: 12px; color: #9B9B9B;">{{ item.date | dateStr }}</span>
+    <div class="swiper-container" style="padding: 2% 0;">
+      <el-tooltip class="item" effect="dark" content="温馨提示:点击添加可以新建里程碑" placement="bottom-end">
+        <span class="el-icon-circle-plus-outline created" @click="details_projectMilepost" />
+      </el-tooltip>
+      <swiper ref="mySwiper" class="swiper-wrapper timeline" :options="options">
+        <swiper-slide v-for="(item,index) in valuesList" :key="index" class="swiper-slide">
+          <div class="line" />
+          <div class="center circle circle2">
+            <el-popover placement="top" width="200" trigger="click">
+              <p style="text-align: center">
+                <el-button size="mini" @click="dalete_Milepost = true">删除</el-button>
+                <el-button size="mini" type="primary" @click="query_date">编辑</el-button>
+              </p>
+              <div slot="reference" class="circle-of center" @click="get_Milepost(item)" />
+            </el-popover>
           </div>
-        </li>
-      </ul>
+          <div class="content3">
+            {{ item.title | ellipsis(20) }}
+          </div>
+          <div class="content1">
+            {{ item.date | dateStr }}
+          </div>
+          <div class="content2">
+            {{ item.description }}
+          </div>
+        </swiper-slide>
+      </swiper>
     </div>
-    <el-dialog :visible.sync="dialogFormVisible" class="dialog" :close-on-click-modal="false" @close="close_dialog">
-      <div style="display:flex;align-items: center;margin:0 0 30px 10px;">
-        <div class="titIcon" />
-        <div style="width:150px;height:20px;font-size:18px;font-family:MicrosoftYaHei;color:rgba(51,59,74,1);margin-left:6px">{{ title_name }}</div>
-      </div>
+
+    <el-dialog :title="title_name" :visible.sync="dialogFormVisible" class="dialog public_task" :close-on-click-modal="false" @close="close_dialog">
+      <div class="blueStripe" />
       <el-form
         ref="form"
         :model="form"
@@ -67,23 +66,35 @@
         <el-button type="primary" @click="Milepost_Submission(form)">提 交</el-button>
       </div>
     </el-dialog>
-    <el-dialog :visible.sync="dalete_Milepost" width="30%" center :close-on-click-modal="false">
-      <div align="center">确定要删除 {{ get_Milepost_data.title }} 项目吗?</div>
+
+    <el-dialog title="删除确认" class="public_task" :visible.sync="dalete_Milepost" width="30%" :close-on-click-modal="false">
+      <div class="blueStripe" />
+      <p align="center">确定要删除 {{ get_Milepost_data.title }} 项目吗?</p>
       <span slot="footer" class="dialog-footer">
-        <el-button @click="dalete_Milepost = false">关 闭</el-button>
-        <el-button type="primary" @click="select_Milepost">确 定</el-button>
+        <el-button size="mini" @click="dalete_Milepost = false">关 闭</el-button>
+        <el-button size="mini" type="primary" @click="select_Milepost">确 定</el-button>
       </span>
     </el-dialog>
   </div>
 </template>
 <script>
 const _ = require('lodash')
+import { Swiper, SwiperSlide, directive } from 'vue-awesome-swiper'
+import 'swiper/css/swiper.css'
+import '@/styles/PublicStyle/index.scss'
 import {
   mileStoneCreate,
   mileStoneUpdate,
   mileStoneDelete
 } from '@/api/projectIndex'
 export default {
+  components: {
+    Swiper,
+    SwiperSlide
+  },
+  directives: {
+    swiper: directive
+  },
   filters: {
     dateStr(value) {
       if (!value) return ''
@@ -153,10 +164,21 @@ export default {
         title: [{ required: true, validator: validatePass, trigger: 'blur' }],
         mtime: [{ required: true, validator: validate, trigger: 'blur' }]
       },
-      form: {}
+      form: {},
+      steps: [],
+      options: {
+        pagination: {
+          el: '.swiper-pagination'
+        },
+        slidesPerView: 5,
+        grabCursor: true
+      }
     }
   },
   computed: {
+    swiper() {
+      return this.$refs.mySwiper.$swiper
+    },
     isEmpty() {
       return this.inputValue === ''
     }
@@ -247,60 +269,103 @@ export default {
   }
 }
 </script>
+
 <style scoped lang="scss">
->>>.el-divider--horizontal {
-  margin: 0;
+.swiper-container {
+  position: relative;
 }
-.time-line {
+.timeline {
+  width: calc(100% - 60px);
   list-style-type: none;
-  padding: 0px;
-  margin: 0px;
-  width: 100%;
-  height: 20vh;
-  min-height: 150px;
-  white-space: nowrap;
-  li {
-    display: inline-block;
-    position: relative;
-    text-align: center;
-    width: 24%;
-    padding-top: 4%;
-    margin: 0 1%;
-    i div {
-      position: absolute;
-      top: -10px;
-      left: 50%;
-      margin-left: -10px;
-      width: 20px;
-      height: 20px;
-      b {
-        display: inline-block;
-        cursor: pointer;
-        border: 2px solid #61D3B8;
-        border-radius: 50%;
-        background: #61D3B8;
-        color: #61D3B8;
-        z-index: 9999;
-        width: 20px;
-        height: 20px;
-      }
-    }
-    i:before {
-      content: '';
-      width: 0%;
-      text-align: center;
-      position: absolute;
-      top: -50%;
-      left: 49.3%;
-      height: 100%;
-      border: 1px dashed #BBBBBB;
-    }
-    div {
-      text-align: center;
-      width: 100%;
-      position: absolute;
-      bottom: 284%;
-    }
+  display: flex;
+  padding: 0;
+  text-align: center;
+}
+.swiper-slide {
+  height: 300px;
+  display: flex;
+  align-items: center;
+  font-size: 18px;
+  position: relative;
+  .line{
+    width: 100%;
+    height:0px;
+    border: 1px solid #DCDFE6;
   }
+  .center {
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%,-50%);
+  }
+  .circle {
+    position: absolute;
+  }
+  .circle2::after{
+    content: '';
+    position: absolute;
+    height: 100px;
+    border: 1px dashed #BBBBBB;
+    left: 50%;
+    bottom: -16px;
+    transform: translate(-50%,33px);
+  }
+
+  .circle-of {
+    position: absolute;
+    border-radius: 50%;
+    width: 18px;
+    height: 18px;
+    z-index: 99;
+    background: #61D3B8;
+  }
+
+   .content1,.content2 {
+    width: 100%;
+    font-size: 12px;
+    color: rgba(51,51,51,1);
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+  }
+  .content3 {
+    font-size: 16px;
+    color: #333B4A;
+    font-weight: 500;
+    width: 100%;
+    position: absolute;
+    left: 50%;
+    top: 28px;
+    transform: translateX(-50%);
+  }
+  .content2 {
+    bottom:5px;
+    font-weight:500;
+  }
+  .content1 {
+    font-size: 12px;
+    color: #9B9B9B;
+    top: 45px;
+  }
+}
+.created {
+  position: absolute;
+  right: 55px;
+  top: 42%;
+  // bottom: 186px;
+  z-index: 9999999;
+  background: #409EFF;
+  color: #FFF;
+  border-radius: 50%;
+  font-size: 27px;
+  cursor: pointer;
+}
+.swiper-slide {
+  margin-top: -30px;
+}
+.swiper-slide:nth-child(2n) {
+  width: 40%;
+}
+.swiper-slide:nth-child(3n) {
+  width: 20%;
 }
 </style>

+ 5 - 5
src/views/projectManage/projectList/components/taskList.vue

@@ -107,7 +107,7 @@
     </el-table>
     <TestReport v-if="dialogTestReport" ref="TestReport" />
     <DailyReport v-if="dialogDailyReport" ref="DailyReport" />
-    <ClientReport v-if="dialogClientReport" ref="ClientReport" />
+    <ReleaseReport v-if="dialogClientReport" ref="ClientReport" />
     <taskDialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskId.id" :status-name="taskId.statusString" @getList="get_allTask" />
     <!-- 批量排期 -->
     <modify-schedule
@@ -122,9 +122,9 @@
 <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 TestReport from '@/views/reportManagement/components/TestingReport' // 提测
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
 import { taskList } from '@/api/projectIndex'
 import { taskUpdate } from '@/api/projectViewDetails'
 import { configShowTaskEnum, configShowTaskStatusEnum } from '@/api/taskIndex'
@@ -135,7 +135,7 @@ export default {
   components: {
     TestReport,
     DailyReport,
-    ClientReport,
+    ReleaseReport,
     scheduleList,
     taskDialog,
     modifySchedule

+ 5 - 5
src/views/projectManage/requirement/components/taskList.vue

@@ -108,7 +108,7 @@
     </el-table>
     <TestReport v-if="dialogTestReport" ref="TestReport" />
     <DailyReport v-if="dialogDailyReport" ref="DailyReport" />
-    <ClientReport v-if="dialogClientReport" ref="ClientReport" />
+    <ReleaseReport v-if="dialogClientReport" ref="ClientReport" />
     <task-dialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskId.id" :status-name="taskId.statusString" @getList="get_allTask" />
     <!-- 批量排期 -->
     <modify-schedule
@@ -122,9 +122,9 @@
 </template>
 <script>
 import imgUrl from '@/assets/建立档案@2x.png'
-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 TestReport from '@/views/reportManagement/components/TestingReport' // 提测
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
 import { taskList } from '@/api/projectIndex'
 import { taskUpdate } from '@/api/projectViewDetails'
 import { configShowTaskEnum, configShowTaskStatusEnum } from '@/api/taskIndex'
@@ -136,7 +136,7 @@ export default {
   components: {
     TestReport,
     DailyReport,
-    ClientReport,
+    ReleaseReport,
     scheduleList,
     taskDialog,
     modifySchedule

+ 1 - 1
src/views/projectManage/taskList/components/reportList.vue

@@ -203,7 +203,7 @@ import {
   launchTestDelete
 } from '@/api/taskIndex' // ajax
 import TestReport from '@/views/Platform/presentation/Templates/TestReport' // 提测
-import DailyReport from '@/views/Platform/presentation/Templates/DailyReport' // 日报
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
 import ClientReport from '@/views/Platform/presentation/Templates/ClientReport' // 准出
 import { dailyReportDelete, projectTestReportDelete } from '@/api/testPresentetion' // 日报
 import { launchTestUpdate } from '@/api/InterfaceReport'

+ 10 - 8
src/views/projectManage/taskList/taskViewDetail.vue

@@ -280,7 +280,7 @@
       <create-children v-if="createChildren" :visible.sync="createChildren" :data="form_query" :new-add="true" @change="reloadList" />
       <Test-report v-if="dialogTest" ref="TestReport" />
       <Daily-report v-if="dialogDaily" ref="DailyReport" />
-      <Client-report v-if="dialogClient" ref="ClientReport" />
+      <ReleaseReport v-if="dialogClient" ref="ClientReport" />
       <!-- 新建 -->
       <!-- 编辑 -->
       <open-dialog v-if="updateVisible" ref="task_createdUpdata" />
@@ -346,9 +346,9 @@ import childrenList from './childrenTask/childrenList'
 import scheduleList from './components/scheduleList'
 import reportList from './components/reportList'
 import dataStatistics from './components/dataStatistics'
-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 TestReport from '@/views/reportManagement/components/TestingReport' // 提测
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
 import stage from '@/assets/detailPage/风险状态.png'
 import stage1 from '@/assets/detailPage/正常状态.png'
 import stage2 from '@/assets/detailPage/延期状态.png'
@@ -373,7 +373,7 @@ export default {
     dataStatistics,
     TestReport,
     DailyReport,
-    ClientReport,
+    ReleaseReport,
     taskDialog,
     bugTableDialog,
     schedule,
@@ -673,15 +673,17 @@ export default {
       switch (e) {
         case 1: // 提测
           this.dialogTest = true
-          this.$nextTick(() => { this.$refs.TestReport.init(1, ele) })
+          this.$nextTick(() => { this.$refs.TestReport.init(7, [this.taskId]) })
           break
         case 2: // 日报
           this.dialogDaily = true
-          this.$nextTick(() => { this.$refs.DailyReport.init(1) })
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(7, [this.taskId])
+          })
           break
         case 3:
           this.dialogClient = true
-          this.$nextTick(() => { this.$refs.ClientReport.init(1, ele) })
+          this.$nextTick(() => { this.$refs.ClientReport.init(7, [this.taskId]) })
           break
       }
     },

+ 7 - 3
src/views/projectManage/taskList/versionsCalendar.vue

@@ -401,14 +401,18 @@ export default {
     // 遍历首页列表
     versionlist() {
       this.events = []
-      for (var j = 0; j < this.eventData.length; j++) {
-        var event = {}
+      const newArr = []
+      for (let j = 0; j < this.eventData.length; j++) {
+        const event = {}
         event.title = this.eventData[j].version + this.eventData[j].name
         event.start = this.formatDate(this.eventData[j].startTime)
         event.end = this.formatDate(this.eventData[j].endTime)
         event.cssClass = this.red
-        this.events.push(event)
+        newArr.push(event)
       }
+      this.$nextTick(() => {
+        this.events = newArr
+      })
     },
 
     adds() {

+ 1 - 1
src/views/projectManage/version/components/taskList.vue

@@ -125,7 +125,7 @@
 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 DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
 import ClientReport from '@/views/Platform/presentation/Templates/ClientReport' // 准出
 import { taskUpdate } from '@/api/projectViewDetails'
 import { configShowTaskEnum, configShowTaskStatusEnum } from '@/api/taskIndex'

+ 126 - 0
src/views/quality/components/childCharts.vue

@@ -0,0 +1,126 @@
+<template>
+  <click-hidden id="pie-bar-child-chart" :show.sync="visible">
+    <div class="child-chart">
+      <normal-echart v-if="childOption" :chart-id="'child-chart'" :option="childOption" />
+    </div>
+  </click-hidden>
+</template>
+<script>
+import { getDistributeData } from '@/api/defectStatistics'
+import normalEchart from '@/components/chart/normalEchart'
+import clickHidden from '@/components/dialog/clickHidden'
+export default {
+  components: { normalEchart, clickHidden },
+  props: {
+    chartType: {
+      type: String,
+      default: 'bar',
+      required: false
+    },
+    show: {
+      type: Boolean,
+      default: false,
+      required: true
+    },
+    params: {
+      type: Object,
+      default: () => null,
+      required: false
+    }
+  },
+  data() {
+    return {
+      visible: this.show,
+      childOption: null, // 图表设置项
+      childChartData: null // 图表显示数据
+    }
+  },
+  watch: {
+    chartType: {
+      handler(newV) {
+        this.changeBarOrPie(newV)
+      }
+    },
+    show: {
+      handler(newV) {
+        this.visible = newV
+      },
+      immediate: true
+    },
+    visible: {
+      handler(newV) {
+        this.$emit('update:show', newV)
+      },
+      immediate: true
+    },
+    params: {
+      handler(newV) {
+        if (!newV) return
+        this.params = newV
+        this.getChartData()
+      },
+      immediate: true,
+      deep: true
+    }
+  },
+  methods: {
+    async getChartData() {
+      const res = await getDistributeData(this.params)
+      this.childChartData = res.data || []
+      this.changeBarOrPie(this.chartType)
+    },
+    changeBarOrPie(type) { // 饼图柱状图切换
+      if (!this.childChartData) return
+      if (this.childChartData.xaxis && this.childChartData.xaxis.length === 0) {
+        this.visible = false
+      }
+      if (type === 'bar') {
+        this.childOption = {
+          color: ['#3AA1FF'],
+          tooltip: { trigger: 'axis', axisPointer: { type: 'line' }}, // 默认为直线,可选为:'line' | 'shadow'
+          grid: { left: '5%', right: '5%', top: '10%', bottom: '0%', containLabel: true },
+          xAxis: [{ type: 'category', data: this.childChartData.xaxis, axisLabel: { interval: 0, rotate: 40 }, axisTick: { alignWithLabel: true }}],
+          yAxis: [{ type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { type: 'dashed' }}}],
+          series: [
+            {
+              name: '缺陷数量', type: 'bar', barWidth: '20px', data: this.childChartData.yaxis[0] && this.childChartData.yaxis[0].data || [],
+              itemStyle: { normal: { label: { show: true, formatter: '{c}', position: 'top' }}}
+            }
+          ]
+        }
+      } else {
+        const newArr = this.childChartData.xaxis.map((item, index) => {
+          return {
+            value: this.childChartData.yaxis[0] && this.childChartData.yaxis[0].data[index] || null,
+            name: item
+          }
+        })
+        this.childOption = {
+          color: ['#1890FF', '#13C2C2', '#2FC25B', '#FACC14', '#F04864', '#8543E0'],
+          grid: { left: '0', right: '0', top: '3%', bottom: '0' },
+          tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} ({d}%)' },
+          legend: { orient: 'vertical', left: 'right', top: 'center', data: this.childChartData.xaxis },
+          series: [
+            {
+              name: '缺陷数量', type: 'pie', radius: ['45%', '60%'], right: '30%', label: { position: 'outer', alignTo: 'edge', margin: 20 }, data: newArr,
+              itemStyle: { normal: { label: { show: true, formatter: '{b} : {c} ({d}%)' }, labelLine: { show: true }}}
+            }
+          ]
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.child-chart {
+  position: absolute;
+  z-index: 99;
+  height: 300px;
+  width: 45%;
+  right: 0;
+  top: 0;
+  border: 1px solid #333333;
+  background-color: #ffffff;
+}
+</style>

+ 119 - 43
src/views/quality/defectStatistics.vue

@@ -19,11 +19,12 @@
             size="small"
             value-format="yyyy.MM.dd"
             :default-time="['00:00:00','23:59:59']"
+            @change="dateType = ''"
           />
         </el-form-item>
       </el-form>
       <el-form :model="defectForm" class="demo-form-inline" :inline="true">
-        <el-form-item label="团队:">
+        <el-form-item label="责任团队:">
           <el-select
             v-model="defectForm.team"
             placeholder="请选择"
@@ -126,13 +127,14 @@
           </el-col>
           <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>
+            <div class="bar-pie" :class="[barOrPie==='pie'?'active':'']" @click="changeBarOrPie('pie')">图</div>
           </el-col>
         </el-row>
         <el-row type="flex" align="middle">
           <el-col :span="24">
             <div class="chart-contain">
-              <normal-echart v-if="echartsOption1" :chart-id="'chartFirst'" :option="echartsOption1" />
+              <child-chart :show.sync="showChild" :chart-type="barOrPie" :params="childParams" />
+              <normal-echart v-if="echartsOption1" :chart-id="'chartFirst'" :option="echartsOption1" @onClick="echartClick" />
             </div>
           </el-col>
         </el-row>
@@ -196,30 +198,44 @@
           @sort-change="moduleTableSortChange"
         >
           <el-table-column prop="name" label="模块" />
-          <el-table-column v-if="activeTab=== 1" prop="repair" label="新增" sortable="custom" show-overflow-tooltip>
+          <el-table-column v-if="activeTab=== 1" prop="newData" label="新增" sortable="custom" show-overflow-tooltip>
             <template slot-scope="scope">
-              <span class="table-repair-item1 repair-span">{{ scope.row.newData.total }}</span>/
+              <span class="table-repair-item1 repair-span">{{ scope.row.newData.total }}</span>
               <span class="repair-span">{{ scope.row.newData.detail[0].label }}:{{ scope.row.newData.detail[0].total }}</span>
               <span class="repair-span">{{ scope.row.newData.detail[1].label }}:{{ scope.row.newData.detail[1].total }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="isRepair" label="累计修复" sortable="custom">
+          <el-table-column prop="newAndReopenData" label="待修复/Reopen" sortable="custom">
             <template slot-scope="scope">
-              <span class="table-repair-item2 repair-span2">{{ scope.row.repairData.total }}</span>/
+              <span class="table-repair-item2 repair-span2">{{ scope.row.newAndReopenData.total }}</span>
+              <span class="repair-span">{{ scope.row.newAndReopenData.detail[0].label }}:{{ scope.row.newAndReopenData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.newAndReopenData.detail[1].label }}:{{ scope.row.newAndReopenData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="waitTestData" label="待测试" sortable="custom">
+            <template slot-scope="scope">
+              <span class="table-repair-item2 repair-span2">{{ scope.row.waitTestData.total }}</span>
+              <span class="repair-span">{{ scope.row.waitTestData.detail[0].label }}:{{ scope.row.waitTestData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.waitTestData.detail[1].label }}:{{ scope.row.waitTestData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="repairData" label="已完成" sortable="custom">
+            <template slot-scope="scope">
+              <span class="table-repair-item2 repair-span2">{{ scope.row.repairData.total }}</span>
               <span class="repair-span">{{ scope.row.repairData.detail[0].label }}:{{ scope.row.repairData.detail[0].total }}</span>
               <span class="repair-span">{{ scope.row.repairData.detail[1].label }}:{{ scope.row.repairData.detail[1].total }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="time" label="平均修复时长">
+          <el-table-column prop="repairTimeAvgData" label="平均修复时长">
             <template slot-scope="scope">
-              <span class="table-repair-item3 repair-span">{{ scope.row.repairTimeAvgData.total }}</span>/
+              <span class="table-repair-item3 repair-span">{{ scope.row.repairTimeAvgData.total }}</span>
               <span class="repair-span">{{ scope.row.repairTimeAvgData.detail[0].label }}:{{ scope.row.repairTimeAvgData.detail[0].total }}</span>
               <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="平均修复时长(去除节假日)">
+          <el-table-column prop="repairTimeAvgPurgeNhData" label="平均修复时长(去除节假日)">
             <template slot-scope="scope">
-              <span class="table-repair-item4 repair-span">{{ scope.row.repairTimeAvgPurgeNhData.total }}</span>/
+              <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>
@@ -240,30 +256,44 @@
           @sort-change="memberTableSortChange"
         >
           <el-table-column prop="name" label="姓名" />
-          <el-table-column v-if="activeTab=== 1" prop="repair" label="新增" sortable="custom" show-overflow-tooltip>
+          <el-table-column v-if="activeTab=== 1" prop="newData" label="新增" sortable="custom" show-overflow-tooltip>
             <template slot-scope="scope">
-              <span class="table-repair-item1 repair-span">{{ scope.row.newData.total }}</span>/
+              <span class="table-repair-item1 repair-span">{{ scope.row.newData.total }}</span>
               <span class="repair-span">{{ scope.row.newData.detail[0].label }}:{{ scope.row.newData.detail[0].total }}</span>
               <span class="repair-span">{{ scope.row.newData.detail[1].label }}:{{ scope.row.newData.detail[1].total }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="isRepair" label="累计修复" sortable="custom">
+          <el-table-column prop="newAndReopenData" label="待修复/Reopen" sortable="custom">
+            <template slot-scope="scope">
+              <span class="table-repair-item2 repair-span2">{{ scope.row.newAndReopenData.total }}</span>
+              <span class="repair-span">{{ scope.row.newAndReopenData.detail[0].label }}:{{ scope.row.newAndReopenData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.newAndReopenData.detail[1].label }}:{{ scope.row.newAndReopenData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="waitTestData" label="待测试" sortable="custom">
+            <template slot-scope="scope">
+              <span class="table-repair-item2 repair-span2">{{ scope.row.waitTestData.total }}</span>
+              <span class="repair-span">{{ scope.row.waitTestData.detail[0].label }}:{{ scope.row.waitTestData.detail[0].total }}</span>
+              <span class="repair-span">{{ scope.row.waitTestData.detail[1].label }}:{{ scope.row.waitTestData.detail[1].total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="repairData" label="已完成" sortable="custom">
             <template slot-scope="scope">
-              <span class="table-repair-item2 repair-span2">{{ scope.row.repairData.total }}</span>/
+              <span class="table-repair-item2 repair-span2">{{ scope.row.repairData.total }}</span>
               <span class="repair-span">{{ scope.row.repairData.detail[0].label }}:{{ scope.row.repairData.detail[0].total }}</span>
               <span class="repair-span">{{ scope.row.repairData.detail[1].label }}:{{ scope.row.repairData.detail[1].total }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="time" label="平均修复时长">
+          <el-table-column prop="repairTimeAvgData" label="平均修复时长">
             <template slot-scope="scope">
-              <span class="table-repair-item3 repair-span">{{ scope.row.repairTimeAvgData.total }}</span>/
+              <span class="table-repair-item3 repair-span">{{ scope.row.repairTimeAvgData.total }}</span>
               <span class="repair-span">{{ scope.row.repairTimeAvgData.detail[0].label }}:{{ scope.row.repairTimeAvgData.detail[0].total }}</span>
               <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="平均修复时长(去除节假日)">
+          <el-table-column prop="repairTimeAvgPurgeNhData" label="平均修复时长(去除节假日)">
             <template slot-scope="scope">
-              <span class="table-repair-item4 repair-span">{{ scope.row.repairTimeAvgPurgeNhData.total }}</span>/
+              <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>
@@ -290,8 +320,9 @@ import {
   getBugCountTrend
 } from '@/api/defectStatistics'
 import normalEchart from '@/components/chart/normalEchart'
+import childChart from './components/childCharts'
 export default {
-  components: { normalEchart },
+  components: { normalEchart, childChart },
   data() {
     return {
       echartsOption1: null,
@@ -331,12 +362,15 @@ export default {
       onHoliday: [], // 有假期数据
       offHoliday: [], // 无假期数据
       chart1Data: null, // 图表1数据
+      chartChildData: null, // 图表1二级子分类数据
       chart2Data: null, // 图表2数据
       chart3Data: null, // 缺陷趋势图数据
       moduleSort: 2, // 模块数据排序
       moduleData: [], // 模块数据
       memberSort: 2, // 责任人数据排序
-      memberData: [] // 责任人数据
+      memberData: [], // 责任人数据
+      showChild: false, // 显示二级子图表
+      childParams: null // 二级子图表的筛选项
     }
   },
   created() {
@@ -467,7 +501,12 @@ export default {
         moduleIds: moduleIds && moduleIds.length > 0 ? moduleIds : null
       }
       const res = await getDistributeData(params)
-      this.chart1Data = res.data || []
+      this.chart1Data = res.data || []// 一级主数据
+      if (this.defectStatus === 7) {
+        params.distributeType = 9
+        const resChild = await getDistributeData(params)
+        this.chartChildData = resChild.data || []// 二级子分类数据
+      }
       this.changeBarOrPie(this.barOrPie)
     },
     changeBarOrPie(type) { // 饼图柱状图切换
@@ -479,12 +518,10 @@ export default {
           grid: { left: '0', right: '0', top: '5%', bottom: '0', containLabel: true },
           xAxis: [{ type: 'category', data: this.chart1Data.xaxis, axisLabel: { interval: 0, rotate: 40 }, axisTick: { alignWithLabel: true }}],
           yAxis: [{ type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { type: 'dashed' }}}],
-          series: [
-            {
-              name: '缺陷数量', type: 'bar', barWidth: '20px', data: this.chart1Data.yaxis[0] && this.chart1Data.yaxis[0].data || [],
-              itemStyle: { normal: { label: { show: true, formatter: '{c}', position: 'top' }}}
-            }
-          ]
+          series: [{
+            name: '缺陷数量', type: 'bar', barWidth: '20px', data: this.chart1Data.yaxis[0] && this.chart1Data.yaxis[0].data || [],
+            itemStyle: { normal: { label: { show: true, formatter: '{c}', position: 'top' }}}
+          }]
         }
       } else {
         const newArr = this.chart1Data.xaxis.map((item, index) => {
@@ -498,15 +535,44 @@ export default {
           grid: { left: '0', right: '0', top: '3%', bottom: '0' },
           tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} ({d}%)' },
           legend: { orient: 'vertical', left: 'right', top: 'center', data: this.chart1Data.xaxis },
-          series: [
+          series: [{
+            name: '缺陷数量', type: 'pie', radius: ['45%', '60%'], right: '30%', label: { position: 'outer', alignTo: 'edge', margin: 20 }, data: newArr,
+            itemStyle: { normal: { label: { show: true, formatter: '{b} : {c} ({d}%)' }, labelLine: { show: true }}}
+          }]
+        }
+        if (this.defectStatus === 7) { // 如果是缺陷类型,则增加二级饼图
+          // this.echartsOption1.legend.data = [...this.chart1Data.xaxis, ...this.chartChildData.xaxis]
+          const childArr = this.chartChildData.xaxis.map((item, index) => {
+            return {
+              value: this.chartChildData.yaxis[0] && this.chartChildData.yaxis[0].data[index] || null,
+              name: item
+            }
+          })
+          this.echartsOption1.series = [
             {
-              name: '缺陷数量', type: 'pie', radius: ['45%', '60%'], right: '30%', label: { position: 'outer', alignTo: 'edge', margin: 20 }, data: newArr,
+              name: '缺陷数量', type: 'pie', radius: ['45%', '60%'], right: '30%', label: { position: 'outer' }, data: childArr,
               itemStyle: { normal: { label: { show: true, formatter: '{b} : {c} ({d}%)' }, labelLine: { show: true }}}
-            }
+            },
+            { name: '缺陷数量', type: 'pie', radius: ['0', '44%'], right: '30%', label: { position: 'inner', alignTo: 'edge', margin: 20 }, data: newArr, animation: false }
           ]
         }
       }
     },
+    echartClick(params) { // 图表1点击事件
+      if (this.defectStatus !== 7 || this.barOrPie === 'pie') return // 只有状态是缺陷类型的时候才显示二级
+      this.showChild = true
+      const moduleIds = this.defectForm.moduleIds
+      this.childParams = {
+        startTime: this.stratAndEnd[0] || null,
+        endTime: this.stratAndEnd[1] || null,
+        bizId: Number(localStorage.getItem('bizId')),
+        teamIds: this.defectForm.team || null,
+        type: this.activeTab,
+        distributeType: 8,
+        moduleIds: moduleIds && moduleIds.length > 0 ? moduleIds : null,
+        bugTypeName: params.name
+      }
+    },
     async getSumData() { // 头部数据
       const moduleIds = this.defectForm.moduleIds
       const params = {
@@ -563,6 +629,7 @@ export default {
     },
     changeBarOrLine(type) { // 柱状图折线图切换
       this.barOrLine = type
+      if (!this.chart2Data.yaxis) return
       const newArr = this.chart2Data.yaxis.filter(item => { return item.name !== '全部' })
       const colorArr = ['#3AA1FF', '#4ECB73', '#975FE5', '#FBD437', '#13C2C2']
       if (type === 'line') {
@@ -578,9 +645,7 @@ export default {
                 total = total + item.value
                 backString = backString + `<span style="color: ${colorArr[index] || ''}">${item.seriesName}</span>:${item.value}%</br>`
               })
-              total = total.toFixed(2)
-              backString = backString + `<span style="color: #F04864">总和</span>:${total}%`
-              return backString
+              return backString + `<span style="color: #F04864">总和</span>:${total.toFixed(2)}%`
             }
           },
           legend: { data: newArr.map(item => { return item.name }), left: 10, top: 0 },
@@ -602,9 +667,7 @@ export default {
                 total = total + item.value
                 backString = backString + `<span style="color: ${colorArr[index] || ''}">${item.seriesName}</span>:${item.value}%</br>`
               })
-              total = total.toFixed(2)
-              backString = backString + `<span style="color: #F04864">总和</span>:${total}%`
-              return backString
+              return backString + `<span style="color: #F04864">总和</span>:${total.toFixed(2)}%`
             }
           },
           legend: { data: newArr.map(item => { return item.name }), left: 0, top: 0 },
@@ -630,10 +693,15 @@ export default {
       this.moduleData = res.data || []
     },
     moduleTableSortChange(column) { // 模块table排序变动
-      if (column.prop === 'repair') {
+      console.log(column)
+      if (column.prop === 'newData') { // 新增排序
         column.order === 'ascending' ? this.moduleSort = 1 : this.moduleSort = 2
-      } else {
+      } else if (column.prop === 'repairData') { // 已完成排序
         column.order === 'ascending' ? this.moduleSort = 3 : this.moduleSort = 4
+      } else if (column.prop === 'newAndReopenData') { // 带修复
+        column.order === 'ascending' ? this.moduleSort = 5 : this.moduleSort = 6
+      } else if (column.prop === 'waitTestData') { // 待测试
+        column.order === 'ascending' ? this.moduleSort = 7 : this.moduleSort = 8
       }
       this.getModuleDistributeData()
     },
@@ -652,10 +720,14 @@ export default {
       this.memberData = res.data || []
     },
     memberTableSortChange(column) { // 责任人table排序变动
-      if (column.prop === 'repair') {
+      if (column.prop === 'newData') { // 新增排序
         column.order === 'ascending' ? this.memberSort = 1 : this.memberSort = 2
-      } else {
+      } else if (column.prop === 'repairData') { // 已完成排序
         column.order === 'ascending' ? this.memberSort = 3 : this.memberSort = 4
+      } else if (column.prop === 'newAndReopenData') { // 带修复
+        column.order === 'ascending' ? this.memberSort = 5 : this.memberSort = 6
+      } else if (column.prop === 'waitTestData') { // 待测试
+        column.order === 'ascending' ? this.memberSort = 7 : this.memberSort = 8
       }
       this.getMemberDistributeData()
     }
@@ -903,15 +975,19 @@ export default {
       }
       .table-repair-item1,.table-repair-item4 {
         color:#4089FF;
+        margin-right: 5px;
       }
       .table-repair-item2 {
-        color:#47D4D5
+        color:#47D4D5;
+        margin-right: 5px;
       }
       .table-repair-item3 {
-        color:#FD978A
+        color:#FD978A;
+        margin-right: 5px;
       }
     }
     .chart-contain {
+      position: relative;
       height: 400px;
       width: 100%;
       margin-top: 20px;

+ 394 - 0
src/views/reportManagement/ReleaseReport/components/ResultPageyL.vue

@@ -0,0 +1,394 @@
+<template>
+  <div class="velStyle">
+    <!-- 准出预览 -->
+    <div v-if="towShow" class="reportContent">
+      <div>
+        <div style="display: flex; white-space: nowrap; font-family:SimSuncss">
+          <span style="flex:1;font-weight: bold;font-size: 20px;color: #3a8ee6">{{ ClientDatayl.reportName }}</span>
+          <span style="flex:1;margin: 0.5% 0 0 20px;font-size: 17px;">by {{ ClientDatayl.ownner }}</span>
+        </div>
+        <div style="margin: 2% 0 1% 0; font-size: 17px; font-weight: bold;">一. 项目概述</div><br>
+        <div style="display:flex;">
+          <div style="flex:1">
+            <div class="marage">测试结果 : <span :style="status1">{{ status }}</span></div><br>
+            <div class="marage">开发人员 : {{ ClientDatayl.developer }}</div><br>
+            <div class="marage">开发周期 : {{ ClientDatayl.devTimeEnd }} 至 {{ ClientDatayl.devTimeStart }}</div><br>
+            <div class="marage">准出延期 : <span :style="taskLateDisabled">{{ ClientDatayl.taskLateStatus }}</span></div><br>
+          </div>
+          <div style="flex:1">
+            <div class="marage">准入结果 : {{ ClientDatayl.launchInfo }}</div><br>
+            <div class="marage">测试人员 : {{ ClientDatayl.tester }}</div><br>
+            <div class="marage">测试周期 : {{ ClientDatayl.testTimeEnd }} 至 {{ ClientDatayl.testTimeStart }} </div><br>
+            <div v-show="showDelay1" class="marage">延期原因 : {{ ClientDatayl.taskLateReason }}</div><br>
+          </div>
+        </div>
+        <div style="display:flex;">
+          <div style="flex:1">
+            <div class="marage">涉及安全项 : <span :style="getInfoBtnDisabled">{{ ClientDatayl.getInfoBtn }}</span></div><br>
+          </div>
+          <div style="flex:1">
+            <div v-show="showData" class="marage">完成结果 : {{ ClientDatayl.safeInfo }}</div>
+          </div>
+        </div>
+        <div style="white-space: nowrap;">SDL链接 : <el-link href="http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=237016271" type="primary" target="_blank"> 普惠SDL准入标准</el-link></div>
+        <div class="titleStyle">二. 项目背景</div><br>
+        <div class="rich" v-html="editorElem" />
+
+        <div class="titleStyle">三. 模块信息</div>
+
+        <div class="marage">1、模块信息</div>
+
+        <div class="rich" v-html="editorElems" />
+
+        <div class="marage">2、本期功能</div>
+
+        <div class="rich" v-html="editorFrom" />
+
+        <div class="marage">3、风险点</div>
+
+        <div class="rich" v-html="editorF" />
+
+        <div class="marage">4、缺陷分析</div>
+
+        <el-table :data="tableData" border>
+          <el-table-column prop="totalBug" label="bug总数" min-width="200" align="center" edit="false">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.totalBug.edit" ref="totalBug" v-model="scope.row.totalBug.value" style="width: 100%" @blur="scope.row.totalBug.edit = false" />
+              <span v-else>{{ scope.row.totalBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="fixBug" min-width="200" align="center" label="已解决bug数">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.fixBug.edit" ref="fixBug" v-model="scope.row.fixBug.value" style="width: 100%" @blur="scope.row.fixBug.edit = false" />
+              <span v-else>{{ scope.row.fixBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="remainBug" min-width="200" align="center" label="遗留bug数">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.remainBug.edit" ref="remainBug" v-model="scope.row.remainBug.value" style="width: 100%" @blur="scope.row.remainBug.edit = false" />
+              <span v-else>{{ scope.row.remainBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="rateOfReopen" min-width="200" align="center" label="reopen率">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.rateOfReopen.edit" ref="rateOfReopen" v-model="scope.row.rateOfReopen.value" style="width: 100%" @blur="scope.row.rateOfReopen.edit = false" />
+              <span v-else>{{ scope.row.rateOfReopen.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="invalidBug" min-width="200" align="center" label="无效bug数">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.invalidBug.edit" ref="invalidBug" v-model="scope.row.invalidBug.value" style="width: 100%" @blur="scope.row.invalidBug.edit = false" />
+              <span v-else>{{ scope.row.invalidBug.value }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-row>
+          <el-col :span="24"><div style="margin:2% 0;">5、遗留问题</div>{{ ClientDatayl.bugInfo }}</el-col>
+        </el-row>
+
+        <div class="rich" v-html="editorData" />
+
+        <div class="titleStyle">四. 测试项</div>
+
+        <div class="marage">1、功能测试 : <span style="margin-left:40px;" :style="fctResultChange">{{ fctResult }}</span></div>
+
+        <div class="rich" v-html="editorEl" />
+
+        <div class="marage">2、可靠性测试 : <span style="margin-left:40px;" :style="rqtResultChange">{{ rqtResult }}</span></div>
+
+        <div class="rich" v-html="editorEle" />
+
+        <div class="marage">3、稳定性测试 : <span style="margin-left:40px;" :style="pftResultChange">{{ pftResult }}</span></div>
+
+        <div class="rich" v-html="editorSix" />
+
+        <div class="marage">4、安全性测试 : <span style="margin-left:40px;" :style="safeResultChange">{{ safeResult }}</span></div>
+
+        <div class="rich" v-html="editorEight" />
+
+        <div class="marage">5、线上监控 : <span style="margin-left:40px;" :style="moniterResultChange">{{ moniterResult }}</span></div>
+
+        <div class="rich" v-html="editorNine" />
+      </div>
+    </div>
+
+    <div v-if="oneShow" class="reportContent">
+      <div>
+        <div style="display: flex; white-space: nowrap; font-family:SimSuncss">
+          <span style="flex:1;font-weight: bold;font-size: 20px;color: #3a8ee6">{{ ClientDatayl.reportName }}</span>
+          <span style="flex:2;margin: 0.5% 0 0 20px;font-size: 17px;">by {{ ClientDatayl.ownner }}</span>
+        </div>
+        <div style="margin: 2% 0 1% 0; font-size: 19px; font-weight: bold;">一、项目概述</div><br>
+        <div style="display:flex;">
+          <div style="flex:1">
+            <div class="marage">测试结果 : <span :style="status1">{{ status }}</span></div><br>
+            <div class="marage">开发人员 : {{ ClientDatayl.developer }}</div><br>
+            <div class="marage">开发周期 : {{ ClientDatayl.devTimeEnd }} 至 {{ ClientDatayl.devTimeStart }}</div><br>
+            <div class="marage">准出延期 : <span :style="taskLateDisabled">{{ ClientDatayl.taskLateStatus }}</span></div><br>
+          </div>
+          <div style="flex:1">
+            <div class="marage">准入结果 : {{ ClientDatayl.smokeTestResult }}</div><br>
+            <div class="marage">测试人员 : {{ ClientDatayl.tester }}</div><br>
+            <div class="marage">测试周期 : {{ ClientDatayl.testTimeEnd }} 至 {{ ClientDatayl.testTimeStart }} </div><br>
+            <div v-show="showDelay1" class="marage">延期原因 : {{ ClientDatayl.taskLateReason }}</div><br>
+          </div>
+        </div>
+
+        <div class="titleStyle">二. 项目背景</div>
+
+        <div class="rich" v-html="editorElem" />
+
+        <div class="titleStyle">三. 测试项</div>
+
+        <p>功能测试 : <span style="margin-left:40px;" :style="pftResult1">{{ pftResult }}</span></p>
+
+        <div class="rich" v-html="editorElems1" />
+
+        <p>兼容测试 : <span style="margin-left:40px;" :style="sctResult1">{{ sctResult }}</span></p>
+
+        <div class="rich" v-html="editorFrom1" />
+
+        <div class="titleStyle">四. 产品验收</div>
+
+        <p>验收结果 : <span style="margin-left:40px;" :style="acceptanceResult1">{{ acceptanceResult }}</span></p>
+
+        <div class="rich" v-html="editorFro" />
+
+        <div class="titleStyle">五. bug指标</div>
+
+        <el-table :data="tableData" border>
+          <el-table-column prop="totalBug" label="bug总数" min-width="200" align="center" edit="false">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.totalBug.edit" ref="totalBug" v-model="scope.row.totalBug.value" style="width: 100%" @blur="scope.row.totalBug.edit = false" />
+              <span v-else>{{ scope.row.totalBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="fixBug" min-width="200" align="center" label="已解决bug数">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.fixBug.edit" ref="fixBug" v-model="scope.row.fixBug.value" style="width: 100%" @blur="scope.row.fixBug.edit = false" />
+              <span v-else>{{ scope.row.fixBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="remainBug" min-width="200" align="center" label="遗留bug数">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.remainBug.edit" ref="remainBug" v-model="scope.row.remainBug.value" style="width: 100%" @blur="scope.row.remainBug.edit = false" />
+              <span v-else>{{ scope.row.remainBug.value }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="rateOfFix" min-width="200" align="center" label="bug解决率">
+            <template slot-scope="scope">
+              <el-input v-if="scope.row.rateOfFix.edit" ref="rateOfFix" v-model="scope.row.rateOfFix.value" style="width: 100%" @blur="scope.row.rateOfFix.edit = false" />
+              <span v-else>{{ scope.row.rateOfFix.value }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-row class="pre-line">
+          <el-col :span="24"><div style="margin: 2% 0;">1、遗留问题</div>{{ ClientDatayl.bugInfo }}</el-col>
+        </el-row>
+
+        <div class="rich" v-html="editorEle1" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { bugFinishList } from '@/api/ResultPage'
+
+export default {
+  name: 'ResultPageyL',
+  props: {
+    message: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      showDelay1: false,
+      taskLateStatus: '',
+      getInfoBtnDisabled: { color: 'green' },
+      taskLateDisabled: { color: 'green' },
+      pftResult1: { colocr: 'green' },
+      sctResult1: { colocr: 'green' },
+      acceptanceResult1: { colocr: 'green' },
+      fctResultChange: { colocr: '' },
+      rqtResultChange: { color: '' },
+      pftResultChange: { color: '' },
+      safeResultChange: { color: '' },
+      moniterResultChange: { color: '' },
+      showData: false,
+      status: '',
+      acceptanceResult: '',
+      sctResult: '',
+      pftResult: '',
+      towShow: false,
+      oneShow: false,
+      showDisabled: true,
+      showDisabled1: true,
+      ClientDatayl: {},
+      editorElem: '',
+      editorElems: '',
+      editorElems1: '',
+      editorFrom: '',
+      editorFrom1: '',
+      editorF: '',
+      editorData: '',
+      editorEl: '',
+      editorEle: '',
+      editorEle1: '',
+      editorSix: '',
+      editorEight: '',
+      editorNine: '',
+      tableData: [],
+      bugNum: {},
+      status1: { color: 'green' },
+      fctResult: '',
+      moniterResult: '',
+      rqtResult: '',
+      safeResult: ''
+    }
+  },
+  created() {
+    this.idGet()
+  },
+  methods: {
+    idGet() {
+      this.ClientDatayl = this.message
+      console.log(this.ClientDatayl, 'ddddddd')
+      this.editorElems1 = this.ClientDatayl.fctInfo
+      this.editorFrom1 = this.ClientDatayl.sctInfo
+      this.editorFro = this.ClientDatayl.acceptanceResultInfo
+      this.editorEle1 = this.ClientDatayl.bugTarget
+      this.editorElem = this.ClientDatayl.projectBackground
+      this.editorElems = this.ClientDatayl.moduleInfo
+      this.editorFrom = this.ClientDatayl.functionInfo
+      this.editorF = this.ClientDatayl.onlineRisk
+      this.editorEle = this.ClientDatayl.rqtInfo
+      this.editorData = this.ClientDatayl.bugInfo
+      this.editorEl = this.ClientDatayl.fctInfo
+      this.editorSix = this.ClientDatayl.pftInfo
+      this.editorEight = this.ClientDatayl.safeResultInfo
+      this.editorNine = this.ClientDatayl.moniterResultInfo
+      this.getBugData()
+      if (this.ClientDatayl.type === 2) {
+        this.towShow = true
+        this.oneShow = false
+      } else {
+        this.oneShow = true
+        this.towShow = false
+      }
+      if (this.ClientDatayl.status === 1) {
+        this.status = '通过'
+      } else {
+        this.status = '未通过'
+        this.status1.color = 'red'
+      }
+      if (this.ClientDatayl.taskLateStatus === 1) {
+        this.ClientDatayl.taskLateStatus = '否'
+        this.showDelay1 = false
+        this.taskLateDisabled.color = 'green'
+      } else {
+        this.ClientDatayl.taskLateStatus = '是'
+        this.taskLateDisabled.color = 'red'
+        this.showDelay1 = true
+      }
+      if (this.ClientDatayl.safeInfo !== '') {
+        this.ClientDatayl.getInfoBtn = '是'
+        this.getInfoBtnDisabled.color = 'red'
+        this.showData = true
+      } else {
+        this.ClientDatayl.getInfoBtn = '否'
+        this.getInfoBtnDisabled.color = 'green'
+        this.showData = false
+      }
+      switch (this.ClientDatayl.pftResult) {
+        case 1: this.pftResult = '通过'; this.pftResult1.color = 'green'; break
+        case 2: this.pftResult = '未通过'; this.pftResult1.color = 'red'; break
+        case 3: this.pftResult = '未执行'; this.pftResult1.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.sctResult) {
+        case 1: this.sctResult = '测试通过'; this.sctResult1.color = 'green'; break
+        case 2: this.sctResult = '测试未通过'; this.sctResult1.color = 'red'; break
+      }
+      switch (this.ClientDatayl.acceptanceResult) {
+        case 1: this.acceptanceResult = '通过'; this.acceptanceResult1.color = 'green'; break
+        case 2: this.acceptanceResult = '未通过'; this.acceptanceResult1.color = 'red'; break
+        case 3: this.acceptanceResult = '未执行'; this.acceptanceResult1.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.fctResult) { // 功能测试
+        case 1: this.fctResult = '通过'; this.fctResultChange.color = 'green'; break
+        case 2: this.fctResult = '未通过'; this.fctResultChange.color = 'red'; break
+        case 3: this.fctResult = '未执行'; this.fctResultChange.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.rqtResult) { // 可靠性测试
+        case 1: this.rqtResult = '通过'; this.rqtResultChange.color = 'green'; break
+        case 2: this.rqtResult = '未通过'; this.rqtResultChange.color = 'red'; break
+        case 3: this.rqtResult = '未执行'; this.rqtResultChange.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.pftResult) { // 稳定性测试
+        case 1: this.pftResult = '通过'; this.pftResultChange.color = 'green'; break
+        case 2: this.pftResult = '未通过'; this.pftResultChange.color = 'red'; break
+        case 3: this.pftResult = '未执行'; this.pftResultChange.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.safeResult) { // 安全性测试
+        case 1: this.safeResult = '通过'; this.safeResultChange.color = 'green'; break
+        case 2: this.safeResult = '未通过'; this.safeResultChange.color = 'red'; break
+        case 3: this.safeResult = '未执行'; this.safeResultChange.color = 'Orange'; break
+      }
+      switch (this.ClientDatayl.moniterResult) { // 线上监控
+        case 1: this.moniterResult = '通过'; this.moniterResultChange.color = 'green'; break
+        case 2: this.moniterResult = '未通过'; this.moniterResultChange.color = 'red'; break
+        case 3: this.moniterResult = '未执行'; this.moniterResultChange.color = 'Orange'; break
+      }
+    },
+    getBugData() {
+      this.bugNum = { type: this.ClientDatayl.type, taskIds: this.ClientDatayl.taskIds }
+      bugFinishList(this.bugNum).then(res => {
+        this.$set(this.ClientDatayl, 'launchInfo', res.data.launchInfo)
+        this.tableData = [res.data]
+        this.formatData()
+      })
+    },
+
+    formatData() {
+      this.tableData.forEach(item => {
+        for (var key in item) {
+          item[key] = {
+            value: item[key],
+            edit: false
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .marage {
+    margin: 1% 0;
+  }
+  .reportContent {
+    padding: 2%;
+  }
+  .velStyle {
+    width: 100%;
+    height:100%;
+    display: inline-block;
+    font-size: 14px;
+    color: #333B4A;
+  }
+  .titleStyle {
+    color: #333B4A;
+    margin: 2% 0;
+    font-size: 17px;
+    font-weight: bold;
+  }
+  .pre-line >>> .el-col{
+    white-space: pre-line
+  }
+  .rich>>> table tr td{border:1px solid #ccc;font-size: 15px; color: #606266}
+  .rich>>> table th{border:1px solid #ccc; font-size: 15px; background: #F0F7FF; color: #606266}
+  .rich>>> table {border:1px solid #ccc; border-collapse: collapse;line-height: 30px; text-align: center;font-size: 15px; color: #606266}
+</style>

+ 154 - 0
src/views/reportManagement/ReleaseReport/components/iconDisplay.vue

@@ -0,0 +1,154 @@
+<template>
+  <div>
+    <el-table
+      :data="bugTableData"
+      border
+      size="mini"
+      style="width: 100%"
+      :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+    >
+      <el-table-column prop="缺陷总数" label="缺陷总数" align="center" min-width="100" />
+      <el-table-column prop="已完成缺陷" label="已完成缺陷" align="center" min-width="100" />
+      <el-table-column prop="遗留缺陷" label="遗留缺陷数" align="center" min-width="100" />
+      <el-table-column prop="缺陷解决率" label="缺陷解决率" align="center" min-width="100" />
+    </el-table>
+    <div id="line-echarts" class="line-echarts" />
+    <div class="Layout_space_between">
+      <div id="lineShow" class="backTop" />
+      <div id="barShow" class="backTop" />
+    </div>
+    <div class="backStyle">遗留缺陷</div>
+    <el-table
+      :data="tableData"
+      border
+      size="mini"
+      :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+      style="width: 100%"
+      show-overflow-tooltip="true"
+    >
+      <el-table-column prop="bugName" label="缺陷标题" align="center" min-width="100" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span class="didi-hover" @click.stop="click_bugName(scope.row.id)">{{ scope.row.bugName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="priorityLevel" label="缺陷状态" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="priorityName" label="缺陷等级" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="creatorList" label="提报人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="assignerList" label="责任人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="currentHandlerList" label="修复人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="date" label="备注(Hole原因等)" align="center" min-width="150" />
+    </el-table>
+  </div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import { bugGetReportOutSumData, bugGetReportNotResolveData, bugGetReportDisDataByMember, bugGetReportDisDataByPri, bugGetReportDisDataByDate } from '@/api/reportTemplate' // 模版添删改查
+export default {
+  props: {
+    taskIds: { type: Array, default: null }
+  },
+  data() {
+    return {
+      bugTableData: [],
+      tableData: [],
+      taskId: [] // 创建准出的任务
+    }
+  },
+  watch: {
+    taskIds: {
+      handler(newV) {
+        newV ? this.getRouterData(newV) : ''
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async getRouterData(val) {
+      const res = await bugGetReportOutSumData({ taskIds: val })
+      if (res.code === 200) {
+        this.bugTableData = [res.data]
+      }
+      const res1 = await bugGetReportNotResolveData({ taskIds: val })
+      if (res1.code === 200) {
+        this.tableData = res1.dada
+      }
+      const res6 = await bugGetReportDisDataByDate({ taskIds: val })
+      if (res6.code === 200) {
+        const data = res6.data.yaxis.map(item => ({
+          ...item,
+          type: 'line',
+          smooth: true
+        }))
+        setTimeout(() => {
+          echarts.init(document.getElementById('line-echarts')).setOption({
+            color: ['#409EFF'],
+            title: { text: '新增缺陷趋势图', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+            tooltip: { axisPointer: { type: 'shadow' }},
+            grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+            xAxis: [{ type: 'category', data: res6.data.xaxis === null ? ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期七'] : res6.data.xaxis, axisTick: { alignWithLabel: true }}],
+            yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+            series: res6.data.yaxis[0].data <= 0 ? [{ name: '直接访问', type: 'line', smooth: true, data: [0, 0, 0, 0, 0, 0, 0] }] : data
+
+          })
+        }, 200)
+      }
+      const res2 = await bugGetReportDisDataByMember({ taskIds: val })
+      if (res2.code === 200) {
+        const data = res2.data.yaxis.map(item => ({
+          ...item,
+          type: 'bar',
+          barWidth: '20px'
+        }))
+        setTimeout(() => {
+          echarts.init(document.getElementById('lineShow')).setOption({
+            color: ['#409EFF'],
+            title: { text: '缺陷责任人分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+            tooltip: { axisPointer: { type: 'shadow' }},
+            grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+            xAxis: [{ type: 'category', data: res2.data.xaxis[0] ? res2.data.xaxis : ['P0', 'P1', 'P2', 'P3'], axisTick: { alignWithLabel: true }}],
+            yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+            series: res2.data.yaxis[0].data <= 0 ? [{ name: '无数据', type: 'bar', barWidth: '20px', data: [0, 0, 0, 0] }] : data
+          })
+        }, 200)
+      }
+      const res3 = await bugGetReportDisDataByPri({ taskIds: val })
+      if (res3.code === 200) {
+        const data = res3.data.yaxis.map(item => ({
+          ...item,
+          type: 'bar',
+          barWidth: '20px'
+        }))
+        setTimeout(() => {
+          echarts.init(document.getElementById('barShow')).setOption({
+            backgroundColor: '#FFF',
+            color: ['#409EFF'],
+            title: { text: '缺陷等级分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+            tooltip: { axisPointer: { type: 'shadow' }},
+            grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+            xAxis: [{ type: 'category', data: res3.data.xaxis, axisTick: { alignWithLabel: true }}],
+            yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+            series: res3.data.yaxis[0].data <= 0 ? [{ name: '无数据', type: 'bar', barWidth: '20px', data: [0, 0, 0, 0] }] : data
+          })
+        }, 200)
+      }
+    },
+
+    click_bugName(id) { // 缺陷跳转
+      this.$router.push({ name: '缺陷详情', params: { id: id }})
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+ .line-echarts {
+     width: 100%;
+     height:400px;
+  }
+
+  .backTop {
+    width: 400px;
+    height:400px;
+  }
+</style>

+ 313 - 0
src/views/reportManagement/ReleaseReport/components/releaseDetails.vue

@@ -0,0 +1,313 @@
+<template>
+  <el-container class="BackgroundCloth">
+    <el-header class="public_header setLine">
+      <div class="Layout_space_between">
+        <div class="Layout_flex_start">
+          <div>
+            <span class="details-id">{{ 'report-' + details.id }}</span><br>
+            <span class="report-title">{{ details.reportName }}</span>
+          </div>
+          <div class="details-statusString">{{ details.statusString }}</div>
+        </div>
+        <div v-if="details.status === 1 ? false : true">
+          <span class="didi-hover" @click="clientButtom(3,details)">发送</span>
+          <span style="margin: 0 30px;" class="didi-hover" @click="clientButtom(2,details)">编辑</span>
+          <span class="didi-hover" @click="dialog_testData = true">删除</span>
+        </div>
+      </div>
+    </el-header>
+    <el-container>
+      <el-main class="report-main">
+        <div class="title"><div class="blur-column" /> 报告内容</div>
+        <el-row class="from-margin">
+          <el-col :span="24">
+            <span class="from-names">测试结果: </span>
+            <span class="from-value">通过</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">计划准出时间:{{ details.releasePlanTime }}</span>
+          </el-col>
+          <el-col :span="12">
+            <span class="from-namev"> 实际准出时间:{{ details.releaseActualTime }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="24" class="Layout_space_between">
+            <span class="from-namea">准出延期原因 : {{ details.moduleName }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">计划开发周期:{{ details.testPlanTimeStart }}</span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer"> 实际开发周期:{{ details.testPlanTimeEnd }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">计划测试周期:{{ details.testActualTimeStart }} </span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer">实际测试周期:{{ details.testActualTimeEnd }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">开发人员:{{ details.developer }}</span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer"> 测试人员:{{ details.tester }}</span>
+          </el-col>
+        </el-row>
+        <div v-html="details.content" />
+        <icon-display :task-ids="details.taskIds" />
+      </el-main>
+      <el-aside width="400px">
+        <el-container>
+          <el-header class="report-mains">
+            <div class="title"><div class="blur-column" /> 用户信息</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">报告人 : </div>
+              <div class="task-name">{{ details.reportorObject ? details.reportorObject.name : '' }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">收件人 : </div>
+              <div v-for="(item, index) in details.sendToObject" :key="index" class="task-name"> {{ item.name }} <span v-if="index < details.sendToObject.length - 1"> , </span></div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">抄送人 : </div>
+              <div v-for="(item, index) in details.sendCcObject" :key="index" class="task-name">{{ item.name }} <span v-if="index < details.sendCcObject.length - 1"> , </span></div>
+            </div>
+          </el-header>
+          <el-main class="report-mains">
+            <div class="title"><div class="blur-column" /> 时间</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">创建时间 : </div>
+              <div class="task-name">{{ details.gmtCreate }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">发送时间 : </div>
+              <div class="task-name">{{ details.gmtModify }}</div>
+            </div>
+          </el-main>
+          <el-footer class="report-mains">
+            <div class="title"><div class="blur-column" /> 关联任务</div>
+            <div v-for="(item, index) in details.taskDetailList" :key="index" class="Layout_flex_start task-bot">
+              <div class="task-id">{{ item.taskId }}</div>
+              <div class="task-name">{{ item.name }}</div>
+            </div>
+          </el-footer>
+        </el-container>
+      </el-aside>
+    </el-container>
+    <el-dialog title="删除确认" :visible.sync="dialog_testData" width="30%" :close-on-click-modal="false">
+      <div style="position: absolute; top: 23px; left: 12px;width:4px;height:17px;background:#409EFF;border-radius:1px;" />
+      <div align="center">
+        <div>是否删除以下准出报告?</div>
+        <div style="color: #f79232;">{{ details.reportName }}</div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" size="mini" @click="deleteDaily()">确 定</el-button>
+        <el-button type="danger" size="mini" @click="dialog_testData = false">取 消</el-button>
+      </span>
+    </el-dialog>
+    <ReleaseReport v-if="dialogDaily" ref="DailyReport" @getList="reportreleaseGetReportById(reportId)" />
+  </el-container>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { reportreleaseGetReportById, reportreleaseDelete } from '@/api/reportTemplate'
+import iconDisplay from '@/views/reportManagement/ReleaseReport/components/iconDisplay.vue'
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
+export default {
+  components: {
+    ReleaseReport,
+    iconDisplay
+  },
+  data() {
+    return {
+      dialogDaily: false, // 准出报告弹窗
+      dialog_testData: false, // 操作弹窗
+      reportId: this.$route.query.id,
+      details: {}
+    }
+  },
+  created() {
+    this.reportreleaseGetReportById(this.reportId)
+  },
+  methods: {
+    async reportreleaseGetReportById(e) { // 获取准出报告data
+      const res = await reportreleaseGetReportById(e)
+      if (res.code === 200) {
+        this.details = res.data
+      }
+    },
+    clientButtom(e, data) { // 准出报告
+      this.report_data = data
+      this.dialogDaily = true
+      this.$nextTick(() => {
+        this.$refs.DailyReport.init(e, data)
+      })
+    },
+    async deleteDaily() { // 删除准出报告
+      const res = await reportreleaseDelete({}, this.details.id)
+      if (res.code === 200) {
+        this.dialog_testData = false
+        this.$router.push({ name: '报告' })
+        this.$message({ type: 'success', message: '删除成功' })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.BackgroundCloth {
+.report-Header {
+  margin: 10px 10px 0;
+  background: #FFF;
+  border-radius:4px;
+}
+.from-margin {
+    width: 100%;
+    display: inline-block;
+    font-size:14px;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 140px !important;
+    }
+    .from-names {
+      width: 100px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+    .from-value {
+      margin-left: 30px;
+      color:rgba(126,211,33,1);
+    }
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+
+.details-id {
+  font-size:12px;
+  font-family:PingFang SC;
+  font-weight:400;
+  line-height:20px;
+  color:rgba(51,59,74,1);
+  opacity:0.5;
+}
+
+.report-title {
+  font-size:20px;
+  font-family:PingFangSC-Medium;
+  line-height:28px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.details-statusString {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  padding: 5px 8px;
+  margin-left: 15px;
+  color:rgba(111,124,147,1);
+  border:1px solid rgba(191,198,220,1);
+  opacity:1;
+  border-radius:4px;
+}
+
+.report-main {
+  margin: 10px;
+  background: #FFF;
+  border-radius:4px;
+}
+.report-mains {
+  min-height: 200px;
+  padding: 20px ;
+  margin: 10px 10px 0 0;
+  background: #FFF;
+  border-radius:4px;
+}
+.title {
+  font-size:16px;
+  font-family:PingFangSC-Medium;
+  line-height:35px;
+  margin-bottom: 10px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.title-name {
+  width:100px;
+  font-size:14px;
+  margin-bottom: 10px;
+  font-family:PingFangSC-Regular;
+  line-height:20px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-id {
+  width:100px;
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-name {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+
+.task-bot {
+   margin-bottom: 10px;
+}
+}
+.setLine {
+  padding: 10px 20px;
+}
+</style>

+ 314 - 0
src/views/reportManagement/ReleaseReport/newReleaeTemplate.vue

@@ -0,0 +1,314 @@
+<template>
+  <!-- 新建报告模版 -->
+  <div class="report-container">
+    <el-form ref="fromCreateData" :model="fromCreateData">
+      <el-form-item v-if="releaseType === 'new'" label="模版名称" prop="moduleName" :rules="[{ required: true, message: '模版名称不能为空', trigger: 'change'}]"><br>
+        <el-input v-model="fromCreateData.moduleName" size="small" style="width:100%;" placeholder="请输入模版名称(不可与现有模版重名)" />
+      </el-form-item>
+      <el-form-item v-if="releaseType === 'create'" label="报告名称" prop="reportName" :rules="[{ required: true, message: '模版名称不能为空', trigger: 'change'}]"><br>
+        <el-input v-model="fromCreateData.reportName" size="small" style="width:100%;" placeholder="请输入模版名称(不可与现有模版重名)" />
+      </el-form-item>
+      <div class="backStyle">模版内容</div>
+
+      <el-row class="from-margin">
+        <el-col :span="24">
+          <span class="from-names">测试结果: </span>
+          <span class="from-value">通过</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划准出时间: </span>
+          <el-date-picker
+            v-model="from.releasePlanTime"
+            :disabled="releaseType === 'new'"
+            type="date"
+            placeholder="选择日期时间"
+            format="yyyy.MM.dd"
+            value-format="yyyy.MM.dd"
+            style="width: 100%;"
+            size="small"
+          />
+        </el-col>
+        <el-col :span="12">
+          <span class="from-namev"> 实际准出时间:{{ from.releaseActualTime }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_flex_start">
+          <span class="from-name">是否延期: </span>
+          <template>
+            <el-radio-group v-model="from.isDelay">
+              <el-radio :label="0">否</el-radio>
+              <el-radio :label="1">是</el-radio>
+            </el-radio-group>
+          </template>
+        </el-col>
+        <el-col v-show="from.isDelay === 1" :span="12" class="Layout_space_between">
+          <span class="from-namea"><span v-if="releaseType === 'create'" style="color:red;">*</span>准出延期原因 : </span>
+          <el-input v-model="from.delayReason" size="small" :disabled="releaseType === 'new'" placeholder="请输入准出原因" style="width: 80%;" />
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划开发周期: </span>
+          <el-date-picker v-model="from.testPlanTimeStart" type="daterange" size="small" :disabled="releaseType === 'new'" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer"> 实际开发周期:</span>
+          <el-date-picker v-model="from.testPlanTimeEnd" type="daterange" size="small" :disabled="releaseType === 'new'" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划测试周期: </span>
+          <el-date-picker v-model="from.testActualTimeStart" type="daterange" size="small" :disabled="releaseType === 'new'" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer">实际测试周期:</span>
+          <el-date-picker v-model="from.testActualTimeEnd" type="daterange" size="small" :disabled="releaseType === 'new'" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">开发人员: </span>
+          <searchTeam :value.sync="from.developer" :clearable="true" :multiple="true" :disabled="releaseType === 'new'" :size="'small'" style="width: 100%;" />
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer"> 测试人员:</span>
+          <searchTeam :value.sync="from.tester" :clearable="true" :multiple="true" :disabled="releaseType === 'new'" :size="'small'" style="width: 100%;" />
+        </el-col>
+      </el-row>
+      <normal-area id="report-template" :value.sync="fromCreateData.content" :height="500" />
+    </el-form>
+    <div class="backStyle">缺陷统计</div>
+    <iconDisplay :task-ids="releaseType === 'new' ? taskId : fromCreateData.taskIds" />
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss' // 公共css
+import searchTeam from '@/components/select/searchTeam' // 人员搜索
+import normalArea from '@/components/input/normalArea' // 富文本
+import iconDisplay from '@/views/reportManagement/ReleaseReport/components/iconDisplay.vue'
+import { settingAddReportModule, settingUpdateReportModule, settingGetReportModuleById, reportreleaseInitReportRelease, reportreleaseCreate, reportreleaseUpdate } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  components: {
+    normalArea,
+    searchTeam,
+    iconDisplay
+  },
+  props: {
+    templateId: { type: [String, Number, Object], default: null }, // 模版id
+    type: { type: String, default: 'new' },
+    taskIds: { type: Array, default: null }
+  },
+  data() {
+    return {
+      tpltId: '', // 模版id
+      taskId: [], // 创建准出的任务
+      fromCreateData: {}, // from
+      from: {}, // from-date
+      releaseType: '' // 新建模版还是新建准出报告
+    }
+  },
+  watch: {
+    templateId: {
+      handler(newV) {
+        console.log(newV, '更新')
+        if (newV.id) {
+          console.log(newV, '有数据')
+          this.fromCreateData = newV
+          this.from = newV
+        } else {
+          this.tpltId = newV
+          if (newV !== 1 && newV !== 2) {
+            this.tpltId ? this.settingGetReportModuleById(newV) : ''
+          }
+          if (newV === 1) {
+            this.fromCreateData.content = `
+          <p>背景</p><br>
+          <div>测试内容</div>
+          <p>功能测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="20%"><col width="20%"><col width="20%"><col width="20%"></colgroup><thead><tr><th>页面</th><th>模块</th><th>接口</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <p>兼容性测试-机型兼容</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>机型</th><th>操作系统</th><th>分辨率</th><th>测试结果</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <p>兼容性测试-网络兼容</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>网络类型</th><th>测试结果</th></tr></thead><tbody><tr><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td></tr></tbody></table>
+          <p>产品验收</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="20%"><col width="20%"><col width="20%"><col width="20%"></colgroup><thead><tr><th>验收项</th><th>验收点</th><th>验收人</th><th>验收结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+         `
+          }
+          if (newV === 2) {
+            this.fromCreateData.content = `
+          <p>背景</p><br>
+          <div>测试内容</div>
+          <p>功能测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="20%"><col width="20%"><col width="20%"><col width="20%"></colgroup><thead><tr><th>页面</th><th>模块</th><th>接口</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <p>可靠性测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>子类</th><th>描述</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <p>稳定性测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>子类</th><th>描述</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <p>安全性测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>子类</th><th>描述</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+         `
+          }
+        }
+      },
+      immediate: true
+    },
+    type: {
+      handler(newV) {
+        this.releaseType = newV
+      },
+      immediate: true
+    },
+    taskIds: {
+      handler(newV) {
+        if (newV) {
+          this.taskId = newV
+          this.reportreleaseInitReportRelease(newV)
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async reportreleaseInitReportRelease(val) { // 获取表单数据
+      const res = await reportreleaseInitReportRelease({ taskIds: val })
+      if (res.code === 200) {
+        this.from = res.data
+      }
+    },
+    async settingGetReportModuleById(val) { // 获取自定义模版内容
+      const res = await settingGetReportModuleById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+
+    // 创建准出报告
+    reportreleaseCreate(val) {
+      this.$refs.fromCreateData.validate((valid) => {
+        if (valid) {
+          console.log(this.from, this.fromCreateData, 'cdfcfd')
+          if (val) {
+            const data = this.fromCreateData
+            data.id = this.fromCreateData.id
+            data.releasePlanTime = this.from.releasePlanTime
+            data.releaseActualTime = this.from.releaseActualTime
+            data.isDelay = this.from.isDelay
+            data.delayReason = this.from.delayReason
+            data.testPlanTimeStart = this.from.testPlanTimeStart
+            data.testPlanTimeEnd = this.from.testPlanTimeEnd
+            data.testActualTimeStart = this.from.testActualTimeStart
+            data.testActualTimeEnd = this.from.testActualTimeEnd
+            data.developer = this.from.developer ? this.from.developer.toString() : null
+            data.tester = this.from.tester ? this.from.tester.toString() : null
+            reportreleaseUpdate(data).then(res => {
+              if (res.code === 200) {
+                this.$emit('SaveNextStep', res.data)
+                this.$message({ type: 'success', message: '更新成功' })
+              }
+            })
+          } else {
+            const data = this.from
+            data.taskIds = this.taskId
+            data.content = this.fromCreateData.content
+            data.reportName = this.fromCreateData.reportName
+            data.bizId = localStorage.getItem('bizId')
+            data.moduleId = this.tpltId
+            data.developer = this.from.developer ? this.from.developer.toString() : null
+            data.tester = this.from.tester ? this.from.tester.toString() : null
+            reportreleaseCreate(data).then(res => {
+              if (res.code === 200) {
+                this.$emit('SaveNextStep', res.data)
+                this.$message({ type: 'success', message: '创建成功' })
+              }
+            })
+          }
+        }
+      })
+    },
+
+    // 新建模版
+    getCreateData(e) {
+      this.$refs.fromCreateData.validate((valid) => {
+        if (valid) {
+          this.fromCreateData.bizId = localStorage.getItem('bizId')
+          this.fromCreateData.type = e
+          if (this.tpltId) {
+            settingUpdateReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '更新成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          } else {
+            settingAddReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '创建成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .backStyle {
+    font-size:16px;
+    font-family:MicrosoftYaHei;
+    line-height:19px;
+    color:rgba(51,51,51,1);
+    margin: 1% 0;
+  }
+
+.report-container {
+    display: inline-block;
+    font-size:14px;
+    width: 100%;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 140px !important;
+    }
+    .from-names {
+      width: 100px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+    .from-value {
+      margin-left: 30px;
+      color:rgba(126,211,33,1);
+    }
+}
+
+  .from-margin {
+    margin-bottom:20px;
+  }
+</style>

+ 190 - 0
src/views/reportManagement/ReleaseReport/releaePreview.vue

@@ -0,0 +1,190 @@
+<template>
+  <!-- 预览准出报告 -->
+  <div class="parent-style">
+    <div class="backStyle"> 邮件列表</div>
+    <div class="Layout_space_between" style="margin-bottom: 10px;">
+      <div class="div1">收件人</div>
+      <searchTeam :value.sync="form.name" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div class="Layout_space_between">
+      <div class="div1">抄送</div>
+      <searchTeam :value.sync="form.names" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div id="repot-list">
+      <div class="backStyle">模版名称 :{{ fromCreateData.reportName }}</div>
+      <div class="backStyle">模版内容</div>
+
+      <el-row>
+        <el-col :span="24">
+          <span class="from-names">测试结果: </span>
+          <span class="from-value">通过</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划准出时间:{{ fromCreateData.releasePlanTime }}</span>
+        </el-col>
+        <el-col :span="12">
+          <span class="from-namev"> 实际准出时间:{{ fromCreateData.releaseActualTime }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="24" class="Layout_space_between">
+          <span class="from-namea">准出延期原因 : {{ fromCreateData.moduleName }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划开发周期:{{ fromCreateData.testPlanTimeStart }}</span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer"> 实际开发周期:{{ fromCreateData.testPlanTimeEnd }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划测试周期:{{ fromCreateData.testActualTimeStart }} </span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer">实际测试周期:{{ fromCreateData.testActualTimeEnd }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">开发人员:{{ fromCreateData.developer }}</span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer"> 测试人员:{{ fromCreateData.tester }}</span>
+        </el-col>
+      </el-row>
+      <div v-html="fromCreateData.content" />
+      <div class="backStyle">缺陷统计</div>
+      <iconDisplay :task-ids="fromCreateData.taskIds" />
+    </div>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import html2canvas from 'html2canvas'
+import searchTeam from '@/components/select/searchTeam'
+import iconDisplay from '@/views/reportManagement/ReleaseReport/components/iconDisplay.vue'
+import { reportreleaseGetReportById, reportreleaseSendmail } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  name: 'DailyNewsAdded',
+  components: {
+    searchTeam,
+    iconDisplay
+  },
+  props: {
+    dailyId: { type: [String, Number], default: null }
+  },
+  data() {
+    return {
+      form: {}, // 发送报告content
+      fromCreateData: {}, // listAll
+      tasksOptions: [], // 任务下拉选项
+      tasksDetailList: [], // 已有任务项目
+      taskid_arr: [], // taskIds
+      moduleId: '', // 模块id
+      daily_Id: '' // daily_Id
+    }
+  },
+  watch: {
+    dailyId: {
+      handler(newV) {
+        this.daily_Id = newV
+        this.reportreleaseGetReportById(newV)
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async reportreleaseGetReportById(val) { // 获取准出报告数据
+      const res = await reportreleaseGetReportById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+
+    sendReport() {
+      if (this.form.name !== undefined) {
+        setTimeout(() => {
+          html2canvas(document.getElementById('repot-list'), { useCORS: true }).then(canvas => {
+            const imgData = canvas.toDataURL('image/png', 1)
+            const sendImgData = imgData.toString().substring(imgData.indexOf(',') + 1)
+            const postData = { 'reportId': this.daily_Id, 'imgStr': sendImgData, 'url': window.location.href, 'emailUser': this.form.name ? this.form.name.join(',') : null, 'copyTo': this.form.names ? this.form.names.join(',') : null }
+            reportreleaseSendmail(postData).then(res => {
+              res.code === 200 ? this.$message.success('报告发送中,请稍后进行邮件查收!') : this.$message.error('发送测试日报失败,请联系管理员!')
+              this.$emit('handleClose')
+            })
+          })
+        }, 500)
+      } else {
+        this.$message({ message: '请填写邮箱', type: 'error', offset: 150 })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.parent-style {
+    width: 100%;
+    display: inline-block;
+    font-size:14px;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 140px !important;
+    }
+    .from-names {
+      width: 100px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+    .from-value {
+      margin-left: 30px;
+      color:rgba(126,211,33,1);
+    }
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+.div1 {
+    width: 60px;
+    font-size: 14px;
+    font-family: MicrosoftYaHei;
+    color: rgba(51, 51, 51, 1);
+    line-height: 19px;
+}
+  .backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+</style>

+ 210 - 0
src/views/reportManagement/Testing/TestingPreview.vue

@@ -0,0 +1,210 @@
+<template>
+  <!-- 预览提测报告 -->
+  <div class="parent-style">
+    <div class="backStyle"> 邮件列表</div>
+    <div class="Layout_space_between" style="margin-bottom: 10px;">
+      <div class="div1">收件人</div>
+      <searchTeam :value.sync="form.name" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div class="Layout_space_between">
+      <div class="div1">抄送</div>
+      <searchTeam :value.sync="form.names" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div id="repot-list">
+      <div class="backStyle">报告名称 :{{ fromCreateData.reportName }}</div>
+      <div class="backStyle">报告内容</div>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划提测时间:{{ fromCreateData.deliverTestPlanTime }}</span>
+        </el-col>
+        <el-col :span="12">
+          <span class="from-namev">实际提测时间:{{ fromCreateData.deliverTestActualTime }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row v-show="fromCreateData.isDelay === 1" class="from-margin">
+        <el-col :span="24" class="Layout_space_between">
+          <span class="from-namea">提测延期原因 : {{ fromCreateData.delayReason }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划开发时间:{{ fromCreateData.devPlanTimeStart + '至' + fromCreateData.devPlanTimeEnd }}</span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer">实际开发时间:{{ fromCreateData.devActualTimeStart + '至' + fromCreateData.devActualTimeEnd }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">是否跟版:{{ fromCreateData.followVersion === 2 ? '否' : '是' }} </span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer">跟版客户端:{{ fromCreateData.involveAppString }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">CodeReview:{{ fromCreateData.isCodeReview === 0 ? '否' : '是' }}</span>
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer">执行人:{{ fromCreateData.codeReviewExecutor }}</span>
+        </el-col>
+      </el-row>
+      <div class="backStyle">需求列表</div>
+
+      <el-table
+        :data="tableData"
+        border
+        size="mini"
+        :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+        style="width: 100%; margin-bottom: 20px;"
+        show-overflow-tooltip="true"
+      >
+        <el-table-column prop="bugName" label="需求" align="center" min-width="250" show-overflow-tooltip>
+          <template slot-scope="scope">
+            <span class="didi-hover">{{ scope.row.bugName }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="priorityLevel" label="优先级" align="center" min-width="100" show-overflow-tooltip />
+        <el-table-column prop="priorityName" label="PM" align="center" min-width="100" show-overflow-tooltip />
+        <el-table-column prop="creatorList" label="跟版客户端" align="center" min-width="90" show-overflow-tooltip />
+      </el-table>
+
+      <div v-html="fromCreateData.content" />
+
+    </div>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import html2canvas from 'html2canvas'
+import searchTeam from '@/components/select/searchTeam'
+import { reportdelivertestGetReportById, reportdelivertestSendmail, reportdelivertestGetRequiresByTaskIds } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  name: 'DailyNewsAdded',
+  components: {
+    searchTeam
+  },
+  props: {
+    dailyId: { type: [String, Number], default: null }
+  },
+  data() {
+    return {
+      form: {}, // 发送报告content
+      fromCreateData: {}, // listAll
+      tasksOptions: [], // 任务下拉选项
+      tasksDetailList: [], // 已有任务项目
+      taskid_arr: [], // taskIds
+      moduleId: '', // 模块id
+      tableData: [],
+      daily_Id: '' // daily_Id
+    }
+  },
+  watch: {
+    dailyId: {
+      handler(newV) {
+        console.log(newV, 'cdskcjbdsjcbdsbcnjdsncjkdsncjkdsncjkdsncjkldsncklsdnclkndsklcndklsnckl')
+        this.daily_Id = newV
+        this.reportdelivertestGetReportById(newV)
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async reportdelivertestGetReportById(val) { // 获取提测报告数据
+      const res = await reportdelivertestGetReportById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+        this.reportdelivertestGetRequiresByTaskIds(this.fromCreateData.taskIds)
+      }
+    },
+
+    async reportdelivertestGetRequiresByTaskIds(val) {
+      const res2 = await reportdelivertestGetRequiresByTaskIds({ taskIds: val })
+      if (res2.code === 200) {
+        this.tableData = res2.data.list
+      }
+    },
+
+    sendReport() {
+      if (this.form.name !== undefined) {
+        setTimeout(() => {
+          html2canvas(document.getElementById('repot-list'), { useCORS: true }).then(canvas => {
+            const imgData = canvas.toDataURL('image/png', 1)
+            const sendImgData = imgData.toString().substring(imgData.indexOf(',') + 1)
+            const postData = { 'reportId': this.daily_Id, 'imgStr': sendImgData, 'url': window.location.href, 'emailUser': this.form.name ? this.form.name.join(',') : null, 'copyTo': this.form.names ? this.form.names.join(',') : null }
+            reportdelivertestSendmail(postData).then(res => {
+              res.code === 200 ? this.$message.success('报告发送中,请稍后进行邮件查收!') : this.$message.error('发送测试日报失败,请联系管理员!')
+              this.$emit('handleClose')
+            })
+          })
+        }, 500)
+      } else {
+        this.$message({ message: '请填写邮箱', type: 'error', offset: 150 })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.parent-style {
+    width: 100%;
+    display: inline-block;
+    font-size:14px;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 140px !important;
+    }
+    .from-names {
+      width: 100px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+    .from-value {
+      margin-left: 30px;
+      color:rgba(126,211,33,1);
+    }
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+.div1 {
+    width: 60px;
+    font-size: 14px;
+    font-family: MicrosoftYaHei;
+    color: rgba(51, 51, 51, 1);
+    line-height: 19px;
+}
+  .backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+</style>

+ 247 - 0
src/views/reportManagement/Testing/components/acceptTheReport.vue

@@ -0,0 +1,247 @@
+<template>
+  <!-- 提测预览 -->
+  <div class="eleStyle_one">
+    <div class="reportContent">
+      <div style="display: flex; white-space: nowrap; font-family:SimSuncss">
+        <span style="flex:1;font-weight: bold;font-size: 20px;color: #3a8ee6">{{ fromCreateData.name }}</span>
+        <span style="flex:2;margin:1% 0 0 20px;font-size: 17px;">by {{ fromCreateData.submitter }}</span>
+      </div>
+      <div class="titleStyle" style="margin:1% 0;">一. 提测详情</div>
+      <div v-if="oneShow">
+        <el-form :model="fromCreateData">
+          <div style="display: flex;">
+            <div style="flex:1" class="marage">是否延期 : <span :style="lateStatus1">{{ lateStatus }}</span></div><br>
+            <div v-show="showDelay" style="flex:1" class="marage">延期原因 : {{ fromCreateData.lateReason }}</div><br>
+          </div>
+
+          <div style="display: flex;">
+            <div style="flex:1" class="marage">涉及安全项 : <span :style="safeStatus1">{{ safeStatus }}</span></div><br>
+            <div v-show="showData" style="flex:1" class="marage">完成结果 : {{ fromCreateData.safeInfo }}</div><br>
+          </div>
+
+          <div style="display: flex;">
+            <el-form-item style="flex:1;margin: 0 0 1%;" label="CodeReview : "><span :style="CodeReview1">{{ CodeReview }}</span></el-form-item>
+            <el-form-item v-show="showCodeReview" style="flex:1" label="执行人 : ">{{ fromCreateData.crBy }}</el-form-item>
+          </div>
+
+          <div style="display: flex;">
+            <div style="flex:1">
+              <div class="marage">SDL链接 : <a href="http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=237016271" style="color:blue;">普惠SDL准入标准</a></div><br>
+              <div class="marage">是否跟版 : {{ fromCreateData.isEdition }}</div><br>
+              <div class="marage">优 先 级 : {{ fromCreateData.priority }}</div><br>
+            </div>
+            <div style="flex:1;">
+              <div class="marage">开发时间 : {{ fromCreateData.devTimeStart }} 至 {{ fromCreateData.devTimeEnd }}</div><br>
+              <div class="marage">计划提测时间 : {{ fromCreateData.planLaunchTime }}</div><br>
+              <div class="marage">实际提测时间 : {{ fromCreateData.launchTime }}</div><br>
+            </div>
+          </div>
+          <div class="marage">prd地址 : {{ fromCreateData.prdUrl }}</div><br>
+          <div class="marage">设计方案 : {{ fromCreateData.devUrl }}</div><br>
+          <div class="marage">自测结果 : {{ fromCreateData.selfTestInfo }}</div><br>
+          <div class="marage">测试建议 : {{ fromCreateData.testSuggest }}</div><br>
+          <el-form-item label="提测模块" style="margin: 2px 0;" />
+          <div class="rich" v-html=" moduleInfoOne" />
+        </el-form>
+      </div>
+
+      <div v-if="towShow">
+        <el-form :model="fromCreateData">
+          <div style="display:flex;">
+            <div style="flex:1">
+              <el-form-item label="测试地址 : ">{{ fromCreateData.packageUrl }}</el-form-item><br>
+              <el-form-item label="提测环境 : ">{{ fromCreateData.env }}</el-form-item><br>
+              <el-form-item label="自测结果 : ">{{ fromCreateData.selfTestInfo }}</el-form-item><br>
+            </div>
+            <div style="flex:1">
+              <el-form-item label="打包分支 : ">{{ fromCreateData.packageBranch }}</el-form-item><br>
+              <el-form-item label="优 先 级 : ">{{ fromCreateData.priority }}</el-form-item><br>
+            </div>
+          </div>
+
+          <div style="display: flex;">
+            <el-form-item style="flex:1" label="新增Apollo : "><span :style="configInfo1">{{ config }}</span></el-form-item><br>
+            <el-form-item v-show="showDelay1" style="flex:1" label="Apollo名称 : ">{{ fromCreateData.configInfo }}</el-form-item><br>
+          </div>
+
+          <div style="display: flex;">
+            <el-form-item style="flex:1;margin: 1% 0;" label="依赖组件 : "><span :style="dependentComponents1">{{ dependentCom }}</span></el-form-item>
+            <el-form-item v-show="showDelay2" style="flex:1" label="组件名称 : ">{{ fromCreateData.dependentComponents }}</el-form-item>
+          </div>
+
+          <div style="display: flex;">
+            <el-form-item style="flex:1;margin: 0 0 1%;" label="是否延期 : "><span :style="lateStatus1">{{ lateStatus }}</span></el-form-item>
+            <el-form-item v-show="showDelay" style="flex:1" label="延期原因 : ">{{ fromCreateData.lateReason }}</el-form-item>
+          </div>
+
+          <div style="display: flex;">
+            <el-form-item style="flex:1;margin: 0 0 1%;" label="CodeReview : "><span :style="CodeReview1">{{ CodeReview }}</span></el-form-item>
+            <el-form-item v-show="showCodeReview" style="flex:1" label="执行人 : ">{{ fromCreateData.crBy }}</el-form-item>
+          </div>
+
+          <el-form-item label="PM & UI : ">{{ fromCreateData.pmUi }}</el-form-item><br>
+          <div class="noWrap">
+            <el-form-item label="测试建议 :">{{ fromCreateData.testSuggest }}</el-form-item><br>
+            <el-form-item label="需求list :">{{ fromCreateData.functionInfo }}</el-form-item><br>
+            <el-form-item label="涉及接口 :">{{ fromCreateData.interfaceInfo }}</el-form-item><br>
+          </div>
+        </el-form>
+      </div>
+      <div class="titleStyle">二. 联调详情</div>
+      <div class="rich" v-html="joinTestOne" />
+
+      <div class="titleStyle">三. 其他</div>
+      <el-form :model="fromCreateData">
+        <div class="noWrap">
+          <el-form-item v-if="oneShow" label="新增配置 :">{{ fromCreateData.configInfo }}</el-form-item><br>
+          <el-form-item label="其他 :">{{ fromCreateData.others }}</el-form-item><br>
+        </div>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'AcceptTheReport',
+  props: {
+    message: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      configInfo1: { color: 'green' },
+      dependentComponents1: { color: 'green' },
+      lateStatus1: { color: 'red' },
+      CodeReview1: { color: 'red' },
+      safeStatus1: { color: 'green' },
+      form: {},
+      dependentCom: '否',
+      config: '否',
+      showDelay: false,
+      showDelay1: false,
+      showDelay2: false,
+      showCodeReview: false,
+      towShow: false,
+      oneShow: false,
+      showData: false,
+      joinTestOne: '',
+      lateStatus: '',
+      CodeReview: '否', // CodeReview
+      safeStatus: '',
+      name: '',
+      haha: '',
+      moduleInfoOne: '',
+      fromCreateData: {}
+    }
+  },
+  created() {
+    this.idGet()
+  },
+  methods: {
+    idGet() {
+      this.fromCreateData = this.message
+
+      if (this.fromCreateData.type === 2) {
+        this.towShow = false
+        this.oneShow = true
+      } else {
+        this.oneShow = false
+        this.towShow = true
+      }
+      this.name = this.fromCreateData.name
+      this.joinTestOne = this.fromCreateData.joinTest
+      this.moduleInfoOne = this.fromCreateData.moduleInfo
+      if (this.fromCreateData.safeInfo !== '') {
+        this.showData = true
+        this.safeStatus = '是'
+        this.safeStatus1.color = 'red'
+      } else {
+        this.showData = false
+        this.safeStatus = '否'
+        this.safeStatus1.color = 'green'
+      }
+
+      if (this.fromCreateData.lateReason !== '' && this.fromCreateData.lateReason !== null) {
+        this.showDelay = true
+        this.lateStatus = '是'
+      } else {
+        this.showDelay = false
+        this.lateStatus = '否'
+        this.lateStatus1.color = 'green'
+      }
+      if (this.fromCreateData.configInfo !== '') {
+        this.showDelay1 = true
+        this.config = '是'
+      } else {
+        this.showDelay1 = false
+        this.config = '否'
+        this.configInfo1.color = 'red'
+      }
+      if (this.fromCreateData.dependentComponents !== '') {
+        this.showDelay2 = true
+        this.dependentCom = '是'
+      } else {
+        this.showDelay2 = false
+        this.dependentCom = '否'
+        this.dependentComponents1.color = 'red'
+      }
+      if (this.fromCreateData.crBy !== '' && this.fromCreateData.crBy !== null) { // CodeReview
+        this.showCodeReview = true
+        this.CodeReview = '是'
+        this.CodeReview1.color = 'green'
+      } else {
+        this.showCodeReview = false
+        this.CodeReview = '否'
+      }
+    }
+
+  }
+}
+</script>
+
+<style scoped>
+  .reportContent {
+    padding: 2%;
+  }
+  .marage {
+    padding: 2% 0;
+  }
+  .eleStyle_one {
+    width: 100%;
+    height:100%;
+    display: inline-block;
+    font-size: 14px;
+    color: #606266;
+  }
+   .eleStyle_one .el-form-item {
+      margin-bottom: -15px;
+    }
+  .titleStyle {
+    color: #333B4A;
+    margin: 1% 0;
+    font-size: 17px;
+    font-weight: bold;
+  }
+  .rich>>> table tr td{border:1px solid #ccc;font-size: 15px; color: #606266}
+  .rich>>> table th{border:1px solid #ccc; font-size: 15px; background: #F0F7FF; color: #606266}
+  .rich>>> table {border:1px solid #ccc; border-collapse: collapse;line-height: 30px; text-align: center;font-size: 15px; color: #606266}
+
+</style>
+<style lang="stylus" scoped>
+ .noWrap >>> .el-form-item
+  display flex
+ .eleStyle_one  >>> .el-form-item__label
+  text-align left
+  font-weight 400 !important
+</style>
+<style scoped lang="scss">
+/deep/ .el-form-item__content{
+  white-space: pre-line
+}
+.marage {
+  white-space: pre-line
+}
+</style>

+ 361 - 0
src/views/reportManagement/Testing/components/deliverDetails.vue

@@ -0,0 +1,361 @@
+<template>
+  <el-container class="BackgroundCloth">
+    <el-header class="public_header setLine">
+      <div class="Layout_space_between">
+        <div class="Layout_flex_start">
+          <div>
+            <span class="details-id">{{ 'report-' + details.id }}</span><br>
+            <span class="report-title">{{ details.reportName }}</span>
+          </div>
+          <div class="details-statusString">{{ details.statusString }}</div>
+        </div>
+        <div v-if="details.status === 1 ? false : true">
+          <span v-if="details.status === 3 ? true : false" class="didi-hover" @click="dialog_testData = true, AsTp = '通过'">通过</span>
+          <span v-if="details.status === 3 ? true : false" style="margin-left: 30px;" class="didi-hover" @click="dialog_testData = true, AsTp = '打回'">打回</span>
+          <span v-if="details.status === 0 ? true : false" class="didi-hover" @click="report_click(3,details)">发送</span>
+          <span v-if="details.status === 0 ? true : false" style="margin: 0 30px;" class="didi-hover" @click="report_click(2,details)">编辑</span>
+          <span v-if="details.status === 0 ? true : false" class="didi-hover" @click="dialog_testData = true, AsTp = '删除'">删除</span>
+          <span v-if="details.status === 2 ? true : false" class="didi-hover" @click="report_click(2,details)">重新提测</span>
+        </div>
+      </div>
+    </el-header>
+    <el-container>
+      <el-main class="report-main">
+        <div class="title"><div class="blur-column" /> 报告内容</div>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">计划提测时间:{{ details.deliverTestPlanTime }}</span>
+          </el-col>
+          <el-col :span="12">
+            <span class="from-namev">实际提测时间:{{ details.deliverTestActualTime }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row v-show="details.isDelay === 1" class="from-margin">
+          <el-col :span="24" class="Layout_space_between">
+            <span class="from-namea">提测延期原因 : {{ details.delayReason }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">计划开发时间:{{ details.devPlanTimeStart + '至' + details.devPlanTimeEnd }}</span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer">实际开发时间:{{ details.devActualTimeStart + '至' + details.devActualTimeEnd }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">是否跟版:{{ details.followVersion === 2 ? '否' : '是' }} </span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer">跟版客户端:{{ details.involveAppString }}</span>
+          </el-col>
+        </el-row>
+
+        <el-row class="from-margin">
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-name">CodeReview:{{ details.isCodeReview === 0 ? '否' : '是' }}</span>
+          </el-col>
+          <el-col :span="12" class="Layout_space_between">
+            <span class="from-namer">执行人:{{ details.codeReviewExecutor }}</span>
+          </el-col>
+        </el-row>
+        <div class="backStyle">需求列表</div>
+
+        <el-table
+          :data="tableData"
+          border
+          size="mini"
+          :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+          style="width: 100%; margin-bottom: 20px;"
+          show-overflow-tooltip="true"
+        >
+          <el-table-column prop="bugName" label="需求" align="center" min-width="250" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <span class="didi-hover">{{ scope.row.bugName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="priorityLevel" label="优先级" align="center" min-width="100" show-overflow-tooltip />
+          <el-table-column prop="priorityName" label="PM" align="center" min-width="100" show-overflow-tooltip />
+          <el-table-column prop="creatorList" label="跟版客户端" align="center" min-width="90" show-overflow-tooltip />
+        </el-table>
+
+        <div v-html="details.content" />
+
+      </el-main>
+      <el-aside width="400px">
+        <el-container>
+          <el-header class="report-mains">
+            <div class="title"><div class="blur-column" /> 用户信息</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">报告人 : </div>
+              <div class="task-name">{{ details.reportorObject ? details.reportorObject.name : '' }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">收件人 : </div>
+              <div v-for="(item, index) in details.sendToObject" :key="index" class="task-name"> {{ item.name }} <span v-if="index < details.sendToObject.length - 1"> , </span></div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">抄送人 : </div>
+              <div v-for="(item, index) in details.sendCcObject" :key="index" class="task-name">{{ item.name }} <span v-if="index < details.sendCcObject.length - 1"> , </span></div>
+            </div>
+          </el-header>
+          <el-main class="report-mains">
+            <div class="title"><div class="blur-column" /> 时间</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">创建时间 : </div>
+              <div class="task-name">{{ details.gmtCreate }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">发送时间 : </div>
+              <div class="task-name">{{ details.gmtModify }}</div>
+            </div>
+          </el-main>
+          <el-footer class="report-mains">
+            <div class="title"><div class="blur-column" /> 关联任务</div>
+            <div v-for="(item, index) in details.taskDetailList" :key="index" class="Layout_flex_start task-bot">
+              <div class="task-id">{{ item.taskId }}</div>
+              <div class="task-name">{{ item.name }}</div>
+            </div>
+          </el-footer>
+        </el-container>
+      </el-aside>
+    </el-container>
+    <el-dialog :title="AsTp === '删除'? '删除确认': '提测确认'" :visible.sync="dialog_testData" width="30%" :close-on-click-modal="false">
+      <div style="position: absolute; top: 23px; left: 12px;width:4px;height:17px;background:#409EFF;border-radius:1px;" />
+      <div align="center">
+        <div v-if="AsTp === '删除'">是否删除以下提测报告?</div>
+        <div v-if="AsTp === '通过'">是否通过以下提测报告?</div>
+        <div v-if="AsTp === '打回'">是否打回以下提测报告?</div>
+        <div style="color: #f79232;">{{ details.reportName }}</div>
+        <el-input v-show="AsTp === '打回'" v-model="details.returnReason" type="textarea" placeholder="请输入打回原因..." :rows="3" />
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" size="mini" @click="deleteDaily()">确 定</el-button>
+        <el-button type="danger" size="mini" @click="dialog_testData = false">取 消</el-button>
+      </span>
+    </el-dialog>
+    <TestingReport v-if="dialogDaily" ref="DailyReport" @getList="reportreleaseGetReportById(reportId)" />
+  </el-container>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { reportdelivertestGetReportById, reportreleaseDelete, reportdelivertestGetRequiresByTaskIds, reportdelivertestUpdate } from '@/api/reportTemplate'
+import TestingReport from '@/views/reportManagement/components/TestingReport' // 准出
+export default {
+  components: {
+    TestingReport
+  },
+  data() {
+    return {
+      dialogDaily: false, // 准出报告弹窗
+      dialog_testData: false, // 操作弹窗
+      tableData: [],
+      AsTp: '',
+      reportId: this.$route.query.id,
+      details: {}
+    }
+  },
+  created() {
+    this.reportdelivertestGetReportById(this.reportId)
+  },
+  methods: {
+    async reportdelivertestGetReportById(e) { // 获取准出报告data
+      const res = await reportdelivertestGetReportById(e)
+      if (res.code === 200) {
+        this.details = res.data
+        this.reportdelivertestGetRequiresByTaskIds(this.details.taskIds)
+      }
+    },
+
+    async reportdelivertestGetRequiresByTaskIds(val) {
+      const res2 = await reportdelivertestGetRequiresByTaskIds({ taskIds: val })
+      if (res2.code === 200) {
+        this.tableData = res2.data.list
+      }
+    },
+
+    report_click(e, data) { // 准出报告
+      this.report_data = data
+      this.dialogDaily = true
+      this.$nextTick(() => {
+        this.$refs.DailyReport.init(e, data)
+      })
+    },
+    async deleteDaily() { // 删除准出报告
+      if (this.AsTp === '打回' || this.AsTp === '通过') {
+        const data = {
+          id: this.details.id,
+          moduleId: this.details.moduleId,
+          bizId: this.details.bizId,
+          taskIds: this.details.taskIds,
+          reportName: this.details.reportName,
+          returnReason: this.details.returnReason,
+          status: this.AsTp === '打回' ? 2 : this.AsTp === '通过' ? 1 : ''
+        }
+        const res1 = await reportdelivertestUpdate(data)
+        if (res1.code === 200) {
+          this.dialog_testData = false
+          this.$message({ type: 'success', message: this.AsTp === '打回' ? '已打回' : '已通过' })
+          this.reportdelivertestGetReportById(this.reportId)
+        }
+      }
+      if (this.AsTp === '删除') {
+        const res = await reportreleaseDelete({}, this.details.id)
+        if (res.code === 200) {
+          this.dialog_testData = false
+          this.$router.push({ name: '报告' })
+          this.$message({ type: 'success', message: '删除成功' })
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.BackgroundCloth {
+.report-Header {
+  margin: 10px 10px 0;
+  background: #FFF;
+  border-radius:4px;
+}
+.from-margin {
+    width: 100%;
+    display: inline-block;
+    font-size:14px;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 140px !important;
+    }
+    .from-names {
+      width: 100px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+    .from-value {
+      margin-left: 30px;
+      color:rgba(126,211,33,1);
+    }
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+
+.details-id {
+  font-size:12px;
+  font-family:PingFang SC;
+  font-weight:400;
+  line-height:20px;
+  color:rgba(51,59,74,1);
+  opacity:0.5;
+}
+
+.report-title {
+  font-size:20px;
+  font-family:PingFangSC-Medium;
+  line-height:28px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.details-statusString {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  padding: 5px 8px;
+  margin-left: 15px;
+  color:rgba(111,124,147,1);
+  border:1px solid rgba(191,198,220,1);
+  opacity:1;
+  border-radius:4px;
+}
+
+.report-main {
+  margin: 10px;
+  background: #FFF;
+  border-radius:4px;
+}
+.report-mains {
+  min-height: 200px;
+  padding: 20px ;
+  margin: 10px 10px 0 0;
+  background: #FFF;
+  border-radius:4px;
+}
+.title {
+  font-size:16px;
+  font-family:PingFangSC-Medium;
+  line-height:35px;
+  margin-bottom: 10px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.title-name {
+  width:100px;
+  font-size:14px;
+  margin-bottom: 10px;
+  font-family:PingFangSC-Regular;
+  line-height:20px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-id {
+  width:100px;
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-name {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+
+.task-bot {
+   margin-bottom: 10px;
+}
+}
+.setLine {
+  padding: 10px 20px;
+}
+</style>

+ 71 - 0
src/views/reportManagement/Testing/components/iconDisplay.vue

@@ -0,0 +1,71 @@
+<template>
+  <div>
+    <div class="backStyle">需求列表</div>
+    <el-table :data="report_bugList" border size="mini" style="width: 100%" show-overflow-tooltip="true">
+      <el-table-column prop="bugId" label="缺陷ID" align="center" min-width="80" show-overflow-tooltip />
+      <el-table-column prop="bugName" label="缺陷标题" align="center" min-width="100" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span class="didi-hover" @click.stop="click_bugName(scope.row.id)">{{ scope.row.bugName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="priorityLevel" label="状态" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="priorityName" label="缺陷等级" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="creatorList" label="提报人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="assignerList" label="责任人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="currentHandlerList" label="修复人" align="center" min-width="90" show-overflow-tooltip />
+    </el-table>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { bugGetReportSumData } from '@/api/reportTemplate' // 模版添删改查
+export default {
+  props: {
+    id: { type: Array, default: null }
+  },
+  data() {
+    return {
+      report_bugList: [], // 需求列表
+      taskid_arr: []
+    }
+  },
+  watch: {
+    id: {
+      handler(newV) {
+        if (newV !== null) {
+          this.$forceUpdate()
+          this.taskid_arr = JSON.parse(JSON.stringify(newV))
+          this.taskid_arr.map(item => {
+            this.bugGetReportSumData(item)
+          })
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    click_bugName(id) { // 缺陷跳转
+      this.$router.push({ name: '需求详情', params: { id: id }})
+    },
+    async bugGetReportSumData(data) {
+      const res = await bugGetReportSumData(data) // 获取缺陷统计
+      if (res.code === 200) {
+        this.tableList = []
+        this.tableList.push(res.data)
+      }
+    }
+
+  }
+}
+
+</script>
+
+<style lang="scss" scoped>
+.backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+</style>

+ 327 - 0
src/views/reportManagement/Testing/newTestingTemplate.vue

@@ -0,0 +1,327 @@
+<template>
+  <!-- 新建报告模版 -->
+  <div class="report-container">
+    <el-form ref="fromCreateData" :model="fromCreateData">
+      <el-form-item v-if="releaseType === 'new'" label="模版名称" prop="moduleName" :rules="[{ required: true, message: '模版名称不能为空', trigger: 'change'}]"><br>
+        <el-input v-model="fromCreateData.moduleName" size="small" style="width:100%;" placeholder="请输入模版名称(不可与现有模版重名)" />
+      </el-form-item>
+      <el-form-item v-if="releaseType === 'create'" label="报告名称" prop="reportName" :rules="[{ required: true, message: '报告名称不能为空', trigger: 'change'}]"><br>
+        <el-input v-model="fromCreateData.reportName" size="small" style="width:100%;" placeholder="请输入报告名称名称" />
+      </el-form-item>
+      <div class="backStyle">{{ releaseType === 'create'? "报告内容" : '模版内容' }}</div>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划提测时间: </span>
+          <el-date-picker
+            v-model="from.deliverTestPlanTime"
+            type="date"
+            placeholder="选择日期时间"
+            format="yyyy.MM.dd"
+            :disabled="releaseType === 'new'"
+            value-format="yyyy.MM.dd"
+            style="width: 100%;"
+            size="small"
+          />
+        </el-col>
+        <el-col :span="12">
+          <span class="from-namev"> 实际提测时间:{{ from.deliverTestActualTime }}</span>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col v-show="from.isDelay === 1" :span="24" class="Layout_space_between">
+          <span class="from-namea"><span v-if="releaseType === 'create'" style="color:red;">*</span>提测延期原因 : </span>
+          <el-input v-model="from.delayReason" size="small" :disabled="releaseType === 'new'" placeholder="请输入准出原因" style="width: 100%;" />
+        </el-col>
+      </el-row>
+      {{ from.devPlanTimeStart }}
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-name">计划开发时间:</span>
+          <el-date-picker v-model="from.devPlanTimeStart" type="daterange" :disabled="releaseType === 'new'" size="small" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+        <el-col :span="12" class="Layout_space_between">
+          <span class="from-namer"> 实际开发时间:</span>
+          <el-date-picker v-model="from.devActualTimeStart" type="daterange" size="small" :disabled="releaseType === 'new'" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy.MM.dd" value-format="yyyy.MM.dd" style="width: -webkit-fill-available;" />
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_flex_start">
+          <span class="from-name">是否跟版: </span>
+          <template>
+            <el-radio-group v-model="from.followVersion" :disabled="releaseType === 'new'">
+              <el-radio :label="2">否</el-radio>
+              <el-radio :label="1">是</el-radio>
+            </el-radio-group>
+          </template>
+        </el-col>
+        <el-col v-if="from.followVersion === 1" :span="12" class="Layout_flex_start">
+          <span class="from-namer">跟版客户端</span>
+          <el-select v-model="from.involveAppString" filterable remote size="small" :disabled="releaseType === 'new'" clearable placeholder="请选择" style="width: -webkit-fill-available;">
+            <el-option v-for="item in appClient" :key="item.code" :label="item.msg" :value="item.code" />
+          </el-select>
+        </el-col>
+      </el-row>
+
+      <el-row class="from-margin">
+        <el-col :span="12" class="Layout_flex_start">
+          <span class="from-name"><span style="color: red;">*</span>CodeReview:</span>
+          <template>
+            <el-radio-group v-model="from.isCodeReview" :disabled="releaseType === 'new'">
+              <el-radio :label="0">否</el-radio>
+              <el-radio :label="1">是</el-radio>
+            </el-radio-group>
+          </template>
+        </el-col>
+        <el-col v-if="from.isCodeReview === 1" :span="12" class="Layout_space_between">
+          <span class="from-namer"><span style="color: red;">*</span>执行人:</span>
+          <searchTeam :value.sync="from.codeReviewExecutor" :clearable="true" :multiple="true" :size="'small'" :disabled="releaseType === 'new'" style="width: 100%;" />
+        </el-col>
+      </el-row>
+    </el-form>
+    <div class="backStyle">需求列表</div>
+    <el-table
+      :data="tableData"
+      border
+      size="mini"
+      :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+      style="width: 100%; margin-bottom: 20px;"
+      show-overflow-tooltip="true"
+    >
+      <el-table-column prop="bugName" label="需求" align="center" min-width="250" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span class="didi-hover">{{ scope.row.bugName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="priorityLevel" label="优先级" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="priorityName" label="PM" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="creatorList" label="跟版客户端" align="center" min-width="90" show-overflow-tooltip />
+    </el-table>
+
+    <normal-area id="report-template" :value.sync="fromCreateData.content" :height="500" />
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss' // 公共css
+import searchTeam from '@/components/select/searchTeam' // 人员搜索
+import normalArea from '@/components/input/normalArea' // 富文本
+import { configShowTaskEnum } from '@/api/taskIndex'
+import { settingAddReportModule, settingUpdateReportModule, settingGetReportModuleById, reportdelivertestInitReportRelease, reportdelivertestCreate, reportdelivertestGetRequiresByTaskIds, reportdelivertestUpdate } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  components: {
+    normalArea,
+    searchTeam
+  },
+  props: {
+    templateId: { type: [String, Number], default: null }, // 模版id
+    type: { type: String, default: 'new' },
+    taskIds: { type: Array, default: null }
+  },
+  data() {
+    return {
+      tableData: [],
+      tpltId: '', // 模版id
+      taskId: [], // 创建准出的任务
+      fromCreateData: {}, // from
+      from: {},
+      appClient: [], // 跟版客户端
+      releaseType: '' // 新建模版还是新建准出报告
+    }
+  },
+  watch: {
+    templateId: {
+      handler(newV) {
+        console.log(newV, '更新')
+        if (newV.id) {
+          console.log(newV, '有数据')
+          this.fromCreateData = newV
+          this.from = newV
+        } else {
+          if (newV !== 1 && newV !== 2) {
+            console.log(newV, 'tmepId')
+            this.tpltId = newV
+            this.tpltId ? this.settingGetReportModuleById(newV) : ''
+          }
+          if (newV === 1) {
+            this.tpltId = newV
+            this.fromCreateData.content = `
+          <p>背景</p><br>
+          <div>测试内容</div>
+          <p>功能测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="20%"><col width="20%"><col width="20%"><col width="20%"></colgroup><thead><tr><th>验收项</th><th>验收点</th><th>验收人</th><th>验收结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+         `
+          }
+          if (newV === 2) {
+            this.tpltId = newV
+            this.fromCreateData.content = `
+          <p>背景</p><br>
+          <div>测试内容</div>
+          <p>功能测试</p>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="20%"><col width="20%"><col width="20%"><col width="20%"></colgroup><thead><tr><th>页面</th><th>模块</th><th>接口</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+          <table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>子类</th><th>描述</th><th>测试结果</th><th>备注</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table>
+         `
+          }
+        }
+      },
+      immediate: true
+    },
+    type: {
+      handler(newV) {
+        this.releaseType = newV
+      },
+      immediate: true
+    },
+    taskIds: {
+      handler(newV) {
+        console.log(newV, ' taskids')
+        if (newV) {
+          this.taskId = newV
+          this.reportdelivertestInitReportRelease(newV)
+        }
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.configShowTaskEnum()
+  },
+  methods: {
+    async reportdelivertestInitReportRelease(val) { // 报告时间
+      const res = await reportdelivertestInitReportRelease({ taskIds: val })
+      if (res.code === 200) {
+        console.log(res, 'xsaxabu')
+        this.from = res.data
+      }
+      const res2 = await reportdelivertestGetRequiresByTaskIds({ taskIds: val })
+      if (res2.code === 200) {
+        this.tableData = res.data.list
+      }
+    },
+    async configShowTaskEnum() {
+      const res = await configShowTaskEnum()
+      if (res.code === 200) {
+        this.appClient = res.data.appClient // 涉及客户端
+      }
+    },
+    async settingGetReportModuleById(val) { // 获取自定义模版内容
+      const res = await settingGetReportModuleById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+
+    // 创建提测报告
+    reportreleaseCreate(val) {
+      this.$refs.fromCreateData.validate((valid) => {
+        if (valid) {
+          if (val) {
+            const data = this.fromCreateData
+            data.deliverTestPlanTime = this.from.deliverTestPlanTime
+            data.delayReason = this.from.delayReason
+            data.deliverTestActualTime = this.from.deliverTestActualTime
+            data.devActualTimeStart = this.from.devActualTimeStart
+
+            data.followVersion = this.from.followVersion
+            data.involveAppString = this.from.involveAppString
+
+            data.isCodeReview = this.from.isCodeReview
+            data.codeReviewExecutor = this.from.codeReviewExecutor
+            data.taskIds = this.taskId
+            data.bizId = localStorage.getItem('bizId')
+            data.moduleId = this.tpltId
+            reportdelivertestUpdate(data).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '更新成功' })
+                this.$emit('SaveNextStep', res.data)
+              }
+            })
+          } else {
+            const data = {}
+            data.reportName = this.fromCreateData.reportName
+            data.content = this.fromCreateData.content
+            data.taskIds = this.taskId
+            data.bizId = localStorage.getItem('bizId')
+            data.moduleId = this.tpltId
+            reportdelivertestCreate(data).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '创建成功' })
+                this.$emit('SaveNextStep', res.data)
+              }
+            })
+          }
+        }
+      })
+    },
+
+    // 新建模版
+    getCreateData(e) {
+      this.$refs.fromCreateData.validate((valid) => {
+        if (valid) {
+          this.fromCreateData.bizId = localStorage.getItem('bizId')
+          this.fromCreateData.type = e
+          if (this.tpltId) {
+            settingUpdateReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '更新成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          } else {
+            settingAddReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '创建成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .backStyle {
+    font-size:16px;
+    font-family:MicrosoftYaHei;
+    line-height:19px;
+    color:rgba(51,51,51,1);
+    margin: 1% 0;
+  }
+
+.report-container {
+    display: inline-block;
+    font-size:14px;
+    width: 100%;
+    font-family:Microsoft Sans Serif;
+    font-weight:400;
+    line-height:22px;
+    color:#666666;
+    opacity:1;
+    .from-name {
+      width: 150px !important;
+    }
+    .from-namea {
+      width: 119px !important;
+    }
+    .from-namer {
+      width: 140px !important;
+      margin-left:10px;
+    }
+    .from-namev {
+      margin-left:10px;
+      vertical-align: sub;
+    }
+}
+
+  .from-margin {
+    margin-bottom:20px;
+  }
+</style>

+ 373 - 0
src/views/reportManagement/components/DailyReport.vue

@@ -0,0 +1,373 @@
+<template>
+  <el-dialog :visible.sync="dialogDaliy" width="70vw" class="public_task report-dialog" :title="reportHome ? '测试日报' : `创建测试日报模版`" :close-on-click-modal="false" :destroy-on-close="true" :before-close="handleClose">
+    <div v-if="reportHome" class="blueStripe" />
+    <i v-if="!reportHome" class="el-icon-arrow-left report-return didi-hover" @click="reportReturn" />
+
+    <el-steps v-if="reportHome" :active="active" align-center finish-status="success" class="report-steps">
+      <el-step title="选择模版" />
+      <el-step title="填写报告" />
+      <el-step title="发送报告" />
+    </el-steps>
+
+    <div class="report-leftRight">
+      <div v-if="showOne" style="min-height: 50vh;">
+        <el-row type="flex" justify="center">
+          <el-col :span="19" class="creator">模版名称</el-col>
+          <el-col :span="5" class="creator">创建人</el-col>
+        </el-row>
+        <el-row v-for="(item, index) in reportModel" :key="index" type="flex" justify="center">
+          <el-col :span="19">
+            <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+          </el-col>
+          <el-col :span="5" class="creatorList">{{ item.creatorObject.name }}</el-col>
+        </el-row>
+
+        <div ref="refName" style="max-height: 260px; overflow:scroll; overflow-x: hidden">
+          <el-row v-for="(item, index) in selectTemplate" :key="index" type="flex" justify="center" @mouseover.native="item.operation = true" @mouseleave.native="item.operation = false">
+            <el-col :span="19">
+              <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+            </el-col>
+            <el-col :span="5" class="creatorList">
+              {{ item.creatorObject.name }}
+              <span class="operation">
+                <i class="el-icon-edit-outline didi-hover" @click="open_new_template(item)" />
+                <el-popover :ref="item.id" placement="bottom" width="300" trigger="click">
+                  <div><div class="blur-column" /> 删除模版</div>
+                  <div class="blueStripe" />
+                  <div class="deletreport">是否要删除模版{{ item.moduleName }}?</div>
+                  <div style="text-align: right; margin: 0">
+                    <el-button size="mini" type="danger" @click="settingDeleteReportModule(item)">确定</el-button>
+                    <el-button size="mini" @click="closeDefaultPopover()">取消</el-button>
+                  </div>
+                  <i slot="reference" class="el-icon-delete reportModel didi-hover" />
+                </el-popover>
+              </span>
+            </el-col>
+          </el-row>
+        </div>
+        <el-row type="flex" justify="center">
+          <el-col :span="24">
+            <span class="didi-hover" @click="open_new_template()"><i class="el-icon-circle-plus-outline creatorList didi-hover" /> <span style="margin-left: 8px">新建模版</span></span>
+          </el-col>
+        </el-row>
+      </div>
+
+      <!-- new模版 -->
+      <newReportTemplate v-if="reportTamplate" ref="newReportTemplate" class="daily" :template-id="templateId" @getreportTemplate="getreportTemplate" @reportReturn="reportReturn" />
+      <!-- new模版 -->
+
+      <!-- 新建日报模版 -->
+      <dailyTemplate v-if="newDailyTemplate" ref="dailyTemplate" class="daily" :model-id="fromData.radio" :task-ids="daily_taskIds" @SaveNextStep="SaveNextStep" />
+      <!-- 新建日报模版 -->
+
+      <!-- 日报预览 -->
+      <dailyPreview v-if="dailyPreview" ref="dailyPreview" class="daily" :daily-id="dailyId" @handleClose="handleClose" />
+      <!-- 日报预览 -->
+
+    </div>
+    <div slot="footer" class="dialog-footer" align="center">
+      <!-- 新建模版 -->
+      <el-button v-if="reportTamplate" size="small" type="primary" @click="created_out()">保存</el-button>
+      <!-- 第一步 -->
+      <el-button v-if="showOne" size="small" type="primary" @click="NextStep()">下一步</el-button>
+      <!-- 第二步 -->
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="reportReturn">上一步</el-button>
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="getCreateData">保存, 下一步</el-button>
+      <!-- 第三步 -->
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReportReturn">上一步</el-button>
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReport">发送</el-button>
+    </div>
+
+  </el-dialog>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { settingQueryReportModuleList, settingDeleteReportModule, dailyReportGetV2 } from '@/api/reportTemplate'
+import dailyTemplate from '@/views/reportManagement/daily/dailyTemplate.vue'
+import newReportTemplate from '@/views/reportManagement/daily/newReportTemplate.vue'
+import dailyPreview from '@/views/reportManagement/daily/dailyPreview.vue'
+
+export default {
+  components: {
+    dailyTemplate,
+    newReportTemplate,
+    dailyPreview
+  },
+  data() {
+    return {
+      reportHome: true, // 报告主页
+      reportModel: [
+        { id: 1, moduleName: '客户端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }},
+        { id: 2, moduleName: '服务端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }}
+      ], // 创建的模版
+      templateId: '', // 模版id
+      modelId: '', // 下一步选择的模版id
+      selectTemplate: [], // 模版option
+      fromData: {
+        radio: 1
+      },
+      newDailyTemplate: false, // 新建日报模版
+      reportTamplate: false, // new模版
+      dailyPreview: false, // 日报预览
+      dailyId: '', // 当前创建报告的id
+      updateDaily: false, // 编辑
+      dialogDaliy: false,
+      showOne: true,
+      active: 1,
+      daily_taskIds: [] // 选择的任务ID
+    }
+  },
+  created() {
+    this.getreportTemplate()
+  },
+  methods: {
+    async getreportTemplate() { // 获取模版list
+      const res = await settingQueryReportModuleList({ bizId: localStorage.getItem('bizId'), type: 3 }) // 3 日报
+      if (res.code === 200) {
+        this.$nextTick(() => {
+          const data = res.data
+          this.selectTemplate = data.map(item => ({
+            ...item,
+            operation: false
+          }))
+        })
+      }
+    },
+
+    init(index, newData) {
+      console.log(index, newData, '测试')
+      this.dialogDaliy = true
+      switch (index) {
+        case 2: // 编辑
+          dailyReportGetV2(newData.id).then(res => {
+            if (res.code === 200) {
+              this.daily_taskIds = res.data.taskIds // 关联任务
+              this.fromData.radio = res.data // 选择的模块
+            }
+          })
+          this.reportHome = true // 步骤条
+          this.active = 2 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = true // 隐藏第二步
+          this.dailyPreview = false // 展示第三部
+          this.updateDaily = true // 编辑
+          break
+        case 3: // 发送报告
+          this.dailyId = newData.id
+          this.reportHome = true // 步骤条
+          this.active = 3 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = true // 展示第三部
+          break
+        case 4: // 复制
+          dailyReportGetV2(newData.id).then(res => {
+            if (res.code === 200) {
+              this.daily_taskIds = res.data.taskIds // 关联任务
+              const data = res.data
+              data.updateDaily = false
+              this.fromData.radio = data // 选择的模块
+            }
+          })
+          this.reportHome = true // 步骤条
+          this.active = 2 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = true // 隐藏第二步
+          this.dailyPreview = false // 展示第三部
+          this.updateDaily = false // 新建
+          break
+        case 7: // 新建
+          this.daily_taskIds = newData
+          this.reportHome = true // 步骤条
+          this.active = 1 // 步骤条状态第三步
+          this.showOne = true // 展示第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = false // 隐藏第三部
+          break
+      }
+    },
+
+    report_update() { // 编辑模版
+      this.$refs.DailyReport.getQueryData(3)
+    },
+
+    created_out() { // 新建模版
+      this.$refs.newReportTemplate.getCreateData(3)
+    },
+
+    reportReturn() { // 新建模版点击返回
+      this.fromData.radio = 1
+      this.reportHome = true // 步骤条
+      this.showOne = true // 模版选择
+      this.reportTamplate = false // 编辑区域
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    open_new_template(val) { // 点击新建模版
+      val ? this.templateId = val.id : this.templateId = null
+      this.reportTamplate = true // 编辑区域
+      this.reportHome = false // 步骤条
+      this.showOne = false // 模版选择
+    },
+
+    async settingDeleteReportModule(item) {
+      const res = await settingDeleteReportModule({ id: item.id }, item.id)
+      if (res.code === 200) {
+        this.getreportTemplate()
+        this.closeDefaultPopover()
+        this.$message({ message: '已删除’', type: 'success', duration: 1000, offset: 150 })
+      }
+    },
+
+    closeDefaultPopover() { // 模拟点击
+      this.$refs.refName.click()
+    },
+
+    getCreateData() { // 保存,下一步
+      this.$refs.dailyTemplate.getCreateData(this.updateDaily)
+    },
+
+    NextStep() { // 第一步到第二步
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第二步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 展示第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    SaveNextStep(ele) { // 第二步到第三部
+      this.dailyId = ele.id // 新建报告id
+      this.reportHome = true // 步骤条
+      this.active = 3 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = true // 展示第三部
+    },
+
+    async sendReportReturn() { // 第三步返回第二部
+      const res = await dailyReportGetV2(this.dailyId)
+      if (res.code === 200) {
+        this.daily_taskIds = res.data.taskIds // 关联任务
+        this.fromData.radio = res.data // 选择的模块
+      }
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 隐藏第二步
+      this.dailyPreview = false // 展示第三部
+      this.updateDaily = true // 编辑
+    },
+
+    sendReport() { // 截图
+      this.$refs.dailyPreview.sendReport()
+    },
+
+    handleClose() {
+      this.dialogDaliy = false
+      this.$emit('getList')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-leftRight {
+  margin: 0 13%;
+  >>> .el-row .el-col {
+    margin: 0;
+}
+}
+
+.titIcon {
+    width: 4px;
+    height: 17px;
+    background: #409EFF;
+    border-radius: 1px;
+}
+
+.el-dialog__header {
+    padding: 0 !important;
+}
+
+.reportModel {
+    margin-left: 10px;
+}
+
+.operation {
+    margin-left: 30px;
+}
+
+.creator {
+  display: inline-block;
+  font-size:16px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.creatorList {
+  display: inline-block;
+  font-size:14px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height: 2.8;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.deletreport {
+  font-size:14px;
+  text-align: center;
+  margin: 30px 0;
+  font-family:MicrosoftYaHei;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.report-dialog {
+  >>>.el-dialog__header {
+    padding: 20px 20px 10px;
+    border-bottom: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+  >>>.el-dialog__footer {
+    padding: 15px 20px;
+    text-align: right;
+    border-top: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+}
+.report-return {
+  font-size: 18px;
+  position: absolute;
+  top: 23px;
+  left: 11px;
+}
+.report-steps {
+  margin-bottom: 20px;
+  font-size:16px;
+  font-family:PingFang SC;
+  font-weight:500;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+.daily {
+   max-height: 460px;
+   overflow:scroll;
+   overflow-x: hidden
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+</style>

+ 369 - 0
src/views/reportManagement/components/ReleaseReport.vue

@@ -0,0 +1,369 @@
+<template>
+  <el-dialog :visible.sync="dialogDaliy" width="70vw" class="public_task report-dialog" :title="reportHome ? '准出报告' : `创建准出报告模版`" :close-on-click-modal="false" :destroy-on-close="true" :before-close="handleClose">
+    <div v-if="reportHome" class="blueStripe" />
+    <i v-if="!reportHome" class="el-icon-arrow-left report-return didi-hover" @click="reportReturn" />
+
+    <el-steps v-if="reportHome" :active="active" align-center finish-status="success" class="report-steps">
+      <el-step title="选择模版" />
+      <el-step title="填写报告" />
+      <el-step title="发送报告" />
+    </el-steps>
+
+    <div class="report-leftRight">
+      <div v-if="showOne" style="min-height: 50vh; margin: 0 13%; ">
+        <el-row type="flex" justify="center">
+          <el-col :span="19" class="creator">模版名称</el-col>
+          <el-col :span="5" class="creator">创建人</el-col>
+        </el-row>
+        <el-row v-for="(item, index) in reportModel" :key="index" type="flex" justify="center">
+          <el-col :span="19">
+            <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+          </el-col>
+          <el-col :span="5" class="creatorList">{{ item.creatorObject.name }}</el-col>
+        </el-row>
+
+        <div ref="refName" style="max-height: 260px; overflow:scroll; overflow-x: hidden">
+          <el-row v-for="(item, index) in selectTemplate" :key="index" type="flex" justify="center" @mouseover.native="item.operation = true" @mouseleave.native="item.operation = false">
+            <el-col :span="19">
+              <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+            </el-col>
+            <el-col :span="5" class="creatorList">
+              {{ item.creatorObject.name }}
+              <span class="operation">
+                <i class="el-icon-edit-outline didi-hover" @click="open_new_template(item)" />
+                <el-popover :ref="item.id" placement="bottom" width="300" trigger="click">
+                  <div><div class="blur-column" /> 删除模版</div>
+                  <div class="blueStripe" />
+                  <div class="deletreport">是否要删除模版{{ item.moduleName }}?</div>
+                  <div style="text-align: right; margin: 0">
+                    <el-button size="mini" type="danger" @click="settingDeleteReportModule(item)">确定</el-button>
+                    <el-button size="mini" @click="closeDefaultPopover()">取消</el-button>
+                  </div>
+                  <i slot="reference" class="el-icon-delete reportModel didi-hover" />
+                </el-popover>
+              </span>
+            </el-col>
+          </el-row>
+        </div>
+        <el-row type="flex" justify="center">
+          <el-col :span="24">
+            <span class="didi-hover" @click="open_new_template()"><i class="el-icon-circle-plus-outline creatorList didi-hover" /> <span style="margin-left: 8px">新建模版</span></span>
+          </el-col>
+        </el-row>
+      </div>
+
+      <!-- new模版 -->
+      <newReleaeTemplate v-if="reportTamplate" ref="newReleaeTemplate" class="daily" :template-id="templateId" :task-ids="daily_taskIds" :type="'new'" @getreportTemplate="getreportTemplate" @reportReturn="reportReturn" />
+      <!-- new模版 -->
+
+      <!-- 新建准出模版 -->
+      <newReleaeTemplate v-if="newDailyTemplate" ref="dailyTemplate" class="daily" :template-id="fromData.radio" :task-ids="daily_taskIds" :type="'create'" @SaveNextStep="SaveNextStep" />
+      <!-- 新建准出模版 -->
+
+      <!-- 准出预览 -->
+      <releaePreview v-if="dailyPreview" ref="dailyPreview" class="daily" :daily-id="dailyId" @handleClose="handleClose" />
+      <!-- 准出预览 -->
+
+    </div>
+    <div slot="footer" class="dialog-footer" align="center">
+      <!-- 新建模版 -->
+      <el-button v-if="reportTamplate" size="small" type="primary" @click="created_out()">保存</el-button>
+      <!-- 第一步 -->
+      <el-button v-if="showOne" size="small" type="primary" @click="NextStep()">下一步</el-button>
+      <!-- 第二步 -->
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="reportReturn">上一步</el-button>
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="getCreateData">保存, 下一步</el-button>
+      <!-- 第三步 -->
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReportReturn">上一步</el-button>
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReport">发送</el-button>
+    </div>
+
+  </el-dialog>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { settingQueryReportModuleList, settingDeleteReportModule, reportreleaseGetReportById } from '@/api/reportTemplate'
+import newReleaeTemplate from '@/views/reportManagement/ReleaseReport/newReleaeTemplate.vue'
+import releaePreview from '@/views/reportManagement/ReleaseReport/releaePreview.vue'
+
+export default {
+  components: {
+    releaePreview,
+    newReleaeTemplate
+  },
+  data() {
+    return {
+      templateStatus: false, // 模版状态
+      reportHome: true, // 报告主页
+      reportModel: [
+        { id: 1, moduleName: '客户端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }},
+        { id: 2, moduleName: '服务端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }}
+      ], // 创建的模版
+      templateId: '', // 模版id
+      modelId: '', // 下一步选择的模版id
+      selectTemplate: [],
+      fromData: {
+        radio: 1
+      },
+      bizJson: localStorage.getItem('bizId'),
+      preview: {},
+      newDailyTemplate: false, // 新建日报模版
+      reportTamplate: false, // new模版
+      dailyPreview: false, // 日报预览
+      dailyId: '', // 当前创建报告的id
+      updateDaily: false, // 编辑
+      dialogDaliy: false,
+      showOne: true,
+      showTow: false,
+      active: 1,
+      daily_taskIds: [], // 选择的任务ID
+      num: 0,
+      dailys: this.$route.query.id
+    }
+  },
+  created() {
+    this.getreportTemplate()
+  },
+  methods: {
+    async getreportTemplate() { // 获取模版list
+      const res = await settingQueryReportModuleList({ bizId: this.bizJson, type: 4 })
+      if (res.code === 200) {
+        this.$nextTick(() => {
+          const data = res.data
+          this.selectTemplate = data.map(item => ({
+            ...item,
+            operation: false
+          }))
+          console.log(this.selectTemplate, 'xsaxaxsa')
+        })
+      }
+    },
+    init(index, newData) {
+      this.dialogDaliy = true
+      switch (index) {
+        case 2: // 编辑
+          console.log(newData, '西单商场')
+          this.daily_taskIds = newData.taskIds // 关联任务
+          this.fromData.radio = newData // 选择的模块
+          this.reportHome = true // 步骤条
+          this.active = 2 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = true // 展示第二步
+          this.dailyPreview = false // 隐藏第三部
+          this.updateDaily = true // 编辑
+          break
+        case 3: // 发送报告
+          this.dailyId = newData.id
+          this.reportHome = true // 步骤条
+          this.active = 3 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = true // 展示第三部
+          break
+        case 7: // 新建
+          this.daily_taskIds = newData // taskList
+          this.fromData.radio = 1 // 选择的模版
+          this.reportHome = true // 步骤条
+          this.active = 1 // 步骤条状态第一步
+          this.showOne = true // 展示第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = false // 隐藏第三部
+          this.reportTamplate = false // 隐藏模版
+          break
+        case 8: // 新建
+          this.daily_taskIds = newData
+          this.fromData.radio = 1 // 选择的模版
+          this.reportHome = true // 步骤条
+          this.active = 1 // 步骤条状态第三步
+          this.showOne = true // 展示第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = false // 隐藏第三部
+          break
+      }
+    },
+
+    report_update() { // 编辑模版
+      this.$refs.DailyReport.getQueryData(4)
+    },
+
+    created_out() { // 新建模版
+      this.$refs.newReleaeTemplate.getCreateData(4)
+    },
+
+    reportReturn() { // 新建模版点击返回
+      this.fromData.radio = 1
+      this.reportHome = true // 步骤条
+      this.showOne = true // 模版选择
+      this.reportTamplate = false // 编辑区域
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    open_new_template(val) { // 点击新建模版
+      val ? this.templateId = val.id : this.templateId = null
+      this.reportTamplate = true // 编辑区域
+      this.reportHome = false // 步骤条
+      this.showOne = false // 模版选择
+    },
+
+    async settingDeleteReportModule(item) {
+      const res = await settingDeleteReportModule({ id: item.id }, item.id)
+      if (res.code === 200) {
+        this.getreportTemplate()
+        this.closeDefaultPopover()
+        this.$message({ message: '已删除’', type: 'success', duration: 1000, offset: 150 })
+      }
+    },
+
+    closeDefaultPopover() { // 模拟点击
+      this.$refs.refName.click()
+    },
+
+    getCreateData() { // 保存,下一步
+      this.$refs.dailyTemplate.reportreleaseCreate(this.updateDaily)
+    },
+
+    NextStep() { // 第一步到第二步
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第二步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 展示第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    SaveNextStep(ele) { // 第二步到第三部
+      this.dailyId = ele.id // 新建报告id
+      this.reportHome = true // 步骤条
+      this.active = 3 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = true // 展示第三部
+    },
+
+    async sendReportReturn() { // 第三步返回第二部
+      const res = await reportreleaseGetReportById(this.dailyId)
+      if (res.code === 200) {
+        this.daily_taskIds = null// 关联任务
+        this.fromData.radio = res.data // 选择的模块
+      }
+
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 隐藏第二步
+      this.dailyPreview = false // 展示第三部
+      this.updateDaily = true // 编辑
+    },
+
+    sendReport() { // 截图
+      this.$refs.dailyPreview.sendReport()
+    },
+
+    handleClose() {
+      this.dialogDaliy = false
+      this.$emit('getList')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-leftRight {
+  margin: 0 1%;
+  >>> .el-row .el-col {
+    margin: 0;
+}
+}
+
+.titIcon {
+    width: 4px;
+    height: 17px;
+    background: #409EFF;
+    border-radius: 1px;
+}
+
+.el-dialog__header {
+    padding: 0 !important;
+}
+
+.reportModel {
+    margin-left: 10px;
+}
+
+.operation {
+    margin-left: 30px;
+}
+
+.creator {
+  display: inline-block;
+  font-size:16px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.creatorList {
+  display: inline-block;
+  font-size:14px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height: 2.8;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.deletreport {
+  font-size:14px;
+  text-align: center;
+  margin: 30px 0;
+  font-family:MicrosoftYaHei;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.report-dialog {
+  >>>.el-dialog__header {
+    padding: 20px 20px 10px;
+    border-bottom: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+  >>>.el-dialog__footer {
+    padding: 15px 20px;
+    text-align: right;
+    border-top: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+}
+.report-return {
+  font-size: 18px;
+  position: absolute;
+  top: 23px;
+  left: 11px;
+}
+.report-steps {
+  margin-bottom: 20px;
+  font-size:16px;
+  font-family:PingFang SC;
+  font-weight:500;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+.daily {
+   max-height: 460px;
+   overflow:scroll;
+   overflow-x: hidden
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+</style>

+ 356 - 0
src/views/reportManagement/components/TestingReport.vue

@@ -0,0 +1,356 @@
+<template>
+  <el-dialog :visible.sync="dialogDaliy" width="70vw" class="public_task report-dialog" :title="reportHome ? '提测报告' : `创建提测报告模版`" :close-on-click-modal="false" :destroy-on-close="true" :before-close="handleClose">
+    <div v-if="reportHome" class="blueStripe" />
+    <i v-if="!reportHome" class="el-icon-arrow-left report-return didi-hover" @click="reportReturn" />
+
+    <el-steps v-if="reportHome" :active="active" align-center finish-status="success" class="report-steps">
+      <el-step title="选择模版" />
+      <el-step title="填写报告" />
+      <el-step title="发送报告" />
+    </el-steps>
+
+    <div class="report-leftRight">
+      <div v-if="showOne" style="min-height: 50vh;">
+        <el-row type="flex" justify="center">
+          <el-col :span="19" class="creator">模版名称</el-col>
+          <el-col :span="5" class="creator">创建人</el-col>
+        </el-row>
+        <el-row v-for="(item, index) in reportModel" :key="index" type="flex" justify="center">
+          <el-col :span="19">
+            <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+          </el-col>
+          <el-col :span="5" class="creatorList">{{ item.creatorObject.name }}</el-col>
+        </el-row>
+
+        <div ref="refName" style="max-height: 260px; overflow:scroll; overflow-x: hidden">
+          <el-row v-for="(item, index) in selectTemplate" :key="index" type="flex" justify="center" @mouseover.native="item.operation = true" @mouseleave.native="item.operation = false">
+            <el-col :span="19">
+              <el-radio v-model="fromData.radio" class="creatorList" :label="item.id">{{ item.moduleName }}</el-radio>
+            </el-col>
+            <el-col :span="5" class="creatorList">
+              {{ item.creatorObject.name }}
+              <span class="operation">
+                <i class="el-icon-edit-outline didi-hover" @click="open_new_template(item)" />
+                <el-popover :ref="item.id" placement="bottom" width="300" trigger="click">
+                  <div><div class="blur-column" /> 删除模版</div>
+                  <div class="blueStripe" />
+                  <div class="deletreport">是否要删除模版{{ item.moduleName }}?</div>
+                  <div style="text-align: right; margin: 0">
+                    <el-button size="mini" type="danger" @click="settingDeleteReportModule(item)">确定</el-button>
+                    <el-button size="mini" @click="closeDefaultPopover()">取消</el-button>
+                  </div>
+                  <i slot="reference" class="el-icon-delete reportModel didi-hover" />
+                </el-popover>
+              </span>
+            </el-col>
+          </el-row>
+        </div>
+        <el-row type="flex" justify="center">
+          <el-col :span="24">
+            <span class="didi-hover" @click="open_new_template()"><i class="el-icon-circle-plus-outline creatorList didi-hover" /> <span style="margin-left: 8px">新建模版</span></span>
+          </el-col>
+        </el-row>
+      </div>
+
+      <!-- new模版 -->
+      <newTestingTemplate v-if="reportTamplate" ref="newReportTemplate" class="daily" :template-id="templateId" :type="'new'" @getreportTemplate="getreportTemplate" @reportReturn="reportReturn" />
+      <!-- new模版 -->
+
+      <!-- 新建日报模版 -->
+      <newTestingTemplate v-if="newDailyTemplate" ref="dailyTemplate" class="daily" :template-id="fromData.radio" :task-ids="daily_taskIds" :type="'create'" @SaveNextStep="SaveNextStep" />
+      <!-- 新建日报模版 -->
+
+      <!-- 日报预览 -->
+      <TestingPreview v-if="dailyPreview" ref="dailyPreview" class="daily" :daily-id="dailyId" @handleClose="handleClose" />
+      <!-- 日报预览 -->
+
+    </div>
+    <div slot="footer" class="dialog-footer" align="center">
+      <!-- 新建模版 -->
+      <el-button v-if="reportTamplate" size="small" type="primary" @click="created_out()">保存</el-button>
+      <!-- 第一步 -->
+      <el-button v-if="showOne" size="small" type="primary" @click="NextStep()">下一步</el-button>
+      <!-- 第二步 -->
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="reportReturn">上一步</el-button>
+      <el-button v-if="newDailyTemplate" size="small" type="primary" @click="getCreateData">保存, 下一步</el-button>
+      <!-- 第三步 -->
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReportReturn">上一步</el-button>
+      <el-button v-if="dailyPreview" size="small" type="primary" @click="sendReport">发送</el-button>
+    </div>
+
+  </el-dialog>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { settingQueryReportModuleList, settingDeleteReportModule, reportdelivertestGetReportById } from '@/api/reportTemplate'
+import newTestingTemplate from '@/views/reportManagement/Testing/newTestingTemplate.vue'
+import TestingPreview from '@/views/reportManagement/Testing/TestingPreview.vue'
+
+export default {
+  components: {
+    newTestingTemplate,
+    TestingPreview
+  },
+  data() {
+    return {
+      reportHome: true, // 报告主页
+      reportModel: [
+        { id: 1, moduleName: '客户端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }},
+        { id: 2, moduleName: '服务端模版', creatorObject: { 'idap': '', 'name': '系统', 'deptid': '', 'deptName': '', 'empId': '', 'phoneUrl': null }}
+      ], // 创建的模版
+      templateId: '', // 模版id
+      modelId: '', // 下一步选择的模版id
+      selectTemplate: [], // 模版option
+      fromData: {
+        radio: 1
+      },
+      newDailyTemplate: false, // 新建日报模版
+      reportTamplate: false, // new模版
+      dailyPreview: false, // 日报预览
+      dailyId: '', // 当前创建报告的id
+      updateDaily: false, // 编辑
+      dialogDaliy: false,
+      showOne: true,
+      active: 1,
+      daily_taskIds: [] // 选择的任务ID
+    }
+  },
+  created() {
+    this.getreportTemplate()
+  },
+  methods: {
+    async getreportTemplate() { // 获取模版list
+      const res = await settingQueryReportModuleList({ bizId: localStorage.getItem('bizId'), type: 1 }) // 1 提测
+      if (res.code === 200) {
+        this.$nextTick(() => {
+          const data = res.data
+          this.selectTemplate = data.map(item => ({
+            ...item,
+            operation: false
+          }))
+        })
+      }
+    },
+
+    init(index, newData) {
+      console.log(index, newData, '测试')
+      this.dialogDaliy = true
+      switch (index) {
+        case 2: // 编辑
+          reportdelivertestGetReportById(newData.id).then(res => {
+            if (res.code === 200) {
+              this.daily_taskIds = res.data.taskIds // 关联任务
+              this.fromData.radio = res.data // 选择的模块
+            }
+          })
+          this.reportHome = true // 步骤条
+          this.active = 2 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = true // 隐藏第二步
+          this.dailyPreview = false // 展示第三部
+          this.updateDaily = true // 编辑
+          break
+        case 3: // 发送报告
+          this.dailyId = newData.id
+          this.reportHome = true // 步骤条
+          this.active = 3 // 步骤条状态第三步
+          this.showOne = false // 隐藏第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = true // 展示第三部
+          break
+        case 7: // 新建
+          this.daily_taskIds = newData
+          this.reportHome = true // 步骤条
+          this.active = 1 // 步骤条状态第三步
+          this.showOne = true // 展示第一步
+          this.newDailyTemplate = false // 隐藏第二步
+          this.dailyPreview = false // 隐藏第三部
+          break
+      }
+    },
+
+    report_update() { // 编辑模版
+      this.$refs.DailyReport.getQueryData(1)
+    },
+
+    created_out() { // 新建模版
+      this.$refs.newReportTemplate.getCreateData(1)
+    },
+
+    reportReturn() { // 新建模版点击返回
+      this.fromData.radio = 1
+      this.reportHome = true // 步骤条
+      this.showOne = true // 模版选择
+      this.reportTamplate = false // 编辑区域
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    open_new_template(val) { // 点击新建模版
+      val ? this.templateId = val.id : this.templateId = null
+      this.reportTamplate = true // 编辑区域
+      this.reportHome = false // 步骤条
+      this.showOne = false // 模版选择
+    },
+
+    async settingDeleteReportModule(item) {
+      const res = await settingDeleteReportModule({ id: item.id }, item.id)
+      if (res.code === 200) {
+        this.getreportTemplate()
+        this.closeDefaultPopover()
+        this.$message({ message: '已删除’', type: 'success', duration: 1000, offset: 150 })
+      }
+    },
+
+    closeDefaultPopover() { // 模拟点击
+      this.$refs.refName.click()
+    },
+
+    getCreateData() { // 保存,下一步
+      this.$refs.dailyTemplate.reportreleaseCreate(this.updateDaily)
+    },
+
+    NextStep() { // 第一步到第二步
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第二步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 展示第二步
+      this.dailyPreview = false // 隐藏第三步
+    },
+
+    SaveNextStep(ele) { // 第二步到第三部
+      console.log(ele, 'xsaxasxasxsaxsa')
+      this.dailyId = ele.id // 新建报告id
+      this.reportHome = true // 步骤条
+      this.active = 3 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = false // 隐藏第二步
+      this.dailyPreview = true // 展示第三部
+    },
+
+    async sendReportReturn() { // 第三步返回第二部
+      const res = await reportdelivertestGetReportById(this.dailyId)
+      if (res.code === 200) {
+        this.daily_taskIds = res.data.taskIds // 关联任务
+        this.fromData.radio = res.data // 选择的模块
+      }
+      this.reportHome = true // 步骤条
+      this.active = 2 // 步骤条状态第三步
+      this.showOne = false // 隐藏第一步
+      this.newDailyTemplate = true // 隐藏第二步
+      this.dailyPreview = false // 展示第三部
+      this.updateDaily = true // 编辑
+    },
+
+    sendReport() { // 截图
+      this.$refs.dailyPreview.sendReport()
+    },
+
+    handleClose() {
+      this.dialogDaliy = false
+      this.$emit('getList')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-leftRight {
+  margin: 0 13%;
+  >>> .el-row .el-col {
+    margin: 0;
+}
+}
+
+.titIcon {
+    width: 4px;
+    height: 17px;
+    background: #409EFF;
+    border-radius: 1px;
+}
+
+.el-dialog__header {
+    padding: 0 !important;
+}
+
+.reportModel {
+    margin-left: 10px;
+}
+
+.operation {
+    margin-left: 30px;
+}
+
+.creator {
+  display: inline-block;
+  font-size:16px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.creatorList {
+  display: inline-block;
+  font-size:14px;
+  font-family:Microsoft Sans Serif;
+  font-weight:400;
+  line-height: 2.8;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.deletreport {
+  font-size:14px;
+  text-align: center;
+  margin: 30px 0;
+  font-family:MicrosoftYaHei;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.report-dialog {
+  >>>.el-dialog__header {
+    padding: 20px 20px 10px;
+    border-bottom: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+  >>>.el-dialog__footer {
+    padding: 15px 20px;
+    text-align: right;
+    border-top: 1px solid rgba(238,238,238,1);
+    opacity:1;
+  }
+}
+.report-return {
+  font-size: 18px;
+  position: absolute;
+  top: 23px;
+  left: 11px;
+}
+.report-steps {
+  margin-bottom: 20px;
+  font-size:16px;
+  font-family:PingFang SC;
+  font-weight:500;
+  line-height:22px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+.daily {
+   max-height: 460px;
+   overflow:scroll;
+   overflow-x: hidden
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+</style>

+ 245 - 0
src/views/reportManagement/daily/components/DailyDetails.vue

@@ -0,0 +1,245 @@
+<template>
+  <el-container class="BackgroundCloth">
+    <el-header class="public_header setLine">
+      <div class="Layout_space_between">
+        <div class="Layout_flex_start">
+          <div>
+            <span class="details-id">{{ 'report-' + details.id }}</span><br>
+            <span class="report-title">{{ details.reportName }}</span>
+          </div>
+          <div class="details-statusString">{{ details.statusString }}</div>
+        </div>
+        <div>
+          <span v-if="details.status === 0 ? true : false" class="didi-hover" @click="dailyButtom(5,details)">发送</span>
+          <span v-if="details.status === 0 ? true : false" style="margin: 0 30px;" class="didi-hover" @click="dailyButtom(6,details)">编辑</span>
+          <span v-if="details.status === 0 ? true : false" class="didi-hover" @click="dialog_testData = true">删除</span>
+          <span v-if="details.status === 3 ? true : false" class="didi-hover" @click="dailyButtom(3,details)">复制</span>
+        </div>
+      </div>
+    </el-header>
+    <el-container>
+      <el-main class="report-main">
+        <div class="title"><div class="blur-column" /> 报告内容</div>
+        <div v-html="details.content" />
+        <icon-display :id="[$route.query.id]" />
+      </el-main>
+      <el-aside width="400px">
+        <el-container>
+          <el-header class="report-mains">
+            <div class="title"><div class="blur-column" /> 用户信息</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">报告人 : </div>
+              <div class="task-name">{{ details.reportorObject ? details.reportorObject.name : '' }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">收件人 : </div>
+              <div v-for="(item, index) in details.sendToObject" :key="index" class="task-name"> {{ item.name }} <span v-if="index < details.sendToObject.length - 1"> , </span></div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">抄送人 : </div>
+              <div v-for="(item, index) in details.sendCcObject" :key="index" class="task-name">{{ item.name }} <span v-if="index < details.sendCcObject.length - 1"> , </span></div>
+            </div>
+          </el-header>
+          <el-main class="report-mains">
+            <div class="title"><div class="blur-column" /> 时间</div>
+            <div class="Layout_flex_start">
+              <div class="title-name">创建时间 : </div>
+              <div class="task-name">{{ details.gmtCreate }}</div>
+            </div>
+            <div class="Layout_flex_start">
+              <div class="title-name">发送时间 : </div>
+              <div class="task-name">{{ details.gmtModify }}</div>
+            </div>
+          </el-main>
+          <el-footer class="report-mains">
+            <div class="title"><div class="blur-column" /> 关联任务</div>
+            <div v-for="(item, index) in details.taskDetailList" :key="index" class="Layout_flex_start task-bot">
+              <div class="task-id">{{ item.taskId }}</div>
+              <div class="task-name">{{ item.name }}</div>
+            </div>
+          </el-footer>
+        </el-container>
+      </el-aside>
+    </el-container>
+    <el-dialog title="删除确认" :visible.sync="dialog_testData" width="30%" :close-on-click-modal="false">
+      <div style="position: absolute; top: 23px; left: 12px;width:4px;height:17px;background:#409EFF;border-radius:1px;" />
+      <div align="center">
+        <div>是否删除以下测试日报?</div>
+        <div style="color: #f79232;">{{ details.reportName }}</div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" size="mini" @click="deleteDaily()">确 定</el-button>
+        <el-button type="danger" size="mini" @click="dialog_testData = false">取 消</el-button>
+      </span>
+    </el-dialog>
+    <DailyReport v-if="dialogDaily" ref="DailyReport" @getList="getReportContent(reportId)" />
+  </el-container>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { dailyReportGetV2, dailyReportDelete } from '@/api/reportTemplate'
+import iconDisplay from '@/views/reportManagement/daily/components/iconDisplay.vue'
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+export default {
+  components: {
+    DailyReport,
+    iconDisplay
+  },
+  data() {
+    return {
+      userInformation: localStorage.getItem('username'),
+      userNames: localStorage.getItem('realname'),
+      userData: { id: '', ename: this.userInformation, name: this.userNames },
+      dialogDaily: false, // 日报弹窗
+      dialog_testData: false, // 操作弹窗
+      reportId: this.$route.query.id,
+      details: {}
+    }
+  },
+  created() {
+    this.getReportContent(this.reportId)
+  },
+  methods: {
+    async getReportContent(e) { // 获取日报data
+      const res = await dailyReportGetV2(e)
+      if (res.code === 200) {
+        this.details = res.data
+      }
+    },
+    dailyButtom(e, data) { // 测试报告
+      switch (e) {
+        case 3: // 复制 第二步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(4, data)
+          })
+          break
+        case 5: // 日报第三步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(3, data)
+          })
+          break
+        case 6: // 日报第二步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(2, data)
+          })
+          break
+      }
+    },
+    async deleteDaily() { // 删除日报‘
+      const res = await dailyReportDelete(this.userData, this.details.id)
+      if (res.code === 200) {
+        this.dialog_testData = false
+        this.$router.push({ name: '报告' })
+        this.$message({ type: 'success', message: '删除成功' })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.BackgroundCloth {
+.report-Header {
+  margin: 10px 10px 0;
+  background: #FFF;
+  border-radius:4px;
+}
+
+.details-id {
+  font-size:12px;
+  font-family:PingFang SC;
+  font-weight:400;
+  line-height:20px;
+  color:rgba(51,59,74,1);
+  opacity:0.5;
+}
+
+.report-title {
+  font-size:20px;
+  font-family:PingFangSC-Medium;
+  line-height:28px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.details-statusString {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  padding: 5px 8px;
+  margin-left: 15px;
+  color:rgba(111,124,147,1);
+  border:1px solid rgba(191,198,220,1);
+  opacity:1;
+  border-radius:4px;
+}
+
+.report-main {
+  margin: 10px;
+  background: #FFF;
+  border-radius:4px;
+}
+.report-mains {
+  min-height: 200px;
+  padding: 20px ;
+  margin: 10px 10px 0 0;
+  background: #FFF;
+  border-radius:4px;
+}
+.title {
+  font-size:16px;
+  font-family:PingFangSC-Medium;
+  line-height:35px;
+  margin-bottom: 10px;
+  color:rgba(51,59,74,1);
+  opacity:1;
+}
+
+.title-name {
+  width:100px;
+  font-size:14px;
+  margin-bottom: 10px;
+  font-family:PingFangSC-Regular;
+  line-height:20px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-id {
+  width:100px;
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(102,102,102,1);
+  opacity:1;
+}
+
+.task-name {
+  font-size:14px;
+  font-family:MicrosoftYaHei;
+  line-height:17px;
+  color:rgba(51,51,51,1);
+  opacity:1;
+}
+
+.blur-column {
+  width:4px;
+  height:15px;
+  display:inline-block;
+  vertical-align: middle;
+  background:#409EFF;
+  border-radius:1px;
+}
+
+.task-bot {
+   margin-bottom: 10px;
+}
+}
+.setLine {
+  padding: 10px 20px;
+}
+</style>

+ 150 - 0
src/views/reportManagement/daily/components/iconDisplay.vue

@@ -0,0 +1,150 @@
+<template>
+  <div>
+    <div class="backStyle">缺陷统计</div>
+    <el-table :data="tableList" border size="mini" style="width: 100%">
+      <el-table-column prop="缺陷总数" label="缺陷总数" align="center" min-width="100" />
+      <el-table-column prop="待修复" label="待修复" align="center" min-width="100" />
+      <el-table-column prop="待测试" label="待测试" align="center" min-width="100" />
+      <el-table-column prop="已完成" label="已完成" align="center" min-width="100" />
+      <el-table-column prop="Reopen" label="Reopen" align="center" min-width="100" />
+      <el-table-column prop="Hold" label="Hold" align="center" min-width="100" />
+    </el-table>
+    <div class="backStyle">今日新增缺陷(-个)</div>
+    <div class="Layout_space_between">
+      <div id="lineShow" class="backTop" />
+      <div id="barShow" class="backTop" />
+    </div>
+    <div class="backStyle">P0&P1缺陷列表(-个)</div>
+    <el-table :data="report_bugList" border size="mini" style="width: 100%" show-overflow-tooltip="true">
+      <el-table-column prop="bugId" label="缺陷ID" align="center" min-width="80" show-overflow-tooltip />
+      <el-table-column prop="bugName" label="缺陷标题" align="center" min-width="100" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span class="didi-hover" @click.stop="click_bugName(scope.row.id)">{{ scope.row.bugName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="bugStatusName" label="状态" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="priorityName" label="缺陷等级" align="center" min-width="100" show-overflow-tooltip />
+      <el-table-column prop="creatorList" label="提报人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="assignerList" label="责任人" align="center" min-width="90" show-overflow-tooltip />
+      <el-table-column prop="currentHandlerList" label="修复人" align="center" min-width="90" show-overflow-tooltip />
+    </el-table>
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import echarts from 'echarts'
+import '@/styles/PublicStyle/index.scss'
+import { bugGetReportSumData, bugGetReportHighPriData, bugGetReportDisDataByMember, bugGetReportDisDataByPri } from '@/api/reportTemplate' // 模版添删改查
+export default {
+  props: {
+    id: { type: Array, default: null }
+  },
+  data() {
+    return {
+      tableList: [], // 缺陷统计
+      report_bugList: [], // P0&P1缺陷列表
+      taskid_arr: []
+    }
+  },
+  watch: {
+    id: {
+      handler(newV) {
+        if (newV !== null) {
+          this.$forceUpdate()
+          this.taskid_arr = JSON.parse(JSON.stringify(newV))
+          this.taskid_arr.map(item => {
+            this.bugGetReportSumData(item)
+          })
+        }
+      },
+      immediate: true
+    }
+  },
+  //  mounted() {
+  // const myChart = echarts.init(document.getElementById('lineShow'))
+  // const myChartA = echarts.init(document.getElementById('barShow'))
+  // window.addEventListener('resize', () => {
+  //   if (myChart) {
+  //     myChart.resize()
+  //     myChartA.resize()
+  //   }
+  // })
+  // },
+  methods: {
+    click_bugName(id) { // 缺陷跳转
+      this.$router.push({ name: '缺陷详情', params: { id: id }})
+    },
+    async bugGetReportSumData() {
+      const date = moment().locale('zh-cn').format('YYYY-MM-DD')
+      const data = {
+        createStartTime: `${date} 00:00:00`, // 当天的开始时间
+        createEndTime: `${date} 23:59:59`, // 当天的结束时间
+        taskIds: this.taskid_arr // 任务id list
+      }
+      const res = await bugGetReportSumData(data) // 获取缺陷统计
+      if (res.code === 200) {
+        this.tableList = []
+        this.tableList.push(res.data)
+      }
+      const res1 = await bugGetReportHighPriData(data) // 获取P0&P1缺陷列表
+      if (res1.code === 200) {
+        this.report_bugList = res1.data
+      }
+      const res2 = await bugGetReportDisDataByMember(data) // 获取缺陷责任人分布
+      if (res2.code === 200) {
+        const data = res2.data.yaxis.map(item => ({
+          ...item,
+          type: 'bar',
+          barWidth: '20px'
+        }))
+        setTimeout(() => {
+          echarts.init(document.getElementById('lineShow')).setOption({
+            backgroundColor: '#FFF',
+            color: ['#409EFF'],
+            title: { text: '缺陷责任人分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+            tooltip: { axisPointer: { type: 'shadow' }},
+            grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+            xAxis: [{ type: 'category', data: res2.data.xaxis.length <= 0 ? ['P0', 'P1', 'P2', 'P3'] : res2.data.xaxis, axisTick: { alignWithLabel: true }}],
+            yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+            series: res2.data.yaxis[0].data <= 0 ? [{ name: '无数据', type: 'bar', barWidth: '20px', data: [0, 0, 0, 0] }] : data
+          })
+        }, 200)
+      }
+      const res3 = await bugGetReportDisDataByPri(data) // 获取缺陷等级分布
+      if (res3.code === 200) {
+        const data = res3.data.yaxis.map(item => ({
+          ...item,
+          type: 'bar',
+          barWidth: '20px'
+        }))
+        setTimeout(() => {
+          echarts.init(document.getElementById('barShow')).setOption({
+            backgroundColor: '#FFF',
+            color: ['#409EFF'],
+            title: { text: '缺陷等级分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+            tooltip: { axisPointer: { type: 'shadow' }},
+            grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+            xAxis: [{ type: 'category', data: res3.data.xaxis, axisTick: { alignWithLabel: true }}],
+            yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+            series: res3.data.yaxis[0].data <= 0 ? [{ name: '无数据', type: 'bar', barWidth: '20px', data: [0, 0, 0, 0] }] : data
+          })
+        }, 200)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+  .backTop {
+    width: 350px;
+    height:350px;
+  }
+</style>

+ 155 - 0
src/views/reportManagement/daily/components/testPresenyL.vue

@@ -0,0 +1,155 @@
+<template>
+  <!-- 老日报预览 -->
+  <div>
+    <el-form :model="fromCreat" class="from-creat reportContent">
+      <div style="display: flex; white-space: nowrap; font-family:SimSuncss">
+        <span style="flex:1;font-weight: bold;font-size: 20px;color: #3a8ee6">{{ fromCreat.reportName }}</span>
+        <span style="flex:2;margin: 0.5% 0 0 20px;font-size: 17px;">by {{ fromCreat.ownner }}</span>
+      </div>
+      <div style="font-size:15px;color:#606266;line-height: 25px;" class="rich" v-html="projectProgress" />
+      <div class="titleStyle" style="margin-top: 10px;">三. bug情况</div>
+      <div style="border: 1px,solid #ccc;font-size:14px;color:#606266;padding-bottom: 20px;">
+        <div style="margin: 1%;">1、bug统计</div>
+        <div :class="{'space-between' : xaxisTotal < 8} ">
+          <div id="lineShow" :class="{'backTop' : xaxisTotal < 8,'backLeft' : xaxisTotal > 7}" />
+          <div id="barShow" :class="{'backTop' : xaxisTotal < 8, 'backLeft' : xaxisTotal > 7}" />
+        </div>
+        <div style="margin: 1%;">2、bug说明:</div>
+        <div class="pre-line">{{ bugshow }}</div>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import echarts from 'echarts'
+import { bugDailyList } from '@/api/testPresentetion'
+
+export default {
+  name: 'TestPresenyL',
+  props: {
+    message: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      userInformation: localStorage.getItem('username'),
+      userNames: localStorage.getItem('realname'),
+      bugshow: '',
+      postData: {},
+      fromCreat: {},
+      TestProgress: '',
+      projectProgress: '',
+      dateList: [],
+      numList: [],
+      bugName: [],
+      statusMap: [],
+      statusList: [],
+      pro: '',
+      xaxisTotal: 0,
+      name: ''
+    }
+  },
+  mounted() {
+    this.idGet()
+    const myChart = echarts.init(document.getElementById('lineShow'))
+    const myChartA = echarts.init(document.getElementById('barShow'))
+    window.addEventListener('resize', () => {
+      if (myChart) {
+        myChart.resize()
+        myChartA.resize()
+      }
+    })
+  },
+  methods: {
+    idGet() {
+      this.fromCreat = this.message
+      this.name = this.fromCreat.reportName
+      this.gntCreateEnd = this.fromCreat.gmtCreate
+      this.bugshow = this.fromCreat.bugExplain
+      this.projectProgress = this.fromCreat.testExplain
+      this.pro = { taskIds: this.fromCreat.taskIds, gntCreateEnd: this.gntCreateEnd }
+      bugDailyList(this.pro).then(res => {
+        this.dateList = res.data.dateList
+        this.statusMap = res.data.statusMap
+        this.statusList = res.data.statusList
+        this.numList = res.data.bugMap
+        for (var ele of this.numList) {
+          this.bugName.push(ele.name)
+        }
+        if (this.dateList.length >= 7 || this.statusList.length >= 7) {
+          this.xaxisTotal = 8
+        } else {
+          this.xaxisTotal = 1
+        }
+        this.$nextTick(() => {
+          echarts.init(document.getElementById('lineShow')).setOption({
+            title: { left: 'center', text: 'bug数量汇总' },
+            tooltip: { trigger: 'axis' },
+            legend: { top: 30, data: this.bugName },
+            grid: { left: '5%', right: '5%', bottom: '12%', containLabel: true },
+            xAxis: { type: 'category', boundaryGap: true, data: this.dateList, axisLabel: { interval: 0, rotate: 30 }},
+            yAxis: { type: 'value' },
+            series: this.numList
+          })
+          echarts.init(document.getElementById('lineShow')).resize()
+          echarts.init(document.getElementById('barShow')).setOption({
+            title: { text: 'bug状态汇总', x: 'center' },
+            color: ['#003366', '#006699', '#4cabce', '#e5323e'],
+            tooltip: { trigger: 'axis' },
+            legend: { top: 30, data: this.statusMap },
+            grid: { left: '5%', right: '5%', bottom: '12%', containLabel: true },
+            xAxis: [{ data: this.statusList, axisLabel: { interval: 0, rotate: 30 }}],
+            yAxis: [{}],
+            series: this.statusMap
+          })
+          echarts.init(document.getElementById('barShow')).resize()
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .from-creat {
+    margin: 3% auto;
+    padding: 0 2%;
+    width: 100%;
+  }
+  .titleStyle {
+    color: #333B4A;
+    margin: 1% 0 1% 0;
+    font-size: 17px;
+    font-weight: bold;
+  }
+
+  .space-between {
+    display:flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+
+  .backTop {
+    flex:1.5;
+    width: 400px;
+    height:400px;
+  }
+
+  .backLeft {
+    width: 100%;
+    height:400px;
+  }
+  #app .hideSidebar .sidebar-container {
+    display: none;
+  }
+  .pre-line {
+    white-space: pre-line;
+    padding-left: 10px;
+  }
+    .rich>>> table tr td{border:1px solid #ccc;font-size: 15px; color: #606266}
+  .rich>>> table th{border:1px solid #ccc; font-size: 15px; background: #F0F7FF; color: #606266}
+  .rich>>> table {border:1px solid #ccc; border-collapse: collapse;line-height: 30px; text-align: center;font-size: 15px; color: #606266}
+</style>

+ 125 - 0
src/views/reportManagement/daily/dailyPreview.vue

@@ -0,0 +1,125 @@
+<template>
+  <!-- 预览测试日报 -->
+  <div class="parent-style">
+    <div class="backStyle"> 邮件列表</div>
+    <div class="Layout_space_between" style="margin-bottom: 10px;">
+      <div class="div1">收件人</div>
+      <searchTeam :value.sync="form.name" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div class="Layout_space_between">
+      <div class="div1">抄送</div>
+      <searchTeam :value.sync="form.names" :clearable="true" :multiple="true" style="width:100%" />
+    </div>
+    <div class="backStyle"> 报告预览</div>
+    <div id="repot-list">
+      <span class="backStyle"> 任务名称</span>
+      <div v-for="(item, index) in fromCreateData.taskDetailList" :key="index" class="Layout_flex_start report-taskList">
+        <span>{{ item.taskId }}</span>
+        <span>{{ item.name }}</span>
+      </div>
+      <div class="Layout_space_between">
+        <span class="backStyle"> 标题 : {{ fromCreateData.reportName }}</span>
+        <span>报告人:{{ fromCreateData.reportor }}</span>
+      </div>
+      <span class="backStyle"> 模版内容</span>
+      <div v-html="fromCreateData.content" />
+      <icon-display :id="fromCreateData.taskIds" />
+    </div>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import html2canvas from 'html2canvas'
+import { dailyReportSendmail } from '@/api/ResultPage'
+import searchTeam from '@/components/select/searchTeam'
+import iconDisplay from '@/views/reportManagement/daily/components/iconDisplay.vue'
+import { dailyReportGetV2 } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  name: 'DailyNewsAdded',
+  components: {
+    searchTeam,
+    iconDisplay
+  },
+  props: {
+    dailyId: { type: [String, Number], default: null }
+  },
+  data() {
+    return {
+      form: {}, // 发送报告content
+      fromCreateData: {}, // listAll
+      tasksOptions: [], // 任务下拉选项
+      tasksDetailList: [], // 已有任务项目
+      taskid_arr: [], // taskIds
+      moduleId: '', // 模块id
+      daily_Id: '' // daily_Id
+    }
+  },
+  watch: {
+    dailyId: {
+      handler(newV) {
+        this.daily_Id = newV
+        this.dailyReportGetV2(newV)
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async dailyReportGetV2(val) { // 获取日报数据
+      const res = await dailyReportGetV2(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+
+    sendReport() {
+      if (this.form.name !== undefined) {
+        // const targetDom = document.getElementById('repot-list')
+        // const copyDom = targetDom.cloneNode(true)
+        // document.querySelector('body').appendChild(copyDom)
+        setTimeout(() => {
+          html2canvas(document.getElementById('repot-list'), { useCORS: true }).then(canvas => {
+            const imgData = canvas.toDataURL('image/png', 1)
+            const sendImgData = imgData.toString().substring(imgData.indexOf(',') + 1)
+            const postData = { 'reportId': this.daily_Id, 'imgStr': sendImgData, 'url': window.location.href, 'emailUser': this.form.name ? this.form.name.join(',') : null, 'copyTo': this.form.names ? this.form.names.join(',') : null }
+            dailyReportSendmail(postData).then(res => {
+              res.code === 200 ? this.$message.success('报告发送中,请稍后进行邮件查收!') : this.$message.error('发送测试日报失败,请联系管理员!')
+              // document.querySelector('body').removeChild(copyDom)
+              this.$emit('handleClose')
+            })
+          })
+        }, 500)
+      } else {
+        this.$message({ message: '请填写邮箱', type: 'error', offset: 150 })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.parent-style {
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+.div1 {
+    width: 60px;
+    font-size: 14px;
+    font-family: MicrosoftYaHei;
+    color: rgba(51, 51, 51, 1);
+    line-height: 19px;
+}
+  .backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+</style>

+ 220 - 0
src/views/reportManagement/daily/dailyTemplate.vue

@@ -0,0 +1,220 @@
+<template>
+  <!-- 新增测试日报 -->
+  <div class="parent-style">
+    <el-form ref="fromCreateData" class="dailyFrom" :model="fromCreateData" :rules="serviceDataRules">
+      <div class="report-Padding">
+        <span style="color: #f56b6c">*</span>
+        <span class="backStyle"> 任务名称</span>
+      </div>
+
+      <el-select
+        v-model="fromCreateData.taskIds"
+        filterable
+        remote
+        reserve-keyword
+        placeholder="请输入任务名称或ID"
+        :remote-method="remoteMethod"
+        style="width: 100%"
+        size="small"
+        @change="colseSelect"
+      >
+        <el-option v-for="item in tasksOptions" :key="item.id" :label="item.name" :value="item.id" :disabled="item.isScheduleLocked === 1" @click.native="tasksChange(item)">
+          <div class="Layout_space_between"><span>{{ item.name }}</span></div>
+        </el-option>
+      </el-select>
+      <div v-if="selectTask" class="taskError">任务名称不能为空</div>
+      <div v-for="(item, index) in tasksDetailList" :key="index" class="Layout_space_between report-taskList">
+        <span>{{ item.taskIdSting }}</span>
+        <span>{{ item.name }}</span>
+        <i class="el-icon-circle-close didi-hover" @click="delete_task(item)" />
+      </div>
+      <el-form-item label="标题" prop="reportName"><br>
+        <el-input v-model="fromCreateData.reportName" size="small" style="width: 100%;" placeholder="请输入报告名称" />
+      </el-form-item>
+      <el-form-item label="模版内容" prop="content"><br>
+        <normal-area id="report-template" :value.sync="fromCreateData.content" :height="500" />
+      </el-form-item>
+    </el-form>
+    <icon-display :id="taskid_arr" />
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import normalArea from '@/components/input/normalArea'
+import { taskList as allTaskList } from '@/api/taskIndex'
+import iconDisplay from '@/views/reportManagement/daily/components/iconDisplay.vue'
+import { settingGetReportModuleById, dailyReportCreate, dailyReportUpdate } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  name: 'DailyNewsAdded',
+  components: {
+    normalArea,
+    iconDisplay
+  },
+  props: {
+    modelId: { type: [String, Number, Object], default: 1 },
+    taskIds: { type: Array, default: () => null }
+  },
+  data() {
+    return {
+      serviceDataRules: {
+        reportName: [{ required: true, message: '标题不能为空', trigger: 'change' }],
+        content: [{ required: true, message: '模版内容不能为空', trigger: 'change' }]
+      },
+      fromCreateData: {}, // listAll
+      tasksOptions: [], // 任务下拉选项
+      tasksDetailList: [], // 已有任务项目
+      taskid_arr: [], // taskIds
+      moduleId: '', // 模块id
+      selectTask: false // 选择的任务id
+    }
+  },
+  watch: {
+    modelId: {
+      handler(newV) {
+        console.log(newV, 'cdcdcdc')
+        if (newV.id) {
+          if (newV.updateDaily === false) {
+            newV.reportName = ''
+          }
+          this.fromCreateData = newV
+          this.$set(this.fromCreateData, 'taskIds', null)
+          this.moduleId = newV.moduleId
+          newV.updateDaily === false ? this.$refs.fromCreateData.resetFields() : ''
+        } else {
+          this.moduleId = newV
+          this.fromCreateData = {}
+          if (newV === 1 || newV === 2) {
+            this.fromCreateData.content = `<div style="color: #606266"><h3>进度和风险</h3><p>项目整体进度</p><p>项目风险与问题</p><table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>风险等级</th><th>风险项</th><th>当前状态</th><th>跟进人</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table><h3>测试情况</h3><p>测试进展</p><table border="1" style="border: 1px solid #DEE2E7" width="100%"><colgroup><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"><col width="8%"></colgroup><thead><tr><th>标题1</th><th>标题2</th><th>标题3</th><th>标题4</th><th>标题5</th><th>标题6</th><th>标题7</th></tr></thead><tbody><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr><tr><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td><td><br></td></tr></tbody></table><p>测试说明</p></div>`
+          } else {
+            this.settingGetReportModuleById(newV)
+          }
+        }
+      },
+      immediate: true
+    },
+    taskIds: {
+      handler(newV) {
+        if (newV[0]) {
+          this.taskid_arr = newV
+          this.tasksDetailList = []
+          newV.map(item => {
+            this.remoteMethods(item)
+          })
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    async settingGetReportModuleById(val) { // 获取表单数据
+      const res = await settingGetReportModuleById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+    async remoteMethods(query) { // 远程搜索任务
+      const res = await allTaskList({ bizId: Number(localStorage.getItem('bizId')), name: query })
+      if (res.code === 200) {
+        this.tasksOptions = res.data
+        this.tasksDetailList.push(res.data[0])
+        this.$set(this.fromCreateData, 'taskIds', null)
+      }
+    },
+    async remoteMethod(query) { // 远程搜索任务
+      const res = await allTaskList({ bizId: Number(localStorage.getItem('bizId')), name: query })
+      if (res.code === 200) {
+        this.tasksOptions = res.data
+      }
+    },
+    tasksChange(data) { // 任务列表变动
+      this.tasksDetailList.length <= 0 ? this.selectTask = true : this.selectTask = false
+      const isEx = this.tasksDetailList.find(item => item.id === data.id)
+      if (isEx) {
+        this.$message({ message: '任务已存在', type: 'warning', duration: 1000, offset: 150 })
+        return false
+      }
+      this.tasksDetailList.push(data)
+      this.taskid_arr.push(data.id)
+    },
+
+    colseSelect() { // 清空任务名称
+      this.$set(this.fromCreateData, 'taskIds', null)
+    },
+
+    delete_task(val) { // 删除关联的任务
+      this.tasksDetailList = this.tasksDetailList.filter(item => {
+        return item.id !== val.id
+      })
+      this.taskid_arr = this.taskid_arr.filter(item => {
+        return item.id !== val.id
+      })
+      this.tasksDetailList.length <= 0 ? this.selectTask = true : this.selectTask = false
+    },
+
+    // 新建模版
+    getCreateData(val) {
+      this.$refs.fromCreateData.validate((valid) => {
+        if (valid) {
+          this.fromCreateData.bizId = localStorage.getItem('bizId')
+          this.fromCreateData.reportor = localStorage.getItem('usernames')
+          this.fromCreateData.taskIds = this.taskid_arr
+          this.fromCreateData.moduleId = this.moduleId
+          if (val) { // 编辑
+            dailyReportUpdate(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$emit('SaveNextStep', res.data)
+                this.$message({ type: 'success', message: '更新成功' })
+              }
+            })
+          } else {
+            dailyReportCreate(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$emit('SaveNextStep', res.data)
+                this.$message({ type: 'success', message: '创建成功' })
+              }
+            })
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.dailyFrom {
+  >>> .el-form-item {
+    margin-bottom: 0px;
+}
+}
+.parent-style {
+  .report-taskList{
+    font-size:14px;
+    font-family:MicrosoftYaHei;
+    line-height:17px;
+    color:rgba(102,102,102,1);
+    margin-top: 10px;
+    opacity:1;
+  }
+}
+
+  .report-Padding {
+    margin-bottom: 12px;
+  }
+
+  .backStyle {
+    font-size: 14px;
+    font-weight: bold;
+    border-radius: 4px;
+    margin: 10px 0;
+  }
+
+  .taskError {
+    color: #F56C6C;
+    font-size: 12px;
+    line-height: 1;
+    padding-top: 4px;
+  }
+</style>

+ 171 - 0
src/views/reportManagement/daily/newReportTemplate.vue

@@ -0,0 +1,171 @@
+<template>
+  <!-- 新建报告模版 -->
+  <div>
+    <el-form ref="fromCreateData" :model="fromCreateData" :rules="serviceDataRules">
+      <el-form-item label="模版名称" prop="moduleName" label-width="80px">
+        <el-input v-model="fromCreateData.moduleName" size="small" style="width:100%;" placeholder="请输入模版名称(不可与现有模版重名)" />
+      </el-form-item>
+      <el-form-item label="模版内容" prop="content"><br>
+        <normal-area id="report-template" :value.sync="fromCreateData.content" :height="500" />
+      </el-form-item>
+    </el-form>
+    <div class="backStyle">缺陷统计</div>
+    <el-table
+      :data="tableData"
+      border
+      size="mini"
+      style="width: 100%"
+      :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+    >
+      <el-table-column prop="date" label="缺陷总数" align="center" min-width="100" />
+      <el-table-column prop="date" label="待修复" align="center" min-width="100" />
+      <el-table-column prop="date" label="待测试" align="center" min-width="100" />
+      <el-table-column prop="date" label="已完成" align="center" min-width="100" />
+      <el-table-column prop="date" label="Reopen" align="center" min-width="100" />
+      <el-table-column prop="date" label="Hold" align="center" min-width="100" />
+    </el-table>
+    <div class="backStyle">今日新增缺陷(-个)</div>
+    <div class="Layout_space_between">
+      <div id="lineShow" class="backTop" />
+      <div id="barShow" class="backTop" />
+    </div>
+    <div class="backStyle">P0&P1缺陷列表(-个)</div>
+    <el-table
+      :data="tableData"
+      border
+      size="mini"
+      :header-cell-style="{ backgroundColor: 'rgba(241,241,241,1)', color: 'rgba(51,59,74,1)', fontSize: '14px', fontWeight: '400'}"
+      style="width: 100%"
+    >
+      <el-table-column prop="date" label="缺陷ID" align="center" min-width="100" />
+      <el-table-column prop="date" label="缺陷标题" align="center" min-width="100" />
+      <el-table-column prop="date" label="状态" align="center" min-width="100" />
+      <el-table-column prop="date" label="缺陷等级" align="center" min-width="100" />
+      <el-table-column prop="date" label="提报人" align="center" min-width="100" />
+      <el-table-column prop="date" label="责任人" align="center" min-width="100" />
+      <el-table-column prop="date" label="修复人" align="center" min-width="100" />
+    </el-table>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss' // 公共css
+import echarts from 'echarts'
+import normalArea from '@/components/input/normalArea' // 富文本
+import { settingAddReportModule, settingUpdateReportModule, settingGetReportModuleById } from '@/api/reportTemplate' // 模版添删改查
+
+export default {
+  components: {
+    normalArea
+  },
+  props: {
+    templateId: { type: [String, Number], default: null } // 模版id
+  },
+  data() {
+    return {
+      tableData: [{ date: 0 }],
+      tpltId: '', // 模版id
+      bugP0P1: [], // bugP0P1数据
+      serviceDataRules: {
+        moduleName: [{ required: true, message: '模版名称不能为空', trigger: 'change' }],
+        content: [{ required: true, message: '模版内容不能为空', trigger: 'change' }]
+      },
+      fromCreateData: {},
+      TLstatus: false // 模版状态
+    }
+  },
+  watch: {
+    templateId: {
+      handler(newV) {
+        this.tpltId = newV
+        this.tpltId ? this.settingGetReportModuleById(newV) : ''
+      },
+      immediate: true
+    }
+  },
+  created() {
+    this.getRouterData()
+  },
+  methods: {
+    async settingGetReportModuleById(val) {
+      const res = await settingGetReportModuleById(val)
+      if (res.code === 200) {
+        this.fromCreateData = res.data
+      }
+    },
+    getRouterData() {
+      setTimeout(() => {
+        echarts.init(document.getElementById('lineShow')).setOption({
+          backgroundColor: '#FFF',
+          color: ['#FF333333'],
+          title: { text: '缺陷责任人分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+          tooltip: { axisPointer: { type: 'shadow' }},
+          grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+          xAxis: [{ type: 'category', data: ['P0', 'P1', 'P2', 'P3'], axisTick: { alignWithLabel: true }}],
+          yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+          series: [{ name: '直接访问', type: 'bar', barWidth: '20%', data: [0, 0, 0, 0] }]
+
+        })
+        echarts.init(document.getElementById('barShow')).setOption({
+          backgroundColor: '#FFF',
+          color: ['#FF4A5164'],
+          title: { text: '缺陷等级分布', x: 'center', textStyle: { fontSize: 14, fontStyle: 'normal', fontWeight: 'normal' }},
+          tooltip: { axisPointer: { type: 'shadow' }},
+          grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+          xAxis: [{ type: 'category', data: ['P0', 'P1', 'P2', 'P3'], axisTick: { alignWithLabel: true }}],
+          yAxis: [{ type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed' }}}],
+          series: [{ name: '直接访问', type: 'bar', barWidth: '20%', data: [0, 0, 0, 0] }]
+        })
+      }, 200)
+    },
+
+    // 新建模版
+    getCreateData(e) {
+      this.$refs['fromCreateData'].validate((valid) => {
+        if (valid) {
+          this.fromCreateData.bizId = localStorage.getItem('bizId')
+          this.fromCreateData.type = e
+          if (this.tpltId) {
+            settingUpdateReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '更新成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          } else {
+            settingAddReportModule(this.fromCreateData).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '创建成功' })
+                this.$emit('getreportTemplate')
+                this.$emit('reportReturn')
+              }
+            })
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .backStyle {
+    font-size:16px;
+    font-family:MicrosoftYaHei;
+    line-height:19px;
+    color:rgba(51,51,51,1);
+    margin: 1% 0;
+  }
+
+  .space-between {
+    display:flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+
+  .backTop {
+    width: 400px;
+    height:400px;
+  }
+</style>

+ 543 - 0
src/views/reportManagement/testPresentation.vue

@@ -0,0 +1,543 @@
+<template>
+  <div class="eleStyle">
+    <el-container class="header_sty">
+      <el-header class="public_header">
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="测试日报" name="first" />
+          <el-tab-pane label="准出报告" name="second" />
+          <el-tab-pane label="提测报告" name="third" />
+        </el-tabs>
+      </el-header>
+
+      <el-main class="public_main report-Layout">
+        <div class="Layout_space_between distance">
+          <div class="Layout_space_between">
+            <span style="width: 100px;">{{ title }}</span>
+            <el-input v-if="history" v-model="state" size="medium" filterable placeholder="报告名称搜索" style="width:100%;" @change="getList(state)" />
+            <el-input v-if="!history" v-model="state" size="medium" filterable placeholder="报告名称搜索" style="width:100%;" @change="gethistoryData(state)" />
+          </div>
+          <div class="Layout_space_between">
+            <el-button v-if="!history" type="primary" size="medium" @click="returnNewest">返回最新</el-button>
+            <el-button v-if="history" type="primary" size="medium" @click="gethistoryData">查看老数据</el-button>
+            <el-button v-if="history" type="primary" size="medium" @click="getQueryData">新建{{ title }}</el-button>
+          </div>
+        </div>
+        <el-table v-loading="loading" :data="tableData" size="mini" :header-cell-style="{ background: '#F2F3F6' }" border style="width: 100%" :show-overflow-tooltip="true">
+          <el-table-column label="报告名称" min-width="280" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <a v-if="title === '测试日报' || title === '准出报告'" href="javascript:void(0)" style="color:#20a0ff" @click="history ? toReportView(scope.row) : OldDaily(scope.row)">{{ scope.row.reportName }}</a>
+              <a v-if="title === '提测报告'" href="javascript:void(0)" style="color:#20a0ff" @click="history ? toReportView(scope.row) : OldDaily(scope.row)">{{ history ? scope.row.reportName : scope.row.name }}</a>
+              <div v-if="title === '提测报告'">{{ scope.row.returnReason }}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态" min-width="150">
+            <template slot-scope="scope">{{ scope.row.statusString }}</template>
+          </el-table-column>
+          <el-table-column label="报告人" min-width="180">
+            <template slot-scope="scope">
+              <div v-if="history">
+                <div v-if="title === '测试日报' || title === '准出报告'">{{ scope.row.reportorObject.name ===null ? '' : scope.row.reportorObject.name }}</div>
+                <div v-if="title === '提测报告'">{{ scope.row.reportorObject.name }}</div>
+              </div>
+              <div v-if="!history">
+                <div v-if="title === '测试日报' || title === '准出报告'">{{ scope.row.ownner }}</div>
+                <div v-if="title === '提测报告'">{{ scope.row.submitter }}</div>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="创建时间" min-width="280">
+            <template slot-scope="scope">{{ scope.row.gmtCreate }}</template>
+          </el-table-column>
+          <el-table-column v-if="history" label="操作" align="center" fixed="right" min-width="230">
+            <template slot-scope="scope">
+              <div v-if="title === '测试日报'">
+                <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="dailyButtom(5,scope.row)">发送</span>
+                <span v-if="scope.row.status === 0 ? true : false" style="margin: 0 30px;" class="didi-hover" @click="dailyButtom(6,scope.row)">编辑</span>
+                <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="report_click(4,scope.row )">删除</span>
+                <span v-if="scope.row.status === 3 ? true : false" class="didi-hover" @click="dailyButtom(3,scope.row)">复制</span>
+              </div>
+              <div v-if="title === '准出报告'">
+                <div v-if="scope.row.status === 3 ? false : true">
+                  <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="clientButtom(5,scope.row)">发送</span>
+                  <span v-if="scope.row.status === 0 ? true : false" style="margin: 0 30px;" class="didi-hover" @click="clientButtom(6,scope.row)">编辑</span>
+                  <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="report_click(4,scope.row )">删除</span>
+                </div>
+              </div>
+              <div v-if="title === '提测报告'">
+                <div v-if="scope.row.status === 1 ? false : true">
+                  <span v-if="scope.row.status === 3 ? true : false" class="didi-hover" @click="report_click(1,scope.row)">通过</span>
+                  <span v-if="scope.row.status === 3 ? true : false" style="margin-left: 30px;" class="didi-hover" @click="report_click(2,scope.row)">打回</span>
+                  <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="report_click(5,scope.row)">发送</span>
+                  <span v-if="scope.row.status === 0 ? true : false" style="margin: 0 30px;" class="didi-hover" @click="report_click(6,scope.row)">编辑</span>
+                  <span v-if="scope.row.status === 0 ? true : false" class="didi-hover" @click="report_click(4,scope.row )">删除</span>
+                  <span v-if="scope.row.status === 2 ? true : false" class="didi-hover" @click="report_click(3,scope.row)">重新提测</span>
+                </div>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-main>
+      <el-footer class="public_footer">
+        <el-pagination v-if="history" style="margin-top:30px;" align="center" :current-page="curIndex" :page-sizes="[5, 10, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+        <el-pagination v-if="!history" style="margin-top:30px;" align="center" :current-page="curIndex" :page-sizes="[5, 10, 20]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" />
+      </el-footer>
+    </el-container>
+    <!-- 日报/准出/提测选择任务 -->
+    <el-dialog title="选择任务" :visible.sync="centerDialogVisible" width="30%" center>
+      <div class="Layout_space_between">
+        <div style="width:100px;">选择任务 :</div>
+        <el-select v-model="queryData.code" filterable placeholder="请选择任务" size="mini" style="width:100%;">
+          <el-option v-for="item in restaurants" :key="item.id" :label="item.name" :value="item.id" />
+        </el-select>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" size="mini" @click="createPresentation(queryData.code)">创建</el-button>
+      </span>
+    </el-dialog>
+
+    <el-dialog :title="report_from.titName" :visible.sync="dialog_testData" width="30%" :close-on-click-modal="false">
+      <div style="position: absolute; top: 23px; left: 12px;width:4px;height:17px;background:#409EFF;border-radius:1px;" />
+      <div align="center">
+        <div v-if="title === '提测报告'">是否{{ report_from.statusString }}以下提测?</div>
+        <div v-if="title === '测试日报'">是否{{ report_from.statusString }}以下测试日报?</div>
+        <div v-if="title === '准出报告'">是否{{ report_from.statusString }}以下准出报告?</div>
+        <div style="color: #f79232;">{{ report_from.name }}</div>
+      </div>
+      <el-input v-show="report_from.statusString === '打回'" v-model="report_from.reason" type="textarea" placeholder="请输入打回原因..." :rows="3" />
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" size="mini" @click="passOrBackSend()">确 定</el-button>
+        <el-button type="danger" size="mini" @click="endDialog">取 消</el-button>
+      </span>
+    </el-dialog>
+
+    <TestingReport v-if="dialogVisible1" ref="TestReport" />
+    <DailyReport v-if="dialogDaily" ref="DailyReport" @getList="getList" />
+    <ReleaseReport v-if="dialogClient" ref="ClientReport" />
+
+    <el-dialog :title="title" :visible.sync="reportDaily" class="public_task" width="70%" :close-on-click-modal="false">
+      <div class="blueStripe" />
+      <div v-if="title === '测试日报'" style=" margin-bottom: 2%; height: 600px; overflow:scroll; overflow-x: hidden">
+        <testPresenyL v-if="testPresenyL" :message="message" />
+      </div>
+      <div v-if="title === '准出报告'" style=" margin-bottom: 2%; height: 600px; overflow:scroll; overflow-x: hidden">
+        <ResultPageyL v-if="ResultPageyL" :message="message" />
+      </div>
+      <div v-if="title === '提测报告'" style=" margin-bottom: 2%; height: 600px; overflow:scroll; overflow-x: hidden">
+        <acceptTheReport v-if="acceptTheReport" :message="message" />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import '@/styles/PublicStyle/index.scss'
+import { dailyReportDelete } from '@/api/testPresentetion' // 日报
+import { projectTestReportList } from '@/api/ResultPage' // 准出
+import { launchTestList, taskListCreate } from '@/api/InterfaceReport' // 提测
+import TestingReport from '@/views/reportManagement/components/TestingReport' // 提测
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
+import { dailyReportList, dailyReportListV2, reportreleaseList, reportdelivertestList, reportreleaseDelete, reportdelivertestDelete, reportdelivertestUpdate } from '@/api/reportTemplate'
+import testPresenyL from '@/views/reportManagement/daily/components/testPresenyL.vue' // 老日报数据
+import ResultPageyL from '@/views/reportManagement/ReleaseReport/components/ResultPageyL.vue' // 老准出报告
+import acceptTheReport from '@/views/reportManagement/Testing/components/acceptTheReport.vue' // 老提测报告
+
+export default {
+  name: 'TestPresentation',
+  components: {
+    TestingReport,
+    DailyReport,
+    ReleaseReport,
+    testPresenyL,
+    ResultPageyL,
+    acceptTheReport
+  },
+  data() {
+    return {
+      activeName: 'first',
+      title: '测试日报', // 报告title
+      history: true, // 新老数据
+      userInformation: localStorage.getItem('username'),
+      userNames: localStorage.getItem('realname'),
+      bizJson: localStorage.getItem('bizId'),
+      message: {}, // 老日报数据
+      reportDaily: false,
+      testPresenyL: false, // 老日报数据
+      ResultPageyL: false, // 老准出报告
+      acceptTheReport: false, // 老提测报告
+      centerDialogVisible: false, // 新建报告选择任务
+      dialog_testData: false, // 操作弹窗
+      report_data: {}, // 当前点击数据
+      userData: { id: '', ename: this.userInformation, name: this.userNames },
+      loading: true,
+      pageSize: 10,
+      curIndex: 1,
+      total: 0,
+      state: '',
+      restaurants: [],
+      queryData: {}, // 选择的任务code为id
+      report_from: {
+        name: '',
+        titName: '',
+        statusString: ''
+      },
+      tableData: [],
+      z_name: '',
+      restaurants2: [],
+      dialogVisible1: false, // 提测弹窗
+      dialogDaily: false,
+      dialogClient: false,
+      indexPage: {
+        pageSize: 10,
+        curIndex: 1
+      }
+    }
+  },
+  destroyed() {
+    this.$store.state.data.status = false
+  },
+  created() {
+    this.getList()
+    this.$store.state.data.status = true
+  },
+  methods: {
+    handleClick(tab, event) {
+      this.curIndex = 1
+      this.loading = true
+      console.log(tab.index, 'cdscsc')
+      switch (Number(tab.index)) {
+        case 0:
+          this.title = '测试日报'
+          this.history ? this.getList() : this.gethistoryData()
+          break
+        case 1:
+          this.title = '准出报告'
+          this.history ? this.getList() : this.gethistoryData()
+          break
+        case 2:
+          this.title = '提测报告'
+          this.history ? this.getList() : this.gethistoryData()
+          break
+      }
+    },
+
+    async getList(e) { // 报告list
+      this.loading = true
+      this.history = true
+      const indexPage = { bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
+      e ? indexPage.reportName = this.state : ''
+      if (this.title === '测试日报') {
+        const res = await dailyReportListV2(indexPage)
+        if (res.code === 200) {
+          this.tableData = res.data
+          this.total = res.total
+        }
+      }
+      if (this.title === '准出报告') {
+        const res = await reportreleaseList(indexPage)
+        if (res.code === 200) {
+          this.tableData = res.data.list || []
+          this.total = res.data.total
+        }
+      }
+      if (this.title === '提测报告') {
+        const data = { bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
+        e ? indexPage.name = this.state : ''
+        const res = await reportdelivertestList(data)
+        if (res.code === 200) {
+          this.tableData = res.data.list || []
+          this.total = res.data.total
+        }
+      }
+      this.loading = false
+    },
+
+    returnNewest() { // 返回最新
+      this.pageSize = 10
+      this.curIndex = 1
+      this.state = ''
+      this.getList()
+    },
+
+    async passOrBackSend() { // 提测打回
+      this.dialog_testData = false
+
+      if (this.report_from.statusString === '通过' || this.report_from.statusString === '打回') {
+        const data = {
+          id: this.report_data.id,
+          moduleId: this.report_data.moduleId,
+          bizId: this.report_data.bizId,
+          taskIds: this.report_data.taskIds,
+          reportName: this.report_data.reportName,
+          returnReason: this.report_from.reason,
+          status: this.report_from.statusString === '打回' ? 2 : this.report_from.statusString === '通过' ? 1 : ''
+        }
+        const res = await reportdelivertestUpdate(data)
+        if (res.code === 200) {
+          this.getList()
+          this.$message({ message: res.msg, type: 'success', offset: 150 })
+        }
+      } else if (this.report_from.statusString === '删除') {
+        switch (this.title) {
+          case '测试日报':
+            dailyReportDelete(this.userData, this.report_data.id).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '删除成功' })
+                this.getList()
+              }
+            })
+            break
+          case '准出报告':
+            reportreleaseDelete(this.userData, this.report_data.id).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '删除成功' })
+                this.getList()
+              }
+            })
+            break
+          case '提测报告':
+            reportdelivertestDelete({}, this.report_data.id).then(res => {
+              if (res.code === 200) {
+                this.$message({ type: 'success', message: '删除成功' })
+                this.getList()
+              }
+            })
+            break
+        }
+      }
+    },
+
+    dailyButtom(e, data) { // 测试报告
+      this.report_data = data
+      switch (e) {
+        case 3: // 复制 第二步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(4, data)
+          })
+          break
+        case 5: // 日报第三步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(3, data)
+          })
+          break
+        case 6: // 日报第二步
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(2, data)
+          })
+          break
+      }
+    },
+
+    clientButtom(e, data) { // 准出报告
+      this.report_data = data
+      switch (e) {
+        case 5:
+          this.dialogClient = true
+          this.$nextTick(() => {
+            this.$refs.ClientReport.init(3, data)
+          })
+          break
+        case 6:
+          this.dialogClient = true
+          this.$nextTick(() => {
+            this.$refs.ClientReport.init(2, data)
+          })
+          break
+      }
+    },
+
+    report_click(e, data) { // 提测报告
+      this.report_from.name = data.name || data.reportName
+      this.report_data = data
+      switch (e) {
+        case 1:
+          this.dialog_testData = true
+          this.report_from.titName = '提测确认'
+          this.report_from.statusString = '通过'
+          break
+        case 2:
+          this.dialog_testData = true
+          this.report_from.titName = '提测确认'
+          this.report_from.statusString = '打回'
+          break
+        case 3:
+          data.taskIds = [Number(this.taskId)]
+          this.dialogVisible1 = true
+          this.$nextTick(() => {
+            this.$refs.TestReport.init(4, data)
+          })
+          break
+        case 4:
+          this.dialog_testData = true
+          this.report_from.titName = '删除确认'
+          this.report_from.statusString = '删除'
+          break
+        case 5:
+          this.dialogVisible1 = true
+          this.$nextTick(() => {
+            this.$refs.TestReport.init(3, data)
+          })
+          break
+        case 6:
+          this.dialogVisible1 = true
+          this.$nextTick(() => {
+            this.$refs.TestReport.init(2, data)
+          })
+          break
+      }
+    },
+    // 获取任务数据
+    async getQueryData() { // 获取任务数据
+      this.centerDialogVisible = true
+      this.$set(this.queryData, 'code', '')
+      const res = await taskListCreate({ bizId: localStorage.getItem('bizId') })
+      if (res.code === 200) {
+        this.restaurants = res.data.taskInfoList
+      }
+    },
+
+    createPresentation(vel) {
+      if (vel !== '') {
+        if (this.title === '测试日报') {
+          this.dialogDaily = true
+          this.$nextTick(() => {
+            this.$refs.DailyReport.init(7, [vel])
+          })
+        }
+        if (this.title === '准出报告') {
+          this.dialogClient = true
+          this.$nextTick(() => {
+            this.$refs.ClientReport.init(7, [vel])
+          })
+        }
+        if (this.title === '提测报告') {
+          this.dialogVisible1 = true
+          this.$nextTick(() => {
+            this.$refs.TestReport.init(7, [vel])
+          })
+        }
+        this.centerDialogVisible = false
+      } else {
+        this.$message({ message: '提示,请选择要添加的任务ID', type: 'warning' })
+      }
+    },
+    createFilter(queryString) {
+      return (restaurant) => {
+        return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
+      }
+    },
+
+    // 日报/准出/提测
+    toReportView(ele) {
+      switch (this.title) {
+        case '测试日报':
+          this.$router.push({ name: '日报详情', query: { id: ele.id }})
+          break
+        case '准出报告':
+          this.$router.push({ name: '准出详情', query: { id: ele.id }})
+          break
+        case '提测报告':
+          this.$router.push({ name: '提测详情', query: { id: ele.id }})
+          break
+      }
+    },
+
+    async gethistoryData(e) { // 查看所有老日报列表
+      this.loading = true
+      this.history = false
+      const indexPage = { bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
+      e ? indexPage.reportName = this.state : ''
+      if (this.title === '测试日报') {
+        const res = await dailyReportList(indexPage)
+        if (res.code === 200) {
+          this.tableData = res.data
+          this.total = res.total
+        }
+      }
+      if (this.title === '准出报告') {
+        const res = await projectTestReportList(indexPage)
+        if (res.code === 200) {
+          this.tableData = res.data
+          this.total = res.total
+        }
+      }
+      if (this.title === '提测报告') {
+        const data = { bizId: localStorage.getItem('bizId'), pageSize: this.pageSize, curIndex: this.curIndex }
+        e ? indexPage.name = this.state : ''
+        const res = await launchTestList(data)
+        if (res.code === 200) {
+          this.tableData = res.data
+          this.total = res.total
+        }
+      }
+      this.loading = false
+    },
+
+    OldDaily(val) {
+      this.reportDaily = true
+      if (this.title === '测试日报') {
+        this.testPresenyL = true
+        this.message = val
+      }
+      if (this.title === '准出报告') {
+        this.ResultPageyL = true
+        this.message = val
+      }
+      if (this.title === '提测报告') {
+        this.acceptTheReport = true
+        this.message = val
+      }
+    },
+
+    endDialog() { // 结束对话框
+      this.dialog_testData = false
+      this.$message({ type: 'warning', message: '已取消' })
+    },
+    handleSizeChange(size) { // 分页
+      this.pageSize = size
+      this.getList()
+    },
+    handleCurrentChange(curIndex) { // 分页
+      this.curIndex = curIndex
+      this.getList()
+    },
+    handleSizeChange1(size) { // used 分页
+      this.pageSize = size
+      this.gethistoryData()
+    },
+    handleCurrentChange1(curIndex) { // used 分页
+      this.curIndex = curIndex
+      this.gethistoryData()
+    }
+  }
+}
+</script>
+<style scoped>
+  .eleStyle {
+    width: 100%;
+    height:100%;
+    background:#F2F3F6;
+    display: inline-block;
+  }
+  .header_sty {
+    font-size: 14px;
+    background:#ffffff;
+    margin: 10px;
+    border-radius: 4px;
+    overflow: hidden;
+  }
+  .distance {
+    margin-bottom: 20px;
+  }
+  .report-Layout {
+    min-height: calc(100vh - 221px)
+  }
+</style>
+<style lang="stylus">
+.el-tabs__nav-wrap::after {
+    background-color: #FFF !important;
+    }
+</style>

+ 15 - 1
src/views/workbench/bugTableList.vue

@@ -144,10 +144,24 @@ export default {
         this.statusObj = {
           bugEnumList: res.data.bugEnumList, // status
           repairResultEnumList: res.data.repairResultEnumList, // 修复结果
-          bugReasonEnumList: res.data.bugReasonEnumList // 缺陷原因
+          bugReasonEnumList: res.data.bugReasonEnumList, // 缺陷原因
+          theBugTypeEnumList: this.deleteChild(res.data.theBugTypeEnumList) // 缺陷类型
         }
       })
     },
+    deleteChild(arr) { // 删除无用子属性
+      const bfs = arr => {
+        arr.forEach(item => {
+          if (!item.childrenEnums || item.childrenEnums.length === 0) {
+            delete item.childrenEnums
+          } else {
+            this.deleteChild(item.childrenEnums)
+          }
+        })
+      }
+      bfs(arr)
+      return arr
+    },
     async bugGetTableList(name, value) {
       const teamSearchInfo = value || { teamId: this.teamId, bizId: this.bizId }
       if (value) {

+ 31 - 13
src/views/workbench/person/components/calenderDetail.vue

@@ -61,17 +61,20 @@ export default {
   data() {
     return {
       showDetail: this.show,
-      nowDetailData: this.data
+      nowDetailData: this.data,
+      topScroll: 0// 距离顶部距离
     }
   },
   watch: {
     show(newV) {
       this.showDetail = newV
+      if (!newV) this.topScroll = 0
     },
     data: {
       handler(newV) {
         if (newV) {
           this.nowDetailData = newV
+          this.topScroll = 0
         }
       },
       deep: true
@@ -87,7 +90,32 @@ export default {
     }
   },
   mounted() {
-    document.body.addEventListener('click', e => { // 日历弹出层操作
+    document.body.addEventListener('click', this.hiddenDetail)
+    window.addEventListener('scroll', this.handleScroll, true)
+  },
+  destroyed() {
+    document.body.removeEventListener('click', this.hiddenDetail)
+  },
+  methods: {
+    handleScroll(e) {
+      if (this.topScroll === 0 && this.showDetail) {
+        this.topScroll = e.srcElement.scrollTop
+        return
+      }
+      if (this.showDetail) {
+        const topScroll = e.srcElement.scrollTop // 获取页面滚动高度
+        this.$refs['show-schedule-detail'].style.top = Number(this.position[1].replace('px', '')) - (topScroll - this.topScroll) + 'px'
+      }
+    },
+    editSchedule() {
+      this.$emit('edit', this.nowDetailData)
+      this.$emit('update:show', this.showDetail)
+    },
+    deleteSchedule() {
+      this.$emit('delete', this.nowDetailData)
+      this.$emit('update:show', this.showDetail)
+    },
+    hiddenDetail(e) {
       const event = document.querySelector('.show-schedule-detail')
       const isIn = e.target.className === 'fc-content' || e.target.className === 'fc-time' || e.target.className === 'fc-title'
       if (!event || isIn) {
@@ -98,16 +126,6 @@ export default {
         this.showDetail = false
         this.$emit('update:show', this.showDetail)
       }
-    })
-  },
-  methods: {
-    editSchedule() {
-      this.$emit('edit', this.nowDetailData)
-      this.$emit('update:show', this.showDetail)
-    },
-    deleteSchedule() {
-      this.$emit('delete', this.nowDetailData)
-      this.$emit('update:show', this.showDetail)
     }
   }
 }
@@ -129,7 +147,7 @@ export default {
   max-height: 326px;
   width: 400px;
   position: fixed;
-  z-index: 2000;
+  z-index: 1;
   top: 0;
   left: 0;
   background-color: #FFFFFF;

+ 5 - 5
src/views/workbench/team/components/taskList.vue

@@ -115,7 +115,7 @@
     </div>
     <TestReport v-if="dialogTestReport" ref="TestReport" />
     <DailyReport v-if="dialogDailyReport" ref="DailyReport" />
-    <ClientReport v-if="dialogClientReport" ref="ClientReport" />
+    <ReleaseReport v-if="dialogClientReport" ref="ClientReport" />
     <taskDialog v-if="showTaskDialog" :show.sync="showTaskDialog" :task-id="taskId.id" :status-name="taskId.statusString" @getList="get_allTask" />
     <!-- 批量排期 -->
     <modify-schedule
@@ -130,9 +130,9 @@
 <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 TestReport from '@/views/reportManagement/components/TestingReport' // 提测
+import DailyReport from '@/views/reportManagement/components/DailyReport' // 日报
+import ReleaseReport from '@/views/reportManagement/components/ReleaseReport' // 准出
 import { taskSelfList, taskTeamList } from '@/api/workSchedule'
 import { taskUpdate } from '@/api/projectViewDetails'
 import { configShowTaskEnum, configShowTaskStatusEnum } from '@/api/taskIndex'
@@ -142,7 +142,7 @@ export default {
   components: {
     TestReport,
     DailyReport,
-    ClientReport,
+    ReleaseReport,
     taskDialog,
     modifySchedule
   },