Jelajahi Sumber

feat: 定制化分析报告

tsz 2 tahun lalu
induk
melakukan
fcd092be29

+ 11 - 0
public/index.html

@@ -30,6 +30,7 @@
     <!-- 使用CDN的CSS文件 -->
     <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
     <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/style.min.css />
     <% } %>
     <!-- 使用CDN的JS文件 -->
     <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
@@ -37,7 +38,17 @@
     <% } %>
     <% if (process.env.NODE_ENV === 'production') { %>
       <script src="/antiRes/js/mainHook.js"></script>
+      <script defer src="http://127.0.0.1/common-module/chart-module/js/chart-common.js"></script>
     <% } %>
+    <% if (process.env.NODE_ENV === 'development') { %>
+      <!-- test--- 加载 公共js方法 -->
+      <script src="//cdn-common.jianyu360.com/cdn/lib/lodash/4.17.21/lodash.min.js"></script>
+       <script defer src="http://127.0.0.1/common-module/chart-module/js/chart-common.js"></script>
+       <script src="//cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js"></script>
+       <script src=//cdn-common.jianyu360.com/cdn/lib/echarts/4.8.0/echarts.min.js></script>
+       <script src=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/index.min.js></script>
+       <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/style.min.css />
+     <% } %>
   </head>
   <style>
     .big-member-page {

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

@@ -19,3 +19,4 @@ export * from './workspace'
 export * from './entbase'
 export * from './public'
 export * from './entnicheNew'
+export * from './leadGeneration'

+ 13 - 0
src/api/modules/leadGeneration.js

@@ -0,0 +1,13 @@
+import request from '@/api'
+import qs from 'qs'
+
+// 定制化分析报告&超前项目
+export function leadGetDate (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/leadGeneration/getDate',
+    baseURL: '/jyapi',
+    method: 'post',
+    data
+  })
+}

+ 251 - 0
src/components/custom-report/customReport.vue

