瀏覽代碼

feat: 工作桌面首页完成

cuiyalong 3 年之前
父節點
當前提交
6a899a5df7

+ 3 - 1
src/App.vue

@@ -15,7 +15,9 @@ export default {
       cashViews: ['list-potential']
     }
   },
-  created () {},
+  created () {
+    this.$store.dispatch('user/getNewEnt')
+  },
   methods: {}
 }
 </script>

+ 9 - 0
src/api/modules/entbase.js

@@ -0,0 +1,9 @@
+import request from '@/api'
+
+export function entBaseInfo () {
+  return request({
+    baseURL: '/entbase',
+    url: '/ent/entinfo',
+    method: 'GET'
+  })
+}

+ 1 - 1
src/api/modules/forecast.js

@@ -32,7 +32,7 @@ export function getResultDetail (data) {
 }
 
 // 我关注的企业列表
-export function getFollowtList (data) {
+export function getEntFollowList (data) {
   data = qs.stringify(data)
   return request({
     url: '/follow/ent/list',

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

@@ -13,3 +13,4 @@ export * from './file'
 export * from './customer'
 export * from './dataExport'
 export * from './workspace'
+export * from './entbase'

+ 25 - 3
src/api/modules/workspace.js

@@ -1,12 +1,12 @@
 import request from '@/api'
-// import qs from 'qs'
+import qs from 'qs'
 
 // 商机管理 - 我的客户
 export function customerQuery (data) {
   return request({
     baseURL: '/entnicheNew',
     url: '/customer/query',
-    method: 'post',
+    method: 'POST',
     data
   })
 }
@@ -16,6 +16,28 @@ export function entNewFollowClientList () {
   return request({
     baseURL: '/entnicheNew',
     url: '/customer/list',
-    method: 'get'
+    method: 'GET'
+  })
+}
+
+// 商机管理 - 过程数据看板 - 数据概览
+export function getEmployeeDataOverview (data) {
+  data = qs.stringify(data)
+  return request({
+    baseURL: '/entnicheNew',
+    url: '/employeeDataBoard/userDataView',
+    method: 'POST',
+    data
+  })
+}
+
+// 消息中心 - 消息列表查询
+export function getMessageCenterList (data) {
+  data = qs.stringify(data)
+  return request({
+    baseURL: '/jymessageCenter',
+    url: '/messageList',
+    method: 'POST',
+    data
   })
 }

+ 8 - 13
src/components/collect-info/CollectInfo.vue

@@ -61,7 +61,6 @@
                       @focus="companyFocus" @input="searchCompany" placeholder="请输入准确的公司名称">
                     </el-input>
                   </el-form-item>
-                  
                   <div class="company-result" v-if="showSearchResult">
                     <div class="company-list" v-for="item in companyList" :key="item" @click="selectCompany(item)"
                       v-html="item"></div>
@@ -876,7 +875,6 @@ export default {
     /*滚动条整体样式*/
     width: 6px;
     height: 1px;
-    
   }
   .user-data-dialog ::-webkit-scrollbar-thumb {
     /*滚动条里面小方块*/
@@ -1014,18 +1012,17 @@ export default {
     border-radius: 4px 4px 4px 4px;
     opacity: 1;
     margin-bottom: 10px;
-    text-align: center;  
+    text-align: center;
     display: flex;
     justify-content: center;
     align-items: center;
     .icon-warning{
-        display: flex;
-        width: 15px;
-        height: 15px;
-        background: url('../../assets/images/icon/icon-warning1.png') no-repeat;
-        background-size: contain;
-        
-        }
+      display: flex;
+      width: 15px;
+      height: 15px;
+      background: url('../../assets/images/icon/icon-warning1.png') no-repeat;
+      background-size: contain;
+    }
     .warm-text{
       // text-align: center;
       line-height: 30px;
@@ -1034,10 +1031,8 @@ export default {
       font-weight: 400;
       color: #F56500;
       margin-left: 2px;
-   
     }
-    }        
-  
+  }
   .dialog-footer {
     padding-top: 20px;
     text-align: center;

+ 1 - 1
src/components/common/Empty.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="empty-container" :class="{ mtb60 }">
     <div class="empty-content-position" :class="[directions]">
-      <el-image :src="images"></el-image>
+      <el-image v-if="images" :src="images"></el-image>
       <div class="empty-main">
         <slot name="default">{{ tip }}</slot>
         <slot name="button"></slot>

+ 1 - 1
src/store/user.js

@@ -10,7 +10,7 @@ export default {
   namespaced: true,
   state: () => ({
     // 新版商机管理判断
-    isNewEnt: recoveryPageData('is-login-new-ent', []),
+    isNewEnt: recoveryPageData('is-login-new-ent', {}),
     power: recoveryPageData('bigmember-login-clear-power', []),
     info: recoveryPageData('bigmember-login-clear-info', {}),
     // 业务范围

+ 28 - 1
src/store/workspace.js

@@ -4,19 +4,46 @@ import subscribe from './workspace/subscribe'
 import customer from './workspace/my-customer'
 import collections from './workspace/collections'
 import customerWatcher from './workspace/customer-watcher'
+import profile from './workspace/business-profile'
+import projectFollow from './workspace/project-follow'
+import entFollow from './workspace/ent-follow'
+import dataReport from './workspace/data-report'
 
 export default {
   namespaced: true,
   state: () => ({}),
   mutations: {},
   actions: {},
-  getters: {},
+  getters: {
+    entniche (state, getters, rootState, rootGetters) {
+      const { 'user/entniche': entniche } = rootGetters
+      return entniche
+    },
+    businessProfileShow (state, getters) {
+      return getters.entniche
+    },
+    myCustomerShow (state, getters) {
+      return getters.entniche
+    },
+    customerWatcherShow (state, getters) {
+      return getters.entniche
+    },
+    // 10: 周报月报+定制化报告
+    dataReportShow (state, getters, rootState, rootGetters) {
+      const { 'user/power': power } = rootGetters
+      return Array.isArray(power) && power.includes(10)
+    }
+  },
   modules: {
     commonUse,
     message,
+    profile,
     subscribe,
     customer,
     collections,
+    projectFollow,
+    entFollow,
+    dataReport,
     customerWatcher
   }
 }

+ 105 - 0
src/store/workspace/business-profile.js

@@ -0,0 +1,105 @@
+import { entBaseInfo, getEmployeeDataOverview } from '@/api/modules'
+import { dateFormatter } from '@/utils'
+
+export default {
+  namespaced: true,
+  state: () => ({
+    entInfo: {
+      admin_department: false,
+      admin_system: false,
+      dept_name: '',
+      ent_name: '',
+      user_name: ''
+    },
+    boardInfo: {}
+  }),
+  mutations: {
+    setEntInfo (state, obj = {}) {
+      Object.assign(state.entInfo, obj)
+    },
+    setBoardInfo (state, obj = {}) {
+      Object.assign(state.boardInfo, obj)
+    }
+  },
+  actions: {
+    async getEntInfo ({ commit, dispatch }) {
+      try {
+        const { data = {}, error_code: code } = await entBaseInfo()
+        if (code === 0 && data) {
+          commit('setEntInfo', data)
+        }
+        dispatch('getBoardInfo')
+        return data
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getBoardInfo ({ dispatch }) {
+      const now = Date.now()
+      const day7 = 7 * 24 * 60 * 60 * 1000
+      await dispatch('getOverview', {
+        entUserId: 0,
+        stime: dateFormatter(now - day7, 'yyyy-MM-dd HH:mm:ss'),
+        etime: dateFormatter(now, 'yyyy-MM-dd HH:mm:ss')
+      })
+    },
+    async getOverview ({ commit }, payload) {
+      try {
+        const { data = {} } = await getEmployeeDataOverview(payload)
+        if (data) {
+          commit('setBoardInfo', data)
+        }
+        return data
+      } catch (error) {
+        console.log(error)
+      }
+    }
+  },
+  getters: {
+    isAdmin (state) {
+      const { entInfo } = state
+      const isAdmin = entInfo.admin_system || entInfo.admin_department
+      return isAdmin
+    },
+    myLocationInEnt (state, getters) {
+      const { entInfo } = state
+      const { isAdmin } = getters
+      const locationArr = []
+      if (entInfo.ent_name) {
+        locationArr.push(entInfo.ent_name)
+      }
+      if (entInfo.dept_name) {
+        locationArr.push(entInfo.dept_name)
+      }
+      if (entInfo.user_name && !isAdmin) {
+        locationArr.push(entInfo.user_name)
+      }
+
+      return [...new Set(locationArr)].join('-')
+    },
+    overviewList (state) {
+      const { boardInfo } = state
+      const increaseProject = {
+        label: '新增项目',
+        count: boardInfo.addProjectCount || 0,
+        className: ''
+      }
+      const dealProject = {
+        label: '成交项目',
+        count: boardInfo.winnerProjectCount || 0,
+        className: ''
+      }
+      const increaseCustomer = {
+        label: '新增客户',
+        count: boardInfo.userAddCusCount || 0,
+        className: ''
+      }
+      const dealCustomer = {
+        label: '成交客户',
+        count: boardInfo.winnerCustomerCount || 0,
+        className: ''
+      }
+      return [increaseProject, dealProject, increaseCustomer, dealCustomer]
+    }
+  }
+}

+ 72 - 0
src/store/workspace/data-report.js

@@ -0,0 +1,72 @@
+// 周报月报
+import { getReportList } from '@/api/modules'
+
+export default {
+  namespaced: true,
+  state: () => ({
+    loading: true,
+    loaded: false,
+    monthList: [],
+    weekList: []
+  }),
+  mutations: {
+    changeMonthList (state, list = []) {
+      if (Array.isArray(list)) {
+        state.monthList = list
+      }
+    },
+    changeWeekList (state, list = []) {
+      if (Array.isArray(list)) {
+        state.weekList = list
+      }
+    },
+    changeLoading (state, f = false) {
+      state.loading = f
+    },
+    changeLoaded (state, f = false) {
+      state.loaded = f
+    }
+  },
+  actions: {
+    async getList ({ dispatch }) {
+      const now = new Date()
+      const currentYear = now.getFullYear()
+      const currentMonth = now.getMonth() + 1
+
+      // 上个月 年月
+      let prevYear = currentYear
+      let prevMonth = currentMonth - 1
+      if (prevMonth < 1) {
+        prevYear -= 1
+        prevMonth = 12
+      }
+      if (prevMonth < 10) {
+        prevMonth = '0' + prevMonth
+      }
+
+      const params = {
+        ym: `${prevYear}${prevMonth}` - 0
+      }
+      await dispatch('doRequest', params)
+    },
+    async doRequest ({ commit }, payload) {
+      try {
+        commit('changeLoading', true)
+        commit('changeLoaded', false)
+        const { weeks = [], months = [] } = await getReportList(payload)
+        if (Array.isArray(weeks)) {
+          commit('changeWeekList', weeks.slice(0, 1))
+        }
+        if (Array.isArray(months)) {
+          commit('changeMonthList', months.slice(0, 1))
+        }
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+      } catch (error) {
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+        console.log(error)
+      }
+    }
+  }
+}

+ 67 - 0
src/store/workspace/ent-follow.js

@@ -0,0 +1,67 @@
+import { getEntFollowList } from '@/api/modules'
+
+export default {
+  namespaced: true,
+  state: () => ({
+    params: {
+      pageNum: 0,
+      pageSize: 5
+    },
+    loading: true,
+    loaded: false,
+    list: []
+  }),
+  mutations: {
+    changeList (state, list = []) {
+      if (Array.isArray(list)) {
+        state.list = list
+      }
+    },
+    changeLoading (state, f = false) {
+      state.loading = f
+    },
+    changeLoaded (state, f = false) {
+      state.loaded = f
+    }
+  },
+  actions: {
+    async getList ({ state, dispatch }) {
+      const { params } = state
+      await dispatch('doRequest', params)
+    },
+    async doRequest ({ commit }, payload) {
+      try {
+        commit('changeLoading', true)
+        commit('changeLoaded', false)
+        const { data = {}, error_code: code } = await getEntFollowList(payload)
+        if (code === 0 && data) {
+          const { list: rList = [] } = data
+          const list = rList.map(v => {
+            // const visited = this.pathVisited(
+            //   this.createPathItem(
+            //     '/article/content/*.html',
+            //     `id=${v.s_entId}`
+            //   )
+            // )
+            return {
+              ...v,
+              // visited,
+              _id: v.s_entId,
+              title: v.s_entname,
+              unread: false,
+              time: v.l_lastpushtime ? v.l_lastpushtime * 1000 : 0
+            }
+          })
+          commit('changeList', list)
+        }
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+        return data || []
+      } catch (error) {
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+        console.log(error)
+      }
+    }
+  }
+}

+ 28 - 9
src/store/workspace/message.js

@@ -1,4 +1,4 @@
-import { latestNews, readMark } from '@/api/modules'
+import { getMessageCenterList, latestNews, readMark } from '@/api/modules'
 import { dateMatter } from '@/utils/'
 
 const messageTypeMap = {
@@ -40,23 +40,42 @@ export default {
     }
   },
   actions: {
-    // 获取所有
-    async getMessageList ({ commit }) {
+    async getList ({ dispatch }) {
+      const params = {
+        needFilter: 0,
+        msgType: 0,
+        isRead: -1,
+        offset: 1,
+        pageSize: 5
+      }
+      dispatch('getMessageList', params)
+      dispatch('getLastNews', params)
+    },
+    async getLastNews ({ commit }) {
+      try {
+        const { count: unReadCount = 0, status } = await latestNews()
+        if (status === 1) {
+          commit('changeUnReadCount', unReadCount)
+        }
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async getMessageList ({ commit }, payload) {
       try {
         commit('changeLoading', true)
         commit('changeLoaded', false)
-        const { count: unReadCount = 0, data = [], status } = await latestNews()
+        const { data = {}, status } = await getMessageCenterList(payload)
+        const { list } = data
         if (status === 1) {
-          commit('changeUnReadCount', unReadCount)
-          if (Array.isArray(data)) {
-            data.forEach(v => {
+          if (Array.isArray(list)) {
+            list.forEach(v => {
               v.messageType = messageTypeText(v.msg_type)
               v.createTime = dateMatter(v.createtime)
             })
-            commit('changeMessageList', data)
+            commit('changeMessageList', list)
           }
         } else {
-          // commit('changeUnReadCount', 0)
           // commit('changeMessageList', [])
         }
         commit('changeLoading', false)

+ 67 - 0
src/store/workspace/project-follow.js

@@ -0,0 +1,67 @@
+import { getFollowProjectList } from '@/api/modules'
+
+export default {
+  namespaced: true,
+  state: () => ({
+    params: {
+      pageNum: 0,
+      pageSize: 5
+    },
+    loading: true,
+    loaded: false,
+    list: []
+  }),
+  mutations: {
+    changeList (state, list = []) {
+      if (Array.isArray(list)) {
+        state.list = list
+      }
+    },
+    changeLoading (state, f = false) {
+      state.loading = f
+    },
+    changeLoaded (state, f = false) {
+      state.loaded = f
+    }
+  },
+  actions: {
+    async getList ({ state, dispatch }) {
+      const { params } = state
+      await dispatch('doRequest', params)
+    },
+    async doRequest ({ commit }, payload) {
+      try {
+        commit('changeLoading', true)
+        commit('changeLoaded', false)
+        const { data = {}, error_code: code } = await getFollowProjectList(payload)
+        if (code === 0 && data) {
+          const { List = [] } = data
+          const list = List.map(v => {
+            // const visited = this.pathVisited(
+            //   this.createPathItem(
+            //     '/article/content/*.html',
+            //     `id=${v.sid}`
+            //   )
+            // )
+            return {
+              ...v,
+              // visited,
+              _id: v.sid,
+              title: v.title,
+              unread: false,
+              time: v.l_lastpushtime ? v.l_lastpushtime * 1000 : 0
+            }
+          })
+          commit('changeList', list)
+        }
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+        return data || []
+      } catch (error) {
+        commit('changeLoading', false)
+        commit('changeLoaded', true)
+        console.log(error)
+      }
+    }
+  }
+}

+ 2 - 1
src/utils/globalFunctions.js

@@ -1,3 +1,4 @@
+import moment from 'moment'
 // 字符串处理相关函数
 // 手机号中间4位加* ------------>
 export function addConfusionForTel (tel) {
@@ -151,7 +152,7 @@ export function formatPrice (s, n = -1, comma = false) {
 export function dateFormatter (date, fmt = 'yyyy-MM-dd HH:mm:ss') {
   // 将传入的date转为时间对象
   if (!date) return ''
-  date = new Date(date)
+  date = moment(date).toDate()
   const o = {
     'y+': date.getFullYear(),
     'M+': date.getMonth() + 1, // 月份

+ 0 - 1
src/views/ProjectProgress.vue

@@ -547,7 +547,6 @@ export default {
     this.changeBusiness([])
   },
   async created () {
-    this.$store.dispatch('user/getNewEnt')
     if (!this.isDeleteAllScope) {
       await this.$store.dispatch('user/getKeywordsList')
     }

+ 2 - 2
src/views/ent-intel/EntIntel.vue

@@ -30,7 +30,7 @@ import ForeCast from '@/components/forecast/ForeCast.vue'
 import TabHeader from '@/components/common/TabHeader.vue'
 import ForFilter from '@/components/forecast/ForFilter.vue'
 import { mapState } from 'vuex'
-import { getFollowtList } from '@/api/modules'
+import { getEntFollowList } from '@/api/modules'
 export default {
   name: 'ent-intel',
   components: {
@@ -79,7 +79,7 @@ export default {
           this.$refs.myList.listState.pageNum = 1
         })
       }
-      getFollowtList({ pageNum: p, pageSize: 20, match: match, group: group }).then(res => {
+      getEntFollowList({ pageNum: p, pageSize: 20, match: match, group: group }).then(res => {
         if (res.error_code === 0 && res.data) {
           this.loading = false
           if (res.data.list) {

+ 1 - 3
src/views/ent-intel/MyClient.vue

@@ -157,9 +157,7 @@ export default {
       return this.client.list.length === 0 && !this.loading
     }
   },
-  created () {
-    this.$store.dispatch('user/getNewEnt')
-  },
+  created () {},
   mounted () {
     this.getClientList()
   },

+ 22 - 12
src/views/workspace/components/BusinessProfile.vue

@@ -1,16 +1,16 @@
 <template>
   <WorkspaceCard title="核心数据" class="business-profile">
-    <div slot="header-right" class="desc">近7天(北京拓普风险信息工程有限公司-销售部-xxx)</div>
+    <div slot="header-right" class="desc">近7天({{ myLocationInEnt }})</div>
     <div class="profile-content">
-      <div class="content-header">
+      <div class="content-header" @click="seeMore">
         <span class="title">商机过程管理</span>
         <span class="more-data">更多分析<i class="el-icon-arrow-right"></i></span>
       </div>
       <div class="content-list">
-        <div class="list-item" v-for="item in 4" :key="item">
-          <span class="i-label">新增项目</span>
+        <div class="list-item" :class="[item.className]" v-for="(item, index) in overviewList" :key="index">
+          <span class="i-label">{{ item.label }}</span>
           <span class="text-container">
-            <span class="i-count">10</span>
+            <span class="i-count">{{ item.count }}</span>
             <span class="suffix-unit">个</span>
           </span>
         </div>
@@ -20,6 +20,7 @@
 </template>
 
 <script>
+import { mapActions, mapGetters } from 'vuex'
 import { Icon } from 'element-ui'
 import WorkspaceCard from './WorkspaceCard'
 
@@ -29,14 +30,23 @@ export default {
     [Icon.name]: Icon,
     WorkspaceCard
   },
-  data () {
-    return {
-      loading: true,
-      loaded: false
-    }
+  computed: {
+    ...mapGetters('workspace/profile', [
+      'myLocationInEnt',
+      'overviewList'
+    ])
+  },
+  created () {
+    this.getEntInfo()
   },
-  created () {},
-  methods: {}
+  methods: {
+    ...mapActions('workspace/profile', [
+      'getEntInfo'
+    ]),
+    seeMore () {
+      window.open('/entpc/newBus/board?m1=3&m2=0')
+    }
+  }
 }
 </script>
 

+ 4 - 2
src/views/workspace/components/CommonUse.vue

@@ -61,8 +61,7 @@ export default {
   methods: {
     ...mapMutations('workspace/commonUse', [
       'changeDialogState',
-      'transferSave',
-      'openLink'
+      'transferSave'
     ]),
     ...mapActions('workspace/commonUse', [
       'getAllFunctions',
@@ -73,6 +72,9 @@ export default {
     onTransferSave (data) {
       this.transferSave(data)
     },
+    openLink (url) {
+      window.open(url)
+    },
     confirmSaveFn () {
       try {
         this.confirmSave()

+ 9 - 4
src/views/workspace/components/CustomerWatcher.vue

@@ -1,5 +1,5 @@
 <template>
-  <!-- 商机管理我关注的客户 -->
+  <!-- 商机管理我关注的客户 - 采购单位画像关注 -->
   <ListCard
     class="customer-watcher"
     :list="list"
@@ -35,6 +35,10 @@ export default {
     ...mapActions('workspace/customerWatcher', [
       'getList'
     ]),
+    resolveLink (link) {
+      const { href } = this.$router.resolve(link)
+      return href
+    },
     clickListItem (item) {
       // this.pathVisiting(
       //   this.createPathItem(
@@ -42,11 +46,12 @@ export default {
       //     `id=${item.name}`
       //   )
       // )
-      const href = `/entpc/unit_portrayal/${item.name}`
-      window.open(href)
+      // window.open(`/entpc/unit_portrayal/${item.name}`)
+      window.open(this.resolveLink(`/unit_portrayal/${item.name}`))
     },
     linkMore () {
-      window.open('/entpc/newBus/client_follow')
+      // window.open('/entpc/newBus/client_follow')
+      window.open(this.resolveLink('/my_client'))
     }
   }
 }

+ 163 - 0
src/views/workspace/components/DataReport.vue

@@ -0,0 +1,163 @@
+<template>
+  <div class="data-report">
+    <ListCard
+      class="report-card report-week"
+      title="周报"
+      :list="weekList"
+      @linkMore="linkMore('week')"
+      :loading="loading"
+      :loaded="loaded">
+      <div class="report-content">
+        <div
+          class="report-item"
+          v-for="(item, index) in weekList"
+          :key="index">
+          <div class="report-left" @click="clickListItem('week', item)">
+            <span class="report-round main">周</span>
+            <span class="report-title">{{ dateFormatter(item.startdate * 1000, 'MM月dd日')}}-{{ dateFormatter(item.enddate * 1000, 'MM月dd日')}}</span>
+            <span class="red-dot" v-if="item.unread && item.unread !== 0"></span>
+          </div>
+          <div class="report-right r-time" v-if="item.pushtime">{{dateFormatter(item.pushtime * 1000, 'yyyy/MM/dd')}}</div>
+        </div>
+        <Empty
+          images=""
+          :mtb60="false"
+          direction="row"
+          v-if="emptyWeekShow">本周结束后,将为您推送周报,敬请期待~</Empty>
+      </div>
+    </ListCard>
+    <ListCard
+      class="report-card report-month"
+      title="月报"
+      :list="monthList"
+      @linkMore="linkMore('month')"
+      :loading="loading"
+      :loaded="loaded">
+      <div class="report-content">
+        <div
+          class="report-item"
+          v-for="(item, index) in monthList"
+          :key="index">
+          <div class="report-left" @click="clickListItem('month', item)">
+            <span class="report-round yellow">月</span>
+            <span class="report-title">{{dateFormatter(item.startdate * 1000, 'MM月dd日')}}-{{dateFormatter(item.enddate * 1000, 'MM月dd日')}}</span>
+            <span class="red-dot" v-if="item.unread && item.unread !== 0"></span>
+          </div>
+          <div class="report-right r-time" v-if="item.pushtime">{{dateFormatter(item.pushtime * 1000, 'yyyy/MM/dd')}}</div>
+        </div>
+        <Empty
+          images=""
+          :mtb60="false"
+          direction="row"
+          v-if="emptyMonthShow">本月结束后,将为您推送月报,敬请期待~~</Empty>
+      </div>
+    </ListCard>
+  </div>
+</template>
+
+<script>
+import { mapState, mapActions } from 'vuex'
+import ListCard from './ListCard'
+import Empty from '@/components/common/Empty.vue'
+import { dateFormatter } from '@/utils/'
+
+export default {
+  name: 'DataReport',
+  components: {
+    Empty,
+    ListCard
+  },
+  computed: {
+    emptyWeekShow () {
+      return this.loaded && this.weekList.length === 0
+    },
+    emptyMonthShow () {
+      return this.loaded && this.monthList.length === 0
+    },
+    ...mapState({
+      loading: state => state.workspace.dataReport.loading,
+      loaded: state => state.workspace.dataReport.loaded,
+      weekList: state => state.workspace.dataReport.weekList,
+      monthList: state => state.workspace.dataReport.monthList
+    })
+  },
+  created () {
+    this.getList()
+  },
+  methods: {
+    dateFormatter,
+    ...mapActions('workspace/dataReport', [
+      'getList'
+    ]),
+    resolveLink (link) {
+      const { href } = this.$router.resolve(link)
+      return href
+    },
+    clickListItem (type, item) {
+      if (type === 'week') {
+        window.open(this.resolveLink(`/bigvip_subreport_week?start=${item.startdate}&end=${item.enddate}`))
+      } else if (type === 'month') {
+        window.open(this.resolveLink(`/bigvip_subreport_month?start=${item.startdate}&end=${item.enddate}`))
+      }
+    },
+    linkMore (type) {
+      if (type === 'week') {
+        window.open(this.resolveLink('/bigvip_subreport_week'))
+      } else if (type === 'month') {
+        window.open(this.resolveLink('/bigvip_subreport_month'))
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+::v-deep {
+  .list-container {
+    min-height: unset;
+  }
+  .empty-container {
+    margin-top: -8px;
+  }
+}
+.data-report {
+  display: flex;
+  width: 100%;
+}
+.report-item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 12px 0;
+}
+.report-left {
+  display: flex;
+  align-items: center;
+}
+.report-title {
+  margin: 0 8px;
+  font-size: 14px;
+  color: #1D1D1D;
+  line-height: 22px;
+  cursor: pointer;
+  &:hover {
+    color: #2cb7ca;
+  }
+}
+.report-round {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  font-size: 13px;
+  color: #fff;
+  border-radius: 50%;
+  &.main {
+    background-color: #2cb7ca;
+  }
+  &.yellow {
+    background-color: #ff9f40;
+  }
+}
+</style>

+ 76 - 0
src/views/workspace/components/EntFollow.vue

@@ -0,0 +1,76 @@
+<template>
+  <!-- 企业关注 - 企业画像关注 -->
+  <ListCard
+    class="ent-follow"
+    :list="list"
+    title="企业情报监控"
+    @clickListItem="clickListItem"
+    @linkMore="linkMore"
+    :loading="loading"
+    :loaded="loaded">
+    <div slot="empty-content" class="empty-content">
+      <p>暂无企业情报信息,前往企业搜索关注企业</p>
+      <button class="empty-button mt12" @click="toFollow">添加关注企业</button>
+    </div>
+  </ListCard>
+</template>
+
+<script>
+import { mapState, mapActions, mapGetters } from 'vuex'
+import ListCard from './ListCard'
+
+export default {
+  name: 'EntFollow',
+  components: {
+    ListCard
+  },
+  computed: {
+    ...mapGetters('user', [
+      'entniche', // 是否是商机管理
+      'bigmember', // 是否大会员
+      'svip', // 是否是超级订阅
+      'power'
+    ]),
+    ...mapState({
+      loading: state => state.workspace.entFollow.loading,
+      loaded: state => state.workspace.entFollow.loaded,
+      list: state => state.workspace.entFollow.list
+    })
+  },
+  created () {
+    this.getList()
+  },
+  methods: {
+    ...mapActions('workspace/entFollow', [
+      'getList'
+    ]),
+    resolveLink (link) {
+      const { href } = this.$router.resolve(link)
+      return href
+    },
+    clickListItem (item) {
+      // this.pathVisiting(
+      //   this.createPathItem(
+      //     '/ent_portrait/*',
+      //     `id=${item._id}`
+      //   )
+      // )
+      if (this.entniche) {
+        window.open(this.resolveLink(`/ent_portrait/${item._id}`))
+      } else {
+        window.open(this.resolveLink(`/ent_portrait/${item._id}`))
+      }
+    },
+    linkMore () {
+      window.open(this.resolveLink('/free/ent_follow'))
+    },
+    toFollow () {
+      window.open('/jylab/entSearch/index.html')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 18 - 16
src/views/workspace/components/ListCard.vue

@@ -7,23 +7,25 @@
       </div>
     </slot>
     <div class="list-container" v-loading="loading">
-      <div
-        class="list-item"
-        :class="{ visited: item.visited, last: index === list.length - 1 }"
-        v-for="(item, index) in list"
-        @click="clickListItem(item)"
-        :key="index">
-        <div class="list-item-l ellipsis visited-hd">{{ item.title }}</div>
-        <div class="list-item-r">
-          <span class="red-dot" v-if="item.unread && item.unread !== 0"></span>
-          <span class="r-time" v-if="item.time">{{ dateFormatter(item.time, 'yyyy-MM-dd') }}</span>
+      <slot name="default">
+        <div
+          class="list-item"
+          :class="{ visited: item.visited, last: index === list.length - 1 }"
+          v-for="(item, index) in list"
+          @click="clickListItem(item)"
+          :key="index">
+          <div class="list-item-l ellipsis visited-hd">{{ item.title }}</div>
+          <div class="list-item-r">
+            <span class="red-dot" v-if="item.unread && item.unread !== 0"></span>
+            <span class="r-time" v-if="item.time">{{ dateFormatter(item.time, 'yyyy-MM-dd') }}</span>
+          </div>
         </div>
-      </div>
-      <div class="empty-wrapper" v-show="list.length === 0 && loaded">
-        <Empty class="empty-mini" direction="row" :mtb60="false">
-          <slot name="empty-content">暂无数据</slot>
-        </Empty>
-      </div>
+        <div class="empty-wrapper" v-show="list.length === 0 && loaded">
+          <Empty class="empty-mini" direction="row" :mtb60="false">
+            <slot name="empty-content">暂无数据</slot>
+          </Empty>
+        </div>
+      </slot>
     </div>
   </WorkspaceCard>
 </template>

+ 11 - 5
src/views/workspace/components/MessageTips.vue

@@ -1,5 +1,9 @@
 <template>
-  <WorkspaceCard class="message-card" title="我的消息" v-show="messageList.length">
+  <WorkspaceCard class="message-card" v-show="messageList.length">
+    <div slot="header-title">
+      <span>我的消息</span>
+      <span class="sub-text">(<span class="highlight-text">{{ unReadCount }} </span> 条未读)</span>
+    </div>
     <div slot="header-right" class="header-right-set" @click="toMessageCenter">更多<i class="icon el-icon-arrow-right"></i></div>
     <div class="message-content message-list" v-loading="loading">
       <div class="message-item" v-for="item in messageList" :key="item.id">
@@ -41,12 +45,9 @@ export default {
   },
   methods: {
     ...mapActions('workspace/message', [
-      'getMessageList',
+      'getList',
       'remarkRead'
     ]),
-    async getList () {
-      await this.getMessageList()
-    },
     async titleGoto (item) {
       try {
         await this.remarkRead(item)
@@ -72,6 +73,11 @@ export default {
   }
 }
 
+.sub-text {
+  font-size: 14px;
+  color: #999;
+}
+
 .header-right-set {
   display: flex;
   align-items: center;

+ 67 - 0
src/views/workspace/components/ProjectFollow.vue

@@ -0,0 +1,67 @@
+<template>
+  <!-- 项目关注 -->
+  <ListCard
+    class="project-follow"
+    :list="list"
+    title="项目进度监控"
+    @clickListItem="clickListItem"
+    @linkMore="linkMore"
+    :loading="loading"
+    :loaded="loaded">
+    <div slot="empty-content" class="empty-content">
+      <p>暂无项目进度信息,前往招标搜索关注项目</p>
+      <button class="empty-button mt12" @click="toFollow">添加关注项目</button>
+    </div>
+  </ListCard>
+</template>
+
+<script>
+import { mapState, mapActions } from 'vuex'
+import ListCard from './ListCard'
+
+export default {
+  name: 'ProjectFollow',
+  components: {
+    ListCard
+  },
+  computed: {
+    ...mapState({
+      loading: state => state.workspace.projectFollow.loading,
+      loaded: state => state.workspace.projectFollow.loaded,
+      list: state => state.workspace.projectFollow.list
+    })
+  },
+  created () {
+    this.getList()
+  },
+  methods: {
+    ...mapActions('workspace/projectFollow', [
+      'getList'
+    ]),
+    resolveLink (link) {
+      const { href } = this.$router.resolve(link)
+      return href
+    },
+    clickListItem (item) {
+      const { sid, fid } = item
+      // this.pathVisiting(
+      //   this.createPathItem(
+      //     '/pro_follow_detail/*',
+      //     `id=${sid}`
+      //   )
+      // )
+      window.open(this.resolveLink(`/pro_follow_detail?sid=${sid}&fid=${fid}`))
+    },
+    linkMore () {
+      window.open(this.resolveLink('/free/project_progress'))
+    },
+    toFollow () {
+      window.open('/jylab/supsearch/index.html')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 33 - 12
src/views/workspace/dashboard.vue

@@ -2,15 +2,22 @@
   <el-container class="workspace-dashboard">
     <el-main>
       <CommonUse class="main-module"></CommonUse>
-      <BusinessProfile class="main-module"></BusinessProfile>
-      <div class="main-module card-list-module">
-        <MyCustomer></MyCustomer>
-        <CustomerWatcher></CustomerWatcher>
+      <BusinessProfile v-if="businessProfileShow" class="main-module"></BusinessProfile>
+      <div class="main-module card-list-module" v-if="myCustomerShow || customerWatcherShow">
+        <MyCustomer v-if="myCustomerShow"></MyCustomer>
+        <CustomerWatcher v-if="customerWatcherShow"></CustomerWatcher>
       </div>
       <div class="main-module card-list-module">
         <SubscribeList></SubscribeList>
         <MyCollections></MyCollections>
       </div>
+      <div class="main-module card-list-module">
+        <ProjectFollow></ProjectFollow>
+        <EntFollow></EntFollow>
+      </div>
+      <div class="main-module card-list-module" v-if="dataReportShow">
+        <DataReport></DataReport>
+      </div>
     </el-main>
     <el-aside width="396px">
       <MessageTips></MessageTips>
@@ -19,6 +26,7 @@
 </template>
 
 <script>
+import { mapGetters } from 'vuex'
 import { Container, Aside, Main } from 'element-ui'
 import MessageTips from './components//MessageTips.vue'
 import CommonUse from './components/CommonUse.vue'
@@ -27,6 +35,9 @@ import MyCustomer from './components/MyCustomer.vue'
 import CustomerWatcher from './components/CustomerWatcher.vue'
 import SubscribeList from './components/SubscribeList.vue'
 import MyCollections from './components/MyCollections.vue'
+import ProjectFollow from './components/ProjectFollow.vue'
+import EntFollow from './components/EntFollow.vue'
+import DataReport from './components/DataReport.vue'
 export default {
   name: 'WorkspaceDashboard',
   components: {
@@ -39,10 +50,18 @@ export default {
     MyCustomer,
     CustomerWatcher,
     SubscribeList,
-    MyCollections
+    MyCollections,
+    ProjectFollow,
+    DataReport,
+    EntFollow
   },
-  data () {
-    return {}
+  computed: {
+    ...mapGetters('workspace', [
+      'businessProfileShow',
+      'myCustomerShow',
+      'customerWatcherShow',
+      'dataReportShow'
+    ])
   }
 }
 </script>
@@ -61,11 +80,13 @@ export default {
 }
 .card-list-module {
   display: flex;
-  .list-card {
-    flex: 1;
-    max-width: 49%;
-    &:not(:first-of-type) {
-      margin-left: 16px;
+  ::v-deep {
+    .list-card {
+      flex: 1;
+      max-width: 49%;
+      &:not(:first-of-type) {
+        margin-left: 16px;
+      }
     }
   }
 }

+ 6 - 0
vue.config.js

@@ -72,6 +72,12 @@ module.exports = {
         changeOrigin: true,
         logLevel: 'debug'
       },
+      '^/entbase': {
+        target: 'https://jybx2-webtest.jydev.jianyu360.com',
+        // target: 'http://127.0.0.1:829',
+        changeOrigin: true,
+        logLevel: 'debug'
+      },
       '^/entnicheNew': {
         target: 'https://jybx2-webtest.jydev.jianyu360.com',
         // target: 'http://127.0.0.1:829',

+ 3 - 13
yarn.lock

@@ -918,9 +918,9 @@
     postcss "^7.0.0"
 
 "@jianyu/easy-inject-qiankun@^0.1.1":
-  version "0.1.1"
-  resolved "http://192.168.3.207:4873/@jianyu%2feasy-inject-qiankun/-/easy-inject-qiankun-0.1.1.tgz#0671a8b1453bc0ccbbccde3855bfc8b1e58f7ff5"
-  integrity sha512-9DbSSMZ3L4OA7WGoCsOd7tkfcgElfD2kbsrQONB5NtIvKFH8qbbgPzK4NAmQAtxqc8AyaEWgZ/Av872QegomJw==
+  version "0.1.4"
+  resolved "http://192.168.3.207:4873/@jianyu%2feasy-inject-qiankun/-/easy-inject-qiankun-0.1.4.tgz#da9f215b4821c43a834f8d8ee5e97b870f748b83"
+  integrity sha512-YFPNQnrl9FQ9AJBQ7d/tsTobr5i34BI04jQ4AZ2M/lIjDspj8nSgcC8CSUQ1VVNBCicpSxHv/oAuDveCJXagvg==
 
 "@mrmlnc/readdir-enhanced@^2.2.1":
   version "2.2.1"
@@ -7604,11 +7604,6 @@ simple-swizzle@^0.2.2:
   dependencies:
     is-arrayish "^0.3.1"
 
-single-spa-vue@^1.5.4:
-  version "1.10.1"
-  resolved "https://registry.npm.taobao.org/single-spa-vue/download/single-spa-vue-1.10.1.tgz#80cbb603dc8eaec4148577b3570fa04b2d45ee16"
-  integrity sha1-gMu2A9yOrsQUhXezVw+gSy1F7hY=
-
 sirv@^1.0.7:
   version "1.0.11"
   resolved "https://registry.npm.taobao.org/sirv/download/sirv-1.0.11.tgz#81c19a29202048507d6ec0d8ba8910fda52eb5a4"
@@ -8057,11 +8052,6 @@ svgo@^1.0.0:
     unquote "~1.1.1"
     util.promisify "~1.0.0"
 
-systemjs-webpack-interop@^1.1.2:
-  version "1.2.1"
-  resolved "https://registry.npm.taobao.org/systemjs-webpack-interop/download/systemjs-webpack-interop-1.2.1.tgz#70cce64a93ff646f52344eb560288d83362c9695"
-  integrity sha1-cMzmSpP/ZG9SNE61YCiNgzYslpU=
-
 table@^5.2.3:
   version "5.4.6"
   resolved "https://registry.npm.taobao.org/table/download/table-5.4.6.tgz?cache=0&sync_timestamp=1609732718890&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftable%2Fdownload%2Ftable-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"