浏览代码

分支合并

lianbingjie 2 年之前
父节点
当前提交
9e9a49ca70
共有 57 个文件被更改,包括 7896 次插入124 次删除
  1. 1 1
      src/jfw/front/supsearch.go
  2. 2 4
      src/jfw/modules/app/src/app/front/bigMember.go
  3. 8 2
      src/jfw/modules/app/src/app/front/laboratory.go
  4. 9 1
      src/jfw/modules/app/src/web/staticres/jyapp/big-member/js/report_analysis.js
  5. 150 26
      src/jfw/modules/app/src/web/templates/big-member/page_report_analysis.html
  6. 2 2
      src/jfw/modules/app/src/web/templates/big-member/page_report_analysis_history.html
  7. 10 0
      src/jfw/modules/app/src/web/templates/weixin/historypush.html
  8. 55 42
      src/jfw/modules/bigmember/src/entity/marketAnalysis/customizad_distribution.go
  9. 88 8
      src/jfw/modules/bigmember/src/service/report/marketAnalysis.go
  10. 7 8
      src/jfw/modules/common/src/qfw/util/bidsearch/search.go
  11. 705 0
      src/web/staticres/common-module/chart-module/js/chart-common.js
  12. 7 4
      src/web/staticres/common-module/collection/css/index.css
  13. 325 0
      src/web/staticres/common-module/collection/js/analysis-report-example.js
  14. 1 1
      src/web/staticres/common-module/collection/js/keyword-mobile.js
  15. 71 0
      src/web/staticres/common-module/history-push/css/recommend.css
  16. 8 2
      src/web/staticres/common-module/history-push/js/historypush.js
  17. 76 0
      src/web/staticres/common-module/history-push/js/recommend.js
  18. 34 5
      src/web/staticres/common-module/perfect-info/js/perfect-info.js
  19. 584 0
      src/web/staticres/common-module/report-analysis/css/report_analysis.css
  20. 二进制
      src/web/staticres/common-module/report-analysis/image/01-bg.png
  21. 二进制
      src/web/staticres/common-module/report-analysis/image/01.png
  22. 二进制
      src/web/staticres/common-module/report-analysis/image/02-bg.png
  23. 二进制
      src/web/staticres/common-module/report-analysis/image/02.png
  24. 二进制
      src/web/staticres/common-module/report-analysis/image/03-bg.png
  25. 二进制
      src/web/staticres/common-module/report-analysis/image/03.png
  26. 二进制
      src/web/staticres/common-module/report-analysis/image/04-1-bg.png
  27. 二进制
      src/web/staticres/common-module/report-analysis/image/04-1.png
  28. 二进制
      src/web/staticres/common-module/report-analysis/image/04-2-bg.png
  29. 二进制
      src/web/staticres/common-module/report-analysis/image/04-2.png
  30. 二进制
      src/web/staticres/common-module/report-analysis/image/05-bg.png
  31. 二进制
      src/web/staticres/common-module/report-analysis/image/05.png
  32. 二进制
      src/web/staticres/common-module/report-analysis/image/06-bg.png
  33. 二进制
      src/web/staticres/common-module/report-analysis/image/06.png
  34. 二进制
      src/web/staticres/common-module/report-analysis/image/07-bg.png
  35. 二进制
      src/web/staticres/common-module/report-analysis/image/07.png
  36. 二进制
      src/web/staticres/common-module/report-analysis/image/08-bg.png
  37. 二进制
      src/web/staticres/common-module/report-analysis/image/08.png
  38. 185 0
      src/web/staticres/common-module/report-analysis/js/components/lineChartScatter.js
  39. 120 0
      src/web/staticres/common-module/report-analysis/js/components/marketAreaScatter.js
  40. 237 0
      src/web/staticres/common-module/report-analysis/js/components/marketSegment.js
  41. 241 0
      src/web/staticres/common-module/report-analysis/js/components/marketTimeScatter.js
  42. 105 0
      src/web/staticres/common-module/report-analysis/js/components/marketTop3Table.js
  43. 161 0
      src/web/staticres/common-module/report-analysis/js/components/marketUserScatter.js
  44. 198 0
      src/web/staticres/common-module/report-analysis/js/components/projectScatter.js
  45. 1006 0
      src/web/staticres/common-module/report-analysis/js/echarts_option.js
  46. 1831 0
      src/web/staticres/common-module/report-analysis/js/report_analysis.js
  47. 222 0
      src/web/staticres/common-module/report-analysis/js/report_analysis_history.js
  48. 0 0
      src/web/staticres/css/advanced/index.css
  49. 288 0
      src/web/staticres/css/advanced/index.scss
  50. 103 0
      src/web/staticres/css/dev2/superSearch-inside.css
  51. 二进制
      src/web/staticres/images/advanced/dialog-head.png
  52. 二进制
      src/web/staticres/images/advanced/dialog-qrcode.png
  53. 3 3
      src/web/staticres/js/pc-collect-user-info.js
  54. 574 0
      src/web/templates/big-member/wx/page_report_analysis.html
  55. 58 0
      src/web/templates/big-member/wx/page_report_analysis_history.html
  56. 411 15
      src/web/templates/pc/supsearch.html
  57. 10 0
      src/web/templates/weixin/historypush.html

+ 1 - 1
src/jfw/front/supsearch.go

@@ -627,7 +627,7 @@ var topType = map[string]string{
 	"招标信用信息": "其它",
 }
 
