Przeglądaj źródła

Merge branch 'http_test' into http_mock

洪海涛 4 lat temu
rodzic
commit
51672aabc6

+ 10 - 1
src/api/common.js

@@ -1,5 +1,5 @@
 import request from '@/utils/request'
 import request from '@/utils/request'
-import { envWebUrl } from '@/apiConfig/api'
+import { envWebUrl, projectManagementUrl } from '@/apiConfig/api'
 
 
 export function feedback(data) {
 export function feedback(data) {
   return request({
   return request({
@@ -17,3 +17,12 @@ export function uploadImage(data) {
     data
     data
   })
   })
 }
 }
+
+// 标签
+export function taskGetTag(data) {
+  return request({
+    url: projectManagementUrl + '/task/getTag',
+    method: 'post',
+    data
+  })
+}

+ 87 - 0
src/components/Tag/TagSearch.vue

@@ -0,0 +1,87 @@
+<template>
+  <el-select
+    ref="select"
+    v-model="tagSelectValue"
+    style="width: 100%"
+    multiple
+    remote
+    size="small"
+    filterable
+    default-first-option
+    :placeholder="placeholder"
+    :remote-method="remoteMethod"
+    @change="change"
+  >
+    <el-option
+      v-for="(item, itemIndex) in options"
+      :key="itemIndex"
+      :label="item.tag"
+      :value="item.id"
+    >
+      {{ item.tag }}
+    </el-option>
+  </el-select>
+</template>
+<script>
+import { taskGetTag } from '@/api/common'
+import { desDecryptId, analysisBizId_id } from '@/utils/crypto-js'
+
+export default {
+  name: 'TagSearch',
+  props: {
+    value: {
+      required: false,
+      type: Array,
+      default: () => []
+    },
+    type: {
+      required: false,
+      type: String,
+      default: () => ''
+    },
+    placeholder: {
+      required: false,
+      type: String,
+      default: () => '请选择标签'
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      isAddTag: true,
+      options: [],
+      tagSelectValue: [],
+      tagValue: []
+    }
+  },
+  mounted() {
+    setTimeout(() => {
+      this.remoteMethod()
+    }, 700)
+  },
+  methods: {
+    change() {
+      this.$emit('input', this.tagSelectValue)
+      this.$emit('change', this.tagSelectValue)
+    },
+    remoteMethod(searchTag = '') {
+      if (!this.$route.query.bizId) return
+      // const bizId_id = analysisBizId_id(this.$route.query.bizId)
+      // const bizId_id = window.localStorage.getItem('bizId')
+      const bizId_id = desDecryptId(this.$route.query.bizId).replace(/_.*/, '')
+      console.log(bizId_id)
+      taskGetTag({
+        type: this.type,
+        searchTag,
+        bizId: bizId_id
+      }).then(res => {
+        if (res.code === 200) {
+          this.options = res.data.map(elm => elm)
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped lang="less">
+</style>

+ 238 - 0
src/components/Tag/index.vue

@@ -0,0 +1,238 @@
+<template>
+  <div class="tips-wrapper">
+    <span>
+      <el-tag
+        v-for="item in value"
+        :key="item"
+        closable
+        size="small"
+        type="info"
+        @close="() => tabClose(item)">
+          {{ item }}
+        </el-tag>
+    </span>
+    <span class="add-tag" @click="addTag">打标</span>
+
+    <!-- 弹窗 -->
+    <div v-if="visible" class="dialogbox">
+      <div class="box">
+        <div class="title">
+          <span class="line" />
+          <span class="name">设置标签</span>
+          <i class="el-icon-close icon"  />
+        </div>
+        <div class="body">
+          <el-form-item style="width: 100%;margin-right: 0;" :rules="[{ required: true, message: '标签不能为空'}]" label="标签:" class="tag-from">
+           <el-select
+            style="width: 100%;"
+            ref="select"
+            v-model="tagSelectValue"
+            multiple
+            remote
+            filterable
+            allow-create
+            default-first-option
+            :placeholder="placeholder"
+            :remote-method="remoteMethod"
+            @click.stop
+            @change="change"
+          >
+            <el-option
+              v-for="(item, itemIndex) in options"
+              :key="itemIndex"
+              :label="item"
+              :value="item"
+            >
+              {{ item }}
+            </el-option>
+          </el-select>
+      <template slot="footer">
+        <el-button size="small" @click="close">取消</el-button>
+        <el-button size="small" type="primary" @click="ok">确定</el-button>
+      </template>
+          </el-form-item>
+        </div>
+        <div class="footer">
+          <el-button size="small" @click="close">取消</el-button>
+        <el-button size="small" type="primary" @click="ok">确定</el-button>
+        </div>
+      </div>
+      <div class="bg" />
+    </div>
+  </div>
+</template>
+<script>
+import Clickoutside from 'element-ui/src/utils/clickoutside'
+import { EncryptId, analysisBizId_id } from '@/utils/crypto-js.js'
+import { taskGetTag } from '@/api/common'
+import Modal from '@/components/modal'
+
+export default {
+  name: 'Tag',
+  components: { Modal },
+  directives: { Clickoutside },
+  props: {
+    value: {
+      required: false,
+      type: Array,
+      default: () => []
+    },
+    type: {
+      required: false,
+      type: String,
+      default: () => ''
+    },
+    placeholder: {
+      required: false,
+      type: String,
+      default: () => '请选择标签'
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      isAddTag: true,
+      options: [],
+      tagSelectValue: [],
+      tagValue: []
+    }
+  },
+  methods: {
+    change() {
+      this.tagSelectValue = Array.from(new Set(this.tagSelectValue))
+      this.options = Array.from(new Set([...this.options, ...this.tagSelectValue]))
+    },
+    close() {
+      this.visible = false
+    },
+    tabClose(item) {
+      const newTagValue = [...this.value].filter(elm => elm !== item)
+      this.$emit('input', newTagValue)
+      this.$emit('change', newTagValue)
+    },
+    ok() {
+      this.$emit('input', this.tagSelectValue)
+      this.$emit('change', this.tagSelectValue)
+
+      this.close()
+    },
+    addTag() {
+      this.remoteMethod()
+      this.tagSelectValue = Array.from(new Set(this.value))
+      this.options = Array.from(new Set([...this.options, ...this.value]))
+      this.visible = true
+    },
+    remoteMethod(searchTag = '') {
+      if (!this.$route.query.bizId) return
+      // const bizId_id = analysisBizId_id(this.$route.query.bizId)
+      // const bizId_id = window.localStorage.getItem('bizId')
+      const bizId_id = desDecryptId(this.$route.query.bizId).replace(/_.*/, '')
+      console.log(bizId_id)
+      taskGetTag({
+        type: this.type,
+        searchTag,
+        bizId: bizId_id
+      }).then(res => {
+        if (res.code === 200) {
+          this.options = res.data.map(elm => elm.tag)
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped lang="less">
+.tips-wrapper {
+  display: inline-block;
+}
+
+/deep/ .el-select__tags {
+  max-width: calc(100% - 100px) !important;
+}
+
+.el-tag {
+  margin-left: 5px;
+  user-select: none;
+}
+
+.add-tag {
+  color: #00a0ff;
+  margin-left: 10px;
+  cursor: pointer;
+}
+
+/deep/ .el-select {
+  /deep/ .el-input__inner {
+    border: 1px solid rgba(220, 223, 230) !important;
+  }
+}
+
+.dialogbox {
+  .box {
+    position: fixed;
+    top:20vh;
+    left: calc(50% - 250px);
+    width: 500px;
+    min-height: 180px;
+    // overflow: auto;
+    background: #fff;
+    z-index: 1000;
+    border-radius: 4px;
+    display: flex;
+    flex-direction: column;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+    .title {
+      padding: 5px 0px 5px 18px;
+      // border-bottom: 1px solid #eee;
+      position: relative;
+      .line {
+        display: inline-block;
+        width: 4px;
+        height: 18px;
+        background: #409eff;
+        border-radius: 1px;
+        vertical-align: text-top;
+      }
+      .name {
+        margin-left: 6px;
+        color: rgba(0,0,0,.85);
+        font-weight: 500;
+        font-size: 16px;
+        line-height: 22px;
+        word-wrap: break-word;
+      }
+      .icon {
+        position: absolute;
+        top: 20px;
+        right: 20px;
+        font-size: 16px;
+        color: #909399;
+        cursor: pointer;
+      }
+    }
+    .body {
+      padding: 15px 20px;
+      color: #606266;
+      font-size: 14px;
+      word-break: break-all;
+      // height: calc(80vh - 118px);
+      overflow: auto;
+    }
+    .footer {
+      padding: 15px 20px;
+      text-align: right;
+      // border-top: 1px solid #eee;
+      background: #fff;
+    }
+  }
+  .bg {
+    background: rgba(000, 000, 000, 0.5);
+    position: fixed;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    z-index: 100;
+  }
+}
+</style>

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

@@ -70,7 +70,7 @@
       v-else-if="type === 'date'"
       v-else-if="type === 'date'"
       v-model="val"
       v-model="val"
       :size="size"
       :size="size"
-      value-format="yyyy-MM-dd hh:mm:ss"
+      value-format="yyyy-MM-dd hh:mm:ss a"
       type="datetime"
       type="datetime"
       :placeholder="placeholder"
       :placeholder="placeholder"
       :style="itemStyles"
       :style="itemStyles"

+ 13 - 0
src/components/searchHeader/searchForm.vue

@@ -123,6 +123,15 @@
         :tree-data="l.option"
         :tree-data="l.option"
         @change="(e) => $emit('change', l.key, e || '')"
         @change="(e) => $emit('change', l.key, e || '')"
       />
       />
+
+      <TagSearch
+        v-else-if="l.type === 'TagSearch'"
+        v-model="l.value"
+        :type="l.pageType"
+        style="width: 100%"
+         :placeholder="l.placeholder"
+        @change="(e) => $emit('change', l.key, e || '')"
+      />
       <el-input
       <el-input
         v-else
         v-else
         v-model="l.value"
         v-model="l.value"
@@ -138,8 +147,12 @@
 </template>
 </template>
 <script>
 <script>
 import moment from 'moment'
 import moment from 'moment'
+import TagSearch from '@/components/Tag/TagSearch'
 moment.locale('zh-cn')
 moment.locale('zh-cn')
 export default {
 export default {
+  components: {
+    TagSearch
+  },
   props: {
   props: {
     data: {
     data: {
       type: Array,
       type: Array,

+ 7 - 1
src/components/select/selectCascader.vue

@@ -10,6 +10,7 @@
     :style="itemStyles"
     :style="itemStyles"
     :placeholder="placeholder"
     :placeholder="placeholder"
     :remote-method="remoteMethod"
     :remote-method="remoteMethod"
+    :popper-append-to-body="popperAppendToBody"
     @change="changeCascader"
     @change="changeCascader"
   >
   >
     <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
     <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
@@ -63,6 +64,11 @@ export default {
       type: String,
       type: String,
       required: false,
       required: false,
       default: '请选择'
       default: '请选择'
+    },
+    popperAppendToBody: {
+      type: Boolean,
+      required: false,
+      default: true
     }
     }
   },
   },
   data() {
   data() {
@@ -78,7 +84,7 @@ export default {
   },
   },
   watch: {
   watch: {
     value() {
     value() {
-      this.init()
+      // this.init()
     },
     },
     selectEnum() {
     selectEnum() {
       this.init()
       this.init()

+ 2 - 3
src/components/select/selectCascaderInfo.vue

@@ -7,11 +7,10 @@
           effect="dark"
           effect="dark"
           :content="item.deptPath"
           :content="item.deptPath"
           placement="top">
           placement="top">
-          <span>{{ item.label }}</span>
+          <span>{{ item.label }}{{ index === itemName.length - 1 ? '' : ',' }}</span>
         </el-tooltip>
         </el-tooltip>
-        <span>{{ !(index >= itemName.length - 1) ? ',' : '' }}</span>
       </span>
       </span>
-    </span>
+    </span><slot />
   </div>
   </div>
 </template>
 </template>
 
 

+ 36 - 8
src/views/monthlyReport/childrenPage/editReport/components/VarText.vue

@@ -5,29 +5,44 @@
         {{ name }}:
         {{ name }}:
       </div>
       </div>
       <div class="value">
       <div class="value">
-        <el-input
-          v-if="pageDate.status < 20 && !isHistory"
-          v-model="textValue"
-          type="textarea"
-          :placeholder="headerTitleType === 'Head2' ? `请针对${headerTitle}进行分析` : '请输入'"
-          show-word-limit
-        />
+        <el-row v-if="pageDate.status < 20 && !isHistory" type="flex" justify="space-between">
+          <el-input
+            v-model="textValue"
+            type="textarea"
+            :placeholder="headerTitleType === 'Head2' ? `请针对${headerTitle}进行分析,建议格式:【1、事实描述:XXXXXX;2、根因分析:XXXXXX;3、建议:XXXXXX。】` : '请输入'"
+            show-word-limit
+          />
+          <el-button
+            style="margin-left: 20px;margin-right: 20px;font-size: 14px;font-weight: 400;"
+            type="text"
+            @click="markingIssues"
+          >
+            标记
+          </el-button>
+        </el-row>
         <span
         <span
           v-if="pageDate.status > 10 && textValue || isHistory && textValue"
           v-if="pageDate.status > 10 && textValue || isHistory && textValue"
           style="display: inline-block;line-height: 1.65;background-color: #f7f7f7; padding: 10px; border-radius: 5px;"
           style="display: inline-block;line-height: 1.65;background-color: #f7f7f7; padding: 10px; border-radius: 5px;"
           v-html="textValue.replace(/\n/g, '<br />')"
           v-html="textValue.replace(/\n/g, '<br />')"
-          />
+        />
       </div>
       </div>
     </div>
     </div>
+    <span @click.stop>
+      <markingIssues ref="markingIssues" />
+    </span>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
 import { mapState } from 'vuex'
 import { mapState } from 'vuex'
+import markingIssues from './markingIssues'
 import _ from 'lodash'
 import _ from 'lodash'
 
 
 export default {
 export default {
   name: 'VarText',
   name: 'VarText',
+  components: {
+    markingIssues
+  },
   props: {
   props: {
     title: {
     title: {
       type: String,
       type: String,
@@ -84,6 +99,16 @@ export default {
   methods: {
   methods: {
     upData() {
     upData() {
       this.$emit('input', this.textValue)
       this.$emit('input', this.textValue)
+    },
+    markingIssues() {
+      this.$refs.markingIssues.modalShow = true
+      this.$nextTick(() => {
+        this.$refs.markingIssues.openModal({
+          title: '标记为重点问题',
+          normalAreaName: `${this.value}`,
+          headerTitle: this.headerTitle
+        })
+      })
     }
     }
   }
   }
 }
 }
@@ -93,6 +118,7 @@ export default {
 .fixedText {
 .fixedText {
   //margin-top: 10px;
   //margin-top: 10px;
   padding-top: 10px;
   padding-top: 10px;
+
   .top-title {
   .top-title {
     width: 100%;
     width: 100%;
     display: flex;
     display: flex;
@@ -126,6 +152,7 @@ export default {
     }
     }
   }
   }
 }
 }
+
 .VarTextV2 {
 .VarTextV2 {
   padding-top: 10px;
   padding-top: 10px;
   margin-top: 5px;
   margin-top: 5px;
@@ -136,6 +163,7 @@ export default {
   //  }
   //  }
   //}
   //}
 }
 }
+
 .fontWeight {
 .fontWeight {
   font-weight: 600;
   font-weight: 600;
   padding-top: 10px;
   padding-top: 10px;

+ 23 - 23
src/views/monthlyReport/childrenPage/editReport/components/markingIssues.vue

@@ -1,25 +1,25 @@
 <template>
 <template>
   <div>
   <div>
     <normal-dialog
     <normal-dialog
-      v-if="modalShow"
-      ref="normalDialog"
-      v-loading="loading"
-      :show-dialog="false"
-      is-succes
-      :title="titleName"
-      width="45%"
-      @succes="updateModule"
+        v-if="modalShow"
+        ref="normalDialog"
+        v-loading="loading"
+        :show-dialog="false"
+        is-succes
+        :title="titleName"
+        width="45%"
+        @succes="updateModule"
     >
     >
       <el-form :key="domKey" label-width="100px" style="padding-right: 20px;padding-left: 20px">
       <el-form :key="domKey" label-width="100px" style="padding-right: 20px;padding-left: 20px">
         <el-form-item label="问题">
         <el-form-item label="问题">
           <el-input
           <el-input
-            v-model="normalAreaName"
-            autocomplete="off"
-            size="small"
-            type="textarea"
-            :autosize="{ minRows: 2, maxRows: 30 }"
-            show-word-limit
-            placeholder="请输入问题"
+              v-model="normalAreaName"
+              autocomplete="off"
+              size="small"
+              type="textarea"
+              :autosize="{ minRows: 2, maxRows: 30 }"
+              show-word-limit
+              placeholder="请输入问题"
           />
           />
         </el-form-item>
         </el-form-item>
         <el-form-item label="责任团队">
         <el-form-item label="责任团队">
@@ -27,10 +27,10 @@
         </el-form-item>
         </el-form-item>
         <el-form-item label="责任人">
         <el-form-item label="责任人">
           <searchPeople
           <searchPeople
-            ref="searchPeople"
-            style="width: 100%"
-            :value.sync="multiplePeople"
-            :multiple="true"
+              ref="searchPeople"
+              style="width: 100%"
+              :value.sync="multiplePeople"
+              :multiple="true"
           />
           />
         </el-form-item>
         </el-form-item>
       </el-form>
       </el-form>
@@ -108,7 +108,7 @@ export default {
       this.subTitles = subTitles
       this.subTitles = subTitles
       this.headerTitle = headerTitle
       this.headerTitle = headerTitle
       if (normalAreaName) this.normalAreaName = normalAreaName
       if (normalAreaName) this.normalAreaName = normalAreaName
-      this.setDefaultValues()
+      // this.setDefaultValues()
       this.loading = false
       this.loading = false
     },
     },
     // 设置默认值
     // 设置默认值
@@ -166,8 +166,8 @@ export default {
           (elm) => elm.name.search(/模块/) > -1
           (elm) => elm.name.search(/模块/) > -1
         )[0]
         )[0]
         this.normalAreaName =
         this.normalAreaName =
-          this.menuData[headerKeyMK.headerKey] &&
-          `${this.menuData[headerKeyMK.headerKey]}模块一次全量回滚`
+            this.menuData[headerKeyMK.headerKey] &&
+            `${this.menuData[headerKeyMK.headerKey]}模块一次全量回滚`
       }
       }
       if (this.cascaderValue && this.cascaderValue.length) {
       if (this.cascaderValue && this.cascaderValue.length) {
         this.setDeptCharge()
         this.setDeptCharge()
@@ -197,7 +197,7 @@ export default {
   }
   }
 }
 }
 </script>
 </script>
-<style scoped lang='less'>
+<style scoped lang="less">
 /deep/ .el-form-item__label {
 /deep/ .el-form-item__label {
   text-align: left !important;
   text-align: left !important;
 }
 }

+ 10 - 2
src/views/projectManage/bugList/bugindex.vue

@@ -210,15 +210,20 @@
                         start-placeholder="开始日期"
                         start-placeholder="开始日期"
                         end-placeholder="结束日期"
                         end-placeholder="结束日期"
                         size="small"
                         size="small"
+                        style="min-width: 493px"
                         value-format="yyyy-MM-dd HH:mm:ss"
                         value-format="yyyy-MM-dd HH:mm:ss"
                         :default-time="['00:00:00','23:59:59']"
                         :default-time="['00:00:00','23:59:59']"
                         :picker-options="pickerOptions"
                         :picker-options="pickerOptions"
                       />
                       />
                     </div>
                     </div>
+                    <div class="Layout searchItem">
+                      <div class="queryName">标签</div>
+                      <TagSearch v-model="formInline.tagIdList" type="BUG" placeholder="请选择" @change="query_project(form_all)" />
+                    </div>
                   </div>
                   </div>
                   <div align="right">
                   <div align="right">
                     <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
                     <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
-                    <el-button type="primary" style="margin: 0 20px;" size="mini" @click="getBugList()">筛 选</el-button>
+                    <el-button type="primary" style="margin: 0 0 0 10px;" size="mini" @click="getBugList()">筛 选</el-button>
                     <el-button size="mini" @click="resetQuery()">重 置</el-button>
                     <el-button size="mini" @click="resetQuery()">重 置</el-button>
                   </div>
                   </div>
                 </el-col>
                 </el-col>
@@ -284,13 +289,16 @@ import {
   getFilterItem
   getFilterItem
 } from '@/api/defectManage'
 } from '@/api/defectManage'
 import '@/views/projectManage/bugList/css/index.css'
 import '@/views/projectManage/bugList/css/index.css'
+import TagSearch from '@/components/Tag/TagSearch'
+
 export default {
 export default {
   components: {
   components: {
     createdBug,
     createdBug,
     normalDialog,
     normalDialog,
     filterList,
     filterList,
     bugTableDialog,
     bugTableDialog,
-    searchPeople
+    searchPeople,
+    TagSearch
   },
   },
   data() {
   data() {
     return {
     return {

+ 7 - 1
src/views/projectManage/bugList/details/index.vue

@@ -160,6 +160,9 @@
                   <el-form-item label="Hold次数">
                   <el-form-item label="Hold次数">
                     <div class="bug_manage_div">{{ bug.holdCount }}</div>
                     <div class="bug_manage_div">{{ bug.holdCount }}</div>
                   </el-form-item>
                   </el-form-item>
+                  <el-form-item label="标签">
+                    <Tag v-model="bug.tags" type="BUG" @change="bugUpdate(bug,'details')" />
+                  </el-form-item>
                 </el-form>
                 </el-form>
               </el-aside>
               </el-aside>
               <el-aside width="49%">
               <el-aside width="49%">
@@ -575,6 +578,7 @@ import normalArea from '@/components/input/normalArea' // 富文本
 import 'tinymce/plugins/table'// 插入表格插件
 import 'tinymce/plugins/table'// 插入表格插件
 // import 'tinymce/themes/silver/theme'
 // import 'tinymce/themes/silver/theme'
 // import 'tinymce/icons/default/icons'
 // import 'tinymce/icons/default/icons'
+import Tag from '@/components/Tag'
 
 
 document.body.onpaste = function(event) {
 document.body.onpaste = function(event) {
   const data = (event.clipboardData || window.clipboardData)
   const data = (event.clipboardData || window.clipboardData)
@@ -598,7 +602,8 @@ export default {
     statusChange,
     statusChange,
     searchPeople,
     searchPeople,
     ElImageViewer,
     ElImageViewer,
-    normalArea
+    normalArea,
+    Tag
   },
   },
   props: {
   props: {
     id: {
     id: {
@@ -1075,6 +1080,7 @@ export default {
             document.getElementsByClassName('scop')[0].scrollTop = 0
             document.getElementsByClassName('scop')[0].scrollTop = 0
           }
           }
           this.bug = res.data
           this.bug = res.data
+          this.bug.tags = res.data.tags || []
           this.bizId = this.bug.bizId
           this.bizId = this.bug.bizId
           this.bug.currentHandler = res.data.currentHandler.split(',')
           this.bug.currentHandler = res.data.currentHandler.split(',')
           this.bug.assigner = res.data.assigner.split(',')
           this.bug.assigner = res.data.assigner.split(',')

+ 10 - 1
src/views/projectManage/onlineproblem/component/header/searchData.js

@@ -77,7 +77,16 @@ const data = {
       placeholder: '请选择创建人',
       placeholder: '请选择创建人',
       value: '',
       value: '',
       option: []
       option: []
-    }]
+    },
+    {
+      name: '标签',
+      key: 'tagIdList',
+      type: 'TagSearch',
+      pageType: 'ONLINE_PROBLEM',
+      placeholder: '请选择标签',
+      value: []
+    }
+    ]
   ]
   ]
 }
 }
 export default data
 export default data

+ 4 - 0
src/views/projectManage/onlineproblem/create/index.vue

@@ -87,6 +87,10 @@ export default {
       addLinkModelvisible: false
       addLinkModelvisible: false
     }
     }
   },
   },
+  mounted() {
+    // 获取部门数据
+    this.$store.dispatch('monthlyReportEdit/setSelectEnum')
+  },
   methods: {
   methods: {
     back() {
     back() {
       this.$router.push({ name: '线上问题 ', query: { id: 111 }})
       this.$router.push({ name: '线上问题 ', query: { id: 111 }})

+ 59 - 4
src/views/projectManage/onlineproblem/detial/component/base.vue

@@ -58,8 +58,33 @@
           </template>
           </template>
         </over-click>
         </over-click>
       </el-form-item>
       </el-form-item>
-      <el-form-item label="责任团队:">
-        <over-click id="teamId-select" @overMouse="changeArea">
+      <el-form-item label="责任团队:" class="over-context-from">
+        <span v-if="isActive" v-clickoutside="() => {isActive = false; changeArea()}" class="active">
+          <selectTeam
+            v-if="data.teamId"
+            :value="data.teamId"
+            :name="data.teamName"
+            :biz-id-flag="false"
+            @click.stop
+            @onChange="(e) => onChange('teamId', e)"
+          />
+          <span v-else>
+            <selectCascader
+            v-model="data.deptIds"
+            :popper-append-to-body="false"
+            placeholder="请选择责任团队"
+            @click.stop
+            @change="(e) => {onChange('deptIds', e)}"
+          />
+          </span>
+        </span>
+        <span v-else class="overMouse over-context">
+          <selectCascaderInfo v-if="data.deptIds && data.deptIds.length" :key="data.deptIds.length" :team-data="data.deptIds">
+            <i class="el-icon-edit" @click="isActive = !isActive" />
+          </selectCascaderInfo>
+          <span v-else :class="!data.teamName && 'showPlacehodler'">{{ data.teamName ? data.teamName : '请选择' }}<i class="el-icon-edit" @click="isActive = !isActive" /></span>
+        </span>
+        <!-- <over-click id="teamId-select" inline @overMouse="changeArea">
           <template slot="active">
           <template slot="active">
             <selectTeam
             <selectTeam
               v-if="data.teamId"
               v-if="data.teamId"
@@ -80,7 +105,7 @@
             <selectCascaderInfo v-if="data.deptIds" :key="data.deptIds.length" :team-data="data.deptIds" />
             <selectCascaderInfo v-if="data.deptIds" :key="data.deptIds.length" :team-data="data.deptIds" />
             <span v-else :class="!data.teamName && 'showPlacehodler'">{{ data.teamName ? data.teamName : '请选择' }}</span>
             <span v-else :class="!data.teamName && 'showPlacehodler'">{{ data.teamName ? data.teamName : '请选择' }}</span>
           </template>
           </template>
-        </over-click>
+        </over-click> -->
       </el-form-item>
       </el-form-item>
       <el-form-item label="影响面:">
       <el-form-item label="影响面:">
         <over-click id="influenceSurface-select" @overMouse="changeArea">
         <over-click id="influenceSurface-select" @overMouse="changeArea">
@@ -170,6 +195,9 @@
           </template>
           </template>
         </over-click>
         </over-click>
       </el-form-item>
       </el-form-item>
+      <el-form-item label="标签:" class="tag-from">
+        <Tag v-model="data.tags" type="ONLINE_PROBLEM" @change="(e) => {onChange('tags', e); changeArea()}" />
+      </el-form-item>
     </el-form>
     </el-form>
   </div>
   </div>
 </template>
 </template>
@@ -178,13 +206,18 @@ import selectTeam from '@/components/select/selectTeam'
 import selectCascader from '@/components/select/selectCascader'
 import selectCascader from '@/components/select/selectCascader'
 import selectCascaderInfo from '@/components/select/selectCascaderInfo'
 import selectCascaderInfo from '@/components/select/selectCascaderInfo'
 import overClick from '@/components/click/overClick'
 import overClick from '@/components/click/overClick'
+import Tag from '@/components/Tag'
+import Clickoutside from 'element-ui/src/utils/clickoutside'
+
 export default {
 export default {
   components: {
   components: {
     overClick,
     overClick,
     selectTeam,
     selectTeam,
     selectCascader,
     selectCascader,
-    selectCascaderInfo
+    selectCascaderInfo,
+    Tag
   },
   },
+  directives: { Clickoutside },
   props: {
   props: {
     data: {
     data: {
       type: Object,
       type: Object,
@@ -196,6 +229,7 @@ export default {
     return {
     return {
       size: 'small',
       size: 'small',
       form_data: this.data,
       form_data: this.data,
+      isActive: false,
       // data: this.data,
       // data: this.data,
       priorityOption: [
       priorityOption: [
         { value: '0', label: 'P0' },
         { value: '0', label: 'P0' },
@@ -258,11 +292,32 @@ export default {
         line-height: 18px;
         line-height: 18px;
       }
       }
     }
     }
+    .over-context {
+      .el-icon-edit{
+        display: none;
+      }
+    }
+    .over-context:hover{
+      color: #409EFF;
+      .el-icon-edit {
+        display: inline;
+      }
+    }
+    .el-icon-edit {
+      cursor: pointer;
+      padding-right: 5px;
+      color: #409EFF;
+    }
     /deep/.el-form-item__content {
     /deep/.el-form-item__content {
       width: calc(100% - 340px);
       width: calc(100% - 340px);
       color: #333333;
       color: #333333;
       font-size: 14px;
       font-size: 14px;
     }
     }
+    .over-context-from {
+      /deep/.el-form-item__content {
+        width: calc(100% - 200px);
+      }
+    }
   }
   }
 }
 }
 </style>
 </style>

+ 10 - 0
src/views/projectManage/projectList/projectIndex.vue

@@ -45,6 +45,7 @@
                 <el-option v-for="item in arr_priority" :key="item.value" :label="item.name" :value="item.value" />
                 <el-option v-for="item in arr_priority" :key="item.value" :label="item.name" :value="item.value" />
               </el-select>
               </el-select>
             </div>
             </div>
+
           </el-form>
           </el-form>
         </div>
         </div>
         <div class="screen" @click="showSelect">{{ goodName }}</div>
         <div class="screen" @click="showSelect">{{ goodName }}</div>
@@ -85,6 +86,10 @@
                 </el-option>
                 </el-option>
               </el-select>
               </el-select>
             </div>
             </div>
+            <div class="Layout">
+              <div class="queryName marginLeft">标签</div>
+              <TagSearch v-model="form_all.tagIdList" type="PROEJCT" placeholder="请选择" />
+            </div>
           </el-form>
           </el-form>
         </div>
         </div>
         <div align="right" style="padding-top: 1%;">
         <div align="right" style="padding-top: 1%;">
@@ -329,8 +334,12 @@ import {
   projectCreate
   projectCreate
 } from '@/api/projectIndex'
 } from '@/api/projectIndex'
 import '@/views/projectManage/publicCss/index.css'
 import '@/views/projectManage/publicCss/index.css'
+import TagSearch from '@/components/Tag/TagSearch'
 
 
 export default {
 export default {
+  components: {
+    TagSearch
+  },
   data() {
   data() {
     return {
     return {
       curIndex: 1,
       curIndex: 1,
@@ -390,6 +399,7 @@ export default {
       immediate: true
       immediate: true
     }
     }
   },
   },
+
   created() {
   created() {
     this.$store.state.data.status = true
     this.$store.state.data.status = true
   },
   },

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

@@ -90,6 +90,9 @@
                   <el-option v-for="item in arr_priority" :key="item.value" :label="item.name" :value="item.value" />
                   <el-option v-for="item in arr_priority" :key="item.value" :label="item.name" :value="item.value" />
                 </el-select>
                 </el-select>
               </el-form-item>
               </el-form-item>
+              <el-form-item label="标签:" class="tag-from" style="width: 67%">
+                <Tag v-model="form_query.tags" type="PROEJCT" @change="changeArea" />
+              </el-form-item>
             </el-form>
             </el-form>
           </div>
           </div>
         </section>
         </section>
@@ -232,6 +235,8 @@ import '@/views/projectManage/projectList/css/index.css'
 import drawer from '@/views/projectManage/Drawer'
 import drawer from '@/views/projectManage/Drawer'
 import image_url from '@/assets/home_images/home_u.png'
 import image_url from '@/assets/home_images/home_u.png'
 import bugTableDialog from '@/views/projectManage/bugList/details/bugTableDialog' // 缺陷表格
 import bugTableDialog from '@/views/projectManage/bugList/details/bugTableDialog' // 缺陷表格
+import Tag from '@/components/Tag'
+
 export default {
 export default {
   components: {
   components: {
     record,
     record,
@@ -247,7 +252,8 @@ export default {
     needsList,
     needsList,
     modifyProject,
     modifyProject,
     bugTableDialog,
     bugTableDialog,
-    commentsAndChanges
+    commentsAndChanges,
+    Tag
   },
   },
   filters: {
   filters: {
     ellipsis(value, num) {
     ellipsis(value, num) {
@@ -497,4 +503,7 @@ export default {
 /deep/.el-input--small {
 /deep/.el-input--small {
   font-size: 14px;
   font-size: 14px;
 }
 }
+.el-form-item__content{
+  width: calc(100% - 100px);
+}
 </style>
 </style>

+ 6 - 1
src/views/projectManage/requirement/components/BasicsCode.vue

@@ -139,6 +139,9 @@
           </template>
           </template>
         </over-click>
         </over-click>
       </el-form-item>
       </el-form-item>
+      <el-form-item label="标签:" class="tag-from" style="width: 67%">
+        <Tag v-model="form_query.tags" type="REQUIRE" @change="changeArea" />
+      </el-form-item>
     </el-form>
     </el-form>
 
 
     <el-form :model="form_query" class="demo-form-inline" label-position="left" label-width="100px">
     <el-form :model="form_query" class="demo-form-inline" label-position="left" label-width="100px">
@@ -182,11 +185,13 @@ import { mapGetters } from 'vuex'
 import searchPeople from '@/components/select/searchPeople'
 import searchPeople from '@/components/select/searchPeople'
 import overClick from '@/components/click/overClick'
 import overClick from '@/components/click/overClick'
 import { updateRequirement, iterationList, showRequirementEnum, settingQueryBizRqmtOrntList, projectListProject } from '@/api/requirement.js'
 import { updateRequirement, iterationList, showRequirementEnum, settingQueryBizRqmtOrntList, projectListProject } from '@/api/requirement.js'
+import Tag from '@/components/Tag'
 
 
 export default {
 export default {
   components: {
   components: {
     searchPeople,
     searchPeople,
-    overClick
+    overClick,
+    Tag
   },
   },
   props: {
   props: {
     value: { type: Object, required: true }
     value: { type: Object, required: true }

+ 10 - 2
src/views/projectManage/requirement/list/index.vue

@@ -141,13 +141,19 @@
                   start-placeholder="开始日期"
                   start-placeholder="开始日期"
                   end-placeholder="结束日期"
                   end-placeholder="结束日期"
                   size="small"
                   size="small"
-                  style="min-width: 476px"
+                  style="min-width: 486px"
                   value-format="yyyy-MM-dd HH:mm:ss"
                   value-format="yyyy-MM-dd HH:mm:ss"
                   :default-time="['00:00:00','23:59:59']"
                   :default-time="['00:00:00','23:59:59']"
                   :picker-options="pickerOptions"
                   :picker-options="pickerOptions"
                 />
                 />
               </div>
               </div>
             </el-form>
             </el-form>
+            <el-form :model="searchForm" class="flex_start el-from-spacing">
+              <div class="Layout item">
+                <div class="queryName">标签</div>
+                <TagSearch v-model="searchForm.tagIdList" type="REQUIRE" placeholder="请选择" />
+              </div>
+            </el-form>
             <div v-if="DemandStatus === true" style="color:#409EFF; cursor: pointer; margin-top: 15px;" @click="DemandSta"><i class="el-icon-circle-plus-outline" /> 添加需求状态停留时长条件</div>
             <div v-if="DemandStatus === true" style="color:#409EFF; cursor: pointer; margin-top: 15px;" @click="DemandSta"><i class="el-icon-circle-plus-outline" /> 添加需求状态停留时长条件</div>
             <el-divider v-if="DemandStatus === false"> 且 </el-divider>
             <el-divider v-if="DemandStatus === false"> 且 </el-divider>
             <div v-if="DemandStatus === false" style=" margin-top: 15px;">
             <div v-if="DemandStatus === false" style=" margin-top: 15px;">
@@ -338,6 +344,7 @@ import extraUrgent from '@/assets/extraUrgent.png'
 import normalDialog from '@/components/dialog/normalDialog'
 import normalDialog from '@/components/dialog/normalDialog'
 import rqmtStatus from '@/views/projectManage/components/requirementStatus.vue'
 import rqmtStatus from '@/views/projectManage/components/requirementStatus.vue'
 import '@/views/projectManage/publicCss/index.css'
 import '@/views/projectManage/publicCss/index.css'
+import TagSearch from '@/components/Tag/TagSearch'
 
 
 export default {
 export default {
   components: {
   components: {
@@ -348,7 +355,8 @@ export default {
     chartView,
     chartView,
     filterModal,
     filterModal,
     chartSearchForm,
     chartSearchForm,
-    rqmtStatus
+    rqmtStatus,
+    TagSearch
   },
   },
   data() {
   data() {
     return {
     return {

+ 10 - 3
src/views/projectManage/taskList/taskIndex.vue

@@ -272,11 +272,15 @@
                     />
                     />
                   </el-select>
                   </el-select>
                 </div>
                 </div>
+                <div class="Layout item">
+                  <div class="queryName">标签</div>
+                  <TagSearch v-model="form_task.tagIdList" type="TASK" placeholder="请选择" />
+                </div>
               </el-form>
               </el-form>
             </div>
             </div>
             <div class="Layout" style="margin: 15px 0;">
             <div class="Layout" style="margin: 15px 0;">
               <el-form :model="form_task" class="flex_start">
               <el-form :model="form_task" class="flex_start">
-                <div class="Layout item">
+                <div class="Layout" style="width: 100%">
                   <div class="queryName">创建日期</div>
                   <div class="queryName">创建日期</div>
                   <el-date-picker
                   <el-date-picker
                     v-model="form_task.date"
                     v-model="form_task.date"
@@ -288,7 +292,7 @@
                     end-placeholder="结束日期"
                     end-placeholder="结束日期"
                     size="small"
                     size="small"
                     class="input"
                     class="input"
-                    style="min-width: 458px"
+                    style="min-width: 486px"
                     value-format="yyyy-MM-dd HH:mm:ss"
                     value-format="yyyy-MM-dd HH:mm:ss"
                     :default-time="['00:00:00','23:59:59']"
                     :default-time="['00:00:00','23:59:59']"
                     :picker-options="pickerOptions"
                     :picker-options="pickerOptions"
@@ -509,6 +513,8 @@ import chartSearchFormData from './renderData/chartSearchForm'
 import chartSearchForm from '@/components/searchHeader/searchForm'
 import chartSearchForm from '@/components/searchHeader/searchForm'
 import taskDialog from '@/views/projectManage/taskList/dialog/taskDialog' // 任务状态修改(已上线/已提测/已准出)
 import taskDialog from '@/views/projectManage/taskList/dialog/taskDialog' // 任务状态修改(已上线/已提测/已准出)
 import '@/views/projectManage/publicCss/index.css'
 import '@/views/projectManage/publicCss/index.css'
+import TagSearch from '@/components/Tag/TagSearch'
+
 export default {
 export default {
   components: {
   components: {
     openDialog,
     openDialog,
@@ -518,7 +524,8 @@ export default {
     chartView,
     chartView,
     filterModal,
     filterModal,
     chartSearchForm,
     chartSearchForm,
-    taskDialog
+    taskDialog,
+    TagSearch
   },
   },
   data() {
   data() {
     return {
     return {

+ 15 - 4
src/views/projectManage/taskList/taskViewDetail.vue

@@ -177,6 +177,9 @@
                   <el-progress :percentage="Number(form_query.rate && form_query.rate.substring(0,4)) || 0" color="#409eff" />
                   <el-progress :percentage="Number(form_query.rate && form_query.rate.substring(0,4)) || 0" color="#409eff" />
                 </div>
                 </div>
               </el-form-item>
               </el-form-item>
+              <el-form-item label="标签:" class="tag-from">
+                <Tag v-model="form_query.tags" type="TASK" @change="changeArea" />
+              </el-form-item>
             </el-form>
             </el-form>
             <el-form :inline="true" :model="form_query" class="demo-form-inline" style="white-space: nowrap;" label-position="left" label-width="100px">
             <el-form :inline="true" :model="form_query" class="demo-form-inline" style="white-space: nowrap;" label-position="left" label-width="100px">
               <el-form-item label="技术文档:" class="module">
               <el-form-item label="技术文档:" class="module">
@@ -434,7 +437,7 @@ const _ = require('lodash')
 import Vue from 'vue'
 import Vue from 'vue'
 import VueClipboard from 'vue-clipboard2'
 import VueClipboard from 'vue-clipboard2'
 Vue.use(VueClipboard)
 Vue.use(VueClipboard)
-import { mapGetters } from 'vuex'
+// import { mapGetters } from 'vuex'
 // import store from '@/store'
 // import store from '@/store'
 import { EncryptId, analysisBizId_id } from '@/utils/crypto-js.js'
 import { EncryptId, analysisBizId_id } from '@/utils/crypto-js.js'
 import {
 import {
@@ -482,6 +485,8 @@ import synchronizeDialog from './dialog/synchronizeDialog' // 同步弹框
 import workflowAndStatus from '@/views/projectManage/components/workflowAndStatus.vue'
 import workflowAndStatus from '@/views/projectManage/components/workflowAndStatus.vue'
 import { formatHMS } from '@/utils/global'
 import { formatHMS } from '@/utils/global'
 import testPlan from '@/views/projectManage/components/testPlan.vue'
 import testPlan from '@/views/projectManage/components/testPlan.vue'
+import Tag from '@/components/Tag'
+
 export default {
 export default {
   components: {
   components: {
     searchPeople,
     searchPeople,
@@ -507,6 +512,7 @@ export default {
     synchronizeDialog,
     synchronizeDialog,
     publishTask,
     publishTask,
     testPlan,
     testPlan,
+    Tag,
     checkListStopConfirm // checklist拦截弹窗
     checkListStopConfirm // checklist拦截弹窗
   },
   },
   filters: {
   filters: {
@@ -586,8 +592,8 @@ export default {
   computed: {
   computed: {
     getStatus() {
     getStatus() {
       return this.allStatus.find(item => item.code === this.form_query.status) || { name: null }
       return this.allStatus.find(item => item.code === this.form_query.status) || { name: null }
-    },
-    ...mapGetters(['bizId'])
+    }
+    // ...mapGetters(['bizId'])
   },
   },
   watch: {
   watch: {
     activeName: {
     activeName: {
@@ -790,6 +796,7 @@ export default {
       const res = await taskGet(this.taskId)
       const res = await taskGet(this.taskId)
       if (res.code === 200) {
       if (res.code === 200) {
         this.form_query = res.data
         this.form_query = res.data
+        this.form_query.tags = res.data.tags || []
         if (!this.loaded) {
         if (!this.loaded) {
           this.loaded = true
           this.loaded = true
         }
         }
@@ -1281,5 +1288,9 @@ export default {
   margin: 12px 10px 0 0;
   margin: 12px 10px 0 0;
   width: 300px;
   width: 300px;
 }
 }
-
+.tag-from {
+  .el-form-item__content {
+    width: calc(100% - 100px);
+  }
+}
 </style>
 </style>