index.vue 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. <template>
  2. <div class="autoLaunchReport">
  3. <div class="topOptions">
  4. <span class="OptinItem" style="position: relative; top: 12px; margin-right: 20px">
  5. <Treeselect
  6. :appId.sync="accountIds"
  7. :multiple="true"
  8. request="2,4"
  9. ref="treeSelect"
  10. style="width: 600px"
  11. :limit="1"
  12. />
  13. </span>
  14. <span class="OptinItem">
  15. <a-range-picker @change="dateChange" v-model="dateRange" :disabled-date="disabledDate" style="width: 300px" />
  16. </span>
  17. <span>
  18. <a-button type="primary" style="position: absolute; right: 10px; top: 45px" @click="search">查询</a-button>
  19. <!-- <a-button type='default' @click="reset">重置</a-button> -->
  20. </span>
  21. </div>
  22. <div class="chartBox">
  23. <div class="chartTop">
  24. <span>数据维度:</span>
  25. <a-radio-group v-model="value" @change="chartDataTypeChange">
  26. <a-radio :value="1"> 封面曝光数 </a-radio>
  27. <a-radio :value="2"> 封面点击数 </a-radio>
  28. <a-radio :value="3"> 素材曝光数 </a-radio>
  29. <a-radio :value="4"> 行为数 </a-radio>
  30. <a-radio :value="5"> 封面点击率 </a-radio>
  31. <a-radio :value="6"> 行为点击率 </a-radio>
  32. </a-radio-group>
  33. </div>
  34. <a-spin :spinning="spinning">
  35. <div class="chartBody">
  36. <div
  37. id="mapEchart"
  38. style="width: 30%; height: 300px; border: 1px solid #e0e0e0; padding: 10px; line-height: 300px"
  39. ref="mapEchart"
  40. >
  41. <a-empty style="position: relative; top: 50%; margin-top: -65px" />
  42. </div>
  43. <div
  44. id="sexEchart"
  45. style="width: 30%; height: 300px; border: 1px solid #e0e0e0; padding: 10px"
  46. ref="sexEchart"
  47. >
  48. <a-empty style="position: relative; top: 50%; margin-top: -65px" />
  49. </div>
  50. <div
  51. id="ageEchart"
  52. style="width: 30%; height: 300px; border: 1px solid #e0e0e0; padding: 10px"
  53. ref="ageEchart"
  54. >
  55. <a-empty style="position: relative; top: 50%; margin-top: -65px" />
  56. </div>
  57. <div
  58. id="businessEchart"
  59. style="width: 65%; height: 300px; border: 1px solid #e0e0e0; padding: 10px; margin-top: 20px"
  60. ref="businessEchart"
  61. >
  62. <a-empty style="position: relative; top: 50%; margin-top: -65px" />
  63. </div>
  64. <div
  65. id="systemEchart"
  66. style="width: 30%; height: 300px; border: 1px solid #e0e0e0; padding: 10px; margin-top: 20px"
  67. ref="systemEchart"
  68. >
  69. <a-empty style="position: relative; top: 50%; margin-top: -65px" />
  70. </div>
  71. </div>
  72. </a-spin>
  73. <div class="tableBox">
  74. <!-- <div class="tableTop">
  75. 关联定向
  76. </div> -->
  77. <div class="tableOpt">
  78. <span>表格类型:</span>
  79. <a-radio-group v-model="tableValue" @change="tableTypeChange">
  80. <a-radio value="province"> 省级地域分布 </a-radio>
  81. <a-radio value="city"> 地级地域分布 </a-radio>
  82. <a-radio value="gender"> 性别分布 </a-radio>
  83. <a-radio value="ageSegment"> 年龄分布 </a-radio>
  84. <a-radio value="clientId"> 系统分布 </a-radio>
  85. <a-radio value="businessInterestTags"> 商业兴趣分布 </a-radio>
  86. </a-radio-group>
  87. </div>
  88. <div class="tableBody">
  89. <a-table
  90. size="middle"
  91. :columns="columns"
  92. :dataSource="tableData"
  93. :pagination="ipagination"
  94. bordered
  95. id="outTable"
  96. :loading="materialloading"
  97. style="word-break: break-all; font-size: 16px; font-weight: 600"
  98. :scroll="{ x: true }"
  99. @change="sort"
  100. >
  101. <span slot="charge" slot-scope="charge">{{ charge | decimalsHandle }}</span>
  102. <span slot="eventNextDayStayRatio" slot-scope="eventNextDayStayRatio">{{
  103. eventNextDayStayRatio + '%'
  104. }}</span>
  105. </a-table>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </template>
  111. <script>
  112. import moment from 'moment'
  113. import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
  114. import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
  115. import qs from 'qs'
  116. // 引入基本模板
  117. var echarts = require('echarts')
  118. import 'echarts/map/js/china'
  119. // 引入柱状图组件
  120. require('echarts/lib/chart/bar')
  121. // require('echarts/lib/chart/pie')
  122. require('echarts/lib/chart/line')
  123. require('echarts/lib/chart/map')
  124. // 引入提示框和title组件
  125. require('echarts/lib/component/tooltip')
  126. require('echarts/lib/component/title')
  127. require('echarts/lib/component/graphic')
  128. require('echarts/lib/component/toolbox')
  129. require('echarts/lib/component/legend')
  130. let option = {
  131. color: ['#1890ff'],
  132. tooltip: {
  133. trigger: 'axis',
  134. axisPointer: {
  135. // 坐标轴指示器,坐标轴触发有效
  136. type: 'line', // 默认为直线,可选为:'line' | 'shadow'
  137. },
  138. },
  139. grid: {
  140. left: '0%',
  141. right: '0%',
  142. bottom: '0%',
  143. top: '12%',
  144. containLabel: false,
  145. },
  146. xAxis: [
  147. {
  148. type: 'category',
  149. data: [],
  150. show: true,
  151. axisTick: {
  152. alignWithLabel: true,
  153. },
  154. },
  155. ],
  156. yAxis: [
  157. {
  158. type: 'value',
  159. show: false,
  160. },
  161. ],
  162. series: [
  163. {
  164. name: '',
  165. type: 'bar',
  166. barWidth: '40%',
  167. smooth: true,
  168. areaStyle: {},
  169. itemStyle: {
  170. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  171. { offset: 0, color: '#1890ff' },
  172. { offset: 1, color: '#FFF' },
  173. ]),
  174. },
  175. data: [],
  176. },
  177. ],
  178. }
  179. const regionColumns = [
  180. {
  181. title: '消耗',
  182. dataIndex: 'charge',
  183. key: 'charge',
  184. align: 'center',
  185. scopedSlots: { customRender: 'charge' },
  186. sorter: true,
  187. },
  188. {
  189. title: '次留数',
  190. dataIndex: 'eventNextDayStay',
  191. key: 'eventNextDayStay',
  192. align: 'center',
  193. scopedSlots: { customRender: 'eventNextDayStay' },
  194. sorter: true,
  195. },
  196. {
  197. title: '次留率',
  198. dataIndex: 'eventNextDayStayRatio',
  199. key: 'eventNextDayStayRatio',
  200. align: 'center',
  201. scopedSlots: { customRender: 'eventNextDayStayRatio' },
  202. sorter: true,
  203. },
  204. {
  205. title: '激活数',
  206. dataIndex: 'activation',
  207. key: 'activation',
  208. align: 'center',
  209. scopedSlots: { customRender: 'activation' },
  210. sorter: true,
  211. },
  212. // {
  213. // title: '地域',
  214. // dataIndex: 'region',
  215. // key: 'region',
  216. // align: 'center',
  217. // scopedSlots: { customRender: 'region' },
  218. // width: 120,
  219. // fixed: 'left',
  220. // },
  221. // {
  222. // title: '地域',
  223. // dataIndex: 'region',
  224. // key: 'region',
  225. // align: 'center',
  226. // scopedSlots: { customRender: 'region' },
  227. // width: 120,
  228. // fixed: 'left',
  229. // },
  230. // {
  231. // title: '地域',
  232. // dataIndex: 'region',
  233. // key: 'region',
  234. // align: 'center',
  235. // scopedSlots: { customRender: 'region' },
  236. // width: 120,
  237. // fixed: 'left',
  238. // },
  239. // {
  240. // title: '地域',
  241. // dataIndex: 'region',
  242. // key: 'region',
  243. // align: 'center',
  244. // scopedSlots: { customRender: 'region' },
  245. // width: 120,
  246. // fixed: 'left',
  247. // },
  248. // {
  249. // title: '地域',
  250. // dataIndex: 'region',
  251. // key: 'region',
  252. // align: 'center',
  253. // scopedSlots: { customRender: 'region' },
  254. // width: 120,
  255. // fixed: 'left',
  256. // },
  257. // {
  258. // title: '地域',
  259. // dataIndex: 'region',
  260. // key: 'region',
  261. // align: 'center',
  262. // scopedSlots: { customRender: 'region' },
  263. // width: 120,
  264. // fixed: 'left',
  265. // },
  266. ]
  267. const province = [
  268. {
  269. title: '省份',
  270. dataIndex: 'province',
  271. key: 'province',
  272. align: 'center',
  273. scopedSlots: { customRender: 'province' },
  274. },
  275. ]
  276. const city = [
  277. {
  278. title: '城市',
  279. dataIndex: 'city',
  280. key: 'city',
  281. align: 'center',
  282. scopedSlots: { customRender: 'city' },
  283. },
  284. ]
  285. const ageSegment = [
  286. {
  287. title: '年龄',
  288. dataIndex: 'ageSegment',
  289. key: 'ageSegment',
  290. align: 'center',
  291. scopedSlots: { customRender: 'ageSegment' },
  292. },
  293. ]
  294. const gender = [
  295. {
  296. title: '性别',
  297. dataIndex: 'gender',
  298. key: 'gender',
  299. align: 'center',
  300. scopedSlots: { customRender: 'gender' },
  301. },
  302. ]
  303. const businessInterestTags = [
  304. {
  305. title: '商业兴趣',
  306. dataIndex: 'businessInterestTags',
  307. key: 'businessInterestTags',
  308. align: 'center',
  309. scopedSlots: { customRender: 'businessInterestTags' },
  310. },
  311. ]
  312. const client = [
  313. {
  314. title: '系统',
  315. dataIndex: 'client',
  316. key: 'client',
  317. align: 'center',
  318. scopedSlots: { customRender: 'client' },
  319. },
  320. ]
  321. export default {
  322. components: {
  323. Treeselect,
  324. },
  325. data() {
  326. return {
  327. order: '',
  328. target: '',
  329. searchShow: true,
  330. spinning: false,
  331. materialId: [],
  332. treeData: [],
  333. materialTreeData: [],
  334. userId: '',
  335. tabKey: 1,
  336. loading: false,
  337. ipagination: {
  338. current: 1,
  339. pageSize: 10,
  340. // pageSizeOptions: ['10', '20', '30'],
  341. showTotal: (total, range) => {
  342. return range[0] + '-' + range[1] + ' 共' + total + '条'
  343. },
  344. showQuickJumper: true,
  345. showSizeChanger: true,
  346. pageSizeOptions: ['10', '30', '50'],
  347. total: 0,
  348. onChange: (current, pageSize) => {
  349. // 切换分页时的回调,
  350. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  351. this.ipagination.current = current
  352. this.ipagination.pageSize = pageSize
  353. },
  354. },
  355. tableValue: 'province',
  356. accountIds: [],
  357. accountList: [],
  358. directionalId: undefined,
  359. value: 1,
  360. columns: [...province, ...regionColumns],
  361. tableData: [],
  362. dateRange: [moment().subtract(2, 'day'), moment().subtract(2, 'day')],
  363. topOption: JSON.parse(JSON.stringify(option)),
  364. scrollX: 0,
  365. materialipagination: {
  366. current: 1,
  367. pageSize: 10,
  368. // pageSizeOptions: ['10', '20', '30'],
  369. showTotal: (total, range) => {
  370. return range[0] + '-' + range[1] + ' 共' + total + '条'
  371. },
  372. showQuickJumper: true,
  373. showSizeChanger: true,
  374. pageSizeOptions: ['10', '30', '50'],
  375. total: 0,
  376. onChange: (current, pageSize) => {
  377. // 切换分页时的回调,
  378. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  379. this.ipagination.current = current
  380. this.ipagination.pageSize = pageSize
  381. },
  382. },
  383. materialtableData: [],
  384. materialloading: false,
  385. materialscrollX: 4000,
  386. province: [],
  387. provinceData: [],
  388. sexData: [],
  389. ageData: [],
  390. businessData: [],
  391. systemData: [],
  392. }
  393. },
  394. methods: {
  395. filterOption(input, option) {
  396. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  397. },
  398. disabledDate(current) {
  399. return current && current > moment().subtract(2, 'day')
  400. },
  401. dateChange(date, dateString) {
  402. // console.log(date,dateString)
  403. },
  404. chartDataTypeChange(e) {
  405. this.getEchartData()
  406. },
  407. tableTypeChange(e) {
  408. // console.log('radio checked', e.target.value)
  409. if (e.target.value == 'province') {
  410. this.columns = [...province, ...regionColumns]
  411. } else if (e.target.value == 'city') {
  412. this.columns = [...city, ...regionColumns]
  413. } else if (e.target.value == 'gender') {
  414. this.columns = [...gender, ...regionColumns]
  415. } else if (e.target.value == 'ageSegment') {
  416. this.columns = [...ageSegment, ...regionColumns]
  417. } else if (e.target.value == 'clientId') {
  418. this.columns = [...client, ...regionColumns]
  419. } else if (e.target.value == 'businessInterestTags') {
  420. this.columns = [...businessInterestTags, ...regionColumns]
  421. }
  422. this.ipagination.current = 1
  423. this.getDetailTableData()
  424. },
  425. directionalIdChange(val) {},
  426. //获取echart的值
  427. initEchart(idName, optionName) {
  428. const chart = this.$refs[idName]
  429. // console.log(chart)
  430. if (chart) {
  431. const myChart = echarts.init(document.getElementById(idName))
  432. // myChart.showLoading({
  433. // text: "图表数据正在努力加载..."
  434. // });
  435. myChart.setOption(optionName)
  436. var that = this
  437. window.addEventListener('resize', function () {
  438. that.$nextTick(() => {
  439. myChart.resize()
  440. })
  441. })
  442. }
  443. },
  444. clearEchart(idName) {
  445. const myChart = echarts.init(document.getElementById(idName))
  446. myChart.dispose()
  447. },
  448. // province,data
  449. handlerMapEchartOption(province, data) {
  450. var res = []
  451. var dataEnd = []
  452. var smallValue = [
  453. {
  454. min: 100000,
  455. color: '#73240D',
  456. },
  457. {
  458. min: 50000,
  459. max: 100000,
  460. color: '#BB0000',
  461. },
  462. {
  463. min: 30000,
  464. max: 50000,
  465. color: '#BD430A',
  466. },
  467. {
  468. min: 10000,
  469. max: 30000,
  470. color: '#E08150',
  471. },
  472. {
  473. min: 5000,
  474. max: 10000,
  475. color: '#E9B090',
  476. },
  477. {
  478. min: 1000,
  479. max: 5000,
  480. color: '#F2DDD2',
  481. },
  482. {
  483. value: 0,
  484. color: '#F1eeee',
  485. },
  486. ]
  487. if (this.value == 1) {
  488. res = data.map((item) => {
  489. return item.photoShow
  490. })
  491. } else if (this.value == 2) {
  492. res = data.map((item) => {
  493. return item.photoClick
  494. })
  495. } else if (this.value == 3) {
  496. res = data.map((item) => {
  497. return item.aclick
  498. })
  499. } else if (this.value == 4) {
  500. res = data.map((item) => {
  501. return item.bclick
  502. })
  503. } else if (this.value == 5) {
  504. res = data.map((item) => {
  505. return item.photoClickRatio
  506. })
  507. smallValue = [
  508. {
  509. min: 55,
  510. color: '#73240D',
  511. },
  512. {
  513. min: 45,
  514. max: 55,
  515. color: '#BB0000',
  516. },
  517. {
  518. min: 35,
  519. max: 45,
  520. color: '#BD430A',
  521. },
  522. {
  523. min: 25,
  524. max: 35,
  525. color: '#E08150',
  526. },
  527. {
  528. min: 15,
  529. max: 25,
  530. color: '#E9B090',
  531. },
  532. {
  533. min: 5,
  534. max: 15,
  535. color: '#F2DDD2',
  536. },
  537. {
  538. value: 0,
  539. color: '#F1eeee',
  540. },
  541. ]
  542. } else if (this.value == 6) {
  543. res = data.map((item) => {
  544. return item.actionRatio
  545. })
  546. smallValue = [
  547. {
  548. min: 55,
  549. color: '#73240D',
  550. },
  551. {
  552. min: 45,
  553. max: 55,
  554. color: '#BB0000',
  555. },
  556. {
  557. min: 35,
  558. max: 45,
  559. color: '#BD430A',
  560. },
  561. {
  562. min: 25,
  563. max: 35,
  564. color: '#E08150',
  565. },
  566. {
  567. min: 15,
  568. max: 25,
  569. color: '#E9B090',
  570. },
  571. {
  572. min: 5,
  573. max: 15,
  574. color: '#F2DDD2',
  575. },
  576. {
  577. value: 0,
  578. color: '#F1eeee',
  579. },
  580. ]
  581. }
  582. for (var j = 0; j < province.length; j++) {
  583. dataEnd.push({
  584. name: province[j],
  585. value: res[j],
  586. })
  587. }
  588. var that = this
  589. var option = {
  590. title: {
  591. text: '省级地域分布',
  592. // subtext: '仅供参考',
  593. left: 'left',
  594. },
  595. tooltip: {
  596. show: true,
  597. formatter: function (params) {
  598. var str = ''
  599. if (that.value == 5 || that.value == 6) {
  600. str = params.name + ':' + (params.value ? params.value + '%' : 0)
  601. } else {
  602. str = params.name + ':' + (params.value ? params.value : 0)
  603. }
  604. return str
  605. },
  606. },
  607. layoutCenter: ['30%', '30%'],
  608. visualMap: {
  609. type: 'piecewise',
  610. // text: ['头', '尾'],
  611. pieces: smallValue,
  612. orient: 'vertical',
  613. itemSymbol: 'circle',
  614. itemWidth: 20,
  615. itemHeight: 20,
  616. showLabel: true,
  617. seriesIndex: [0],
  618. textStyle: {
  619. color: '#7B93A7',
  620. },
  621. bottom: '10%',
  622. left: '5%',
  623. },
  624. grid: {
  625. right: '5%',
  626. top: '20%',
  627. left: '60%',
  628. bottom: '10%',
  629. width: '100%',
  630. x: '40%',
  631. containLabel: true,
  632. },
  633. xAxis: {
  634. min: 0,
  635. // max: 4000,
  636. show: false,
  637. },
  638. geo: {
  639. map: 'china',
  640. // right: '35%',
  641. left: '30%',
  642. label: {
  643. emphasis: {
  644. show: false,
  645. },
  646. },
  647. itemStyle: {
  648. emphasis: {
  649. areaColor: '#99FF99',
  650. },
  651. },
  652. },
  653. series: [
  654. {
  655. name: 'mapSer',
  656. type: 'map',
  657. map: 'china',
  658. roam: false,
  659. geoIndex: 0,
  660. label: {
  661. show: false,
  662. },
  663. data: dataEnd,
  664. },
  665. ],
  666. }
  667. return option
  668. },
  669. handlerSexOption(data) {
  670. var res = []
  671. if (this.value == 1) {
  672. res = data.map((item) => {
  673. return { value: item.photoShow, name: item.gender }
  674. })
  675. } else if (this.value == 2) {
  676. res = data.map((item) => {
  677. return { value: item.photoClick, name: item.gender }
  678. })
  679. } else if (this.value == 3) {
  680. res = data.map((item) => {
  681. return { value: item.aclick, name: item.gender }
  682. })
  683. } else if (this.value == 4) {
  684. res = data.map((item) => {
  685. return { value: item.bclick, name: item.gender }
  686. })
  687. } else if (this.value == 5) {
  688. res = data.map((item) => {
  689. return { value: item.photoClickRatio, name: item.gender }
  690. })
  691. } else if (this.value == 6) {
  692. res = data.map((item) => {
  693. return { value: item.actionRatio, name: item.gender }
  694. })
  695. }
  696. var option = {
  697. color: ['#37a2da', '#32c5e9', '#9fe6b8', '#ffdb5c', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378ea'],
  698. tooltip: {
  699. trigger: 'item',
  700. formatter: '{b} : {c} ',
  701. },
  702. toolbox: {
  703. show: true,
  704. },
  705. title: {
  706. text: '性别分布',
  707. // subtext: '仅供参考',
  708. left: 'left',
  709. },
  710. grid: {
  711. containLabel: true,
  712. },
  713. // legend: {
  714. // type: 'scroll',
  715. // orient: 'vertical',
  716. // left: '10%',
  717. // align: 'left',
  718. // top: 'middle',
  719. // textStyle: {
  720. // color: '#8C8C8C',
  721. // },
  722. // height: 100,
  723. // },
  724. series: [
  725. {
  726. type: 'pie',
  727. radius: [0, 100],
  728. data: res,
  729. minAngle: 10,
  730. },
  731. ],
  732. }
  733. return option
  734. },
  735. handlerAgeOption(data) {
  736. var res = []
  737. if (this.value == 1) {
  738. res = data.map((item) => {
  739. return { value: item.photoShow, name: item.ageSegment }
  740. })
  741. } else if (this.value == 2) {
  742. res = data.map((item) => {
  743. return { value: item.photoClick, name: item.ageSegment }
  744. })
  745. } else if (this.value == 3) {
  746. res = data.map((item) => {
  747. return { value: item.aclick, name: item.ageSegment }
  748. })
  749. } else if (this.value == 4) {
  750. res = data.map((item) => {
  751. return { value: item.bclick, name: item.ageSegment }
  752. })
  753. } else if (this.value == 5) {
  754. res = data.map((item) => {
  755. return { value: item.photoClickRatio, name: item.ageSegment }
  756. })
  757. } else if (this.value == 6) {
  758. res = data.map((item) => {
  759. return { value: item.actionRatio, name: item.ageSegment }
  760. })
  761. }
  762. const colorList = ['#58D5FF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF']
  763. var that = this
  764. var option = {
  765. tooltip: {
  766. show: true,
  767. formatter: function (params) {
  768. var str = ''
  769. if (that.value == 5 || that.value == 6) {
  770. str = params.name + ':' + (params.value ? params.value + '%' : 0)
  771. } else {
  772. str = params.name + ':' + (params.value ? params.value : 0)
  773. }
  774. return str
  775. },
  776. },
  777. title: {
  778. text: '年龄分布',
  779. // subtext: '仅供参考',
  780. left: 'left',
  781. },
  782. series: [
  783. {
  784. type: 'pie',
  785. // center: ['30%', '30%'],
  786. radius: ['30%', '60%'],
  787. minAngle: 10,
  788. avoidLabelOverlap: true,
  789. hoverOffset: 15,
  790. itemStyle: {
  791. color: (params) => {
  792. return colorList[params.dataIndex]
  793. },
  794. },
  795. label: {
  796. show: true,
  797. position: 'outer',
  798. alignTo: 'labelLine',
  799. // ·圆点
  800. backgroundColor: 'auto', //圆点颜色,auto:映射的系列色
  801. height: 0,
  802. width: 0,
  803. lineHeight: 0,
  804. // height,width.lineHeight必须为0
  805. distanceToLabelLine: 0, //圆点到labelline距离
  806. borderRadius: 2.5,
  807. padding: [2.5, -2.5, 2.5, -2.5],
  808. /*radius和padding为圆点大小,圆点半径为几radius和padding各项数值就为几
  809. 如:圆点半径为1
  810. borderRadius: 1,
  811. padding: [1, -1, 1, -1]
  812. */
  813. formatter: '{a|{b} }',
  814. rich: {
  815. a: {
  816. padding: [0, 0, 0, 10],
  817. },
  818. b: {
  819. padding: [0, 10, 0, 0],
  820. },
  821. },
  822. },
  823. data: res,
  824. },
  825. ],
  826. }
  827. return option
  828. },
  829. handlerBusinessOption(data) {
  830. var res = []
  831. var dataX = data.map((item) => {
  832. return item.businessInterestTags
  833. })
  834. if (this.value == 1) {
  835. res = data.map((item) => {
  836. return item.photoShow
  837. })
  838. } else if (this.value == 2) {
  839. res = data.map((item) => {
  840. return item.photoClick
  841. })
  842. } else if (this.value == 3) {
  843. res = data.map((item) => {
  844. return item.aclick
  845. })
  846. } else if (this.value == 4) {
  847. res = data.map((item) => {
  848. return item.bclick
  849. })
  850. } else if (this.value == 5) {
  851. res = data.map((item) => {
  852. return item.photoClickRatio
  853. })
  854. } else if (this.value == 6) {
  855. res = data.map((item) => {
  856. return item.actionRatio
  857. })
  858. }
  859. var that = this
  860. const colorList = ['#58D5FF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF']
  861. var option = {
  862. title: {
  863. text: '商业兴趣分布',
  864. // subtext: '仅供参考',
  865. left: 'left',
  866. },
  867. color: colorList,
  868. tooltip: {
  869. trigger: 'axis',
  870. formatter: function (params) {
  871. var str = ''
  872. if (that.value == 5 || that.value == 6) {
  873. str = params[0].name + ':' + params[0].value + '%'
  874. } else {
  875. str = params[0].name + ':' + params[0].value
  876. }
  877. return str
  878. },
  879. },
  880. grid: {
  881. left: '3%',
  882. right: '4%',
  883. bottom: '3%',
  884. containLabel: true,
  885. },
  886. xAxis: [
  887. {
  888. type: 'category',
  889. data: dataX,
  890. axisTick: {
  891. alignWithLabel: true,
  892. },
  893. },
  894. ],
  895. yAxis: [
  896. {
  897. type: 'log',
  898. },
  899. ],
  900. series: [
  901. {
  902. name: '直接访问',
  903. type: 'bar',
  904. barWidth: '60%',
  905. data: res,
  906. },
  907. ],
  908. }
  909. return option
  910. },
  911. handlerSystemOption(data) {
  912. var res = []
  913. var dataX = data.map((item) => {
  914. return item.client
  915. })
  916. if (this.value == 1) {
  917. res = data.map((item) => {
  918. return item.photoShow
  919. })
  920. } else if (this.value == 2) {
  921. res = data.map((item) => {
  922. return item.photoClick
  923. })
  924. } else if (this.value == 3) {
  925. res = data.map((item) => {
  926. return item.aclick
  927. })
  928. } else if (this.value == 4) {
  929. res = data.map((item) => {
  930. return item.bclick
  931. })
  932. } else if (this.value == 5) {
  933. res = data.map((item) => {
  934. return item.photoClickRatio
  935. })
  936. } else if (this.value == 6) {
  937. res = data.map((item) => {
  938. return item.actionRatio
  939. })
  940. }
  941. var that = this
  942. const colorList = ['#58D5FF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF']
  943. var option = {
  944. title: {
  945. text: '系统分布',
  946. // subtext: '仅供参考',
  947. left: 'left',
  948. },
  949. color: colorList,
  950. tooltip: {
  951. trigger: 'axis',
  952. formatter: function (params) {
  953. var str = ''
  954. if (that.value == 5 || that.value == 6) {
  955. str = params[0].name + ':' + params[0].value + '%'
  956. } else {
  957. str = params[0].name + ':' + params[0].value
  958. }
  959. return str
  960. },
  961. },
  962. grid: {
  963. left: '3%',
  964. right: '4%',
  965. bottom: '3%',
  966. containLabel: true,
  967. },
  968. xAxis: [
  969. {
  970. type: 'category',
  971. data: dataX,
  972. axisTick: {
  973. alignWithLabel: true,
  974. },
  975. },
  976. ],
  977. yAxis: [
  978. {
  979. type: 'log',
  980. },
  981. ],
  982. series: [
  983. {
  984. name: '直接访问',
  985. type: 'bar',
  986. barWidth: '60%',
  987. data: res,
  988. },
  989. ],
  990. }
  991. return option
  992. },
  993. //点击分页
  994. sort(pagination, filters, sorter, { currentDataSource }) {
  995. this.ipagination.current = pagination.current
  996. this.ipagination.pageSize = pagination.pageSize
  997. if (sorter.order == 'ascend') {
  998. this.order = ''
  999. this.target = sorter.columnKey
  1000. } else if (sorter.order == 'descend') {
  1001. this.order = 'desc'
  1002. this.target = sorter.columnKey
  1003. }
  1004. this.getTableData()
  1005. },
  1006. materialTableChange(pagination, filters, sorter, { currentDataSource }) {
  1007. this.materialipagination.current = pagination.current
  1008. this.materialipagination.pageSize = pagination.pageSize
  1009. },
  1010. getEchartData() {
  1011. this.spinning = true
  1012. // let params = this.handlerParams()
  1013. // params.dataType = this.value
  1014. // postAction('', params).then((res) => {
  1015. // console.log(res)
  1016. // this.province = province
  1017. if (this.province.length > 0) {
  1018. this.initEchart('mapEchart', this.handlerMapEchartOption(this.province, this.provinceData))
  1019. }
  1020. if (this.sexData.length > 0) {
  1021. this.initEchart('sexEchart', this.handlerSexOption(this.sexData))
  1022. }
  1023. if (this.ageData.length > 0) {
  1024. this.initEchart('ageEchart', this.handlerAgeOption(this.ageData))
  1025. }
  1026. if (this.businessData.length > 0) {
  1027. this.initEchart('businessEchart', this.handlerBusinessOption(this.businessData))
  1028. }
  1029. if (this.systemData.length > 0) {
  1030. this.initEchart('systemEchart', this.handlerSystemOption(this.systemData))
  1031. }
  1032. this.spinning = false
  1033. // })
  1034. },
  1035. getDetailTableData() {
  1036. this.getTableData()
  1037. },
  1038. getRelativeData() {
  1039. let params = this.handlerParams()
  1040. // params.dataType=this.tableValue
  1041. if (params.accountIds) {
  1042. this.spinning = true
  1043. getAction('/audienceReport/queryAllReportForm', params).then((res) => {
  1044. this.spinning = false
  1045. if (res.success) {
  1046. this.province = res.result.province.map((item) => {
  1047. return item.province
  1048. })
  1049. this.provinceData = res.result.province
  1050. this.initEchart('mapEchart', this.handlerMapEchartOption(this.province, this.provinceData))
  1051. this.sexData = res.result.gender
  1052. this.initEchart('sexEchart', this.handlerSexOption(this.sexData))
  1053. this.ageData = res.result.ageSegment
  1054. this.initEchart('ageEchart', this.handlerAgeOption(this.ageData))
  1055. this.businessData = res.result.businessInterestTags
  1056. this.initEchart('businessEchart', this.handlerBusinessOption(this.businessData))
  1057. this.systemData = res.result.client
  1058. this.initEchart('systemEchart', this.handlerSystemOption(this.systemData))
  1059. } else {
  1060. this.$message.error(res.message)
  1061. this.province = []
  1062. this.provinceData = []
  1063. this.sexData = []
  1064. this.ageData = []
  1065. this.businessData = []
  1066. this.systemData = []
  1067. this.initEchart('mapEchart', this.handlerMapEchartOption(this.province, this.provinceData))
  1068. this.initEchart('sexEchart', this.handlerSexOption(this.sexData))
  1069. this.initEchart('ageEchart', this.handlerAgeOption(this.ageData))
  1070. this.initEchart('businessEchart', this.handlerBusinessOption(this.businessData))
  1071. this.initEchart('systemEchart', this.handlerSystemOption(this.systemData))
  1072. }
  1073. })
  1074. }
  1075. },
  1076. getTableData() {
  1077. let params = this.handlerParams() || {}
  1078. if (params.accountIds) {
  1079. this.materialloading = true
  1080. params.audienceType = this.tableValue
  1081. params.pageNo = this.ipagination.current
  1082. params.pageSize = this.ipagination.pageSize
  1083. params.orderType = this.target
  1084. params.upOrDown = this.order
  1085. // params.dataType=this.tableValue
  1086. getAction('/audienceReport/queryPageList', params).then((res) => {
  1087. this.materialloading = false
  1088. if (res) {
  1089. this.tableData = res.list
  1090. this.ipagination.total = res.total
  1091. } else {
  1092. this.$message.error('出错了')
  1093. }
  1094. })
  1095. }
  1096. },
  1097. search() {
  1098. this.searchShow = false
  1099. this.getRelativeData()
  1100. this.getTableData()
  1101. },
  1102. handlerParams() {
  1103. let params = {}
  1104. if (this.accountIds.length <= 0) {
  1105. this.$message.error('请选择账户')
  1106. this.materialloading = false
  1107. this.spinning = false
  1108. return
  1109. } else {
  1110. params.accountIds = ''
  1111. this.accountIds.forEach((item, index) => {
  1112. if (index != this.accountIds.length - 1) {
  1113. params.accountIds += `${item},`
  1114. } else {
  1115. params.accountIds += `${item}`
  1116. }
  1117. })
  1118. }
  1119. if (this.dateRange[0] && this.dateRange.length == 2) {
  1120. params.startTime = this.dateRange[0].format('YYYY-MM-DD')
  1121. params.endTime = this.dateRange[1].format('YYYY-MM-DD')
  1122. } else {
  1123. this.materialloading = false
  1124. this.spinning = false
  1125. this.$message.error('请选择时间')
  1126. return
  1127. }
  1128. // if (this.tabKey == 1) {
  1129. // params.type = 'target'
  1130. // params.strategyId = this.directionalId[0].split('_')[0]
  1131. // params.targetIds = this.directionalId.map((item) => {
  1132. // return item.split('_')[1]
  1133. // })
  1134. // } else {
  1135. // params.type = 'material'
  1136. // params.strategyId = this.materialId[0].split('_')[0]
  1137. // params.codes = this.materialId.map((item) => {
  1138. // return item.split('_')[1]
  1139. // })
  1140. // }
  1141. // if (this.dateRange && this.dateRange.length > 0) {
  1142. // params.startDate = this.dateRange[0].format('YYYY-MM-DD')
  1143. // params.endDate = this.dateRange[1].format('YYYY-MM-DD')
  1144. // }
  1145. return params
  1146. },
  1147. },
  1148. watch: {
  1149. accountIds: function (n, o) {
  1150. if (n.length > 0 && this.searchShow) {
  1151. this.search()
  1152. }
  1153. },
  1154. 'ipagination.current': function (n, o) {
  1155. if (n != o) {
  1156. this.getTableData()
  1157. }
  1158. },
  1159. 'ipagination.pageSize': function (n, o) {
  1160. if (n != o) {
  1161. this.getTableData()
  1162. }
  1163. },
  1164. },
  1165. activated() {
  1166. this.$nextTick(() => {})
  1167. let userInfo = localStorage.getItem('pro__Login_Userinfo')
  1168. let userId = ''
  1169. if (userInfo) {
  1170. this.userId = JSON.parse(userInfo).value.id
  1171. }
  1172. },
  1173. filters: {
  1174. toPercentage(val) {
  1175. if (val) {
  1176. if (typeof val != 'string') {
  1177. return (val * 100).toFixed(2) + '%'
  1178. } else {
  1179. return val
  1180. }
  1181. } else if (typeof val == 'string') {
  1182. return val
  1183. } else {
  1184. return 0
  1185. }
  1186. },
  1187. //保留两位小数并且变成货币格式
  1188. decimalsHandle(val) {
  1189. if (val && typeof val != 'string') {
  1190. if (val >= 0) {
  1191. val = parseFloat(val).toFixed(2)
  1192. let numberStr = val.toString()
  1193. let str = numberStr.split('.')
  1194. let str0 = str[0].split('').reverse()
  1195. for (let i = 0; i < str0.length; i++) {
  1196. if ((i + 1) % 4 === 0) {
  1197. str0.splice(i, 0, ',')
  1198. }
  1199. }
  1200. str0.reverse()
  1201. let handleResult = ''
  1202. for (let j = 0; j < str0.length; j++) {
  1203. handleResult += str0[j]
  1204. }
  1205. return handleResult + '.' + str[1]
  1206. } else {
  1207. val = parseFloat(val).toFixed(2)
  1208. let numberStr = val.toString()
  1209. let str = numberStr.split('.')
  1210. let str0 = str[0].substr(1).split('').reverse()
  1211. for (let i = 0; i < str0.length; i++) {
  1212. if ((i + 1) % 4 === 0) {
  1213. str0.splice(i, 0, ',')
  1214. }
  1215. }
  1216. str0.reverse()
  1217. let handleResult = ''
  1218. for (let j = 0; j < str0.length; j++) {
  1219. handleResult += str0[j]
  1220. }
  1221. return '-' + handleResult + '.' + str[1]
  1222. }
  1223. } else if (typeof val == 'string') {
  1224. return val
  1225. } else {
  1226. return 0
  1227. }
  1228. },
  1229. //变成货币格式
  1230. formatCurrency(val) {
  1231. if ((val || val == 0) && typeof val != 'string') {
  1232. let numberStr = val.toString()
  1233. let str = numberStr.split('').reverse()
  1234. for (let i = 0; i < str.length; i++) {
  1235. if ((i + 1) % 4 === 0) {
  1236. str.splice(i, 0, ',')
  1237. }
  1238. }
  1239. str.reverse()
  1240. let handleResult = ''
  1241. for (let j = 0; j < str.length; j++) {
  1242. handleResult += str[j]
  1243. }
  1244. return handleResult
  1245. } else if (typeof val == 'string') {
  1246. return val
  1247. } else {
  1248. return '-'
  1249. }
  1250. },
  1251. },
  1252. }
  1253. </script>
  1254. <style lang="scss">
  1255. .ant-tooltip-inner,
  1256. .ant-tooltip-arrow::before {
  1257. background-color: #fff;
  1258. color: #333;
  1259. }
  1260. </style>
  1261. <style lang="scss" scoped>
  1262. .autoLaunchReport {
  1263. background-color: #fff;
  1264. padding: 10px 20px;
  1265. position: relative;
  1266. width: 100%;
  1267. .OptinItem {
  1268. display: inline-block;
  1269. margin-right: 15px;
  1270. margin-top: 15px;
  1271. .ok {
  1272. margin-right: 15px;
  1273. }
  1274. }
  1275. .OptinItem:first-child {
  1276. margin-right: 10px;
  1277. }
  1278. .topOptions {
  1279. padding: 15px 10px;
  1280. position: relative;
  1281. .topOpt {
  1282. width: 100%;
  1283. margin-bottom: 10px;
  1284. }
  1285. }
  1286. .optionBtn {
  1287. // display: inline-block;
  1288. float: right;
  1289. // .searchBtn{
  1290. // margin-right: 10px;
  1291. // }
  1292. }
  1293. .circul {
  1294. width: 5px;
  1295. height: 5px;
  1296. border-radius: 50%;
  1297. background-color: #32CD32;
  1298. }
  1299. .show {
  1300. // background-color: #fff;
  1301. width: 100%;
  1302. display: flex;
  1303. justify-content: space-between;
  1304. // padding: 0px 15px;
  1305. box-sizing: border-box;
  1306. .showBox {
  1307. width: 19%;
  1308. box-sizing: border-box;
  1309. padding: 15px 15px;
  1310. background-color: #fff;
  1311. .title {
  1312. color: #999;
  1313. font-size: 16px;
  1314. position: relative;
  1315. text-align: center;
  1316. .infotitle {
  1317. padding: 8px 0;
  1318. }
  1319. span {
  1320. font-size: 1rem;
  1321. // color: #1890ff;
  1322. position: absolute;
  1323. top: 0;
  1324. right: 0;
  1325. cursor: pointer;
  1326. }
  1327. }
  1328. .infoNum {
  1329. padding: 10px 0;
  1330. text-align: center;
  1331. font-weight: 600;
  1332. font-size: 20px;
  1333. span {
  1334. font-weight: 600;
  1335. font-size: 16px;
  1336. }
  1337. .red {
  1338. font-size: 20px;
  1339. font-weight: 600;
  1340. color: red;
  1341. }
  1342. .green {
  1343. display: block;
  1344. text-align: center;
  1345. margin-left: 0.2rem;
  1346. font-size: 14px;
  1347. font-weight: 700;
  1348. color: #32CD32;
  1349. .huanbi {
  1350. // color:#999;
  1351. font-weight: 400;
  1352. font-size: 14px;
  1353. }
  1354. }
  1355. }
  1356. }
  1357. }
  1358. .chartBox {
  1359. background-color: #fff;
  1360. margin: 15px 0px;
  1361. padding: 2px 10px 30px;
  1362. .chartBody {
  1363. margin-top: 20px;
  1364. display: flex;
  1365. justify-content: space-between;
  1366. flex-wrap: wrap;
  1367. }
  1368. }
  1369. .tableBox {
  1370. background-color: #fff;
  1371. margin: 15px 0px;
  1372. padding: 15px 0px;
  1373. .tableTop {
  1374. position: relative;
  1375. padding: 20px 0;
  1376. border-top: 1px solid #e0e0e0;
  1377. font-size: 24px;
  1378. color: black;
  1379. .selectTime {
  1380. margin-right: 20px;
  1381. }
  1382. .add {
  1383. position: absolute;
  1384. top: 0;
  1385. right: 0;
  1386. }
  1387. }
  1388. .tableOpt {
  1389. margin-bottom: 20px;
  1390. }
  1391. }
  1392. }
  1393. </style>