Ver Fonte

Merge branch 'feature/v1.5.4' of http://192.168.3.207:8080/jianyu/page_bigmember_pc into feature/v1.5.4

zhangyuhan há 3 anos atrás
pai
commit
6e27d410e8

+ 17 - 0
src/api/modules/public.js

@@ -8,3 +8,20 @@ export function getCommonAdList (data) {
     data
   })
 }
+
+export function getFreeUserPushInfo (data) {
+  return request({
+    baseURL: '/publicapply',
+    url: '/myinfo',
+    method: 'POST'
+  })
+}
+
+// 获取免费订阅信息接口
+export function getFreeUserSubscribeList (data) {
+  return request({
+    baseURL: '/publicapply',
+    url: '/free/subscribe',
+    method: 'POST'
+  })
+}

BIN
src/assets/images/follow-official-account-dialog-header.png


+ 104 - 0
src/components/dialog/Dialog.vue

@@ -0,0 +1,104 @@
+<template>
+  <el-dialog
+    class="custom-dialog"
+    v-bind="$props"
+    :visible="visible"
+    @update:visible="update">
+    <slot name="default"></slot>
+    <span slot="footer" class="dialog-footer">
+      <slot name="footer">
+        <button class="action-button cancel" @click="onClickCancel">取消</button>
+        <button class="action-button confirm" @click="onClickConfirm">确定</button>
+      </slot>
+    </span>
+    </el-dialog>
+</template>
+
+<script>
+import { Dialog, Button } from 'element-ui'
+
+export default {
+  name: 'CustomDialog',
+  components: {
+    [Dialog.name]: Dialog,
+    [Button.name]: Button
+  },
+  props: {
+    visible: Boolean,
+    top: String,
+    title: {
+      type: String,
+      default: ''
+    },
+    width: {
+      type: String,
+      default: '30%'
+    },
+    'show-close': {
+      type: Boolean,
+      default: false
+    },
+    center: {
+      type: Boolean,
+      default: true
+    }
+  },
+  methods: {
+    update (e) {
+      this.$emit('update:visible', e)
+    },
+    onClickCancel () {
+      this.$emit('cancel')
+    },
+    onClickConfirm () {
+      this.$emit('confirm')
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+::v-deep {
+  .el-dialog {
+    border-radius: 8px;
+  }
+  .el-dialog__body {
+    color: #686868;
+    font-size: 14px;
+    line-height: 22px;
+  }
+  .dialog-footer {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+  .action-button {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex: 1;
+    height: 36px;
+    border-radius: 6px;
+    &.cancel {
+      border: 1px solid #e0e0e0;
+      background-color: #fff;
+      color: #686868;
+    }
+    &.confirm {
+      border: 1px solid $color_main;
+      background-color: $color_main;
+      color: #fff;
+    }
+    &:not(:last-of-type) {
+      margin-right: 48px;
+    }
+  }
+}
+.text-center {
+  ::v-deep {
+    .el-dialog__body {
+      text-align: center;
+    }
+  }
+}
+</style>

+ 97 - 0
src/components/dialog/FollowOfficialAccountDialog.vue

@@ -0,0 +1,97 @@
+<template>
+  <Dialog
+    v-bind="$props"
+    show-close
+    width="336px"
+    top="30vh"
+    class="follow-official-account-dialog"
+    :visible="visible"
+    @update:visible="update">
+    <div class="header-img-container">
+      <img class="header-img" src="@/assets/images/follow-official-account-dialog-header.png" alt="">
+    </div>
+    <div class="content-img-container">
+      <img class="content-img" src="/qr?url=/stl/wxSubscrbePage" alt="">
+    </div>
+    <template #footer>微信扫一扫,关注剑鱼标讯,<br />使用订阅功能</template>
+  </Dialog>
+</template>
+
+<script>
+import Dialog from './Dialog.vue'
+
+export default {
+  name: 'FollowOfficialAccountDialog',
+  components: {
+    Dialog
+  },
+  props: {
+    visible: Boolean
+  },
+  methods: {
+    update (e) {
+      this.$emit('update:visible', e)
+    },
+    onClickCancel () {
+      this.$emit('cancel')
+    },
+    onClickConfirm () {
+      this.$emit('confirm')
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.follow-official-account-dialog {
+  ::v-deep {
+    .el-dialog__header {
+      position: relative;
+      z-index: 2;
+    }
+    .el-dialog__body {
+      position: relative;
+      padding: 0;
+    }
+    .el-dialog__footer {
+      margin-top: 10px;
+      padding-bottom: 32px;
+    }
+    .el-dialog__headerbtn {
+      top: -6px;
+    }
+    .el-icon-close {
+      font-size: 16px;
+      color: $color_main;
+    }
+    .dialog-footer {
+      justify-content: center;
+      font-size: 16px;
+      color: #1D1D1D;
+      line-height: 24px;
+    }
+  }
+}
+.header-img-container,
+.content-img-container {
+  img {
+    width: 100%;
+  }
+}
+.header-img-container {
+  position: absolute;
+  left: 0;
+  top: -116px;
+}
+.content-img-container {
+  padding-top: 80px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  .content-img {
+    display: block;
+    width: 140px;
+    height: 140px;
+  }
+}
+</style>

+ 2 - 0
src/components/selector/AreaSelector.vue

@@ -15,6 +15,7 @@
       :onlyProvince="onlyProvince"
       :singleChoice="singleChoice"
       :initCityMap="initCityMap"
+      :beforeTabClick="beforeTabClick"
       :comtype="comtype"
       @onChange="onChange"
     />
@@ -52,6 +53,7 @@ export default {
       type: Boolean,
       default: false
     },
+    beforeTabClick: Function,
     comtype: {
       type: String,
       default: ''

+ 8 - 0
src/components/selector/AreaSelectorContent.vue

@@ -151,6 +151,7 @@ export default {
       type: Boolean,
       default: false
     },
+    beforeTabClick: Function,
     comtype: {
       type: String,
       default: ''
@@ -381,6 +382,13 @@ export default {
     },
     // 控制城市盒子展开和收起(line)
     changeExpandStateForLine (e, province) {
+      const beforeTabClick = this.beforeTabClick
+      if (beforeTabClick) {
+        const pass = beforeTabClick(e, province)
+        if (!pass) {
+          return
+        }
+      }
       if (province.name === this.expandedProvince.name) return
       // 循环,将其他全部置为false
       for (const key in this.provinceListMap) {

+ 2 - 0
src/components/selector/IndustrySelector.vue

@@ -13,6 +13,7 @@
       @onChange="onChange"
       :dataType="dataType"
       :selectorType="selectorType"
+      :beforeChange="beforeChange"
       :initIndustry="initIndustry"
     />
   </selector-card>
@@ -36,6 +37,7 @@ export default {
       type: String,
       default: 'industry'
     },
+    beforeChange: Function,
     initIndustry: {
       type: Object,
       default () {

+ 9 - 0
src/components/selector/IndustrySelectorContent.vue

@@ -102,6 +102,7 @@ export default {
       type: String,
       default: 'industry'
     },
+    beforeChange: Function,
     initIndustry: {
       type: Object,
       default () {
@@ -220,6 +221,14 @@ export default {
     },
     // 按钮点击事件
     changeIndustryState (item) {
+      const beforeChange = this.beforeChange
+      if (beforeChange) {
+        const pass = beforeChange(item)
+        if (!pass) {
+          return
+        }
+      }
+
       // 循环所有数据,判断并改变状态
       switch (item.level) {
         case 0: {

+ 2 - 0
src/components/selector/InfoTypeSelector.vue

@@ -12,6 +12,7 @@
       ref="content"
       :selectorType="selectorType"
       :initInfoType="initInfoType"
+      :beforeChange="beforeChange"
       @onChange="onChange"
     />
   </selector-card>
@@ -31,6 +32,7 @@ export default {
       type: String,
       default: 'card' // card/line
     },
+    beforeChange: Function,
     initInfoType: {
       type: Array,
       default () {

+ 8 - 0
src/components/selector/InfoTypeSelectorContent.vue

@@ -105,6 +105,7 @@ export default {
       type: String,
       default: 'card' // card/line
     },
+    beforeChange: Function,
     initInfoType: {
       type: Array,
       default () {
@@ -170,6 +171,13 @@ export default {
     },
     // 按钮点击事件
     changeInfoTypeState (item) {
+      const beforeChange = this.beforeChange
+      if (beforeChange) {
+        const pass = beforeChange(item)
+        if (!pass) {
+          return
+        }
+      }
       // 循环所有数据,判断并改变状态
       switch (item.level) {
         case 0: {

+ 8 - 0
src/components/selector/PopSelector.vue

@@ -60,6 +60,7 @@ export default {
       type: String,
       default: 'line' // card/line
     },
+    beforeTabClick: Function,
     showMoreKeyInfoWithCard: { // 是否以卡片展示关键词项的详细内容
       type: Boolean,
       default: false
@@ -219,6 +220,13 @@ export default {
       }
     },
     openChildren (item, e) {
+      const beforeTabClick = this.beforeTabClick
+      if (beforeTabClick) {
+        const pass = beforeTabClick(item)
+        if (!pass) {
+          return
+        }
+      }
       this.changePosition(e)
       this.$nextTick(() => this.changePosition(e))
       this.selectInfo.popStatus.show = true

+ 2 - 0
src/components/selector/PriceSelector.vue

@@ -12,6 +12,7 @@
       ref="content"
       :selectorType="selectorType"
       :defaultSelectedKey="defaultSelectedKey"
+      :beforeConfirm="beforeConfirm"
       @onChange="onChange"
     />
   </selector-card>
@@ -35,6 +36,7 @@ export default {
       type: String,
       default: 'default'
     },
+    beforeConfirm: Function,
     defaultSelectedKey: {
       type: String,
       default: ''

+ 9 - 0
src/components/selector/PriceSelectorContent.vue

@@ -45,6 +45,7 @@ export default {
       default: 'line' // card/line
     },
     // selectSourceList 的 value 以 , 拼接
+    beforeConfirm: Function,
     defaultSelectedKeys: {
       type: String,
       default: ''
@@ -100,6 +101,14 @@ export default {
       }
     },
     onExactConfirm ({ min, max }) {
+      const beforeConfirm = this.beforeConfirm
+      if (beforeConfirm) {
+        const pass = beforeConfirm({ min, max })
+        if (!pass) {
+          return
+        }
+      }
+
       Object.assign(this.price, { min, max })
       this.setExact(true)
       this.onChange()

+ 8 - 0
src/components/selector/RadioGroup.vue

@@ -31,6 +31,7 @@ export default {
       type: String,
       default: 'value'
     },
+    beforeChange: Function,
     value: [String, Number]
   },
   model: {
@@ -39,6 +40,13 @@ export default {
   },
   methods: {
     clickButton (item) {
+      const beforeChange = this.beforeChange
+      if (beforeChange) {
+        const pass = beforeChange(item)
+        if (!pass) {
+          return
+        }
+      }
       const next = item[this.activeKey]
       if (this.value === next) {
         this.$emit('onClick', item)

+ 3 - 1
src/router/router-interceptors.js

@@ -5,7 +5,8 @@ import { getEntNicheAuth } from '@/api/modules'
 
 // 权限控制白名单-路由path
 const powerCheckPathWhiteRegList = [
-  /free_*/
+  /free_*/,
+  /\/big\/page\/index/
 ]
 // 权限控制白名单-路由名
 const powerCheckWhiteList = [
@@ -14,6 +15,7 @@ const powerCheckWhiteList = [
   'ent_ser_portrait',
   'unit_portrayal',
   'ent_follow',
+  'big_subscribe',
   'workspace_dashboard',
   'pro_follow_detail'
 ]

+ 87 - 0
src/store/user.js

@@ -2,10 +2,20 @@ import { recoveryPageData, defaultLocalPageData } from '@/utils/'
 import {
   getEntApi,
   getUserPower,
+  getFreeUserSubscribeList,
+  getSVIPBuyInfo,
+  getEntNicheSubKeyList,
   getBigMemberInfo
 } from '@/api/modules'
 import { formatKeywordsList } from '@/utils/format'
 
+const vtMap = {
+  free: 'f',
+  entniche: 's',
+  svip: 'v',
+  bigmember: 'm'
+}
+
 export default {
   namespaced: true,
   state: () => ({
@@ -23,6 +33,8 @@ export default {
     isDeleteAllScope: defaultLocalPageData('bigmember-login-clear-DELETE_SCOPE', false),
     // 采购内容是否全部删除
     isDeleteAllBuyClass: defaultLocalPageData('bigmember-login-clear-DELETE_BUY_CLASS', false),
+    // 用户订阅关键词列表(包含免费订阅/超级订阅/大会员/商机管理)
+    subscribeKeyList: [],
     // 用户访问灰显记录列表
     visitedList: defaultLocalPageData('visited-path-list', [])
   }),
@@ -49,9 +61,17 @@ export default {
       state.buyClass = data
       localStorage.setItem('bigmember-login-clear-BUY_CLASS', JSON.stringify(data))
     },
+    setSubscribeList (state, list) {
+      if (Array.isArray(list)) {
+        state.subscribeKeyList = list
+      }
+    },
     // 大会员基本信息里所有数据
     setBigKeywords (state, data) {
       state.bigKeywordsData = data
+      if (data.member_jy && Array.isArray(data.member_jy.a_items)) {
+        this.commit('user/setSubscribeList', data.member_jy.a_items)
+      }
       localStorage.setItem('bigmember-login-clear-keywords', JSON.stringify(data))
     },
     // 删除全部业务范围
@@ -121,11 +141,78 @@ export default {
         }
         return formatKeywordsList(data)
       } catch (error) {}
+    },
+    // 免费用户获取订阅关键词
+    async getFreeUserSubscribeList ({ commit }) {
+      try {
+        const { data, error_code: code } = await getFreeUserSubscribeList()
+        if (code === 0 && data.keys) {
+          commit('setSubscribeList', data.keys)
+        }
+      } catch (error) {}
+    },
+    // 超级订阅用户获取订阅关键词
+    async getSvipUserSubscribeList ({ commit }) {
+      try {
+        const { data, error_code: code } = await getSVIPBuyInfo()
+        if (code === 0 && data.items) {
+          commit('setSubscribeList', data.items)
+        }
+      } catch (error) {}
+    },
+    // 商机管理用户获取订阅关键词
+    async getEntNicheUserSubscribeList ({ commit }) {
+      try {
+        const { data, error_code: code } = await getEntNicheSubKeyList()
+        if (code === 0 && data.data) {
+          commit('setSubscribeList', data.data)
+        }
+      } catch (error) {}
+    },
+    // 获取关键词信息
+    async getSubScribeKeyList ({ dispatch }, payload) {
+      const { vt } = payload
+      if (vt === 'f') {
+        // 免费用户
+        await dispatch('getFreeUserSubscribeList')
+      } else if (vt === 'v') {
+        // 超级订阅
+        await dispatch('getSvipUserSubscribeList')
+      } else if (vt === 'm') {
+        // 大会员
+        await dispatch('getKeywordsList')
+      } else if (vt === 's') {
+        // 商机管理
+        await dispatch('getEntNicheUserSubscribeList')
+      } else {
+        // 无操作
+      }
     }
   },
   getters: {
+    // 免费f / 商机管理s / 超级订阅v / 大会员m
+    vt (state, getters) {
+      const { entniche, bigmember, svip } = getters
+      if (entniche) {
+        return vtMap.entniche
+      } else if (bigmember) {
+        return vtMap.bigmember
+      } else if (svip) {
+        return vtMap.svip
+      } else {
+        return vtMap.free
+      }
+    },
+    // 大会员子账号
+    isSubCount: state => state.info.isSubCount,
     // 大会员权限
     power: state => state.power,
+    // 是否免费用户
+    free (_, getters) {
+      const { entniche, bigmember, svip } = getters
+      const vip = entniche || bigmember || svip
+      return !vip
+    },
     // 是否是商机管理
     entniche: state => state.info.entniche,
     // 是否大会员

+ 2 - 22
src/store/workspace/subscribe.js

@@ -1,12 +1,5 @@
 import { getPushList } from '@/api/modules'
 
-const vtMap = {
-  free: 'f',
-  entniche: 's',
-  svip: 'v',
-  bigmember: 'm'
-}
-
 export default {
   namespaced: true,
   state: () => ({
@@ -85,21 +78,8 @@ export default {
   getters: {
     // 免费f / 商机管理s / 超级订阅v / 大会员m
     vt (state, getters, rootState, rootGetters) {
-      const {
-        'user/bigmember': bigmember,
-        'user/entniche': entniche,
-        'user/svip': svip
-      } = rootGetters
-
-      if (entniche) {
-        return vtMap.entniche
-      } else if (bigmember) {
-        return vtMap.bigmember
-      } else if (svip) {
-        return vtMap.svip
-      } else {
-        return vtMap.free
-      }
+      const { 'user/vt': vt } = rootGetters
+      return vt
     }
   }
 }

+ 225 - 45
src/views/SubPush.vue

@@ -1,45 +1,70 @@
 <template>
   <div class="page--sub-push">
     <div class="page-content">
-      <div class="clearfix">
-        <span class="card-title">订阅推送</span>
-        <el-button v-if="canSubmanager" @click="goManage" class="sub-manager" type="plain" icon="el-icon-jy-edit">订阅管理
-        </el-button>
+      <div class="content-header">
+        <span class="header-left card-title">订阅推送</span>
+        <div class="header-right">
+          <el-button v-if="free" @click="toBuySvip" class="sub-manager" type="plain" icon="el-icon-jy-vip">开通超级订阅</el-button>
+          <el-button v-if="showManageButton" @click="goManage" class="sub-manager" type="plain" icon="el-icon-jy-edit">订阅管理</el-button>
+        </div>
+      </div>
+      <div class="max-push-tip red" v-show="tip.maxPushTip">
+        <div class="left">
+          <span class="el-icon-close" @click="tip.maxPushTip = false"></span>
+        </div>
+        <div class="center">本次推送已达150条信息上限,开通超级订阅,支持每天最多推送2000条信息!</div>
+        <div class="right">
+          <button class="action-btn" @click="toBuySvip">立即开通</button>
+        </div>
       </div>
       <div class="border-box">
         <TimeSelector ref="timeSelector" selectorTime="sub"  @onChange="changeTime" selectorType="line">
-          <div slot="header">选择时间:</div>
+          <div class="filter-label" slot="header">选择时间:<span class="el-icon-jy-vip visibility-hidden"></span></div>
         </TimeSelector>
-        <AreaSelector @onChange="changeArea" ref="areaSelector" selectorType="line">
-          <div slot="header">选择区域:</div>
+        <AreaSelector @onChange="changeArea" :beforeTabClick="beforeSelected" ref="areaSelector" selectorType="line">
+          <div class="filter-label" slot="header">选择区域:<span class="el-icon-jy-vip"></span></div>
         </AreaSelector>
-        <IndustrySelector @onChange="changeIndustry"  selectorType="line">
-          <div slot="header">行业:</div>
+        <IndustrySelector @onChange="changeIndustry" :beforeChange="beforeSelected" selectorType="line">
+          <div class="filter-label" slot="header">行业:<span class="el-icon-jy-vip"></span></div>
         </IndustrySelector>
-        <PriceSelector @onChange="onPriceChange" selectorType="line">
-          <div slot="header">价格区间:</div>
+        <PriceSelector @onChange="onPriceChange" :beforeConfirm="beforeSelected" selectorType="line">
+          <div class="filter-label" slot="header">价格区间:<span class="el-icon-jy-vip"></span></div>
         </PriceSelector>
-        <IndustrySelector @onChange="changeBuyer" dataType="buyer" selectorType="line">
-          <div slot="header">采购单位类型:</div>
+        <IndustrySelector class="buyer" @onChange="changeBuyer" :beforeChange="beforeSelected" dataType="buyer" selectorType="line">
+          <div class="filter-label" slot="header">采购单位类型:<span class="el-icon-jy-vip"></span></div>
         </IndustrySelector>
-        <InfoTypeSelector class="my-line" @onChange="changeInfo" selectorType="line">
-          <div slot="header">信息类型:</div>
+        <InfoTypeSelector class="my-line" @onChange="changeInfo" :beforeChange="beforeSelected" selectorType="line">
+          <div class="filter-label" slot="header">信息类型:<span class="el-icon-jy-vip"></span></div>
         </InfoTypeSelector>
-        <PopSelector @onChange="changeKeys" ref="keySelector" selectorType="line">
-          <div slot="header">关键词:</div>
+        <PopSelector @onChange="changeKeys" ref="keySelector" :beforeTabClick="beforeSelected" selectorType="line">
+          <div class="filter-label" slot="header">关键词:<span class="el-icon-jy-vip"></span></div>
         </PopSelector>
         <selectorCard cardType="line">
-          <div slot="header" class="s-header">
-            <slot name="header">附件:</slot>
+          <div slot="header" class="s-header filter-label">
+            <slot name="header">附件:<span class="el-icon-jy-vip"></span></slot>
           </div>
           <RadioGroup
             :sourceList="withFileList"
             v-model="filters.fileExists"
+            :beforeChange="beforeSelected"
             @onChange="onFileStateChange"
           />
         </selectorCard>
       </div>
       <push-list :config="config" :filters="filters" class="m-24" ref="pushList" :showMore="false"></push-list>
+      <Dialog
+        title="开通超级订阅"
+        class="text-center"
+        width="380px"
+        center
+        :visible.sync="dialog.buyVip">
+        立享更多搜索权限,寻找商机更精准
+        <template #footer>
+          <button class="action-button confirm" @click="toBuySvip">去开通</button>
+          <button class="action-button cancel" @click="dialog.buyVip = false">取消</button>
+        </template>
+      </Dialog>
+      <FollowOfficialAccountDialog :visible.sync="dialog.toFollowOfficialAccount"></FollowOfficialAccountDialog>
     </div>
   </div>
 </template>
@@ -55,8 +80,12 @@ import IndustrySelector from '@/components/selector/IndustrySelector.vue'
 import InfoTypeSelector from '@/components/selector/InfoTypeSelector.vue'
 import PriceSelector from '@/components/selector/PriceSelector.vue'
 import RadioGroup from '@/components/selector/RadioGroup.vue'
+import Dialog from '@/components/dialog/Dialog.vue'
+import FollowOfficialAccountDialog from '@/components/dialog/FollowOfficialAccountDialog.vue'
+
+import { getFreeUserPushInfo } from '@/api/modules/'
 
-import { mapState } from 'vuex'
+import { mapState, mapGetters, mapActions } from 'vuex'
 
 export default {
   name: 'SubPush',
@@ -70,10 +99,20 @@ export default {
     InfoTypeSelector,
     PriceSelector,
     RadioGroup,
+    Dialog,
+    FollowOfficialAccountDialog,
     [Button.name]: Button
   },
   data () {
     return {
+      tip: {
+        maxPushTip: false
+      },
+      dialog: {
+        buyVip: false,
+        toFollowOfficialAccount: false
+      },
+      Show: false,
       config: {
         gray: true,
         table: true,
@@ -94,7 +133,7 @@ export default {
         }
       ],
       filters: {
-        vt: 'm',
+        vt: '',
         area: '',
         time: '',
         selectTime: '',
@@ -109,32 +148,103 @@ export default {
       }
     }
   },
+  computed: {
+    vt () {
+      const { vt } = this.filters
+      if (vt) {
+        return vt
+      } else {
+        return this.autoVt
+      }
+    },
+    showManageButton () {
+      // 免费f / 商机管理s / 超级订阅v / 大会员m
+      // 商机管理不显示
+      if (this.vt === 's') {
+        return false
+      }
+      // 子账号不显示
+      if (this.vt === 'm' && this.isSubCount) {
+        return false
+      }
+      return true
+    },
+    ...mapState({
+      subscribeKeyList: state => state.user.subscribeKeyList
+    }),
+    ...mapGetters('user', {
+      autoVt: 'vt'
+    }),
+    ...mapGetters('user', [
+      'isSubCount',
+      'free',
+      'entniche',
+      'bigmember',
+      'svip'
+    ])
+  },
+  async created () {
+    this.getParams()
+    this.getInitInfo()
+    await this.getSubScribeKeyList({ vt: this.vt })
+  },
   mounted () {
     this.initQuery()
     this.initKeyMap()
   },
   watch: {
-    bigKeywordsData: function () {
+    subscribeKeyList: function () {
       this.initKeyMap()
     }
   },
   methods: {
+    ...mapActions('user', [
+      'getSubScribeKeyList'
+    ]),
+    getParams () {
+      const { vt } = this.$route.query
+      if (vt) {
+        this.filters.vt = vt
+      }
+    },
+    getInitInfo () {
+      if (this.vt === 'f') {
+        this.getFreeUserPushInfo()
+      }
+    },
+    async getFreeUserPushInfo () {
+      const { isPassCount } = await getFreeUserPushInfo()
+      if (this.free && isPassCount) {
+        this.tip.maxPushTip = true
+      }
+    },
     initKeyMap () {
-      console.log(this.bigKeywordsData, 'ss')
       const tempKeys = {}
-      // eslint-disable-next-line no-unused-expressions
-      this.bigKeywordsData?.member_jy?.a_items.forEach(v => {
+      if (this.vt === 'f') {
         let tempArr = []
-        v.a_key.forEach(s => {
+        // eslint-disable-next-line no-unused-expressions
+        this.subscribeKeyList.forEach(s => {
           let tempList = s?.key || []
           if (s?.appendkey && s?.key) {
             tempList = [s?.key + ' ' + s?.appendkey.join(' ')]
           }
           tempArr = tempArr.concat(tempList)
         })
-        tempKeys[v.s_item] = tempArr
-      })
-      console.log(tempKeys, 'keys')
+        tempKeys['未分类'] = tempArr
+      } else {
+        // eslint-disable-next-line no-unused-expressions
+        this.subscribeKeyList.forEach(v => {
+          let tempArr = []
+          v.a_key.forEach(s => {
+            let tempList = s?.key || []
+            if (s?.appendkey && s?.key) {
+              tempList = [s?.key + ' ' + s?.appendkey.join(' ')]
+            }
+            tempArr = tempArr.concat(tempList)
+          })
+          tempKeys[v.s_item] = tempArr
+        })
+      }
       this.$refs.keySelector.initDataMap(tempKeys)
     },
     initQuery () {
@@ -184,10 +294,36 @@ export default {
       this.doQuery()
     },
     doQuery () {
-      this.$refs.pushList.doQuery(this.filters)
+      const payload = {
+        ...this.filters,
+        vt: this.vt === 'f' ? '' : this.vt
+      }
+      this.$refs.pushList.doQuery(payload)
     },
     goManage () {
-      this.$router.push('/set_subscribe/config')
+      if (this.vt === 'f') {
+        // 免费用户
+        // 弹窗提示关注公众号
+        this.dialog.toFollowOfficialAccount = true
+      } else if (this.vt === 'v') {
+        // 超级订阅
+        this.dialog.toFollowOfficialAccount = true
+      } else if (this.vt === 'm') {
+        this.$router.push('/set_subscribe/config')
+      } else {
+        // 商机管理该按钮被隐藏,无操作
+      }
+    },
+    toBuySvip () {
+      this.$router.push('/free/svip/buy?type=buy')
+    },
+    beforeSelected () {
+      if (this.free) {
+        this.dialog.buyVip = true
+        return false
+      } else {
+        return true
+      }
     },
     changeTime (item) {
       let time = parseInt(item.start / 1000)
@@ -221,22 +357,12 @@ export default {
       this.filters.city = citys.join(',')
       this.doQuery()
     }
-  },
-  computed: {
-    canSubmanager () {
-      return !this.$store.state.user.info?.isSubCount
-    },
-    ...mapState({
-      bigKeywordsData: state => state.user.bigKeywordsData
-    })
-  },
-  async created () {
-    await this.$store.dispatch('user/getKeywordsList')
   }
 }
 </script>
 
 <style lang="scss" scoped>
+  @include diy-icon('vip', 38, 18);
   @include diy-icon('edit', 20, 20);
   .page--sub-push {
     background-color: #fff;
@@ -281,9 +407,62 @@ export default {
       color: #1d1d1d;
       line-height: 36px;
     }
-    .clearfix .sub-manager {
-      float: right;
-      margin-bottom: 24px;
+    .content-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 24px 0;
+      .header-right {
+        display: flex;
+        align-items: center;
+      }
+      .sub-manager {
+        &:not(:last-of-type) {
+          margin-right: 20px;
+        }
+      }
+    }
+    .visibility-hidden {
+      visibility: hidden;
+    }
+    .buyer {
+      padding-left: 6px;
+    }
+
+    .max-push-tip {
+      display: flex;
+      align-items: center;
+      height: 40px;
+      padding: 0 20px;
+      font-size: 14px;
+      border-radius: 4px;
+      &.red {
+        color: #FF3A20;
+        background-color: rgba(255,58,32,0.1);
+      }
+      .left {
+        font-size: 18px;
+        font-weight: bold;
+      }
+      .el-icon-close {
+        cursor: pointer;
+      }
+      .center {
+        margin: 0 12px;
+      }
+      .action-btn {
+        margin-left: 12px;
+        padding: 4px 16px;
+        background-color: transparent;
+        border: 1px solid #FF3A20;
+        border-radius: 4px;
+      }
+    }
+
+    .filter-label {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
     }
 
     .sub-manager {
@@ -309,6 +488,7 @@ export default {
       padding-bottom: 80px;
     }
     .border-box {
+      margin-top: 12px;
       border: 1px solid #ececec;
       border-radius: 5px;
     }