浏览代码

feat: 订阅设置

yangfeng 4 年之前
父节点
当前提交
c63bbc569d

+ 3 - 1
src/App.vue

@@ -41,7 +41,9 @@ export default {
 </script>
 <style lang="scss">
 @import "~@/assets/style/reset-ele.scss";
-
+.big-member-page{
+  padding-left: calc(100vw - 100%)
+}
 .page--big-member.bg-white {
   background-color: #fff;
   .page-container {

+ 1 - 0
src/api/modules/index.js

@@ -4,3 +4,4 @@ export * from './chart'
 export * from './report'
 export * from './forecast'
 export * from './analysis'
+export * from './subscribe'

+ 32 - 6
src/api/modules/subscribe.js

@@ -2,11 +2,10 @@ import request from '@/api'
 import qs from 'qs'
 
 // 获取大会员信息(订阅设置)
-export function getBigMemberInfo (data) {
+export function getBigMemberInfo () {
   return request({
     url: '/use/info?t=' + Date.now(),
-    method: 'get',
-    data
+    method: 'get'
   })
 }
 
@@ -22,7 +21,6 @@ export function updateKey (data) {
 
 // 修改区域设置
 export function updateArea (data) {
-  data = qs.stringify(data)
   return request({
     url: '/subscribe/area/update',
     method: 'post',
@@ -32,7 +30,6 @@ export function updateArea (data) {
 
 // 修改信息类型
 export function updateInfoType (data) {
-  data = qs.stringify(data)
   return request({
     url: '/subscribe/infotype/update',
     method: 'post',
@@ -42,10 +39,39 @@ export function updateInfoType (data) {
 
 // 修改采购单位行业
 export function updateBuyClass (data) {
-  data = qs.stringify(data)
   return request({
     url: '/subscribe/buyerclass/update',
     method: 'post',
     data: data
   })
 }
+
+// 修改项目匹配
+export function updateProjectMatch (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/subscribe/projectmatch/update',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改”其他“采购单位按钮
+export function updateOtherBuyClass (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/subscribe/otherbuyclass/update',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改匹配方式
+export function updateMatchType (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/subscribe/matchtype/update',
+    method: 'post',
+    data: data
+  })
+}

+ 11 - 1
src/assets/style/_variables.scss

@@ -26,7 +26,7 @@ $bg-main-color: #fff;
 
 html {
   height: 100%;
-  overflow-y: auto;
+  // overflow-y: auto;
 }
 
 body {
@@ -63,6 +63,16 @@ body {
   -webkit-box-orient: vertical;
 }
 
+::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 8px;
+}
+::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 3px;
+  background-color: #ECECEC;
+  opacity: 0.15;
+}
 .scrollbar {
   &::-webkit-scrollbar {
     /*滚动条整体样式*/

+ 2 - 2
src/views/bid-policy/AnalysisResult.vue

@@ -6,12 +6,12 @@
       <el-tabs v-model="activeName" @tab-click="handleClick">
         <el-tab-pane label="类似项目分析" name="1">
           <div class="tab-item">
-            类似项目分析
+            <analysis-chart v-if="flag.charts" :active="activeName" :datas="propAnalysis" :info="baseInfo"></analysis-chart>
           </div>
         </el-tab-pane>
         <el-tab-pane label="类似项目明细" name="2">
           <div class="tab-item">
-            <analysis-chart v-if="flag.charts" :active="activeName" :datas="propAnalysis" :info="baseInfo"></analysis-chart>
+            类似项目分析
           </div>
         </el-tab-pane>
       </el-tabs>

+ 4 - 2
src/views/portrayal/components/AnalysisChart.vue

@@ -131,7 +131,7 @@ export default {
   watch: {
     active: {
       handler (newVal) {
-        if (newVal === '2') {
+        if (newVal === '1') {
           this.initChartData()
         }
       },
@@ -140,7 +140,9 @@ export default {
   },
   computed: {},
   created () {},
-  mounted () {},
+  mounted () {
+    this.initChartData()
+  },
   methods: {
     // 处理图表数据
     initChartData () {

+ 110 - 64
src/views/subscribe/Config.vue

@@ -1,11 +1,17 @@
 <template>
   <div class="config">
     <!-- 订阅设置 -->
-    <sub-config :datas="setData"></sub-config>
+    <div v-if="!isSubCount">
+      <sub-config :datas="setData" @update="getUpdate"></sub-config>
+    </div>
     <!-- 关键词设置 -->
-    <key-config :datas="setData"></key-config>
+    <key-config ref="keyConfigRef" :datas="setData" @updateKey="updateKeyWordsApi"></key-config>
     <!-- 关键词列表 -->
-    <key-list v-if="setData.keywordsList.length > 0" :list="setData.keywordsList" @openKeyDialog="openKeyDialog"></key-list>
+    <key-list v-if="setData.keywordsList.length > 0" :list="setData.keywordsList" @updateKey="updateKeyWordsApi"></key-list>
+    <div v-if="isSubCount">
+      <div class="reset-tips">新增的关键词设置,将在登出时还原</div>
+      <button type="button" class="save-btn" @click="saveSetting">保存设置</button>
+    </div>
   </div>
 </template>
 
@@ -13,7 +19,7 @@
 import SubConfig from './components/SubConfig'
 import KeyConfig from './components/KeyConfig'
 import KeyList from './components/KeyList'
-import { getBigMemberInfo } from '@/api/modules/subscribe'
+import { getBigMemberInfo, updateKey } from '@/api/modules'
 export default {
   name: 'config',
   components: {
@@ -24,26 +30,34 @@ export default {
   data () {
     return {
       setData: {
-        area: '全国',
-        industry: '全部',
-        infotypes: '全部类型',
-        keywordsList: [],
+        // 区域字符串 渲染输入框
+        areaStr: '',
+        // 采购单位行业字符串 渲染输入框
+        buyClassStr: '',
+        // 信息类型字符串
+        infoTypeStr: '',
         projectmatch: null,
         buyclassmatch: null,
-        mathway: 1,
-        maxKeyCounts: 0
-      },
-      // 区域对象
-      areaobj: {},
-      // 行业对象
-      insturyarr: [],
-      // 关键词
-      keyarr: [],
-      // 信息类型
-      infotypearr: []
+        mathway: null,
+        maxKeyCounts: 0,
+        // 区域对象
+        areaObj: {},
+        // 采购单位行业数组
+        buyClassArr: [],
+        // 信息类型数组
+        infoTypeArr: [],
+        // 关键词
+        keywordsList: []
+      }
+    }
+  },
+  computed: {
+    // 是否是子账号
+    isSubCount () {
+      console.log(this.$store.state.user.info.isSubCount)
+      return this.$store.state.user.info.isSubCount
     }
   },
-  computed: {},
   created () {
     this.getBigInfo()
   },
@@ -55,74 +69,62 @@ export default {
       const res = data.data
       if (res) {
         this.setData.maxKeyCounts = res.key_max_length ? res.key_max_length : 0
-        if (res.member_jy && JSON.stringify(res.member_jy) === '{}') {
+        if (res.member_jy && Object.keys(res.member_jy).length === 0) {
           this.setdata.area = '全国'
           this.setdata.industry = '全部'
-          this.setdata.getkeywords = '未分类'
           this.setdata.infotypes = '全部类型'
         } else {
           // 项目匹配
-          if (res.member_jy.i_projectmatch === 1) {
-            this.setData.projectmatch = true
-          } else {
-            this.setData.projectmatch = false
-          }
+          this.setData.projectmatch = res.member_jy.i_projectmatch
           // 其他采购单位
-          if (res.member_jy.i_matchbuyerclass_other === 1) {
-            this.setData.buyclassmatch = true
-          } else {
-            this.setData.buyclassmatch = false
-          }
+          this.setData.buyclassmatch = res.member_jy.i_matchbuyerclass_other
           // 匹配方式
-          this.setData.mathWay = res.member_jy.i_matchway
+          this.setData.mathway = res.member_jy.i_matchway
           // 区域
-          if (res.member_jy.o_area && JSON.stringify(res.member_jy.o_area) !== '{}') {
-            this.areaobj = res.member_jy.o_area
+          if (res.member_jy.o_area && Object.keys(res.member_jy.o_area).length > 0) {
             for (const key in res.member_jy.o_area) {
               provinceArr.push({
                 province: key,
                 citys: res.member_jy.o_area[key]
               })
-              provinceArr.forEach((province, i) => {
-                const cityArr = []
-                let pStr = ''
-                province.citys.forEach((city, ii) => {
-                  cityArr.push(city)
-                })
-                if (cityArr.length === 0) {
-                  pStr = province.province
-                } else {
-                  pStr = province.province + '(' + cityArr.join('、') + ')'
-                }
-                areaArr.push(pStr)
-              })
-              areaArr = areaArr.join('、')
-              this.setdata.area = areaArr
             }
+            provinceArr.forEach((province, i) => {
+              const cityArr = []
+              let pStr = ''
+              province.citys.forEach((city, ii) => {
+                cityArr.push(city)
+              })
+              if (cityArr.length === 0) {
+                pStr = province.province
+              } else {
+                pStr = province.province + '(' + cityArr.join('、') + ')'
+              }
+              areaArr.push(pStr)
+            })
+            areaArr = areaArr.join('、')
+            this.setData.areaStr = areaArr
+            this.setData.areaObj = res.member_jy.o_area
           } else {
-            this.setData.area = '全国'
+            this.setData.areaStr = '全国'
           }
           // 采购单位行业
           if (res.member_jy.a_buyerclass && JSON.stringify(res.member_jy.a_buyerclass) !== '[]') {
-            this.insturyarr = res.member_jy.a_buyerclass
-            this.setData.industry = res.member_jy.a_buyerclass.join('、')
+            this.setData.buyClassStr = res.member_jy.a_buyerclass.join('、')
+            this.setData.buyClassArr = res.member_jy.a_buyerclass
           } else {
-            this.setData.industry = '全部'
+            this.setData.buyClassStr = '全部'
           }
           // 信息类型
           if (res.member_jy.a_infotype && JSON.stringify(res.member_jy.a_infotype) !== '[]') {
-            this.setData.infotypes = res.member_jy.a_infotype.join('、')
-            this.infotypearr = res.member_jy.a_infotype
+            this.setData.infoTypeStr = res.member_jy.a_infotype.join('、')
+            this.setData.infoTypeArr = res.member_jy.a_infotype
           } else {
-            this.setData.infotypes = '全部类型'
+            this.setData.infoTypeStr = '全部类型'
           }
           // 关键词
           if (res.member_jy.a_items && JSON.stringify(res.member_jy.a_items) !== '[]') {
-            this.keyarr = res.member_jy.a_items
             this.setData.keywordsList = res.member_jy.a_items
-            // this.setData.getkeywords = this.getKeyWordnames(this.keyarr)
           } else {
-            // this.setData.getkeywords = '未分类'
             this.setData.keywordsList = []
           }
         }
@@ -130,10 +132,29 @@ export default {
         console.log('状态值为:' + res.status)
       }
     },
-    // 打开关键词弹框
-    openKeyDialog (data) {
-      console.log(data)
-      this.dialog.keyDialog = data.showDialog
+    // 子组件通知父组件更新关键词接口
+    updateKeyWordsApi (data) {
+      updateKey({
+        a_items: data
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$message({
+            type: 'success',
+            message: '关键词修改成功'
+          })
+          this.$refs.keyConfigRef.clearInputData()
+          this.getBigInfo()
+        } else {
+          this.$message({
+            type: 'error',
+            message: res.error_msg || '修改失败'
+          })
+          this.getBigInfo()
+        }
+      })
+    },
+    getUpdate () {
+      this.getBigInfo()
     },
     // 关键词
     getKeyWordnames (group) {
@@ -152,6 +173,9 @@ export default {
       } else {
         return '未分类'
       }
+    },
+    saveSetting () {
+      console.log('保存设置')
     }
   }
 
@@ -166,5 +190,27 @@ export default {
   background: #fff;
   border-radius: 5px;
   box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.08);
+  .reset-tips{
+    width: 100%;
+    height: 32px;
+    line-height: 32px;
+    color: #FF9F40;
+    font-size: 13px;
+    background: rgb(255, 159, 64, 0.1);
+    text-align: center;
+  }
+  .save-btn{
+    display: block;
+    width: 180px;
+    height: 46px;
+    margin: 20px auto;
+    line-height: 46px;
+    color: #fff;
+    background: #2CB7CA;
+    border-radius: 6px;
+    text-align: center;
+    cursor: pointer;
+    border: 0;
+  }
 }
 </style>

+ 66 - 56
src/views/subscribe/components/KeyConfig.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="keywords">
-    <div class="key-title">关键词设置 <span style="font-size:14px;"><em style="color: #2cb7ca;">{{keyCounts}}</em>/{{datas.maxKeyCounts}}</span></div>
+    <div class="key-title">
+      <span v-if="isSubCount">业务范围设置</span>
+      <span v-else>关键词设置</span>
+      <span style="font-size:14px;"><em style="color: #2cb7ca;"> {{keyCounts}}</em>/{{datas.maxKeyCounts}}</span>
+    </div>
     <div class="key-content">
       <div class="item">
         <div class="item-label">关键词分类:</div>
@@ -11,7 +15,7 @@
       <div class="item">
         <div class="item-label item-label-required">关键词:</div>
         <div class="item-value">
-          <el-input class="custom-long-input" v-model.trim="cur.key" maxlength="20" placeholder="请输入关键词"></el-input>
+          <el-input class="custom-long-input" v-model="cur.key" maxlength="20" placeholder="请输入关键词"></el-input>
         </div>
       </div>
       <div class="item">
@@ -63,15 +67,12 @@ export default {
   },
   data () {
     return {
+      // 当前输入框的数据
       cur: {
         classify: '',
         key: '',
         appendkey: [''],
         notkey: ['']
-      },
-      curArr: {
-        a_key: [],
-        s_item: ''
       }
     }
   },
@@ -87,6 +88,10 @@ export default {
     },
     keyDisabled () {
       return !this.cur.key
+    },
+    // 是否是子账号
+    isSubCount () {
+      return this.$store.state.user.info.isSubCount
     }
   },
   mounted () {
@@ -95,17 +100,20 @@ export default {
   methods: {
     // 保存数据
     saveCurData () {
-      let newData = []
-      this.curArr.s_item = this.cur.classify
-      this.curArr.a_key = [{
-        appendkey: this.cur.appendkey,
-        key: [this.cur.key],
-        notkey: this.cur.notkey
-      }]
-      this.datas.keywordsList.push(this.curArr)
-      newData = this.datas.keywordsList
-      console.log(newData)
-      return newData
+      const data = this.datas.keywordsList
+      let obj = {
+        a_key: [
+          {
+            key: this.cur.key.split(' '),
+            notkey: this.cur.notkey,
+            appendkey: this.cur.appendkey
+          }
+        ],
+        s_item: this.cur.classify ? this.cur.classify : this.getNewClassName()
+      }
+      data.push(obj)
+      console.log(data)
+      return data
     },
     // 提交关键词
     submitKeywords () {
@@ -123,15 +131,10 @@ export default {
           message: '关键词不能重复'
         })
       }
-      const params = {
-        a_items: this.saveCurData()
-      }
-      console.log(params, 'data')
-      updateKey({
-        a_items: params.a_items
-      }).then((res) => {
-        console.log(res)
-      })
+      const params = this.saveCurData()
+      console.log(params, '提交的关键词数据')
+      // 通知父组件发请求修改并更新
+      this.$emit('updateKey', params)
     },
     // 添加附加词
     addAttachWordsFn () {
@@ -174,9 +177,9 @@ export default {
     getKeyTotalArray () {
       const keysArr = []
       this.datas.keywordsList.forEach((s) => {
-        if (s && s.a_key && this.isArray(s.a_key)) {
+        if (s && s.a_key && Array.isArray(s.a_key)) {
           s.a_key.forEach((v) => {
-            if (this.isArray(v.key)) {
+            if (Array.isArray(v.key)) {
               v.key.forEach(x => {
                 keysArr.push(x)
               })
@@ -188,37 +191,44 @@ export default {
       })
       return keysArr
     },
-    // 判断变量是否是数组
-    isArray (o) {
-      return Object.prototype.toString.call(o) === '[object Array]'
-    },
-    groupListKeyArrToString (list, state) {
-      let mList = JSON.parse(JSON.stringify(list))
-      if (this.isArray(mList)) {
-        mList.forEach((keyList) => {
-          if (keyList && keyList.a_key && this.isArray(keyList.a_key)) {
-            keyList.a_key.forEach((item) => {
-              if (!state && this.isArray(item.key)) {
-                // 数组拼接
-                item.key = item.key.join(' ')
-              } else if (state === 1) {
-                // 字符串切割
-                item.key = item.key.replace(/\s+/g, ' ').split(' ')
-              } else {
-                if (state) {
-                  console.error('关键词key,必须为字符串。并且state参数只有两种数值0和1')
-                } else {
-                  console.error('关键词key,必须为数组')
-                }
-              }
-            })
+    // 通过已有分类得到一个未分类名
+    getNewClassName () {
+      var conf = {
+        defaultT: '未分类',
+        reg: /^未分类(\d*)$/,
+        // 未分类名称数组
+        unclassified: [],
+        // 未分类名称数字数组
+        unclassifiedNum: [],
+        sortedArr: []
+      }
+      this.datas.keywordsList.forEach((item) => {
+        if (item.s_item && conf.reg.test(item.s_item)) {
+          let num = item.s_item.replace(new RegExp(conf.defaultT, 'g'), '')
+          num = parseInt(num)
+          if (isNaN(num)) {
+            num = 0
           }
-        })
+          conf.unclassifiedNum.push(num)
+          conf.unclassified.push(item.s_item)
+        }
+      })
+      // 得到分类名
+      if (conf.unclassifiedNum.length === 0) {
+        return '未分类'
       } else {
-        mList = []
+        conf.sortedArr = conf.unclassifiedNum.sort(function (a, b) {
+          return b - a
+        })
+        return conf.defaultT + (conf.sortedArr[0] + 1)
       }
-      console.log(mList)
-      return mList
+    },
+    // 清空输入框 供父组件请求成功后刷新
+    clearInputData () {
+      this.cur.classify = ''
+      this.cur.key = '',
+      this.cur.appendkey = [''],
+      this.cur.notkey = ['']
     }
   }
 }

+ 163 - 0
src/views/subscribe/components/KeyEdit.vue

@@ -0,0 +1,163 @@
+<template>
+  <div class="keywords-edit">
+    <div class="item">
+      <div class="item-label">关键词分类:</div>
+      <div class="item-value">{{datas.className}}</div>
+    </div>
+    <div class="item">
+      <div class="item-label item-label-required">关键词:</div>
+      <div class="item-value">
+        <el-input class="custom-long-input" v-model="cur.key" maxlength="20" placeholder="请输入关键词"></el-input>
+      </div>
+    </div>
+    <div class="item">
+      <div class="item-label"></div>
+      <div class="item-value item-keywords-value">
+        <div>
+          <div class="add-word-list" v-for="(add,index) in cur.appendkey" :key="'add' + index">
+            <el-input v-model.trim="cur.appendkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入附加词"></el-input>
+          </div>
+          <div class="add-tag" @click="addAppendKey">+添加附加词</div>
+        </div>
+        <div>
+          <div class="add-word-list" v-for="(not,index) in cur.notkey" :key="'0' + index">
+            <el-input v-model.trim="cur.notkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入排除词"></el-input>
+          </div>
+          <div class="add-tag" @click="addNotKey">+添加排除词</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { Input } from 'element-ui'
+export default {
+  name: 'keywords-edit',
+  components: {
+    [Input.name]: Input
+  },
+  props: {
+    datas: {
+      ways: String,
+      className: String,
+      key: Array,
+      notkey: Array,
+      appendkey: Array
+    }
+  },
+  data () {
+    return {
+      cur: {
+        key: '',
+        appendkey: [],
+        notkey: []
+      }
+    }
+  },
+  watch: {},
+  computed: {},
+  created () {
+    this.getParentData()
+  },
+  mounted () {},
+  methods: {
+    // 获取父组件keyList传来的数据 并进行格式转化渲染到输入框
+    getParentData () {
+      this.cur.key = this.datas.key.join(' ')
+      this.cur.notkey = this.datas.notkey
+      this.cur.appendkey = this.datas.appendkey
+    },
+    addAppendKey () {
+      const arr = this.cur.appendkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入附加词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.appendkey.push('')
+      }
+    },
+    addNotKey () {
+      const arr = this.cur.notkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入排除词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.notkey.push('')
+      }
+    },
+    inputIsEmpty (arr) {
+      return arr.some((v) => !v)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.keywords-edit{
+  .item{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 10px;
+  }
+  .item-label{
+    margin-right: 8px;
+    min-width: 120px;
+    height: 40px;
+    color: #1d1d1d;
+    font-size: 14px;
+    line-height: 40px;
+    text-align: right;
+  }
+  .item-label-required:before{
+    content: "*";
+    color: #f56c6c;
+    margin-right: 2px;
+  }
+  .item-value{
+    width: 352px;
+  }
+  .custom-long-input{
+    width: 352px;
+  }
+  .custom-short-input{
+    width: 170px;
+  }
+  .item-keywords-value{
+    display: flex;
+    justify-content: space-between;
+  }
+  .add-tag{
+    width: 170px;
+    height: 40px;
+    line-height: 40px;
+    color: #2cb7ca;
+    border-radius: 6px;
+    text-align: center;
+    cursor: pointer;
+    color: #2cb7ca;
+    border: 1px dashed #2cb7ca;
+  }
+  .add-word-list{
+    margin-bottom: 6px;
+  }
+  // element-ui样式修改
+  ::v-deep.el-input__inner{
+    font-size: 14px;
+    color: #1D1D1D;
+    border-color: #ececec;
+    padding-left: 16px!important;
+    border-radius: 6px!important;
+    background: #fff!important;
+  }
+  ::v-deep.el-input__inner:hover{
+    border-color: #ececec;
+  }
+  ::v-deep.el-input__inner:focus{
+    border-color: #2cb7ca;
+  }
+}
+</style>

+ 320 - 41
src/views/subscribe/components/KeyList.vue

@@ -1,80 +1,359 @@
 <template>
   <div class="classify">
-    <div class="classify-list" v-for="(item,index) in getList" :key="'1' + index">
+    <div class="classify-list" v-for="(item,index) in list" :key="'1' + index">
       <div class="classify-title">
         <span class="title-text">{{item.s_item}}</span>
-        <span class="icon-edit"></span>
-        <span class="icon-delete"></span>
+        <span class="icon-edit" @click="editClassFn(item.s_item, index)"></span>
+        <span class="icon-delete" @click="deleteClassFn(item.s_item, index)"></span>
       </div>
       <div class="classify-content">
-        <div class="list" v-for="(v,i) in item.a_key" :key="'2' + i">
+        <div class="list" v-for="(v, i) in item.a_key" :key="'2' + i">
           <div class="list-box">
             <div class="list-value">
-              <p>关键词: {{v.key || '--'}}</p>
-              <p>附加词: {{v.appendkey || '--'}}</p>
-              <p>排除词: {{v.notkey || '--'}}</p>
+              <p>关键词: {{v.key.join(' ') || '--'}}</p>
+              <p>附加词: {{v.appendkey.join('、') || '--'}}</p>
+              <p>排除词: {{v.notkey.join('、') || '--'}}</p>
             </div>
-            <div class="list-icon"></div>
-            <div class="list-edit" @click="editHandle(v)">
+            <div class="list-icon" @click="deleteKeyFn(index, i)"></div>
+            <div class="list-edit" @click="editKeyFn(item, v, index, i)">
               编辑
               <i class="tri-down"></i>
             </div>
           </div>
         </div>
-        <div class="words-add">
+        <div class="words-add" @click="addKeyFn(item.s_item)">
           <i class="el-icon-plus"></i>
         </div>
       </div>
     </div>
+    <!-- 修改分类dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.editClass"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="800px"
+      v-if="dialog.editClass"
+    >
+      <KeyCard @onCancel="dialog.editClass = false" @onConfirm="confirmEditClassFn">
+        <div slot="header">修改关键词分类</div>
+        <div class="class-edit-content">
+          <div class="item">
+            <div class="item-label">关键词分类:</div>
+            <div class="item-value">
+              <el-input class="custom-long-input" v-model.trim="props.className"  maxlength="20" placeholder="请输入关键词分类"></el-input>
+            </div>
+          </div>
+        </div>
+      </KeyCard>
+    </el-dialog>
+    <!-- 删除分类dialog -->
+    <el-dialog
+      custom-class="sub-dialog small-dialog"
+      :visible.sync="dialog.delClass"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      top="30vh"
+      width="380px"
+      v-if="dialog.delClass"
+    >
+      <div class="delete-class">
+        <div class="delete-class-header">删除关键词分类</div>
+        <div class="delete-class-content">{{props.className}}</div>
+        <div class="delete-class-footer">
+          <el-button type="primary" class="confirm" @click="confirmDeleteClassFn">删除</el-button>
+          <el-button class="cancel" @click="dialog.delClass = false">取消</el-button>
+        </div>
+      </div>
+    </el-dialog>
+    <!-- 关键词dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.editKey"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="800px"
+      v-if="dialog.editKey"
+    >
+      <KeyCard @onCancel="dialog.editKey = false" @onConfirm="submitKeywords">
+        <div slot="header">修改关键词</div>
+        <div class="key-edit-content">
+          <KeyEdit ref="keyEditRef" :datas="props"></KeyEdit>
+        </div>
+      </KeyCard>
+    </el-dialog>
   </div>
 </template>
 <script>
-import { Tooltip } from 'element-ui'
+import { Tooltip, Dialog, Input, Button } from 'element-ui'
+import KeyCard from '@/components/selector/SelectorCard'
+import KeyEdit from './KeyEdit'
 export default {
   name: 'keywords-list',
   components: {
-    [Tooltip.name]: Tooltip
+    [Tooltip.name]: Tooltip,
+    [Dialog.name]: Dialog,
+    [Input.name]: Input,
+    [Button.name]: Button,
+    KeyCard,
+    KeyEdit
   },
-  props: ['list'],
-  data () {
-    return {}
+  props: {
+    list: Array
   },
-  computed: {
-    getList () {
-      const newArr = this.list
-      newArr.forEach((v) => {
-        if (v.a_key) {
-          v.a_key.forEach((s) => {
-            if (this.isArray(s.key)) {
-              s.key = s.key.join('、')
-            }
-            if (this.isArray(s.appendkey)) {
-              s.appendkey = s.appendkey.join('、')
-            }
-            if (this.isArray(s.notkey)) {
-              s.notkey = s.notkey.join('、')
-            }
-          })
-        }
-      })
-      return newArr
+  data () {
+    return {
+      dialog: {
+        editClass: false, // 修改分类弹框
+        delClass: false,  // 删除分类弹框
+        editKey: false  // 修改关键词弹框
+      },
+      // 传给dialog子组件的数据
+      props: {
+        ways: '', // 编辑还是新增
+        classIndex: null, // 分类下标
+        className: '', // 分类名
+        keyIndex: null, // 关键词下标
+        key: [],  // 关键词
+        notkey: [], // 排除词
+        appendkey: []  // 附加词
+      }
     }
   },
-  mounted () {},
+  computed: {},
+  mounted () {
+    console.log(this.list, 'list')
+  },
   methods: {
-    editHandle (item) {
-      this.$emit('openKeyDialog', {
-        showDialog: true,
-        data: item
+    // 打开修改关键词分类弹框
+    editClassFn (name, index) {
+      this.dialog.editClass = true
+      this.props.className = name
+      this.props.classIndex = index
+    },
+    // 确认修改分类
+    confirmEditClassFn () {
+      this.list.forEach((v, i) => {
+        if (this.props.classIndex === i) {
+          v.s_item = this.props.className
+        }
       })
+      this.$emit('updateKey', this.list)
+      this.dialog.editClass = false
+    },
+    // 打开删除关键词分类弹框
+    deleteClassFn (name, index) {
+      this.props.classIndex = null
+      this.dialog.delClass = true
+      this.props.className = name
+      this.props.classIndex = index
+    },
+    // 确认删除分类
+    confirmDeleteClassFn () {
+      this.dialog.delClass = false
+      // 删除整个分类的数据
+      this.list.splice(this.props.classIndex, 1)
+      this.$emit('updateKey', this.list)
+    },
+    // 添加关键词
+    addKeyFn (name) {
+      this.dialog.editKey = true
+      this.props.ways = 'add'
+      this.props.className = name
+      this.props.key = []
+      this.props.notkey = []
+      this.props.appendkey = []
+    },
+    // 删除单个关键词
+    deleteKeyFn (index, i) {
+      console.log(index, i)
+      if (!this.list) return
+      this.list[index].a_key.splice(i, 1)
+      this.$emit('updateKey', this.list)
+    },
+    // 编辑单个关键词
+    editKeyFn (item, v, index, i) {
+      // index 分类下标 i 关键词下标
+      this.clearPropsData()
+      this.props.ways = 'edit'
+      this.dialog.editKey = true
+      // 把当前关键词传到dialog key,notkey,appendKey都为数组
+      this.props.className = item.s_item
+      this.props.key = v.key
+      this.props.notkey = v.notkey
+      this.props.appendkey = v.appendkey
+      this.props.keyIndex = i
+      this.props.classIndex = index
+      console.log(i)
+    },
+    // 清空传值
+    clearPropsData () {
+      this.props.className = ''
+      this.props.classIndex = null,
+      this.props.key = []
+      this.props.notkey = []
+      this.props.appendkey = []
+    },
+    // 修改关键词dialog 保存数据
+    submitKeywords () {
+      const data = this.list
+      const refs = this.$refs.keyEditRef.cur
+      const keyArr = this.getKeyTotalArray()
+      const type = this.props.ways
+      let obj = {
+        key: refs.key.split(' '),
+        notkey: refs.notkey,
+        appendkey: refs.appendkey
+      }
+      if (type === 'add') {
+        if (keyArr.indexOf(refs.key) > -1) {
+          return this.$message({
+            type: 'warning',
+            message: '关键词不能重复'
+          })
+        }
+        data.forEach((v) => {
+          if (v.s_item === this.props.className){
+            v.a_key.push(obj)
+          }
+        })
+      } else if (type === 'edit') {
+        console.log(this.props.classIndex, this.props.keyIndex)
+        if (!data[this.props.classIndex].a_key) return
+        data[this.props.classIndex].a_key.splice(this.props.keyIndex, 1)
+        data.forEach((v) => {
+          if (v.s_item === this.props.className){
+            v.a_key.push(obj)
+          }
+        })
+      }
+      console.log(data, 'data')
+      // 通知父组件发请求修改并更新
+      this.$emit('updateKey', data)
+      this.dialog.editKey = false
     },
-    isArray (o) {
-      return Object.prototype.toString.call(o) === '[object Array]'
+    // 获取所有关键词的key的属性,并返回一个数组(主要用于判断添加关键词是否重复)
+    getKeyTotalArray () {
+      const keysArr = []
+      this.list.forEach((s) => {
+        if (s && s.a_key && Array.isArray(s.a_key)) {
+          s.a_key.forEach((v) => {
+            if (Array.isArray(v.key)) {
+              v.key.forEach(x => {
+                keysArr.push(x)
+              })
+            } else {
+              keysArr.push(v.key)
+            }
+          })
+        }
+      })
+      return keysArr
     }
   }
 }
 </script>
 <style lang="scss" scoped>
+// dialog 自定义class样式
+.sub-dialog{
+  border-radius: 8px;
+  .selector-card{
+    width: 800px;
+    height: auto;
+  }
+  .key-edit-content,.class-edit-content{
+    width: 740px;
+    padding: 30px 0;
+    height: auto;
+    max-height: 340px;
+    margin: 0 auto;
+    border: 1px solid #ececec;
+    overflow-y: scroll;
+    box-sizing: border-box;
+  }
+  .item{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 10px;
+  }
+  .item-label{
+    margin-right: 8px;
+    min-width: 120px;
+    height: 40px;
+    color: #1d1d1d;
+    font-size: 14px;
+    line-height: 40px;
+    text-align: right;
+  }
+  .item-label-required:before{
+    content: "*";
+    color: #f56c6c;
+    margin-right: 2px;
+  }
+  .item-value{
+    width: 352px;
+  }
+  .custom-long-input{
+    width: 352px;
+  }
+  .custom-short-input{
+    width: 170px;
+  }
+  .delete-class{
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 32px 32px 42px;
+    background: #FFFFFF;
+    border-radius: 6px;
+    .delete-class-header{
+      font-size: 18px;
+      line-height: 28px;
+      color: #1D1D1D;
+    }
+    .delete-class-content{
+      padding: 20px 0 42px;
+      color: #686868;
+      font-size: 14px;
+      line-height: 22px;
+    }
+    .delete-class-footer{
+      display: flex;
+      align-items: center;
+      .confirm,
+      .cancel {
+        padding: 10px 50px;
+        margin: 0 20px;
+      }
+      ::v-deep {
+        .el-button--primary {
+          color: #2cb7ca;
+          background: none;
+          border-color: #2cb7ca;
+          &:hover {
+            color: #fff;
+            background-color: #2cb7ca;
+          }
+        }
+        .el-button--default {
+          &:hover,
+          &:active {
+            color: #2cb7ca;
+            border-color: #2cb7ca;
+            background: #eaf8fa;
+          }
+        }
+      }
+    }
+  }
+}
+.sub-dialog.small-dialog::v-deep.el-dialog{
+  border-radius: 8px!important;
+}
 .classify-list{
   margin-bottom: 30px;
   .classify-title{

+ 197 - 57
src/views/subscribe/components/SubConfig.vue

@@ -4,31 +4,34 @@
     <div class="sub-content">
       <div class="item">
         <div class="item-label item-label-required">区域:</div>
-        <div class="item-value">
-          <el-input class="custom-long-input" v-model="datas.area" disabled></el-input>
+        <div class="item-value" @click="dialog.area = true">
+          <el-input class="my custom-long-input" v-model="datas.areaStr" disabled></el-input>
         </div>
       </div>
       <div class="item">
         <div class="item-label item-label-required">采购单位行业:</div>
-        <div class="item-value">
-          <el-input class="custom-long-input" v-model="datas.industry" disabled></el-input>
+        <div class="item-value" @click="dialog.buyClass = true">
+          <el-input class="my custom-long-input" v-model="datas.buyClassStr" disabled></el-input>
         </div>
       </div>
       <div class="item">
         <div class="item-label item-label-required">信息类型:</div>
-        <div class="item-value">
-          <el-input class="custom-long-input" v-model="datas.infotypes" disabled></el-input>
+        <div class="item-value"  @click="dialog.infoType = true">
+          <el-input class="my custom-long-input" v-model="datas.infoTypeStr" disabled></el-input>
         </div>
       </div>
       <div class="item-other">
         <div class="item-label">项目匹配:</div>
         <div class="item-value item-other-value">
           <el-switch
+            class="my"
             :disabled="projectSwitch.disabled"
             v-loading="projectSwitch.loading"
-            @change="switchProject"
+            @change="switchProjectMatch($event)"
             v-model="datas.projectmatch"
             :width="44"
+            :active-value="1"
+            :inactive-value="0"
             active-text="关"
             inactive-text="开"
             active-color="#2cb7ca"
@@ -41,11 +44,14 @@
         <div class="item-label">"其他"采购单位:</div>
         <div class="item-value item-other-value">
           <el-switch
+            class="my"
             :disabled="unitSwitch.disabled"
             v-loading="unitSwitch.loading"
-            @change="switchUnit"
+            @change="switchOtherUnit($event)"
             v-model="datas.buyclassmatch"
             :width="44"
+            :active-value="1"
+            :inactive-value="0"
             active-text="关"
             inactive-text="开"
             active-color="#2cb7ca"
@@ -57,32 +63,84 @@
       <div class="item-other">
         <div class="item-label">关键词匹配方式:</div>
         <div class="item-value item-other-value">
-          <el-radio-group v-model="datas.mathWay" @change="chooseMathWay">
+          <el-radio-group v-model="datas.mathway" @change="chooseMathWay($event)">
             <div class="radio-item">
-              <el-radio :label="1">按标题匹配</el-radio>
+              <el-radio class="my" name="matchway" :label="1">按标题匹配</el-radio>
             </div>
             <div>
-              <el-radio :label="2">按全文匹配</el-radio>
+              <el-radio class="my" name="matchway" :label="0">按全文匹配</el-radio>
             </div>
           </el-radio-group>
           <p class="math-tips">会产生无效信息,请根据需要选择</p>
         </div>
       </div>
     </div>
+    <!-- 区域选择dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.area"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="460px"
+    >
+      <AreaSelect
+        :initCityMap="datas.areaObj"
+        @onCancel="dialog.area = false"
+        @onConfirm="saveAreaData"
+      ></AreaSelect>
+    </el-dialog>
+    <!-- 采购单位行业dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.buyClass"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="460px"
+    >
+      <BuyClassSelect
+        :initCate="datas.buyClassArr"
+        @onCancel="dialog.buyClass = false"
+        @onConfirm="saveBuyClassData"
+      ></BuyClassSelect>
+    </el-dialog>
+    <!-- 信息类型dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.infoType"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="460px"
+    >
+      <InfoTypeSelect
+        :initInfoType="datas.infoTypeArr"
+        @onCancel="dialog.infoType = false"
+        @onConfirm="saveInfoTypeData"
+      ></InfoTypeSelect>
+    </el-dialog>
   </div>
 </template>
 <script>
-import { Switch, Input, RadioGroup, Radio, Button } from 'element-ui'
+import { Switch, Input, RadioGroup, Radio, Button, Dialog } from 'element-ui'
+import AreaSelect from '@/components/selector/AreaSelector'
+import BuyClassSelect from '@/components/selector/BuyerclassSelector'
+import InfoTypeSelect from '@/components/selector/InfoTypeSelector'
+import { updateArea, updateBuyClass, updateInfoType, updateProjectMatch, updateOtherBuyClass, updateMatchType } from '@/api/modules'
 export default {
   name: 'sub-config',
   props: {
     datas: {
-      area: String,
-      industry: String,
-      infotypes: String,
-      projectmatch: Boolean,
-      buyclassmatch: Boolean,
-      mathway: Number
+      areaStr: String,
+      buyClassStr: String,
+      infoTypeStr: String,
+      projectmatch: Number,
+      buyclassmatch: Number,
+      mathway: Number,
+      areaObj: Object,
+      buyClassArr: Array,
+      infoTypeArr: Array
     }
   },
   components: {
@@ -90,7 +148,11 @@ export default {
     [Input.name]: Input,
     [RadioGroup.name]: RadioGroup,
     [Radio.name]: Radio,
-    [Button.name]: Button
+    [Button.name]: Button,
+    [Dialog.name]: Dialog,
+    AreaSelect,
+    BuyClassSelect,
+    InfoTypeSelect
   },
   data () {
     return {
@@ -101,44 +163,119 @@ export default {
       unitSwitch: {
         loading: false,
         disabled: false
+      },
+      dialog: {
+        area: false,
+        buyClass: false,
+        infoType: false
       }
     }
   },
-  mounted () {},
+  mounted () {
+    console.log(this.datas.areaStr, 'str')
+  },
   methods: {
-    switchProject (state) {
+    // 切换项目匹配按钮
+    switchProjectMatch (event) {
+      console.log(event)
       this.projectSwitch.loading = true
       this.projectSwitch.disabled = true
-      setTimeout(() => {
-        this.form.matchProject = state
-        this.projectSwitch.loading = false
-        this.projectSwitch.disabled = false
-      }, 1000)
+      updateProjectMatch({
+        projectmatch: event
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+          this.projectSwitch.loading = false
+          this.projectSwitch.disabled = false
+          this.$message({
+            message: '切换成功',
+            type: 'success'
+          })
+        }
+      })
     },
-    switchUnit (state) {
+    // 切换其他采购单位按钮
+    switchOtherUnit (state) {
       this.unitSwitch.loading = true
       this.unitSwitch.disabled = true
-      setTimeout(() => {
-        this.form.otherUnit = state
-        this.unitSwitch.loading = false
-        this.unitSwitch.disabled = false
-        this.$message({
-          message: '切换成功',
-          type: 'success'
-        })
-      }, 1000)
+      updateOtherBuyClass({
+        otherbuyclass: state
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+          this.unitSwitch.loading = false
+          this.unitSwitch.disabled = false
+          this.$message({
+            message: '切换成功',
+            type: 'success'
+          })
+        }
+      })
     },
-    chooseMathWay (name) {
-      this.form.mathWay = name
+    chooseMathWay (state) {
+      console.log(state)
+      updateMatchType({
+        matchtype: state
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+        }
+      })
     },
     // 添加附加词
     addAttachWordsFn () {
       this.attachWordsData.push('')
+    },
+    // 保存区域修改数据
+    saveAreaData (data) {
+      updateArea(data).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+          this.dialog.area = false
+        } else {
+          this.$message({
+            message: '修改失败',
+            type: 'error'
+          })
+        }
+      })
+    },
+    // 保存采购单位行业数据
+    saveBuyClassData (data) {
+      updateBuyClass({
+        buyclass: data
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+          this.dialog.buyClass = false
+        } else {
+          this.$message({
+            message: '修改失败',
+            type: 'error'
+          })
+        }
+      })
+    },
+    // 保存采购单位行业数据
+    saveInfoTypeData (data) {
+      updateInfoType({
+        infotype: data
+      }).then((res) => {
+        if (res.data.status === 1) {
+          this.$emit('update')
+          this.dialog.infoType = false
+        } else {
+          this.$message({
+            message: '修改失败',
+            type: 'error'
+          })
+        }
+      })
     }
   }
 }
 </script>
-<style lang="scss" scoped>
+<style lang="scss">
 .subscribe{
   .sub-title{
     padding-bottom: 8px;
@@ -194,7 +331,7 @@ export default {
     margin-bottom: 10px;
   }
   // element-ui样式修改
-  ::v-deep.el-input__inner{
+  .my .el-input__inner{
     font-size: 14px;
     color: #2cb7ca;
     white-space: nowrap;
@@ -202,21 +339,21 @@ export default {
     text-overflow: ellipsis;
     border-color: #ececec;
   }
-  .item-other-value ::v-deep.el-loading-spinner .circular{
+  .my .el-loading-spinner .circular{
     width: 22px;
     height: 22px;
   }
-  .item-other-value ::v-deep.el-loading-spinner{
+  .my .el-loading-spinner{
     margin-top: -11px;
   }
-  ::v-deep .el-input.is-disabled .el-input__inner{
+  .my .el-input__inner{
     background: #fff;
     cursor: pointer;
   }
-  ::v-deep .el-switch{
+  .my .el-switch{
     position: relative;
   }
-  ::v-deep .el-switch__label--left {
+  .my .el-switch__label--left {
     position: absolute;
     left: 6px;
     top: 0;
@@ -224,7 +361,7 @@ export default {
     z-index: 9;
     font-size: 12px;
   }
-  ::v-deep .el-switch__label--right {
+  .my .el-switch__label--right {
     position: absolute;
     right: 6px;
     top: 0;
@@ -232,29 +369,29 @@ export default {
     z-index: 9;
     font-size: 12px;
   }
-  ::v-deep.el-switch__label *{
+  .my .el-switch__label *{
     font-size: 12px;
   }
-  ::v-deep.el-switch,::v-deep.el-switch__core{
+  .my .el-switch,.my .el-switch__core{
     height: 22px;
     line-height: 22px;
   }
-  ::v-deep.el-switch__core:after{
+  .my .el-switch__core:after{
     width: 18px;
     height: 18px;
   }
-  ::v-deep .el-switch.is-checked .el-switch__core::after{
-    margin-left: -18px;
+  .el-switch.is-checked .el-switch__core::after{
+    margin-left: -18px!important;
   }
-  ::v-deep.el-radio{
+  .my .el-radio{
     color: #1d1d1d;
     font-size: 14px;
   }
-  ::v-deep.el-radio__inner{
+  .my .el-radio__inner{
     width: 20px;
     height: 20px;
   }
-  ::v-deep .el-radio__input.is-checked .el-radio__inner{
+  .my .el-radio__input.is-checked .el-radio__inner{
     border: 0;
     background: transparent;
     width: 20px;
@@ -262,14 +399,17 @@ export default {
     background: url('~@/assets/images/icon-checked.png') no-repeat center center;
     background-size: contain;
   }
-  ::v-deep.el-radio__inner::after{
+  .my .el-radio__inner::after{
     background: transparent;
   }
-  ::v-deep.el-radio__input.is-checked+.el-radio__label{
+  .my .el-radio__input.is-checked+.el-radio__label{
     color: #1d1d1d;
   }
-  ::v-deep.el-radio__inner:hover{
+  .my .el-radio__inner:hover{
     border-color: #ececec;
   }
 }
+.sub-dialog .el-dialog__header,.sub-dialog .el-dialog__body{
+  padding: 0;
+}
 </style>