wenbobowen 4 jaren geleden
bovenliggende
commit
bb1b561bbd

+ 9 - 0
src/api/requirement.js

@@ -354,3 +354,12 @@ export function requirementUpdatePreOnlineVersion(id) {
     method: 'get'
   })
 }
+
+// 搜索员工信息
+export function getPerson(data) {
+  return request({
+    url: requestIp + `/member/queryMemberInfoByIDAPorName`,
+    method: 'post',
+    data
+  })
+}

+ 2 - 2
src/apiConfig/requestIP.js

@@ -1,5 +1,5 @@
-// export let host = 'http://zhihui-test.intra.xiaojukeji.com'
-export let host = 'http://zhihui-pre.intra.xiaojukeji.com'
+export let host = 'http://zhihui-test.intra.xiaojukeji.com'
+// export let host = 'http://zhihui-pre.intra.xiaojukeji.com'
 export let requestIp = host + '/zuul'
 export let loginUrl = host + '/sso/login?jumpto=' + 'http://zhihui-test.intra.xiaojukeji.com' + location.pathname
 export let logoutUrl = host + '/sso/logout?jumpto=' + 'http://zhihui-test.intra.xiaojukeji.com' + location.pathname

+ 131 - 0
src/components/chartView/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="op-chart">
+    <div class="chartSearchbar inlineBetween">
+      <div class="inlineBetween">
+        <div>
+          <span class="label">分布类型:</span>
+          <el-select
+            v-model="chartSearchData.chartType"
+            size="small"
+            filterable
+            style="width: 100px"
+            @change="$emit('search', 'type', type)"
+          >
+            <el-option v-for="(t, index) in typeOptionList" :key="index" :label="t.label" :value="t.value" />
+          </el-select>
+        </div>
+        <div class="tip">
+          <span class="item">
+            <span class="title">未上线:</span>
+            <span class="num">12</span>
+          </span>
+          <span class="item">
+            <span class="title">未上线:</span>
+            <span class="num">12</span>
+          </span>
+        </div>
+      </div>
+      <div>
+        <slot name="searchBox" />
+      </div>
+      <!-- <el-select
+        v-model="year"
+        size="small"
+        filterable
+        style="width: 80px"
+        @change="$emit('search', 'year', year)"
+      >
+        <el-option v-for="(y, index) in yearList" :key="index" :label="y" :value="y" />
+      </el-select> -->
+    </div>
+    <normal-echart v-if="echartsOption3" :chart-id="'chartThird'" :option="echartsOption3" @onClick="changeList" />
+  </div>
+</template>
+<script>
+import normalEchart from '@/components/chart/normalEchart'
+import { getBarOption } from '@/utils/options'
+export default {
+  components: {
+    normalEchart
+  },
+  props: {
+    data: {
+      type: Object,
+      default: () => {},
+      required: true
+    },
+    chartSearchData: {
+      type: Object,
+      default: null,
+      required: true
+    },
+    typeOptionList: {
+      type: Array,
+      default: () => [],
+      required: false
+    }
+  },
+  data() {
+    return {
+      echartsOption3: null
+    }
+  },
+  watch: {
+    data: {
+      handler(newV) {
+        this.echartsOption3 = getBarOption(newV.xaxis, newV.data)
+      },
+      immediate: true
+    },
+    chartSearchData: {
+      handler(newV) {
+        this.year = newV.year
+        this.type = newV.type
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    // const d = new Date()
+    const { data, xaxis } = this.data
+    this.echartsOption3 = getBarOption(xaxis, data)
+  },
+  methods: {
+    changeList(data) {
+      this.$emit('changeList', data.data.code)
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.op-chart {
+  height: 324px;
+  .chartSearchbar {
+    padding: 0 5%;
+    .label {
+      font-size: 14px;
+      color: #444;
+    }
+    .tip {
+      margin: 0px 25px;
+      .item {
+        margin-right: 15px;
+        .title {
+          font-size: 14px;
+          color: #444;
+        }
+        .num {
+          color: #409EFF;
+          font-size: 18px;
+          font-weight: 600;
+        }
+      }
+    }
+  }
+  .inlineBetween {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+}
+</style>

+ 68 - 0
src/components/filterModal/index.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="coms-filterModal">
+    <el-dialog
+      :title="title"
+      :visible.sync="visible"
+      :width="width"
+      :modal="false"
+      @close="cancel()"
+    >
+      <slot />
+      <span slot="footer" class="dialog-footer">
+        <el-button size="small" @click="cancel()">取 消</el-button>
+        <el-button type="primary" size="small" @click="confirm()">确定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    title: {
+      type: String,
+      default: '',
+      required: false
+    },
+    width: {
+      type: String,
+      default: '450px',
+      required: false
+    },
+    showDialog: {
+      type: Boolean,
+      default: false,
+      required: true
+    }
+  },
+  data() {
+    return {
+      visible: this.showDialog
+    }
+  },
+  watch: {
+    showDialog() {
+      this.visible = this.showDialog
+    }
+  },
+  methods: {
+    confirm() {
+      this.$emit('update:showDialog', this.visible)
+      this.$emit('confirm', true)
+    },
+    cancel() {
+      this.visible = false
+      this.$emit('update:showDialog', this.visible)
+      this.$emit('cancel', false)
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.coms-filterModal {
+  /deep/.el-dialog {
+    margin: 0px!important;
+    margin-left: calc(100% - 470px)!important;
+    top: 110px;
+  }
+}
+</style>

+ 3 - 3
src/views/projectManage/onlineproblem/component/mainTitle.vue → src/components/mainTitle/index.vue

@@ -60,19 +60,19 @@ export default {
   }
 }
 </script>
-<style lang="scss">
+<style scoped lang="scss">
 .wb-mainTitle {
   .titleBox {
     display: flex;
     .radio {
       margin-left: 18px;
-      .el-radio-button__inner {
+      ::v-deep.el-radio-button__inner {
         &:hover {
           color: #606266;
         }
       }
       .is-active {
-        .el-radio-button__inner {
+        ::v-deep.el-radio-button__inner {
           &:hover {
             color: #fff;
           }

+ 10 - 66
src/components/searchHeader/searchBox.vue

@@ -1,69 +1,26 @@
 <template>
   <div class="searchBox">
     <div v-for="(item, index) in list" :key="index" class="row">
-      <div v-for="l in item" :key="l.name" class="Layout" style="display: inline-flex;padding-left: 15px; width:270px;">
-        <div class="name">{{ l.name }}</div>
-        <el-select
-          v-if="l.type === 'select'"
-          v-model="l.value"
-          size="small"
-          :multiple="l.multiple"
-          clearable
-          filterable
-          :placeholder="l.placeholder"
-          @change="$emit('change')"
-        >
-          <el-option v-for="o in l.option" :key="o.value" :label="o.label" :value="o.value" />
-        </el-select>
-        <el-select
-          v-else-if="l.type === 'remoteSelect'"
-          v-model="l.value"
-          filterable
-          remote
-          clearable
-          :placeholder="l.placeholder"
-          :remote-method="(q) => $emit('getOption', l.key, q, l.utilName)"
-          :loading="loading"
-          size="small"
-          @change="$emit('change')"
-        >
-          <!-- <slot v-if="hasSlot" name="option" /> -->
-          <div v-if="l.hasSlot">
-            <el-option v-for="o in l.option" :key="o.value" :label="o.label" :value="o.value">
-              <div class="item-style">
-                <div class="item-detail">{{ o.deptName }}</div>
-                <div style="min-width:80px">{{ o.name }}</div>
-                <div class="item-detail">{{ o.idap }}</div>
-              </div>
-            </el-option>
-          </div>
-          <el-option v-for="o in l.option" v-else :key="o.value" :label="o.label" :value="o.value" />
-        </el-select>
-        <el-input
-          v-else
-          v-model="l.value"
-          style="width: 72% !important"
-          size="small"
-          clearable
-          :placeholder="l.placeholder"
-          @change="$emit('change')"
-        />
-      </div>
+      <searchForm
+        :data="item"
+        :loading="loading"
+        @change="$emit('change')"
+        @getOption="(key, q, utilName) => $emit('getOption', key, q, utilName)"
+      />
     </div>
   </div>
 </template>
 <script>
+import searchForm from './searchForm'
 export default {
+  components: {
+    searchForm
+  },
   props: {
     list: {
       type: Array,
       required: false,
       default: () => []
-    },
-    hasSlot: {
-      type: Boolean,
-      default: false,
-      required: false
     }
   },
   data() {
@@ -82,18 +39,5 @@ export default {
       margin-top: 0;
     }
   }
-  .name {
-    width: 80px;
-  }
-}
-.item-style {
-  display: flex;
-  justify-content: flex-start;
-  .item-detail {
-    min-width:100px;
-    color: #8492a6;
-    font-size: 13px;
-    overflow:hidden
-  }
 }
 </style>

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

@@ -0,0 +1,146 @@
+<template>
+  <div class="searchForm">
+    <div v-for="l in data" :key="l.key" class="Layout" style="display: inline-flex;padding-left: 15px; width:270px;" :style="styles">
+      <div class="name">{{ l.name }}</div>
+      <el-select
+        v-if="l.type === 'select'"
+        v-model="l.value"
+        size="small"
+        :multiple="l.multiple"
+        clearable
+        filterable
+        :placeholder="l.placeholder"
+        class="chooseItem"
+        @change="(e) => $emit('change', l.key, e)"
+      >
+        <el-option v-for="o in l.option" :key="o.value" :label="o.label" :value="o.value" />
+      </el-select>
+      <el-select
+        v-else-if="l.type === 'remoteSelect'"
+        v-model="l.value"
+        filterable
+        remote
+        clearable
+        :placeholder="l.placeholder"
+        :remote-method="(q) => $emit('getOption', l.key, q, l.utilName)"
+        :loading="loading"
+        size="small"
+        class="chooseItem"
+        @change="(e) => $emit('change', l.key, e)"
+      >
+        <!-- <slot v-if="hasSlot" name="option" /> -->
+        <div v-if="l.hasSlot">
+          <el-option v-for="o in l.option" :key="o.idap" :label="o.name" :value="o.idap">
+            <div class="item-style">
+              <div class="item-detail">{{ o.deptName }}</div>
+              <div style="min-width:80px">{{ o.name }}</div>
+              <div class="item-detail">{{ o.idap }}</div>
+            </div>
+          </el-option>
+        </div>
+        <el-option v-for="o in l.option" v-else :key="o.value" :label="o.label" :value="o.value" />
+      </el-select>
+      <el-date-picker
+        v-else-if="l.type === 'dateStartAndEnd'"
+        v-model="l.value"
+        type="daterange"
+        align="right"
+        unlink-panels
+        range-separator="至"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+        size="small"
+        class="chooseItem"
+        value-format="yyyy-MM-dd HH:mm:ss"
+        :default-time="['00:00:00','23:59:59']"
+        :picker-options="pickerOptions"
+        @change="(e) => $emit('change', l.key, e)"
+      />
+      <el-input
+        v-else
+        v-model="l.value"
+        style="width: 72% !important"
+        size="small"
+        class="chooseItem"
+        clearable
+        :placeholder="l.placeholder"
+        @change="(e) => $emit('change', l.key, e)"
+      />
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    data: {
+      type: Array,
+      required: false,
+      default: () => []
+    },
+    loading: {
+      type: Boolean,
+      default: false,
+      required: true
+    },
+    styles: {
+      type: Object,
+      default: () => {},
+      required: false
+    }
+  },
+  data() {
+    return {
+      pickerOptions: {
+        shortcuts: [{
+          text: '最近一周',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+            picker.$emit('pick', [start, end])
+          }
+        }, {
+          text: '最近一个月',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+            picker.$emit('pick', [start, end])
+          }
+        }, {
+          text: '最近三个月',
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+            picker.$emit('pick', [start, end])
+          }
+        }]
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.searchForm {
+  .name {
+    min-width: 80px;
+  }
+  .chooseItem {
+    flex: 1;
+    /deep/.el-range-separator {
+      width: auto;
+    }
+  }
+}
+.item-style {
+  display: flex;
+  justify-content: flex-start;
+  .item-detail {
+    min-width:100px;
+    color: #8492a6;
+    font-size: 13px;
+    overflow:hidden
+  }
+}
+</style>

+ 6 - 3
src/views/projectManage/onlineproblem/component/header/index.vue

@@ -27,9 +27,10 @@
   </div>
 </template>
 <script>
+const _ = require('lodash')
 import searchHeader from '@/components/searchHeader'
 import searchData from './searchData'
-import mainTitle from '../mainTitle'
+import mainTitle from '@/components/mainTitle'
 import chart from '../chart'
 export default {
   components: {
@@ -51,7 +52,7 @@ export default {
   },
   data() {
     return {
-      renderList: searchData,
+      renderList: _.cloneDeep(searchData),
       year: '',
       month: '',
       nowTab: 'list',
@@ -89,6 +90,7 @@ export default {
     },
     async search(key, value) {
       const data = {}
+      // 因为高级筛选不自动搜索,所以每次出发搜索都map renderList就好。
       this.renderList.default.map(t => t.map(g => {
         data[g.key] = g.value
       }))
@@ -97,7 +99,8 @@ export default {
           data[g.key] = g.value
         }))
       }
-      if (key) {
+      // 如果是年和月更新全局的变量
+      if (key === 'month' || key === 'year') {
         this[key] = value === '全部' ? '0' : value
       }
       data.year = '' + this.year

+ 1 - 1
src/views/projectManage/onlineproblem/create/index.vue

@@ -61,7 +61,7 @@
 </template>
 <script>
 import { create } from '@/api/onlineproblem'
-import mainTitle from '../component/mainTitle'
+import mainTitle from '@/components/mainTitle'
 import headTitle from '@/components/headTitle'
 import baseBox from './component/base'
 import makeBetterList from './component/makeBetterList'

+ 292 - 146
src/views/projectManage/requirement/list/index.vue

@@ -1,149 +1,189 @@
 <template>
   <div class="sos" style="background-color:#F2F3F6;min-height:calc(100vh - 80px);padding:0 10px 10px 10px">
     <div class="stylus-head">
-      <div class="stylus-title">
-        <span style="font-size: 22px;letter-spacing: 1px;font-weight: 600;color: #333B4A;padding-left: 15px">需求</span>
-        <div class="new-tab-open">
-          <!-- 这个可以放按钮 -->
-        </div>
-        <el-button type="primary" size="mini" @click="createDialogVisible = true">新建需求</el-button>
-      </div>
-      <el-divider style="color: #EEF0F5;" />
-      <div class="Layout" style="padding-top: 5px">
-        <div>
-          <el-form :model="searchForm" class="Layout">
-            <div class="Layout_flex_end" style="padding-left:15px">
-              <div class="queryName">需求名称</div>
-              <el-input v-model="requirementName" size="small" clearable style="width:72% !important;" placeholder="请搜索标题或ID或望岳ID" @change="getTableData()" />
-            </div>
+      <mainTitle
+        title="需求"
+        btn-text="新建需求"
+        :tab-show="true"
+        @btn-handle="createDialogVisible = true"
+        @change-tab="changeTab"
+      />
+      <div v-if="nowTab === 'charts'" class="chartView">
+        <chartView
+          :data="chartData"
+          :type-option-list="typeOptionList"
+          :chart-search-data="searchForm"
+          @changeList="(code) => console.log(code)"
+        >
+          <div slot="searchBox">
             <div class="Layout">
-              <div class="queryName marginLeft">需求状态</div>
-              <el-select v-model="searchForm.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="getTableData()">
-                <el-option v-for="(item, index) in requiredStatus" :key="index" :label="item.msg" :value="item.code" />
-              </el-select>
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">需求方向</div>
-              <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="getTableData()" />
+              <div class="Layout">
+                <div class="queryName marginLeft">需求方向</div>
+                <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="getTableData()" />
+              </div>
+              <span class="screen" @click="showChartModal = true">更多筛选</span>
             </div>
-          </el-form>
-        </div>
-        <span class="screen" @click="showSelect">{{ goodName }}</span>
+          </div>
+        </chartView>
       </div>
-      <div v-show="DetailedScreening" class="stylus-more">
-        <div>
-          <el-form :model="searchForm" class="flex_start">
-            <div class="Layout">
-              <div class="queryName">所属项目</div>
-              <el-select v-model="searchForm.belongingProject" size="small" clearable filterable placeholder="请选择">
-                <el-option v-for="item in AttributionItems" :key="item.id" :label="item.name" :value="item.id" />
-              </el-select>
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">PM</div>
-              <search-people :value.sync="searchForm.pm" :clearable="true" :multiple="false" style="width:72% !important;" />
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">需求类型</div>
-              <el-select v-model="searchForm.type" size="small" clearable filterable placeholder="请选择">
-                <el-option v-for="item in searchInfo.type" :key="item.code" :label="item.msg" :value="item.code" />
-              </el-select>
-            </div>
-          </el-form>
-          <el-form :model="searchForm" class="flex_start el-from-spacing">
-            <div class="Layout">
-              <div class="queryName">需求来源</div>
-              <el-select v-model="searchForm.sourceTypeList" size="small" multiple clearable filterable placeholder="请选择">
-                <el-option v-for="item in searchInfo.sourceType" :key="item.code" :label="item.msg" :value="item.code" />
-              </el-select>
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">优先级</div>
-              <el-select v-model="searchForm.priorityList" size="small" multiple clearable filterable placeholder="请选择">
-                <el-option v-for="item in searchInfo.priority" :key="item.code" :label="item.msg" :value="item.code" />
+      <div v-if="nowTab === 'list'" class="search_box">
+        <div class="Layout" style="padding-top: 5px">
+          <div>
+            <el-form :model="searchForm" class="Layout">
+              <div class="Layout_flex_end" style="padding-left:15px">
+                <div class="queryName">需求名称</div>
+                <el-input v-model="searchForm.name" size="small" clearable style="width:72% !important;" placeholder="请搜索标题或ID或望岳ID" @change="getTableData()" />
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">需求状态</div>
+                <el-select v-model="searchForm.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="getTableData()">
+                  <el-option v-for="(item, index) in requiredStatus" :key="index" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">需求方向</div>
+                <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="getTableData()" />
+              </div>
+            </el-form>
+          </div>
+          <span class="screen" @click="showSelect">{{ goodName }}</span>
+        </div>
+        <div v-show="DetailedScreening" class="stylus-more">
+          <div>
+            <el-form :model="searchForm" class="flex_start">
+              <div class="Layout">
+                <div class="queryName">所属项目</div>
+                <el-select v-model="searchForm.belongingProject" size="small" clearable filterable placeholder="请选择">
+                  <el-option v-for="item in AttributionItems" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">PM</div>
+                <!-- <search-people :value.sync="searchForm.pm" :clearable="true" :multiple="false" style="width:72% !important;" /> -->
+                <el-select
+                  v-model="searchForm.pm"
+                  clearable
+                  filterable
+                  remote
+                  placeholder="请输入姓名或邮箱前缀"
+                  :remote-method="remoteMethod"
+                  :loading="loading"
+                  size="small"
+                >
+                  <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="item.idap">
+                    <div class="flex_start">
+                      <div class="deptName">{{ item.deptName }}</div>
+                      <div style="min-width:80px">{{ item.name }}</div>
+                      <div class="deptName">{{ item.idap }}</div>
+                    </div>
+                  </el-option>
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">需求类型</div>
+                <el-select v-model="searchForm.type" size="small" clearable filterable placeholder="请选择">
+                  <el-option v-for="item in searchInfo.type" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+            </el-form>
+            <el-form :model="searchForm" class="flex_start el-from-spacing">
+              <div class="Layout">
+                <div class="queryName">需求来源</div>
+                <el-select v-model="searchForm.sourceTypeList" size="small" multiple clearable filterable placeholder="请选择">
+                  <el-option v-for="item in searchInfo.sourceType" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">优先级</div>
+                <el-select v-model="searchForm.priorityList" size="small" multiple clearable filterable placeholder="请选择">
+                  <el-option v-for="item in searchInfo.priority" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName marginLeft">需求提出人</div>
+                <!-- <search-people :value.sync="searchForm.rqmtProposer" :clearable="true" :multiple="false" style="width:72% !important;" /> -->
+                <el-select
+                  v-model="searchForm.rqmtProposer"
+                  clearable
+                  filterable
+                  remote
+                  placeholder="请输入姓名或邮箱前缀"
+                  :remote-method="remoteMethod"
+                  :loading="loading"
+                  size="small"
+                >
+                  <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="item.idap">
+                    <div class="flex_start">
+                      <div class="deptName">{{ item.deptName }}</div>
+                      <div style="min-width:80px">{{ item.name }}</div>
+                      <div class="deptName">{{ item.idap }}</div>
+                    </div>
+                  </el-option>
+                </el-select>
+              </div>
+            </el-form>
+            <el-form :model="searchForm" class="flex_start el-from-spacing">
+              <div class="Layout">
+                <div class="queryName">来自望岳</div>
+                <el-select v-model="searchForm.isFromDpm" size="small" clearable filterable placeholder="请选择">
+                  <el-option v-for="item in isFromDpmList" :key="item.value" :label="item.label" :value="item.value" />
+                </el-select>
+              </div>
+              <div class="Layout">
+                <div class="queryName" style="margin-left: 2%;">创建时间</div>
+                <el-date-picker
+                  v-model="searchForm.date"
+                  type="daterange"
+                  align="right"
+                  unlink-panels
+                  range-separator="至"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  size="small"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  :default-time="['00:00:00','23:59:59']"
+                  :picker-options="pickerOptions"
+                />
+              </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>
+            <el-divider v-if="DemandStatus === false"> 且 </el-divider>
+            <div v-if="DemandStatus === false" style=" margin-top: 15px;">
+              <div class="DemandStatus">
+                <i style="color:#409EFF; cursor: pointer; margin-right: 5px;" class="el-icon-remove-outline" @click="DemandSta" />
+                <span> 需求状态包含:</span>
+              </div>
+              <el-checkbox-group v-model="searchForm.containStatus" class="allCheckbox">
+                <el-checkbox v-for="item in requiredStatus" :key="item.value" :value="item.value">{{ item.label }}</el-checkbox>
+              </el-checkbox-group>
+              <div class="DemandStatus">状态停留时长:</div>
+              <el-select v-model="searchForm.comparisonOperator" size="small" style="width: 80px; margin: 20px 20px 0 79px;" clearable filterable placeholder="请选择">
+                <el-option v-for="item in formula" :key="item.code" :label="item.msg" :value="item.msg" />
               </el-select>
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">需求提出人</div>
-              <search-people :value.sync="searchForm.rqmtProposer" :clearable="true" :multiple="false" style="width:72% !important;" />
-            </div>
-          </el-form>
-          <el-form :model="searchForm" class="flex_start el-from-spacing">
-            <div class="Layout">
-              <div class="queryName">来自望岳</div>
-              <el-select v-model="searchForm.isFromDpm" size="small" clearable filterable placeholder="请选择">
-                <el-option v-for="item in isFromDpmList" :key="item.id" :label="item.name" :value="item.id" />
+              <el-select v-model="searchForm.days" size="small" style="width: 80px;" clearable filterable placeholder="请选择">
+                <el-option v-for="item in getArrayList()" :key="item.code" :label="item.msg" :value="item.code" />
               </el-select>
             </div>
-            <div class="Layout">
-              <div class="queryName" style="margin-left: 2%;">创建时间</div>
-              <el-date-picker
-                v-model="searchForm.date"
-                type="daterange"
-                align="right"
-                unlink-panels
-                range-separator="至"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                size="small"
-                value-format="yyyy-MM-dd HH:mm:ss"
-                :default-time="['00:00:00','23:59:59']"
-                :picker-options="pickerOptions"
-              />
-            </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>
-          <el-divider v-if="DemandStatus === false"> 且 </el-divider>
-          <div v-if="DemandStatus === false" style=" margin-top: 15px;">
-            <div class="DemandStatus">
-              <i style="color:#409EFF; cursor: pointer; margin-right: 5px;" class="el-icon-remove-outline" @click="DemandSta" />
-              <span> 需求状态包含:</span>
-            </div>
-            <el-checkbox-group v-model="searchForm.containStatus" class="allCheckbox">
-              <el-checkbox v-for="item in requiredStatus" :key="item.code" :label="item.code">{{ item.msg }}</el-checkbox>
-            </el-checkbox-group>
-            <div class="DemandStatus">状态停留时长:</div>
-            <el-select v-model="searchForm.comparisonOperator" size="small" style="width: 80px; margin: 20px 20px 0 79px;" clearable filterable placeholder="请选择">
-              <el-option v-for="item in formula" :key="item.code" :label="item.msg" :value="item.msg" />
-            </el-select>
-            <el-select v-model="searchForm.days" size="small" style="width: 80px;" clearable filterable placeholder="请选择">
-              <el-option v-for="item in getArrayList()" :key="item.code" :label="item.msg" :value="item.code" />
-            </el-select>
-          </div>
 
-          <div align="right">
-            <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
-            <el-button type="primary" size="mini" @click="getTableData">筛 选</el-button>
-            <el-button size="mini" @click="reset">重 置</el-button>
+            <div align="right">
+              <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
+              <el-button type="primary" size="mini" @click="getTableData">筛 选</el-button>
+              <el-button size="mini" @click="reset">重 置</el-button>
+            </div>
           </div>
         </div>
-      </div>
-      <div v-if="filterList.length && filterList.length > 0" class="filter">
-        <div class="filterWrap">
-          <div class="title">我的过滤器:</div>
-          <div class="itemBox">
-            <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
+        <div v-if="filterList.length && filterList.length > 0" class="filter">
+          <div class="filterWrap">
+            <div class="title">我的过滤器:</div>
+            <div class="itemBox">
+              <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
+            </div>
+          </div>
+          <div class="btn">
+            <span @click.stop="showEditSearch = true">管理过滤器</span>
           </div>
-        </div>
-        <div class="btn">
-          <span @click.stop="showEditSearch = true">管理过滤器</span>
         </div>
       </div>
-      <!-- <el-row v-if="filterList.length && filterList.length>0" type="flex" justify="space-between" class="filter">
-        <el-col :span="2">
-          <span>我的过滤器:</span>
-        </el-col>
-        <el-col :span="20" class="mine-filter">
-          <span v-for="item in filterList" :key="item.id" class="filter-item" @click="getFilterItem(item.id)">
-            <el-tooltip class="item" effect="dark" :content="item.name" placement="bottom">
-              <span>{{ item.name }}</span>
-            </el-tooltip>
-          </span>
-        </el-col>
-        <el-col :span="2" align="end">
-          <span @click.stop="showEditSearch = true">管理过滤器</span>
-        </el-col>
-      </el-row> -->
     </div>
     <div class="stylus-content">
       <el-table
@@ -227,10 +267,22 @@
     <normal-dialog :show-footer="false" :show-dialog="showEditSearch" :title="'管理过滤器'" :width="'65%'" @cancel="showEditSearch=false">
       <filter-list :show-filter="showEditSearch" @deleteFilter="deleteFilter" />
     </normal-dialog>
+    <filterModal :show-dialog="showChartModal" @cancel="showChartModal = false">
+      <div>
+        <chartSearchForm
+          :data="chartSearchFormRenderData"
+          :loading="loading"
+          :styles="{ marginBottom: '15px', width: '380px' }"
+          @change="chartSearchFormChange"
+          @getOption="(key, q, utilName) => remoteMethod(q)"
+        />
+      </div>
+    </filterModal>
   </div>
 </template>
 
 <script>
+const _ = require('lodash')
 import { EncryptId } from '@/utils/crypto-js.js'
 import { mapGetters } from 'vuex'
 import {
@@ -241,13 +293,18 @@ import {
   settingQueryBizRqmtOrntList,
   filterCreateFilter,
   filtergetFilterList,
-  filterGetFilter
+  filterGetFilter,
+  getPerson
 } from '@/api/requirement.js'
 import { deepClone } from '@/utils/global'
 import RequirementCreate from './create'
+import mainTitle from '@/components/mainTitle'
+import chartView from '@/components/chartView'
+import filterModal from '@/components/filterModal'
+import chartSearchFormData from '../renderData/chartSearchForm'
+import chartSearchForm from '@/components/searchHeader/searchForm'
 import filterList from '@/views/projectManage/components/filterList'
 import extraUrgent from '@/assets/extraUrgent.png'
-import searchPeople from '@/components/select/searchPeople'
 import normalDialog from '@/components/dialog/normalDialog'
 import '@/views/projectManage/publicCss/index.css'
 import '@/styles/PublicStyle/index.scss'
@@ -255,9 +312,12 @@ import '@/styles/PublicStyle/index.scss'
 export default {
   components: {
     RequirementCreate,
-    searchPeople,
     normalDialog,
-    filterList
+    filterList,
+    mainTitle,
+    chartView,
+    filterModal,
+    chartSearchForm
   },
   data() {
     return {
@@ -291,7 +351,7 @@ export default {
       // newTabOpen: true, // 是否新的tab页打开
       DemandStatus: true, // 筛选需求时长
       extraUrgent: extraUrgent,
-      isFromDpmList: [{ id: true, name: '是' }, { id: false, name: '否' }],
+      isFromDpmList: [{ value: true, label: '是' }, { value: false, label: '否' }],
       priorityColors: ['#F56C6C', '#FF8952', '#F5E300', '#7ED321', '#61D3B8', '#69B3FF', '#BDBDBD'],
       formula: [{ code: 0, msg: '>=' }, { code: 1, msg: '<=' }, { code: 2, msg: '>' }, { code: 3, msg: '<' }],
       // currentRow: null,
@@ -312,7 +372,6 @@ export default {
         bizType: [],
         priority: []
       },
-      requirementName: '',
       goodName: '更多筛选',
       DetailedScreening: false,
       searchFormRules: { name: [
@@ -333,7 +392,17 @@ export default {
       tableData: [], // 需求tableList
       createDialogVisible: false,
       total: 0,
-      data: ''
+      data: '',
+      options: [],
+      nowTab: 'list',
+      chartData: {},
+      typeOptionList: [
+        { value: '0', label: '需求状态' },
+        { value: '1', label: '需求等级' },
+        { value: '2', label: '需求类型' }
+      ],
+      showChartModal: false,
+      chartSearchFormRenderData: _.cloneDeep(chartSearchFormData)
     }
   },
   computed: {
@@ -353,6 +422,9 @@ export default {
   created() {
     this.$store.state.data.status = true
   },
+  mounted() {
+    this.updateChartSlectOption('isFromDpm', this.isFromDpmList)
+  },
   destroyed() {
     this.$store.state.data.status = false
   },
@@ -360,6 +432,16 @@ export default {
     logHandle(d) {
       window.log({ c: 'requirement', d })
     },
+    changeTab(e) {
+      this.nowTab = e
+      if (this.nowTab === 'charts') {
+        // this.$emit('chartSearch')
+        this.updateChartSearchFormValue()
+        console.log('charts')
+      } else {
+        this.getTableData()
+      }
+    },
     getTableData() { // 查询
       if (this.bizId === -1) return
       for (const key in this.searchForm) { // 接口不接受空值的处理
@@ -367,11 +449,11 @@ export default {
           delete this.searchForm[key]
         }
       }
-      if (this.requirementName) { // 判断需求名称
-        this.searchForm.name = this.requirementName
-      } else {
-        this.searchForm.name = ''
-      }
+      // if (this.requirementName) { // 判断需求名称
+      //   this.searchForm.name = this.requirementName
+      // } else {
+      //   this.searchForm.name = ''
+      // }
       if (this.searchForm.date) {
         this.searchForm.createStartTime = this.searchForm.date[0]
         this.searchForm.createEndTime = this.searchForm.date[1]
@@ -394,15 +476,45 @@ export default {
     async showRequirementEnum() {
       const res = await showRequirementEnum()
       if (res.code === 200) {
+        // 类型
+        res.data.type.map(t => {
+          t.value = t.code
+          t.label = t.msg
+        })
+        // 来源
+        res.data.sourceType.map(t => {
+          t.value = t.code
+          t.label = t.msg
+        })
+        // 优先级
+        res.data.priority.map(t => {
+          t.value = t.code
+          t.label = t.msg
+        })
         this.searchInfo = res.data
+        this.updateChartSlectOption('type', res.data.type)
+        this.updateChartSlectOption('sourceTypeList', res.data.sourceType)
+        this.updateChartSlectOption('priorityList', res.data.priority)
       }
       const res1 = await projectListProject({ bizId: this.bizId })
       if (res1.code === 200) {
-        this.AttributionItems = res1.data
+        const AttributionItems = res1.data.map(t => ({
+          ...t,
+          label: t.name,
+          value: t.id
+        }))
+        this.AttributionItems = AttributionItems
+        this.updateChartSlectOption('belongingProject', AttributionItems)
       }
       const res2 = await configShowRequireStatusEnum(this.bizId)
       if (res2.code === 200) {
-        this.requiredStatus = res2.data.requirementStatus
+        const requiredStatus = res2.data.requirementStatus.map(t => ({
+          ...t,
+          label: t.msg,
+          value: t.code
+        }))
+        this.requiredStatus = requiredStatus
+        this.updateChartSlectOption('statusList', requiredStatus)
       }
       const res3 = await settingQueryBizRqmtOrntList(this.bizId)
       if (res3.code === 200) { // 需求方向
@@ -502,7 +614,7 @@ export default {
         // }
         // this.getClient(filter.appId)
         Object.assign(this.searchForm, filter)
-        this.requirementName = filter.name
+        // this.requirementName = filter.name
         this.curIndex = 1
         this.getTableData()
       }
@@ -545,6 +657,23 @@ export default {
       })
       this.getTableData()
     },
+    async remoteMethod(query) {
+      // 人员查询
+      if (query !== '') {
+        // this.loading = true
+        const res = await getPerson({ memberIDAP: query })
+        const obj = {}
+        this.options = res.data.reduce((cur, next) => {
+          obj[next.idap] ? '' : obj[next.idap] = true && cur.push(next)
+          return cur
+        }, [])
+        // this.loading = false
+      } else {
+        this.options = []
+      }
+      this.updateChartSlectOption('pm', this.options)
+      this.updateChartSlectOption('rqmtProposer', this.options)
+    },
     getToRequirementDetails(id) { // table点击跳转
       const bizId_id = EncryptId(`${this.bizId}_${id}`)
       if (localStorage.getItem('openPageHandle') === 'blank') {
@@ -553,6 +682,23 @@ export default {
       } else {
         this.$router.push({ name: '需求详情', query: { bizId_id: bizId_id }})
       }
+    },
+    chartSearchFormChange(key, value) {
+      console.log(key, value, this.chartSearchFormRenderData)
+      this.searchForm[key] = value
+    },
+    updateChartSlectOption(key, option) {
+      this.chartSearchFormRenderData.map(t => {
+        if (t.key === key) {
+          t.option = option
+        }
+      })
+    },
+    updateChartSearchFormValue() {
+      this.chartSearchFormRenderData.map(t => {
+        t.value = this.searchForm[t.key]
+      })
+      console.log(this.searchForm, this.chartSearchFormRenderData)
     }
   }
 }

+ 92 - 0
src/views/projectManage/requirement/renderData/chartSearchForm.js

@@ -0,0 +1,92 @@
+const data = [
+  {
+    name: '需求名称',
+    key: 'name',
+    value: '',
+    placeholder: '请输入标题或ID或望岳ID',
+    type: 'input'
+  },
+  {
+    name: '需求状态',
+    key: 'statusList',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: true,
+    value: [],
+    option: [] // label===msg  value ===code
+  },
+  {
+    name: '所属项目',
+    key: 'belongingProject',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: [] // label===name  value ===id
+  },
+  {
+    name: 'PM',
+    key: 'pm',
+    type: 'remoteSelect',
+    multiple: false,
+    hasSlot: true,
+    utilName: 'getPerson',
+    placeholder: '请输入姓名或邮箱前缀',
+    value: '',
+    option: []
+  },
+  {
+    name: '需求类型',
+    key: 'type',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: [] // label===name  value ===id
+  },
+  {
+    name: '需求来源',
+    key: 'sourceTypeList',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: true,
+    value: [],
+    option: []
+  },
+  {
+    name: '优先级',
+    key: 'priorityList',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: true,
+    value: [],
+    option: [] // label===msg  value ===code
+  },
+  {
+    name: '需求提出人',
+    key: 'rqmtProposer',
+    type: 'remoteSelect',
+    multiple: false,
+    hasSlot: true,
+    utilName: 'getPerson',
+    placeholder: '请输入姓名或邮箱前缀',
+    value: '',
+    option: []
+  },
+  {
+    name: '来自望岳',
+    key: 'isFromDpm',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: null,
+    option: []
+  },
+  {
+    name: '创建日期',
+    key: 'date',
+    type: 'dateStartAndEnd',
+    value: []
+  }
+]
+export default data

+ 92 - 0
src/views/projectManage/taskList/renderData/chartSearchForm.js

@@ -0,0 +1,92 @@
+const data = [
+  {
+    name: '任务名称',
+    key: 'name',
+    value: '',
+    placeholder: '请输入标题或ID或望岳ID',
+    type: 'input'
+  },
+  {
+    name: '状态',
+    key: 'statusList',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: true,
+    value: '',
+    option: [] // label===msg  value ===code
+  },
+  {
+    name: '所属项目',
+    key: 'projectId',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: [] // label===name  value ===id
+  },
+  {
+    name: '所属需求',
+    key: 'requireId',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: [] // label===name  value ===id
+  },
+  {
+    name: '优先级',
+    key: 'priority',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: []
+  },
+  {
+    name: '负责人',
+    key: 'PersonInCharge',
+    type: 'remoteSelect',
+    multiple: false,
+    hasSlot: true,
+    utilName: 'getPerson',
+    placeholder: '请输入姓名或邮箱前缀',
+    value: '',
+    option: []
+  },
+  {
+    name: '健康状态',
+    key: 'stage',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: [] // label===msg  value ===code
+  },
+  {
+    name: '创建人',
+    key: 'creater',
+    type: 'remoteSelect',
+    multiple: false,
+    hasSlot: true,
+    utilName: 'getPerson',
+    placeholder: '请输入姓名或邮箱前缀',
+    value: '',
+    option: []
+  },
+  {
+    name: '来自望岳',
+    key: 'isFromDpm',
+    placeholder: '请选择',
+    type: 'select',
+    multiple: false,
+    value: '',
+    option: []
+  },
+  {
+    name: '创建日期',
+    key: 'date',
+    type: 'dateStartAndEnd',
+    value: []
+  }
+]
+export default data

+ 267 - 161
src/views/projectManage/taskList/taskIndex.vue

@@ -1,160 +1,173 @@
 <template>
   <div class="bgborder" style="background-color:#F2F3F6;min-height:calc(100vh - 80px);padding:0 10px 10px 10px">
     <div class="stylus-head">
-      <div class="stylus-title">
-        <span style="font-size: 22px;letter-spacing: 1px;font-weight: 600;color: #333B4A;padding-left: 15px">任务</span>
-        <div class="new-tab-open">
-          <!-- 这个可以放按钮 -->
-        </div>
-        <div>
-          <el-button
-            type="primary"
-            size="mini"
-            @click="open_created"
-          >新建任务</el-button>
-        </div>
-      </div>
-      <el-divider style="color: #EEF0F5;" />
-      <div class="Layout" style="padding: 5px 0 0 15px">
-        <div>
-          <el-form :model="form_task" class="Layout">
-            <div class="Layout_flex_end">
-              <div class="queryName">任务名称</div>
-              <el-input v-model="form_task.name" size="small" clearable style="width:72% !important;" placeholder="请输入标题或ID或望岳ID" @change="get_taskList()" />
-            </div>
+      <mainTitle
+        title="任务"
+        btn-text="新建任务"
+        :tab-show="true"
+        @btn-handle="open_created"
+        @change-tab="changeTab"
+      />
+      <div v-if="nowTab === 'charts'" class="chartView">
+        <chartView
+          :data="chartData"
+          :type-option-list="typeOptionList"
+          :chart-search-data="form_task"
+          @changeList="(code) => console.log(code)"
+        >
+          <div slot="searchBox">
             <div class="Layout">
-              <div class="queryName marginLeft">状态</div>
-              <el-select v-model="form_task.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="get_taskList()">
-                <el-option v-for="item in daStatus" :key="item.code" :label="item.msg" :value="item.code" />
-              </el-select>
-            </div>
-            <div class="Layout">
-              <div class="queryName marginLeft">模块</div>
-              <el-cascader v-model="form_task.moduleIds" size="small" clearable collapse-tags :props="props" :options="business_platform_Modular" placeholder="请选择" style="width:77% !important;" @change="get_taskList()" />
-            </div>
-          </el-form>
-        </div>
-        <span class="screen" @click="showSelect">{{ goodName }}</span>
-      </div>
-      <div v-show="DetailedScreening" class="stylus-more">
-        <div>
-          <div class="Layout">
-            <el-form :model="form_task" class="flex_start">
               <div class="Layout">
-                <div class="queryName">所属项目</div>
-                <el-select v-model="form_task.projectId" size="small" clearable filterable placeholder="请选择">
-                  <el-option v-for="item in projectList" :key="item.id" :label="item.name" :value="item.id" />
-                </el-select>
-              </div>
-              <div class="Layout marginLeft">
-                <div class="queryName">所属需求</div>
-                <el-select v-model="form_task.requireId" size="small" clearable filterable placeholder="请选择">
-                  <el-option v-for="item in demandList" :key="item.id" :label="item.name" :value="item.id" />
-                </el-select>
-              </div>
-              <div class="Layout marginLeft">
-                <div class="queryName">来自望岳</div>
-                <el-select v-model="form_task.isFromDpm" size="small" clearable filterable placeholder="请选择">
-                  <el-option v-for="item in isFromDpmList" :key="item.id" :label="item.name" :value="item.id" />
-                </el-select>
+                <div class="chartSearchTitle">模块:</div>
+                <el-cascader v-model="form_task.moduleIds" size="small" clearable collapse-tags :props="props" :options="business_platform_Modular" placeholder="请选择" style="width:77% !important;" @change="get_taskList()" />
               </div>
-            </el-form>
+              <span class="screen" @click="showChartModal = true">更多筛选</span>
+            </div>
           </div>
-          <div class="Layout" style="margin: 15px 0;">
-            <el-form :model="form_task" class="flex_start">
-              <div class="Layout">
-                <div class="queryName">优先级</div>
-                <el-select v-model="form_task.priority" size="small" clearable filterable placeholder="请选择">
-                  <el-option v-for="item in arr_priority" :key="item.value" :label="item.name" :value="item.value" />
-                </el-select>
-              </div>
-              <div class="Layout marginLeft">
-                <div class="queryName">负责人</div>
-                <el-select
-                  v-model="form_task.PersonInCharge"
-                  clearable
-                  filterable
-                  remote
-                  placeholder="请输入姓名或邮箱前缀"
-                  :remote-method="remoteMethod"
-                  :loading="loading"
-                  size="small"
-                >
-                  <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
-                    <div class="flex_start">
-                      <div class="deptName">{{ item.deptName }}</div>
-                      <div style="min-width:80px">{{ item.name }}</div>
-                      <div class="deptName">{{ item.idap }}</div>
-                    </div>
-                  </el-option>
-                </el-select>
-              </div>
-              <div class="Layout marginLeft">
-                <div class="queryName">健康状态</div>
-                <el-select v-model="form_task.stage" size="small" clearable filterable placeholder="请选择">
-                  <el-option v-for="item in healthStage" :key="item.code" :label="item.msg" :value="item.code" />
-                </el-select>
+        </chartView>
+      </div>
+      <div v-if="nowTab === 'list'" class="search_box">
+        <div class="Layout" style="padding: 5px 0 0 15px">
+          <div>
+            <el-form :model="form_task" class="Layout">
+              <div class="Layout_flex_end">
+                <div class="queryName">任务名称</div>
+                <el-input v-model="form_task.name" size="small" clearable style="width:72% !important;" placeholder="请输入标题或ID或望岳ID" @change="get_taskList()" />
               </div>
-            </el-form>
-          </div>
-          <div class="Layout" style="margin: 15px 0;">
-            <el-form :model="form_task" class="flex_start">
               <div class="Layout">
-                <div class="queryName" style="width:86px;">创建人</div>
-                <el-select
-                  v-model="form_task.creater"
-                  clearable
-                  filterable
-                  remote
-                  placeholder="请输入姓名或邮箱前缀"
-                  :remote-method="remoteMethod"
-                  :loading="loading"
-                  size="small"
-                  style="width: 82%;"
-                >
-                  <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
-                    <div class="flex_start">
-                      <div class="deptName">{{ item.deptName }}</div>
-                      <div style="min-width:80px">{{ item.name }}</div>
-                      <div class="deptName">{{ item.idap }}</div>
-                    </div>
-                  </el-option>
+                <div class="queryName marginLeft">状态</div>
+                <el-select v-model="form_task.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="get_taskList()">
+                  <el-option v-for="item in daStatus" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
               </div>
-              <div class="Layout marginLeft">
-                <div class="queryName">创建日期</div>
-                <el-date-picker
-                  v-model="form_task.date"
-                  type="daterange"
-                  align="right"
-                  unlink-panels
-                  range-separator="至"
-                  start-placeholder="开始日期"
-                  end-placeholder="结束日期"
-                  size="small"
-                  value-format="yyyy-MM-dd HH:mm:ss"
-                  :default-time="['00:00:00','23:59:59']"
-                  :picker-options="pickerOptions"
-                />
+              <div class="Layout">
+                <div class="queryName marginLeft">模块</div>
+                <el-cascader v-model="form_task.moduleIds" size="small" clearable collapse-tags :props="props" :options="business_platform_Modular" placeholder="请选择" style="width:77% !important;" @change="get_taskList()" />
               </div>
             </el-form>
           </div>
-          <div align="right">
-            <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
-            <el-button type="primary" size="mini" @click="get_taskList(form_task)">筛 选</el-button>
-            <el-button size="mini" @click="query_Reset">重 置</el-button>
-          </div>
+          <span class="screen" @click="showSelect">{{ goodName }}</span>
         </div>
-      </div>
-      <div v-if="filterList.length && filterList.length > 0" class="filter">
-        <div class="filterWrap">
-          <div class="title">我的过滤器:</div>
-          <div class="itemBox">
-            <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
+        <div v-show="DetailedScreening" class="stylus-more">
+          <div>
+            <div class="Layout">
+              <el-form :model="form_task" class="flex_start">
+                <div class="Layout">
+                  <div class="queryName">所属项目</div>
+                  <el-select v-model="form_task.projectId" size="small" clearable filterable placeholder="请选择">
+                    <el-option v-for="item in projectList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </div>
+                <div class="Layout marginLeft">
+                  <div class="queryName">所属需求</div>
+                  <el-select v-model="form_task.requireId" size="small" clearable filterable placeholder="请选择">
+                    <el-option v-for="item in demandList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </div>
+                <div class="Layout marginLeft">
+                  <div class="queryName">来自望岳</div>
+                  <el-select v-model="form_task.isFromDpm" size="small" clearable filterable placeholder="请选择">
+                    <el-option v-for="item in isFromDpmList" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </div>
+              </el-form>
+            </div>
+            <div class="Layout" style="margin: 15px 0;">
+              <el-form :model="form_task" class="flex_start">
+                <div class="Layout">
+                  <div class="queryName">优先级</div>
+                  <el-select v-model="form_task.priority" size="small" clearable filterable placeholder="请选择">
+                    <el-option v-for="item in arr_priority" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </div>
+                <div class="Layout marginLeft">
+                  <div class="queryName">负责人</div>
+                  <el-select
+                    v-model="form_task.PersonInCharge"
+                    clearable
+                    filterable
+                    remote
+                    placeholder="请输入姓名或邮箱前缀"
+                    :remote-method="remoteMethod"
+                    :loading="loading"
+                    size="small"
+                  >
+                    <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
+                      <div class="flex_start">
+                        <div class="deptName">{{ item.deptName }}</div>
+                        <div style="min-width:80px">{{ item.name }}</div>
+                        <div class="deptName">{{ item.idap }}</div>
+                      </div>
+                    </el-option>
+                  </el-select>
+                </div>
+                <div class="Layout marginLeft">
+                  <div class="queryName">健康状态</div>
+                  <el-select v-model="form_task.stage" size="small" clearable filterable placeholder="请选择">
+                    <el-option v-for="item in healthStage" :key="item.value" :label="item.label" :value="item.value" />
+                  </el-select>
+                </div>
+              </el-form>
+            </div>
+            <div class="Layout" style="margin: 15px 0;">
+              <el-form :model="form_task" class="flex_start">
+                <div class="Layout">
+                  <div class="queryName" style="width:86px;">创建人</div>
+                  <el-select
+                    v-model="form_task.creater"
+                    clearable
+                    filterable
+                    remote
+                    placeholder="请输入姓名或邮箱前缀"
+                    :remote-method="remoteMethod"
+                    :loading="loading"
+                    size="small"
+                    style="width: 82%;"
+                  >
+                    <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
+                      <div class="flex_start">
+                        <div class="deptName">{{ item.deptName }}</div>
+                        <div style="min-width:80px">{{ item.name }}</div>
+                        <div class="deptName">{{ item.idap }}</div>
+                      </div>
+                    </el-option>
+                  </el-select>
+                </div>
+                <div class="Layout marginLeft">
+                  <div class="queryName">创建日期</div>
+                  <el-date-picker
+                    v-model="form_task.date"
+                    type="daterange"
+                    align="right"
+                    unlink-panels
+                    range-separator="至"
+                    start-placeholder="开始日期"
+                    end-placeholder="结束日期"
+                    size="small"
+                    value-format="yyyy-MM-dd HH:mm:ss"
+                    :default-time="['00:00:00','23:59:59']"
+                    :picker-options="pickerOptions"
+                  />
+                </div>
+              </el-form>
+            </div>
+            <div align="right">
+              <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
+              <el-button type="primary" size="mini" @click="get_taskList(form_task)">筛 选</el-button>
+              <el-button size="mini" @click="query_Reset">重 置</el-button>
+            </div>
           </div>
         </div>
-        <div class="btn">
-          <span @click.stop="showEditSearch = true">管理过滤器</span>
+        <div v-if="filterList.length && filterList.length > 0" class="filter">
+          <div class="filterWrap">
+            <div class="title">我的过滤器:</div>
+            <div class="itemBox">
+              <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
+            </div>
+          </div>
+          <div class="btn">
+            <span @click.stop="showEditSearch = true">管理过滤器</span>
+          </div>
         </div>
       </div>
     </div>
@@ -257,6 +270,17 @@
     <normal-dialog :show-footer="false" :show-dialog="showEditSearch" :title="'管理过滤器'" :width="'65%'" @cancel="showEditSearch=false">
       <filter-list :show-filter="showEditSearch" :filter-type="2" @deleteFilter="deleteFilter" />
     </normal-dialog>
+    <filterModal :show-dialog="showChartModal" @cancel="showChartModal = false">
+      <div>
+        <chartSearchForm
+          :data="chartSearchFormRenderData"
+          :loading="loading"
+          :styles="{ marginBottom: '15px', width: '380px' }"
+          @change="chartSearchFormChange"
+          @getOption="(key, q, utilName) => remoteMethod(q)"
+        />
+      </div>
+    </filterModal>
   </div>
 </template>
 
@@ -275,18 +299,27 @@ import {
   createFilter,
   filterGetFilter
 } from '@/api/taskIndex' // ajax
+import filterModal from '@/components/filterModal'
 import { settingQueryBizModuleList } from '@/api/defectManage'
 import openDialog from '@/views/projectManage/dialog_vue'
 // 过滤器
 import filterList from '@/views/projectManage/components/filterList'
 import normalDialog from '@/components/dialog/normalDialog'
+import mainTitle from '@/components/mainTitle'
+import chartView from '@/components/chartView'
+import chartSearchFormData from './renderData/chartSearchForm'
+import chartSearchForm from '@/components/searchHeader/searchForm'
 import '@/views/projectManage/publicCss/index.css'
 import '@/styles/PublicStyle/index.scss'
 export default {
   components: {
     openDialog,
     filterList,
-    normalDialog
+    normalDialog,
+    mainTitle,
+    chartView,
+    filterModal,
+    chartSearchForm
   },
   data() {
     return {
@@ -324,9 +357,9 @@ export default {
         children: 'childModules',
         multiple: true
       },
-      isFromDpmList: [{ id: true, name: '是' }, { id: false, name: '否' }],
+      isFromDpmList: [{ value: true, label: '是' }, { value: false, label: '否' }],
       priorityColors: ['#F56C6C', '#FF8952', '#F5E300', '#7ED321', '#61D3B8', '#69B3FF', '#BDBDBD'],
-      arr_priority: [{ value: 0, name: 'P0' }, { value: 1, name: 'P1' }, { value: 2, name: 'P2' }, { value: 3, name: 'P3' }],
+      arr_priority: [{ value: 0, label: 'P0' }, { value: 1, label: 'P1' }, { value: 2, label: 'P2' }, { value: 3, label: 'P3' }],
       dialog_open: false,
       curIndex: 1,
       pageSize: 15,
@@ -337,7 +370,9 @@ export default {
       list: [],
       userInformation: localStorage.getItem('username'),
       userNames: localStorage.getItem('realname'),
-      form_task: {},
+      form_task: {
+        chartType: '0'
+      },
       noTest: [], // 是否免测
       BusinessLine: [], // 业务线
       appClient: [], // 涉及业务线
@@ -365,7 +400,16 @@ export default {
         { required: true, message: '请输入筛选项名称', trigger: 'blur' },
         { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
       ] },
-      showSaveSearch: false // 显示保存筛选项对话框
+      showSaveSearch: false, // 显示保存筛选项对话框
+      nowTab: 'list',
+      chartData: {},
+      typeOptionList: [
+        { value: '0', label: '需求状态' },
+        { value: '1', label: '需求等级' },
+        { value: '2', label: '需求类型' }
+      ],
+      showChartModal: false,
+      chartSearchFormRenderData: _.cloneDeep(chartSearchFormData)
     }
   },
   computed: {
@@ -389,6 +433,8 @@ export default {
       this.bugDataGet()
       this.getFilterList() // 筛选项保存
     })
+    this.updateChartSlectOption('isFromDpm', this.isFromDpmList)
+    this.updateChartSlectOption('priority', this.arr_priority)
   },
   destroyed() {
     this.$store.state.data.status = false
@@ -397,6 +443,16 @@ export default {
     logHandle(d) {
       window.log({ c: 'task', d })
     },
+    changeTab(e) {
+      this.nowTab = e
+      if (this.nowTab === 'charts') {
+        // this.$emit('chartSearch')
+        this.updateChartSearchFormValue()
+        console.log('charts')
+      } else {
+        this.get_taskList()
+      }
+    },
     test2(item, e) {
       // 获取团队人员信息
       if (typeof this.test[item.idap] === 'undefined') {
@@ -486,27 +542,32 @@ export default {
       })
       configShowRequirementVersionEnum({ bizId: this.bizId }).then(res => {
         // 获取需求(查询)
-        this.demandList = res.data
+        const demandList = res.data.map(t => ({
+          ...t,
+          label: t.name,
+          value: t.id
+        }))
+        this.demandList = demandList
+        this.updateChartSlectOption('requireId', demandList)
       })
       this.isToOne = true
     },
-    remoteMethod(query) {
+    async remoteMethod(query) {
       // 人员查询
       if (query !== '') {
         this.loading = true
-        setTimeout(() => {
-          this.loading = false
-          memberQueryMemberInfoByIDAPorName({ memberIDAP: query }).then(res => {
-            const obj = {}
-            this.options = res.data.reduce((cur, next) => {
-              obj[next.idap] ? '' : obj[next.idap] = true && cur.push(next)
-              return cur
-            }, [])
-          })
-        }, 200)
+        const res = await memberQueryMemberInfoByIDAPorName({ memberIDAP: query })
+        const obj = {}
+        this.options = res.data.reduce((cur, next) => {
+          obj[next.idap] ? '' : obj[next.idap] = true && cur.push(next)
+          return cur
+        }, [])
+        this.loading = false
       } else {
         this.options = []
       }
+      this.updateChartSlectOption('PersonInCharge', this.options)
+      this.updateChartSlectOption('creater', this.options)
     },
     showSelect() {
       this.DetailedScreening = !this.DetailedScreening
@@ -576,18 +637,36 @@ export default {
       // 下拉菜单数据
       const res = await configShowTaskEnum()
       if (res.code === 200) {
-        this.healthStage = res.data.taskStage
+        const healthStage = res.data.taskStage.map(t => ({
+          ...t,
+          label: t.msg,
+          value: t.code
+        }))
+        this.healthStage = healthStage
+        this.updateChartSlectOption('stage', healthStage)
         this.noTest = res.data.noTest // 是否免测
         this.taskSource = res.data.taskSource // 归属需求
         this.appClient = res.data.appClient // 涉及客户端
       }
       const res1 = await configShowTaskStatusEnum(this.bizId)
       if (res1.code === 200) {
-        this.daStatus = res1.data.taskStatus
+        const daStatus = res1.data.taskStatus.map(t => ({
+          ...t,
+          label: t.msg,
+          value: t.code
+        }))
+        this.daStatus = daStatus
+        this.updateChartSlectOption('statusList', daStatus)
       }
       const res2 = await projectListProject({ bizId: this.bizId })
       if (res2.code === 200) {
-        this.projectList = res2.data
+        const projectList = res2.data.map(t => ({
+          ...t,
+          label: t.name,
+          value: t.id
+        }))
+        this.projectList = projectList
+        this.updateChartSlectOption('projectId', projectList)
       }
     },
     bugDataGet() { // 所属模块
@@ -613,11 +692,38 @@ export default {
         this.curIndex = 1
         this.get_taskList()
       }
+    },
+    chartSearchFormChange(key, value) {
+      console.log(key, value, this.chartSearchFormRenderData)
+      this.form_task[key] = value
+    },
+    updateChartSlectOption(key, option) {
+      this.chartSearchFormRenderData.map(t => {
+        if (t.key === key) {
+          t.option = option
+        }
+      })
+    },
+    updateChartSearchFormValue() {
+      this.chartSearchFormRenderData.map(t => {
+        t.value = this.form_task[t.key]
+      })
+      console.log(this.form_task, this.chartSearchFormRenderData)
     }
   }
 }
 </script>
 <style lang="scss" scoped>
+.chartView {
+  .chartSearchTitle {
+    width: 50px;
+    color: #333333;
+    font-size: 14px;
+  }
+  .screen {
+    margin-left: 20px;
+  }
+}
 .stylus-head {
   position: relative;
 }
@@ -756,7 +862,7 @@ export default {
     margin:0 auto
     background-color white
     border-radius 4px
-    min-height: calc(100vh - 143px);
+    // min-height: calc(100vh - 143px);
     .stylus-hover:hover
       color #409EFF !important
       cursor pointer

+ 2 - 2
src/views/workbench/team/components/needsList.vue

@@ -224,10 +224,10 @@ export default {
     color:$color;
     border: 1px solid $color;
   }
-  >>> .el-select__caret{
+  >>> .el-select__caret {
     color:$color;
   }
-  >>> .el-input__inner{
+  >>> .el-input__inner {
     color:$color;
     border-color: $color;
   }