dataDisplayStatistics.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. <style lang="scss" scoped>
  2. .search-bar {
  3. display: flex;
  4. align-items: center;
  5. }
  6. .search-box p {
  7. display: inline-block;
  8. border: 1px solid #f2f2f2;
  9. border-radius: 5px;
  10. margin-right: 10px;
  11. padding: 5px 10px;
  12. cursor: pointer;
  13. }
  14. </style>
  15. <style>
  16. /* .data-display-statistics .ant-card-body {
  17. padding: 0 15px;
  18. } */
  19. .data-display-statistics .ant-col-6 {
  20. margin: 10px 0;
  21. }
  22. .data-display-statistics .ant-col-6 .ant-card-body {
  23. display: flex;
  24. justify-content: center;
  25. }
  26. .data-display-statistics .ant-col-6 p,
  27. .data-display-statistics .ant-col-6 span {
  28. text-align: center;
  29. line-height: 40px;
  30. font-size: 30px;
  31. font-weight: 600;
  32. color: red;
  33. margin: 0;
  34. }
  35. .search-box .ant-card-body {
  36. padding: 5px 15px;
  37. }
  38. .data-display-statistics .ant-col-6 .ant-card-body .styleElse {
  39. line-height: 60px;
  40. height: 40px;
  41. font-size: 16px;
  42. font-weight: 400;
  43. margin-left: 10px;
  44. }
  45. .ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
  46. display: none !important;
  47. }
  48. .yincang .ant-col-6 p {
  49. text-align: left;
  50. color: red;
  51. font-size: 16px;
  52. font-weight: 500;
  53. }
  54. .ant-table-thead div {
  55. font-weight: 700;
  56. }
  57. .tool-tip {
  58. position: absolute;
  59. top: 65px;
  60. right: 10px;
  61. }
  62. </style>
  63. <template>
  64. <div class="data-display-statistics">
  65. <a-row class="image-list-heading vm-panel">
  66. <div class="panel-heading">{{ title }}</div>
  67. <a-row type="flex" align="middle" justify="space-between" class="panel-body">
  68. <div class="search-bar" style="width:100%">
  69. <a-select
  70. v-model="appId"
  71. showSearch
  72. allowClear
  73. mode="multiple"
  74. placeholder="请选择账户"
  75. optionFilterProp="children"
  76. style="width: 55%"
  77. @focus="handleFocus"
  78. @blur="handleBlur"
  79. @change="handleChange"
  80. :filterOption="true"
  81. @search="search"
  82. :maxTagCount="1"
  83. >
  84. <a-select-option
  85. v-for="appModel in options"
  86. :key="appModel.id+new Date().getTime()"
  87. :value="appModel.accountId"
  88. >
  89. {{appModel.advertiserName}}&#12288;&#12288;{{appModel.accountId}}&#12288;&nbsp;&#12288;{{appModel.authName}}&#12288;&#12288;{{appModel.operationName}}
  90. <!-- <div v-if="show">
  91. <div
  92. style="width:220px;text-align:right;display:inline-block"
  93. >{{appModel.advertiserName}}</div>
  94. <div
  95. style="width:100px;text-align:center;display:inline-block;margin-right:30px"
  96. >{{appModel.accountId}}</div>
  97. <div style="width:150px;text-align:left;display:inline-block">{{appModel.authName}}</div>
  98. <div
  99. style="width:100px;text-align:center;display:inline-block"
  100. >{{appModel.operationName}}</div>
  101. </div>-->
  102. </a-select-option>
  103. </a-select>
  104. <a-input-number
  105. :min="1"
  106. :max="10"
  107. :step="0.1"
  108. v-model="discount"
  109. placeholder="请输入折扣"
  110. style="width:100px"
  111. />
  112. <a-button type="primary" style="margin:10px" @click="addUser">搜索</a-button>
  113. </div>
  114. </a-row>
  115. <a-row>
  116. <a-col :span="24">
  117. <a-card :bordered="false" class="search-box">
  118. <p :style="active==1?'color:cornflowerblue;background:#f2f2f2':''" @click="getAdd(1)">今天</p>
  119. <p :style="active==2?'color:cornflowerblue;background:#f2f2f2':''" @click="getAdd(2)">昨天</p>
  120. <p
  121. :style="active==3?'color:cornflowerblue;background:#f2f2f2':''"
  122. @click="getAdd(3)"
  123. >近一周</p>
  124. <p
  125. :style="active==4?'color:cornflowerblue;background:#f2f2f2':''"
  126. @click="getAdd(4)"
  127. >近十五天</p>
  128. <p
  129. :style="active==5?'color:cornflowerblue;background:#f2f2f2':''"
  130. @click="getAdd(5)"
  131. >近一月</p>
  132. <p
  133. :style="active==6?'color:cornflowerblue;background:#f2f2f2':''"
  134. @click="getAdd(6)"
  135. >近三月</p>
  136. <p
  137. :style="active==7?'color:cornflowerblue;background:#f2f2f2':''"
  138. @click="getAdd(7)"
  139. >近半年</p>
  140. <p :style="active==8?'color:cornflowerblue;background:#f2f2f2':''" @click="getAdd(8)">所有</p>
  141. <a-range-picker
  142. style="width:400px"
  143. :disabledDate="disabledDate"
  144. :showTime="{
  145. hideDisabledOptions: true,
  146. }"
  147. format="YYYY-MM-DD"
  148. v-model="startValue"
  149. @ok="getAdd(9)"
  150. />
  151. </a-card>
  152. </a-col>
  153. <!-- <a-col :span="24">
  154. <a-card :bordered="false" class="search-box">
  155. <p @click="visible = true">对比</p>
  156. </a-card>
  157. </a-col>-->
  158. </a-row>
  159. </a-row>
  160. <a-row :gutter="16" v-if="kuaishou">
  161. <a-col :span="6" style="width:20%">
  162. <lifting
  163. :kuaishou.sync="kuaishou"
  164. :active.sync="active"
  165. title="总消耗"
  166. typeName="cost"
  167. typeThan="costProportion"
  168. ></lifting>
  169. </a-col>
  170. <a-col :span="6" style="width:20%">
  171. <lifting
  172. :kuaishou.sync="kuaishou"
  173. :active.sync="active"
  174. title="折后消耗"
  175. typeName="discountCost"
  176. typeThan="discountCostProportion"
  177. ></lifting>
  178. </a-col>
  179. <a-col :span="6" style="width:20%">
  180. <lifting
  181. :kuaishou.sync="kuaishou"
  182. :active.sync="active"
  183. title="封面点击数"
  184. typeName="photoClick"
  185. typeThan="photoClickProportion"
  186. ></lifting>
  187. </a-col>
  188. <a-col :span="6" style="width:20%">
  189. <lifting
  190. :kuaishou.sync="kuaishou"
  191. :active.sync="active"
  192. title="封面曝光数"
  193. typeName="photoShow"
  194. typeThan="showProportion"
  195. ></lifting>
  196. </a-col>
  197. <a-col :span="6" style="width:20%">
  198. <lifting
  199. :kuaishou.sync="kuaishou"
  200. :active.sync="active"
  201. title="素材曝光数"
  202. typeName="aclick"
  203. typeThan="aClickProportion"
  204. ></lifting>
  205. </a-col>
  206. </a-row>
  207. <a-row :gutter="10">
  208. <a-col :span="24">
  209. <a-card
  210. style="width:100%"
  211. :tabList="tabListNoTitle"
  212. :activeTabKey="noTitleKey"
  213. @tabChange="key => onTabChange(key, 'noTitleKey')"
  214. >
  215. <div id="chart" style="width:100%;height:500px"></div>
  216. </a-card>
  217. </a-col>
  218. </a-row>
  219. <a-row :gutter="10" style="margin-top:10px">
  220. <a-col :span="24">
  221. <a-card style="width:100%;">
  222. <div style="display:flex;margin-bottom:15px" v-show="active==1||active==2">
  223. <a-select
  224. style="width: 120px"
  225. v-model="statHour"
  226. @change="getElseData"
  227. allowClear
  228. >
  229. <a-select-option v-for="item of 24" :key="item-1" :value="item-1">{{item-1}}</a-select-option>
  230. </a-select>
  231. <a-button type="primary" @click="exportExcel" style="margin-left:15px">导出</a-button>
  232. </div>
  233. <a-table :columns="columns" :dataSource="data" bordered id="outTable" :pagination="false"></a-table>
  234. </a-card>
  235. </a-col>
  236. </a-row>
  237. </div>
  238. </template>
  239. <script>
  240. import ARow from 'ant-design-vue/es/grid/Row'
  241. import ACol from 'ant-design-vue/es/grid/Col'
  242. import countTo from 'vue-count-to'
  243. import moment from 'moment'
  244. import { getAdvertiserList, getReportList, getStatistics } from '@api/statistics'
  245. import axios from 'axios'
  246. import lifting from './components/lifting'
  247. // 引入基本模板
  248. let echarts = require('echarts/lib/echarts')
  249. // 引入柱状图组件
  250. require('echarts/lib/chart/bar')
  251. require('echarts/lib/chart/pie')
  252. require('echarts/lib/chart/line')
  253. // 引入提示框和title组件
  254. require('echarts/lib/component/tooltip')
  255. require('echarts/lib/component/title')
  256. require('echarts/lib/component/graphic')
  257. require('echarts/lib/component/toolbox')
  258. require('echarts/lib/component/legend')
  259. var length = 0
  260. var active = 1
  261. const columns = [
  262. {
  263. title: '时间',
  264. dataIndex: 'date',
  265. align: 'center',
  266. customRender: function(text, record, index) {
  267. const obj = {
  268. children: text,
  269. attrs: {}
  270. }
  271. for (let i = 0; i < length; i++) {
  272. if (index == 0 && i == 0) {
  273. obj.attrs.rowSpan = length
  274. } else {
  275. if (index == i) {
  276. obj.attrs.rowSpan = 0
  277. }
  278. }
  279. }
  280. return obj
  281. }
  282. },
  283. {
  284. title: '账户Id',
  285. dataIndex: 'accountId',
  286. align: 'center',
  287. customRender: function(text, record, index) {
  288. const obj = {
  289. children: text,
  290. attrs: {}
  291. }
  292. if (active == 1) {
  293. for (let i = 0; i < length; i++) {
  294. if (index >= length - 3) {
  295. obj.attrs.colSpan = 2
  296. }
  297. }
  298. }
  299. return obj
  300. }
  301. },
  302. {
  303. title: '账户名称',
  304. dataIndex: 'accountName',
  305. scopedSlots: { customRender: 'cost' },
  306. align: 'center',
  307. customRender: function(text, record, index) {
  308. const obj = {
  309. children: text,
  310. attrs: {}
  311. }
  312. if (active == 1) {
  313. for (let i = 0; i < length; i++) {
  314. if (index >= length - 3) {
  315. obj.attrs.colSpan = 0
  316. }
  317. }
  318. }
  319. return obj
  320. }
  321. },
  322. {
  323. title: '消耗',
  324. dataIndex: 'cost',
  325. scopedSlots: { customRender: 'cost' },
  326. align: 'center'
  327. },
  328. {
  329. title: '折后消耗',
  330. dataIndex: 'costY',
  331. align: 'center'
  332. },
  333. {
  334. title: '封面展示',
  335. dataIndex: 'photoShow',
  336. align: 'center'
  337. },
  338. {
  339. title: '封面点击',
  340. dataIndex: 'photoClick',
  341. align: 'center'
  342. },
  343. {
  344. title: '素材曝光数',
  345. dataIndex: 'aclick',
  346. align: 'center'
  347. },
  348. {
  349. title: '封面点击率',
  350. dataIndex: 'photoClickRatio',
  351. align: 'center'
  352. },
  353. {
  354. title: 'cvr',
  355. dataIndex: 'cvr',
  356. align: 'center'
  357. },
  358. {
  359. title: 'cpm',
  360. dataIndex: 'cpm',
  361. align: 'center'
  362. },
  363. {
  364. title: '行为数',
  365. dataIndex: 'bClick',
  366. align: 'center'
  367. },
  368. {
  369. title: '转化数',
  370. dataIndex: 'formCount',
  371. align: 'center'
  372. },
  373. {
  374. title: '转化单价',
  375. dataIndex: 'formPrice',
  376. align: 'center'
  377. },
  378. {
  379. title: '单价区间',
  380. dataIndex: 'price',
  381. align: 'center',
  382. customRender: function(text, record, index) {
  383. const obj = {
  384. children: text,
  385. attrs: {}
  386. }
  387. for (let i = 0; i < length; i++) {
  388. if (index == 0 && i == 0) {
  389. obj.attrs.rowSpan = length
  390. } else {
  391. if (index == i) {
  392. obj.attrs.rowSpan = 0
  393. }
  394. }
  395. }
  396. return obj
  397. }
  398. }
  399. ]
  400. export default {
  401. name: 'data-display-statistics',
  402. components: {
  403. ACol,
  404. ARow,
  405. countTo,
  406. lifting
  407. },
  408. data: function() {
  409. return {
  410. title: '账户数据展示',
  411. show: true,
  412. data: [],
  413. columns,
  414. options: [],
  415. list: [],
  416. appId: [],
  417. statHour: null,
  418. keyValue: null,
  419. keyValueData: [],
  420. active: 1,
  421. startValue: [],
  422. allValue: [],
  423. discount: 1,
  424. duration: 1000,
  425. kuaishou: {
  426. aclick: 0,
  427. aClickProportion: 0,
  428. cost: 0,
  429. costProportion: 0,
  430. photoClick: 0,
  431. photoClickroportion: 0,
  432. photoShow: 0,
  433. showProportion: 0,
  434. discountCost: 0,
  435. discountCostProportion: 0
  436. },
  437. dataDetail: [],
  438. tabListNoTitle: [
  439. {
  440. key: 'cost',
  441. tab: '总消耗'
  442. },
  443. {
  444. key: 'discountCost',
  445. tab: '折后总消耗'
  446. },
  447. {
  448. key: 'photoClick',
  449. tab: '封面点击数'
  450. },
  451. {
  452. key: 'photoShow',
  453. tab: '封面曝光数'
  454. },
  455. {
  456. key: 'aclick',
  457. tab: '素材曝光数'
  458. }
  459. ],
  460. noTitleKey: 'cost'
  461. }
  462. },
  463. filters: {
  464. formatDate: function(value) {
  465. let date = new Date(value)
  466. let y = date.getFullYear()
  467. let MM = date.getMonth() + 1
  468. MM = MM < 10 ? '0' + MM : MM
  469. let d = date.getDate()
  470. d = d < 10 ? '0' + d : d
  471. let h = date.getHours()
  472. h = h < 10 ? '0' + h : h
  473. let m = date.getMinutes()
  474. m = m < 10 ? '0' + m : m
  475. let s = date.getSeconds()
  476. s = s < 10 ? '0' + s : s
  477. return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
  478. }
  479. },
  480. methods: {
  481. moment,
  482. disabledDate(current) {
  483. return current && current > moment().endOf('day')
  484. },
  485. handleChange(value) {
  486. console.log(value)
  487. // this.appId = value
  488. },
  489. getElseData(value) {
  490. this.getStatistics()
  491. },
  492. handleBlur() {
  493. console.log('blur')
  494. },
  495. handleFocus() {
  496. console.log('focus')
  497. if (this.appId.length > 0) {
  498. this.options = []
  499. for (let i = 0; i < this.list.length; i++) {
  500. for (let j = 0; j < this.appId.length; j++) {
  501. if (this.list[i].accountId == this.appId[j]) {
  502. this.options.push(this.list[i])
  503. }
  504. }
  505. }
  506. } else {
  507. this.options = this.list
  508. }
  509. },
  510. search(value) {
  511. // console.log(value)
  512. this.options = []
  513. if (value != '') {
  514. this.options = this.list.filter(item => {
  515. var data = item.accountId + ' ' + item.authName + ' ' + item.advertiserName + ' ' + item.operationName
  516. return data.toLowerCase().indexOf(value.toLowerCase()) > -1
  517. })
  518. this.options = [...this.options]
  519. console.log(this.options)
  520. } else {
  521. if (this.appId.length > 0) {
  522. this.options = []
  523. for (let i = 0; i < this.list.length; i++) {
  524. for (let j = 0; j < this.appId.length; j++) {
  525. if (this.list[i].accountId == this.appId[j]) {
  526. this.options.push(this.list[i])
  527. }
  528. }
  529. }
  530. } else {
  531. this.options = this.list
  532. }
  533. }
  534. },
  535. addUser() {
  536. var that = this
  537. if (this.appId.length > 0) {
  538. var params = {}
  539. params.accountIds = JSON.stringify(that.appId)
  540. params.type = that.active
  541. params.discount = that.discount
  542. if (that.active == 9) {
  543. params.startDate = this.allValue[0]
  544. params.endDate = this.allValue[1]
  545. }
  546. getReportList(params).then(res => {
  547. if (res == '') {
  548. that.kuaishou.aclick = 0
  549. that.kuaishou.cost = 0
  550. that.kuaishou.photoClick = 0
  551. that.kuaishou.photoShow = 0
  552. that.kuaishou.discountCost = 0
  553. } else {
  554. that.kuaishou = res.summary
  555. that.dataDetail = res.trend
  556. that.drawPie(that.noTitleKey, res.trend)
  557. }
  558. })
  559. that.getStatistics()
  560. } else {
  561. this.$message.error('请选择账户')
  562. }
  563. },
  564. getStatistics() {
  565. var params = {}
  566. params.accountIds = JSON.stringify(this.appId)
  567. params.type = this.active
  568. params.statHour = this.statHour
  569. params.discount = this.discount
  570. if (this.active == 9) {
  571. params.startDate = this.allValue[0]
  572. params.endDate = this.allValue[1]
  573. }
  574. this.data = []
  575. getStatistics(params).then(res => {
  576. console.log(res)
  577. this.data = res.accountDetail.map((item, index) => {
  578. return {
  579. key: index,
  580. ...item,
  581. photoClickRatio: item.photoClickRatio ? (item.photoClickRatio * 100).toFixed(2) + '%' : 0 + '%',
  582. cpm: item.cpm ? '¥' + item.cpm.toFixed(2) : '¥' + 0,
  583. cost: '¥' + item.cost.toFixed(2),
  584. cvr: item.cvr ? (item.cvr * 100).toFixed(2) + '%' : 0 + '%',
  585. costY: '¥' + (item.cost / this.discount).toFixed(2),
  586. formPrice: item.formPrice
  587. ? '¥' + (item.formPrice / this.discount).toFixed(2)
  588. : item.activationPrice
  589. ? '¥' + (item.activationPrice / this.discount).toFixed(2)
  590. : '¥' + 0,
  591. date: this.statHour ? this.getDate() + ' ' + this.statHour : this.getDate(),
  592. formCount: item.formCount > 0 ? item.formCount : item.activationCount
  593. }
  594. })
  595. var index = this.data.length
  596. if (this.active == 1) {
  597. var allNow = {
  598. key: index + 1,
  599. ...res.now,
  600. photoClickRatio: res.now.photoClickRatio ? (res.now.photoClickRatio * 100).toFixed(2) + '%' : 0 + '%',
  601. cpm: res.now.cpm ? '¥' + res.now.cpm.toFixed(2) : '¥' + 0,
  602. cost: '¥' + res.now.cost.toFixed(2),
  603. cvr: res.now.cvr ? (res.now.cvr * 100).toFixed(2) + '%' : 0 + '%',
  604. costY: '¥' + (res.now.cost / this.discount).toFixed(2),
  605. accountId: '总计',
  606. formPrice: res.now.formPrice
  607. ? '¥' + (res.now.formPrice / this.discount).toFixed(2)
  608. : res.now.activationPrice
  609. ? '¥' + (res.now.activationPrice / this.discount).toFixed(2)
  610. : '¥' + 0,
  611. formCount: res.now.formCount > 0 ? res.now.formCount : res.now.activationCount
  612. }
  613. var allYesterday = {
  614. key: index + 2,
  615. ...res.yesterday,
  616. photoClickRatio: res.yesterday.photoClickRatio
  617. ? (res.yesterday.photoClickRatio * 100).toFixed(2) + '%'
  618. : 0 + '%',
  619. cpm: res.yesterday.cpm ? '¥' + res.yesterday.cpm.toFixed(2) : '¥' + 0,
  620. cost: '¥' + res.yesterday.cost.toFixed(2),
  621. cvr: res.yesterday.cvr ? (res.yesterday.cvr * 100).toFixed(2) + '%' : 0 + '%',
  622. costY: '¥' + (res.yesterday.cost / this.discount).toFixed(2),
  623. accountId: '昨日总计',
  624. formPrice: res.yesterday.formPrice
  625. ? '¥' + (res.yesterday.formPrice / this.discount).toFixed(2)
  626. : res.yesterday.activationPrice
  627. ? '¥' + (res.yesterday.activationPrice / this.discount).toFixed(2)
  628. : '¥' + 0,
  629. formCount: res.yesterday.formCount > 0 ? res.yesterday.formCount : res.yesterday.activationCount
  630. }
  631. var chainRatio = {
  632. key: index + 3,
  633. cost: (res.chainRatio.costProportion * 100).toFixed(2) + '%',
  634. photoShow: (res.chainRatio.showProportion * 100).toFixed(2) + '%',
  635. photoClick: (res.chainRatio.photoClickProportion * 100).toFixed(2) + '%',
  636. aclick: (res.chainRatio.aClickProportion * 100).toFixed(2) + '%',
  637. photoClickRatio: res.chainRatio.photoClickRatioProportion
  638. ? (res.chainRatio.photoClickRatioProportion * 100).toFixed(2) + '%'
  639. : 0 + '%',
  640. cvr: (res.chainRatio.cvrProportion * 100).toFixed(2) + '%',
  641. cpm: (res.chainRatio.cpmProportion * 100).toFixed(2) + '%',
  642. bClick: (res.chainRatio.bClickProportion * 100).toFixed(2) + '%',
  643. formCount: res.chainRatio.formCountProportion
  644. ? (res.chainRatio.formCountProportion * 100).toFixed(2) + '%'
  645. : res.chainRatio.activationCountProportion
  646. ? (res.chainRatio.activationCountProportion * 100).toFixed(2) + '%'
  647. : 0 + '%',
  648. formPrice: res.chainRatio.formPriceProportion
  649. ? (res.chainRatio.formPriceProportion * 100).toFixed(2) + '%'
  650. : res.chainRatio.activationPriceProportion
  651. ? (res.chainRatio.activationPriceProportion * 100).toFixed(2) + '%'
  652. : 0 + '%',
  653. costY: (res.chainRatio.costProportion * 100).toFixed(2) + '%',
  654. accountId: '环比'
  655. }
  656. this.data.push(allNow)
  657. this.data.push(allYesterday)
  658. this.data.push(chainRatio)
  659. }
  660. length = this.data.length
  661. })
  662. },
  663. getAdd(checked) {
  664. if (checked == 9) {
  665. if (this.startValue.length > 0 && this.startValue[0]) {
  666. this.allValue[1] = moment(this.startValue[0]._d).format('YYYY-MM-DD')
  667. this.allValue[0] = moment(this.startValue[1]._d).format('YYYY-MM-DD')
  668. }
  669. } else {
  670. this.startValue = []
  671. this.allValue = []
  672. }
  673. this.active = checked
  674. active = checked
  675. this.addUser(checked)
  676. },
  677. onTabChange(key, type) {
  678. console.log(key, type)
  679. this[type] = key
  680. if (type == 'noTitleKey') {
  681. this.drawPie(key, this.dataDetail)
  682. }
  683. },
  684. drawPie(type, data) {
  685. console.log(type)
  686. var dataLegend = []
  687. var dataLength = []
  688. var dataElse = []
  689. var dataDate = []
  690. var that = this
  691. if (this.active == 1 || this.active == 2) {
  692. dataDate = data.map(item => {
  693. return item.statHour
  694. })
  695. } else {
  696. dataDate = data.map(item => {
  697. return item.statDate
  698. })
  699. }
  700. dataLength = data.map(item => {
  701. return item[type]
  702. })
  703. if (type == 'cost') {
  704. dataLegend = ['总消耗']
  705. dataElse = data.map(item => {
  706. if (item.now) {
  707. return { proportion: (item.now.costProportion * 100).toFixed(2) + '%', statHour: item.statHour }
  708. } else {
  709. return { proportion: 0, statHour: item.statHour }
  710. }
  711. })
  712. } else if (type == 'photoClick') {
  713. dataLegend = ['封面点击数']
  714. dataElse = data.map(item => {
  715. if (item.now) {
  716. return { proportion: (item.now.photoClickProportion * 100).toFixed(2) + '%', statHour: item.statHour }
  717. } else {
  718. return { proportion: 0, statHour: item.statHour }
  719. }
  720. })
  721. } else if (type == 'photoShow') {
  722. dataLegend = ['封面曝光数']
  723. dataElse = data.map(item => {
  724. if (item.now) {
  725. return { proportion: (item.now.showProportion * 100).toFixed(2) + '%', statHour: item.statHour }
  726. } else {
  727. return { proportion: 0, statHour: item.statHour }
  728. }
  729. })
  730. } else if (type == 'aclick') {
  731. dataLegend = ['素材曝光数']
  732. dataElse = data.map(item => {
  733. if (item.now) {
  734. return { proportion: (item.now.aClickProportion * 100).toFixed(2) + '%', statHour: item.statHour }
  735. } else {
  736. return { proportion: 0, statHour: item.statHour }
  737. }
  738. })
  739. } else if (type == 'discountCost') {
  740. dataLegend = ['折后总消耗']
  741. dataElse = data.map(item => {
  742. if (item.now) {
  743. return { proportion: (item.now.discountCostProportion * 100).toFixed(2) + '%', statHour: item.statHour }
  744. } else {
  745. return { proportion: 0, statHour: item.statHour }
  746. }
  747. })
  748. dataLength = data.map(item => {
  749. return (item.cost / this.discount).toFixed(2)
  750. })
  751. }
  752. console.log(dataLength, 134123)
  753. var series
  754. if (this.active == 1) {
  755. dataLegend = ['今天', '昨天']
  756. series = [
  757. {
  758. name: dataLegend[0],
  759. type: 'line',
  760. color: '#9933ff',
  761. smooth: true,
  762. symbol: 'circle',
  763. symbolSize: 1,
  764. lineStyle: {
  765. normal: {
  766. width: 2,
  767. color: '#9933ff'
  768. }
  769. },
  770. itemStyle: {
  771. borderColor: '#ffffff',
  772. borderWidth: 3
  773. },
  774. data: data.map(item => {
  775. if (item.now) {
  776. return item.now[type]
  777. } else {
  778. return 0
  779. }
  780. })
  781. },
  782. {
  783. name: dataLegend[1],
  784. type: 'line',
  785. color: '#0bcd74',
  786. smooth: true,
  787. symbol: 'circle',
  788. symbolSize: 1,
  789. lineStyle: {
  790. normal: {
  791. width: 2,
  792. color: '#0bcd74'
  793. }
  794. },
  795. itemStyle: {
  796. borderColor: '#ffffff',
  797. borderWidth: 3
  798. },
  799. data: dataLength
  800. }
  801. ]
  802. } else {
  803. series = [
  804. {
  805. name: dataLegend[0],
  806. type: 'line',
  807. color: '#0bcd74',
  808. smooth: true,
  809. symbol: 'circle',
  810. symbolSize: 1,
  811. lineStyle: {
  812. normal: {
  813. width: 2,
  814. color: '#0bcd74'
  815. }
  816. },
  817. itemStyle: {
  818. borderColor: '#ffffff',
  819. borderWidth: 3
  820. },
  821. data: dataLength
  822. }
  823. ]
  824. }
  825. var option = {
  826. backgroundColor: '#fff',
  827. toolbox: {
  828. show: true,
  829. feature: {
  830. dataView: { readOnly: false }
  831. }
  832. },
  833. tooltip: {
  834. trigger: 'axis',
  835. formatter: function(params) {
  836. var index = dataElse.findIndex(v => v.statHour == params[0].name)
  837. var da = null
  838. if (index >= 0) {
  839. da = dataElse[index].proportion
  840. }
  841. if (that.active == 1) {
  842. if (params.length > 1) {
  843. return `${params[0].marker}今天${params[0].name}时:${params[0].data} <br/>
  844. ${params[1].marker}昨天${params[1].name}时:${params[1].data} <br/>
  845. 环比:${da} <br/> `
  846. } else {
  847. return `${params[0].marker}时间:${params[0].name} <br/>
  848. 数值:${params[0].data} `
  849. }
  850. } else {
  851. return `${params[0].marker}时间:${params[0].name} <br/>
  852. 数值:${params[0].data} `
  853. }
  854. }
  855. },
  856. legend: {
  857. data: dataLegend
  858. },
  859. grid: {
  860. left: '2%',
  861. right: '2%',
  862. bottom: '2%',
  863. containLabel: true
  864. },
  865. xAxis: {
  866. type: 'category',
  867. data: dataDate,
  868. boundaryGap: false,
  869. // 坐标轴线
  870. axisLine: {
  871. show: false,
  872. lineStyle: {
  873. color: '#999'
  874. }
  875. },
  876. // 分割线
  877. splitLine: {
  878. show: true,
  879. lineStyle: {
  880. type: 'dashed',
  881. color: '#e5e5e5'
  882. }
  883. }
  884. },
  885. yAxis: {
  886. type: 'value',
  887. axisLine: {
  888. show: false,
  889. lineStyle: {
  890. color: '#999'
  891. }
  892. },
  893. splitLine: {
  894. lineStyle: {
  895. type: 'dashed',
  896. color: '#e5e5e5'
  897. }
  898. }
  899. },
  900. series: series
  901. }
  902. var chart = echarts.init(document.getElementById('chart'))
  903. chart.clear()
  904. chart.setOption(option, true)
  905. window.onresize = function() {
  906. chart.resize()
  907. }
  908. },
  909. getDate() {
  910. let date = new Date()
  911. let y = date.getFullYear()
  912. let MM = date.getMonth() + 1
  913. MM = MM < 10 ? '0' + MM : MM
  914. let d = date.getDate()
  915. d = d < 10 ? '0' + d : d
  916. let h = date.getHours() - 1
  917. h = h < 10 ? '0' + h : h
  918. if (this.active == 1) {
  919. if (this.statHour) {
  920. return y + '-' + MM + '-' + d
  921. } else {
  922. return y + '-' + MM + '-' + d + ' ' + h
  923. }
  924. } else {
  925. return y + '-' + MM + '-' + (d - 1)
  926. }
  927. },
  928. exportExcel() {
  929. var title = ''
  930. if (this.active == 1) {
  931. if (this.statHour) {
  932. title = this.getDate() + ' ' + this.statHour + '时数据报表'
  933. } else {
  934. title = this.getDate() + '时数据报表'
  935. }
  936. } else {
  937. title = this.getDate() + '数据报表'
  938. }
  939. // var opt = {
  940. // rowIndex: 4
  941. // } //开头空4行
  942. var sheet = XLSX2.utils.table_to_sheet(document.getElementById('outTable'))
  943. sheet['A2'].s = {
  944. font: {
  945. name: '宋体',
  946. sz: 18,
  947. color: { rgb: 'ff0000' },
  948. bold: true
  949. // italic: false,
  950. // underline: false
  951. },
  952. alignment: {
  953. horizontal: 'center',
  954. vertical: 'center'
  955. }
  956. // fill: {
  957. // fgColor: {rgb: "008000"},
  958. // },
  959. }
  960. // sheet['A1'] = {
  961. // t: 's',
  962. // v: '表格导出'
  963. // } //给A1单元格赋值
  964. console.log(sheet)
  965. //["!merges"]这个属性是专门用来进行单元格合并的
  966. // sheet['!merges'].push({
  967. // //如果不为空push 为空 = 赋值
  968. // //合并单元格 index都从0开始
  969. // s: {
  970. // //s开始
  971. // c: 0, //开始列
  972. // r: 0 //开始行
  973. // },
  974. // e: {
  975. // //e结束
  976. // c: 12, //结束列
  977. // r: 3 //结束行
  978. // }
  979. // })
  980. sheet['!cols'] = [
  981. {
  982. wpx: 100
  983. },
  984. {
  985. wpx: 100
  986. },
  987. {
  988. wpx: 100
  989. },
  990. {
  991. wpx: 100
  992. },
  993. {
  994. wpx: 100
  995. },
  996. {
  997. wpx: 100
  998. },
  999. {
  1000. wpx: 100
  1001. },
  1002. {
  1003. wpx: 100
  1004. },
  1005. {
  1006. wpx: 100
  1007. },
  1008. {
  1009. wpx: 100
  1010. },
  1011. {
  1012. wpx: 100
  1013. },
  1014. {
  1015. wpx: 100
  1016. },
  1017. {
  1018. wpx: 100
  1019. },
  1020. {
  1021. wpx: 100
  1022. },
  1023. {
  1024. wpx: 100
  1025. }
  1026. ] //单元格列宽
  1027. openDownloadDialog(sheet2blob(sheet), title + '.xlsx')
  1028. }
  1029. },
  1030. watch: {},
  1031. distoryed() {},
  1032. mounted: function() {
  1033. this.$nextTick(() => {
  1034. getAdvertiserList().then(res => {
  1035. console.log(res)
  1036. if (res.code == 0) {
  1037. this.list = res.result
  1038. this.options = res.result
  1039. }
  1040. })
  1041. })
  1042. }
  1043. }
  1044. </script>