report_analysis.js 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864
  1. function dateFormatter (date, pattern) {
  2. return new Date(date).pattern(pattern)
  3. }
  4. var vm = new Vue({
  5. delimiters: ['${', '}'],
  6. el: '#analysis',
  7. components: {
  8. keywordComponent: keywordComponent,
  9. areaCityMobile: areaCityMobileComponent,
  10. industryComponent: industryComponent,
  11. cateComponent: cateComponent,
  12. dateComponent: dateComponent,
  13. chartExample: chartExample,
  14. // 图表
  15. projectScatter: projectScatter,
  16. marketTimeScatter: marketTimeScatter,
  17. marketAreaScatter: marketAreaScatter,
  18. marketTop3Table: marketTop3Table,
  19. marketUserScatter: marketUserScatter,
  20. marketSegment: marketSegment,
  21. lineChartScatter: lineChartScatter,
  22. },
  23. data: {
  24. sessStorageKey: '$data-report_analysis',
  25. tabActiveName: 'analysis', // analysis/history
  26. tabList: [
  27. {
  28. label: '定制化市场分析',
  29. name: 'analysis'
  30. },
  31. {
  32. label: '历史报告',
  33. name: 'history'
  34. }
  35. ],
  36. tabConf: {
  37. titleActiveColor: '#2ABED1',
  38. titleInactiveColor: '#5F5E64',
  39. lineWidth: '24',
  40. color: '#2ABED1'
  41. },
  42. timeOptions: [
  43. {
  44. name: '近3个月',
  45. value: 'lately90',
  46. selected: false
  47. },
  48. {
  49. name: '近半年',
  50. value: 'lately180',
  51. selected: false
  52. },
  53. {
  54. name: '今年全年',
  55. value: 'thisYear',
  56. selected: false
  57. },
  58. {
  59. name: '去年至今',
  60. value: 'sinceLastYear',
  61. selected: false
  62. },
  63. {
  64. name: '前年至今',
  65. value: 'sinceYearBeforeLast',
  66. selected: false
  67. }
  68. ],
  69. scrollTop: 0,
  70. filtersPageShow: true,
  71. filters: {
  72. selectKeysArr: [], // 关键词简单数组,用于恢复选择状态
  73. keys: [], // 关键词详细数组,用于提交数据
  74. area: {},
  75. industry: [],
  76. industryDetail: {},
  77. buyerclass: [],
  78. rangeTime: {
  79. start: '',
  80. end: '',
  81. exact: 'sinceYearBeforeLast',
  82. },
  83. },
  84. filterDialogShow: {
  85. keys: false,
  86. area: false,
  87. industry: false,
  88. buyerclass: false,
  89. rangeTime: false
  90. },
  91. // 分析结果页面数据
  92. activeDimension: 'market',
  93. dimensionList: [
  94. {
  95. id: 'market',
  96. name: '市场规模',
  97. top: 0,
  98. anchor: 'market-overview'
  99. },
  100. {
  101. id: 'buyer',
  102. name: '采购单位',
  103. top: 0,
  104. anchor: 'buyerclass-scatter'
  105. },
  106. {
  107. id: 'bidder',
  108. name: '中标单位',
  109. top: 0,
  110. anchor: 'winner-scatter'
  111. },
  112. ],
  113. analysis: { // 开始分析请求的loaed和loading
  114. loaded: false,
  115. loading: false
  116. },
  117. rid: '', // reportId
  118. reportFilters: {
  119. keys: [],
  120. selectTime: '',
  121. selectTimeExtra: '',
  122. area: {},
  123. industry: {},
  124. buyerclass: []
  125. },
  126. sections: {
  127. market: {
  128. overview: [],
  129. refine: {
  130. dataAlready: false,
  131. projectCountData: null,
  132. projectAmountData: null,
  133. // 项目数量Top3
  134. projectCountTop3: null,
  135. // 项目金额Top3
  136. projectAmountTop3: null
  137. }
  138. },
  139. projectScatter: {
  140. dataAlready: false,
  141. chartData: null,
  142. tableData: [
  143. // {
  144. // projectname: 'xxxx',
  145. // area: 'xx',
  146. // city: 'xxx',
  147. // sortprice: 'zzz',
  148. // jgtime: 'zzzz',
  149. // winner_s: [
  150. // {
  151. // name: 'w1',
  152. // id: '33'
  153. // },
  154. // {
  155. // name: 'w2',
  156. // id: '33'
  157. // }
  158. // ]
  159. // },
  160. // {
  161. // projectname: 'xxxx',
  162. // area: 'xx',
  163. // city: 'xxx',
  164. // sortprice: 'zzz',
  165. // jgtime: 'zzzz',
  166. // winner_s: [
  167. // {
  168. // name: 'w1',
  169. // id: '33'
  170. // },
  171. // {
  172. // name: 'w2',
  173. // id: '33'
  174. // }
  175. // ]
  176. // }
  177. ]
  178. },
  179. timeScatter: {
  180. dataAlready: false, // 数据准备好之后才能开始渲染
  181. activeAction: 'month',
  182. actionList: [
  183. {
  184. label: '月度数据',
  185. value: 'month'
  186. },
  187. {
  188. label: '年度数据',
  189. value: 'year'
  190. }
  191. ],
  192. month: {
  193. count: {},
  194. amount: {}
  195. },
  196. year: {
  197. count: {},
  198. amount: {}
  199. }
  200. },
  201. areaScatter: {
  202. dataAlready: false,
  203. chartData: null,
  204. // 项目数量Top3
  205. projectCountTop3: null,
  206. // 项目金额Top3
  207. projectAmountTop3: null
  208. },
  209. userScatter: {
  210. list: [],
  211. // 项目数量Top3
  212. projectCountTop3: null,
  213. // 项目金额Top3
  214. projectAmountTop3: null
  215. },
  216. buyerclass: {
  217. dataAlready: false,
  218. chartData: null,
  219. // 项目数量Top3
  220. projectCountTop3: null,
  221. // 项目金额Top3
  222. projectAmountTop3: null
  223. },
  224. winner: {
  225. dataAlready: false,
  226. chartData: null,
  227. // 项目数量Top3
  228. projectCountTop3: null,
  229. // 项目金额Top3
  230. projectAmountTop3: null
  231. }
  232. },
  233. empty: {
  234. defaultMsg: '对不起,没有匹配到相关信息<br />请修改您的分析条件',
  235. msg: ''
  236. },
  237. stickyOffset: 0,
  238. notSetKey: false, // 未设置关键词
  239. isSubCount: false, // 是否子账号
  240. powerInfo: {},
  241. isWeixin: false
  242. },
  243. computed: {
  244. getStatus: function () {
  245. if (JSON.stringify(this.powerInfo) !== '{}') {
  246. return this.powerInfo.power.indexOf(10) !== -1
  247. }
  248. },
  249. anchorTopList: function () {
  250. var arr = []
  251. this.dimensionList.forEach(function (item) {
  252. arr.push(item.top)
  253. })
  254. return arr
  255. },
  256. // 报告详情筛选条件只有一个省份
  257. // 此时不显示地区分布chart
  258. notOneAreaFilter () {
  259. var area = this.reportFilters.area
  260. var showArea = area && (Object.keys(area).length > 1 || Object.keys(area).length === 0)
  261. return showArea
  262. },
  263. emptyShow () {
  264. return !this.rid && this.analysis.loaded
  265. },
  266. tabActive: function () {
  267. var _this = this
  268. var active = {}
  269. this.tabList.some(function (item) {
  270. var findThis = item.name === _this.tabActiveName
  271. if (findThis) {
  272. active = item
  273. return findThis
  274. }
  275. })
  276. return active
  277. },
  278. buyerclassSectionShow () {
  279. const winnerState = this.sections.buyerclass
  280. return winnerState.dataAlready && winnerState.projectCountTop3 && winnerState.projectAmountTop3
  281. },
  282. winnerSectionShow () {
  283. const winnerState = this.sections.winner
  284. return winnerState.dataAlready && winnerState.projectCountTop3 && winnerState.projectAmountTop3
  285. },
  286. overviewRateTotal: function () {
  287. var total = 0
  288. this.sections.market.overview.forEach(function (item) {
  289. if (item.ringRatio !== undefined && item.ringRatio !== null) {
  290. total += item.ringRatio
  291. }
  292. })
  293. return total
  294. }
  295. },
  296. watch: {
  297. filtersPageShow (newVal) {
  298. if (!newVal) {
  299. this.isWeixin = utils.isWeiXinBrowser
  300. if (!this.isWeixin) {
  301. this.calcStickyOffset()
  302. }
  303. }
  304. }
  305. },
  306. created () {
  307. this.calcLastTimeText()
  308. this.getPower()
  309. var id = utils.getParam('id')
  310. if (id) {
  311. this.rid = decodeURIComponent(id)
  312. this.filtersPageShow = false
  313. }
  314. },
  315. mounted: function () {
  316. setTimeout(() => {
  317. var restored = this.reStoreState()
  318. if (!restored) {
  319. if (this.rid) {
  320. this.getReportResult()
  321. }
  322. } else {
  323. this.$nextTick(this.calcOffsetTop)
  324. if (utils.isIos) {
  325. setTimeout(this.calcOffsetTop, 1000)
  326. }
  327. }
  328. }, 0)
  329. this.addEventListeners()
  330. utils.iosBackRefresh()
  331. },
  332. methods: {
  333. gotable () {
  334. this.saveState()
  335. if(this.isWeiXinBrower()){
  336. window.location.href='/big/wx/page/report_table?source=analysis'+'&flag=3'+'&rid='+this.rid+'&header=客户类型分布详情'
  337. } else {
  338. window.location.href='/jyapp/big/page/report_table?source=analysis'+'&flag=3'+'&rid='+this.rid+'&header=客户类型分布详情'
  339. }
  340. },
  341. isWeiXinBrower() {
  342. var ua = navigator.userAgent.toLowerCase();
  343. if(ua.match(/MicroMessenger/i) == 'micromessenger') {
  344. return true;
  345. } else {
  346. return false;
  347. }
  348. },
  349. showLoading: function () {
  350. return this.$toast.loading({
  351. duration: 0,
  352. forbidClick: true,
  353. message: 'loading...',
  354. })
  355. },
  356. showToast: function (message) {
  357. return this.$toast({
  358. duration: 1500,
  359. forbidClick: true,
  360. message: message,
  361. })
  362. },
  363. showDialog: function (conf) {
  364. var defaultConf = {
  365. title: '提示',
  366. message: 'message',
  367. className: 'j-confirm-dialog',
  368. showConfirmButton: true,
  369. showCancelButton: true,
  370. confirmButtonText: '确定',
  371. confirmButtonColor: '#2abed1'
  372. }
  373. if (conf) {
  374. Object.assign(defaultConf, conf)
  375. }
  376. return this.$dialog.confirm(defaultConf)
  377. },
  378. calcOffsetTop: function () {
  379. var sticky = $('.van-sticky')
  380. var stickyHeight = 0
  381. if (sticky.length) {
  382. stickyHeight = sticky[0].clientHeight
  383. }
  384. this.dimensionList.forEach(function (item) {
  385. var anchor = $('.' + item.anchor)
  386. var offsetTop = 0
  387. if (anchor.length) {
  388. offsetTop = parseInt(anchor[0].offsetTop - stickyHeight)
  389. }
  390. item.top = offsetTop
  391. })
  392. },
  393. addEventListeners: function () {
  394. this.scrollToTop()
  395. },
  396. scrollToTop: function () {
  397. var $scrollDOM = $('.j-container.search-result > .j-main')
  398. // 1. 检查当前高度是否满足显示快速滚动到顶部
  399. this.checkScrollTopButtonShow()
  400. // 2. 具体逻辑
  401. $scrollDOM.on('scroll', this.checkScrollTopButtonShow)
  402. setTimeout(function () {
  403. // 2s后绑定(尽可能保证top能够被计算完)
  404. $scrollDOM.on('scroll', this.checkAnchorItemActive)
  405. }.bind(this), 2500)
  406. $('.scroll-to-top').on('click', function () {
  407. $scrollDOM.animate({ scrollTop: 0 })
  408. })
  409. },
  410. checkAnchorItemActive: function () {
  411. var $scrollDOM = $('.j-container.search-result > .j-main')
  412. var anchorTopList = this.anchorTopList
  413. var scrollTop = parseInt($scrollDOM.scrollTop()) + 3 // (误差校正)
  414. var i = 0
  415. if (scrollTop >= anchorTopList[1] && scrollTop < anchorTopList[2]) {
  416. i = 1
  417. } else if (scrollTop > anchorTopList[2] && scrollTop > anchorTopList[1] && scrollTop > anchorTopList[0]) { //逻辑上多余判断条件 ,为了处理高度还没有计算出起始的 anchorTopList[2]为0 tab回显错误问题
  418. i = 2
  419. } else if (scrollTop < anchorTopList[1]) {
  420. i = 0
  421. }
  422. this.activeDimension = this.dimensionList[i].id
  423. },
  424. checkScrollTopButtonShow: function () {
  425. var showButtonHeight = 300
  426. var $scrollDOM = $('.j-container.search-result > .j-main')
  427. var button = $('.scroll-to-top')
  428. var scrollTop = $scrollDOM.scrollTop()
  429. if (scrollTop > showButtonHeight) {
  430. button.show()
  431. } else {
  432. button.hide()
  433. }
  434. },
  435. calcStickyOffset: function () {
  436. setTimeout(function () {
  437. var headerHeight = $('.jy-app-header')[0].clientHeight
  438. var tabHeight = $('.analysis-tab')[0].clientHeight
  439. this.stickyOffset = headerHeight + tabHeight - 5
  440. }.bind(this), 1000)
  441. },
  442. setScrollTop: function (scrollTop) {
  443. this.$nextTick(function () {
  444. var wrapper = document.querySelector('.j-container.search-result > .j-main')
  445. wrapper.scrollTop = scrollTop
  446. })
  447. },
  448. saveScrollTop: function () {
  449. var wrapper = document.querySelector('.j-container.search-result > .j-main')
  450. if (wrapper.scrollTop) {
  451. this.scrollTop = parseInt(wrapper.scrollTop)
  452. }
  453. },
  454. beforeTabChange: function (name) {
  455. if (name !== this.tabActiveName) {
  456. this.goToAnalysisHistory()
  457. }
  458. return false
  459. },
  460. goToAnalysisHistory: function () {
  461. location.href = './report_analysis_history'
  462. },
  463. formatSelectTime (value) {
  464. if (!value) return '-'
  465. const timeArr = value.split('-')
  466. return `${dateFormatter(timeArr[0] * 1000, 'yyyy/MM/dd')}-${dateFormatter(timeArr[1] * 1000, 'yyyy/MM/dd')}`
  467. },
  468. getPower:function () {
  469. var _this = this
  470. $.ajax({
  471. type:'POST',
  472. url:'/bigmember/use/isAdd',
  473. success:function(res) {
  474. _this.powerInfo = res.data
  475. if (res.data && res.data.isSubCount){
  476. _this.isSubCount = true
  477. }
  478. }
  479. })
  480. },
  481. init: function () {
  482. // 初始化页面数据
  483. this.initDateTimeSelector('sinceYearBeforeLast')
  484. },
  485. // 时间选择器选中状态
  486. initDateTimeSelector: function (exact) {
  487. if (exact === 'exact') {
  488. this.$refs.dateSelector.setState(this.filters.rangeTime)
  489. } else {
  490. this.$refs.dateSelector.setTimeSelectListState(exact)
  491. this.$refs.dateSelector.dateStyle = false
  492. }
  493. },
  494. resolveSelected: function (type) {
  495. var filters = this.filters
  496. var prefix = '已选:'
  497. var text = ''
  498. if (type === 'keys') {
  499. if (this.notSetKey) return '请设置'
  500. text = this.resolveSelectKeysText(filters.keys)
  501. } else if (type === 'area') {
  502. text = this.resolveSelectAreaText(filters.area)
  503. } else if (type === 'industry') {
  504. text = this.resolveSelectIndustryText(filters.industryDetail)
  505. } else if (type === 'buyerclass') {
  506. text = this.resolveSelectBuyerclassText(filters.buyerclass)
  507. }
  508. return prefix + text
  509. },
  510. resolveSelectKeysText: function (keys) {
  511. if (Array.isArray(keys)) {
  512. if (keys.length === 0) {
  513. return '全部'
  514. } else {
  515. var count = 0
  516. var arr = []
  517. keys.forEach(function (classify) {
  518. if (Array.isArray(classify.a_key) && classify.a_key.length) {
  519. count += classify.a_key.length
  520. classify.a_key.forEach(function (item) {
  521. arr.push(item.key.join(' '))
  522. })
  523. }
  524. })
  525. if (count <= 0) {
  526. return '全部'
  527. } else {
  528. return arr.join(',')
  529. }
  530. }
  531. } else {
  532. return '全部'
  533. }
  534. },
  535. resolveSelectAreaText: function (area) {
  536. if (!area || Object.keys(area).length === 0) return '全国'
  537. var areaArr = []
  538. var cityArr = []
  539. for (var key in area) {
  540. if (area[key].length === 0) {
  541. areaArr.push(key)
  542. } else {
  543. cityArr = cityArr.concat(area[key])
  544. }
  545. }
  546. return areaArr.concat(cityArr).join(',')
  547. },
  548. resolveSelectIndustryText: function (industry) {
  549. if (!industry || Object.keys(industry).length === 0) return '全部'
  550. var keyArr = []
  551. var valueArr = []
  552. for (var key in industry) {
  553. if (industry[key].length === 0) {
  554. keyArr.push(key)
  555. } else {
  556. valueArr = valueArr.concat(industry[key])
  557. }
  558. }
  559. return keyArr.concat(valueArr).join(',')
  560. },
  561. resolveSelectBuyerclassText: function (buyerclass) {
  562. if (!Array.isArray(buyerclass)) return '全部'
  563. if (buyerclass.length === 0) return '全部'
  564. return buyerclass.join(',')
  565. },
  566. calcLastTimeText: function () {
  567. const renameList = [
  568. 'thisYear', // 今年全年
  569. 'sinceLastYear', // 去年至今
  570. 'sinceYearBeforeLast' // 前年至今
  571. ]
  572. const thisYear = new Date().getFullYear()
  573. this.timeOptions.forEach(item => {
  574. if (renameList.indexOf(item.value) !== -1) {
  575. if (item.value === renameList[0]) {
  576. item.name = `${thisYear}年全年`
  577. } else if (item.value === renameList[1]) {
  578. item.name = `${thisYear - 1}年至今`
  579. } else if (item.value === renameList[2]) {
  580. item.name = `${thisYear - 2}年至今`
  581. }
  582. }
  583. })
  584. },
  585. // 重置
  586. resetFilter: function (type) {
  587. var filters = this.filters
  588. if (type === 'keys') {
  589. filters.keys = []
  590. filters.selectKeysArr = []
  591. try {
  592. this.$refs.keywordSelector.resetAllNoSelect()
  593. } catch (error) {}
  594. } else if (type === 'area') {
  595. filters.area = {}
  596. } else if (type === 'industry') {
  597. filters.industry = []
  598. filters.industryDetail = {}
  599. } else if (type === 'buyerclass') {
  600. filters.buyerclass = []
  601. } else if (type === 'date') {
  602. this.filters.rangeTime.start = ''
  603. this.filters.rangeTime.edd = ''
  604. this.filters.rangeTime.exact = 'sinceYearBeforeLast'
  605. this.initDateTimeSelector(this.filters.rangeTime.exact)
  606. } else {
  607. this.resetFilter('keys')
  608. this.resetFilter('area')
  609. this.resetFilter('industry')
  610. this.resetFilter('buyerclass')
  611. this.resetFilter('date')
  612. }
  613. },
  614. clickCell: function (key) {
  615. var _this = this
  616. var dialog = this.filterDialogShow
  617. if (key === 'keys') {
  618. if (this.notSetKey) {
  619. return this.setKeyTip()
  620. }
  621. } else if (key === 'area') {
  622. setTimeout(function () {
  623. _this.$refs.areaCitySelector.setState(_this.filters.area)
  624. }, 0)
  625. } else if (key === 'buyerclass') {
  626. setTimeout(function () {
  627. _this.$refs.buyerclassSelector.setState()
  628. }, 0)
  629. } else if (key === 'industry') {
  630. setTimeout(function () {
  631. _this.$refs.industrySelector.setState()
  632. }, 0)
  633. }
  634. dialog[key] = true
  635. },
  636. cancel: function (e, key) {
  637. var dialog = this.filterDialogShow
  638. this.resetFilter(key)
  639. dialog[key] = false
  640. },
  641. confirm: function (e, key) {
  642. var dialog = this.filterDialogShow
  643. var filters = this.filters
  644. if (key === 'keys') {
  645. filters.keys = e.detail
  646. filters.selectKeysArr = e.data
  647. } else if (key === 'area') {
  648. filters.area = e.data
  649. } else if (key === 'industry') {
  650. filters.industry = e.data
  651. filters.industryDetail = e.detail
  652. } else if (key === 'buyerclass') {
  653. filters.buyerclass = e.data
  654. console.log(e.data)
  655. }
  656. dialog[key] = false
  657. },
  658. dateTimeSelectorConfirm () {
  659. var result = this.$refs.dateSelector.getState()
  660. this.filters.rangeTime.start = result.start
  661. this.filters.rangeTime.end = result.end
  662. this.filters.rangeTime.exact = result.exact
  663. },
  664. resetAllFilters: function () {
  665. this.analysis.loaded = false
  666. this.resetFilter('all')
  667. },
  668. getReportResult () {
  669. this.sendRequest()
  670. },
  671. getSelectedKeys () {
  672. const keys = this.filters.keys
  673. if (Array.isArray(keys) && keys.length) {
  674. return JSON.stringify(keys)
  675. } else {
  676. var allKeys = this.$refs.keywordSelector.keywordGroupList
  677. return JSON.stringify(allKeys)
  678. }
  679. },
  680. startAnalysis: function () {
  681. this.dateTimeSelectorConfirm()
  682. const query = {
  683. keysItems: this.getSelectedKeys(),
  684. rangeTime: `${parseInt(this.filters.rangeTime.start / 1000)}-${parseInt(this.filters.rangeTime.end / 1000)}`,
  685. rangeTimeExtra: this.filters.rangeTime.exact,
  686. area: JSON.stringify(this.filters.area),
  687. industry: JSON.stringify(this.filters.industryDetail),
  688. buyerclass: this.filters.buyerclass.join(',')
  689. }
  690. this.analysis.loaded = false
  691. this.analysis.loading = true
  692. this.showLoading()
  693. $.ajax({
  694. type: 'POST',
  695. url: '/bigmember/marketAnalysis/doAnalysis',
  696. data: query,
  697. success: function (res) {
  698. if (res && res.error_code === 0 && res.data) {
  699. this.rid = res.data
  700. this.analysis.loaded = true
  701. // location.replace('./report_analysis?id=' + res.data)
  702. this.rid = res.data
  703. history.replaceState({}, null, '?id=' + this.rid)
  704. this.getReportResult()
  705. } else {
  706. this.$toast(res.error_msg)
  707. }
  708. }.bind(this),
  709. complete: function () {
  710. this.analysis.loading = false
  711. }.bind(this)
  712. })
  713. },
  714. // 保存页面状态
  715. saveState: function () {
  716. this.saveScrollTop()
  717. this.dateTimeSelectorConfirm()
  718. var $data = {
  719. analysis: this.analysis,
  720. filters: this.filters,
  721. scrollTop: this.scrollTop,
  722. filtersPageShow: this.filtersPageShow,
  723. reportFilters: this.reportFilters,
  724. sections: this.sections,
  725. isSubCount: this.isSubCount
  726. }
  727. sessionStorage.setItem(this.sessStorageKey, JSON.stringify($data))
  728. },
  729. reStoreState: function () {
  730. var $data = sessionStorage.getItem(this.sessStorageKey)
  731. if ($data) {
  732. $data = JSON.parse($data)
  733. this.isSubCount = $data.isSubCount
  734. this.scrollTop = $data.scrollTop
  735. this.filtersPageShow = $data.filtersPageShow
  736. Object.assign(this.analysis, $data.analysis)
  737. this.$set(this, 'filters', $data.filters)
  738. this.$set(this, 'reportFilters', $data.reportFilters)
  739. this.$set(this, 'sections', $data.sections)
  740. setTimeout(function () {
  741. // 恢复滚动高度
  742. this.setScrollTop(this.scrollTop)
  743. this.initDateTimeSelector(this.filters.rangeTime.exact)
  744. }.bind(this), 0)
  745. sessionStorage.removeItem(this.sessStorageKey)
  746. } else {
  747. this.init()
  748. }
  749. return $data
  750. },
  751. onEmpty (info) {
  752. if (this.loading) {
  753. this.loading.clear()
  754. }
  755. this.filtersPageShow = true
  756. this.analysis.loaded = true
  757. this.rid = ''
  758. if (info && info.msg) {
  759. this.empty.msg = info.msg
  760. } else {
  761. this.empty.msg = this.empty.defaultMsg
  762. }
  763. },
  764. sendRequest () {
  765. let _this = this
  766. // 先请求概况(1),判断报告是否为空
  767. const query = {
  768. rid: this.rid,
  769. flag: 1
  770. }
  771. if (!query.rid) {
  772. return
  773. }
  774. this.loading = this.showLoading()
  775. $.ajax({
  776. type: 'POST',
  777. async: false,
  778. url: '/bigmember/marketAnalysis/getAnalysisResult',
  779. data: query,
  780. success: function(res) {
  781. if (res && res.error_code === 0 && res.data) {
  782. var empty = _this.formatterData(query.flag, res.data)
  783. if (empty) {
  784. return _this.onEmpty()
  785. }
  786. } else {
  787. if (res.error_msg.indexOf('项目数量超出上限') === -1) {
  788. return _this.onEmpty()
  789. } else {
  790. return _this.onEmpty({ msg: '当前分析条件涉及项目数量已超过最大限制,请修改分析条件进行精确分析' })
  791. }
  792. }
  793. }
  794. }).responseJSON
  795. this.filtersPageShow = false
  796. const flagArr = [
  797. 0, // 筛选条件
  798. // 1, // 市场概括与时间分布
  799. 2, // 项目规模Top10
  800. 3, // 项目规模分布/地区规模分布/客户分布/地区分布及客户分布&Top3(table+chart)
  801. 4, // 细分市场
  802. 5 // 采购单位/中标单位&Top3(table+chart)
  803. ]
  804. flagArr.forEach(this.getReport)
  805. if (this.loading) {
  806. this.loading.clear()
  807. }
  808. },
  809. getReport (flag) {
  810. const query = {
  811. rid: this.rid,
  812. flag
  813. }
  814. if (!query.rid) {
  815. return
  816. }
  817. $.ajax({
  818. type: 'POST',
  819. url: '/bigmember/marketAnalysis/getAnalysisResult',
  820. data: query,
  821. success: function (res) {
  822. if (res && res.error_code === 0 && res.data) {
  823. if(flag==3){
  824. sessionStorage.setItem('getAnalysisResult_',JSON.stringify(res))
  825. }
  826. this.formatterData(flag, res.data)
  827. } else {
  828. this.$toast('请求失败')
  829. }
  830. }.bind(this)
  831. })
  832. },
  833. formatterData (flag, data) {
  834. if (flag === 0) {
  835. this.sortReportFilters(data)
  836. } else if (flag === 1) {
  837. // 市场概况
  838. const totalCount = this.sortMarketOverview(data.market_profile)
  839. if (!totalCount) {
  840. return true
  841. }
  842. // 时间分布
  843. this.sortTimeScatter(data)
  844. } else if (flag === 2) {
  845. // 项目规模Top10
  846. this.sortProjectTop10(data.ProjectTop10)
  847. } else if (flag === 3) {
  848. // 项目规模分布/地区规模分布/客户分布/地区分布及客户分布&Top3(table+chart)
  849. // 项目规模分布
  850. this.sortProjectScatter(data.projectScale)
  851. // 地区规模分布
  852. this.sortAreaScatter(data.area_infos)
  853. // 客户分布
  854. if(data.customer_scale){
  855. if(data.customer_scale.length!=0){
  856. let data_=data.customer_scale.slice(0,10)
  857. this.sortUserScatter(data_)
  858. }
  859. }
  860. // 地区分布及客户分布Top3
  861. this.sortAreaUserTop3(data)
  862. } else if (flag === 4) {
  863. // 细分市场
  864. this.sortMarketRefineData(data)
  865. } else if (flag === 5) {
  866. // 采购单位/中标单位&Top3(table+chart)
  867. this.sortBuyerclassData(data)
  868. // 中标单位分析
  869. this.sortWinnerData(data)
  870. }
  871. this.$nextTick(this.calcOffsetTop)
  872. },
  873. formatSelectTime (value) {
  874. if (!value) return '-'
  875. const timeArr = value.split('-')
  876. return `${dateFormatter(timeArr[0] * 1000, 'yyyy/MM/dd')}-${dateFormatter(timeArr[1] * 1000, 'yyyy/MM/dd')}`
  877. },
  878. // 整理数据,并赋值给filters
  879. sortReportFilters (data) {
  880. if (data.keysItems && data.keysItems !== '[]') {
  881. this.reportFilters.keys = JSON.parse(data.keysItems)
  882. this.filters.keys = this.reportFilters.keys
  883. var keyArr = []
  884. this.filters.keys.forEach(function (classify) {
  885. if(Array.isArray(classify.a_key)) {
  886. classify.a_key.forEach(function (item) {
  887. keyArr.push(item.key.join(' '))
  888. })
  889. }
  890. })
  891. this.filters.selectKeysArr = keyArr
  892. }
  893. // if (data.s_rangeTimeExtra) {
  894. // this.reportFilters.selectTimeExtra = data.s_rangeTimeExtra
  895. // this.filters.rangeTime.exact = this.reportFilters.selectTimeExtra
  896. // } else {
  897. // this.filters.rangeTime.exact = 'exact'
  898. // }
  899. this.filters.rangeTime.exact = 'exact'
  900. if (data.rangeTime) {
  901. this.reportFilters.selectTime = data.rangeTime
  902. var arr = data.rangeTime.split('-')
  903. this.filters.rangeTime.start = arr[0] * 1000
  904. this.filters.rangeTime.end = arr[1] * 1000
  905. if (this.filters.rangeTime.exact === 'exact') {
  906. var date = new Date(this.filters.rangeTime.end)
  907. var timeString = date.pattern('yyyy/MM/dd')
  908. this.filters.rangeTime.end = new Date(timeString).getTime()
  909. }
  910. }
  911. this.$refs.dateSelector.setState(this.filters.rangeTime)
  912. if (data.area && data.area !== '{}') {
  913. this.reportFilters.area = JSON.parse(data.area)
  914. this.filters.area = this.reportFilters.area
  915. }
  916. if (data.industry && data.industry !== '{}') {
  917. this.reportFilters.industry = JSON.parse(data.industry)
  918. this.$set(this.filters, 'industryDetail', this.reportFilters.industry)
  919. var industry = []
  920. for (var key in this.reportFilters.industry) {
  921. this.reportFilters.industry[key].forEach(function (item) {
  922. industry.push(key + '_' + item)
  923. })
  924. }
  925. this.filters.industry = industry
  926. }
  927. if (data.buyerclass) {
  928. this.reportFilters.buyerclass = data.buyerclass.split(',')
  929. this.filters.buyerclass = this.reportFilters.buyerclass
  930. }
  931. },
  932. // 市场概况
  933. sortMarketOverview (profile) {
  934. if (!profile) return
  935. const list = [
  936. {
  937. label: '项目总数',
  938. unit: '个',
  939. count: 0,
  940. ringRatio: 0
  941. },
  942. {
  943. label: '项目总金额',
  944. unit: '万元',
  945. count: 0,
  946. ringRatio: 0
  947. },
  948. {
  949. label: '项目平均金额',
  950. unit: '万元',
  951. count: 10.04,
  952. ringRatio: 0
  953. },
  954. {
  955. label: '中标单位数',
  956. unit: '家',
  957. count: 10628,
  958. ringRatio: 0
  959. },
  960. {
  961. label: '采购单位数',
  962. unit: '家',
  963. count: 16215,
  964. ringRatio: 0
  965. }
  966. ]
  967. // 项目总数
  968. list[0].count = profile.project_count ? profile.project_count : 0
  969. list[0].ringRatio = profile.project_count_ratio ? (profile.project_count_ratio * 100).toFixed(2) : 0
  970. // 项目总金额
  971. const projectTotalMoney = this.moneyUnit(profile.projctamout ? profile.projctamout : 0)
  972. list[1].count = projectTotalMoney.count || 0
  973. list[1].unit = projectTotalMoney.unit || '万元'
  974. list[1].ringRatio = profile.projctamount_ratio ? (profile.projctamount_ratio * 100).toFixed(2) : 0
  975. // 项目平均金额
  976. const projectAvgMoney = this.moneyUnit(profile.projectavgmoney ? profile.projectavgmoney : 0)
  977. list[2].count = projectAvgMoney.count || 0
  978. list[2].unit = projectAvgMoney.unit || '万元'
  979. list[2].ringRatio = profile.projectavgmoney_ratio ? (profile.projectavgmoney_ratio * 100).toFixed(2) : 0
  980. // 中标单位数
  981. list[3].count = profile.winnercount ? profile.winnercount : 0
  982. list[3].ringRatio = profile.winnercount_ratio ? (profile.winnercount_ratio * 100).toFixed(2) : 0
  983. // 采购单位数
  984. list[4].count = profile.buyercount ? profile.buyercount : 0
  985. list[4].ringRatio = profile.winnercount_ratio ? (profile.winnercount_ratio * 100).toFixed(2) : 0
  986. var totalCount = list.reduce((total, item) => item.count + total, 0)
  987. if (totalCount) {
  988. this.sections.market.overview = list
  989. }
  990. return totalCount
  991. },
  992. // 时间分布
  993. sortTimeScatter (data) {
  994. const hasDataM = this.sortTimeScatterData('month', data.month_distribution)
  995. const hasDataY = this.sortTimeScatterData('year', data.year_distribution)
  996. const hasData = hasDataM && hasDataY
  997. this.sections.timeScatter.dataAlready = hasData
  998. },
  999. sortTimeScatterData (type, data) {
  1000. // columns: ['日期', '项目规模', '环比增长率(%)'],
  1001. // rows: [
  1002. // {
  1003. // 日期: '6月',
  1004. // 项目规模: 0,
  1005. // '环比增长率(%)': -99
  1006. // },
  1007. // {
  1008. // 日期: '7月',
  1009. // 项目规模: 736325,
  1010. // '环比增长率(%)': 0
  1011. // },
  1012. // ]
  1013. if (!data) return
  1014. // 项目数量
  1015. const mDCount = {
  1016. columns: ['日期', '项目数量(个)', '项目数量环比'],
  1017. rows: []
  1018. }
  1019. let mDCountTotal = 0
  1020. if (Array.isArray(data.project_count)) {
  1021. const field = {
  1022. [mDCount.columns[0]]: 'minth',
  1023. [mDCount.columns[1]]: 'value',
  1024. [mDCount.columns[2]]: 'ratio'
  1025. }
  1026. data.project_count.forEach(item => {
  1027. const row = {}
  1028. mDCount.columns.forEach(column => {
  1029. var value = item[field[column]]
  1030. if (value) {
  1031. if (field[column] === 'ratio') {
  1032. row[column] = utils.formatMoney(value * 100, undefined, true) - 0
  1033. } else {
  1034. row[column] = value
  1035. }
  1036. } else {
  1037. row[column] = null
  1038. }
  1039. if (typeof value === 'number') {
  1040. mDCountTotal += value
  1041. }
  1042. })
  1043. mDCount.rows.push(row)
  1044. })
  1045. }
  1046. if (mDCountTotal || isNaN(mDCountTotal)) {
  1047. this.$set(this.sections.timeScatter[type], 'count', mDCount)
  1048. }
  1049. // 项目规模
  1050. const mDAmount = {
  1051. columns: ['日期', '项目金额(万元)', '项目金额环比'],
  1052. rows: []
  1053. }
  1054. let mDAmuntTotal = 0
  1055. if (Array.isArray(data.project_amount)) {
  1056. const field = {
  1057. [mDAmount.columns[0]]: 'minth',
  1058. [mDAmount.columns[1]]: 'value',
  1059. [mDAmount.columns[2]]: 'ratio'
  1060. }
  1061. data.project_amount.forEach(item => {
  1062. const row = {}
  1063. mDAmount.columns.forEach(column => {
  1064. const value = item[field[column]]
  1065. if (value) {
  1066. if (field[column] === 'value') {
  1067. row[column] = utils.formatMoney(value / 10000, undefined, true) - 0
  1068. } else if (field[column] === 'ratio') {
  1069. row[column] = utils.formatMoney(value * 100, undefined, true)
  1070. } else {
  1071. row[column] = value
  1072. }
  1073. } else {
  1074. row[column] = null
  1075. }
  1076. if (typeof value === 'number') {
  1077. mDAmuntTotal += value
  1078. }
  1079. })
  1080. mDAmount.rows.push(row)
  1081. })
  1082. }
  1083. if (mDAmuntTotal || !isNaN(mDAmuntTotal)) {
  1084. this.$set(this.sections.timeScatter[type], 'amount', mDAmount)
  1085. }
  1086. const r = !!(mDCountTotal + mDAmuntTotal)
  1087. const hasOneNaN = isNaN(mDCountTotal) || isNaN(mDAmuntTotal)
  1088. return hasOneNaN || r
  1089. },
  1090. // 项目规模分布
  1091. sortProjectScatter (data) {
  1092. // const chartData = {
  1093. // columns: ['项目规模', '项目总金额占比', '项目总数占比'],
  1094. // rows: [
  1095. // {
  1096. // 项目规模: '≥1亿',
  1097. // 项目总金额占比: 20,
  1098. // 项目总数占比: 10
  1099. // },
  1100. // {
  1101. // 项目规模: '1000万-1亿',
  1102. // 项目总金额占比: 50,
  1103. // 项目总数占比: 40
  1104. // },
  1105. // {
  1106. // 项目规模: '500万-1000万',
  1107. // 项目总金额占比: 20,
  1108. // 项目总数占比: 30
  1109. // },
  1110. // {
  1111. // 项目规模: '100万-500万',
  1112. // 项目总金额占比: 20,
  1113. // 项目总数占比: 30
  1114. // }
  1115. // ]
  1116. // }
  1117. const scaleList = data
  1118. const scaleData = {
  1119. columns: ['项目规模', '项目总金额占比', '项目总数占比'],
  1120. rows: []
  1121. }
  1122. let total = 0
  1123. if (scaleList && Array.isArray(scaleList)) {
  1124. const field = {
  1125. [scaleData.columns[0]]: 'Name',
  1126. [scaleData.columns[1]]: 'Persent_c',
  1127. [scaleData.columns[2]]: 'Persent_a'
  1128. }
  1129. scaleList.forEach(item => {
  1130. const row = {}
  1131. scaleData.columns.forEach(column => {
  1132. if (field[column] === 'Persent_c' || field[column] === 'Persent_a') {
  1133. row[column] = (item[field[column]] * 100).toFixed(2)
  1134. total += (item[field[column]] - 0)
  1135. } else {
  1136. row[column] = item[field[column]]
  1137. }
  1138. })
  1139. scaleData.rows.push(row)
  1140. })
  1141. }
  1142. if (total) {
  1143. scaleData.rows.reverse()
  1144. this.$set(this.sections.projectScatter, 'chartData', scaleData)
  1145. if (this.sections.projectScatter.tableData.length) {
  1146. this.sections.projectScatter.dataAlready = true
  1147. }
  1148. }
  1149. },
  1150. // 项目规模Top10
  1151. sortProjectTop10 (top10List) {
  1152. if (!Array.isArray(top10List)) return
  1153. this.sections.projectScatter.tableData = top10List.map(top => {
  1154. let winners = top.winner_s ? top.winner_s.join(',') : ''
  1155. if (!winners) {
  1156. winners = []
  1157. } else {
  1158. winners = top.winner_s
  1159. }
  1160. winners = winners.map((item, index) => {
  1161. return {
  1162. name: item,
  1163. id: Array.isArray(top.eidlist) ? top.eidlist[index] : null
  1164. }
  1165. })
  1166. top.area = top.area ? top.area : ''
  1167. top.city = top.city ? top.city : ''
  1168. top.sortprice = top.sortprice ? utils.formatMoney(top.sortprice / 10000, undefined, true) : ''
  1169. top.jgtime = top.jgtime ? dateFormatter(top.jgtime * 1000, 'yyyy-MM-dd') : ''
  1170. top.winner_s = winners
  1171. return top
  1172. })
  1173. if (this.sections.projectScatter.chartData) {
  1174. this.sections.projectScatter.dataAlready = true
  1175. }
  1176. },
  1177. // 地区规模分布
  1178. sortAreaScatter (areaList) {
  1179. // const chartData = {
  1180. // columns: ['项目所在地', '项目数量', '项目金额'],
  1181. // rows: [
  1182. // {
  1183. // 项目所在地: '河南',
  1184. // 项目数量: 2,
  1185. // 项目金额: 2222
  1186. // },
  1187. // {
  1188. // 项目所在地: '北京',
  1189. // 项目数量: 22,
  1190. // 项目金额: 565666
  1191. // },
  1192. // {
  1193. // 项目所在地: '浙江',
  1194. // 项目数量: 22,
  1195. // 项目金额: 765666
  1196. // }
  1197. // ]
  1198. // }
  1199. const areaChartData = {
  1200. columns: ['项目所在地', '项目数量'],
  1201. sColumns: ['项目金额'],
  1202. rows: []
  1203. }
  1204. let total = 0
  1205. if (areaList && Array.isArray(areaList)) {
  1206. const field = {
  1207. [areaChartData.columns[0]]: 'area',
  1208. [areaChartData.columns[1]]: 'total',
  1209. [areaChartData.sColumns[0]]: 'amount'
  1210. }
  1211. areaList.forEach(item => {
  1212. const row = {}
  1213. areaChartData.columns.concat(areaChartData.sColumns).forEach(column => {
  1214. if (field[column] === 'amount') {
  1215. row[column] = utils.formatMoney(item[field[column]] / 10000, undefined, true) - 0
  1216. } else {
  1217. row[column] = item[field[column]]
  1218. }
  1219. if (field[column] === 'amount' || field[column] === 'total') {
  1220. total += (item[field[column]] - 0)
  1221. }
  1222. })
  1223. areaChartData.rows.push(row)
  1224. })
  1225. }
  1226. if (total) {
  1227. this.$set(this.sections.areaScatter, 'chartData', areaChartData)
  1228. this.sections.areaScatter.dataAlready = true
  1229. }
  1230. },
  1231. // 客户分布
  1232. sortUserScatter (userList) {
  1233. if (Array.isArray(userList)) {
  1234. this.sections.userScatter.list = userList.map(item => {
  1235. item.name = item.buyclass
  1236. item.value = item.total
  1237. item.amount = utils.formatMoney(item.amount / 10000, undefined, true)
  1238. return item
  1239. })
  1240. }
  1241. },
  1242. // 地区分布及客户分布Top3
  1243. sortAreaUserTop3 (data) {
  1244. if (data.scaleAreaCountTop || data.scaleAreaAmountTop) {
  1245. this.sorAreaTop3(data)
  1246. }
  1247. if (data.scaleBuyclassCountTop || data.scaleBuyclassAmountTop) {
  1248. this.sorUserTop3(data)
  1249. }
  1250. },
  1251. sorAreaTop3 (data) {
  1252. const tableDataCount = {
  1253. columns: ['序号', '地区:项目数量(个),占比', '前3中标单位:中标数量(个)'], // ,该地区占比
  1254. rows: []
  1255. }
  1256. const tableDataAmount = {
  1257. columns: ['序号', '地区:项目金额(万元),占比', '前3中标单位:中标金额(万元)'], // ,该地区占比
  1258. rows: []
  1259. }
  1260. const scaleAreaCountTop3 = data.scaleAreaCountTop
  1261. if (Array.isArray(scaleAreaCountTop3)) {
  1262. scaleAreaCountTop3.forEach((item, index) => {
  1263. item.name = item.name
  1264. item.subInfo1 = item.area_count ? `项目数量:${item.area_count}个` : ''
  1265. item.subInfo2 = item.area_scale ? `全国占比:${utils.formatMoney(item.area_scale * 100, undefined, true)}%` : ''
  1266. item.actionText = `中标单位 TOP3`
  1267. item.childrenShow = true
  1268. item.children = []
  1269. if (Array.isArray(item.winner)) {
  1270. item.winner.forEach((w, i) => {
  1271. const row = {
  1272. name: w.winner,
  1273. id: w.id,
  1274. type: 'winner',
  1275. subInfo1: w.winner_total ? `中标个数:${w.winner_total}个` : '',
  1276. // subInfo2: w.total_scale ? `地区占比:${utils.formatMoney(w.total_scale * 100, undefined, true)}%` : 0
  1277. }
  1278. item.children.push(row)
  1279. })
  1280. }
  1281. })
  1282. tableDataCount.rows = scaleAreaCountTop3
  1283. }
  1284. const scaleAreaAmountTop3 = data.scaleAreaAmountTop
  1285. if (Array.isArray(scaleAreaAmountTop3)) {
  1286. scaleAreaAmountTop3.forEach((item, index) => {
  1287. item.name = item.name
  1288. item.subInfo1 = item.area_amount ? `中标金额:${utils.formatMoney(item.area_amount / 10000, undefined, true)}万元` : ''
  1289. item.subInfo2 = item.area_scale ? `全国占比:${utils.formatMoney(item.area_scale * 100, undefined, true)}%` : ''
  1290. item.actionText = `中标单位 TOP3`
  1291. item.childrenShow = true
  1292. item.children = []
  1293. if (Array.isArray(item.winner)) {
  1294. item.winner.forEach((w, i) => {
  1295. const row = {
  1296. name: w.winner,
  1297. id: w.id,
  1298. type: 'winner',
  1299. subInfo1: w.winner_amount ? `中标金额:${utils.formatMoney(w.winner_amount / 10000, undefined, true)}万元` : '',
  1300. // subInfo2: w.amount_scale ? `地区占比:${utils.formatMoney(w.amount_scale * 100, undefined, true)}%` : ''
  1301. }
  1302. item.children.push(row)
  1303. })
  1304. }
  1305. })
  1306. tableDataAmount.rows = scaleAreaAmountTop3
  1307. }
  1308. if (tableDataCount.rows.length) {
  1309. this.$set(this.sections.areaScatter, 'projectCountTop3', tableDataCount.rows)
  1310. }
  1311. if (tableDataAmount.rows.length) {
  1312. this.$set(this.sections.areaScatter, 'projectAmountTop3', tableDataAmount.rows)
  1313. }
  1314. },
  1315. sorUserTop3 (data) {
  1316. const tableDataCount = {
  1317. columns: ['序号', '客户类型:项目数量(个),占比', '前3中标单位:中标数量(个)'], // ,该客户类型占比
  1318. rows: []
  1319. }
  1320. const tableDataAmount = {
  1321. columns: ['序号', '客户类型:项目金额(万元),占比', '前3中标单位:中标金额(万元)'], // ,该客户类型占比
  1322. rows: []
  1323. }
  1324. const countTop3 = data.scaleBuyclassCountTop
  1325. if (Array.isArray(countTop3)) {
  1326. countTop3.forEach((item, index) => {
  1327. item.name = item.name
  1328. item.subInfo1 = item.buyclass_count ? `项目数量:${item.buyclass_count}个` : ''
  1329. item.subInfo2 = item.buyclass_scale ? `全部占比:${utils.formatMoney(item.buyclass_scale * 100, undefined, true)}%` : ''
  1330. item.actionText = `中标单位 TOP3`
  1331. item.childrenShow = true
  1332. item.children = []
  1333. if (Array.isArray(item.winner)) {
  1334. item.winner.forEach((w, i) => {
  1335. const row = {
  1336. name: w.winner,
  1337. id: w.id,
  1338. type: 'winner',
  1339. subInfo1: w.winner_total ? `中标个数:${w.winner_total}个` : '',
  1340. // subInfo2: w.total_scale ? `该行业占比:${utils.formatMoney(w.total_scale * 100, undefined, true)}%` : ''
  1341. }
  1342. item.children.push(row)
  1343. })
  1344. }
  1345. })
  1346. tableDataCount.rows = countTop3
  1347. }
  1348. const amountTop3 = data.scaleBuyclassAmountTop
  1349. if (Array.isArray(amountTop3)) {
  1350. amountTop3.forEach((item, index) => {
  1351. item.name = item.name
  1352. item.subInfo1 = item.buyclass_amount ? `项目金额:${utils.formatMoney(item.buyclass_amount / 10000, undefined, true)}万元` : ''
  1353. item.subInfo2 = item.buyclass_scale ? `全部占比:${utils.formatMoney(item.buyclass_scale * 100, undefined, true)}%` : 0
  1354. item.actionText = `中标单位 TOP3`
  1355. item.childrenShow = true
  1356. item.children = []
  1357. if (Array.isArray(item.winner)) {
  1358. item.winner.forEach((w, i) => {
  1359. const row = {
  1360. name: w.winner,
  1361. id: w.id,
  1362. type: 'winner',
  1363. subInfo1: w.winner_amount ? `中标金额:${utils.formatMoney(w.winner_amount / 10000, undefined, true)}万元` : '',
  1364. // subInfo2: w.amount_scale ? `该行业占比:${utils.formatMoney(w.amount_scale * 100, undefined, true)}%` : ''
  1365. }
  1366. item.children.push(row)
  1367. })
  1368. }
  1369. })
  1370. tableDataAmount.rows = amountTop3
  1371. }
  1372. if (tableDataCount.rows.length) {
  1373. this.$set(this.sections.userScatter, 'projectCountTop3', tableDataCount.rows)
  1374. }
  1375. if (tableDataAmount.rows.length) {
  1376. this.$set(this.sections.userScatter, 'projectAmountTop3', tableDataAmount.rows)
  1377. }
  1378. },
  1379. // 细分市场
  1380. sortMarketRefineData (data) {
  1381. const refineCount = {
  1382. columns: ['行业', '项目数量'],
  1383. rows: []
  1384. }
  1385. const refineAmount = {
  1386. columns: ['行业', '项目金额'],
  1387. rows: []
  1388. }
  1389. let total = 0
  1390. const refineAll = data.scaleRefineAll
  1391. if (Array.isArray(refineAll)) {
  1392. const field = {
  1393. 行业: 'name',
  1394. 项目数量: 'total',
  1395. 项目金额: 'amount'
  1396. }
  1397. refineAll.forEach(item => {
  1398. const row = {}
  1399. for (const key in field) {
  1400. if (field[key] === 'amount') {
  1401. row[key] = utils.formatMoney(item[field[key]] / 10000, undefined, true)
  1402. } else {
  1403. row[key] = item[field[key]]
  1404. }
  1405. if (field[key] === 'total' || field[key] === 'amount') {
  1406. total += (item[field[key]] - 0)
  1407. }
  1408. }
  1409. refineCount.rows.push(row)
  1410. refineAmount.rows.push(row)
  1411. })
  1412. }
  1413. if (total) {
  1414. this.$set(this.sections.market.refine, 'projectCountData', refineCount)
  1415. this.$set(this.sections.market.refine, 'projectAmountData', refineAmount)
  1416. this.sections.market.refine.dataAlready = true
  1417. }
  1418. this.sortRefineTop3(data)
  1419. },
  1420. sortRefineTop3 (data) {
  1421. const tableDataCount = {
  1422. columns: ['序号', '细分市场:项目数量(个)', '前3中标单位:中标数量(个)'], // ,占比,该细分市场占比
  1423. rows: []
  1424. }
  1425. const tableDataAmount = {
  1426. columns: ['序号', '细分市场:项目金额(万元)', '前3中标单位:中标金额(万元)'], // ,占比,该细分市场占比
  1427. rows: []
  1428. }
  1429. const countTop3 = data.scaleRefineTotalTop
  1430. if (Array.isArray(countTop3)) {
  1431. countTop3.forEach((item, index) => {
  1432. item.name = item.name
  1433. item.subInfo1 = item.value ? `项目数量:${item.value}个` : ''
  1434. // item.subInfo2 = item.prop ? `全部占比:${utils.formatMoney(item.prop * 100, undefined, true)}%` : 0
  1435. item.actionText = `中标单位 TOP3`
  1436. item.childrenShow = true
  1437. item.children = []
  1438. if (Array.isArray(item.topList)) {
  1439. item.topList.forEach((w, i) => {
  1440. const row = {
  1441. name: w.name,
  1442. id: w.id,
  1443. type: 'winner',
  1444. subInfo1: w.value ? `中标个数:${w.value}个` : '',
  1445. // subInfo2: w.prop ? `该细分市场占比:${utils.formatMoney(w.prop * 100, undefined, true)}%` : ''
  1446. }
  1447. item.children.push(row)
  1448. })
  1449. }
  1450. })
  1451. tableDataCount.rows = countTop3
  1452. }
  1453. const amountTop3 = data.scaleRefineAmountTop
  1454. if (Array.isArray(amountTop3)) {
  1455. amountTop3.forEach((item, index) => {
  1456. item.name = item.name
  1457. item.subInfo1 = item.value ? `项目金额:${utils.formatMoney(item.value / 10000, undefined, true)}万元` : ''
  1458. // item.subInfo2 = item.prop ? `全部占比:${utils.formatMoney(item.prop * 100, undefined, true)}%` : 0
  1459. item.actionText = `中标单位 TOP3`
  1460. item.childrenShow = true
  1461. item.children = []
  1462. if (Array.isArray(item.topList)) {
  1463. item.topList.forEach((w, i) => {
  1464. const row = {
  1465. name: w.name,
  1466. id: w.id,
  1467. type: 'winner',
  1468. subInfo1: w.value ? `中标金额:${utils.formatMoney(w.value / 10000, undefined, true)}万元` : '',
  1469. // subInfo2: w.prop ? `该细分市场占比:${utils.formatMoney(w.prop * 100, undefined, true)}%`: ''
  1470. }
  1471. item.children.push(row)
  1472. })
  1473. }
  1474. })
  1475. tableDataAmount.rows = amountTop3
  1476. }
  1477. if (tableDataCount.rows.length) {
  1478. this.$set(this.sections.market.refine, 'projectCountTop3', tableDataCount.rows)
  1479. }
  1480. if (tableDataAmount.rows.length) {
  1481. this.$set(this.sections.market.refine, 'projectAmountTop3', tableDataAmount.rows)
  1482. }
  1483. },
  1484. // 采购单位
  1485. sortBuyerclassData (data) {
  1486. const buyerclassChartData = {
  1487. columns: ['金额区间', '采购总金额占比', '采购单位数量占比'],
  1488. rows: []
  1489. }
  1490. let total = 0
  1491. const buyerclassList = data.buyer_time_distribution
  1492. if (Array.isArray(buyerclassList)) {
  1493. const field = {
  1494. [buyerclassChartData.columns[0]]: 'key',
  1495. [buyerclassChartData.columns[1]]: 'total_amount',
  1496. [buyerclassChartData.columns[2]]: 'total_number'
  1497. }
  1498. buyerclassList.forEach(item => {
  1499. const row = {}
  1500. buyerclassChartData.columns.forEach(column => {
  1501. if (field[column] === 'total_amount' || field[column] === 'total_number') {
  1502. row[column] = (item[field[column]] * 100).toFixed(2)
  1503. total += (item[field[column]] - 0)
  1504. } else {
  1505. row[column] = item[field[column]]
  1506. }
  1507. })
  1508. buyerclassChartData.rows.push(row)
  1509. })
  1510. }
  1511. if (total) {
  1512. buyerclassChartData.rows.reverse()
  1513. this.$set(this.sections.buyerclass, 'chartData', buyerclassChartData)
  1514. this.sections.buyerclass.dataAlready = true
  1515. }
  1516. this.sortBuyerclassTableData(data)
  1517. },
  1518. sortBuyerclassTableData (data) {
  1519. const dataCount = {
  1520. columns: ['序号', '采购单位:采购数量(个)', '前3中标单位:中标数量(个)'], //,占比 | ,占该采购单位
  1521. rows: []
  1522. }
  1523. const dataAmount = {
  1524. columns: ['序号', '采购单位:采购金额(万元)', '前3中标单位:中标金额(万元)'], //,占比 | ,占该采购单位
  1525. rows: []
  1526. }
  1527. const countTop3 = data.buyer_count_top3
  1528. if (Array.isArray(countTop3)) {
  1529. countTop3.forEach((item, index) => {
  1530. item.name = item.name
  1531. item.type = 'buyer'
  1532. item.id = item.name
  1533. item.subInfo1 = item.number ? `项目数量:${item.number}个` : ''
  1534. // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
  1535. item.actionText = `中标单位 TOP3`
  1536. item.childrenShow = true
  1537. item.children = []
  1538. if (Array.isArray(item.winnertop3)) {
  1539. item.winnertop3.forEach((w, i) => {
  1540. const row = {
  1541. name: w.name,
  1542. id: w.id,
  1543. type: 'winner',
  1544. subInfo1: w.number ? `中标个数:${w.number}个` : '',
  1545. // subInfo2: w.accounted ? `占该采购单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
  1546. }
  1547. item.children.push(row)
  1548. })
  1549. }
  1550. })
  1551. dataCount.rows = countTop3
  1552. }
  1553. const amountTop3 = data.buyer_amount_top3
  1554. if (Array.isArray(amountTop3)) {
  1555. amountTop3.forEach((item, index) => {
  1556. item.name = item.name
  1557. item.type = 'buyer'
  1558. item.id = item.name
  1559. item.subInfo1 = item.amount ? `采购金额:${utils.formatMoney(item.amount / 10000, undefined, true)}万元` : ''
  1560. // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
  1561. item.actionText = `中标单位 TOP3`
  1562. item.childrenShow = true
  1563. item.children = []
  1564. if (Array.isArray(item.winnertop3)) {
  1565. item.winnertop3.forEach((w, i) => {
  1566. const row = {
  1567. name: w.name,
  1568. id: w.id,
  1569. type: 'winner',
  1570. subInfo1: w.amount ? `中标金额:${utils.formatMoney(w.amount / 10000, undefined, true)}万元` : '',
  1571. // subInfo2: w.accounted ? `该行业占比:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
  1572. }
  1573. item.children.push(row)
  1574. })
  1575. }
  1576. })
  1577. dataAmount.rows = amountTop3
  1578. }
  1579. if (dataCount.rows.length) {
  1580. this.$set(this.sections.buyerclass, 'projectCountTop3', dataCount.rows)
  1581. }
  1582. if (dataAmount.rows.length) {
  1583. this.$set(this.sections.buyerclass, 'projectAmountTop3', dataAmount.rows)
  1584. }
  1585. },
  1586. // 中标单位
  1587. sortWinnerData (data) {
  1588. const chartData = {
  1589. columns: ['金额区间', '中标总金额占比', '中标单位数量占比'],
  1590. rows: []
  1591. }
  1592. let total = 0
  1593. const chartLIst = data.winner_time_distribution
  1594. if (Array.isArray(chartLIst)) {
  1595. const field = {
  1596. [chartData.columns[0]]: 'key',
  1597. [chartData.columns[1]]: 'total_amount',
  1598. [chartData.columns[2]]: 'total_number'
  1599. }
  1600. chartLIst.forEach(item => {
  1601. const row = {}
  1602. chartData.columns.forEach(column => {
  1603. if (field[column] === 'total_amount' || field[column] === 'total_number') {
  1604. row[column] = (item[field[column]] * 100).toFixed(2)
  1605. total += (item[field[column]] - 0)
  1606. } else {
  1607. row[column] = item[field[column]]
  1608. }
  1609. })
  1610. chartData.rows.push(row)
  1611. })
  1612. }
  1613. if (total) {
  1614. chartData.rows.reverse()
  1615. this.$set(this.sections.winner, 'chartData', chartData)
  1616. this.sections.winner.dataAlready = true
  1617. }
  1618. this.sortWinnerTableData(data)
  1619. },
  1620. sortWinnerTableData (data) {
  1621. const dataCount = {
  1622. columns: ['序号', '中标单位:中标数量(个)', '前3采购单位:采购数量(个)'], // ,占比 | ,占该中标单位
  1623. rows: []
  1624. }
  1625. const dataAmount = {
  1626. columns: ['序号', '中标单位:中标金额(万元),占比', '前3采购单位:采购金额(万元),占该中标单位'], // ,占比 | ,占该中标单位
  1627. rows: []
  1628. }
  1629. const countTop3 = data.winner_count_top3
  1630. if (Array.isArray(countTop3)) {
  1631. countTop3.forEach((item, index) => {
  1632. item.name = item.name
  1633. item.type = 'winner'
  1634. item.id = item.id
  1635. item.subInfo1 = item.number ? `中标数量:${item.number}个` : ''
  1636. // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
  1637. item.actionText = `采购单位 TOP3`
  1638. item.childrenShow = true
  1639. item.children = []
  1640. if (Array.isArray(item.buyertop3)) {
  1641. item.buyertop3.forEach((w, i) => {
  1642. const row = {
  1643. name: w.name,
  1644. id: w.name,
  1645. type: 'buyer',
  1646. subInfo1: w.number ? `采购数量:${w.number}个` : '',
  1647. // subInfo2: w.accounted ? `占该中标单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
  1648. }
  1649. item.children.push(row)
  1650. })
  1651. }
  1652. })
  1653. dataCount.rows = countTop3
  1654. }
  1655. const amountTop3 = data.winner_amount_top3
  1656. if (Array.isArray(amountTop3)) {
  1657. amountTop3.forEach((item, index) => {
  1658. item.name = item.name
  1659. item.type = 'winner'
  1660. item.id = item.id
  1661. item.subInfo1 = item.amount ? `中标金额:${utils.formatMoney(item.amount / 10000, undefined, true)}万元` : ''
  1662. // item.subInfo2 = item.accounted ? `全部占比:${utils.formatMoney(item.accounted * 100, undefined, true)}%` : ''
  1663. item.actionText = `采购单位 TOP3`
  1664. item.childrenShow = true
  1665. item.children = []
  1666. if (Array.isArray(item.buyertop3)) {
  1667. item.buyertop3.forEach((w, i) => {
  1668. const row = {
  1669. name: w.name,
  1670. id: w.name,
  1671. type: 'buyer',
  1672. subInfo1: w.amount ? `采购金额:${utils.formatMoney(w.amount / 10000, undefined, true)}万元` : '',
  1673. // subInfo2: w.accounted ? `占该中标单位:${utils.formatMoney(w.accounted * 100, undefined, true)}%` : ''
  1674. }
  1675. item.children.push(row)
  1676. })
  1677. }
  1678. })
  1679. dataAmount.rows = amountTop3
  1680. }
  1681. if (dataCount.rows.length) {
  1682. this.$set(this.sections.winner, 'projectCountTop3', dataCount.rows)
  1683. }
  1684. if (dataAmount.rows.length) {
  1685. this.$set(this.sections.winner, 'projectAmountTop3', dataAmount.rows)
  1686. }
  1687. },
  1688. toAnalysisPage: function () {
  1689. this.rid = ''
  1690. this.analysis.loaded = false
  1691. this.filtersPageShow = true
  1692. },
  1693. moneyUnit (num, type, lv) {
  1694. const m = utils.moneyUnit(num, type, lv)
  1695. let unit = String(m).match(/[\u4e00-\u9fa5]/g)
  1696. if (unit && Array.isArray(unit)) {
  1697. unit = unit.join('')
  1698. } else {
  1699. unit = ''
  1700. }
  1701. let count = ''
  1702. if (unit) {
  1703. count = m.replace(unit, '') - 0
  1704. }
  1705. return {
  1706. unit,
  1707. count
  1708. }
  1709. },
  1710. anchorTo (item) {
  1711. // if (!item.top) return
  1712. var offsetTop = item.top || 0
  1713. this.activeDimension = item.id
  1714. this.$nextTick(function () {
  1715. $('.search-result > .j-main')[0].scrollTop = offsetTop
  1716. })
  1717. },
  1718. showSetKeyTip: function () {
  1719. this.notSetKey = true
  1720. },
  1721. setKeyTip: function () {
  1722. this.showDialog({
  1723. title: '',
  1724. message: '分析内容为您订阅的关键词组,您<br />当前尚未订阅,请前往完善',
  1725. className: 'j-confirm-dialog text-center',
  1726. showConfirmButton: true,
  1727. showCancelButton: true,
  1728. confirmButtonText: '订阅管理',
  1729. confirmButtonColor: '#2abed1'
  1730. }).then(() => {
  1731. if (this.isSubCount) {
  1732. // 提示联系管理员
  1733. this.showToast('请联系管理员完善订阅的关键词')
  1734. // this.showDialog({
  1735. // title: '',
  1736. // message: '请联系管理员完善订阅的关键词',
  1737. // className: 'j-confirm-dialog text-center',
  1738. // showConfirmButton: true,
  1739. // showCancelButton: false,
  1740. // confirmButtonText: '我知道了',
  1741. // confirmButtonColor: '#2abed1'
  1742. // })
  1743. } else {
  1744. this.toSubManage()
  1745. }
  1746. })
  1747. },
  1748. toSubManageButtonClick: function () {
  1749. if (this.isSubCount) {
  1750. this.showToast('请联系管理员完善订阅的关键词')
  1751. } else {
  1752. this.toSubManage()
  1753. }
  1754. },
  1755. toSubManage: function () {
  1756. this.isWeixin = utils.isWeiXinBrowser
  1757. let rootlink = 'f'
  1758. if (this.powerInfo.memberStatus > 0) {
  1759. rootlink = 'm'
  1760. } else if (this.powerInfo.vipStatus > 0) {
  1761. rootlink = 'v'
  1762. } else {
  1763. rootlink = 'f'
  1764. }
  1765. if(this.isWeixin) {
  1766. location.href = '/front/vipsubscribe/toSetKeyWordPage?vSwitch=' + rootlink
  1767. } else {
  1768. location.href = '/jyapp/vipsubscribe/toSetKeyWordPage?vSwitch=' + rootlink
  1769. }
  1770. },
  1771. toArticleContent (item) {
  1772. this.saveState()
  1773. location.href = `/jyapp/article/content/${item._id}.html`
  1774. },
  1775. toPortrait (id, type) {
  1776. if (!type || !id) return
  1777. this.saveState()
  1778. if (type === 'winner') {
  1779. location.href = `./ent_portrait?eId=${id}`
  1780. } else if (type === 'buyer') {
  1781. location.href = `./unit_portrayal?entName=${id}`
  1782. }
  1783. }
  1784. }
  1785. })