-//未登录变成top5000了...
+// 未登录变成top5000了...
 func top500(subtype string, bidField string, userId string) (list *[]map[string]interface{}) {
 	qstr := ""
 	if bidField != "" {

+ 2 - 4
src/jfw/modules/app/src/app/front/bigMember.go

@@ -1,11 +1,10 @@
 package front
 
 import (
+	"github.com/go-xweb/xweb"
 	"jfw/public"
 	"qfw/util/jy"
 	"regexp"
-
-	"github.com/go-xweb/xweb"
 )
 
 type NewBigMemberAction struct {
@@ -14,14 +13,13 @@ type NewBigMemberAction struct {
 	powerClear     xweb.Mapper `xweb:"/jyapp/bigMember/powerClear"` //大会员清除redis 服务id缓存
 }
 
-var freePageReg = regexp.MustCompile(`full|landingPage|pro_follow_detail|buy_commit|push_setting_detail|land_setting|push_settings|contrast|orderdetail_.*|write_infor|init|set_.*|ontrial_commit|bid_.*|free_.*|ent_portrait|bigvip_subreport_.*|report_detail_.*|analysis_(search|filter)|client_*|pro_follow_list`)
+var freePageReg = regexp.MustCompile(`full|landingPage|pro_follow_detail|buy_commit|push_setting_detail|land_setting|push_settings|contrast|orderdetail_.*|write_infor|init|set_.*|ontrial_commit|bid_.*|free_.*|ent_portrait|bigvip_subreport_.*|report_detail_.*|analysis_(search|filter)|client_*|pro_follow_list|report_analysis`)
 
 func init() {
 	jy.InitBigVipService(public.Mysql)
 	xweb.AddAction(&NewBigMemberAction{})
 }
 
-//
 func (s *NewBigMemberAction) PowerClear() {
 	userid := s.GetString("userid")
 	if userid == "" {

+ 8 - 2
src/jfw/modules/app/src/app/front/laboratory.go

@@ -7,8 +7,9 @@ import (
 type Lab struct {
 	*xweb.Action
 	/********************剑鱼标讯实验室dev2.0**************************/
-	index   xweb.Mapper `xweb:"/jyapp/jylab/index"`   //实验室首页
-	indexNg xweb.Mapper `xweb:"/jyapp/jylab/indexNg"` //实验室 nginx跳转
+	index    xweb.Mapper `xweb:"/jyapp/jylab/index"`    //实验室首页
+	indexNg  xweb.Mapper `xweb:"/jyapp/jylab/indexNg"`  //实验室 nginx跳转
+	newIndex xweb.Mapper `xweb:"/jyapp/jylab/newIndex"` //实验室 nginx跳转
 }
 
 //
@@ -25,3 +26,8 @@ func (l *Lab) Index() error {
 func (l *Lab) IndexNg() error {
 	return l.Redirect("/jyapp/jylab/page_index") //在nginx配置的路由
 }
+
+//剑鱼标讯实验室首页>移动端工作桌面(百宝箱)
+func (l *Lab) NewIndex() error {
+	return l.Redirect("/jy_mobile/tabbar/box")
+}

+ 9 - 1
src/jfw/modules/app/src/web/staticres/jyapp/big-member/js/report_analysis.js

@@ -10,6 +10,7 @@ var vm = new Vue({
     industryComponent: industryComponent,
     cateComponent: cateComponent,
     dateComponent: dateComponent,
+    chartExample: chartExample,
     // 图表
     projectScatter: projectScatter,
     marketTimeScatter: marketTimeScatter,
@@ -235,9 +236,15 @@ var vm = new Vue({
     },
     stickyOffset: 0,
     notSetKey: false, // 未设置关键词
-    isSubCount: false // 是否子账号
+    isSubCount: false, // 是否子账号
+    powerInfo: {}
   },
   computed: {
+    getStatus: function () {
+      if (JSON.stringify(this.powerInfo) !== '{}') {
+        return this.powerInfo.power.indexOf(10) === -1
+      }
+    },
     anchorTopList: function () {
       var arr = []
       this.dimensionList.forEach(function (item) {
@@ -450,6 +457,7 @@ var vm = new Vue({
         type:'POST',
         url:'/bigmember/use/isAdd',
         success:function(res) {
+          _this.powerInfo = res.data
           if (res.data && res.data.isSubCount){
             _this.isSubCount = true
           }

+ 150 - 26
src/jfw/modules/app/src/web/templates/big-member/page_report_analysis.html

@@ -8,7 +8,8 @@
     <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
     <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
     <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/css/index.css?v={{Msg "seo" "version"}}'/>
-    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/css/report_analysis.css?v={{Msg "seo" "version"}}' />
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/css/report_analysis.css?v={{Msg "seo" "version"}}1' />
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/css/index.css?v={{Msg "seo" "version"}}' />
     <style>
         /* fix: --- 弹窗组件不能显示底部问题  */
         .report-popup .j-main.unitTab {
@@ -17,6 +18,47 @@
         .collection .unitTab {
             flex: 1;
         }
+        .example-title{
+        padding: .32rem .32rem .12rem;
+        font-size: .36rem;
+        line-height: .52rem;
+        color: #171826;
+        font-weight: bold;
+        background-color: #fcfcfd;
+      }
+      .vip_openDialog{
+        margin-top: 0.92rem 0 .6rem;
+        width: 6.06rem;
+        background: url(/jyapp/big-member/image/openVip.png) no-repeat;
+        background-size: 100% 100%;
+        box-sizing: border-box;
+      }
+      .vip_openDialog .goBtn{
+        margin-bottom: .48rem;
+      }
+      .vip_extend{
+        padding: .16rem 0 0;
+        line-height: .4rem;
+        color: #171826;
+      }
+      .vip_component {
+        margin-top: .16rem;
+        flex-direction: column;
+      }
+
+      .vip_component .example-title {
+        width: 100%;
+        min-height: .96rem;
+        background: #fcfcfd;
+        font-size: .36rem;
+      }
+      .vip_component .chart_com{
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        height: inherit;
+      }
         /* fix: --- end */
     </style>
 </head>
@@ -41,7 +83,7 @@
                     :name="tab.name"></van-tab>
             </van-tabs>
             <section v-show="tabActiveName === 'analysis'" class="j-main analysis-content">
-                <div class="j-container search-filters bg-white" v-show="filtersPageShow && !rid">
+                <div class="j-container search-filters bg-white" v-show="!rid">
                     <div class="j-main">
                         <div class="height8">height8</div>
                         <div class="filters-title pd-lr16">
@@ -102,7 +144,7 @@
                             </div>
                         </section>
                         <!-- 市场概况 -->
-                        <section class="section bg-white market-overview" id="market">
+                        <section class="section bg-white market-overview" id="market" v-if="getStatus">
                             <div class="section-title pd-16">市场概况</div>
                             <div class="section-content market-overview-list">
                                 <div
@@ -129,15 +171,24 @@
                                 环比:统计学术语,是表示连续2个统计周期(比如连<br />续两月)内的量的变化比。
                             </div>
                         </section>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:8.84rem">
+                          <p class="example-title">市场概况</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/01-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_1" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/01.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                         <!-- 项目规模分布 -->
-                        <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.dataAlready">
+                        <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.dataAlready && getStatus">
                             <div class="section-title">项目规模分布</div>
                             <div class="section-content">
                                 <project-scatter :chart-data="sections.projectScatter.chartData"></project-scatter>
                             </div>
                         </section>
                         <!-- 项目规模TOP10 -->
-                        <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.tableData.length">
+                        <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.tableData.length && getStatus">
                             <div class="section-title">项目规模TOP10</div>
                             <div class="section-content project-top-list">
                                 <div
@@ -178,6 +229,15 @@
                                 </div>
                             </div>
                         </section>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:11.38rem">
+                          <p class="example-title">项目规模分布</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/02-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_2" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/02.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                         <!-- 时间分布 -->
                         <section class="section bg-white pd-16 time-scatter" v-if="sections.timeScatter.dataAlready">
                             <div class="section-header">
@@ -205,24 +265,33 @@
                             </div>
                         </section>
                         <!-- 地区分布 -->
-                        <div class="section bg-white pd-16 area-scatter" v-if="sections.areaScatter.dataAlready && notOneAreaFilter">
+                        <div class="section bg-white pd-16 area-scatter" v-if="sections.areaScatter.dataAlready && notOneAreaFilter && getStatus">
                             <div class="section-title">地区分布</div>
                             <div class="section-content">
                                 <market-area-scatter :chart-data="sections.areaScatter.chartData"></market-area-scatter>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.areaScatter.projectCountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.areaScatter.projectCountTop3 && getStatus">
                             <div class="section-title">项目数量TOP3地区的重点中标单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.areaScatter.projectCountTop3" type="count" @save="saveState"></market-top3-table>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.areaScatter.projectAmountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.areaScatter.projectAmountTop3 && getStatus">
                             <div class="section-title">项目金额TOP3地区的重点中标单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.areaScatter.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
                             </div>
                         </div>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:13.08rem">
+                          <p class="example-title">地区分布</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/03-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_3" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/03.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                         <!-- 客户分布 -->
                         <div class="section bg-white pd-16 user-scatter" v-if="sections.userScatter.list.length">
                            <div class="clearfix">
@@ -246,31 +315,49 @@
                             </div>
                         </div>
                         <!-- 细分市场 - 项目数量 -->
-                        <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready">
+                        <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready && getStatus">
                             <div class="section-title">细分市场 - 项目数量</div>
                             <div class="section-content">
                                 <market-segment :chart-data="sections.market.refine.projectCountData" type="count"></market-segment>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.market.refine.projectCountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.market.refine.projectCountTop3 && getStatus">
                             <div class="section-title">细分市场的重点中标单位-项目数量</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.market.refine.projectCountTop3" type="count" @save="saveState"></market-top3-table>
                             </div>
                         </div>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">细分市场 - 项目数量</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/04-2-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_4_1" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/04-2.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                         <!-- 细分市场 - 项目金额 -->
-                        <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready">
+                        <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready && getStatus">
                             <div class="section-title">细分市场 - 项目金额</div>
                             <div class="section-content">
                                 <market-segment :chart-data="sections.market.refine.projectAmountData" type="amount"></market-segment>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.market.refine.projectAmountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.market.refine.projectAmountTop3 && getStatus">
                             <div class="section-title">细分市场的重点中标单位-项目金额</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.market.refine.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
                             </div>
                         </div>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">细分市场 - 项目金额</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/04-1-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_4_2" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/04-1.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                         <!-- 采购规模分布 -->
                         <div class="section bg-white pd-16 buyerclass-scatter" id="buyer" v-if="sections.buyerclass.dataAlready">
                             <div class="section-title">采购规模分布</div>
@@ -278,37 +365,73 @@
                                 <line-chart-scatter :chart-data="sections.buyerclass.chartData"></line-chart-scatter>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.buyerclass.projectCountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.buyerclass.projectCountTop3 && getStatus">
                             <div class="section-title">项目数量TOP3采购单位及其重点合作中标单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.buyerclass.projectCountTop3" type="count" @save="saveState"></market-top3-table>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.buyerclass.projectAmountTop3">
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">项目数量TOP3采购单位及其重点合作中标单位</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/05-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_5" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/05.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
+                        <div class="section bg-white pd-16" v-if="sections.buyerclass.projectAmountTop3 && getStatus">
                             <div class="section-title">采购金额TOP3采购单位及其重点合作中标单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.buyerclass.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
                             </div>
                         </div>
-                        <!-- 采购规模分布 -->
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">采购金额TOP3采购单位及其重点合作中标单位</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/06-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_6" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/06.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
+                        <!-- 中标规模分布 -->
                         <div class="section bg-white pd-16 winner-scatter" id="winner" v-if="sections.winner.dataAlready">
                             <div class="section-title">中标规模分布</div>
                             <div class="section-content">
                                 <line-chart-scatter :chart-data="sections.winner.chartData"></line-chart-scatter>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.winner.projectCountTop3">
+                        <div class="section bg-white pd-16" v-if="sections.winner.projectCountTop3 && getStatus">
                             <div class="section-title">项目数量TOP3中标单位及其重点合作采购单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.winner.projectCountTop3" type="count" @save="saveState"></market-top3-table>
                             </div>
                         </div>
-                        <div class="section bg-white pd-16" v-if="sections.winner.projectAmountTop3">
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">项目数量TOP3中标单位及其重点合作采购单位</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/07-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_7" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/07.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
+                        <div class="section bg-white pd-16" v-if="sections.winner.projectAmountTop3 && getStatus">
                             <div class="section-title">中标金额TOP3中标单位及其重点合作采购单位</div>
                             <div class="section-content">
                                 <market-top3-table :table-data="sections.winner.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
                             </div>
                         </div>
+                        <div class="vip_component"
+                          v-if="!getStatus"
+                          style="height:10.8rem">
+                          <p class="example-title">中标金额TOP3中标单位及其重点合作采购单位</p>
+                          <div class="chart_com" style="background:url('{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/08-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                            <chart-example type="item_8" imgurl='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/image/08.png?v={{Msg "seo" "version"}}'>
+                            </chart-example>
+                          </div>
+                        </div>
                     </div>
                     <div class="fixed-bottom-right clickable scroll-to-top" style="display: none;">
                         <van-icon name="arrow-up"></van-icon>
@@ -430,16 +553,17 @@
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/js/industry-mobile.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/js/cate-mobile.js?v={{Msg "seo" "version"}}'></script>
 <!-- components -->
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/echarts_option.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/projectScatter.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/marketTimeScatter.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/marketAreaScatter.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/marketTop3Table.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/marketUserScatter.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/marketSegment.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/components/lineChartScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/echarts_option.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/js/analysis-report-example.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/projectScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/marketTimeScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/marketAreaScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/marketTop3Table.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/marketUserScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/marketSegment.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/components/lineChartScatter.js?v={{Msg "seo" "version"}}'></script>
 <!-- main.js -->
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/report_analysis.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/report_analysis.js?v={{Msg "seo" "version"}}12'></script>
 
 </body>
 </html>

+ 2 - 2
src/jfw/modules/app/src/web/templates/big-member/page_report_analysis_history.html

@@ -7,7 +7,7 @@
     <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/reset-css/5.0.1/reset.min.css />
     <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
     <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
-    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/css/report_analysis.css?v={{Msg "seo" "version"}}' />
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/css/report_analysis.css?v={{Msg "seo" "version"}}' />
     <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/diy-report/css/report-list.css?v={{Msg "seo" "version"}}' />
 </head>
 
@@ -43,7 +43,7 @@
 {{include "/big-member/commonjs.html"}}
 
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/diy-report/js/report-list.js?v={{Msg "seo" "version"}}'></script>
-<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/big-member/js/report_analysis_history.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/report-analysis/js/report_analysis_history.js?v={{Msg "seo" "version"}}'></script>
 
 </body>
 </html>

+ 10 - 0
src/jfw/modules/app/src/web/templates/weixin/historypush.html

@@ -18,6 +18,7 @@
     <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/css/index.css?v={{Msg "seo" "version"}}'/>
     <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/css/public.css?v={{Msg "seo" "version"}}'/>
     <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/css/old-page-style.css?v={{Msg "seo" "version"}}'/>
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/css/recommend.css?v={{Msg "seo" "version"}}'/>
 </head>
 <body class="p13" id="viperSuper" style="background: #fff;overflow: hidden;">
 <!-- 加载数据-->
@@ -293,6 +294,14 @@
         </div>
         <div class="color_top" style="display:none;"></div>
         <div id="dropDownItemGroup" class="collection"></div>
+        <!-- <div class="analysis-module"> -->
+          <!-- 超前项目推荐 -->
+          <!-- <recommend-com  ref="recommendRef"  @toggle="onToggleStatus"></recommend-com> -->
+          <!-- 定制化分析报告 -->
+          <!-- <div v-show="collapseStatus"> -->
+            <!-- <CustomReport :chartData="chartData"></CustomReport> -->
+          <!-- </div>
+        </div> -->
         <div class="j-main">
             <div class="listcontent" onscroll="listScroll()">
                 <div id="list"></div>
@@ -484,6 +493,7 @@
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/js/notice-mobile.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/collection/js/money-mobile.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/keep-tags/keep-tags-template.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/js/recommend.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/js/historypush.js?v={{Msg "seo" "version"}}'></script>
 <script src=//cdn-common.jianyu360.com/cdn/lib/weui.js/1.2.1/weui.min.js></script>
 <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/history-push/js/old-page-script.js?v={{Msg "seo" "version"}}'></script>

+ 55 - 42
src/jfw/modules/bigmember/src/entity/marketAnalysis/customizad_distribution.go

@@ -6,7 +6,9 @@ import (
 	"fmt"
 	elastic1 "gopkg.in/olivere/elastic.v1"
 	"math"
+	qutil "qfw/util"
 	"strings"
+	"sync"
 	"time"
 	"util"
 )
@@ -70,7 +72,7 @@ func getPreviousMarket(sTime, eTime time.Time) int64 {
 	return os_time
 }
 
-//判断是否月初到月末
+// 判断是否月初到月末
 func SEMonth(sTime, eTime time.Time) bool {
 	var day int
 	month := int(eTime.Month())
@@ -153,8 +155,8 @@ func getBidamountStatistics(sTime, eTime time.Time) string {
 	return timeRange[:len(timeRange)-1]
 }
 
-//getMonthRange获取月份范围
-//isStart true本月月初  false 本月月末(下月月初)
+// getMonthRange获取月份范围
+// isStart true本月月初  false 本月月末(下月月初)
 func getMonthRange(t time.Time, isStart bool) time.Time {
 	if isStart {
 		return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
@@ -172,8 +174,8 @@ func GetYearData(sTime, eTime time.Time) (bool, string) {
 	return _b, getCommonYearStatistics(sTime, eTime)
 }
 
-//getYearRange获取月份范围
-//isStart true本月月初  false 本月月末(下月月初)
+// getYearRange获取月份范围
+// isStart true本月月初  false 本月月末(下月月初)
 func getYearRange(t time.Time, isStart bool) time.Time {
 	if isStart {
 		return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
@@ -181,7 +183,7 @@ func getYearRange(t time.Time, isStart bool) time.Time {
 	return time.Date(t.Year()+1, 1, 1, 0, 0, 0, 0, t.Location())
 }
 
-//年份统计
+// 年份统计
 func getCommonYearStatistics(sTime, eTime time.Time) string {
 	timeRange := ``
 	tmpTime, rTime, tEndTime := sTime, sTime, getYearRange(eTime, false)
@@ -261,7 +263,7 @@ func sequential(now, old float64) interface{} {
 	return (now - old) / old
 }
 
-//市场概况+时间分布
+// 市场概况+时间分布
 func (mae *MarketAnalysisEntity) MarketTime() (map[string]interface{}, error) {
 	var (
 		sql                   []string
@@ -352,7 +354,7 @@ func (mae *MarketAnalysisEntity) MarketTime() (map[string]interface{}, error) {
 	return rMap, nil
 }
 
-//时间分布月,年通用数据处理
+// 时间分布月,年通用数据处理
 func (mae *MarketAnalysisEntity) TimeData(_b bool, thisRow []Buckets) map[string]interface{} {
 	var count_ss, amout_ss []map[string]interface{}
 
@@ -395,35 +397,35 @@ func amountDistribution(v float64, data map[string]*distributionTrend) {
 		data["<10万"].Amount += v
 		data["<10万"].Count++
 	} else if v < 500000 {
-		if data["10万-50万"] == nil {
-			data["10万-50万"] = new(distributionTrend)
+		if data["10万~50万"] == nil {
+			data["10万~50万"] = new(distributionTrend)
 		}
-		data["10万-50万"].Amount += v
-		data["10万-50万"].Count++
+		data["10万~50万"].Amount += v
+		data["10万~50万"].Count++
 	} else if v < 1000000 {
-		if data["50万-100万"] == nil {
-			data["50万-100万"] = new(distributionTrend)
+		if data["50万~100万"] == nil {
+			data["50万~100万"] = new(distributionTrend)
 		}
-		data["50万-100万"].Amount += v
-		data["50万-100万"].Count++
+		data["50万~100万"].Amount += v
+		data["50万~100万"].Count++
 	} else if v < 1000000*5 {
-		if data["100万-500万"] == nil {
-			data["100万-500万"] = new(distributionTrend)
+		if data["100万~500万"] == nil {
+			data["100万~500万"] = new(distributionTrend)
 		}
-		data["100万-500万"].Amount += v
-		data["100万-500万"].Count++
+		data["100万~500万"].Amount += v
+		data["100万~500万"].Count++
 	} else if v < 1000000*10 {
-		if data["500万-1000万"] == nil {
-			data["500万-1000万"] = new(distributionTrend)
+		if data["500万~1000万"] == nil {
+			data["500万~1000万"] = new(distributionTrend)
 		}
-		data["500万-1000万"].Amount += v
-		data["500万-1000万"].Count++
+		data["500万~1000万"].Amount += v
+		data["500万~1000万"].Count++
 	} else if v < 100000000 {
-		if data["1000万-1亿"] == nil {
-			data["1000万-1亿"] = new(distributionTrend)
+		if data["1000万~1亿"] == nil {
+			data["1000万~1亿"] = new(distributionTrend)
 		}
-		data["1000万-1亿"].Amount += v
-		data["1000万-1亿"].Count++
+		data["1000万~1亿"].Amount += v
+		data["1000万~1亿"].Count++
 	} else if v >= 100000000 {
 		if data["≥1亿"] == nil {
 			data["≥1亿"] = new(distributionTrend)
@@ -661,10 +663,19 @@ func (mae *MarketAnalysisEntity) BuyerWinnerAnalysis() map[string]interface{} {
 		winnerKeys = append(winnerKeys, k)
 	}
 	winnerName := GetEntNameByIds(winnerKeys)
-	rMap := make(map[string]interface{})
-	BuyerAnalysis(thisBuyerWinnerRow, rMap, winnerName)
-	WinningAnalysis(thisBuyerWinnerRow, rMap, winnerName)
-	return rMap
+	//rMap := make(map[string]interface{})
+	var rMap = sync.Map{}
+	sy := sync.WaitGroup{}
+	sy.Add(2)
+	go BuyerAnalysis(thisBuyerWinnerRow, &rMap, winnerName, &sy)
+	go WinningAnalysis(thisBuyerWinnerRow, &rMap, winnerName, &sy)
+	sy.Wait()
+	rMaps := make(map[string]interface{})
+	rMap.Range(func(key, value interface{}) bool {
+		rMaps[qutil.InterfaceToStr(key)] = value
+		return true
+	})
+	return rMaps
 }
 
 type distributionTrend struct {
@@ -673,9 +684,10 @@ type distributionTrend struct {
 	Amount float64
 }
 
-var Analysis = []string{"<10万", "10万-50万", "50万-100万", "100万-500万", "500万-1000万", "1000万-1亿", "≥1亿"}
+var Analysis = []string{"<10万", "10万~50万", "50万~100万", "100万~500万", "500万~1000万", "1000万~1亿", "≥1亿"}
 
-func BuyerAnalysis(thisBuyerRow BuyerWinnerRow, rMap map[string]interface{}, winnerName map[string]string) {
+func BuyerAnalysis(thisBuyerRow BuyerWinnerRow, rMap *sync.Map, winnerName map[string]string, sy *sync.WaitGroup) {
+	defer sy.Done()
 	type buyer struct {
 		Name        string      `json:"key"`
 		TotalAmount interface{} `json:"total_amount"`
@@ -791,13 +803,14 @@ func BuyerAnalysis(thisBuyerRow BuyerWinnerRow, rMap map[string]interface{}, win
 		_d.Data = ss
 		amountMap = append(amountMap, _d)
 	}
-	rMap["buyer_time_distribution"] = buyerMap
-	rMap["buyer_count_top3"] = countMap
-	rMap["buyer_amount_top3"] = amountMap
+	rMap.Store("buyer_time_distribution", buyerMap)
+	rMap.Store("buyer_count_top3", countMap)
+	rMap.Store("buyer_amount_top3", amountMap)
 }
 
-//中标单位分析
-func WinningAnalysis(thisWinnerRow BuyerWinnerRow, rMap map[string]interface{}, winnerName map[string]string) {
+// 中标单位分析
+func WinningAnalysis(thisWinnerRow BuyerWinnerRow, rMap *sync.Map, winnerName map[string]string, sy *sync.WaitGroup) {
+	defer sy.Done()
 	type s_Winner struct {
 		Name        string      `json:"key"`
 		TotalAmount interface{} `json:"total_amount"`
@@ -908,7 +921,7 @@ func WinningAnalysis(thisWinnerRow BuyerWinnerRow, rMap map[string]interface{},
 		_d.Data = ss
 		amountMap = append(amountMap, _d)
 	}
-	rMap["winner_time_distribution"] = buyerMap
-	rMap["winner_count_top3"] = countMap
-	rMap["winner_amount_top3"] = amountMap
+	rMap.Store("winner_time_distribution", buyerMap)
+	rMap.Store("winner_count_top3", countMap)
+	rMap.Store("winner_amount_top3", amountMap)
 }

+ 88 - 8
src/jfw/modules/bigmember/src/service/report/marketAnalysis.go

@@ -2,6 +2,7 @@ package report
 
 import (
 	. "api"
+	"config"
 	"db"
 	"entity/marketAnalysis"
 	"fmt"
@@ -9,31 +10,33 @@ import (
 	"log"
 	qutil "qfw/util"
 	"qfw/util/jy"
+	"time"
 	"util"
 )
 
-//MarketAnalysis 市场分析报告路由定义
+// MarketAnalysis 市场分析报告路由定义
 type MarketAnalysis struct {
 	*xweb.Action
 	doAnalysis        xweb.Mapper `xweb:"/marketAnalysis/doAnalysis"`        //市场分析分析查询(此接口只做为保存查询条件,返回记录id)
 	getAnalysisResult xweb.Mapper `xweb:"/marketAnalysis/getAnalysisResult"` //获取分析报告结果(根据记录id查询报告结果)
 	analysisHistory   xweb.Mapper `xweb:"/marketAnalysis/analysisHistory"`   //市场分析报告历史记录
+	analysisKeyWord   xweb.Mapper `xweb:"/marketAnalysis/analysisKeyWord"`   //市场分析报告订阅词
 }
 
-//checkPower 权限校验
+// checkPower 权限校验
 func checkPower(userId string) (string, error) {
 	if userId == "" {
 		return "", fmt.Errorf("未登录")
 	}
 	//仅购买《周报/月报/定制化市场分析报告》的大会员有权限
 	bigMeg := jy.GetBigVipUserBaseMsg(userId, db.Mysql, db.Mgo)
-	if bigMeg.Status <= 0 || !bigMeg.CheckBigVipBackPower("report") {
-		return "", fmt.Errorf("非法请求")
-	}
+	//if bigMeg.Status <= 0 || !bigMeg.CheckBigVipBackPower("report") {
+	//	return "", fmt.Errorf("非法请求")
+	//}
 	return bigMeg.Pid, nil
 }
 
-//DoAnalysis 开始分析报告
+// DoAnalysis 开始分析报告
 func (this *MarketAnalysis) DoAnalysis() {
 	userId := qutil.ObjToString(this.GetSession("userId"))
 	rData, errMsg := func() (interface{}, error) {
@@ -66,7 +69,7 @@ func (this *MarketAnalysis) DoAnalysis() {
 	this.ServeJson(NewResult(rData, errMsg))
 }
 
-//GetAnalysisResult 获取分析结果
+// GetAnalysisResult 获取分析结果
 func (this *MarketAnalysis) GetAnalysisResult() {
 	userId := qutil.ObjToString(this.GetSession("userId"))
 	rData, errMsg := func() (interface{}, error) {
@@ -96,7 +99,7 @@ func (this *MarketAnalysis) GetAnalysisResult() {
 	this.ServeJson(NewResult(rData, errMsg))
 }
 
-//AnalysisHistory 分析报告历史
+// AnalysisHistory 分析报告历史
 func (this *MarketAnalysis) AnalysisHistory() {
 	userId := qutil.ObjToString(this.GetSession("userId"))
 	rData, errMsg := func() (interface{}, error) {
@@ -125,3 +128,80 @@ func (this *MarketAnalysis) AnalysisHistory() {
 	}
 	this.ServeJson(NewResult(rData, errMsg))
 }
+
+func (this *MarketAnalysis) AnalysisKeyWord() {
+	r := func() Result {
+		userid := qutil.ObjToString(this.GetSession("userId"))
+		if userid == "" {
+			return Result{Data: M{"status": -1}, Error_msg: "未登录"}
+		}
+		mainid, _, _ := util.MainUserId(userid, "", 0)
+		d := map[string]interface{}{
+			"member_status": 0,
+		}
+		data, _ := db.Mgo.FindById("user", mainid, `{"o_jy":1,"o_vipjy":1,"i_member_starttime":1,"i_member_endtime":1,"i_member_status":1,"l_vip_endtime":1,"l_vip_starttime":1,"o_member_jy":1,"i_vip_status":1,:1,"l_registedate":1}`)
+		i_member_status := qutil.IntAll((*data)["i_member_status"])
+		i_vip_status := qutil.IntAll((*data)["i_vip_status"])
+
+		o_member_jy := qutil.ObjToMap((*data)["o_member_jy"])
+		oJy, _ := (*data)["o_jy"].(map[string]interface{})      //免费用户关键词
+		vipJy, _ := (*data)["o_vipjy"].(map[string]interface{}) //超级订阅关键词
+		if i_member_status > 0 {
+			btip, _ := (*o_member_jy)["b_keytip"].(bool)
+			KeyWord(btip, i_member_status, qutil.IntAll((*data)["i_member_starttime"]), qutil.IntAll((*data)["i_member_starttime"]), *o_member_jy, *data, d)
+		} else if i_vip_status > 0 {
+			btip, _ := vipJy["b_keytip"].(bool)
+			KeyWord(btip, i_vip_status, qutil.IntAll((*data)["l_vip_endtime"]), qutil.IntAll((*data)["l_vip_starttime"]), vipJy, *data, d)
+		} else {
+			if oJy["a_key"] != nil && len(oJy["a_key"].([]interface{})) > 0 {
+				//免费用户关键词格式统一
+				arrMap := map[string]interface{}{
+					"s_item": "未分类",
+					"a_key":  oJy["a_key"],
+				}
+				oJy["a_items"] = []map[string]interface{}{arrMap}
+				d["member_jy"] = oJy
+				d["key_max_length"] = config.Config.KeyMaxLength
+			}
+		}
+		return Result{Data: d}
+	}()
+	this.ServeJson(r)
+}
+
+func KeyWord(btip bool, status, i_member_starttime, i_member_endtime int, o_member_jy, data, d map[string]interface{}) {
+	//是否展示附加词合并
+	appendK_bl := false
+	if !btip && status > 0 && o_member_jy != nil && len(o_member_jy) > 0 {
+		if o_member_jy["a_items"] != nil {
+			for _, v := range o_member_jy["a_items"].([]interface{}) {
+				tmp := qutil.ObjToMap(v.(map[string]interface{}))
+				a_key := (*tmp)["a_key"].([]interface{})
+				for _, n := range a_key {
+					ntmp := qutil.ObjToMap(n.(interface{}))
+					if (*ntmp)["appendkey"] != nil && (*ntmp)["updatetime"] == nil {
+						appendkey := qutil.ObjArrToStringArr((*ntmp)["appendkey"].([]interface{}))
+						if len(appendkey) > 0 {
+							appendK_bl = true
+						}
+					}
+				}
+			}
+		}
+
+		//订阅设置优化版本上线之前的用户弹窗提醒
+		optime := time.Unix(config.Config.OldSubscribeMoveTip, 0)
+		regtime, _ := data["l_registedate"].(int64)
+		if time.Unix(regtime, 0).Before(optime) && appendK_bl {
+			o_member_jy["b_keytip"] = false
+		} else {
+			o_member_jy["b_keytip"] = true
+		}
+	}
+	d["member_jy"] = o_member_jy
+	d["member_status"] = status
+	d["member_starttime"] = i_member_starttime
+	d["member_endtime"] = i_member_endtime
+	//d["member_jy"] = qu.ObjToMap((*data)["o_member_jy"])
+	d["key_max_length"] = config.Config.KeyMaxLength
+}

+ 7 - 8
src/jfw/modules/common/src/qfw/util/bidsearch/search.go

@@ -41,7 +41,7 @@ const (
 	bidSearch_field   = bidSearch_field_1 + `,"bidopentime","winner","buyer","projectname","projectcode","projectinfo"`
 )
 
-//GetWxsearchlistData 移动端招标信息搜索
+// GetWxsearchlistData 移动端招标信息搜索
 func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, pageNum int, selectTypeArr []string, field, notkey string, searchTypeSwitch bool, pageSize int) (list *[]map[string]interface{}, b_word, a_word, s_word string) {
 	var hightlightContent bool = false //是否高亮正文
 	for _, v := range selectTypeArr {
@@ -75,7 +75,7 @@ func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry,
 	return list, b_word, a_word, s_word
 }
 
-//GetPcBidSearchData pc端招标信息搜索
+// GetPcBidSearchData pc端招标信息搜索
 func GetPcBidSearchData(searchvalue, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, start int, isGetCount bool, selectTypeArr []string, field, notkey string, ispayed, searchTypeSwitch bool, bidField string, pageSize int, userId string) (count, totalPage int64, list *[]map[string]interface{}) {
 	var findfields string
 	var hightlightContent bool = false //是否高亮正文
@@ -249,12 +249,12 @@ func GetBidSearchQuery(area, city, publishtime, subtype, winner, buyerclass stri
 	return query
 }
 
-//包含正文或 附件 不包含标题
+// 包含正文或 附件 不包含标题
 func DetailFileORTitle(findfields string) bool {
 	return (strings.Contains(findfields, `"detail"`) || strings.Contains(findfields, `"filetext"`)) && !strings.Contains(findfields, `"title"`)
 }
 
-//包含标题和正文
+// 包含标题和正文
 func DetailTitle(findfields string) bool {
 	return strings.Contains(findfields, `"detail"`) && strings.Contains(findfields, `"title"`)
 }
@@ -419,7 +419,7 @@ func PublicSearch(userId, selectType, publishtime string, bidSearchOldUserLimit
 	return isPayedUser, publishtime, queryItems, currentPage, start
 }
 
-//所有的再次分词查询 只查标题
+// 所有的再次分词查询 只查标题
 func IntegratedData(platform string, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey string, queryItems []string, list *[]map[string]interface{}, field string, searchTypeSwitch bool, bidField string, pageSize int) (string, string, string, string, *[]map[string]interface{}) {
 	var pcAjaxFlag string
 	var secRel *[]map[string]interface{} = list
@@ -480,8 +480,8 @@ func classify(stp, area, industry string, configData map[string]interface{}) (st
 	return tpadd, areaadd, induadd
 }
 
-//list != nil && len(*list) == bidsearch.SearchPageSize_APP && pageNum < util.If(isPayedUser, bidsearch.SearchMaxPageNum_PAYED, bidsearch.SearchMaxPageNum_APP).(int)
-//数据格式化处理
+// list != nil && len(*list) == bidsearch.SearchPageSize_APP && pageNum < util.If(isPayedUser, bidsearch.SearchMaxPageNum_PAYED, bidsearch.SearchMaxPageNum_APP).(int)
+// 数据格式化处理
 func LisetData(stype, pageNum int, list *[]map[string]interface{}, secondFlag string, configData map[string]interface{}, isPayedUser bool, pageSize int, userId string) ([]map[string]interface{}, int64, bool) {
 	var (
 		secondList  []map[string]interface{}
@@ -556,7 +556,6 @@ func SearchData(platform string, request *http.Request, currentPage int, userId,
 	} else {
 		count, totalPage, list = GetPcBidSearchData(s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, start, isGetCount, queryItems, field, notkey, isPayedUser, searchTypeSwitch, bidField, pageSize, userId)
 	}
-
 	if len([]rune(s_word)) > 3 && int(count) < pageSize && start == number && secondSearch {
 		var paramList = list
 		s_word, pcAjaxFlag, secondFlag, second, list = IntegratedData(platform, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey, queryItems, paramList, field, searchTypeSwitch, bidField, pageSize)

+ 705 - 0
src/web/staticres/common-module/chart-module/js/chart-common.js

@@ -0,0 +1,705 @@
+/**
+ * 说明:
+  * el: 挂载的dom节点
+  * chartData 图表数据集合
+  * config 支持配置的文本,点击事件函数
+  * type 判断图表类型,有以下几个参数
+  * {
+      * ve-histogram 柱状图
+      * ve-finehistogram 柱状图+折线图
+      * ve-treemap 树形图
+      * ve-line 折线图
+  * }
+ */
+
+
+var chartTemplate =
+`
+  <template>
+      <ve-histogram
+        v-if='type==="ve-histogram"'
+        :id="type"
+        :colors="histogramChart.options.colors"
+        :width="histogramChart.options.width"
+        :height="histogramChart.options.height"
+        :data="chartData"
+        :settings="histogramChart.options.settings"
+        :after-config="histogramChart.options.config"
+        :after-set-option="extend"
+        :extend="histogramChart.defaultOptions"
+        >
+      </ve-histogram>
+      <ve-histogram
+        v-else-if='type==="ve-finehistogram"'
+        :id="type"
+        :height="barLineChart.options.height"
+        :width="barLineChart.options.width ? barLineChart.options.width : null"
+        :colors="barLineChart.options.colors"
+        :data="chartData"
+        :settings="barLineChart.options.settings"
+        :after-config="barLineChart.options.config"
+        :after-set-option="barExtend"
+        :extend="barLineChart.defaultOptions"
+        >
+      </ve-histogram>
+      <div v-else-if='type==="ve-treemap"' class="rect-tree-map-chart" style="height: 100%"></div>
+      <ve-line
+        v-else-if='type==="ve-line"'
+        :data="chartData"
+        :height="lineChart.options.height"
+        :after-config="lineChart.options.config"
+        :extend="lineChart.defaultOption"
+        >
+      </ve-line>
+  </template>
+`
+var vComponentChart = function (el, chartData, config, type) {
+  new Vue({
+    delimiters: ['${', '}'],
+    el: el,
+    template: chartTemplate,
+    data () {
+      return {
+        myChart: null,
+        type: type,
+        chartData: {},
+        // histogram 柱状图
+        histogramChart: {},
+        // barLineChart 柱状图+折线图
+        barLineChart: {},
+        // treeMapChart 树形图
+        treeMapChart: {},
+        // lineChart 折线图
+        lineChart: {}
+      }
+    },
+    created () {
+      this.chartData = chartData
+    },
+    mounted () {
+      this.getChartConfig()
+      if(this.type === 've-treemap') {
+        this.updateChartView()
+      } else if (this.type === 've-line') {
+        this.mergeExtendOptions()
+      }
+    },
+    methods: {
+      IsPC () {
+        var userAgentInfo = navigator.userAgent
+        var Agents = ["Android", "iPhone",
+        "SymbianOS", "Windows Phone",
+        "iPad", "iPod"]
+        var flagPc = true
+        for (var v = 0; v < Agents.length; v++) {
+          if (userAgentInfo.indexOf(Agents[v]) > 0) {
+            flagPc = false;
+            break;
+          }
+        }
+        return flagPc;
+      },
+      // 判断类型,取对应配置
+      getChartConfig () {
+        if (this.type === 've-histogram') {
+          this.histogramChart = {
+            options: {
+              colors: ['#FF9F3F', '#05A5F2'],
+              width: '100%',
+              height: '100%',
+              settings: {}
+            },
+            defaultOptions: {
+              grid: {
+                top: 20
+              },
+              xAxis: {
+                axisLabel: {
+                  margin: 10,
+                  interval: 1, // 强制显示x轴所有刻度
+                  fontSize: 12
+                },
+                nameLocation: 'start',
+                nameTextStyle: {
+                  fontSize: 12,
+                  align: 'left',
+                  padding: [70, 0, 0, 50],
+                  color: '#9B9CA3'
+                }
+              },
+              yAxis (item) {
+                Object.assign(item[0], {
+                  splitLine: {
+                    lineStyle: {
+                      type: 'dashed',
+                      width: 0.5
+                    }
+                  },
+                  axisLabel: {
+                    margin: 2,
+                    fontSize: 12,
+                    formatter: (value, index) => value.toString().replace(/,/, '') + '%'
+                  }
+                })
+
+                Object.assign(item[1], {
+                  splitLine: {
+                    show: false
+                  },
+                  axisLabel: {
+                    show: false,
+                    fontSize: 12,
+                    formatter: (value, index) => value.toString().replace(/,/, '')
+                  }
+                })
+                return item
+              },
+              tooltip: {
+                trigger: 'axis',
+                confine: true,
+                backgroundColor: '#fff',
+                axisPointer: {
+                  type: 'shadow',
+                  shadowStyle: {
+                    color: 'rgba(42, 190, 209,0.1)'
+                  },
+                  z: 3
+                },
+                textStyle: {
+                  color: '#171826',
+                  fontSize: 12
+                },
+                padding: [7, 12],
+                extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)',
+                formatter: this.tooltipFormatter
+              },
+              legend: {
+                orient: 'horizontal',
+                icon: 'rect',
+                bottom: 20,
+                align: 'left',
+                itemGap: 20,
+                itemWidth: 9,
+                itemHeight: 9,
+                textStyle: {
+                  fontSize: 10,
+                  lineHeight: 14,
+                  verticalAlign: 'bottom',
+                  rich: {
+                    a: {
+                      fontSize: 16,
+                      verticalAlign: 'top',
+                      align: 'center',
+                      padding: [0, 15, 28, 0]
+                    },
+                    b: {
+                      fontSize: 14,
+                      align: 'center',
+                      padding: [0, 15, 0, 0],
+                      lineHeight: 25
+                    }
+                  }
+                },
+                formatter: name => name
+              }
+            }
+          }
+        } else if (this.type === 've-finehistogram') {
+          this.barLineChart = {
+            options: {
+              height: '100%',
+              width: '100%',
+              colors: ['#05A6F3', '#FF3A20'],
+              settings: {
+                showLine: [chartData.columns[2]],
+                axisSite: { right: [chartData.columns[2]] }
+              },
+              config: this.newTimeConfig
+            },
+            defaultOptions: {
+              grid: {
+                top: 20
+              },
+              xAxis: {
+                axisLabel: {
+                  margin: 10,
+                  interval: 0, // 强制显示x轴所有刻度
+                  fontSize: 12
+                },
+                nameLocation: 'start',
+                nameTextStyle: {
+                  fontSize: 12,
+                  align: 'left',
+                  padding: [70, 0, 0, 50],
+                  color: '#9B9CA3'
+                }
+              },
+              yAxis (item) {
+                item[0].splitLine = {
+                  lineStyle: {
+                    type: 'dashed',
+                    width: 0.5
+                  }
+                }
+                item[0].axisLabel = {
+                  margin: 2,
+                  fontSize: 12
+                }
+                item[1].splitLine = {
+                  show: false
+                }
+                item[1].axisLabel = {
+                  show: false,
+                  fontSize: 12
+                }
+                item[0].axisLabel.formatter = (value, index) => {
+                  return value.toString().replace(/,/, '')
+                }
+                item[1].axisLabel.formatter = (value, index) => {
+                  return value.toString().replace(/,/, '')
+                }
+                return item
+              },
+              tooltip: {
+                trigger: 'axis',
+                confine: true,
+                backgroundColor: '#fff',
+                axisPointer: {
+                  type: 'shadow',
+                  shadowStyle: {
+                    color: 'rgba(42, 190, 209,0.1)'
+                  },
+                  z: 3
+                },
+                textStyle: {
+                  color: '#171826',
+                  fontSize: 12
+                },
+                padding: [7, 12],
+                extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)'
+              },
+              legend: {
+                orient: 'horizontal',
+                icon: 'circle',
+                bottom: 0,
+                align: 'left',
+                itemWidth: 8,
+                itemHeight: 8,
+                itemGap: 20,
+                textStyle: {
+                  fontSize: 12,
+                  rich: {
+                    a: {
+                      fontSize: 16,
+                      verticalAlign: 'top',
+                      align: 'center',
+                      padding: [0, 15, 28, 0]
+                    },
+                    b: {
+                      fontSize: 14,
+                      align: 'center',
+                      padding: [0, 15, 0, 0],
+                      lineHeight: 25
+                    }
+                  }
+                },
+                formatter: (name) => {
+                  if (name === '企业数量') {
+                    name = name + '(个)'
+                  }
+                  return name
+                }
+              }
+            }
+          }
+        } else if (this.type === 've-treemap') {
+          this.treeMapChart = {
+            options: {
+              title: {
+                subtext: '单位:个、万元',
+                left: '0',
+                top: '-8px',
+                textStyle: {
+                  color: '#000',
+                  fontWeight: 'normal'
+                }
+              },
+              tooltip: {
+                formatter: this.treetooltipFormatter
+              }
+            },
+            defaultOptions: {
+              legend: {
+                show: true,
+                selectedMode: 'single',
+                data: [],
+                bottom: 0,
+                itemGap: 5
+              },
+              tooltip: {
+                backgroundColor: '#fff',
+                confine: true,
+                textStyle: {
+                  color: '#171826',
+                  fontSize: 12
+                },
+                padding: [7, 12],
+                extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+                borderWidth: 2,
+                borderColor: '#F5F6F7'
+              },
+              series: [
+                {
+                  type: 'treemap',
+                  width: '100%',
+                  // height: '85%',
+                  // top: '15%',
+                  roam: false, // 是否开启拖拽漫游(移动和缩放)
+                  nodeClick: false, // 点击节点后的行为,false无反应
+                  breadcrumb: {
+                    show: false
+                  },
+                  label: { // 描述了每个矩形中,文本标签的样式。
+                    normal: {
+                      show: true,
+                      position: ['10%', '40%']
+                    }
+                  },
+                  itemStyle: {
+                    normal: {
+                      show: true,
+                      textStyle: {
+                        color: '#fff',
+                        fontSize: 16
+                      },
+                      borderWidth: 1,
+                      borderColor: '#fff'
+                    },
+                    emphasis: {
+                      label: {
+                        show: true
+                      }
+                    }
+                  },
+                  data: [
+                    // {
+                    //   name: 'xxx',
+                    //   value: 122
+                    // },
+                    // {
+                    //   name: 'yyy',
+                    //   value: 122
+                    // }
+                  ]
+                }
+              ]
+            }
+          }
+        } else if (this.type === 've-line') {
+          let _this = this
+          this.lineChart = {
+            options: {
+              height: '100%',
+              colors: ['#05A6F3', '#FF9F40'],
+              config: this.configOptions
+            },
+            extend: {
+              yAxis: {
+                axisLabel: {
+                  formatter: p => p + '%'
+                }
+              }
+            },
+            defaultOption: {
+              color: ['#05A6F3', '#FF9F40'],
+              xAxis: {
+                axisLabel: {
+                  formatter: function (params) {
+                    var arr = params.split('~')
+                    var isPc = _this.IsPC()
+                    if (arr.length === 2 && !isPc) {
+                      return arr.join('\n~')
+                    } else {
+                      return params
+                    }
+                  },
+                  textStyle: {
+                    color: '#626262',
+                    fontSize: 10
+                  },
+                  interval: 0
+                }
+              },
+              grid: {
+                top: 10,
+                left: 12,
+                right: 12
+              },
+              yAxis: {
+                splitLine: {
+                  lineStyle: {
+                    type: 'dashed',
+                    width: 0.5
+                  }
+                },
+                nameGap: 15,
+                nameTextStyle: {
+                  fontSize: 12,
+                  align: 'left',
+                  color: '#9B9CA3',
+                  padding: [0, 0, 0, -30]
+                },
+                axisLabel: {
+                  margin: 2,
+                  fontSize: 12,
+                  color: '#5F5E64',
+                  interval: 'auto',
+                  formatter: (value, index) => {
+                    return value.toString().replace(/,/, '')
+                  }
+                }
+              },
+              legend: {
+                orient: 'horizontal',
+                icon: 'circle',
+                bottom: 10,
+                itemWidth: 8,
+                itemHeight: 8,
+                itemGap: 40,
+                textStyle: {
+                  color: '#5F5E64',
+                  fontSize: 12
+                }
+              },
+              series: {
+                type: 'line',
+                showSymbol: false,
+                smooth: false,
+                symbol: 'circle',
+                symbolSize: 3,
+                itemStyle: {
+                  borderColor: '#fff',
+                  borderWidth: 1
+                }
+              },
+              tooltip: {
+                backgroundColor: '#fff',
+                confine: true,
+                axisPointer: {
+                  type: 'line',
+                  lineStyle: {
+                    width: 2,
+                    color: '#2ABED1'
+                  },
+                  z: 3
+                },
+                textStyle: {
+                  color: '#171826',
+                  fontSize: 12
+                },
+                padding: [7, 12],
+                extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+                borderWidth: 2,
+                borderColor: '#F5F6F7'
+              },
+              lineStyle: {
+                width: 0.5
+              }
+            }
+          }
+        }
+      },
+      // S--histogram--S
+      extend (chart) {
+        chart.setOption({
+          series: [
+            {
+              type: 'bar',
+              barMaxWidth: 20
+            },
+            {
+              type: 'bar',
+              barMaxWidth: 20
+            }
+          ]
+        })
+      },
+      tooltipFormatter (params) {
+        let tip = `<div style="padding-top:2px;color:#9B9CA3;">${params[0].name}</div>`
+        for (let i = 0; i < params.length; i++) {
+          if (params[i].value === undefined || params[i].value === '') {
+            params[i].value = 0
+          }
+          if (i === 0) {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%<br/>'
+          } else if (i === 1) {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%<br/>'
+          }
+        }
+        return tip
+      },
+      // E--histogram--E
+      // S--barLineChart--S
+      barExtend (chart) {
+        chart.setOption({
+          series: [{
+            type: 'bar',
+            barMaxWidth: 20
+          }, {
+            type: 'line',
+            smooth: false,
+            symbol: 'none'
+          }]
+        })
+      },
+      newTimeConfig (options) {
+        options.xAxis[0].axisLabel.rotate = 60
+        options.xAxis[0].axisLabel.interval = 'auto'
+
+        options.yAxis[1].axisLabel.show = true
+
+        if (this.chartData.rows.length > 12) {
+          // 设置时间轴
+          Object.assign(options, {
+            // grid解决dataZoom文字被隐藏的问题
+            // https://github.com/apache/echarts/issues/11601
+            grid: {
+              left: '5%',
+              right: '13%'
+            },
+            dataZoom: {
+              show: true, // 显示滚动条
+              realtime: true, // 拖动时,是否实时更新系列的视图
+              type: 'slider',
+              height: 20,
+              bottom: 0,
+              textStyle: {
+                fontSize: 10
+              }
+            }
+          })
+        }
+
+        options.legend.bottom = 30
+        options.legend.data = [
+          { icon: 'rect', name: this.chartData.columns[1] },
+          { icon: 'line', name: this.chartData.columns[2] }
+        ]
+
+        options.tooltip.axisPointer.shadowStyle.color = 'rgba(5,166,243,0.1)'
+        options.tooltip.formatter = params => {
+          let tip = `<div style="padding-top:2px;color:#9B9CA3;">${params[0].name}</div>`
+          for (let i = 0; i < params.length; i++) {
+            if (params[i].value === undefined || params[i].value === '') {
+              params[i].value = 0
+            }
+            if (params[i].seriesName.indexOf('环比') === -1) {
+              const match = params[i].seriesName.match(/((.*))$/g)
+              let unit = ''
+              if (Array.isArray(match)) {
+                unit = match.join('').replace(/[()]/g, '')
+              }
+              tip = tip + params[i].marker + params[i].seriesName.replace(`(${unit})`, '') + ':' + params[i].value + unit + '<br/>'
+            } else {
+              tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>'
+            }
+          }
+          return tip
+        }
+        return options
+      },
+      // E--barLineChart--E
+      // S--treeMapChart--S
+      updateChartView () {
+        this.myChart = echarts.init(this.$el, 'light')
+        if (!this.myChart) return
+        this.mergeOptions()
+        this.myChart.setOption(this.treeMapChart.defaultOptions)
+        window.addEventListener('resize', () => {
+          // this.myChart.resize()
+        })
+      },
+      mergeOptions () {
+        // 设置数据
+        this.treeMapChart.defaultOptions.series[0].data = this.chartData
+        // 设置图例?
+        this.treeMapChart.defaultOptions.legend.data = this.chartData.map(item => {
+          return item.name
+        })
+
+        _.merge(this.treeMapChart.defaultOptions, this.treeMapChart.options)
+      },
+      treetooltipFormatter (params) {
+        const item = params.data
+        let tip = `<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:${params.color};"></span>${params.name}<br />`
+        if (item && item.value) {
+          tip += `<div>项目数量:${item.value}个<div>`
+        }
+        if (item && item.amount) {
+          tip += `<div>项目金额:${item.amount}万元<div>`
+        }
+        return tip
+      },
+      // E--treeMapChart--E
+      // S--lineChart--S
+      configOptions (options) {
+        // 面积颜色-渐变
+        Object.assign(options.series[0], {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                {
+                  offset: 0,
+                  color: 'rgba(42, 190, 209, 0.12)'
+                },
+                {
+                  offset: 1,
+                  color: 'rgba(42, 190, 209, 0)'
+                }
+              ], false)
+            }
+          }
+        })
+        Object.assign(options.series[1], {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                {
+                  offset: 0,
+                  color: 'rgba(255, 159, 63, 0.12)'
+                },
+                {
+                  offset: 1,
+                  color: 'rgba(255, 159, 63, 0)'
+                }
+              ], false)
+            }
+          }
+        })
+
+        Object.assign(options.legend, {
+          icon: 'rect'
+        })
+
+        options.tooltip.formatter = params => {
+          let tip = `<div style="padding-top:2px;color:#9B9CA3;">${params[0].name}</div>`
+          for (let i = 0; i < params.length; i++) {
+            params[i].marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' + params[i].color + ';"></span>'
+            tip += params[i].marker + params[i].seriesName + ':' + params[i].value[1].toString().replace(/,/, '') + '%' + '<br/>'
+          }
+          return tip
+        }
+        return options
+      },
+      mergeExtendOptions () {
+        _.merge(this.lineChart.defaultOption, this.lineChart.extend)
+      }
+      // E--lineChart--E
+    }
+  })
+}
+
+window.vComponentChart = vComponentChart
+if (window.proxy) {
+  window.proxy.vComponentChart = vComponentChart
+}

+ 7 - 4
src/web/staticres/common-module/collection/css/index.css

@@ -480,7 +480,7 @@
 }
 
 .collection .timeTag .area-card-item {
-    width: 1.56rem;
+    min-width: 1.56rem;
     height: .72rem;
     background: #F5F6F7;
     border-radius: .08rem;
@@ -1001,10 +1001,10 @@
     display: flex;
     justify-content: center;
     align-items: center;
+    margin-top: .48rem;
 }
 
 .vip_openDialog .openBtn .goBtn {
-    margin-top: .48rem;
     width: 4.78rem;
     height: 100%;
     background: #2cb7ca;
@@ -1073,7 +1073,7 @@
 
 
 /* 企业画像历史项目联系人 */
-.history-list .tab-card-title, 
+.history-list .tab-card-title,
 .history-list .project-info-item{
   padding-left: 0!important;
   padding-right: 0!important;
@@ -1440,6 +1440,7 @@
   width: 100%;
   height: 100%;
 }
+<<<<<<< HEAD
 .fl_{
   float: left;
 }
@@ -1455,4 +1456,6 @@
   vertical-align: top;
   margin-left: 0.08rem;
 
-}
+}
+=======
+>>>>>>> master

+ 325 - 0
src/web/staticres/common-module/collection/js/analysis-report-example.js

@@ -0,0 +1,325 @@
+var vipDialog = `
+<div class="vip_openDialog">
+  <div class="vip_content">
+    <div class="vip_content_div">
+      <img class="vip_img" :src="imgurl" />
+      <span class="vip_example">示例</span>
+    </div>
+  </div>
+  <div class="vip_head">
+      <span style="display:none;">{{getTextMap.titleText}}</span>
+      <span class="vip_extend"><span>{{getTextMap.headText.top}}</span><br/>{{getTextMap.headText.bot}}</span>
+  </div>
+  <div class="openBtn">
+      <button class="goBtn" @click="goOpen(getTextMap.headText.top,getTextMap.headText.bot, getTextMap.source)">{{getTextMap.btnText}}</button>
+  </div>
+</div>
+`
+
+var chartExample = {
+  name: 'chart-example',
+  template: vipDialog,
+  props: {
+    'imgurl': {
+      type: String,
+      default: function() {
+        return ''
+      }
+    },
+    "type": {
+      type: String,
+      default: function () {
+        return ''
+      }
+    },
+    "power": {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    "status": {
+      type: Number,
+      default: function () {
+        return 0
+      }
+    },
+    "userinfo": {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    },
+    "useage": {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    },
+  },
+  data: function() {
+    return {
+      titleText: '开通大会员',
+      btnText: '免费体验',
+      headText: {
+        top: '通过实时监控项目的招标、中标、合同等',
+        bot: '信息,全面挖掘更多潜在商机!'
+      }
+    }
+  },
+  computed: {
+    getTextMap () {
+      var textMap = {
+        titleText: '开通大会员',
+        btnText: '去开通',
+        headText: {
+          top: '通过实时监控项目的招标、中标、合同等',
+          bot: '信息,全面挖掘更多潜在商机!'
+        },
+        source: ''
+      }
+      // if (this.power.indexOf(5) < 0 && this.status > 0) {
+      //   textMap.btnText = '联系客服'
+      // }
+      var platform = utils.isWeiXinBrowser ? 'wx' : 'app'
+      switch (this.type) {
+          // 市场概况
+        case 'item_1': {
+          textMap.headText.top = '通过招标大数据综合分析项目体量,'
+          textMap.headText.bot = '采购单位和中标单位数量,全面掌握市场趋势'
+          textMap.source = platform + "_analysis_market_overview"
+          break
+        }
+          // 项目规模分布
+        case 'item_2': {
+          textMap.headText.top = '从项目总金额、项目总数等多维度分析'
+          textMap.headText.bot = '了解市场需求状况,全面挖掘更多潜在商机'
+          textMap.source = platform + "_analysis_Scale_project"
+          break
+        }
+          // 地区分布
+        case 'item_3': {
+          textMap.headText.top = '根据项目数量、中标金额统计市场热度高的区域'
+          textMap.headText.bot = '为企业市场战略布局提供可靠的数据支持'
+          textMap.source = platform + '_analysis_regional_distribution'
+          break
+        }
+          // 细分市场
+        case 'item_4_1': {
+          textMap.headText.top = '通过市场细分,企业可以综合选择适合的目标市场'
+          textMap.headText.bot = '有利于挖掘市场机会,开拓新市场'
+          textMap.source = platform + '_analysis_refining_market'
+          break
+        }
+        case 'item_4_2': {
+          textMap.headText.top = '通过市场细分,企业可以综合选择适合的目标市场'
+          textMap.headText.bot = '有利于挖掘市场机会,开拓新市场'
+          textMap.source = platform + '_analysis_refining_market'
+          break
+        }
+          // 采购单位项目数量TOP3
+        case 'item_5': {
+          textMap.headText.top = '直观了解优质采购单位名单'
+          textMap.headText.bot = '分析采购单位与供应商关系远近,辅助市场决策'
+          textMap.source = platform + '_analysis_buyer_number'
+          break
+        }
+          // 采购单位项目金额TOP3
+        case 'item_6': {
+          textMap.headText.top = '透过采购单位项目采购金额排名'
+          textMap.headText.bot = '重点合作单位采购占比,帮助供应商挖掘市场机会'
+          textMap.source = platform + '_analysis_buyer_amount'
+          break
+        }
+          // 中标单位项目数量TOP3
+        case 'item_7': {
+          textMap.headText.top = '综合分析中标企业及合作采购单位'
+          textMap.headText.bot = '洞悉行业的市场竞争格局和市场份额'
+          textMap.source = platform + '_analysis_winner_number'
+          break
+        }
+          // 中标单位项目金额TOP3
+        case 'item_8': {
+          textMap.headText.top = '洞察行业的中标市场情况、分析业务关系'
+          textMap.headText.bot = '为企业找准市场机会,制定市场策略提供数据分析'
+          textMap.source = platform + '_analysis_winner_amount'
+          break
+        }
+      }
+      return textMap
+    },
+    // 遮罩按钮对应文案
+    shadeBottomBtnText () {
+      let btnText = ''
+      var info = this.userinfo
+      var usage = this.useage
+      // 【立即解锁】:未体验过采购单位画像的免费用户,点击进行“欢迎体验采购单位全景分析”留资
+      // 【去开通】:已体验过1次采购单位画像的免费用户,点击进入超级订阅购买页
+      // 【前往升级】:超级订阅老版用户+购买了非全国采购单位画像余额为0的超级订阅新版用户,点击进入超级订阅升级页
+      // 【联系客服】:购买了全国采购单位画像余额为0的超级订阅新版用户+无采购单位画像权限的大会员客户;点击调起智齿在线客服
+      if (info.isFree) {
+        if (info.freeBuyerPort === 0) {
+          btnText = '立即解锁'
+        } else {
+          btnText = '去开通'
+        }
+      } else {
+        // 老超级订阅用户
+        var oldVip = info.vipStatus > 0 && !info.viper
+        // 新超级订阅用户
+        var newVip = info.vipStatus > 0 && info.viper
+        // 大会员用户
+        var member = this.status > 0
+        // 新超级订阅用户买的非全国 余额为0
+        var noAllProvinNoCounts = newVip && usage.provin !== -1 && usage.surplus <= 0
+        // 超级订阅新用户 购买的全国 余额为0
+        var allProvinNoCounts = newVip && usage.provin === -1 && usage.surplus <= 0
+        // 无权限的大会员用户
+        var noAuthMember = member && this.power.indexOf(5) === -1
+        // 纯商机管理用户
+        var entniche = info.entniche && !oldVip && !newVip && !member
+        // 超级订阅用户采购单位画像查看次数为0遮罩按钮显示'立即充值'
+        if (oldVip || noAllProvinNoCounts) {
+          if(oldVip) {
+            btnText = '前往升级'
+          } else {
+            btnText = '立即充值'
+          }
+        } else if (allProvinNoCounts || noAuthMember || entniche) {
+          if(allProvinNoCounts) {
+            btnText = '立即充值'
+          } else {
+            btnText = '联系客服'
+          }
+        }
+      }
+      return btnText
+    }
+  },
+  methods: {
+    linkFn: function(id, source) {
+      var u = this.useage
+      const textinit = `
+      <div><span class="on">升级超级订阅:</span><span>适合需要订阅更多省份、查看更多采购单位画像及企业画像的用户。</span></div><div style="margin-top:20px"><span class="on">充值画像包:</span><span>适合仅需要查看更多采购单位画像用户。</span></div>
+      `
+      var isWeixin = utils.isWeiXinBrowser
+      if(!isWeixin) {
+        if (this.getTextMap.btnText == '立即解锁') {
+          // 留资
+          location.href = '/jyapp/frontPage/bigmember/free/perfect_info?source=' + source
+        } else if (this.getTextMap.btnText == '联系客服') {
+          // try {
+          //   JyObj.callPhone('400-108-6670');
+          // } catch (error) {
+          //   console.log(error)
+          // }
+          location.href = '/jyapp/free/customer' // 客服
+        } else if (this.getTextMap.btnText == '去开通') {
+          // location.href = '/jyapp/vipsubscribe/vipsubscribe_new'
+          location.href = '/jyapp/frontPage/bigmember/free/perfect_info?source=app_search_dzhfxbg'
+        } else if (this.getTextMap.btnText == '前往升级') {
+          //跳转清除旧套餐缓存,防止计算价格出错
+          sessionStorage.removeItem('vipSub_oldBuySet')
+          // location.href = '/jyapp/vipsubscribe/upgradePage'
+          location.href = '/jy_mobile/common/order/create/svip?type=upgrade'
+        } else if (this.getTextMap.btnText == '立即充值') {
+          // 选择充值方式
+          // 判断是否购买全国,全国直接跳转到到充值页面, 非全国显示弹窗
+          if(u.provin == -1) {
+            location.href = '/jy_mobile/common/order/create/areapack?type=1'
+          } else {
+            this.$dialog.confirm({
+              title: '请选择充值方式',
+              message: textinit,
+              overlayClass: 'showSelectDialog',
+              width: 303,
+              className: 'pro-log select-recharge',
+              messageAlign: 'left',
+              confirmButtonColor: '#2ABED1',
+              confirmButtonText: '充值画像包',
+              cancelButtonText: '升级超级订阅',
+              closeOnClickOverlay: true,
+              showCancelButton: true
+            }).then(function () {
+              location.href = '/jy_mobile/common/order/create/buyerpack?type=1'
+            }).catch(function (e) {
+              if(e == 'cancel') {
+                //跳转清除旧套餐缓存,防止计算价格出错
+                sessionStorage.removeItem('vipSub_oldBuySet')
+                // location.href = '/jyapp/vipsubscribe/upgradePage'
+                location.href = '/jy_mobile/common/order/create/svip?type=upgrade'
+              }
+            })
+          }
+        }
+      } else {
+        if (this.getTextMap.btnText == '立即解锁') {
+          // 留资
+          location.href = '/weixin/frontPage/bigmember/free/perfect_info?source=' + source
+        } else if (this.getTextMap.btnText == '联系客服') {
+          // location.href = 'tel:400-108-6670'
+          location.href = '/big/wx/page/customer'
+        } else if (this.getTextMap.btnText == '去开通') {
+          // location.href = '/front/vipsubscribe/vipsubscribe_new'
+          location.href = '/weixin/frontPage/bigmember/free/perfect_info?source=wx_search_dzhfxbg'
+        } else if (this.getTextMap.btnText == '前往升级') {
+          // location.href = '/front/vipsubscribe/upgradePage'
+          location.href = '/jy_mobile/common/order/create/svip?type=upgrade'
+        } else if (this.getTextMap.btnText == '立即充值') {
+          // 判断是否购买全国,全国直接跳转到到充值页面, 非全国显示弹窗
+          if(u.provin == -1) {
+            location.href = '/jy_mobile/common/order/create/areapack?type=1'
+          }  else {
+            this.$dialog.confirm({
+              title: '请选择充值方式',
+              message: textinit,
+              overlayClass: 'showSelectDialog',
+              width: 303,
+              className: 'pro-log select-recharge',
+              messageAlign: 'left',
+              confirmButtonColor: '#2ABED1',
+              confirmButtonText: '充值画像包',
+              cancelButtonText: '升级超级订阅',
+              closeOnClickOverlay: true,
+              showCancelButton: true
+            }).then(function () {
+              location.href = '/jy_mobile/common/order/create/buyerpack?type=1'
+            }).catch(function (e) {
+              if(e == 'cancel') {
+                // location.href = '/front/vipsubscribe/upgradePage'
+                location.href = '/jy_mobile/common/order/create/svip?type=upgrade'
+              }
+            })
+          }
+        }
+      }
+    },
+    goOpen: function(top, bot, source) {
+      console.log(this.$parent.encryptId)
+      var params = {
+        mold: 'isCBBT',
+        id: this.$parent.encryptId,
+        introduce: top + bot
+      }
+      var _this = this
+      console.log(_this.getTextMap.btnText)
+      if (_this.getTextMap.btnText == '立即解锁') {
+        $.ajax({
+          type: 'POST',
+          url: '/publicapply/drainage/buyerunit',
+          contentType: "application/json",
+          data: JSON.stringify(params),
+          success: function (res) {
+            _this.linkFn(_this.$parent.encryptId, source)
+          },
+          error: function (error) {
+            console.log(error)
+            _this.linkFn(_this.$parent.encryptId, source)
+          }
+        })
+      } else {
+        _this.linkFn(_this.$parent.encryptId)
+      }
+    }
+  }
+}

+ 1 - 1
src/web/staticres/common-module/collection/js/keyword-mobile.js

@@ -147,7 +147,7 @@ var keywordComponent = {
       const _this = this
       let url = '/subscribepay/afterPay/getUserInfo?t=' + Date.now()
       if(_this.protype == 'bigmember') {
-        url = '/bigmember/use/info?t=' + Date.now()
+        url = '/bigmember/marketAnalysis/analysisKeyWord?t=' + Date.now()
       } else if(_this.protype == 'entniche') {
         url = '/entnicheNew/subscribe/key/get'
       }

+ 71 - 0
src/web/staticres/common-module/history-push/css/recommend.css

@@ -0,0 +1,71 @@
+.analysis-module{
+  z-index: 999;
+}
+.recommend-bg {
+  margin-bottom: .16rem;
+}
+.recommend-bg .item-title {
+  font-size: .32rem;
+  line-height: .44rem;
+  color: #171826;
+}
+.recommend-bg .desc {
+  font-size: .24rem;
+  line-height: .36rem;
+  color: #9b9ca3;
+}
+.recommend-bg .pro-list {
+  display: flex;
+  align-items: center;
+  margin: .16rem 0;
+}
+.recommend-bg .list-title {
+  flex: 1;
+  font-size: .28rem;
+  line-height: .44rem;
+  color: #171826;
+}
+.recommend-bg .tags {
+  display: inline-block;
+  padding: .02rem .16rem;
+  margin-right: .16rem;
+  border-radius: 4.08rem;
+  font-size: .24rem;
+  line-height: .36rem;
+  flex-shrink: 0;
+}
+.recommend-bg .tags.blue-tags {
+  background: rgba(42, 190, 209, 0.08);
+  color: #2ABED1;
+}
+.recommend-bg .tags.orange-tags {
+  background: rgba(255, 159, 64, 0.1);
+  color: #ff9f40;
+}
+.recommend-bg .pro-list-data {
+  flex: 1;
+  display: flex;
+  justify-content: space-between;
+}
+.recommend-bg .proposed-data,
+.recommend-bg .buyer-data {
+  flex-shrink: 0;
+  font-size: .28rem;
+  line-height: .44rem;
+  color: #171826;
+}
+.recommend-bg .data-color{
+  color: #5f5e64;;
+}
+.recommend-bg .mr-49 {
+  margin-right: .98rem;
+}
+.recommend-bg .j-button-group {
+  padding: .16rem 0;
+}
+.recommend-bg .j-button-confirm {
+  font-size: .32rem;
+}
+.recommend-bg ::v-deep .van-collapse-item__content {
+  padding: .16rem .32rem 0;
+}

+ 8 - 2
src/web/staticres/common-module/history-push/js/historypush.js

@@ -66,7 +66,8 @@ var vm = new Vue({
     keywordComponent: keywordComponent,
     noticeComponent: noticeComponent,
     rootComponent: rootComponent,
-    moneyComponent: moneyComponent
+    moneyComponent: moneyComponent,
+    recommendCom: recommendCom
   },
   data: function() {
     return {
@@ -166,7 +167,8 @@ var vm = new Vue({
         },
       ],
       selectFile: '',
-      selectMoney: ''
+      selectMoney: '',
+      collapseStatus: true
     }
   },
   computed: {
@@ -231,6 +233,10 @@ var vm = new Vue({
     this.addEventListerWeb()
   },
   methods: {
+    // 超前项目推荐是否折叠
+    onToggleStatus (status) {
+      this.collapseStatus = status
+    },
     // 搬家提示弹窗
     subPageMove(data) {
       let _this = this

+ 76 - 0
src/web/staticres/common-module/history-push/js/recommend.js

@@ -0,0 +1,76 @@
+var recommendTemplate = 
+`
+<template>
+<div class="recommend-bg" v-click-outside="onClickOutSide">
+  <van-sticky>
+    <van-collapse v-model="activeName" accordion :border="false">
+      <van-collapse-item :name="1" ref="collapseRef">
+        <div slot="title">
+          <span class="item-title">超前项目推荐</span>
+          <div slot="label">
+            <span v-if="activeName" class="desc">提前推送超前项目,优先对接项目负责人</span>
+            <p v-else>
+              <span class="proposed-data data-color mr-49">拟建项目:<em class="highlight-text">299条</em></span>
+              <span class="buyer-data data-color">采购意向:<em class="highlight-text">299条</em></span>
+            </p>
+          </div>
+        </div>
+        <div class="item-content">
+          <div class="pro-list">
+            <span class="tags blue-tags">累计发布</span>
+            <div class="pro-list-data">
+              <span class="proposed-data">拟建项目:<em class="highlight-text">299条</em></span>
+              <span class="buyer-data">采购意向:<em class="highlight-text">299条</em></span>
+            </div>
+          </div>
+          <div class="pro-list" v-for="(item, index) in list" :key="index">
+            <span class="tags orange-tags">最新项目</span>
+            <span class="ellipsis list-title" v-html="getTitle(item.title)"></span>
+          </div>
+          <div class="j-button-group height40">
+            <button class="j-button-confirm" @click="$emit('onClick')">感兴趣点我</button>
+          </div>
+        </div>
+      </van-collapse-item>
+    </van-collapse>
+  </van-sticky>
+</div>
+</template>
+
+`
+
+var recommendCom = {
+  name: 'recommend-card',
+  template: recommendTemplate,
+  props: {
+    keys: {
+      type: Array,
+      default () {
+        return []
+      }
+    }
+  },
+  data () {
+    return {
+      activeName: 1,
+      list: [{
+        title: '某单位智慧饭堂软件采购流标公告(2022-JLDJBE-W3003)'
+      }, {
+        title: '某单位智慧饭堂软件采购流标公告(2022-JLDJBE-W3003)'
+      }]
+    }
+  },
+  watch: {
+    activeName (val) {
+      this.$emit('toggle', Boolean(val))
+    }
+  },
+  methods: {
+    getTitle (title) {
+      return utils.replaceKeyword(title, this.keys)
+    },
+    onClickOutSide () {
+      this.activeName = 0
+    }
+  }
+}

+ 34 - 5
src/web/staticres/common-module/perfect-info/js/perfect-info.js

@@ -24,12 +24,21 @@ var titleMap = {
   'article_original': '完善信息',
   'peugeot_supplier_regist':'供应商报名',
   'certificateServices-': '企业认证服务',
-  article_purchase_intention: '欢迎体验剑鱼超前项目预测',
-  article_proposed_project: '欢迎体验剑鱼超前项目预测',
+  article_purchase_intention: '欢迎体验剑鱼大会员',
+  article_proposed_project: '欢迎体验剑鱼大会员',
 
   'medical-app': '欢迎体验医械通',
   'medical-wx': '欢迎体验医械通',
-  'super_subscrip_buy_advanced_items': '欢迎体验剑鱼超前项目预测',
+  'super_subscrip_buy_advanced_items': '欢迎体验剑鱼大会员',
+  // P271 企业潜客 搜索、订阅页面新增
+  app_subscribe_cqxm: '欢迎体验剑鱼大会员',
+  app_search_cqxm: '欢迎体验剑鱼大会员',
+  app_subscribe_dzhfxbg: '欢迎体验剑鱼大会员',
+  app_search_dzhfxbg: '欢迎体验剑鱼大会员',
+  wx_subscribe_cqxm: '欢迎体验剑鱼大会员',
+  wx_search_cqxm: '欢迎体验剑鱼大会员',
+  wx_subscribe_dzhfxbg: '欢迎体验剑鱼大会员',
+  wx_search_dzhfxbg: '欢迎体验剑鱼大会员'
 }
 
 // tip
@@ -106,7 +115,15 @@ var tipMap = {
   'medical-app': '请填写以下表单,服务专员会尽快与您联系',
   'medical-wx': '请填写以下表单,服务专员会尽快与您联系',
   super_subscrip_buy_advanced_items: '留下您的联系方式,我们会尽快和您联系。提前介入项目,助您轻松中标。', // 采购意向
-
+  // P271 企业潜客 搜索、订阅页面新增
+  app_subscribe_cqxm: '请完善个人信息,我们将尽快与您联系,体验超前项目推荐服务!',
+  app_search_cqxm: '请完善个人信息,我们将尽快与您联系,体验超前项目推荐服务!',
+  app_subscribe_dzhfxbg: '请完善个人信息,我们将尽快与您联系,为您量身定制报告,做市场复盘数据支持。',
+  app_search_dzhfxbg: '请完善个人信息,我们将尽快与您联系,为您量身定制报告,做市场复盘数据支持。',
+  wx_subscribe_cqxm: '请完善个人信息,我们将尽快与您联系,体验超前项目推荐服务!',
+  wx_search_cqxm: '请完善个人信息,我们将尽快与您联系,体验超前项目推荐服务!',
+  wx_subscribe_dzhfxbg: '请完善个人信息,我们将尽快与您联系,为您量身定制报告,做市场复盘数据支持。',
+  wx_search_dzhfxbg: '请完善个人信息,我们将尽快与您联系,为您量身定制报告,做市场复盘数据支持。'
 }
 
 var vNode = {
@@ -272,7 +289,7 @@ var vNode = {
         titleText = '完善信息'
       }
 
-      
+
       for (var key in titleMap) {
         if (source.indexOf(key) !== -1) {
           titleText = titleMap[key]
@@ -307,6 +324,18 @@ var vNode = {
           hideLabel(['area', 'class',  'workScope', 'partnerNeeds', 'agree'])
           break
         }
+
+        case 'app_subscribe_cqxm':
+        case 'app_search_cqxm':
+        case 'app_subscribe_dzhfxbg':
+        case 'app_search_dzhfxbg':
+        case 'wx_subscribe_cqxm':
+        case 'wx_search_cqxm':
+        case 'wx_subscribe_dzhfxbg':
+        case 'wx_search_dzhfxbg': {
+          hideLabel()
+          break
+        }
         default: {
           // 标书制作或者三方认证(case语句满足不了条件,放default中做更多判断)
           if (source === 'bid_document_Introduction_page' || source.indexOf('certificateServices') > -1) {

+ 584 - 0
src/web/staticres/common-module/report-analysis/css/report_analysis.css

@@ -0,0 +1,584 @@
+.order-list-container .van-tabs__wrap {
+  height: .96rem;
+}
+.order-list-container .van-tabs__line {
+  bottom: .36rem;
+}
+.order-list-container .van-tab__pane {
+  height: 100%;
+}
+.order-list-container .van-tabs__content {
+  flex: 1;
+  overflow-y: scroll;
+  overflow-x: hidden;
+}
+.order-list-container .van-tabs {
+  width: 100%;
+}
+.order-list-container .van-tab {
+  font-size: .32rem;
+  line-height: .4rem;
+}
+
+/* vant-reset */
+.van-dialog {
+  width: 6rem;
+  border-radius: .16rem;
+}
+.van-dialog__header {
+  font-weight: 700;
+  font-size: 18px;
+  line-height: 26px;
+  color: #171826;
+}
+.van-dialog__content {
+  padding: .16rem .6rem;
+}
+.van-dialog__message {
+  padding-left: 0;
+  padding-right: 0;
+  font-size: .3rem;
+  line-height: .44rem;
+  color: #5F5E64;
+}
+.van-dialog .van-button {
+  font-size: 18px;
+  line-height: 26px;
+}
+
+.van-dialog  .van-button--default {
+  color: #171826;
+}
+
+.van-toast {
+  max-width: 4.2rem;
+  line-height: 1.6;
+}
+
+/* vant-custom */
+.j-confirm-dialog {
+  border-radius: 8px;
+}
+.j-confirm-dialog .van-dialog__message {
+  font-size: .32rem;
+  color: #171826;
+  line-height: .48rem;
+  text-align: left;
+}
+.j-confirm-dialog.text-center .van-dialog__message {
+  text-align: center;
+}
+.j-confirm-dialog .van-button {
+  font-size: .36rem;
+  color: #171826;
+  line-height: .52rem;
+}
+
+/* j-tag */
+.j-tag {
+  white-space: nowrap;
+}
+.j-tag.tag-orange {
+  color: #FF9F3F;
+  background-color: rgba(255, 159, 63, 0.1);
+  border-color: rgba(255, 159, 63, 0.1);
+}
+.j-tag.tag-blue {
+  color: #05A6F3;
+  background-color: rgba(5, 166, 243, 0.1);
+  border-color: rgba(5, 166, 243, 0.1);
+}
+.j-tag.tag-plain {
+  color: #5E5E64;
+  background-color: #F7F9F9;
+  border-color: rgba(0, 0, 0, 0.05);
+}
+
+/* empty */
+.empty-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  flex: 1;
+  height: 80%;
+  padding: .32rem;
+  box-sizing: border-box;
+  background-color: rgba(245, 244, 249, 1);
+}
+.empty-container {
+  min-height: 7rem;
+}
+.empty-main,
+.empty-content-position {
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.empty-content-position {
+  margin-top: -1rem;
+}
+
+.empty-container .tip-text {
+  margin-top: .2rem;
+  color: #5F5E64;
+  font-size: .28rem;
+  line-height: .4rem;
+  text-align: center;
+}
+
+.empty-container .tip-sub-text {
+  color: #9B9CA3;
+  font-size: .26rem;
+  line-height: .4rem;
+  margin-top: .12rem;
+  text-align: center;
+}
+
+.empty-container .image {
+  width: 4rem;
+  height: 4rem;
+}
+.empty-container .image > img {
+  width: 100%;
+  height: 100%;
+}
+
+/* common-css */
+.j-container .van-tabs__wrap {
+  height: 0.96rem;
+}
+.van-tab {
+  font-size: .32rem;
+  line-height: .4rem;
+}
+
+/* analysis-page */
+.pd-16 {
+  padding: .32rem;
+}
+.pd-lr16 {
+  padding: 0 .32rem;
+}
+.height8 {
+  height: .16rem;
+  width: 100%;
+  color: transparent;
+  background-color: transparent;
+}
+
+.filters-title {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: .24rem .32rem;
+  color: #161826;
+  line-height: .6rem;
+  font-size: .4rem;
+  font-weight: 700;
+}
+.filters-list {
+  margin-bottom: .16rem;
+  border-top: 1px solid transparent;
+}
+.filters-list .van-cell {
+  height: 1.08rem;
+}
+.date-cell .cell-title,
+.filters-list .van-cell__title {
+  color: #161826;
+  line-height: .48rem;
+  font-size: .28rem;
+}
+.j-popup .keys-popup .popup-header {
+  /* padding-top: .24rem;
+  padding-bottom: .24rem; */
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  justify-content: center;
+  height: 1.28rem;
+  padding: 0 .32rem;
+}
+.keys-popup .header-top {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.keys-popup .header-title {
+  margin-right: .2rem;
+}
+.keys-popup .header-action {
+  padding: 0 .32rem;
+  font-size: .26rem;
+  line-height: .42rem;
+  color: #2ABDD1;
+  background: rgba(42, 189, 209, 0.1);
+  border-radius: .24rem;
+  border: 1px solid #2ABDD1;
+}
+
+.keys-popup .header-bottom {
+  margin-top: .1rem;
+  color: #2ABDD1;
+  font-size: .22rem;
+  line-height: .26rem;
+}
+
+.date-cell {
+  padding: 10px 0;
+}
+.date-cell .cell-title {
+  padding: 0 16px;
+}
+
+.filters-list .collection .dateTags .customTime {
+  display: none;
+}
+.filters-list .collection .dateTags .timeTag {
+  flex-wrap: wrap;
+}
+.collection .dateTags {
+  height: unset;
+}
+.collection .timePicker.clickactive {
+  background-color: #fff;
+}
+.collection .timePicker.clickactive::after {
+  content: unset;
+}
+.collection .timePicker.clickactive .van-cell.van-field {
+  border-color: #2abed1;
+}
+.collection .timeTag .area-card-item {
+  width: unset;
+  height: unset;
+  padding: 0 .16rem;
+}
+.date-cell > .j-container > .j-footer {
+  display: none;
+}
+
+.search-result {
+  position: relative;
+}
+.search-result .filters-list .van-cell__title {
+  color: #161826;
+  font-size: .4rem;
+}
+.search-result .section:not(:first-of-type) {
+  position: relative;
+  margin-top: .16rem;
+}
+.search-result .section-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.search-result .section .section-title {
+  color: #161826;
+  line-height: .52rem;
+  font-size: .36rem;
+}
+.search-result .section:not(:first-of-type) .section-content {
+  margin: .16rem 0;
+  padding: .12rem 0;
+}
+
+.fixed-bottom-right {
+  position: absolute;
+  bottom: 15%;
+  right: .32rem;
+}
+.scroll-to-top {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: .8rem;
+  height: .8rem;
+  font-size: .4rem;
+  border-radius: 50%;
+  background-color: #fff;
+  box-shadow: rgb(54,147,79,20%) 0 0 30px 5px;
+}
+
+.section-sticky {
+  width: 100%;
+}
+.van-sticky {
+  padding: 0 .32rem;
+  width: 100%;
+  background-color: #fff;
+}
+
+.section .section-tip-text {
+  font-size: .22rem;
+  line-height: .3rem;
+  color: #9B9BA3;
+  text-align: center;
+}
+
+.search-result .dimension {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  min-height: 2.5rem;
+}
+
+.search-result .dimension .section-content {
+  padding: .28rem 0;
+}
+.van-sticky--fixed {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 1.32rem;
+  background-color: #fff;
+}
+.van-sticky--fixed .dimension-list {
+  padding: 0!important;
+}
+.search-result .dimension > div {
+  width: 100%;
+}
+.search-result .dimension .section-title {
+  font-size: .28rem;
+  line-height: .28rem;
+  padding: .32rem;
+  padding-bottom: 0;
+  text-align: center;
+}
+.search-result .dimension .section-tip-text {
+  padding-bottom: .32rem;
+}
+
+
+.search-result .dimension-list {
+  display: flex;
+  align-items: center;
+  width: 100%;
+}
+.search-result .dimension-item {
+  display: flex;
+  flex: 1;
+  font-size: .28rem;
+  line-height: .4rem;
+}
+.search-result .dimension-item:not(:last-of-type) {
+  margin-right: .32rem;
+}
+.search-result .dimension-item::after {
+  content: unset;
+}
+
+.market-overview-list {
+  display: flex;
+  margin: 0!important;
+  padding-left: .08rem!important;
+  padding-right: .08rem!important;
+}
+.market-overview-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  flex: 1;
+  padding: 0 .08rem;
+}
+.market-overview-item:not(:last-of-type) {
+  border-right: 1px solid #F2F2F2;
+}
+
+.m-overview-name {
+  margin-bottom: .08rem;
+  white-space: nowrap;
+}
+.m-overview-name,
+.m-overview-unit,
+.m-overview-type {
+  font-size: .22rem;
+  line-height: .28rem;
+  color: #5E5E64;
+  text-align: center;
+}
+.m-overview-count {
+  margin: .12rem 0;
+}
+.m-overview-ratio {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-top: .08rem;
+  height: .32rem;
+  padding: 0 .08rem;
+  border-radius: .2rem;
+}
+.m-overview-ratio.red {
+  color: #FA483C;
+  background-color: #FFEDEC;
+}
+.m-overview-ratio.green {
+  color: #04B15E;
+  background-color: #EAF8E5;
+}
+.m-overview-ratio .icon-reverse {
+  transform: rotate(180deg);
+}
+
+/* 表格首页索引 */
+.table-index-rect {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin: 0 auto;
+  width: .4rem;
+  height: .4rem;
+  color: #fff;
+  font-size: .28rem;
+  border-radius: 3px;
+  background-color: #C0C4CC;
+}
+.table-index-rect.red {
+  background-color: #FF3A20;
+}
+.table-index-rect.orange {
+  background-color: #FF9F3F;
+}
+.table-index-rect.soft-orange {
+  background-color: #EED08C;
+}
+
+/* TOP10 */
+.project-top-item {
+  padding: .32rem 0;
+}
+.project-top-item:first-of-type {
+  padding-top: .16rem;
+}
+.project-top-item:last-of-type {
+  padding-bottom: .16rem;
+}
+.project-top-item:not(:last-of-type) {
+  border-bottom: 1px solid rgba(0, 0, 0, 0.03);
+}
+.project-top-item .p-t-i-hd {
+  display: flex;
+  justify-content: space-between;
+}
+.project-top-item .p-t-i-hd .p-t-i-hd-r {
+  display: flex;
+  flex-direction: column;
+  flex: 1;
+  margin-left: .16rem;
+}
+.project-top-item .p-t-i-hd .p-t-i-hd-r-top {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+}
+.project-top-item .p-t-i-hd-r .project-actions {
+  display: flex;
+  align-items: center;
+  color: #2ABDD1;
+  line-height: .36rem;
+  font-size: .24rem;
+  white-space: nowrap;
+}
+.project-top-item .p-t-i-hd-r .project-actions .van-icon {
+  margin-left: .12rem;
+}
+.project-top-item .p-t-i-hd-r .project-actions.icon-reverse .van-icon {
+  transform: rotate(180deg);
+}
+.project-top-item .p-t-i-hd-r .project-info {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.market-top3-table .project-name {
+  max-width: 4rem;
+}
+.project-top-item .p-t-i-hd-r .project-name {
+  font-size: .28rem;
+  color: #1D1D1D;
+  line-height: .48rem;
+  flex: 1;
+}
+.project-top-item .p-t-i-hd-r .project-tags {
+  display: flex;
+  align-items: center;
+}
+.project-top-item .p-t-i-hd-r .project-right {
+  color: #5E5E64;
+}
+.project-top-item .j-tag {
+  margin-right: .08rem;
+}
+.project-top-item .p-t-i-ft {
+  margin-top: .24rem;
+  padding: .16rem;
+  background: linear-gradient(180deg, rgba(108, 217, 236, 0.3) 0%, rgba(255, 255, 255, 0) 100%);
+  border-radius: 6px;
+}
+.project-top-item .p-t-i-ft .p-t-i-ft-top {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.project-top-item .p-t-i-ft .p-t-i-ft-bottom {
+  display: flex;
+  align-items: center;
+  font-size: .24rem;
+  color: #5E5E64;
+  line-height: .36rem;
+}
+.project-top-item .p-t-i-ft .p-t-i-ft-sub {
+  margin-right: .24rem;
+}
+.project-top-item .p-t-i-ft .p-t-i-ft-title {
+  font-size: .26rem;
+  color: #161826;
+  line-height: .36rem;
+}
+.project-top-item .p-t-i-ft .p-t-i-ft-winner {
+  font-size: .24rem;
+  color: #5E5E64;
+  line-height: .36rem;
+}
+.project-top-item .p-t-i-ft.disabled,
+.project-top-item .p-t-i-hd-r .project-name.disabled,
+.project-top-item .p-t-i-ft .p-t-i-ft-winner.disabled {
+  color: #a2a2a2;
+  cursor: not-allowed;
+}
+
+/* time scatter */
+.time-scatter .section-actions {
+  display: flex;
+  align-items: center;
+}
+.time-scatter .action-button {
+  position: relative;
+  margin-left: .36rem;
+  font-size: .26rem;
+  color: #5E5E64;
+  line-height: .28rem;
+}
+.time-scatter .action-button.active {
+  color: #2ABDD1;
+}
+.time-scatter .action-button.active::after {
+  content: '';
+  position: absolute;
+  bottom: -8px;
+  left: 50%;
+  width: 80%;
+  height: .04rem;
+  transform: translateX(-50%);
+  background-color: #2ABDD1;
+}

二进制
src/web/staticres/common-module/report-analysis/image/01-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/01.png


二进制
src/web/staticres/common-module/report-analysis/image/02-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/02.png


二进制
src/web/staticres/common-module/report-analysis/image/03-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/03.png


二进制
src/web/staticres/common-module/report-analysis/image/04-1-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/04-1.png


二进制
src/web/staticres/common-module/report-analysis/image/04-2-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/04-2.png


二进制
src/web/staticres/common-module/report-analysis/image/05-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/05.png


二进制
src/web/staticres/common-module/report-analysis/image/06-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/06.png


二进制
src/web/staticres/common-module/report-analysis/image/07-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/07.png


二进制
src/web/staticres/common-module/report-analysis/image/08-bg.png


二进制
src/web/staticres/common-module/report-analysis/image/08.png


+ 185 - 0
src/web/staticres/common-module/report-analysis/js/components/lineChartScatter.js

@@ -0,0 +1,185 @@
+var lineChartScatterTemplate = `
+<ve-line :data="chartData" :height="options.height" :after-config="options.config" :extend="defaultOption"></ve-line>
+`
+
+var lineChartScatter = {
+  name: 'line-chart-scatter',
+  template: lineChartScatterTemplate,
+  props: {
+    chartData: {
+      type: Object,
+      default () {
+        return {
+          columns: ['金额区间', '采购总金额占比', '采购单位数量占比'],
+          rows: [
+            // {
+            //   金额区间: '>=1亿',
+            //   采购总金额占比: 2,
+            //   采购单位数量占比: 222
+            // },
+            // {
+            //   金额区间: '1000万-1亿',
+            //   采购总金额占比: 322,
+            //   采购单位数量占比: 2222
+            // },
+            // {
+            //   金额区间: '500万-1000万',
+            //   采购总金额占比: 1,
+            //   采购单位数量占比: 111
+            // }
+          ]
+        }
+      }
+    },
+  },
+  data:function () {
+    return {
+      options: {
+        height: '326px',
+        config: this.configOptions
+      },
+      defaultOption: {
+        color: ['#05A6F3', '#FF9F40'],
+        xAxis: {
+          axisLabel: {
+            textStyle: {
+              color: '#626262',
+              fontSize: 10
+            },
+            formatter: this.xAxisFormatter,
+            interval: 0
+          }
+        },
+        grid: {
+          top: 10,
+          left: 12,
+          right: 12
+        },
+        yAxis: {
+          splitLine: {
+            lineStyle: {
+              type: 'dashed',
+              width: 0.5
+            }
+          },
+          nameGap: 15,
+          nameTextStyle: {
+            fontSize: 12,
+            align: 'left',
+            color: '#9B9CA3',
+            padding: [0, 0, 0, -30]
+          },
+          axisLabel: {
+            margin: 2,
+            fontSize: 12,
+            color: '#5F5E64',
+            interval: 'auto',
+            formatter: p => p + '%'
+          }
+        },
+        legend: {
+          orient: 'horizontal',
+          icon: 'circle',
+          bottom: 10,
+          itemWidth: 8,
+          itemHeight: 8,
+          itemGap: 40,
+          textStyle: {
+            color: '#5F5E64',
+            fontSize: 12
+          }
+        },
+        series: {
+          type: 'line',
+          showSymbol: false,
+          smooth: false,
+          symbol: 'circle',
+          symbolSize: 3,
+          itemStyle: {
+            borderColor: '#fff',
+            borderWidth: 1
+          }
+        },
+        tooltip: {
+          backgroundColor: '#fff',
+          confine: true,
+          axisPointer: {
+            type: 'line',
+            lineStyle: {
+              width: 2,
+              color: '#FA483C'
+            },
+            z: 3
+          },
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+          borderWidth: 2,
+          borderColor: '#F5F6F7'
+        },
+        lineStyle: {
+          width: 0.5
+        }
+      }
+    }
+  },
+  computed: {},
+  created () {},
+  methods: {
+    xAxisFormatter (params) {
+      var arr = params.split('~')
+      if (arr.length === 2) {
+        return arr.join('\n~')
+      } else {
+        return params
+      }
+    },
+    configOptions (options) {
+      // 面积颜色-渐变
+      Object.assign(options.series[0], {
+        areaStyle: {
+          normal: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              {
+                offset: 0,
+                color: 'rgba(42, 190, 209, 0.5)'
+              },
+              {
+                offset: 1,
+                color: 'rgba(42, 190, 209, 0)'
+              }
+            ], false)
+          }
+        }
+      })
+      Object.assign(options.series[1], {
+        areaStyle: {
+          normal: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              {
+                offset: 0,
+                color: 'rgba(255, 159, 63, 0.5)'
+              },
+              {
+                offset: 1,
+                color: 'rgba(255, 159, 63, 0)'
+              }
+            ], false)
+          }
+        }
+      })
+      options.tooltip.formatter = params => {
+        let tip = `<div style="padding-top:2px;color:#9B9CA3;">${params[0].name}</div>`
+        for (let i = 0; i < params.length; i++) {
+          params[i].marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' + params[i].color + ';"></span>'
+          tip += params[i].marker + params[i].seriesName + ':' + params[i].value[1].toString().replace(/,/, '') + '%' + '<br/>'
+        }
+        return tip
+      }
+      return options
+    }
+  }
+}

+ 120 - 0
src/web/staticres/common-module/report-analysis/js/components/marketAreaScatter.js

@@ -0,0 +1,120 @@
+var marketAreaScatterTemplate = `
+  <div class="market-area-scatter-chart">
+    <ve-map
+      :height="options.height"
+      :init-options="initRendererSvg"
+      :after-config="options.config"
+      :data="getMapDatas"
+      :settings="defaultSettings"
+      :extend="defaultOptions">
+    </ve-map>
+  </div>
+`
+var marketAreaScatter = {
+  name: 'market-area-scatter',
+  template: marketAreaScatterTemplate,
+  props: {
+    chartData: {
+      type: Object,
+      default () {
+        return {
+          columns: ['项目所在地', '项目数量', '中标金额'],
+          rows: [
+            // {
+            //   项目所在地: '河南',
+            //   项目数量: 2,
+            //   中标金额: 2222
+            // },
+            // {
+            //   项目所在地: '北京',
+            //   项目数量: 22,
+            //   中标金额: 565666
+            // },
+            // {
+            //   项目所在地: '浙江',
+            //   项目数量: 22,
+            //   中标金额: 765666
+            // }
+          ]
+        }
+      }
+    },
+  },
+  data:function () {
+    return {
+      options: {
+        height: '400px',
+        colors: ['#05a6f3'],
+        config: this.configArea
+      },
+      initRendererSvg: {
+        renderer: 'svg'
+      },
+      // 引用/jyapp/big-member/js/echarts_option.js中配置文件
+      defaultSettings: mapSettings.chartSettings,
+      defaultOptions: mapSettings.chartExtend
+    }
+  },
+  computed: {
+    getMapDatas () {
+      return {
+        columns: this.chartData.columns,
+        rows: this.chartData.rows.map(function (v) {
+          return Object.assign({}, v, {
+            name: mapSettings.completionMapName(v.name),
+            _name: v.name
+          })
+        })
+      }
+    }
+  },
+  created () {},
+  methods: {
+    extend (chart) {
+      chart.setOption({
+        series: [{
+          type: 'bar',
+          barWidth: 20
+        }, {
+          type: 'line',
+          smooth: false,
+          symbol: 'none'
+        }]
+      })
+    },
+    configArea (options) {
+      const arr = this.getMapDatas.rows || []
+      const maxNum = Math.max.apply(Math, arr.map((o) => { return o['项目数量'] }))
+      options.visualMap.min = 1
+      options.visualMap.max = maxNum < 100 ? 100 : maxNum
+      options.graphic[0].children[0].style.text = '项目数量(个)'
+      options.graphic[options.graphic.length - 1].children[0].style.text = maxNum > 100 ? maxNum : 100
+      options.graphic[options.graphic.length - 1].children[1].style.text = 1
+      options.tooltip.formatter = params => {
+        const obj = {}
+        let tip = ''
+        arr.forEach((v) => {
+          if (v['项目所在地'] === params.name) {
+            for (const key in v) {
+              obj[key] = v[key]
+            }
+          }
+        })
+        if (Object.keys(obj).length > 0) {
+          const regArea = '<span style="color: #999">' + obj['项目所在地'] + '</span></br>'
+          const count = '<span>项目数量:' + obj['项目数量'] + '个</span></br>'
+          const scale = '<span>项目金额:' + obj['项目金额'] + '万元</span></br>'
+          tip = regArea + count + scale
+        } else {
+          tip = ''
+        }
+        return tip
+      }
+      options.series[0].aspectScale = 0.75
+      options.series[0].layoutCenter = ['50%', '50%']
+      options.series[0].zoom = 0.8
+      options.series[0].layoutSize = 400
+      return options
+    }
+  }
+}

+ 237 - 0
src/web/staticres/common-module/report-analysis/js/components/marketSegment.js

@@ -0,0 +1,237 @@
+var marketSegmentTemplate = `
+<ve-histogram
+  :id="id"
+  :height="options.height"
+  :width="options.width ? options.width : null"
+  :colors="options.colors"
+  :data="chartData"
+  :settings="options.settings"
+  :after-config="options.config"
+  :after-set-option="extend"
+  :extend="defaultOptions"
+></ve-histogram>
+`
+
+var marketSegment = {
+  name: 'market-segment',
+  template: marketSegmentTemplate,
+  props: {
+    id: String,
+    type: {
+      type: String,
+      default: 'count' // count/amount
+    },
+    chartData: {
+      type: Object,
+      default () {
+        return {
+          columns: ['行业', '项目金额'],
+          rows: [
+            // {
+            //   行业: '6月2',
+            //   项目金额: 2
+            // },
+            // {
+            //   行业: '6月3',
+            //   项目金额: 3
+            // },
+            // {
+            //   行业: '6月4',
+            //   项目金额: 4
+            // },
+            // {
+            //   行业: '6月4',
+            //   项目金额: 0
+            // },
+            // {
+            //   行业: '6月5',
+            //   项目金额: 5
+            // }
+          ]
+        }
+      }
+    },
+  },
+  data: function () {
+    const color = this.type === 'count' ? '#05A6F3' : '#FF9F3F'
+    return {
+      options: {
+        height: '320px',
+        colors: [color],
+        config: this.config(this.type)
+      },
+      defaultOptions: {
+        grid: {
+          top: 20
+        },
+        xAxis: {
+          axisLabel: {
+            margin: 10,
+            interval: 0, // 强制显示x轴所有刻度
+            fontSize: 10
+          },
+          nameLocation: 'start',
+          nameTextStyle: {
+            fontSize: 12,
+            align: 'left',
+            padding: [70, 0, 0, 50],
+            color: '#9B9CA3'
+          }
+        },
+        yAxis (item) {
+          item[0].splitLine = {
+            lineStyle: {
+              type: 'dashed',
+              width: 0.5
+            }
+          }
+          item[0].axisLabel = {
+            margin: 2,
+            fontSize: 12
+          }
+          item[1].splitLine = {
+            show: false
+          }
+          item[1].axisLabel = {
+            show: false,
+            fontSize: 12
+          }
+          item[0].axisLabel.formatter = (value, index) => {
+            return value.toString().replace(/,/, '')
+          }
+          item[1].axisLabel.formatter = (value, index) => {
+            return value.toString().replace(/,/, '')
+          }
+          return item
+        },
+        tooltip: {
+          trigger: 'axis',
+          confine: true,
+          backgroundColor: '#fff',
+          axisPointer: {
+            type: 'shadow',
+            shadowStyle: {
+              color: 'rgba(42, 190, 209,0.1)'
+            },
+            z: 3
+          },
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)'
+        },
+        legend: {
+          orient: 'horizontal',
+          icon: 'circle',
+          bottom: 0,
+          align: 'left',
+          itemWidth: 8,
+          itemHeight: 8,
+          itemGap: 20,
+          textStyle: {
+            fontSize: 12,
+            rich: {
+              a: {
+                fontSize: 16,
+                verticalAlign: 'top',
+                align: 'center',
+                padding: [0, 15, 28, 0]
+              },
+              b: {
+                fontSize: 14,
+                align: 'center',
+                padding: [0, 15, 0, 0],
+                lineHeight: 25
+              }
+            }
+          },
+          formatter: (name) => {
+            if (name === '企业数量') {
+              name = name + '(个)'
+            }
+            return name
+          }
+        }
+      }
+    }
+  },
+  computed: {},
+  created () {
+    // console.log(this.chartData)
+  },
+  methods: {
+    extend (chart) {
+      chart.setOption({
+        series: [{
+          type: 'bar',
+          barMaxWidth: 40
+        }, {
+          type: 'line',
+          smooth: false,
+          symbol: 'none'
+        }]
+      })
+    },
+    config (type) {
+      return options => {
+        const suffix = type === 'count' ? '个' : '万元'
+        options.xAxis[0].axisLabel.rotate = 60
+        options.xAxis[0].axisLabel.formatter = name => {
+          if (name && name.length > 4) {
+            return `${name.slice(0, 4)}...`
+          } else {
+            return name
+          }
+        }
+
+        if (this.chartData.rows.length > 8) {
+          // 设置时间轴
+          Object.assign(options, {
+            // grid解决dataZoom文字被隐藏的问题
+            // https://github.com/apache/echarts/issues/11601
+            grid: {
+              left: '5%',
+              right: '13%'
+            },
+            dataZoom: {
+              show: true, // 显示滚动条
+              realtime: true, // 拖动时,是否实时更新系列的视图
+              type: 'slider',
+              height: 20,
+              bottom: 0,
+              textStyle: {
+                fontSize: 10
+              }
+            }
+          })
+        }
+
+        options.legend.bottom = 30
+        options.legend.formatter = name => {
+          return `${name}(${suffix})`
+        }
+
+        options.legend.data = [
+          { icon: 'rect', name: this.chartData.columns[1] }
+        ]
+
+        options.tooltip.axisPointer.shadowStyle.color = 'rgba(5,166,243,0.1)'
+        options.tooltip.formatter = params => {
+          let tip = `<div style="padding-top:2px;color:#9B9CA3;">${params[0].name}</div>`
+          for (let i = 0; i < params.length; i++) {
+            if (params[i].value === undefined) {
+              params[i].value = 0
+            }
+            if (i === 0) {
+              tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + suffix + '<br/>'
+            }
+          }
+          return tip
+        }
+        return options
+      }
+    }
+  }
+}

+ 241 - 0
src/web/staticres/common-module/report-analysis/js/components/marketTimeScatter.js

@@ -0,0 +1,241 @@
+var marketTimeScatterTemplate = `
+  <div class="market-time-scatter">
+    <ve-histogram
+      id="bar-line-histogram-chart"
+      :init-options="initRendererSvg"
+      :height="options.height"
+      :width="options.width ? options.width : null"
+      :colors="options.colors"
+      :data="chartData"
+      :settings="options.settings"
+      :after-config="options.config"
+      :after-set-option="extend"
+      :extend="defaultOptions"
+      >
+    </ve-histogram>
+  </div>
+`
+
+
+var marketTimeScatter = {
+  name: 'market-time-scatter',
+  template: marketTimeScatterTemplate,
+  props: {
+    chartData: {
+      type: Object,
+      default () {
+        return {
+          columns: ['日期', '项目规模', '环比增长率(%)'],
+          rows: [
+            // {
+            //   日期: '6月',
+            //   项目规模: 0,
+            //   '环比增长率(%)': -33
+            // },
+            // {
+            //   日期: '7月',
+            //   项目规模: 736325,
+            //   '环比增长率(%)': 0
+            // },
+            // {
+            //   日期: '8月',
+            //   项目规模: 73145,
+            //   '环比增长率(%)': 20
+            // }
+          ]
+        }
+      }
+    },
+    width: String,
+    // 柱状图颜色
+    barChartColor: {
+      type: String,
+      default: '#05A6F3'
+    }
+  },
+  data:function () {
+    return {
+      initRendererSvg: {
+        renderer: 'svg'
+      },
+      options: {
+        height: '320px',
+        width: this.width,
+        colors: [this.barChartColor, '#FF3A20'],
+        settings: {
+          showLine: [this.chartData.columns[2]],
+          axisSite: { right: [this.chartData.columns[2]] }
+        },
+        config: this.newTimeConfig
+      },
+      defaultOptions: {
+        grid: {
+          top: 20
+        },
+        xAxis: {
+          axisLabel: {
+            margin: 10,
+            interval: 0, // 强制显示x轴所有刻度
+            fontSize: 10
+          },
+          nameLocation: 'start',
+          nameTextStyle: {
+            fontSize: 12,
+            align: 'left',
+            padding: [70, 0, 0, 50],
+            color: '#9B9CA3'
+          }
+        },
+        yAxis (item) {
+          item[0].splitLine = {
+            lineStyle: {
+              type: 'dashed',
+              width: 0.5
+            }
+          }
+          item[0].axisLabel = {
+            margin: 2,
+            fontSize: 12
+          }
+          item[1].splitLine = {
+            show: false
+          }
+          item[1].axisLabel = {
+            show: false,
+            fontSize: 12
+          }
+          item[0].axisLabel.formatter = (value, index) => {
+            return value.toString().replace(/,/, '')
+          }
+          item[1].axisLabel.formatter = (value, index) => {
+            return value.toString().replace(/,/, '')
+          }
+          return item
+        },
+        tooltip: {
+          trigger: 'axis',
+          confine: true,
+          backgroundColor: '#fff',
+          axisPointer: {
+            type: 'shadow',
+            shadowStyle: {
+              color: 'rgba(42, 190, 209,0.1)'
+            },
+            z: 3
+          },
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)'
+        },
+        legend: {
+          orient: 'horizontal',
+          icon: 'circle',
+          bottom: 0,
+          align: 'left',
+          itemWidth: 8,
+          itemHeight: 8,
+          itemGap: 20,
+          textStyle: {
+            fontSize: 12,
+            rich: {
+              a: {
+                fontSize: 16,
+                verticalAlign: 'top',
+                align: 'center',
+                padding: [0, 15, 28, 0]
+              },
+              b: {
+                fontSize: 14,
+                align: 'center',
+                padding: [0, 15, 0, 0],
+                lineHeight: 25
+              }
+            }
+          },
+          formatter: (name) => {
+            if (name === '企业数量') {
+              name = name + '(个)'
+            }
+            return name
+          }
+        }
+      }
+    }
+  },
+  computed: {},
+  created () {},
+  methods: {
+    extend (chart) {
+      chart.setOption({
+        series: [{
+          type: 'bar',
+          barMaxWidth: 40
+        }, {
+          type: 'line',
+          smooth: false,
+          symbol: 'none'
+        }]
+      })
+    },
+    newTimeConfig (options) {
+      options.xAxis[0].axisLabel.rotate = 60
+      options.xAxis[0].axisLabel.interval = 'auto'
+
+      options.yAxis[1].axisLabel.show = true
+
+      if (this.chartData.rows.length > 8) {
+        // 设置时间轴
+        Object.assign(options, {
+          // grid解决dataZoom文字被隐藏的问题
+          // https://github.com/apache/echarts/issues/11601
+          grid: {
+            left: '5%',
+            right: '13%'
+          },
+          dataZoom: {
+            show: true, // 显示滚动条
+            realtime: true, // 拖动时,是否实时更新系列的视图
+            type: 'slider',
+            height: 20,
+            bottom: 0,
+            textStyle: {
+              fontSize: 10
+            }
+          }
+        })
+      }
+
+      options.legend.bottom = 30
+      options.legend.data = [
+        { icon: 'rect', name: this.chartData.columns[1] },
+        { icon: 'line', name: this.chartData.columns[2] }
+      ]
+
+      options.tooltip.axisPointer.shadowStyle.color = 'rgba(5,166,243,0.1)'
+      options.tooltip.formatter = params => {
+        let tip = '' 
+        for (let i = 0; i < params.length; i++) {
+          if (params[i].value === undefined || params[i].value === '') {
+            params[i].value = 0
+          }
+          if (params[i].seriesName.indexOf('环比') === -1) {
+            var match = params[i].seriesName.match(/((.*))$/g)
+            var unit = ''
+            if (Array.isArray(match)) {
+              unit = match.join('').replace(/[()]/g, '')
+            }
+            tip = tip + params[i].marker + params[i].seriesName.replace(`(${unit})`, '') + ':' + params[i].value + unit + '<br/>'
+          } else {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>'
+          }
+        }
+        tip += `<div style="padding-top:2px;color:#9B9CA3;text-align:center">- ${params[0].name} -</div>`
+        return tip
+      }
+      return options
+    }
+  }
+}

+ 105 - 0
src/web/staticres/common-module/report-analysis/js/components/marketTop3Table.js

@@ -0,0 +1,105 @@
+var marketTop3TableTemplate = `
+  <div class="market-top3-table">
+    <div
+      class="project-top-item"
+      v-for="(item, index) in tableData"
+      :key="index">
+      <div class="p-t-i-hd">
+        <div
+          class="p-t-i-hd-l table-index-rect"
+          v-text="index + 1"
+          :class="{
+              red: index === 0,
+              orange: index === 1,
+              'soft-orange': index === 2
+          }"></div>
+        <div class="p-t-i-hd-r">
+          <div class="p-t-i-hd-r-top">
+            <div class="project-name ellipsis" v-text="item.name" :class="{ disabled: !item.id }" @click="toPortrait(item.id, item.type)"></div>
+            <div class="project-actions" v-show="item.children.length" :class="{ 'icon-reverse': item.childrenShow }" @click="changeChildrenShow(item)">
+              <div v-text="item.actionText"></div>
+              <van-icon name="arrow-down"></van-icon>
+            </div>
+          </div>
+          <div class="project-info">
+            <div class="project-tags">
+              <div class="j-tag" :class="{ 'tag-blue': type === 'count', 'tag-orange': type === 'amount' }" v-text="item.subInfo1" v-if="item.subInfo1"></div>
+              <div class="j-tag tag-plain" v-text="item.subInfo2" v-if="item.subInfo2"></div>
+            </div>
+            <div class="project-right"></div>
+          </div>
+        </div>
+      </div>
+      <div
+        class="p-t-i-ft"
+        :class="{ disabled: !child.id }"
+        v-for="(child, i) in item.children"
+        :key="i"
+        @click="toPortrait(child.id, child.type)"
+        v-show="item.childrenShow">
+        <div class="p-t-i-ft-title" v-text="child.name"></div>
+        <div class="p-t-i-ft-bottom">
+          <div class="p-t-i-ft-sub" v-text="child.subInfo1" v-if="child.subInfo1"></div>
+          <div class="p-t-i-ft-sub" v-text="child.subInfo2" v-if="child.subInfo2"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+`
+
+var marketTop3Table = {
+  name: 'market-top3-table',
+  template: marketTop3TableTemplate,
+  props: {
+    type: {
+      type: String,
+      default: 'count' // count/amount
+    },
+    tableData: {
+      type: Array,
+      default () {
+        return [
+          // {
+          //   name: 'xxxx',
+          //   subInfo1: 'xx',
+          //   subInfo2: 'xxx',
+          //   actionText: 'actionText',
+          //   childrenShow: true,
+          //   children: [
+          //     {
+          //       name: 'w1',
+          //       subInfo1: 'xx',
+          //       subInfo2: 'xx',
+          //     },
+          //     {
+          //       name: 'w2',
+          //       subInfo1: 'xx',
+          //       subInfo2: 'xx',
+          //     }
+          //   ]
+          // }
+        ]
+      }
+    },
+  },
+  data:function () {
+    return {}
+  },
+  computed: {},
+  created () {},
+  methods: {
+    toPortrait (id, type) {
+      console.log(...arguments)
+      if (!type || !id) return
+      this.$emit('save')
+      if (type === 'winner') {
+        location.href = `./ent_portrait?eId=${id}`
+      } else if (type === 'buyer') {
+        location.href = `./unit_portrayal?entName=${id}`
+      }
+    },
+    changeChildrenShow (item) {
+      item.childrenShow = !item.childrenShow
+    }
+  }
+}

+ 161 - 0
src/web/staticres/common-module/report-analysis/js/components/marketUserScatter.js

@@ -0,0 +1,161 @@
+var marketUserScatterTemplate = `<div class="rect-tree-map-chart" style="width: 100%;min-height: 400px"></div>`
+
+var marketUserScatter = {
+  name: 'market-user-scatter',
+  template: marketUserScatterTemplate,
+  props: {
+    chartData: {
+      type: Array,
+      default () {
+        return [
+          // {
+          //   name: 'a',
+          //   value: 222,
+          //   amount: '22'
+          // },
+          // {
+          //   name: 'b',
+          //   value: 122,
+          //   amount: '22'
+          // },
+          // {
+          //   name: 'b',
+          //   value: 22,
+          //   amount: '22'
+          // },
+          // {
+          //   name: 'd',
+          //   value: 2,
+          //   amount: '22'
+          // },
+        ]
+      }
+    },
+  },
+  data:function () {
+    return {
+      myChart: null,
+      height: '500px',
+      options: {
+        title: {
+          subtext: '单位:个、万元',
+          left: '0',
+          textStyle: {
+            color: '#000',
+            fontWeight: 'normal'
+          }
+        },
+        tooltip: {
+          formatter: this.tooltipFormatter
+        }
+      },
+      defaultOptions: {
+        legend: {
+          show: true,
+          selectedMode: 'single',
+          data: [],
+          bottom: 0,
+          itemGap: 5
+        },
+        tooltip: {
+          backgroundColor: '#fff',
+          confine: true,
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+          borderWidth: 2,
+          borderColor: '#F5F6F7'
+        },
+        series: [
+          {
+            type: 'treemap',
+            width: '100%',
+            // height: '85%',
+            // top: '15%',
+            roam: false, // 是否开启拖拽漫游(移动和缩放)
+            nodeClick: false, // 点击节点后的行为,false无反应
+            breadcrumb: {
+              show: false
+            },
+            label: { // 描述了每个矩形中,文本标签的样式。
+              normal: {
+                show: true,
+                position: ['10%', '40%']
+              }
+            },
+            itemStyle: {
+              normal: {
+                show: true,
+                textStyle: {
+                  color: '#fff',
+                  fontSize: 16
+                },
+                borderWidth: 1,
+                borderColor: '#fff'
+              },
+              emphasis: {
+                label: {
+                  show: true
+                }
+              }
+            },
+            data: [
+              // {
+              //   name: 'xxx',
+              //   value: 122
+              // },
+              // {
+              //   name: 'yyy',
+              //   value: 122
+              // }
+            ]
+          }
+        ]
+      }
+    }
+  },
+  computed: {},
+  mounted () {
+    this.updateChartView()
+  },
+  methods: {
+    updateChartView () {
+      this.myChart = echarts.init(this.$el, 'light', { renderer: 'canvas' })
+      if (!this.myChart) return
+      this.mergeOptions()
+      this.myChart.setOption(this.defaultOptions)
+      window.addEventListener('resize', () => {
+        // this.myChart.resize()
+      })
+    },
+    mergeOptions () {
+      // 设置数据
+      this.defaultOptions.series[0].data = this.chartData
+      // 设置图例?
+      this.defaultOptions.legend.data = this.chartData.map(item => {
+        return item.name
+      })
+
+      _.merge(this.defaultOptions, this.options)
+    },
+    tooltipFormatter (params) {
+      const item = params.data
+      let tip = `<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:${params.color};"></span>${params.name}<br />`
+      if (item && item.value) {
+        tip += `<div>项目数量:${item.value}个<div>`
+      }
+      if (item && item.amount) {
+        tip += `<div>项目金额:${item.amount}万元<div>`
+      }
+      return tip
+    }
+  },
+  beforeDestroy () {
+    if (this.myChart) {
+      this.myChart.dispose()
+    }
+  }
+}

+ 198 - 0
src/web/staticres/common-module/report-analysis/js/components/projectScatter.js

@@ -0,0 +1,198 @@
+var projectScatterTemplate = `
+  <div class="project-scatter-chart" v-if="chartData.rows.length">
+    <ve-histogram
+      id="simple-histogram-chart"
+      :init-options="initRendererSvg"
+      :colors="options.colors"
+      :width="options.width"
+      :height="options.height"
+      :data="chartData"
+      :settings="options.settings"
+      :after-config="options.config"
+      :after-set-option="extend"
+      :extend="defaultOptions"
+      >
+    </ve-histogram>
+  </div>
+`
+
+
+var projectScatter = {
+  name: 'project-scatter',
+  template: projectScatterTemplate,
+  props: {
+    chartData: {
+      type: Object,
+      default () {
+        return {
+          columns: ['项目规模', '项目总金额占比', '项目总数占比'],
+          rows: [
+            // {
+            //   项目规模: '≥1亿',
+            //   项目总金额占比: 20,
+            //   项目总数占比: 10
+            // },
+            // {
+            //   项目规模: '1000万-1亿',
+            //   项目总金额占比: 50,
+            //   项目总数占比: 40
+            // },
+            // {
+            //   项目规模: '500万-1000万',
+            //   项目总金额占比: 20,
+            //   项目总数占比: 30
+            // },
+            // {
+            //   项目规模: '100万-500万',
+            //   项目总金额占比: 20,
+            //   项目总数占比: 30
+            // }
+          ]
+        }
+      }
+    },
+  },
+  data:function () {
+    return {
+      initRendererSvg: {
+        renderer: 'svg'
+      },
+      options: {
+        colors: ['#FF9F3F', '#05A5F2'],
+        width: '100%',
+        height: '300px',
+        settings: {}
+      },
+      defaultOptions: {
+        grid: {
+          top: 20
+        },
+        xAxis: {
+          axisLabel: {
+            margin: 10,
+            interval: 0, // 强制显示x轴所有刻度
+            fontSize: 10,
+            formatter: this.xAxisFormatter
+          },
+          nameLocation: 'start',
+          nameTextStyle: {
+            fontSize: 12,
+            align: 'left',
+            padding: [70, 0, 0, 50],
+            color: '#9B9CA3'
+          }
+        },
+        yAxis (item) {
+          Object.assign(item[0], {
+            splitLine: {
+              lineStyle: {
+                type: 'dashed',
+                width: 0.5
+              }
+            },
+            axisLabel: {
+              margin: 2,
+              fontSize: 12,
+              formatter: (value, index) => value.toString().replace(/,/, '') + '%'
+            }
+          })
+
+          Object.assign(item[1], {
+            splitLine: {
+              show: false
+            },
+            axisLabel: {
+              show: false,
+              fontSize: 12,
+              formatter: (value, index) => value.toString().replace(/,/, '')
+            }
+          })
+          return item
+        },
+        tooltip: {
+          trigger: 'axis',
+          confine: true,
+          backgroundColor: '#fff',
+          axisPointer: {
+            type: 'shadow',
+            shadowStyle: {
+              color: 'rgba(42, 190, 209,0.1)'
+            },
+            z: 3
+          },
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)',
+          formatter: this.tooltipFormatter
+        },
+        legend: {
+          orient: 'horizontal',
+          icon: 'rect',
+          bottom: 20,
+          align: 'left',
+          itemGap: 20,
+          textStyle: {
+            fontSize: 12,
+            rich: {
+              a: {
+                fontSize: 16,
+                verticalAlign: 'top',
+                align: 'center',
+                padding: [0, 15, 28, 0]
+              },
+              b: {
+                fontSize: 14,
+                align: 'center',
+                padding: [0, 15, 0, 0],
+                lineHeight: 25
+              }
+            }
+          },
+          formatter: name => name
+        }
+      }
+    }
+  },
+  computed: {},
+  created () {},
+  methods: {
+    extend (chart) {
+      chart.setOption({
+        series: [
+          {
+            type: 'bar'
+          },
+          {
+            type: 'bar'
+          }
+        ]
+      })
+    },
+    tooltipFormatter (params) {
+      let tip = ''
+      for (let i = 0; i < params.length; i++) {
+        if (params[i].value === undefined || params[i].value === '') {
+          params[i].value = 0
+        }
+        if (i === 0) {
+          tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%<br/>'
+        } else if (i === 1) {
+          tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%<br/>'
+        }
+      }
+      tip +=`<div style="padding-top:2px;color:#9B9CA3;text-align:center">- ${params[0].name} -</div>`
+      return tip
+    },
+    xAxisFormatter (params) {
+      var arr = params.split('-')
+      if (arr.length === 2) {
+        return arr.join('\n-')
+      } else {
+        return params
+      }
+    }
+  }
+}

+ 1006 - 0
src/web/staticres/common-module/report-analysis/js/echarts_option.js

@@ -0,0 +1,1006 @@
+// 中国地图配置项
+function completionMapName (name) {
+  return name
+  // const beforeMaps = {
+  //   '新疆': '新疆维吾尔自治区',
+  //   '西藏': '西藏自治区',
+  //   '宁夏': '宁夏回族自治区',
+  //   '广西': '广西壮族自治区',
+  //   '内蒙古': '内蒙古自治区',
+  //   '香港': '香港特别行政区',
+  //   '澳门': '澳门特别行政区',
+  //   '重庆': '重庆市',
+  //   '上海': '上海市',
+  //   '天津': '天津市',
+  //   '北京': '北京市'
+  // }
+  // if (beforeMaps[name]) {
+  //   return beforeMaps[name]
+  // } else {
+  //   return name
+  // }
+}
+
+var mapSettings = {
+    completionMapName: completionMapName,
+    chartSettings:{
+        positionJsonLink: "/jyapp/big-member/js/china-n.json?v=908",
+        beforeRegisterMapOnce (map) {
+            return map
+        },
+        beforeRegisterMap (map) {
+            return map
+        },
+        label:{
+            show:true,
+            fontSize:7
+        },
+        selectedMode:false, // 去掉省份小圆点
+        itemStyle:{
+            normal:{
+                borderColor:'#F06326',
+                areaColor: '#FFFFFF'
+            }
+        },
+        // zoom:0.95, // 缩放比例
+    },
+    chartExtend: {
+        tooltip: {
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+                type: 'shadow',        // 默认为直线,可选为:'line' | 'shadow'
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                },
+                z: 3
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[8,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter:function(params,ticket, callback){
+                if(params.data == null){
+                    return params.name+':0'
+                }else{
+                    return params.name+':'+ params.value
+                }
+            }
+        },
+        grid:{
+            height: '280px',
+            containLabel: true
+        },
+        legend:{ // 隐藏图标上方小方块及文字
+            selectedMode: false,
+            textStyle:{
+                color:'transparent'
+            },
+            itemWidth:0,
+            itemHeight:0,
+        },
+        silent:false, // 禁用鼠标点击、滑过事件
+        series: {
+            showLegendSymbol:false,
+            selectedMode:false,
+        },
+        graphic:[
+            {
+                type:'group',
+                bottom: 54,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'市场分布数量',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            },
+            {
+                type: 'rect',
+                z: 101,
+                left: 0,
+                bottom: 34,
+                shape: {
+                    width: 84,
+                    height: 14
+                },
+                style: {
+                    stroke: '#FB483D',
+                    fill: 'transparent',
+                    lineWidth: 0.5
+                }
+            },
+            rectGroup(0,'#F06326'),
+            rectGroup(14,'#F48A5D'),
+            rectGroup(28,'#FFB366'),
+            rectGroup(42,'#FFCF9F'),
+            rectGroup(56,'#FFE7CF'),
+            rectGroup(70,'#FFF4EB'),
+            {
+                type:'group',
+                width: 84,
+                bottom: 20,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'100',
+                        font: '10px Microsoft YaHei'
+                    }
+                },
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'right',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'0',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            }
+        ],
+        visualMap: {
+            show:false,
+            inRange:{                             //定义 在选中范围中 的视觉元素
+                color: ['#FFF4EB','#FFE7CF', '#FFCF9F','#FFB366','#F48A5D', '#F06326'],
+            },
+            outOfRange:{
+                color: ['#F06326'],
+            },
+        },
+    },
+    chart: null
+}
+// 月报本月项目规模分布
+var mapSettings2 = {
+    completionMapName: completionMapName,
+    chartSettings:{
+        positionJsonLink: "/jyapp/big-member/js/china-n.json?v=908",
+        beforeRegisterMapOnce (map) {
+            return map
+        },
+        beforeRegisterMap (map) {
+            return map
+        },
+        label:{
+            show:true,
+            fontSize:7
+        },
+        selectedMode:false,
+        itemStyle:{
+            normal:{
+                borderColor:'#F06326',
+                areaColor: '#FFFFFF'
+            }
+        },
+    },
+    chartExtend: {
+        tooltip: {
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                },
+                z: 3
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[8,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter:function(params,ticket, callback){
+                if(params.data == null){
+                    return params.name + ':0'
+                }else{
+                    return params.name + ':'+ params.value
+                }
+            }
+        },
+        grid:{
+            height: '280px',
+            containLabel: true
+        },
+        legend:{
+            selectedMode: false,
+            textStyle:{
+                color:'transparent'
+            },
+            itemWidth:0,
+            itemHeight:0,
+        },
+        silent:false,
+        series: {
+            showLegendSymbol:false,
+            selectedMode:false,
+        },
+        graphic:[
+            {
+                type:'group',
+                bottom: 54,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'单位:万元',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            },
+            {
+                type: 'rect',
+                z: 101,
+                left: 0,
+                bottom: 34,
+                shape: {
+                    width: 84,
+                    height: 14
+                },
+                style: {
+                    stroke: '#FB483D',
+                    fill: 'transparent',
+                    lineWidth: 0.5
+                }
+            },
+            rectGroup(0,'#F06326'),
+            rectGroup(14,'#F48A5D'),
+            rectGroup(28,'#FFB366'),
+            rectGroup(42,'#FFCF9F'),
+            rectGroup(56,'#FFE7CF'),
+            rectGroup(70,'#FFF4EB'),
+            {
+                type:'group',
+                width: 84,
+                bottom: 20,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'100',
+                        font: '10px Microsoft YaHei'
+                    }
+                },
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'right',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'0',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            }
+        ],
+        visualMap: {
+            show:false,
+            inRange:{
+                color: ['#FFF4EB','#FFE7CF', '#FFCF9F','#FFB366','#F48A5D', '#F06326'],
+            },
+            outOfRange:{
+                color: ['#F06326'],
+            },
+        },
+    },
+    chart: null
+}
+// 月报本月中标企业注册地分布
+var mapSettings3 = {
+    completionMapName: completionMapName,
+    chartSettings:{
+        positionJsonLink: "/jyapp/big-member/js/china-n.json?v=908",
+        beforeRegisterMapOnce (map) {
+            return map
+        },
+        beforeRegisterMap (map) {
+            return map
+        },
+        label:{
+            show:true,
+            fontSize:7
+        },
+        selectedMode:false,
+        itemStyle:{
+            normal:{
+                borderColor:'#F06326',
+                areaColor: '#FFFFFF'
+            }
+        },
+    },
+    chartExtend: {
+        tooltip: {
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                },
+                z: 3
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[8,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter:function(params,ticket, callback){
+                if(params.data == null){
+                    return params.name + ':0'
+                }else{
+                    return params.name + ':'+ params.value
+                }
+            }
+        },
+        grid:{
+            height: '280px',
+            containLabel: true
+        },
+        legend:{
+            selectedMode: false,
+            textStyle:{
+                color:'transparent'
+            },
+            itemWidth:0,
+            itemHeight:0,
+        },
+        silent:false,
+        series: {
+            showLegendSymbol:false,
+            selectedMode:false,
+        },
+        graphic:[
+            {
+                type:'group',
+                bottom: 54,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'单位:个',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            },
+            {
+                type: 'rect',
+                z: 101,
+                left: 0,
+                bottom: 34,
+                shape: {
+                    width: 84,
+                    height: 14
+                },
+                style: {
+                    stroke: '#FB483D',
+                    fill: 'transparent',
+                    lineWidth: 0.5
+                }
+            },
+            rectGroup(0,'#F06326'),
+            rectGroup(14,'#F48A5D'),
+            rectGroup(28,'#FFB366'),
+            rectGroup(42,'#FFCF9F'),
+            rectGroup(56,'#FFE7CF'),
+            rectGroup(70,'#FFF4EB'),
+            {
+                type:'group',
+                width: 84,
+                bottom: 20,
+                children:[
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'left',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'100',
+                        font: '10px Microsoft YaHei'
+                    }
+                },
+                {
+                    type: 'text',
+                    z: 100,
+                    left: 'right',
+                    top: 'middle',
+                    style: {
+                        fill: '#333',
+                        text:'0',
+                        font: '10px Microsoft YaHei'
+                    }
+                }]
+            }
+        ],
+        visualMap: {
+            show:false,
+            inRange:{
+                color: ['#FFF4EB','#FFE7CF', '#FFCF9F','#FFB366','#F48A5D', '#F06326'],
+            },
+            outOfRange:{
+                color: ['#F06326'],
+            },
+        },
+    },
+    chart: null
+}
+// 中国地图例graphic配置函数
+function rectGroup(left,color) {
+    return {
+        type: 'rect',
+        z: 100,
+        left: left,
+        bottom: 34,
+        shape: {
+            width: 14,
+            height: 14
+        },
+        style: {
+            fill: color
+        }
+    }
+}
+//  投标决策分析页面:预算分布、中标金额、折扣率分布三个图表配置项(只配置相同部分,不同部分在页面里单独配置)
+var barChart = {
+    chartSettings: {},
+    chartExtend:{
+        grid:{
+            left:4,
+            x:0,
+            y:20,
+            x2:0,
+            bottom:20
+        },
+        xAxis:{
+            axisLabel:{
+                interval: 0, // 强制显示x轴所有刻度
+                fontSize: 10
+            }
+        },
+        yAxis(item){
+            item[0].splitLine = {
+                lineStyle:{
+                    type: 'dashed',  // y轴背景虚线
+                    width: 0.5
+                }
+            }
+            item[0].axisLabel = {
+                margin:2,
+                fontSize: 10
+            }
+            item[1].splitLine = {
+                show:false
+            }
+            item[1].axisLabel = {
+                show:false,
+                fontSize: 10
+            }
+            return item;
+        },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle: {},
+                z: 3
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[7,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)',
+            formatter:function(params){
+                //移除重复的数据
+                for (var i = 0; i < params.length; i++) {
+                    for (var j = params.length - 1; j > i; j--) {
+                        if (params[j].data == params[i].data) {
+                            params.splice(j, 1);
+                            break;
+                        }
+                    }
+                }
+                var tip = '';
+                for (var i = 0; i < params.length; i++) {
+                    if( i == 0) {
+                        tip = params[i].value == 0 ? '' : tip + params[i].seriesName + ':' + params[i].value + '个' + '<br/>';
+                    }else if(i == 1){
+                        if (params[i].value != 0 || params[i].value != '0.00') {
+                            if (params[i].seriesName === '平均折扣率') {
+                                tip = tip + params[i].seriesName + ':' + params[i].value + '%' + '<br/>';
+                            } else {
+                                tip = tip + params[i].seriesName + ':' + params[i].value + '万元' + '<br/>';
+                            }
+                        } else {
+                            tip = tip
+                        }
+
+                    }
+                }
+                return tip;
+            }
+        },
+        legend: {
+            show:false,
+            orient: 'horizontal',
+            icon:'circle',
+            bottom:20,
+            align:'left',
+            itemWidth: 8,
+            itemHeight: 8,
+            itemGap:20,
+            textStyle:{
+                fontSize:11,
+                rich:{
+                    a:{
+                        fontSize:16,
+                        verticalAlign:'top',
+                        align:'center',
+                        padding:[0,15,28,0]
+                    },
+                    b:{
+                        fontSize:14,
+                        align:'center',
+                        padding:[0,15,0,0],
+                        lineHeight:25
+                    }
+                }
+            },
+            formatter: function (name) {
+                var wnYuan = ['金额', '项目金额', '项目规划', '项目总预算', '项目总规模']
+                var ge = ['数量', '项目数量']
+                if (wnYuan.indexOf(name) !== -1) {
+                    name += '(万元)'
+                } else if (ge.indexOf(name) !== -1) {
+                    name += '(个)'
+                }
+                return name;
+            },
+        },
+        series: {
+            barWidth: 20,
+            smooth:false,
+            symbol:'none',
+            lineStyle: {
+                width: 0,
+                color: 'rgba(0, 0, 0, 0)' // 线的颜色是透明的
+            },
+        },
+
+    },
+}
+
+// 平均折扣率配置
+var multiBarChart = {
+    chartSettings: {
+        showLine: ['平均折扣率'],
+    },
+    chartExtend:{
+        grid:{
+            x:12,
+            y:20,
+            x2:12,
+        },
+        yAxis: {
+            splitLine: {
+                show: true,
+                lineStyle: {
+                    type: 'dashed',  // y轴背景虚线
+                    width: 0.5
+                }
+            },
+            axisLabel:{
+                fontSize:10
+            },
+        },
+        xAxis: {
+            axisLabel:{
+                fontSize:10
+            }
+        },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                }
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding: [8,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter: function(params){
+                var tip = '';
+                for (var i = 0; i < params.length; i++) {
+                    if( i< 4) {
+                        tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '<br/>';
+                    }else {
+                        tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>';
+                    }
+                }
+                tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name.substring(0,params[0].name.lastIndexOf('年')) + ' - ' + '</div>'
+                return tip;
+            },
+        },
+        legend: {
+            orient: 'horizontal',
+            bottom:20,
+            icon:'circle',
+            itemWidth: 8,
+            itemHeight: 8,
+            padding:[0,6],
+            data:['日期', '0~5%', '5~10%','10~30%','30~100%','平均折扣率'],
+            textStyle:{
+                fontSize:11
+            }
+        },
+        series: {
+            smooth:false,
+        },
+        color:['#05A6F3','#0BD991','#FF9F40','#8E6DF2','#F1D090']
+    },
+}
+
+var mBarChart = {
+    dataEmpty: true,
+    chartSettings: {},
+    chartExtend:{
+        grid:{
+            x:14,
+            y:20,
+            x2:14
+        },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                }
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[8,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            z: 3
+        },
+        legend: {
+            orient: 'horizontal',
+            icon:'circle',
+            bottom:10,
+            left: 'center',
+            itemWidth: 8,
+            itemHeight: 8,
+            itemGap:10,
+            textStyle:{
+                fontSize:11
+            }
+        },
+        yAxis: {
+            splitLine: {
+                show: true,
+                lineStyle: {
+                    type: 'dashed',
+                    width: 0.5,
+                    color:'rgba(0, 0, 0, 0.08)'
+                }
+            },
+            axisLabel:{
+                fontSize:10
+            },
+        },
+        xAxis: {
+            axisLabel:{
+                fontSize:10
+            }
+        },
+        series: {
+            barWidth: 20,
+            type:'bar'
+        },
+        color:['#9C72F4','#6B78E8','#05A6F3','#2ABED1','#0BD991','#C0C4CC','#B8D4F9','#444A7A','#F1D090','#B8D4F9','#C09BFC','#104EA3','#21CED2','#FFB901','#7BBFE5','#82E9D6','#62B8FF','#7E56EE','#B3E3E7','#8591FF','#96C3D8','#3774E8','#CDCEFE','#6BBEF4','#6E55B4','#2B82FE','#FF9A01','#01C290','#BAE1A8','#EB97D8']
+    },
+}
+
+
+// 月报 (本月项目规模)
+var barChart2 = {
+    chartExtend:{
+        grid:{
+            left:4,
+            x:0,
+            y:20,
+            x2:12,
+        },
+        xAxis: {
+            axisLabel:{
+                fontSize:10
+            }
+        },
+        yAxis(item){
+            var maxCountList = vNode.data.curMonthScaleData.rows.map(v =>{
+                return v['项目规模']
+            })
+            var maxPriceList = vNode.data.curMonthScaleData.rows.map(v =>{
+                return v['环比增长率(%)-右纵轴']
+            })
+            var maxCount = Math.ceil(Math.max.apply(null,maxCountList)).toString();
+            var maxPrice = Math.ceil(Math.max.apply(null,maxPriceList)).toString();
+            var minRight = Math.ceil(Math.min.apply(null,maxPriceList)).toString();
+            maxCount = Math.ceil(maxCount / (Math.pow(10,maxCount.length -1))) * Math.pow(10,maxCount.length -1);
+            maxPrice = Math.ceil(maxPrice / (Math.pow(10,maxPrice.length -1))) * Math.pow(10,maxPrice.length -1);
+            if(minRight.indexOf('-') > -1) {
+                minRight = '-'  + Math.ceil(minRight.replace('-','') / (Math.pow(10,minRight.replace('-','').length -1))) * Math.pow(10,minRight.replace('-','').length -1)
+            } else {
+                minRight = 0;
+            }
+            item[0].min = 0;
+            item[1].min = minRight;
+            item[0].max = maxCount;
+            item[0].interval = Math.ceil(maxCount / 5);
+            item[1].max = maxPrice;
+            item[1].interval = Math.ceil((maxPrice - minRight) / 5);
+            item[0].splitLine = {
+                lineStyle:{
+                    type: 'dashed',
+                    width: 0.5
+                }
+            }
+            item[1].splitLine = {
+                show:false,
+                lineStyle:{
+                    type: 'dashed',
+                    width: 0.5
+                }
+            },
+            item[1].axisLabel = {
+                show: true,
+                fontSize: 10
+            },
+            item[0].axisLabel = {
+                margin:2,
+                fontSize: 10,
+                formatter: function(value, index){
+                    return value.toString().replace(/,/,'');
+                }
+            }
+            return item;
+        },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                }
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[7,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter:function(params){
+                return formatterTip(params)
+            }
+        },
+        legend: {
+            show: true,
+            orient: 'horizontal',
+            icon:'circle',
+            bottom:20,
+            align:'left',
+            itemWidth: 8,
+            itemHeight: 8,
+            itemGap:20,
+            textStyle:{
+                fontSize:11,
+                rich:{
+                    a:{
+                        fontSize:16,
+                        verticalAlign:'top',
+                        align:'center',
+                        padding:[0,15,28,0]
+                    },
+                    b:{
+                        fontSize:14,
+                        align:'center',
+                        padding:[0,15,0,0],
+                        lineHeight:25
+                    }
+                }
+            },
+            formatter: function (name) {
+                if(name == '项目规模') {
+                    name = name + '(万元)'
+                }
+                return name;
+            },
+            data:["项目规模","环比增长率(%)-右纵轴"],
+        },
+        series: {
+            barWidth: 20,
+            smooth:false,
+        },
+        color:['#05A6F3', '#FF9F40']
+    },
+}
+// 月报 (本月中标企业中标项目数量分布)
+var barChart3 = {
+    chartExtend:{
+        grid:{
+            x:8,
+            y:20,
+            x2:12,
+        },
+        xAxis: {
+            axisLabel: {
+                fontSize: 10,
+                formatter: function (val) {
+                    return val + '个';
+                }
+            }
+        },
+        yAxis(item){
+            var maxCountList = vNode.data.curWinEntCountData.rows.map(v =>{
+                return v['企业数量']
+            })
+            var maxPriceList = vNode.data.curWinEntCountData.rows.map(v =>{
+                return v['累计占比(%)-右纵轴']
+            })
+            var maxCount = Math.ceil(Math.max.apply(null,maxCountList)).toString();
+            var maxPrice = Math.ceil(Math.max.apply(null,maxPriceList)).toString();
+            maxCount = Math.ceil(maxCount / (Math.pow(10,maxCount.length -1))) * Math.pow(10,maxCount.length -1);
+            maxPrice = Math.ceil(maxPrice / (Math.pow(10,maxPrice.length -1))) * Math.pow(10,maxPrice.length -1);
+            item[0].min = 0;
+            item[1].min = 0;
+            item[0].max = maxCount;
+            item[0].interval = Math.ceil(maxCount / 5);
+            item[1].max = maxPrice;
+            item[1].interval = Math.ceil((maxPrice - 0) / 5);
+            item[0].splitLine = {
+                lineStyle:{
+                    type: 'dashed',
+                    width: 0.5
+                }
+            }
+            item[1].splitLine = {
+                show:false,
+                lineStyle:{
+                    type: 'dashed',
+                    width: 0.5
+                }
+            },
+            item[1].axisLabel = {
+                show: true,
+                fontSize: 10
+            },
+            item[0].axisLabel = {
+                margin:2,
+                fontSize: 10,
+                formatter: function(value, index){
+                    return value.toString().replace(/,/,'');
+                }
+            }
+            return item;
+        },
+        tooltip: {
+            trigger: 'axis',
+            confine: true,
+            backgroundColor:'#fff',
+            axisPointer: {
+                type: 'shadow',
+                shadowStyle:{
+                    color:'rgba(5,166,243,0.1)'
+                }
+            },
+            textStyle:{
+                color:'#171826',
+                fontSize:12
+            },
+            padding:[7,12],
+            extraCssText:'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+            formatter:function(params){
+                return formatterTip(params)
+            }
+        },
+        legend: {
+            show: true,
+            orient: 'horizontal',
+            icon:'circle',
+            bottom:20,
+            align:'left',
+            itemWidth: 8,
+            itemHeight: 8,
+            itemGap:20,
+            textStyle:{
+                fontSize:11,
+                rich:{
+                    a:{
+                        fontSize:16,
+                        verticalAlign:'top',
+                        align:'center',
+                        padding:[0,15,28,0]
+                    },
+                    b:{
+                        fontSize:14,
+                        align:'center',
+                        padding:[0,15,0,0],
+                        lineHeight:25
+                    }
+                }
+            },
+            formatter: function (name) {
+                if(name == '企业数量') {
+                    name = name + '(个)'
+                }
+                return name;
+            },
+            data:["企业数量","累计占比(%)-右纵轴"],
+        },
+        series: {
+            barWidth: 20,
+            smooth:false
+        },
+        color:['#05A6F3', '#FF9F40']
+    },
+}
+// 修改tooltip展示效果函数
+function formatterTip(params) {
+    var tip = '';
+    for (var i = 0; i < params.length; i++) {//这里是自己定义样式, params[i].marker 表示是否显示左边的那个小圆圈
+        params[i].value == undefined ? params[i].value = 0 : params[i].value;
+        params[i].marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' +  params[i].color + '"></span>';
+        if( params[i].seriesName === '项目数量' || params[i].seriesName === '企业数量') {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '个' + '<br/>';
+        }else if(params[i].seriesName === '环比增长率(%)-右纵轴' || params[i].seriesName === '累计占比(%)-右纵轴'){
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>';
+        } else {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '万元' + '<br/>';
+        }
+    }
+    tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name + ' - ' + '</div>'
+    return tip;
+}

+ 1831 - 0
src/web/staticres/common-module/report-analysis/js/report_analysis.js

@@ -0,0 +1,1831 @@
+function dateFormatter (date, pattern) {
+  return new Date(date).pattern(pattern)
+}
+var vm = new Vue({
+  delimiters: ['${', '}'],
+  el: '#analysis',
+  components: {
+    keywordComponent: keywordComponent,
+    areaCityMobile: areaCityMobileComponent,
+    industryComponent: industryComponent,
+    cateComponent: cateComponent,
+    dateComponent: dateComponent,
+    chartExample: chartExample,
+    // 图表
+    projectScatter: projectScatter,
+    marketTimeScatter: marketTimeScatter,
+    marketAreaScatter: marketAreaScatter,
+    marketTop3Table: marketTop3Table,
+    marketUserScatter: marketUserScatter,
+    marketSegment: marketSegment,
+    lineChartScatter: lineChartScatter,
+  },
+  data: {
+    sessStorageKey: '$data-report_analysis',
+    tabActiveName: 'analysis', // analysis/history
+    tabList: [
+      {
+        label: '定制化市场分析',
+        name: 'analysis'
+      },
+      {
+        label: '历史报告',
+        name: 'history'
+      }
+    ],
+    tabConf: {
+      titleActiveColor: '#2ABED1',
+      titleInactiveColor: '#5F5E64',
+      lineWidth: '24',
+      color: '#2ABED1'
+    },
+    timeOptions: [
+      {
+        name: '近3个月',
+        value: 'lately90',
+        selected: false
+      },
+      {
+        name: '近半年',
+        value: 'lately180',
+        selected: false
+      },
+      {
+        name: '今年全年',
+        value: 'thisYear',
+        selected: false
+      },
+      {
+        name: '去年至今',
+        value: 'sinceLastYear',
+        selected: false
+      },
+      {
+        name: '前年至今',
+        value: 'sinceYearBeforeLast',
+        selected: false
+      }
+    ],
+    scrollTop: 0,
+    filtersPageShow: true,
+    filters: {
+      selectKeysArr: [], // 关键词简单数组,用于恢复选择状态
+      keys: [], // 关键词详细数组,用于提交数据
+      area: {},
+      industry: [],
+      industryDetail: {},
+      buyerclass: [],
+      rangeTime: {
+        start: '',
+        end: '',
+        exact: 'sinceYearBeforeLast',
+      },
+    },
+    filterDialogShow: {
+      keys: false,
+      area: false,
+      industry: false,
+      buyerclass: false,
+      rangeTime: false
+    },
+    // 分析结果页面数据
+    activeDimension: 'market',
+    dimensionList: [
+      {
+        id: 'market',
+        name: '市场规模',
+        top: 0,
+        anchor: 'market-overview'
+      },
+      {
+        id: 'buyer',
+        name: '采购单位',
+        top: 0,
+        anchor: 'buyerclass-scatter'
+      },
+      {
+        id: 'bidder',
+        name: '中标单位',
+        top: 0,
+        anchor: 'winner-scatter'
+      },
+    ],
+    analysis: { // 开始分析请求的loaed和loading
+      loaded: false,
+      loading: false
+    },
+    rid: '', // reportId
+    reportFilters: {
+      keys: [],
+      selectTime: '',
+      selectTimeExtra: '',
+      area: {},
+      industry: {},
+      buyerclass: []
+    },
+    sections: {
+      market: {
+        overview: [],
+        refine: {
+          dataAlready: false,
+          projectCountData: null,
+          projectAmountData: null,
+          // 项目数量Top3
+          projectCountTop3: null,
+          // 项目金额Top3
+          projectAmountTop3: null
+        }
+      },
+      projectScatter: {
+        dataAlready: false,
+        chartData: null,
+        tableData: [
+          // {
+          //   projectname: 'xxxx',
+          //   area: 'xx',
+          //   city: 'xxx',
+          //   sortprice: 'zzz',
+          //   jgtime: 'zzzz',
+          //   winner_s: [
+          //     {
+          //       name: 'w1',
+          //       id: '33'
+          //     },
+          //     {
+          //       name: 'w2',
+          //       id: '33'
+          //     }
+          //   ]
+          // },
+          // {
+          //   projectname: 'xxxx',
+          //   area: 'xx',
+          //   city: 'xxx',
+          //   sortprice: 'zzz',
+          //   jgtime: 'zzzz',
+          //   winner_s: [
+          //     {
+          //       name: 'w1',
+          //       id: '33'
+          //     },
+          //     {
+          //       name: 'w2',
+          //       id: '33'
+          //     }
+          //   ]
+          // }
+        ]
+      },
+      timeScatter: {
+        dataAlready: false, // 数据准备好之后才能开始渲染
+        activeAction: 'month',
+        actionList: [
+          {
+            label: '月度数据',
+            value: 'month'
+          },
+          {
+            label: '年度数据',
+            value: 'year'
+          }
+        ],
+        month: {
+          count: {},
+          amount: {}
+        },
+        year: {
+          count: {},
+          amount: {}
+        }
+      },
+      areaScatter: {
+        dataAlready: false,
+        chartData: null,
+        // 项目数量Top3
+        projectCountTop3: null,
+        // 项目金额Top3
+        projectAmountTop3: null
+      },
+      userScatter: {
+        list: [],
+        // 项目数量Top3
+        projectCountTop3: null,
+        // 项目金额Top3
+        projectAmountTop3: null
+      },
+      buyerclass: {
+        dataAlready: false,
+        chartData: null,
+        // 项目数量Top3
+        projectCountTop3: null,
+        // 项目金额Top3
+        projectAmountTop3: null
+      },
+      winner: {
+        dataAlready: false,
+        chartData: null,
+        // 项目数量Top3
+        projectCountTop3: null,
+        // 项目金额Top3
+        projectAmountTop3: null
+      }
+    },
+    empty: {
+      defaultMsg: '对不起,没有匹配到相关信息<br />请修改您的分析条件',
+      msg: ''
+    },
+    stickyOffset: 0,
+    notSetKey: false, // 未设置关键词
+    isSubCount: false, // 是否子账号
+    powerInfo: {},
+    isWeixin: false
+  },
+  computed: {
+    getStatus: function () {
+      if (JSON.stringify(this.powerInfo) !== '{}') {
+        return this.powerInfo.power.indexOf(10) !== -1
+      }
+    },
+    anchorTopList: function () {
+      var arr = []
+      this.dimensionList.forEach(function (item) {
+        arr.push(item.top)
+      })
+      return arr
+    },
+    // 报告详情筛选条件只有一个省份
+    // 此时不显示地区分布chart
+    notOneAreaFilter () {
+      var area = this.reportFilters.area
+      var showArea = area && (Object.keys(area).length > 1 || Object.keys(area).length === 0)
+      return showArea
+    },
+    emptyShow () {
+      return !this.rid && this.analysis.loaded
+    },
+    tabActive: function () {
+      var _this = this
+      var active = {}
+      this.tabList.some(function (item) {
+        var findThis = item.name === _this.tabActiveName
+        if (findThis)  {
+          active = item
+          return findThis
+        }
+      })
+      return active
+    },
+    buyerclassSectionShow () {
+      const winnerState = this.sections.buyerclass
+      return winnerState.dataAlready && winnerState.projectCountTop3 && winnerState.projectAmountTop3
+    },
+    winnerSectionShow () {
+      const winnerState = this.sections.winner
+      return winnerState.dataAlready && winnerState.projectCountTop3 && winnerState.projectAmountTop3
+    },
+    overviewRateTotal: function () {
+      var total = 0
+      this.sections.market.overview.forEach(function (item) {
+        if (item.ringRatio !== undefined && item.ringRatio !== null) {
+          total += item.ringRatio
+        }
+      })
+      return total
+    }
+  },
+  watch: {
+    filtersPageShow (newVal) {
+      if (!newVal) {
+        this.isWeixin = utils.isWeiXinBrowser
+        if (!this.isWeixin) {
+          this.calcStickyOffset()
+        }
+      }
+    }
+  },
+  created () {
+    this.calcLastTimeText()
+    this.getPower()
+    var id = utils.getParam('id')
+    if (id) {
+      this.rid = decodeURIComponent(id)
+      this.filtersPageShow = false
+    }
+  },
+  mounted: function () {
+    setTimeout(() => {
+      var restored = this.reStoreState()
+      if (!restored) {
+        if (this.rid) {
+          this.getReportResult()
+        }
+      } else {
+        this.$nextTick(this.calcOffsetTop)
+        if (utils.isIos) {
+          setTimeout(this.calcOffsetTop, 1000)
+        }
+      }
+    }, 0)
+    this.addEventListeners()
+    utils.iosBackRefresh()
+  },
+  methods: {
+    showLoading: function () {
+      return this.$toast.loading({
+        duration: 0,
+        forbidClick: true,
+        message: 'loading...',
+      })
+    },
+    showToast: function (message) {
+      return this.$toast({
+        duration: 1500,
+        forbidClick: true,
+        message: message,
+      })
+    },
+    showDialog: function (conf) {
+      var defaultConf = {
+        title: '提示',
+        message: 'message',
+        className: 'j-confirm-dialog',
+        showConfirmButton: true,
+        showCancelButton: true,
+        confirmButtonText: '确定',
+        confirmButtonColor: '#2abed1'
+      }
+      if (conf) {
+        Object.assign(defaultConf, conf)
+      }
+      return this.$dialog.confirm(defaultConf)
+    },
+    calcOffsetTop: function () {
+      var sticky = $('.van-sticky')
+      var stickyHeight = 0
+      if (sticky.length) {
+        stickyHeight = sticky[0].clientHeight
+      }
+      this.dimensionList.forEach(function (item) {
+        var anchor = $('.' + item.anchor)
+        var offsetTop = 0
+        if (anchor.length) {
+          offsetTop = parseInt(anchor[0].offsetTop - stickyHeight)
+        }
+        item.top = offsetTop
+      })
+    },
+    addEventListeners: function () {
+      this.scrollToTop()
+    },
+    scrollToTop: function () {
+      var $scrollDOM = $('.j-container.search-result > .j-main')
+      // 1. 检查当前高度是否满足显示快速滚动到顶部
+      this.checkScrollTopButtonShow()
+      // 2. 具体逻辑
+      $scrollDOM.on('scroll', this.checkScrollTopButtonShow)
+      setTimeout(function () {
+        // 2s后绑定(尽可能保证top能够被计算完)
+        $scrollDOM.on('scroll', this.checkAnchorItemActive)
+      }.bind(this), 2000)
+
+      $('.scroll-to-top').on('click', function () {
+        $scrollDOM.animate({ scrollTop: 0 })
+      })
+    },
+    checkAnchorItemActive: function () {
+      var $scrollDOM = $('.j-container.search-result > .j-main')
+      var anchorTopList = this.anchorTopList
+      var scrollTop = parseInt($scrollDOM.scrollTop()) + 3 // (误差校正)
+      var i = 0
+      if (scrollTop >= anchorTopList[1] && scrollTop < anchorTopList[2]) {
+        i = 1
+      } else if (scrollTop > anchorTopList[2]) {
+        i = 2
+      } else if (scrollTop < anchorTopList[1]) {
+        i = 0
+      }
+      this.activeDimension = this.dimensionList[i].id
+    },
+    checkScrollTopButtonShow: function () {
+      var showButtonHeight = 300
+      var $scrollDOM = $('.j-container.search-result > .j-main')
+      var button = $('.scroll-to-top')
+      var scrollTop = $scrollDOM.scrollTop()
+      if (scrollTop > showButtonHeight) {
+        button.show()
+      } else {
+        button.hide()
+      }
+    },
+    calcStickyOffset: function () {
+      setTimeout(function () {
+        var headerHeight = $('.jy-app-header')[0].clientHeight
+        var tabHeight = $('.analysis-tab')[0].clientHeight
+        this.stickyOffset = headerHeight + tabHeight - 5
+      }.bind(this), 1000)
+    },
+    setScrollTop: function (scrollTop) {
+      this.$nextTick(function () {
+        var wrapper = document.querySelector('.j-container.search-result > .j-main')
+        wrapper.scrollTop = scrollTop
+      })
+    },
+    saveScrollTop: function () {
+      var wrapper = document.querySelector('.j-container.search-result > .j-main')
+      if (wrapper.scrollTop) {
+        this.scrollTop = parseInt(wrapper.scrollTop)
+      }
+    },
+    beforeTabChange: function (name) {
+      if (name !== this.tabActiveName) {
+        this.goToAnalysisHistory()
+      }
+      return false
+    },
+    goToAnalysisHistory: function () {
+      location.href = './report_analysis_history'
+    },
+    formatSelectTime (value) {
+      if (!value) return '-'
+      const timeArr = value.split('-')
+      return `${dateFormatter(timeArr[0] * 1000, 'yyyy/MM/dd')}-${dateFormatter(timeArr[1] * 1000, 'yyyy/MM/dd')}`
+    },
+    getPower:function () {
+      var _this = this
+      $.ajax({
+        type:'POST',
+        url:'/bigmember/use/isAdd',
+        success:function(res) {
+          _this.powerInfo = res.data
+          if (res.data && res.data.isSubCount){
+            _this.isSubCount = true
+          }
+        }
+      })
+    },
+    init: function () {
+      // 初始化页面数据
+      this.initDateTimeSelector('sinceYearBeforeLast')
+    },
+    // 时间选择器选中状态
+    initDateTimeSelector: function (exact) {
+      if (exact === 'exact') {
+        this.$refs.dateSelector.setState(this.filters.rangeTime)
+      } else {
+        this.$refs.dateSelector.setTimeSelectListState(exact)
+        this.$refs.dateSelector.dateStyle = false
+      }
+    },
+    resolveSelected: function (type) {
+      var filters = this.filters
+      var prefix = '已选:'
+      var text = ''
+      if (type === 'keys') {
+        if (this.notSetKey) return '请设置'
+        text = this.resolveSelectKeysText(filters.keys)
+      } else if (type === 'area') {
+        text = this.resolveSelectAreaText(filters.area)
+      } else if (type === 'industry') {
+        text = this.resolveSelectIndustryText(filters.industryDetail)
+      } else if (type === 'buyerclass') {
+        text = this.resolveSelectBuyerclassText(filters.buyerclass)
+      }
+      return prefix + text
+    },
+    resolveSelectKeysText: function (keys) {
+      if (Array.isArray(keys)) {
+        if (keys.length === 0) {
+          return '全部'
+        } else {
+          var count = 0
+          var arr = []
+          keys.forEach(function (classify) {
+            if (Array.isArray(classify.a_key) && classify.a_key.length) {
+              count += classify.a_key.length
+              classify.a_key.forEach(function (item) {
+                arr.push(item.key.join(' '))
+              })
+            }
+          })
+          if (count <= 0) {
+            return '全部'
+          } else {
+            return arr.join(',')
+          }
+        }
+      } else {
+        return '全部'
+      }
+    },
+    resolveSelectAreaText: function (area) {
+      if (!area || Object.keys(area).length === 0) return '全国'
+      var areaArr = []
+      var cityArr = []
+      for (var key in area) {
+        if (area[key].length === 0) {
+          areaArr.push(key)
+        } else {
+          cityArr = cityArr.concat(area[key])
+        }
+      }
+      return areaArr.concat(cityArr).join(',')
+    },
+    resolveSelectIndustryText: function (industry) {
+      if (!industry || Object.keys(industry).length === 0) return '全部'
+      var keyArr = []
+      var valueArr = []
+      for (var key in industry) {
+        if (industry[key].length === 0) {
+          keyArr.push(key)
+        } else {
+          valueArr = valueArr.concat(industry[key])
+        }
+      }
+      return keyArr.concat(valueArr).join(',')
+    },
+    resolveSelectBuyerclassText: function (buyerclass) {
+      if (!Array.isArray(buyerclass)) return '全部'
+      if (buyerclass.length === 0) return '全部'
+      return buyerclass.join(',')
+    },
+    calcLastTimeText: function () {
+      const renameList = [
+        'thisYear', // 今年全年
+        'sinceLastYear', // 去年至今
+        'sinceYearBeforeLast' // 前年至今
+      ]
+      const thisYear = new Date().getFullYear()
+      this.timeOptions.forEach(item => {
+        if (renameList.indexOf(item.value) !== -1) {
+          if (item.value === renameList[0]) {
+            item.name = `${thisYear}年全年`
+          } else if (item.value === renameList[1]) {
+            item.name = `${thisYear - 1}年至今`
+          } else if (item.value === renameList[2]) {
+            item.name = `${thisYear - 2}年至今`
+          }
+        }
+      })
+    },
+    // 重置
+    resetFilter: function (type) {
+      var filters = this.filters
+      if (type === 'keys') {
+        filters.keys = []
+        filters.selectKeysArr = []
+        try {
+          this.$refs.keywordSelector.resetAllNoSelect()
+        } catch (error) {}
+      } else if (type === 'area') {
+        filters.area = {}
+      } else if (type === 'industry') {
+        filters.industry = []
+        filters.industryDetail = {}
+      } else if (type === 'buyerclass') {
+        filters.buyerclass = []
+      } else if (type === 'date') {
+        this.filters.rangeTime.start = ''
+        this.filters.rangeTime.edd = ''
+        this.filters.rangeTime.exact = 'sinceYearBeforeLast'
+        this.initDateTimeSelector(this.filters.rangeTime.exact)
+      } else {
+        this.resetFilter('keys')
+        this.resetFilter('area')
+        this.resetFilter('industry')
+        this.resetFilter('buyerclass')
+        this.resetFilter('date')
+      }
+    },
+    clickCell: function (key) {
+      var _this = this
+      var dialog = this.filterDialogShow
+      if (key === 'keys') {
+        if (this.notSetKey) {
+          return this.setKeyTip()
+        }
+      } else if (key === 'area') {
+        setTimeout(function () {
+          _this.$refs.areaCitySelector.setState(_this.filters.area)
+        }, 0)
+      } else if (key === 'buyerclass') {
+        setTimeout(function () {
+          _this.$refs.buyerclassSelector.setState()
+        }, 0)
+      }  else if (key === 'industry') {
+        setTimeout(function () {
+          _this.$refs.industrySelector.setState()
+        }, 0)
+      }
+      dialog[key] = true
+    },
+    cancel: function (e, key) {
+      var dialog = this.filterDialogShow
+      this.resetFilter(key)
+      dialog[key] = false
+    },
+    confirm: function (e, key) {
+      var dialog = this.filterDialogShow
+      var filters = this.filters
+      if (key === 'keys') {
+        filters.keys = e.detail
+        filters.selectKeysArr = e.data
+      } else if (key === 'area') {
+        filters.area = e.data
+      } else if (key === 'industry') {
+        filters.industry = e.data
+        filters.industryDetail = e.detail
+      } else if (key === 'buyerclass') {
+        filters.buyerclass = e.data
+        console.log(e.data)
+      } 
+      dialog[key] = false
+    },
+    dateTimeSelectorConfirm () {
+      var result = this.$refs.dateSelector.getState()
+      this.filters.rangeTime.start = result.start
+      this.filters.rangeTime.end = result.end
+      this.filters.rangeTime.exact = result.exact
+    },
+    resetAllFilters: function () {
+      this.analysis.loaded = false
+      this.resetFilter('all')
+    },
+    getReportResult () {
+      this.sendRequest()
+    },
+    getSelectedKeys () {
+      const keys = this.filters.keys
+      if (Array.isArray(keys) && keys.length) {
+        return JSON.stringify(keys)
+      } else {
+        var allKeys = this.$refs.keywordSelector.keywordGroupList
+        return JSON.stringify(allKeys)
+      }
+    },
+    startAnalysis: function () {
+      this.dateTimeSelectorConfirm()
+
+      const query = {
+        keysItems: this.getSelectedKeys(),
+        rangeTime: `${parseInt(this.filters.rangeTime.start / 1000)}-${parseInt(this.filters.rangeTime.end / 1000)}`,
+        rangeTimeExtra: this.filters.rangeTime.exact,
+        area: JSON.stringify(this.filters.area),
+        industry: JSON.stringify(this.filters.industryDetail),
+        buyerclass: this.filters.buyerclass.join(',')
+      }
+
+      this.analysis.loaded = false
+      this.analysis.loading = true
+      this.showLoading()
+
+      $.ajax({
+        type: 'POST',
+        url: '/bigmember/marketAnalysis/doAnalysis',
+        data: query,
+        success: function (res) {
+          if (res && res.error_code === 0 && res.data) {
+            this.rid = res.data
+            this.analysis.loaded = true
+            // location.replace('./report_analysis?id=' + res.data)
+            this.rid = res.data
+            history.replaceState({}, null, '?id=' + this.rid)
+            this.getReportResult()
+          } else {
+            this.$toast(res.error_msg)
+          }
+        }.bind(this),
+        complete: function () {
+          this.analysis.loading = false
+        }.bind(this)
+      })
+    },
+    // 保存页面状态
+    saveState: function () {
+      this.saveScrollTop()
+      this.dateTimeSelectorConfirm()
+      var $data = {
+        analysis: this.analysis,
+        filters: this.filters,
+        scrollTop: this.scrollTop,
+        filtersPageShow: this.filtersPageShow,
+        reportFilters: this.reportFilters,
+        sections: this.sections,
+        isSubCount: this.isSubCount
+      }
+      sessionStorage.setItem(this.sessStorageKey, JSON.stringify($data))
+    },
+    reStoreState: function () {
+      var $data = sessionStorage.getItem(this.sessStorageKey)
+      if ($data) {
+        $data = JSON.parse($data)
+
+        this.isSubCount = $data.isSubCount
+        this.scrollTop = $data.scrollTop
+        this.filtersPageShow = $data.filtersPageShow
+        Object.assign(this.analysis, $data.analysis)
+        this.$set(this, 'filters', $data.filters)
+        this.$set(this, 'reportFilters', $data.reportFilters)
+        this.$set(this, 'sections', $data.sections)
+
+        setTimeout(function () {
+          // 恢复滚动高度
+          this.setScrollTop(this.scrollTop)
+          this.initDateTimeSelector(this.filters.rangeTime.exact)
+        }.bind(this), 0)
+
+        sessionStorage.removeItem(this.sessStorageKey)
+      } else {
+        this.init()
+      }
+
+      return $data
+    },
+    onEmpty (info) {
+      if (this.loading) {
+        this.loading.clear()
+      }
+      this.filtersPageShow = true
+      this.analysis.loaded = true
+      this.rid = ''
+      if (info && info.msg) {
+        this.empty.msg = info.msg
+      } else {
+        this.empty.msg = this.empty.defaultMsg
+      }
+    },
+    sendRequest () {
+      let _this = this
+      // 先请求概况(1),判断报告是否为空
+      const query = {
+        rid: this.rid,
+        flag: 1
+      }
+      if (!query.rid) {
+        return
+      }
+      this.loading = this.showLoading()
+      $.ajax({
+        type: 'POST',
+        async: false,
+        url: '/bigmember/marketAnalysis/getAnalysisResult',
+        data: query,
+        success: function(res) {
+          if (res && res.error_code === 0 && res.data) {
+            var empty = _this.formatterData(query.flag, res.data)
+            if (empty) {
+              return _this.onEmpty()
+            }
+          } else {
+            if (res.error_msg.indexOf('项目数量超出上限') === -1) {
+              return _this.onEmpty()
+            } else {
+              return _this.onEmpty({ msg: '当前分析条件涉及项目数量已超过最大限制,请修改分析条件进行精确分析' })
+            }
+          }
+        }
+      }).responseJSON
+
+
+      this.filtersPageShow = false
+
+      const flagArr = [
+        0, // 筛选条件
+        // 1, // 市场概括与时间分布
+        2, // 项目规模Top10
+        3, // 项目规模分布/地区规模分布/客户分布/地区分布及客户分布&Top3(table+chart)
+        4, // 细分市场
+        5 // 采购单位/中标单位&Top3(table+chart)
+      ]
+
+      flagArr.forEach(this.getReport)
+
+      if (this.loading) {
+        this.loading.clear()
+      }
+    },
+    getReport (flag) {
+      const query = {
+        rid: this.rid,
+        flag
+      }
+      if (!query.rid) {
+        return
+      }
+      
+      $.ajax({
+        type: 'POST',
+        url: '/bigmember/marketAnalysis/getAnalysisResult',
+        data: query,
+        success: function (res) {
+          if (res && res.error_code === 0 && res.data) {
+            this.formatterData(flag, res.data)
+          } else {
+            this.$toast('请求失败')
+          }
+        }.bind(this)
+      })
+    },
+    formatterData (flag, data) {
+      if (flag === 0) {
+        this.sortReportFilters(data)
+      } else if (flag === 1) {
+        // 市场概况
+        const totalCount = this.sortMarketOverview(data.market_profile)
+        if (!totalCount) {
+          return true
+        }
+        // 时间分布
+        this.sortTimeScatter(data)
+      } else if (flag === 2) {
+        // 项目规模Top10
+        this.sortProjectTop10(data.ProjectTop10)
+      } else if (flag === 3) {
+        // 项目规模分布/地区规模分布/客户分布/地区分布及客户分布&Top3(table+chart)
+        // 项目规模分布
+        this.sortProjectScatter(data.projectScale)
+        // 地区规模分布
+        this.sortAreaScatter(data.area_infos)
+        // 客户分布
+        this.sortUserScatter(data.customer_scale)
+        // 地区分布及客户分布Top3
+        this.sortAreaUserTop3(data)
+      } else if (flag === 4) {
+        // 细分市场
+        this.sortMarketRefineData(data)
+      } else if (flag === 5) {
+        // 采购单位/中标单位&Top3(table+chart)
+        this.sortBuyerclassData(data)
+        // 中标单位分析
+        this.sortWinnerData(data)
+      }
+
+      this.$nextTick(this.calcOffsetTop)
+    },
+    formatSelectTime (value) {
+      if (!value) return '-'
+      const timeArr = value.split('-')
+      return `${dateFormatter(timeArr[0] * 1000, 'yyyy/MM/dd')}-${dateFormatter(timeArr[1] * 1000, 'yyyy/MM/dd')}`
+    },
+    // 整理数据,并赋值给filters
+    sortReportFilters (data) {
+      if (data.keysItems && data.keysItems !== '[]') {
+        this.reportFilters.keys = JSON.parse(data.keysItems)
+        this.filters.keys = this.reportFilters.keys
+        var keyArr = []
+        this.filters.keys.forEach(function (classify) {
+          if(Array.isArray(classify.a_key)) {
+            classify.a_key.forEach(function (item) {
+              keyArr.push(item.key.join(' '))
+            })
+          }
+        })
+        this.filters.selectKeysArr = keyArr
+      }
+
+      // if (data.s_rangeTimeExtra) {
+      //   this.reportFilters.selectTimeExtra = data.s_rangeTimeExtra
+      //   this.filters.rangeTime.exact = this.reportFilters.selectTimeExtra
+      // } else {
+      //   this.filters.rangeTime.exact = 'exact'
+      // }
+      this.filters.rangeTime.exact = 'exact'
+      if (data.rangeTime) {
+        this.reportFilters.selectTime = data.rangeTime
+        var arr = data.rangeTime.split('-')
+        this.filters.rangeTime.start = arr[0] * 1000
+        this.filters.rangeTime.end = arr[1] * 1000
+        if (this.filters.rangeTime.exact === 'exact') {
+          var date = new Date(this.filters.rangeTime.end)
+          var timeString = date.pattern('yyyy/MM/dd')
+          this.filters.rangeTime.end = new Date(timeString).getTime()
+        }
+      }
+      
+      this.$refs.dateSelector.setState(this.filters.rangeTime)
+      if (data.area && data.area !== '{}') {
+        this.reportFilters.area = JSON.parse(data.area)
+        this.filters.area = this.reportFilters.area
+      }
+      if (data.industry && data.industry !== '{}') {
+        this.reportFilters.industry = JSON.parse(data.industry)
+        this.$set(this.filters, 'industryDetail', this.reportFilters.industry)
+        var industry = []
+        for (var key in this.reportFilters.industry) {
+          this.reportFilters.industry[key].forEach(function (item) {
+            industry.push(key + '_' + item)
+          })
+        }
+        this.filters.industry = industry
+      }
+      if (data.buyerclass) {
+        this.reportFilters.buyerclass = data.buyerclass.split(',')
+        this.filters.buyerclass = this.reportFilters.buyerclass
+      }
+    },
+    // 市场概况
+    sortMarketOverview (profile) {
+      if (!profile) return
+      const list = [
+        {
+          label: '项目总数',
+          unit: '个',
+          count: 0,
+          ringRatio: 0
+        },
+        {
+          label: '项目总金额',
+          unit: '万元',
+          count: 0,
+          ringRatio: 0
+        },
+        {
+          label: '项目平均金额',
+          unit: '万元',
+          count: 10.04,
+          ringRatio: 0
+        },
+        {
+          label: '中标单位数',
+          unit: '家',
+          count: 10628,
+          ringRatio: 0
+        },
+        {
+          label: '采购单位数',
+          unit: '家',
+          count: 16215,
+          ringRatio: 0
+        }
+      ]
+
+      // 项目总数
+      list[0].count = profile.project_count ? profile.project_count : 0
+      list[0].ringRatio = profile.project_count_ratio ? (profile.project_count_ratio * 100).toFixed(2) : 0
+      // 项目总金额
+      const projectTotalMoney = this.moneyUnit(profile.projctamout ? profile.projctamout : 0)
+      list[1].count = projectTotalMoney.count || 0
+      list[1].unit = projectTotalMoney.unit || '万元'
+
+      list[1].ringRatio = profile.projctamount_ratio ? (profile.projctamount_ratio * 100).toFixed(2) : 0
+      // 项目平均金额
+      const projectAvgMoney = this.moneyUnit(profile.projectavgmoney ? profile.projectavgmoney : 0)
+      list[2].count = projectAvgMoney.count || 0
+      list[2].unit = projectAvgMoney.unit || '万元'
+      list[2].ringRatio = profile.projectavgmoney_ratio ? (profile.projectavgmoney_ratio * 100).toFixed(2) : 0
+      // 中标单位数
+      list[3].count = profile.winnercount ? profile.winnercount : 0
+      list[3].ringRatio = profile.winnercount_ratio ? (profile.winnercount_ratio * 100).toFixed(2) : 0
+      // 采购单位数
+      list[4].count = profile.buyercount ? profile.buyercount : 0
+      list[4].ringRatio = profile.winnercount_ratio ? (profile.winnercount_ratio * 100).toFixed(2) : 0
+
+      var totalCount = list.reduce((total, item) => item.count + total, 0)
+
+      if (totalCount) {
+        this.sections.market.overview = list
+      }
+
+      return totalCount
+    },
+    // 时间分布
+    sortTimeScatter (data) {
+      const hasDataM = this.sortTimeScatterData('month', data.month_distribution)
+      const hasDataY = this.sortTimeScatterData('year', data.year_distribution)
+
+      const hasData = hasDataM && hasDataY
+      this.sections.timeScatter.dataAlready = hasData
+    },
+    sortTimeScatterData (type, data) {
+      // columns: ['日期', '项目规模', '环比增长率(%)'],
+      // rows: [
+      //   {
+      //     日期: '6月',
+      //     项目规模: 0,
+      //     '环比增长率(%)': -99
+      //   },
+      //   {
+      //     日期: '7月',
+      //     项目规模: 736325,
+      //     '环比增长率(%)': 0
+      //   },
+      // ]
+
+      if (!data) return
+
+      // 项目数量
+      const mDCount = {
+        columns: ['日期', '项目数量(个)', '项目数量环比'],
+        rows: []
+      }
+      let mDCountTotal = 0
+      if (Array.isArray(data.project_count)) {
+        const field = {
+          [mDCount.columns[0]]: 'minth',
+          [mDCount.columns[1]]: 'value',
+          [mDCount.columns[2]]: 'ratio'
+        }
+        data.project_count.forEach(item => {
+          const row = {}
+          mDCount.columns.forEach(column => {
+            var value = item[field[column]]
+            if (value) {
+              if (field[column] === 'ratio') {
+                row[column] = utils.formatMoney(value * 100, undefined, true) - 0
+              } else {
+                row[column] = value
+              }
+            } else {
+              row[column] = null
+            }
+
+            if (typeof value === 'number') {
+              mDCountTotal += value
+            }
+          })
+          mDCount.rows.push(row)
+        })
+      }
+
+      if (mDCountTotal || isNaN(mDCountTotal)) {
+        this.$set(this.sections.timeScatter[type], 'count', mDCount)
+      }
+
+      // 项目规模
+      const mDAmount = {
+        columns: ['日期', '项目金额(万元)', '项目金额环比'],
+        rows: []
+      }
+      let mDAmuntTotal = 0
+      if (Array.isArray(data.project_amount)) {
+        const field = {
+          [mDAmount.columns[0]]: 'minth',
+          [mDAmount.columns[1]]: 'value',
+          [mDAmount.columns[2]]: 'ratio'
+        }
+        data.project_amount.forEach(item => {
+          const row = {}
+          mDAmount.columns.forEach(column => {
+            const value = item[field[column]]
+            if (value) {
+              if (field[column] === 'value') {
+                row[column] = utils.formatMoney(value / 10000, undefined, true) - 0
+              } else if (field[column] === 'ratio') {
+                row[column] = utils.formatMoney(value * 100, undefined, true)
+              } else {
+                row[column] = value
+              }
+            } else {
+              row[column] = null
+            }
+
+            if (typeof value === 'number') {
+              mDAmuntTotal += value
+            }
+          })
+          mDAmount.rows.push(row)
+        })
+      }
+
+      if (mDAmuntTotal || !isNaN(mDAmuntTotal)) {
+        this.$set(this.sections.timeScatter[type], 'amount', mDAmount)
+      }
+
+      const r = !!(mDCountTotal + mDAmuntTotal)
+      const hasOneNaN = isNaN(mDCountTotal) || isNaN(mDAmuntTotal)
+      return hasOneNaN || r
+    },
+    // 项目规模分布
+    sortProjectScatter (data) {
+      // const chartData = {
+      //   columns: ['项目规模', '项目总金额占比', '项目总数占比'],
+      //   rows: [
+      //     {
+      //       项目规模: '≥1亿',
+      //       项目总金额占比: 20,
+      //       项目总数占比: 10
+      //     },
+      //     {
+      //       项目规模: '1000万-1亿',
+      //       项目总金额占比: 50,
+      //       项目总数占比: 40
+      //     },
+      //     {
+      //       项目规模: '500万-1000万',
+      //       项目总金额占比: 20,
+      //       项目总数占比: 30
+      //     },
+      //     {
+      //       项目规模: '100万-500万',
+      //       项目总金额占比: 20,
+      //       项目总数占比: 30
+      //     }
+      //   ]
+      // }
+
+      const scaleList = data
+      const scaleData = {
+        columns: ['项目规模', '项目总金额占比', '项目总数占比'],
+        rows: []
+      }
+      let total = 0
+
+      if (scaleList && Array.isArray(scaleList)) {
+        const field = {
+          [scaleData.columns[0]]: 'Name',
+          [scaleData.columns[1]]: 'Persent_c',
+          [scaleData.columns[2]]: 'Persent_a'
+        }
+        scaleList.forEach(item => {
+          const row = {}
+          scaleData.columns.forEach(column => {
+            if (field[column] === 'Persent_c' || field[column] === 'Persent_a') {
+              row[column] = (item[field[column]] * 100).toFixed(2)
+              total += (item[field[column]] - 0)
+            } else {
+              row[column] = item[field[column]]
+            }
+          })
+          scaleData.rows.push(row)
+        })
+      }
+
+      if (total) {
+        scaleData.rows.reverse()
+        this.$set(this.sections.projectScatter, 'chartData', scaleData)
+        if (this.sections.projectScatter.tableData.length) {
+          this.sections.projectScatter.dataAlready = true
+        }
+      }
+    },
+    // 项目规模Top10
+    sortProjectTop10 (top10List) {
+      if (!Array.isArray(top10List)) return
+
+      this.sections.projectScatter.tableData = top10List.map(top => {
+        let winners = top.winner_s ? top.winner_s.join(',') : ''
+        if (!winners) {
+          winners = []
+        } else {
+          winners = top.winner_s
+        }
+
+        winners = winners.map((item, index) => {
+          return {
+            name: item,
+            id: Array.isArray(top.eidlist) ? top.eidlist[index] : null
+          }
+        })
+
+        top.area = top.area ? top.area : ''
+        top.city = top.city ? top.city : ''
+        top.sortprice = top.sortprice ? utils.formatMoney(top.sortprice / 10000, undefined, true) : ''
+        top.jgtime = top.jgtime ? dateFormatter(top.jgtime * 1000, 'yyyy-MM-dd') : ''
+        top.winner_s = winners
+
+        return top
+      })
+
+      if (this.sections.projectScatter.chartData) {
+        this.sections.projectScatter.dataAlready = true
+      }
+    },
+    // 地区规模分布
+    sortAreaScatter (areaList) {
+      // const chartData = {
+      //   columns: ['项目所在地', '项目数量', '项目金额'],
+      //   rows: [
+      //     {
+      //       项目所在地: '河南',
+      //       项目数量: 2,
+      //       项目金额: 2222
+      //     },
+      //     {
+      //       项目所在地: '北京',
+      //       项目数量: 22,
+      //       项目金额: 565666
+      //     },
+      //     {
+      //       项目所在地: '浙江',
+      //       项目数量: 22,
+      //       项目金额: 765666
+      //     }
+      //   ]
+      // }
+
+      const areaChartData = {
+        columns: ['项目所在地', '项目数量'],
+        sColumns: ['项目金额'],
+        rows: []
+      }
+      let total = 0
+
+      if (areaList && Array.isArray(areaList)) {
+        const field = {
+          [areaChartData.columns[0]]: 'area',
+          [areaChartData.columns[1]]: 'total',
+          [areaChartData.sColumns[0]]: 'amount'
+        }
+        areaList.forEach(item => {
+          const row = {}
+          areaChartData.columns.concat(areaChartData.sColumns).forEach(column => {
+            if (field[column] === 'amount') {
+              row[column] = utils.formatMoney(item[field[column]] / 10000, undefined, true) - 0
+            } else {
+              row[column] = item[field[column]]
+            }
+
+            if (field[column] === 'amount' || field[column] === 'total') {
+              total += (item[field[column]] - 0)
+            }
+          })
+          areaChartData.rows.push(row)
+        })
+      }
+
+      if (total) {
+        this.$set(this.sections.areaScatter, 'chartData', areaChartData)
+        this.sections.areaScatter.dataAlready = true
+      }
+    },
+    // 客户分布
+    sortUserScatter (userList) {
+      if (Array.isArray(userList)) {
+        this.sections.userScatter.list = userList.map(item => {
+          item.name = item.buyclass
+          item.value = item.total
+          item.amount = utils.formatMoney(item.amount / 10000, undefined, true)
+          return item
+        })
+      }
+    },
+    // 地区分布及客户分布Top3
+    sortAreaUserTop3 (data) {
+      if (data.scaleAreaCountTop || data.scaleAreaAmountTop) {
+        this.sorAreaTop3(data)
+      }
+      if (data.scaleBuyclassCountTop || data.scaleBuyclassAmountTop) {
+        this.sorUserTop3(data)
+      }
+    },
+    sorAreaTop3 (data) {
+      const tableDataCount = {
+        columns: ['序号', '地区:项目数量(个),占比', '前3中标单位:中标数量(个)'], // ,该地区占比
+        rows: []
+      }
+      const tableDataAmount = {
+        columns: ['序号', '地区:项目金额(万元),占比', '前3中标单位:中标金额(万元)'], // ,该地区占比
+        rows: []
+      }
+
+      const scaleAreaCountTop3 = data.scaleAreaCountTop
+      if (Array.isArray(scaleAreaCountTop3)) {
+        scaleAreaCountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.area_count ? `项目数量:${item.area_count}个` : ''
+          item.subInfo2 = item.area_scale ? `全国占比:${utils.formatMoney(item.area_scale * 100, undefined, true)}%` : ''
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.winner)) {
+            item.winner.forEach((w, i) => {
+              const row = {
+                name: w.winner,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.winner_total ? `中标个数:${w.winner_total}个` : '',
+                // subInfo2: w.total_scale ? `地区占比:${utils.formatMoney(w.total_scale * 100, undefined, true)}%` : 0
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataCount.rows = scaleAreaCountTop3
+      }
+
+      const scaleAreaAmountTop3 = data.scaleAreaAmountTop
+      if (Array.isArray(scaleAreaAmountTop3)) {
+        scaleAreaAmountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.area_amount ? `中标金额:${utils.formatMoney(item.area_amount / 10000, undefined, true)}万元` : ''
+          item.subInfo2 = item.area_scale ? `全国占比:${utils.formatMoney(item.area_scale * 100, undefined, true)}%` : ''
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.winner)) {
+            item.winner.forEach((w, i) => {
+              const row = {
+                name: w.winner,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.winner_amount ? `中标金额:${utils.formatMoney(w.winner_amount / 10000, undefined, true)}万元` : '',
+                // subInfo2: w.amount_scale ? `地区占比:${utils.formatMoney(w.amount_scale * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataAmount.rows = scaleAreaAmountTop3
+      }
+
+      if (tableDataCount.rows.length) {
+        this.$set(this.sections.areaScatter, 'projectCountTop3', tableDataCount.rows)
+      }
+      if (tableDataAmount.rows.length) {
+        this.$set(this.sections.areaScatter, 'projectAmountTop3', tableDataAmount.rows)
+      }
+    },
+    sorUserTop3 (data) {
+      const tableDataCount = {
+        columns: ['序号', '客户类型:项目数量(个),占比', '前3中标单位:中标数量(个)'], // ,该客户类型占比
+        rows: []
+      }
+      const tableDataAmount = {
+        columns: ['序号', '客户类型:项目金额(万元),占比', '前3中标单位:中标金额(万元)'], // ,该客户类型占比
+        rows: []
+      }
+
+      const countTop3 = data.scaleBuyclassCountTop
+      if (Array.isArray(countTop3)) {
+        countTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.buyclass_count ? `项目数量:${item.buyclass_count}个` : ''
+          item.subInfo2 = item.buyclass_scale ? `全部占比:${utils.formatMoney(item.buyclass_scale * 100, undefined, true)}%` : ''
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+
+          if (Array.isArray(item.winner)) {
+            item.winner.forEach((w, i) => {
+              const row = {
+                name: w.winner,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.winner_total ? `中标个数:${w.winner_total}个` : '',
+                // subInfo2: w.total_scale ? `该行业占比:${utils.formatMoney(w.total_scale * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataCount.rows = countTop3
+      }
+
+      const amountTop3 = data.scaleBuyclassAmountTop
+      if (Array.isArray(amountTop3)) {
+        amountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.buyclass_amount ? `项目金额:${utils.formatMoney(item.buyclass_amount / 10000, undefined, true)}万元` : ''
+          item.subInfo2 = item.buyclass_scale ? `全部占比:${utils.formatMoney(item.buyclass_scale * 100, undefined, true)}%` : 0
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.winner)) {
+            item.winner.forEach((w, i) => {
+              const row = {
+                name: w.winner,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.winner_amount ? `中标金额:${utils.formatMoney(w.winner_amount / 10000, undefined, true)}万元` : '',
+                // subInfo2: w.amount_scale ? `该行业占比:${utils.formatMoney(w.amount_scale * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataAmount.rows = amountTop3
+      }
+
+      if (tableDataCount.rows.length) {
+        this.$set(this.sections.userScatter, 'projectCountTop3', tableDataCount.rows)
+      }
+      if (tableDataAmount.rows.length) {
+        this.$set(this.sections.userScatter, 'projectAmountTop3', tableDataAmount.rows)
+      }
+    },
+    // 细分市场
+    sortMarketRefineData (data) {
+      const refineCount = {
+        columns: ['行业', '项目数量'],
+        rows: []
+      }
+      const refineAmount = {
+        columns: ['行业', '项目金额'],
+        rows: []
+      }
+      let total = 0
+      const refineAll = data.scaleRefineAll
+      if (Array.isArray(refineAll)) {
+        const field = {
+          行业: 'name',
+          项目数量: 'total',
+          项目金额: 'amount'
+        }
+        refineAll.forEach(item => {
+          const row = {}
+          for (const key in field) {
+            if (field[key] === 'amount') {
+              row[key] = utils.formatMoney(item[field[key]] / 10000, undefined, true)
+            } else {
+              row[key] = item[field[key]]
+            }
+
+            if (field[key] === 'total' || field[key] === 'amount') {
+              total += (item[field[key]] - 0)
+            }
+          }
+          refineCount.rows.push(row)
+          refineAmount.rows.push(row)
+        })
+      }
+
+      if (total) {
+        this.$set(this.sections.market.refine, 'projectCountData', refineCount)
+        this.$set(this.sections.market.refine, 'projectAmountData', refineAmount)
+
+        this.sections.market.refine.dataAlready = true
+      }
+      
+      this.sortRefineTop3(data)
+    },
+    sortRefineTop3 (data) {
+      const tableDataCount = {
+        columns: ['序号', '细分市场:项目数量(个)', '前3中标单位:中标数量(个)'], // ,占比,该细分市场占比
+        rows: []
+      }
+      const tableDataAmount = {
+        columns: ['序号', '细分市场:项目金额(万元)', '前3中标单位:中标金额(万元)'], // ,占比,该细分市场占比
+        rows: []
+      }
+
+      const countTop3 = data.scaleRefineTotalTop
+      if (Array.isArray(countTop3)) {
+        countTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.value ? `项目数量:${item.value}个` : ''
+          // item.subInfo2 = item.prop ? `全部占比:${utils.formatMoney(item.prop * 100, undefined, true)}%` : 0
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.topList)) {
+            item.topList.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.value ? `中标个数:${w.value}个` : '',
+                // subInfo2: w.prop ? `该细分市场占比:${utils.formatMoney(w.prop * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataCount.rows = countTop3
+      }
+
+      const amountTop3 = data.scaleRefineAmountTop
+      if (Array.isArray(amountTop3)) {
+        amountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.subInfo1 = item.value ? `项目金额:${utils.formatMoney(item.value / 10000, undefined, true)}万元` : ''
+          // item.subInfo2 = item.prop ? `全部占比:${utils.formatMoney(item.prop * 100, undefined, true)}%` : 0
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.topList)) {
+            item.topList.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.value ? `中标金额:${utils.formatMoney(w.value / 10000, undefined, true)}万元` : '',
+                // subInfo2: w.prop ? `该细分市场占比:${utils.formatMoney(w.prop * 100, undefined, true)}%`: ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        tableDataAmount.rows = amountTop3
+      }
+
+      if (tableDataCount.rows.length) {
+        this.$set(this.sections.market.refine, 'projectCountTop3', tableDataCount.rows)
+      }
+      if (tableDataAmount.rows.length) {
+        this.$set(this.sections.market.refine, 'projectAmountTop3', tableDataAmount.rows)
+      }
+    },
+    // 采购单位
+    sortBuyerclassData (data) {
+      const buyerclassChartData = {
+        columns: ['金额区间', '采购总金额占比', '采购单位数量占比'],
+        rows: []
+      }
+      let total = 0
+
+      const buyerclassList = data.buyer_time_distribution
+      if (Array.isArray(buyerclassList)) {
+        const field = {
+          [buyerclassChartData.columns[0]]: 'key',
+          [buyerclassChartData.columns[1]]: 'total_amount',
+          [buyerclassChartData.columns[2]]: 'total_number'
+        }
+        buyerclassList.forEach(item => {
+          const row = {}
+          buyerclassChartData.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]]
+            }
+          })
+          buyerclassChartData.rows.push(row)
+        })
+      }
+
+      if (total) {
+        buyerclassChartData.rows.reverse()
+        this.$set(this.sections.buyerclass, 'chartData', buyerclassChartData)
+
+        this.sections.buyerclass.dataAlready = true
+      }
+      
+      this.sortBuyerclassTableData(data)
+    },
+    sortBuyerclassTableData (data) {
+      const dataCount = {
+        columns: ['序号', '采购单位:采购数量(个)', '前3中标单位:中标数量(个)'], //,占比 |  ,占该采购单位
+        rows: []
+      }
+      const dataAmount = {
+        columns: ['序号', '采购单位:采购金额(万元)', '前3中标单位:中标金额(万元)'], //,占比 |  ,占该采购单位
+        rows: []
+      }
+
+      const countTop3 = data.buyer_count_top3
+      if (Array.isArray(countTop3)) {
+        countTop3.forEach((item, index) => {
+          item.name = item.name
+          item.type = 'buyer'
+          item.id = item.name
+          item.subInfo1 = item.number ? `项目数量:${item.number}个` : ''
+          // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.winnertop3)) {
+            item.winnertop3.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.number ? `中标个数:${w.number}个` : '',
+                // subInfo2: w.accounted ? `占该采购单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        dataCount.rows = countTop3
+      }
+
+      const amountTop3 = data.buyer_amount_top3
+      if (Array.isArray(amountTop3)) {
+        amountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.type = 'buyer'
+          item.id = item.name
+          item.subInfo1 = item.amount ? `采购金额:${utils.formatMoney(item.amount / 10000, undefined, true)}万元` : ''
+          // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
+          item.actionText = `中标单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.winnertop3)) {
+            item.winnertop3.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.id,
+                type: 'winner',
+                subInfo1: w.amount ? `中标金额:${utils.formatMoney(w.amount / 10000, undefined, true)}万元` : '',
+                // subInfo2: w.accounted ? `该行业占比:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        dataAmount.rows = amountTop3
+      }
+      if (dataCount.rows.length) {
+        this.$set(this.sections.buyerclass, 'projectCountTop3', dataCount.rows)
+      }
+      if (dataAmount.rows.length) {
+        this.$set(this.sections.buyerclass, 'projectAmountTop3', dataAmount.rows)
+      }
+    },
+    // 中标单位
+    sortWinnerData (data) {
+      const chartData = {
+        columns: ['金额区间', '中标总金额占比', '中标单位数量占比'],
+        rows: []
+      }
+      let total = 0
+
+      const chartLIst = data.winner_time_distribution
+      if (Array.isArray(chartLIst)) {
+        const field = {
+          [chartData.columns[0]]: 'key',
+          [chartData.columns[1]]: 'total_amount',
+          [chartData.columns[2]]: 'total_number'
+        }
+        chartLIst.forEach(item => {
+          const row = {}
+          chartData.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]]
+            }
+          })
+          chartData.rows.push(row)
+        })
+      }
+
+      if (total) {
+        chartData.rows.reverse()
+        this.$set(this.sections.winner, 'chartData', chartData)
+
+        this.sections.winner.dataAlready = true
+      }
+
+      this.sortWinnerTableData(data)
+    },
+    sortWinnerTableData (data) {
+      const dataCount = {
+        columns: ['序号', '中标单位:中标数量(个)', '前3采购单位:采购数量(个)'], // ,占比 | ,占该中标单位
+        rows: []
+      }
+      const dataAmount = {
+        columns: ['序号', '中标单位:中标金额(万元),占比', '前3采购单位:采购金额(万元),占该中标单位'], // ,占比 | ,占该中标单位
+        rows: []
+      }
+
+      const countTop3 = data.winner_count_top3
+      if (Array.isArray(countTop3)) {
+        countTop3.forEach((item, index) => {
+          item.name = item.name
+          item.type = 'winner'
+          item.id = item.id
+          item.subInfo1 = item.number ? `中标数量:${item.number}个` : ''
+          // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
+          item.actionText = `采购单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.buyertop3)) {
+            item.buyertop3.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.name,
+                type: 'buyer',
+                subInfo1: w.number ? `采购数量:${w.number}个` : '',
+                // subInfo2: w.accounted ? `占该中标单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        dataCount.rows = countTop3
+      }
+
+      const amountTop3 = data.winner_amount_top3
+      if (Array.isArray(amountTop3)) {
+        amountTop3.forEach((item, index) => {
+          item.name = item.name
+          item.type = 'winner'
+          item.id = item.id
+          item.subInfo1 = item.amount ? `中标金额:${utils.formatMoney(item.amount / 10000, undefined, true)}万元` : ''
+          // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
+          item.actionText = `采购单位 TOP3`
+          item.childrenShow = true
+          item.children = []
+          if (Array.isArray(item.buyertop3)) {
+            item.buyertop3.forEach((w, i) => {
+              const row = {
+                name: w.name,
+                id: w.name,
+                type: 'buyer',
+                subInfo1: w.amount ? `采购金额:${utils.formatMoney(w.amount / 10000, undefined, true)}万元` : '',
+                // subInfo2: w.accounted ? `占该中标单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
+              }
+              item.children.push(row)
+            })
+          }
+        })
+        dataAmount.rows = amountTop3
+      }
+
+      if (dataCount.rows.length) {
+        this.$set(this.sections.winner, 'projectCountTop3', dataCount.rows)
+      }
+      if (dataAmount.rows.length) {
+        this.$set(this.sections.winner, 'projectAmountTop3', dataAmount.rows)
+      }
+    },
+    toAnalysisPage: function () {
+      this.rid = ''
+      this.analysis.loaded = false
+      this.filtersPageShow = true
+    },
+    moneyUnit (num, type, lv) {
+      const m = utils.moneyUnit(num, type, lv)
+      let unit = String(m).match(/[\u4e00-\u9fa5]/g)
+      if (unit && Array.isArray(unit)) {
+        unit = unit.join('')
+      } else {
+        unit = ''
+      }
+      let count = ''
+      if (unit) {
+        count = m.replace(unit, '') - 0
+      }
+      return {
+        unit,
+        count
+      }
+    },
+    anchorTo (item) {
+      // if (!item.top) return
+      var offsetTop = item.top || 0
+      this.activeDimension = item.id
+      this.$nextTick(function () {
+        $('.search-result > .j-main')[0].scrollTop = offsetTop
+      })
+    },
+    showSetKeyTip: function () {
+      this.notSetKey = true
+    },
+    setKeyTip: function () {
+      this.showDialog({
+        title: '',
+        message: '分析内容为您订阅的关键词组,您<br />当前尚未订阅,请前往完善',
+        className: 'j-confirm-dialog text-center',
+        showConfirmButton: true,
+        showCancelButton: true,
+        confirmButtonText: '订阅管理',
+        confirmButtonColor: '#2abed1'
+      }).then(() => {
+        if (this.isSubCount) {
+          // 提示联系管理员
+          this.showToast('请联系管理员完善订阅的关键词')
+          // this.showDialog({
+          //   title: '',
+          //   message: '请联系管理员完善订阅的关键词',
+          //   className: 'j-confirm-dialog text-center',
+          //   showConfirmButton: true,
+          //   showCancelButton: false,
+          //   confirmButtonText: '我知道了',
+          //   confirmButtonColor: '#2abed1'
+          // })
+        } else {
+          this.toSubManage()
+        }
+      })
+    },
+    toSubManageButtonClick: function () {
+      if (this.isSubCount) {
+        this.showToast('请联系管理员完善订阅的关键词')
+      } else {
+        this.toSubManage()
+      }
+    },
+    toSubManage: function () {
+      this.isWeixin = utils.isWeiXinBrowser
+      let rootlink = 'f'
+      if (this.powerInfo.memberStatus > 0) {
+        rootlink = 'm'
+      } else if (this.powerInfo.vipStatus > 0) {
+        rootlink = 'v'
+      } else {
+        rootlink = 'f'
+      }
+      if(this.isWeixin) {
+        location.href = '/front/vipsubscribe/toSetKeyWordPage?vSwitch=' + rootlink
+      } else {
+        location.href = '/jyapp/vipsubscribe/toSetKeyWordPage?vSwitch=' + rootlink
+      }
+    },
+    toArticleContent (item) {
+      this.saveState()
+      location.href = `/jyapp/article/content/${item._id}.html`
+    },
+    toPortrait (id, type) {
+      if (!type || !id) return
+      this.saveState()
+      if (type === 'winner') {
+        location.href = `./ent_portrait?eId=${id}`
+      } else if (type === 'buyer') {
+        location.href = `./unit_portrayal?entName=${id}`
+      }
+    }
+  }
+})

+ 222 - 0
src/web/staticres/common-module/report-analysis/js/report_analysis_history.js

@@ -0,0 +1,222 @@
+var vm = new Vue({
+  delimiters: ['${', '}'],
+  el: '#analysis',
+  components: {
+    reportListMobileComponent: reportListMobileComponent
+  },
+  data: {
+    sessStorageKey: '$data-report_analysis_history',
+    tabActiveName: 'history', // analysis/history
+    tabList: [
+      {
+        label: '定制化市场分析',
+        name: 'analysis'
+      },
+      {
+        label: '历史报告',
+        name: 'history'
+      }
+    ],
+    tabConf: {
+      titleActiveColor: '#2ABED1',
+      titleInactiveColor: '#5F5E64',
+      lineWidth: '24',
+      color: '#2ABED1'
+    },
+    historyPageState: {
+      scrollTop: 0,
+      listState: {
+        refreshing: false,
+        loaded: false,
+        loading: false,
+        finished: false,
+        pageNum: 1,
+        pageSize: 10,
+        offset: 100,
+        list: []
+      }
+    }
+  },
+  computed: {
+    tabActive: function () {
+      var _this = this
+      var active = {}
+      this.tabList.some(function (item) {
+        var findThis = item.name === _this.tabActiveName
+        if (findThis)  {
+          active = item
+          return findThis
+        }
+      })
+      return active
+    }
+  },
+  created: function () {},
+  mounted: function () {
+    this.reStoreState()
+    utils.iosBackRefresh()
+  },
+  methods: {
+    showLoading: function () {
+      return this.$toast.loading({
+        duration: 0,
+        forbidClick: true,
+        message: 'loading...',
+      })
+    },
+    showToast: function (message) {
+      return this.$toast({
+        duration: 1500,
+        forbidClick: true,
+        message: message,
+      })
+    },
+    showDialog: function (conf) {
+      var defaultConf = {
+        title: '提示',
+        message: 'message',
+        className: 'j-confirm-dialog',
+        showConfirmButton: true,
+        showCancelButton: true,
+        confirmButtonText: '确定',
+        confirmButtonColor: '#2abed1'
+      }
+      if (conf) {
+        Object.assign(defaultConf, conf)
+      }
+      return this.$dialog.confirm(defaultConf)
+    },
+    setScrollTop: function (scrollTop) {
+      this.$nextTick(function () {
+        var wrapper = document.querySelector('.van-tabs__content')
+        wrapper.scrollTop = scrollTop
+      })
+    },
+    saveScrollTop: function () {
+      var wrapper = document.querySelector('.van-tabs__content')
+      if (wrapper.scrollTop) {
+        this.historyPageState.listState.scrollTop = parseInt(wrapper.scrollTop)
+      }
+    },
+    beforeTabChange: function (name) {
+      if (name !== this.tabActiveName) {
+        this.saveState()
+        this.goToAnalysis()
+      }
+      return false
+    },
+    goToAnalysis: function (id) {
+      var href = './report_analysis'
+      if (id) {
+        href += ('?id=' + id)
+      }
+      location.replace(href)
+    },
+    // 重置列表数据
+    resetHistoryState: function () {
+      var rState = {
+        refreshing: false,
+        loaded: false,
+        loading: false,
+        finished: false,
+        pageNum: 1,
+        pageSize: 10,
+        list: []
+      }
+
+      this.historyPageState.scrollTop = 0
+      Object.assign(this.historyPageState.listState, rState)
+    },
+    // 加载历史记录数据
+    onHistoryListLoad: function () {
+      var _this = this
+      var t = this.historyPageState.listState
+      var query = {
+        pageNum: t.pageNum,
+        pageSize: t.pageSize
+      }
+
+      t.loading = true
+
+      $.ajax({
+        type: 'POST',
+        url: '/bigmember/marketAnalysis/analysisHistory?t=' + Date.now(),
+        data: query,
+        success: function (res) {
+          if (res) {
+            // 判断是否为刷新
+            if (t.refreshing) {
+              t.list = []
+              t.refreshing = false
+            }
+
+            // 列表赋值
+            var list = res.res
+            if (Array.isArray(list)) {
+              _this.preSortList(list)
+              t.list = t.list.concat(list)
+            }
+
+            // 加载状态结束
+            t.loaded = true
+            t.loading = false
+
+            // 翻页
+            if (res.hasNextPage) {
+              t.pageNum++
+            } else {
+              t.finished = true
+            }
+          } else {
+            t.loaded = true
+            t.loading = false
+            t.finished = true
+            _this.$toast('请求失败')
+          }
+        },
+        error: function (error) {
+          console.log(error)
+        }
+      })
+    },
+    // 刷新历史记录数据
+    onHistoryListRefresh: function () {
+      var t = this.historyPageState.listState
+      // 重置数据
+      t.pageNum = 1
+      // 解除加载完成状态
+      t.finished = false
+      // 重新加载数据
+      // 将 loading 设置为 true,表示处于加载状态
+      t.loading = true
+      // 请求数据
+      this.onHistoryListLoad()
+    },
+    // 保存页面状态
+    saveState: function () {
+      this.saveScrollTop()
+      var $data = {
+        historyPageState: this.historyPageState
+      }
+      sessionStorage.setItem(this.sessStorageKey, JSON.stringify($data))
+    },
+    reStoreState: function () {
+      var $data = sessionStorage.getItem(this.sessStorageKey)
+      if ($data) {
+        $data = JSON.parse($data)
+        Object.assign(this.historyPageState, $data.historyPageState)
+
+        if (this.tabActiveName === 'history') {
+          setTimeout(function () {
+            // 恢复滚动高度
+            this.setScrollTop(this.historyPageState.scrollTop)
+          }.bind(this), 0)
+        }
+
+        sessionStorage.removeItem(this.sessStorageKey)
+      }
+
+      return $data
+    }
+  }
+})

文件差异内容过多而无法显示
+ 0 - 0
src/web/staticres/css/advanced/index.css


+ 288 - 0
src/web/staticres/css/advanced/index.scss

@@ -0,0 +1,288 @@
+.searchControl {
+
+  #jyChartCom {
+    background: #fff;
+    border-radius: 8px;
+
+    .advanced-pro-rec {
+      margin-top: 16px;
+
+      .custom-report {
+        padding: 0 16px 0 32px;
+      }
+
+      // 超前项目模块
+      $total-color: #2ABED1;
+      $new-color: #FF9F40;
+
+      .total-item {
+        line-height: 24px;
+        em {
+          font-weight: 700;
+          font-size: 20px;
+        }
+
+        & + .total-item {
+          margin-left: 72px;
+        }
+      }
+
+      .project-module {
+        font-weight: 400;
+        font-size: 14px;
+        line-height: 22px;
+        color: #1D1D1D;
+        padding: 24px 32px;
+        border-bottom: 1px solid #ECECEC;
+
+        &.remove-bl {
+          border-bottom-color: transparent;
+        }
+
+        .left-tag {
+          flex-shrink: 0;
+          display: inline-block;
+          font-size: 14px;
+          line-height: 24px;
+          color: #FFFFFF;
+          padding: 0 9px;
+          border-radius: 0 12px 12px 0;
+          margin-right: 24px;
+
+          &.total-color {
+            background: $total-color;
+          }
+
+          &.new-color {
+            background: $new-color;
+          }
+        }
+
+        .project-item {
+          width: 100%;
+          display: flex;
+          flex-direction: row;
+          align-items: center;
+
+          & + .project-item {
+            margin-top: 18px;
+          }
+        }
+
+        .new-group {
+          display: flex;
+          flex-direction: row;
+          width: 100%;
+        }
+
+        .new-item {
+          cursor: pointer;
+          font-size: 16px;
+          line-height: 24px;
+          max-width: calc(50% - 72px);
+
+          & + .new-item {
+            margin-left: 36px;
+          }
+
+          &::before {
+            content: "";
+            display: inline-block;
+            vertical-align: middle;
+            width: 7px;
+            height: 7px;
+            border-radius: 50%;
+            margin-right: 8px;
+            background: $new-color;
+          }
+        }
+      }
+
+      .p-lr-32 {
+        padding: 0 16px 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-up-or-down {
+        margin-left: 32px;
+        .el-icon--right {
+          margin-left: 2px;
+        }
+
+        .el-button--text {
+          padding: 0;
+          font-weight: 400;
+          font-size: 14px;
+          line-height: 19px;
+          color: #686868;
+          border: none !important;
+        }
+      }
+
+      .c-view-interest {
+        margin-left: 36px;
+        background: #2ABED1;
+        color: #fff;
+        border: 1px solid #2ABDD1;
+      }
+
+      .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;
+      }
+    }
+  }
+
+  .advanced-dialog {
+      width: 370px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      border-radius: 8px;
+
+      .el-dialog__body {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+      }
+
+      .el-dialog__close {
+        font-size: 20px;
+        font-weight: bold;
+        color: #2ABDD1;
+        cursor: pointer;
+      }
+
+      .el-dialog__header,
+      .el-dialog__body {
+        padding: 0;
+      }
+
+      &--head {
+        margin-top: -58px;
+        max-width: 100%;
+      }
+
+      &--qrcode {
+        margin-top: 26px;
+        margin-bottom: 22px;
+        width: 154px;
+        height: 154px;
+      }
+
+      &--info {
+        padding: 24px 20px;
+        padding-top: 0;
+
+        h4 {
+          font-weight: 400;
+          font-size: 16px;
+          line-height: 24px;
+          text-align: center;
+          color: #1D1D1D;
+        }
+
+        p {
+          margin-top: 16px;
+          font-weight: 400;
+          font-size: 12px;
+          line-height: 18px;
+          text-align: center;
+          color: #999999;
+        }
+      }
+  }
+
+  #jyChartCom .custom-analysis-report {
+    padding: 0 16px 0 32px;
+  }
+  #jyChartCom .advanced-pro-rec {
+    padding: 0;
+  }
+}

+ 103 - 0
src/web/staticres/css/dev2/superSearch-inside.css

@@ -392,3 +392,106 @@ input, textarea {
 #hasNoData_tiptext .tip-text-for-group .tip-text-for-search {
   color: #2ABED1;
 }
+
+#jyChartCom{
+  background: #fff;
+  border-radius: 8px;
+}
+
+#jyChartCom .advanced-pro-rec, #jyChartCom .custom-analysis-report{
+  padding: 0 32px;
+}
+
+
+#jyChartCom .c-a-r-top {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 60px;
+  border-bottom: 1px dashed #E0E0E0;
+}
+
+#jyChartCom .c-a-r-top .c-a-r-title{
+  display: flex;
+  align-items: center;
+  height: 100%;
+  line-height: 21px;
+  font-family: 'Microsoft YaHei';
+  font-style: normal;
+  font-weight: 400;
+}
+#jyChartCom .c-a-r-top .c-a-r-title .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;
+}
+#jyChartCom .c-a-r-top .r-title-tip{
+  margin-top: 5px;
+  margin-left: 32px;
+  color: #686868;
+  font-size: 14px;
+}
+
+#jyChartCom .c-a-r-option{
+  display: flex;
+  align-items: center;
+}
+
+#jyChartCom .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;
+}
+#jyChartCom .c-view-report{
+  border: 1px solid #2ABED1;
+  color: #2ABED1;
+}
+
+#jyChartCom .c-view-interest{
+  margin-left: 36px;
+  background: #2ABED1;
+  color: #fff;
+}
+
+#jyChartCom .c-a-r-chart{
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-top: 16px;
+}
+.chart-common{
+  /* width: 590px; */
+  height: 280px;
+}
+
+.c-c-content{
+  width: 383px;
+  height: 211px;
+}
+.c-c-content.chart-line {
+  width: 558px;
+}
+
+#jyChartCom .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;
+}

二进制
src/web/staticres/images/advanced/dialog-head.png


二进制
src/web/staticres/images/advanced/dialog-qrcode.png


+ 3 - 3
src/web/staticres/js/pc-collect-user-info.js

@@ -534,7 +534,7 @@ var vm = new Vue({
           this.dialogTitleTop = '完善信息'
         } else if (source === 'article_proposed_project' || source === 'article_purchase_intention') {
           this.dialogTitle = text
-          this.dialogTitleTop = '欢迎体验剑鱼超前项目预测'
+          this.dialogTitleTop = '欢迎体验剑鱼大会员'
         }
         // else if (source.indexOf("article_collection") > -1){
         //   this.dialogTitle = text
@@ -591,7 +591,7 @@ var vm = new Vue({
             var checkKeys = ['name', 'phone','companyType', 'company', 'branch', 'position']
 
           }
-          
+
           var sourceList = ['article_collection', 'article_original', 'jyarticle_see3_plus_app', 'jyarticle_see3_plus_pc', 'jyarticle_see3_plus_wx', 'jypush_see10_plus_app', 'jypush_see10_plus_wx']
           var isCollect = sourceList.includes(source)
           if (infoid != ""){
@@ -648,7 +648,7 @@ var vm = new Vue({
                 _this.curDom = dom
               } else {
                 callback && callback(res)
-              }              
+              }
             } else {
               callback && callback(res)
             }

+ 574 - 0
src/web/templates/big-member/wx/page_report_analysis.html

@@ -0,0 +1,574 @@
+<!DOCTYPE html>
+<html lang="zh-CN" style="font-size: 50px;">
+<head>
+    <title>定制化市场分析报告 </title>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta name="format-detection" content="telephone=yes"/>
+    <meta name="apple-mobile-web-app-status-bar-style" content="black">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <script src="/big-member/js/rem.js"></script>
+    <!--S-当前页面的css资源-->
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/reset-css/5.0.1/reset.min.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/style.min.css />
+    <!--E-当前页面的css资源-->
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/public.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/j-icons.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/collection/css/index.css?v={{Msg "seo" "version"}}'/>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/report-analysis/css/report_analysis.css?v={{Msg "seo" "version"}}' />
+    <style>
+      /* fix: --- 弹窗组件不能显示底部问题  */
+      .report-popup .j-main.unitTab {
+        height: unset;
+      }
+      .collection .unitTab {
+        flex: 1;
+      }
+      .example-title{
+        padding: .32rem .32rem .12rem;
+        font-size: .36rem;
+        line-height: .52rem;
+        color: #171826;
+        font-weight: bold;
+        background-color: #fcfcfd;
+      }
+      .vip_openDialog{
+        margin-top: 0.92rem 0 .6rem;
+        width: 6.06rem;
+        background: url(/big-member/image/openVip.png) no-repeat;
+        background-size: 100% 100%;
+        box-sizing: border-box;
+      }
+      .vip_openDialog .goBtn{
+        margin-bottom: .48rem;
+      }
+      .vip_extend{
+        padding: .16rem 0 0;
+        line-height: .4rem;
+        color: #171826;
+      }
+      .vip_component {
+        margin-top: .16rem;
+        flex-direction: column;
+      }
+
+      .vip_component .example-title {
+        width: 100%;
+        min-height: .96rem;
+        background: #fcfcfd;
+        font-size: .36rem;
+      }
+      .vip_component .chart_com{
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        height: inherit;
+      }
+    </style>
+</head>
+<body>
+  <div class="j-container">
+    <div class="j-main" id="analysis" v-cloak>
+      <div class="j-container">
+          <van-tabs
+              class="analysis-tab"
+              :title-active-color="tabConf.titleActiveColor"
+              :title-inactive-color="tabConf.titleInactiveColor"
+              :line-width="tabConf.lineWidth"
+              :color="tabConf.color"
+              :before-change="beforeTabChange"
+              v-model="tabActiveName">
+              <van-tab
+                  v-for="(tab, index) in tabList"
+                  :key="index"
+                  :title="tab.label"
+                  :name="tab.name"></van-tab>
+          </van-tabs>
+          <section v-show="tabActiveName === 'analysis'" class="j-main analysis-content">
+              <div class="j-container search-filters bg-white" v-show="!rid">
+                  <div class="j-main">
+                      <div class="height8">height8</div>
+                      <div class="filters-title pd-lr16">
+                          <span>分析条件</span>
+                      </div>
+                      <van-cell-group class="filters-list">
+                          <van-cell center title="分析内容" is-link value-class="ellipsis" :value="resolveSelected('keys')" @click="clickCell('keys')"></van-cell>
+                          <van-cell center title="区域" is-link value-class="ellipsis" :value="resolveSelected('area')" @click="clickCell('area')"></van-cell>
+                          <van-cell center title="行业" is-link value-class="ellipsis" :value="resolveSelected('industry')" @click="clickCell('industry')"></van-cell>
+                          <van-cell center title="采购单位类型" value-class="ellipsis" is-link :value="resolveSelected('buyerclass')" @click="clickCell('buyerclass')"></van-cell>
+                          <div class="date-cell collection">
+                              <div class="cell-title">时间</div>
+                              <date-component
+                                  ref="dateSelector"
+                                  popup-container="body"
+                                  :diy="true"
+                                  :times="timeOptions"></date-component>
+                          </div>
+                      </van-cell-group>
+                      <div class="empty-container analysis-empty" v-show="emptyShow">
+                          <div class="empty-content-position">
+                              <div class="image">
+                                  <img src='/common-module/public/image/jy-sleep.png'>
+                              </div>
+                              <div class="empty-main tip-text" v-html="empty.msg"></div>
+                          </div>
+                      </div>
+                  </div>
+                  <div class="j-footer j-button-group">
+                      <button class="j-button-cancel" @click="resetAllFilters">重置</button>
+                      <button class="j-button-confirm" @click="startAnalysis">开始分析</button>
+                  </div>
+              </div>
+              <div class="j-container search-result" v-show="!filtersPageShow && rid">
+                  <div class="j-main">
+                      <div class="height8">height8</div>
+                      <van-cell-group class="filters-list">
+                          <van-cell center title="分析条件" is-link @click="toAnalysisPage"></van-cell>
+                      </van-cell-group>
+                      <div class="height8" v-show="false"></div>
+                      <section class="section bg-white dimension">
+                          <div class="section-title"> - 分析维度 -</div>
+                          <van-sticky class="section-sticky" z-index="99999999" :offset-top="stickyOffset">
+                              <div class="section-content dimension-list bg-white">
+                                  <div
+                                      class="j-button j-button-item dimension-item"
+                                      v-for="(item, index) in dimensionList"
+                                      :key="index"
+                                      v-text="item.name"
+                                      :class="{ active: item.id === activeDimension }"
+                                      @click="anchorTo(item)"
+                                  ></div>
+                              </div>
+                          </van-sticky>
+                          <div class="section-footer section-tip-text">
+                              <span>数据统计范围:</span>
+                              <span v-text="formatSelectTime(reportFilters.selectTime)"></span>
+                          </div>
+                      </section>
+                      <!-- 市场概况 -->
+                      <section class="section bg-white market-overview" id="market" v-if="getStatus">
+                          <div class="section-title pd-16">市场概况</div>
+                          <div class="section-content market-overview-list">
+                              <div
+                                  class="market-overview-item"
+                                  v-for="(item, index) in sections.market.overview"
+                                  :key="index">
+                                  <span class="m-overview-name">${ item.label }</span>
+                                  <span class="m-overview-unit">(${ item.unit })</span>
+                                  <span class="m-overview-count">${ item.count }</span>
+                                  <span class="m-overview-type" v-if="item.ringRatio">环比</span>
+                                  <span
+                                      class="m-overview-ratio"
+                                      v-show="overviewRateTotal"
+                                      :class="{
+                                          red: item.ringRatio > 0,
+                                          green: item.ringRatio < 0
+                                      }">
+                                      <van-icon name="down" :class="{ 'icon-reverse': item.ringRatio >= 0 }" v-if="item.ringRatio"></van-icon>
+                                      <span>${ item.ringRatio ? (Math.abs(item.ringRatio) + '%') : '-' }</span>
+                                  </span>
+                              </div>
+                          </div>
+                          <div class="section-footer section-tip-text pd-16">
+                              环比:统计学术语,是表示连续2个统计周期(比如连<br />续两月)内的量的变化比。
+                          </div>
+                      </section>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:8.84rem">
+                        <p class="example-title">市场概况</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/01-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_1" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/01.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 项目规模分布 -->
+                      <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.dataAlready && getStatus">
+                          <div class="section-title">项目规模分布</div>
+                          <div class="section-content">
+                              <project-scatter :chart-data="sections.projectScatter.chartData"></project-scatter>
+                          </div>
+                      </section>
+                      <!-- 项目规模TOP10 -->
+                      <section class="section bg-white pd-16 project-scatter" v-if="sections.projectScatter.tableData.length && getStatus">
+                          <div class="section-title">项目规模TOP10</div>
+                          <div class="section-content project-top-list">
+                              <div
+                                  class="project-top-item"
+                                  v-for="(item, index) in sections.projectScatter.tableData"
+                                  :key="index">
+                                  <div class="p-t-i-hd">
+                                      <div
+                                          class="p-t-i-hd-l table-index-rect"
+                                          :class="{
+                                              red: index === 0,
+                                              orange: index === 1,
+                                              'soft-orange': index === 2
+                                          }">
+                                          ${ index + 1 }</div>
+                                      <div class="p-t-i-hd-r" @click="toArticleContent(item)">
+                                          <div class="project-name">${ item.projectname }</div>
+                                          <div class="project-info">
+                                              <div class="project-tags">
+                                                  <div class="j-tag tag-orange" v-if="item.sortprice">项目金额:${ item.sortprice }万元</div>
+                                                  <div class="j-tag tag-plain" v-if="item.area">${ item.area }</div>
+                                                  <div class="j-tag tag-plain" v-if="item.city">${ item.city }</div>
+                                              </div>
+                                              <div class="project-right">${ item.jgtime }</div>
+                                          </div>
+                                      </div>
+                                  </div>
+                                  <div class="p-t-i-ft" v-if="item.winner_s.length">
+                                      <div class="p-t-i-ft-title">中标单位</div>
+                                      <div
+                                          class="p-t-i-ft-winner"
+                                          :class="{ disabled: !winner.id }"
+                                          v-for="(winner, i) in item.winner_s"
+                                          :key="index"
+                                          v-text="winner.name"
+                                          @click="toPortrait(winner.id, 'winner')"></div>
+                                  </div>
+                              </div>
+                          </div>
+                      </section>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:11.38rem">
+                        <p class="example-title">项目规模分布</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/02-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_2" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/02.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 时间分布 -->
+                      <section class="section bg-white pd-16 time-scatter" v-if="sections.timeScatter.dataAlready">
+                          <div class="section-header">
+                              <div class="section-title">时间分布</div>
+                              <div class="section-actions">
+                                  <div
+                                      class="action-button"
+                                      :class="{ active: sections.timeScatter.activeAction == 'month' }"
+                                      @click="sections.timeScatter.activeAction = 'month'">
+                                      月度数据</div>
+                                  <div
+                                      class="action-button"
+                                      :class="{ active: sections.timeScatter.activeAction == 'year' }"
+                                      @click="sections.timeScatter.activeAction = 'year'">
+                                      年度数据</div>
+                              </div>
+                          </div>
+                          <div class="section-content">
+                              <div class="sub-section-content">
+                                  <market-time-scatter width="100%" :chart-data="sections.timeScatter[sections.timeScatter.activeAction].count"></market-time-scatter>
+                              </div>
+                              <div class="sub-section-content">
+                                  <market-time-scatter width="100%" :chart-data="sections.timeScatter[sections.timeScatter.activeAction].amount"></market-time-scatter>
+                              </div>
+                          </div>
+                      </section>
+                      <!-- 地区分布 -->
+                      <div class="section bg-white pd-16 area-scatter" v-if="sections.areaScatter.dataAlready && notOneAreaFilter && getStatus">
+                          <div class="section-title">地区分布</div>
+                          <div class="section-content">
+                              <market-area-scatter :chart-data="sections.areaScatter.chartData"></market-area-scatter>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.areaScatter.projectCountTop3 && getStatus">
+                          <div class="section-title">项目数量TOP3地区的重点中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.areaScatter.projectCountTop3" type="count" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.areaScatter.projectAmountTop3 && getStatus">
+                          <div class="section-title">项目金额TOP3地区的重点中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.areaScatter.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:13.08rem">
+                        <p class="example-title">地区分布</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/03-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_3" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/03.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 客户分布 -->
+                      <div class="section bg-white pd-16 user-scatter" v-if="sections.userScatter.list.length">
+                          <div class="section-title">客户分布</div>
+                          <div class="section-content">
+                              <market-user-scatter :chart-data="sections.userScatter.list"></market-user-scatter>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.userScatter.projectCountTop3">
+                          <div class="section-title">项目数量TOP3客户类型的重点中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.userScatter.projectCountTop3" type="count" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.userScatter.projectAmountTop3">
+                          <div class="section-title">项目金额TOP3客户类型的重点中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.userScatter.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <!-- 细分市场 - 项目数量 -->
+                      <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready && getStatus">
+                          <div class="section-title">细分市场 - 项目数量</div>
+                          <div class="section-content">
+                              <market-segment :chart-data="sections.market.refine.projectCountData" type="count"></market-segment>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.market.refine.projectCountTop3 && getStatus">
+                          <div class="section-title">细分市场的重点中标单位-项目数量</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.market.refine.projectCountTop3" type="count" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">细分市场 - 项目数量</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/04-2-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_4_1" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/04-2.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 细分市场 - 项目金额 -->
+                      <div class="section bg-white pd-16 market-refine" v-if="sections.market.refine.dataAlready && getStatus">
+                          <div class="section-title">细分市场 - 项目金额</div>
+                          <div class="section-content">
+                              <market-segment :chart-data="sections.market.refine.projectAmountData" type="amount"></market-segment>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.market.refine.projectAmountTop3 && getStatus">
+                          <div class="section-title">细分市场的重点中标单位-项目金额</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.market.refine.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">细分市场 - 项目金额</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/04-1-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_4_2" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/04-1.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 采购规模分布 -->
+                      <div class="section bg-white pd-16 buyerclass-scatter" id="buyer" v-if="sections.buyerclass.dataAlready">
+                          <div class="section-title">采购规模分布</div>
+                          <div class="section-content">
+                              <line-chart-scatter :chart-data="sections.buyerclass.chartData"></line-chart-scatter>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.buyerclass.projectCountTop3 && getStatus">
+                          <div class="section-title">项目数量TOP3采购单位及其重点合作中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.buyerclass.projectCountTop3" type="count" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">项目数量TOP3采购单位及其重点合作中标单位</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/05-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_5" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/05.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.buyerclass.projectAmountTop3 && getStatus">
+                          <div class="section-title">采购金额TOP3采购单位及其重点合作中标单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.buyerclass.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">采购金额TOP3采购单位及其重点合作中标单位</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/06-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_6" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/06.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <!-- 中标规模分布 -->
+                      <div class="section bg-white pd-16 winner-scatter" id="winner" v-if="sections.winner.dataAlready">
+                          <div class="section-title">中标规模分布</div>
+                          <div class="section-content">
+                              <line-chart-scatter :chart-data="sections.winner.chartData"></line-chart-scatter>
+                          </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.winner.projectCountTop3 && getStatus">
+                          <div class="section-title">项目数量TOP3中标单位及其重点合作采购单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.winner.projectCountTop3" type="count" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">项目数量TOP3中标单位及其重点合作采购单位</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/07-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_7" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/07.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                      <div class="section bg-white pd-16" v-if="sections.winner.projectAmountTop3 && getStatus">
+                          <div class="section-title">中标金额TOP3中标单位及其重点合作采购单位</div>
+                          <div class="section-content">
+                              <market-top3-table :table-data="sections.winner.projectAmountTop3" type="amount" @save="saveState"></market-top3-table>
+                          </div>
+                      </div>
+                      <div class="vip_component"
+                        v-if="!getStatus"
+                        style="height:10.8rem">
+                        <p class="example-title">中标金额TOP3中标单位及其重点合作采购单位</p>
+                        <div class="chart_com" style="background:url('/common-module/report-analysis/image/08-bg.png?v={{Msg "seo" "version"}}') no-repeat;background-size:100% 100%">
+                          <chart-example type="item_8" imgurl='{{Msg "seo" "cdn"}}/common-module/report-analysis/image/08.png?v={{Msg "seo" "version"}}'>
+                          </chart-example>
+                        </div>
+                      </div>
+                  </div>
+                  <div class="fixed-bottom-right clickable scroll-to-top" style="display: none;">
+                      <van-icon name="arrow-up"></van-icon>
+                  </div>
+              </div>
+          </section>
+      </div>
+      <van-popup
+          v-model="filterDialogShow.keys"
+          closeable
+          round
+          position="bottom"
+          close-icon="clear"
+          class="j-popup collection"
+          overlay-class="j-overlay"
+          :lazy-render="false"
+          :style="{ height: '60%' }"
+          get-container="body">
+          <div class="j-container keys-popup">
+              <div class="popup-header">
+                  <div class="header-top">
+                      <div class="header-title">选择分析内容</div>
+                      <div class="header-action" @click="toSubManageButtonClick">订阅管理</div>
+                  </div>
+                  <div class="header-bottom">注:如需新增分析内容,请完善您的订阅关键词</div>
+              </div>
+              <div class="j-main">
+                  <keyword-component
+                      ref="keywordSelector"
+                      protype="bigmember"
+                      :use-key-card="true"
+                      @nokeys="showSetKeyTip"
+                      @cancel="cancel($event, 'keys')"
+                      @confirm="confirm($event, 'keys')"
+                      :selectkeywordlist="filters.selectKeysArr"></keyword-component>
+              </div>
+          </div>
+      </van-popup>
+      <van-popup
+          v-model="filterDialogShow.area"
+          closeable
+          round
+          position="bottom"
+          close-icon="clear"
+          :lazy-render="false"
+          class="j-popup collection"
+          overlay-class="j-overlay"
+          :style="{ height: '60%' }"
+          get-container="body">
+          <div class="j-container report-popup">
+              <div class="popup-header header-title">选择区域</div>
+              <div class="j-main">
+                  <area-city-mobile
+                      ref="areaCitySelector"
+                      @cancel="cancel($event, 'area')"
+                      @confirm="confirm($event, 'area')"></area-city-mobile>
+              </div>
+          </div>
+      </van-popup>
+      <van-popup
+          v-model="filterDialogShow.industry"
+          closeable
+          round
+          position="bottom"
+          close-icon="clear"
+          class="j-popup collection"
+          overlay-class="j-overlay"
+          :lazy-render="false"
+          :style="{ height: '60%' }"
+          get-container="body">
+          <div class="j-container report-popup">
+              <div class="popup-header header-title">选择行业</div>
+              <div class="j-main">
+                  <industry-component
+                      ref="industrySelector"
+                      :selectindustrylist="filters.industry"
+                      @cancel="cancel($event, 'industry')"
+                      @confirm="confirm($event, 'industry')"></industry-component>
+              </div>
+          </div>
+      </van-popup>
+      <van-popup
+          v-model="filterDialogShow.buyerclass"
+          closeable
+          round
+          position="bottom"
+          close-icon="clear"
+          class="j-popup collection"
+          :lazy-render="false"
+          overlay-class="j-overlay"
+          :style="{ height: '60%' }"
+          get-container="body">
+          <div class="j-container report-popup">
+              <div class="popup-header header-title">选择采购单位类型</div>
+              <div class="j-main">
+                  <cate-component
+                      ref="buyerclassSelector"
+                      :selectcatelist="filters.buyerclass"
+                      @cancel="cancel($event, 'buyerclass')"
+                      @confirm="confirm($event, 'buyerclass')"></cate-component>
+              </div>
+          </div>
+      </van-popup>
+  </div>
+</div>
+<script src=//cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/jquery/3.6.0/jquery.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/vant.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/zepto/1.2.0/zepto.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/lodash/4.17.21/lodash.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>
+<script src='{{Msg "seo" "cdn"}}/big-member/js/utils.js?v={{Msg "seo" "version"}}'></script>
+
+<script src='{{Msg "seo" "cdn"}}/common-module/public/js/china-map-data.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/keyword-mobile.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/date-mobile.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/area-city-mobile.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/industry-mobile.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/cate-mobile.js?v={{Msg "seo" "version"}}'></script>
+
+<script src='{{Msg "seo" "cdn"}}/big-member/js/echarts_option.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/echarts_option.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/collection/js/analysis-report-example.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/projectScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/marketTimeScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/marketAreaScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/marketTop3Table.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/marketUserScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/marketSegment.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/components/lineChartScatter.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/report_analysis.js?v={{Msg "seo" "version"}}'></script>
+{{include "/common/baiducc.html"}}
+</body>
+</html>

+ 58 - 0
src/web/templates/big-member/wx/page_report_analysis_history.html

@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="zh-CN" style="font-size: 50px;">
+<head>
+    <title>定制化市场分析报告 </title>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta name="format-detection" content="telephone=yes"/>
+    <meta name="apple-mobile-web-app-status-bar-style" content="black">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <script src="/big-member/js/rem.js"></script>
+    <!--S-当前页面的css资源-->
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/reset-css/5.0.1/reset.min.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/style.min.css />
+    <!--E-当前页面的css资源-->
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/public.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/j-icons.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/report-analysis/css/report_analysis.css?v={{Msg "seo" "version"}}' />
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/diy-report/css/report-list.css?v={{Msg "seo" "version"}}' />
+</head>
+<body>
+  <div class="j-container">
+    <div class="j-main" id="analysis" v-cloak>
+      <div class="j-container">
+          <van-tabs
+              :title-active-color="tabConf.titleActiveColor"
+              :title-inactive-color="tabConf.titleInactiveColor"
+              :line-width="tabConf.lineWidth"
+              :color="tabConf.color"
+              :before-change="beforeTabChange"
+              v-model="tabActiveName">
+              <van-tab
+                  v-for="(tab, index) in tabList"
+                  :key="index"
+                  :title="tab.label"
+                  :name="tab.name"></van-tab>
+          </van-tabs>
+          <section v-show="tabActiveName === 'analysis'" class="j-main analysis-content"></section>
+          <section v-show="tabActiveName === 'history'" class="j-main history-content">
+              <report-list-mobile-component ref="list" @go-report="goToAnalysis"></report-list-mobile-component>
+          </section>
+      </div>
+  </div>
+</div>
+<script src=//cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/vant.min.js></script>
+<script src=//cdn-common.jianyu360.com/cdn/lib/zepto/1.2.0/zepto.min.js></script>
+<script src='{{Msg "seo" "cdn"}}/big-member/js/utils.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/diy-report/js/report-list.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/report-analysis/js/report_analysis_history.js?v={{Msg "seo" "version"}}'></script>
+
+{{include "/common/baiducc.html"}}
+</body>
+</html>

+ 411 - 15
src/web/templates/pc/supsearch.html

@@ -21,8 +21,10 @@
 <link href='{{Msg "seo" "cdn"}}/css/collect-user-info.css?v={{Msg "seo" "version"}}' rel="stylesheet">
 <link href='{{Msg "seo" "cdn"}}/css/ele-reset.css?v={{Msg "seo" "version"}}' rel="stylesheet">
 <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/css/selector/selector.css?v={{Msg "seo" "version"}}'>
+<link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/style.min.css />
 <!-- 原页面head内写的样式 移至superSearch-inside.css里 写到页面里打脸 -->
 <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/css/dev2/superSearch-inside.css?v={{Msg "seo" "version"}}'>
+<link rel="stylesheet" href='{{Msg "seo" "cdn"}}/css/advanced/index.css?v={{Msg "seo" "version"}}'>
 <script src='{{Msg "seo" "cdn"}}/common-module/selector/js/industryMap.js?v={{Msg "seo" "version"}}'></script>
 <script>
   // var vipState = {{.T.showVipScreen}}; //是否是超级订阅用户
@@ -784,11 +786,11 @@ var IframeOnClick = {
           供应搜索
         </a> -->
         <a id="entsearch" href="javascript:;" left="98" onclick="tab_serch('/jylab/entSearch/index.html')">
-        
+
           企业搜索
 				</a>
         <a id="pursearch" href="javascript:;"  left="201"  onclick="tab_serch('/jylab/purSearch/index.html')">
-         
+
           采购单位搜索
         </a>
         <a id="gysearch"  href="javascript:;" onclick="tab_serch('/swordfish/page_web_pc/search/issued')">
@@ -1084,6 +1086,101 @@ var IframeOnClick = {
         <span>更多选项</span>
         <i class="icon-arrow"></i>
       </div>
+    </div>
+    <!-- 超前项目推荐&&定制化分析报告 -->
+    <div id="jyChartCom" class="w">
+      <div class="advanced-pro-rec" v-show="advancedInfo.show">
+        <div class="p-lr-32">
+          <div class="c-a-r-top">
+            <div class="c-a-r-title">
+              <div class="r-title-text">${getNowInfo.title}</div>
+              <div class="r-title-tip">
+                <span v-if="advancedInfo.showContent || getNotModuleDataStatus">${getNowInfo.desc}</span>
+                <span v-else class="total-item" v-for="(item, index) in advancedInfo.briefList" :key="index">
+                      ${item.key}:<span class="com-highlight"><em>${item.value}</em>条</span>
+                    </span>
+              </div>
+            </div>
+            <div class="c-a-r-option">
+              <div v-if="nowModuleName === '定制化分析报告'" class="c-view-report c-view-common" @click="goToReport">查看完整报告</div>
+              <div class="c-view-interest c-view-common" @click="onClickInterested(nowModuleName === '定制化分析报告' ? 'B' : 'A')">感兴趣点我</div>
+              <div class="c-up-or-down" @click="toggleAdvancedContent()">
+                <el-button type="text">
+                  ${ advancedInfo.showContent ? '收起' : '展开'}
+                  <i class="el-icon--right" :class="'el-icon-arrow-' + (advancedInfo.showContent ? 'up' : 'down')"></i>
+                </el-button>
+              </div>
+            </div>
+          </div>
+        </div>
+        <el-collapse-transition>
+          <div v-show="advancedInfo.showContent">
+            <!-- 超前项目 -->
+            <div class="project-module" v-if="nowModuleName === '超前项目推荐'" :class="{ 'remove-bl': !getShowChart }">
+              <div class="project-item">
+                <div class="left-tag total-color">累计发布</div>
+                <div>
+                    <span class="total-item" v-for="(item, index) in advancedInfo.briefList" :key="index">
+                      ${item.key}:<span class="com-highlight"><em>${item.value}</em>条</span>
+                    </span>
+                </div>
+              </div>
+              <div class="project-item">
+                <div class="left-tag new-color">最新项目</div>
+                <div class="new-group">
+                  <span class="ellipsis new-item" @click="goToContent(item)" v-for="(item, index) in advancedInfo.projectList" :key="index" v-html="getProjectTitle(item)"></span>
+                </div>
+              </div>
+            </div>
+            <!-- 定制化分析报告 -->
+            <!-- 定制化分析报告 -->
+            <div class="custom-analysis-report">
+              <div class="c-a-r-top" v-if="nowModuleName === '超前项目推荐'">
+                <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" @click="goToReport">查看完整报告</div>
+                  <div class="c-view-interest c-view-common" @click="onClickInterested('B')">感兴趣点我</div>
+                </div>
+              </div>
+              <div class="c-a-r-chart">
+                <div class="chart-common" id="customerChart" style="display: none;">
+                  <div class="chart-title">客户分布:</div>
+                  <div class="c-c-content">
+                    <div id="chartTreeMap"></div>
+                  </div>
+                </div>
+                <div class="chart-common" id="winnerChart" style="display: none;">
+                  <div class="chart-title">中标规模分布:</div>
+                  <div class="c-c-content chart-line">
+                    <div id="chartLineChart"></div>
+                  </div>
+                </div>
+                <div class="chart-common" id="buyerChart" style="display: none;">
+                  <div class="chart-title">采购规模分布:</div>
+                  <div class="c-c-content chart-line">
+                    <div id="chartLineChartBuyer"></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+<!--            <custom-report :show-title="nowModuleName === '超前项目推荐'" @on-report="goToReport" @on-interset="onClickInterested('B')" v-if="getShowChart" :chartCustomData="chartCustomData"></custom-report>-->
+          </div>
+        </el-collapse-transition>
+      </div>
+      <el-dialog custom-class="advanced-dialog" :visible.sync="advancedInfo.showDialog">
+        <img class="advanced-dialog--head" src='{{Msg "seo" "cdn"}}/images/advanced/dialog-head.png?v={{Msg "seo" "version"}}' alt="剑鱼标讯">
+        <img class="advanced-dialog--qrcode" src='{{Msg "seo" "cdn"}}/images/advanced/dialog-qrcode.png?v={{Msg "seo" "version"}}' alt="扫码联系客服">
+        <div class="advanced-dialog--info">
+          <h4>扫码联系客服</h4>
+          <h4>${advancedInfo.dialogContent}</h4>
+          <p>专业招投标大数据服务平台丨国家信息中心大数据战略合作商</p>
+        </div>
+      </el-dialog>
     </div>
 		<!--招标搜索列表内容-->
 		<div class="seaTender-inner w" style="position: relative;">
@@ -1405,7 +1502,10 @@ var IframeOnClick = {
 <script src='{{Msg "seo" "cdn"}}/js/selector/area-city-pc.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Msg "seo" "cdn"}}/js/pc-collect-user-info.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Msg "seo" "cdn"}}/common-module/selector/js/buyerClass.js?v={{Msg "seo" "version"}}'></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>
+<script src=//cdn-common.jianyu360.com/cdn/lib/lodash/4.17.21/lodash.min.js></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/chart-module/js/chart-common.js?v={{Msg "seo" "version"}}'></script>
 <script type="text/javascript">
 $(function(){
   if(!loginflag){//未登录隐藏
@@ -1413,7 +1513,7 @@ $(function(){
     $('.nologin-hide').addClass('hide')
     $('.city-list-divide').addClass('hide')
     $('#sideIcon').addClass('hide')
-    searchInnerVue.$refs.areaRefs.shoWcity=false//隐藏地市 
+    searchInnerVue.$refs.areaRefs.shoWcity=false//隐藏地市
   }
   window.loginCallback = function () {//登录成功回调
     $('#go-customer-4').removeClass('hide')
@@ -1425,9 +1525,9 @@ $(function(){
     if(!goTemplateData.inIframe){//不在工作桌面去工作桌面
       var formNode_ = $('#zbSeatchT')
       var goHref_ = location.origin + '/jylab/supsearch/index.html'
-      window.location.replace('/page_workDesktop/work-bench/page?link=' + encodeURIComponent(goHref_ + '?' + formNode_.serialize()))  
+      // window.location.replace('/page_workDesktop/work-bench/page?link=' + encodeURIComponent(goHref_ + '?' + formNode_.serialize()))
     }
-    
+
   }
   // 排除词
   $(".not-key-group input").on('focus', function () {
@@ -1488,7 +1588,7 @@ $(function(){
         } else {
           $("#pursearch").css('display', 'none')
         }
-    }   
+    }
   }
   })
 
@@ -1874,7 +1974,7 @@ $(function(){
   })
 })
 function tab_serch (actionHref) {
- 
+
   if(loginflag){
     if(goTemplateData.inIframe){//在工作桌面中维持以前跳转方式
 
@@ -1889,12 +1989,12 @@ function tab_serch (actionHref) {
     }
     default: {
       var goHref = location.origin + actionHref
-      window.location.href = '/page_workDesktop/work-bench/page?link=' + goHref  
+      window.location.href = '/page_workDesktop/work-bench/page?link=' + goHref
       break
     }
   }
     }
-     
+
   }else{
     $('#bidLogin').modal("show");
 
@@ -2096,7 +2196,7 @@ function checkVisited (val) {
         )
       )
       }
-      
+
     } catch (error) {}
     if (visited) {
       $this.addClass('visited').parents('.liLuceneList').addClass('visited')
@@ -2295,10 +2395,54 @@ if(sessionselect){
         beforeCitySelected: this.beforeCitySelectedFn,
         filterInkey: '',
         noAuth: false,
-        islogin:false
+        islogin:false,
+        chartTitle: '',
+        chartCustomData: {},
+        advancedInfo: {
+          show: false,
+          showContent: false,
+          showDialog: false,
+          dialogContent: '体验超前项目推荐服务!',
+          moduleInfo: {
+            超前项目推荐: {
+              title: '超前项目推荐',
+              desc: '提前推送超前项目,优先对接项目负责人'
+            },
+            定制化分析报告: {
+              title: '定制化分析报告',
+              desc: '量身定制个性化报告,分析市场竞争格局,为企业找准市场机会!'
+            }
+          },
+          briefList: [],
+          projectList: []
+        }
       }
     },
     computed: {
+      // 当前第一位展示内容标识
+      nowModuleName () {
+        if (this.advancedInfo.briefList.length || this.advancedInfo.projectList.length) {
+          return '超前项目推荐'
+        } else {
+          return '定制化分析报告'
+        }
+      },
+      // 获取当前模块展示文本信息
+      getNowInfo () {
+        return this.advancedInfo.moduleInfo[this.nowModuleName]
+      },
+      // 获取当前模块缩小后是否有数据展示
+      getNotModuleDataStatus () {
+        if (this.nowModuleName === '超前项目推荐') {
+          return !this.advancedInfo.briefList.length
+        } else {
+          return true
+        }
+      },
+      // 是否展示定制化分析报告模块
+      getShowChart () {
+        return Object.keys(this.chartCustomData).length
+      },
       vipState: function () {
         var entniche = this.powerInfo.entniche
         var member = this.powerInfo.member
@@ -2317,6 +2461,7 @@ if(sessionselect){
       this.getPower()
     },
     mounted: function () {
+      this.getCustomReportData()
       console.log('总页码:' + totalPage + ',当前页:' + currentPage + ',一页数量:' + pageSize + ',总条数:' + totalCount)
       var isClickSearch = sessionStorage.getItem('is-click-search')
       var val =  $("#zbSeatchT [name='keywords']").val()
@@ -2328,12 +2473,263 @@ if(sessionselect){
         window.addEventListener('scroll', this.watchScroll)
       })
       this.getFilterList()
-
     },
     destroyed: function () {
       window.removeEventListener('scroll', this.watchScroll)
     },
     methods: {
+      // 上报接口
+      ajaxSetLeadGetDateRecordOfJq (params) {
+        $.ajax({
+          url: '/leadGeneration/clickRecord?type=' + params.type,
+          type: 'get',
+          async: false
+        })
+      },
+      // 展示弹窗
+      showAdvancedDialog (title) {
+        this.advancedInfo.dialogContent = title
+        this.advancedInfo.showDialog = true
+      },
+      // 点击感兴趣
+      onClickInterested (type) {
+        console.log(this.nowModuleName)
+        const title = type === 'A' ? '体验超前项目推荐服务!' : '为您量身定制个性化报告!'
+        this.showAdvancedDialog(title)
+        try {
+          this.ajaxSetLeadGetDateRecordOfJq({ type })
+        } catch (e) {
+          console.warn(e)
+        }
+      },
+      // 查看项目详情
+      goToContent (item) {
+        try {
+          this.ajaxSetLeadGetDateRecordOfJq({ type: 'A' })
+        } catch (e) {
+          console.warn(e)
+        }
+        let goURL = '/article/content/' + item._id + '.html'
+        if (Array.isArray(item.keyWord)) {
+          goURL += '?kds=' + encodeURIComponent(item.keyWord.join('+'))
+        }
+        window.open(goURL)
+      },
+      // 查看完整报告
+      goToReport () {
+        console.log(this.nowModuleName)
+        try {
+          this.ajaxSetLeadGetDateRecordOfJq({ type: 'B' })
+        } catch (e) {
+          console.warn(e)
+        }
+        try {
+          window.$BRACE.methods.open({
+            route: {
+              link: '/desktop/report_analysis',
+              appName: 'big',
+              appType: 'qiankun'
+            }
+          })
+        } catch (e) {
+          window.open('/swordfish/page_big_pc/desktop/report_analysis?tab=analysis')
+        }
+      },
+      // 匹配高亮文本信息
+      getProjectTitle ({ title, keyWord }) {
+        return utils.replaceKeyword(title, keyWord, ['<span class="com-highlight">', '</span>'])
+      },
+      // 收起或打开 展示超前项目、模块
+      toggleAdvancedContent (type) {
+        if (typeof type !== 'boolean') {
+          type = !this.advancedInfo.showContent
+        }
+        this.advancedInfo.showContent = type
+      },
+      // 查看完整报告
+      viewReportData () {
+        window.open('/swordfish/page_big_pc/desktop/report_analysis?tab=analysis')
+      },
+      // 感兴趣点我
+      getInterested () {
+        vm.isNeedSubmit('pc_search_dzhfxbg')
+      },
+      // 定制化分析报告&&超前项目推荐数据请求
+      getCustomReportData () {
+        $('#customerChart').hide()
+        $('#winnerChart').hide()
+        $('#buyerChart').hide()
+        let _this = this
+        const params = {
+          dType: 0,
+          keyWords: $("#zbSeatchT [name='keywords']").val()
+        }
+        $.ajax({
+          type: 'post',
+          url: '/leadGeneration/getDate',
+          data: params,
+          success: function(res) {
+            if (res && res.error_code === 0 && res.data) {
+              try {
+                //超前项目
+                if(res.data.ahead){
+                  _this.advancedInfo.briefList = (res.data.ahead.subTypeCount || []).map(v => {
+                    v.value = v.doc_count
+                    return v
+                  })
+                  _this.advancedInfo.projectList = res.data.ahead.projectTop2 || []
+                }
+                //定制化分析报告
+                _this.chartCustomData = res.data.custom || {}
+                if (_this.advancedInfo.briefList.length || _this.advancedInfo.projectList.length || Object.keys(_this.chartCustomData).length) {
+                  _this.advancedInfo.show = true
+                  setTimeout(() => {
+                    _this.advancedInfo.showContent = true
+                  }, 1000)
+                }
+              } catch (e) {
+                console.warn(e)
+              }
+              let customData = res.data.custom || {}
+              const chartKeyArr = Object.keys(customData)
+              const fieldText = _this.getRandomArrayElements(chartKeyArr, 2)
+              fieldText.forEach(item => {
+                if (item === 'customer_scale') {
+                  $('#customerChart').show()
+                  var data = customData.customer_scale.map(item => {
+                    return {
+                      ...item,
+                      name: item.buyclass,
+                      value: item.total,
+                      amount: _this.formatPrice(item.amount / 10000)
+                    }
+                  })
+                  setTimeout(() => {
+                    window.vComponentChart('#chartTreeMap', data, {}, 've-treemap')
+                  }, 1000)
+                } else if (item === 'winner_time_distribution') {
+                  $('#buyerChart').show()
+                  var data = {
+                    columns: ['采购规模分布', '采购总金额占比', '采购单位总数占比'],
+                    rows: []
+                  }
+                  let total = 0
+                  const chartLIst = customData.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()
+                    setTimeout(() => {
+                      window.vComponentChart('#chartLineChartBuyer', data, {}, 've-line')
+                    }, 1000)
+                  }
+                } else if (item === 'buyer_time_distribution') {
+                  $('#winnerChart').show()
+                  var data = {
+                    columns: ['中标规模分布', '中标总金额占比', '中标单位总数占比'],
+                    rows: []
+                  }
+                  let total = 0
+                  const buyerclassList = customData.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()
+                    setTimeout(() => {
+                      window.vComponentChart('#chartLineChart', data, {}, 've-line')
+                    }, 1000)
+                  }
+                }
+              })
+
+            }
+          }
+        })
+      },
+      formatPrice (s, n = -1, comma = false) {
+        // 如果不传s或者s为空,则直接返回0
+        if (!s) return 0
+
+        if (n !== -1) n = n > 0 && n <= 20 ? n : 2
+        const intS = parseInt(String(s))
+        let point = '.'
+        let left = []
+        let right = ''
+        s = parseFloat((s + '').replace(/[^\d.-]/g, ''))
+        // 没传n或者n为-1,默认(如果为整数,则不保留小数。如果为浮点数,则保留两位小数)
+        if (n === -1) {
+          if (s === intS) {
+            n = 0
+            right = ''
+            point = ''
+          } else {
+            n = 2
+            s = s.toFixed(n)
+            right = s.split('.')[1]
+          }
+          s = s + ''
+          left = s.split('.')[0].split('').reverse()
+        } else {
+          s = parseFloat((s + '').replace(/[^\d.-]/g, '')).toFixed(n) + ''
+          left = s.split('.')[0].split('').reverse()
+          right = s.split('.')[1]
+        }
+
+        if (comma) {
+          let t = ''
+          for (let i = 0; i < left.length; i++) {
+            t += left[i] + ((i + 1) % 3 === 0 && (i + 1) !== left.length ? ',' : '')
+          }
+          return t.split('').reverse().join('') + point + right
+        }
+
+        return left.reverse().join('') + point + right
+      },
+      // 随机取字段
+      getRandomArrayElements(arr, count) {
+        var shuffled = arr.slice(0), i = arr.length, min = i - count, temp, 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);
+      },
       // 页面滚动方法 用于悬浮吸顶
       watchScroll: function () {
         var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
@@ -2513,9 +2909,9 @@ if(sessionselect){
         //   return toastFn('超出页码', 3000)
         // }
         // TODO 免费用户搜索结果查看大于11页时弹窗提示
-      
+
         }
-       
+
 
         currentPage = this.listState.num
         this.listState.prevPageNum = this.listState.num

+ 10 - 0
src/web/templates/weixin/historypush.html

@@ -23,6 +23,7 @@
   <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/collection/css/index.css?v={{Msg "seo" "version"}}'/>
   <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/history-push/css/public.css?v={{Msg "seo" "version"}}'/>
   <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/history-push/css/old-page-style.css?v={{Msg "seo" "version"}}'/>
+  <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/history-push/css/recommend.css?v={{Msg "seo" "version"}}'/>
   <script>
     initShare({{.T.signature}},{{.T.openid}}, 2, "jy_extend",{{.T.nickname}},{{.T.avatar}});
   </script>
@@ -301,6 +302,14 @@
     </div>
     <div class="color_top" style="display:none;"></div>
     <div id="dropDownItemGroup" class="collection"></div>
+    <!-- <div class="analysis-module"> -->
+      <!-- 超前项目推荐 -->
+      <!-- <recommend-com  ref="recommendRef"  @toggle="onToggleStatus"></recommend-com> -->
+      <!-- 定制化分析报告 -->
+      <!-- <div v-show="collapseStatus"> -->
+        <!-- <CustomReport :chartData="chartData"></CustomReport> -->
+      <!-- </div>
+    </div> -->
     <div class="j-main">
       <div class="listcontent" onscroll="listScroll()">
         <div id="list"></div>
@@ -483,6 +492,7 @@
 <script src='{{Msg "seo" "cdn"}}/common-module/collection/js/notice-mobile.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Msg "seo" "cdn"}}/common-module/collection/js/money-mobile.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Msg "seo" "cdn"}}/common-module/keep-tags/keep-tags-template.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/history-push/js/recommend.js?v={{Msg "seo" "version"}}'></script>
 <script src='{{Msg "seo" "cdn"}}/common-module/history-push/js/historypush.js?v={{Msg "seo" "version"}}'></script>
 <script src=//cdn-common.jianyu360.com/cdn/lib/weui.js/1.2.1/weui.min.js></script>
 <script src='{{Msg "seo" "cdn"}}/common-module/history-push/js/old-page-script.js?v={{Msg "seo" "version"}}'></script>

部分文件因为文件数量过多而无法显示