@@ -0,0 +1,251 @@
+<template>
+  <div class="custom-report">
+    <div class="c-a-r-top">
+      <div class="c-a-r-title">
+        <div class="r-title-text">定制化分析报告</div>
+        <div class="r-title-tip">
+          量身定制个性化报告,分析市场竞争格局,为企业找准市场机会!
+        </div>
+      </div>
+      <div class="c-a-r-option">
+        <div class="c-view-report c-view-common">查看完整报告</div>
+        <div class="c-view-interest c-view-common">感兴趣点我</div>
+      </div>
+    </div>
+    <div class="c-a-r-chart">
+      <div class="chart-common" id="customerChart"  v-if="showModuleChart!=='customer_scale'">
+        <div class="chart-title">客户分布:</div>
+        <div class="c-c-content">
+          <div id="chartTreeMap"></div>
+        </div>
+      </div>
+      <div class="chart-common" id="winnerChart" v-if="showModuleChart!=='winner_time_distribution'">
+        <div class="chart-title">中标规模分布:</div>
+        <div class="c-c-content chart-line">
+          <div id="chartLineChart"></div>
+        </div>
+      </div>
+      <div class="chart-common" id="buyerChart" v-if="showModuleChart!=='buyer_time_distribution'">
+        <div class="chart-title">采购规模分布:</div>
+        <div class="c-c-content chart-line">
+          <div id="chartLineChartBuyer"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { formatPrice } from '@/utils/'
+export default {
+  name: 'custom-report',
+  props: {
+    chartCustomData: {
+      type: Object,
+      default () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+    }
+  },
+  computed: {
+    showModuleChart () {
+      const chartKeyArr = Object.keys(this.chartCustomData)
+      const fieldText = this.getRandomArrayElements(chartKeyArr, 2)
+      const noShowFiled = _.difference(chartKeyArr, fieldText)
+      return noShowFiled[0]
+    }
+  },
+  watch: {
+    'chartCustomData' (newval) {
+      let data
+      const chartKeyArr = Object.keys(newval)
+      chartKeyArr.forEach(item => {
+        if (item === 'customer_scale') {
+          data = newval.customer_scale.map(item => {
+            return {
+              ...item,
+              name: item.buyclass,
+              value: item.total,
+              amount: formatPrice(item.amount / 10000)
+            }
+          })
+          vComponentChart('#chartTreeMap', data, {}, 've-treemap')
+        } else if (item === 'winner_time_distribution') {
+          data = {
+            columns: ['采购规模分布', '采购总金额占比', '采购单位总数占比'],
+            rows: []
+          }
+          let total = 0
+          const chartLIst = newval.winner_time_distribution
+          if (Array.isArray(chartLIst)) {
+            const field = {
+              [data.columns[0]]: 'key',
+              [data.columns[1]]: 'total_amount',
+              [data.columns[2]]: 'total_number'
+            }
+            chartLIst.forEach(item => {
+              const row = {}
+              data.columns.forEach(column => {
+                if (field[column] === 'total_amount' || field[column] === 'total_number') {
+                  row[column] = (item[field[column]] * 100).toFixed(2)
+                  total += (item[field[column]] - 0)
+                } else {
+                  row[column] = item[field[column]]
+                }
+              })
+              data.rows.push(row)
+            })
+          }
+          if (total) {
+            data.rows.reverse()
+            vComponentChart('#chartLineChartBuyer', data, {}, 've-line')
+          }
+        } else if (item === 'buyer_time_distribution') {
+          data = {
+            columns: ['中标规模分布', '中标总金额占比', '中标单位总数占比'],
+            rows: []
+          }
+          let total = 0
+          const buyerclassList = newval.buyer_time_distribution
+          if (Array.isArray(buyerclassList)) {
+            const field = {
+              [data.columns[0]]: 'key',
+              [data.columns[1]]: 'total_amount',
+              [data.columns[2]]: 'total_number'
+            }
+            buyerclassList.forEach(item => {
+              const row = {}
+              data.columns.forEach(column => {
+                if (field[column] === 'total_amount' || field[column] === 'total_number') {
+                  row[column] = (item[field[column]] * 100).toFixed(2)
+                  total += (item[field[column]] - 0)
+                } else {
+                  row[column] = item[field[column]]
+                }
+              })
+              data.rows.push(row)
+            })
+          }
+          if (total) {
+            data.rows.reverse()
+            vComponentChart('#chartLineChart', data, {}, 've-line')
+          }
+        }
+      })
+    }
+  },
+  methods: {
+    // /* 随机获取数组中的数据*/
+    getRandomArrayElements (arr, count) {
+      const shuffled = arr.slice(0)
+      let i = arr.length
+      const min = i - count
+      let temp
+      let index
+      while (i-- > min) {
+        index = Math.floor((i + 1) * Math.random())
+        temp = shuffled[index]
+        shuffled[index] = shuffled[i]
+        shuffled[i] = temp
+      }
+      return shuffled.slice(min)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .custom-report{
+    padding: 0 32px;
+    .c-a-r-top {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        height: 60px;
+        border-bottom: 1px dashed #E0E0E0;
+        .c-a-r-title{
+          display: flex;
+          align-items: center;
+          height: 100%;
+          line-height: 21px;
+          font-family: 'Microsoft YaHei';
+          font-style: normal;
+          font-weight: 400;
+        }
+        .r-title-text{
+          display: flex;
+          align-items: center;
+          width: fit-content;
+          height: 95%;
+          margin-top: 5px;
+          color: #2CB7CA;
+          font-size: 16px;
+          border-bottom: 2px solid #2CB7CA;
+        }
+        .r-title-tip{
+          margin-top: 5px;
+          margin-left: 32px;
+          color: #686868;
+          font-size: 14px;
+        }
+      }
+      .c-a-r-option{
+        display: flex;
+        align-items: center;
+      }
+      .c-view-common{
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        padding: 0 17px;
+        height: 30px;
+        font-family: 'Microsoft YaHei';
+        font-style: normal;
+        font-weight: 400;
+        font-size: 14px;
+        line-height: 22px;
+        border-radius: 4px;
+        cursor: pointer;
+      }
+      .c-view-report{
+        border: 1px solid #2ABED1;
+        color: #2ABED1;
+      }
+      .chart-common{
+        /* width: 590px; */
+        height: 280px;
+      }
+
+      .c-c-content{
+        width: 383px;
+        height: 211px;
+      }
+      .c-c-content.chart-line {
+        width: 558px;
+      }
+      .c-view-interest{
+        margin-left: 36px;
+        background: #2ABED1;
+        color: #fff;
+      }
+      .c-a-r-chart{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-top: 16px;
+      }
+      .chart-title {
+        padding: 16px 0 12px 0;
+        font-family: 'Microsoft YaHei';
+        font-style: normal;
+        font-weight: 400;
+        font-size: 16px;
+        line-height: 24px;
+        color: #1D1D1D;
+      }
+  }
+</style>

+ 134 - 2
src/views/SubPush.vue

@@ -51,6 +51,27 @@
           />
         </selectorCard>
       </div>
+      <!-- 超前项目推荐&&定制化分析报告 -->
+      <div id="jyChartCom">
+        <div class="advanced-pro-rec">
+          <div class="c-a-r-top">
+            <div class="c-a-r-title">
+              <div class="r-title-text">超前项目推荐</div>
+              <div class="r-title-tip">
+                提前推送超前项目,优先对接项目负责人
+              </div>
+            </div>
+            <div class="c-a-r-option">
+              <div class="c-view-interest c-view-common">感兴趣点我</div>
+              <div class="c-view-report c-view-common">收起</div>
+            </div>
+          </div>
+        </div>
+        <!-- 定制化分析报告 -->
+        <div>
+          <custom-report :chartCustomData="chartCustomData"></custom-report>
+        </div>
+      </div>
       <push-list :vt="vt" :config="config" showManageButton :filters="filters" class="m-24" ref="pushList" :showMore="false"></push-list>
       <Dialog
         title="开通超级订阅"
@@ -86,9 +107,10 @@ 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 CustomReport from '@/components/custom-report/customReport.vue'
 import FollowOfficialAccountDialog from '@/components/dialog/FollowOfficialAccountDialog.vue'
 import ConfigContent from '@/components/subscribe-manager/index'
-import { getFreeUserPushInfo, updateVipSubscribe } from '@/api/modules/'
+import { getFreeUserPushInfo, updateVipSubscribe, leadGetDate } from '@/api/modules/'
 import { dateFormatter, openSelfLink } from '@/utils/'
 import { mapState, mapGetters, mapActions } from 'vuex'
 
@@ -106,6 +128,7 @@ export default {
     RadioGroup,
     DrawerCard,
     Dialog,
+    CustomReport,
     FollowOfficialAccountDialog,
     ConfigContent,
     [Button.name]: Button
@@ -152,7 +175,8 @@ export default {
         price: '',
         exportNum: ''
       },
-      showDrawer: false // 订阅设置弹窗
+      showDrawer: false, // 订阅设置弹窗
+      chartCustomData: {}
     }
   },
   computed: {
@@ -208,6 +232,7 @@ export default {
   mounted () {
     this.initQuery()
     this.initKeyMap()
+    this.getCustomReportData()
   },
   watch: {
     subscribeKeyList: function () {
@@ -408,6 +433,19 @@ export default {
       } else {
         this.$toast(msg, 2000)
       }
+    },
+    // 定制化分析报告&&超前项目推荐数据请求
+    async getCustomReportData () {
+      const params = {
+        dType: 1,
+        keyWords: ''
+      }
+      try {
+        const { error_code: code = 0, data } = await leadGetDate(params)
+        if (code === 0 && data) {
+          this.chartCustomData = data.custom
+        }
+      } catch (error) {}
     }
   }
 }
@@ -481,6 +519,100 @@ export default {
          }
       }
     }
+    #jyChartCom{
+      background: #fff;
+      border-radius: 8px;
+      .advanced-pro-rec{
+        padding: 0 32px;
+        .c-a-r-top {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          height: 60px;
+          border-bottom: 1px dashed #E0E0E0;
+          .c-a-r-title{
+            display: flex;
+            align-items: center;
+            height: 100%;
+            line-height: 21px;
+            font-family: 'Microsoft YaHei';
+            font-style: normal;
+            font-weight: 400;
+          }
+          .r-title-text{
+            display: flex;
+            align-items: center;
+            width: fit-content;
+            height: 95%;
+            margin-top: 5px;
+            color: #2CB7CA;
+            font-size: 16px;
+            border-bottom: 2px solid #2CB7CA;
+          }
+          .r-title-tip{
+            margin-top: 5px;
+            margin-left: 32px;
+            color: #686868;
+            font-size: 14px;
+          }
+        }
+        .c-a-r-option{
+          display: flex;
+          align-items: center;
+        }
+        .c-view-common{
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding: 0 17px;
+          height: 30px;
+          font-family: 'Microsoft YaHei';
+          font-style: normal;
+          font-weight: 400;
+          font-size: 14px;
+          line-height: 22px;
+          border-radius: 4px;
+          cursor: pointer;
+        }
+        .c-view-report{
+          border: 1px solid #2ABED1;
+          color: #2ABED1;
+        }
+        .chart-common{
+          /* width: 590px; */
+          height: 280px;
+        }
+
+        .c-c-content{
+          width: 383px;
+          height: 211px;
+        }
+        .c-c-content.chart-line {
+          width: 558px;
+        }
+        .c-view-interest{
+          margin-left: 36px;
+          background: #2ABED1;
+          color: #fff;
+        }
+        .c-a-r-chart{
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          margin-top: 16px;
+        }
+        .chart-title {
+          padding: 16px 0 12px 0;
+          font-family: 'Microsoft YaHei';
+          font-style: normal;
+          font-weight: 400;
+          font-size: 16px;
+          line-height: 24px;
+          color: #1D1D1D;
+        }
+      }
+    }
+
     .card-title {
       font-size: 24px;
       color: #1d1d1d;