materialReport.vue 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. <style>
  2. .materialReport .chart-card-content {
  3. display: none !important;
  4. }
  5. </style>
  6. <style scoped>
  7. .bg {
  8. width: 100%;
  9. height: 100%;
  10. }
  11. .bg:after {
  12. content: '';
  13. width: 110%;
  14. height: 110%;
  15. position: absolute;
  16. left: -5%;
  17. top: -5%;
  18. background: inherit;
  19. filter: blur(10px);
  20. z-index: 2;
  21. background: rgba(0, 0, 0, 0.8);
  22. }
  23. .top-ul-style {
  24. width: 100%;
  25. padding-left: 0;
  26. }
  27. .top-ul-style li {
  28. height: 100px;
  29. border: 1px solid #f2f2f2;
  30. margin-bottom: 5px;
  31. padding: 10px;
  32. display: flex;
  33. justify-content: space-between;
  34. }
  35. .li-cost {
  36. display: flex;
  37. flex-flow: column;
  38. justify-content: center;
  39. align-content: flex-end;
  40. }
  41. .li-cost span {
  42. font-size: 16px;
  43. font-weight: 500;
  44. min-width: 50px;
  45. text-align: right;
  46. }
  47. </style>
  48. <template>
  49. <div class="materialReport">
  50. <div class="card-containers">
  51. <a-tabs type="card">
  52. <a-tab-pane key="1">
  53. <span slot="tab">
  54. <a-icon type="unordered-list" />
  55. 大盘
  56. </span>
  57. </a-tab-pane>
  58. </a-tabs>
  59. <div class="option" style="justify-content: space-between">
  60. <div class="option" style="padding: 0">
  61. <div class="item">
  62. <span>日期选择</span>
  63. <a-range-picker
  64. v-model="dateValue"
  65. :ranges="dateRanges"
  66. :disabled-date="disabledDate"
  67. style="width: 250px"
  68. />
  69. </div>
  70. <div class="item">
  71. <span>媒体维度</span>
  72. <a-radio-group v-model="mediaDimension" @change="mediaDimensionChange">
  73. <a-radio-button value="b">快手</a-radio-button>
  74. <a-radio-button value="a">头条</a-radio-button>
  75. </a-radio-group>
  76. </div>
  77. <div class="item">
  78. <span>数据维度</span>
  79. <a-radio-group v-model="dataDimension">
  80. <a-radio-button value="a">项目</a-radio-button>
  81. <a-radio-button value="b" disabled>设计组</a-radio-button>
  82. </a-radio-group>
  83. <a-select
  84. style="width: 300px; margin-left: 10px"
  85. mode="multiple"
  86. :maxTagCount="2"
  87. v-model="dataDimensionValue"
  88. allowClear
  89. :loading="specificLoading"
  90. showSearch
  91. :filterOption="filterOption"
  92. >
  93. <a-select-option value="no" disabled v-if="dataDimensionList.length == 0 && specificLoading">
  94. 数据请求中,请稍后。。。
  95. </a-select-option>
  96. <a-select-option
  97. v-for="(item, index) in dataDimensionList"
  98. :key="index"
  99. :value="item.projectId"
  100. >
  101. {{ item.projectName }}
  102. </a-select-option>
  103. </a-select>
  104. </div>
  105. </div>
  106. <div class="item" style="float: right">
  107. <a-button
  108. @click="handleSubmit"
  109. type="primary"
  110. :loading="searchLoading"
  111. :disabled="dateValue.length == 0"
  112. >
  113. 搜索
  114. </a-button>
  115. <a-button
  116. @click="resetSubmit"
  117. style="margin-left: 15px"
  118. :disabled="spinning"
  119. :loading="resetLoading"
  120. >
  121. 重置
  122. </a-button>
  123. </div>
  124. </div>
  125. </div>
  126. <a-spin :spinning="spinning">
  127. <a-row :gutter="24" style="margin-top: 20px">
  128. <a-col :sm="24" :md="12" :xl="6">
  129. <a-card title="总消耗" class="material-report-card">
  130. <span slot="extra">
  131. <a-tooltip title="显示该筛选条件内总消耗" slot="action">
  132. <a-icon type="info-circle-o"/>
  133. </a-tooltip>
  134. </span>
  135. <div class="report-card-result">
  136. <div class="report-card-money">¥{{ materialReportCardList.costTotal || 0 }}</div>
  137. <div class="report-card-msg">
  138. <span>
  139. 同比
  140. <a-icon v-if="materialReportCardList.yearOnYearCompare >= 0" type="caret-up" style="color: green"/>
  141. <a-icon v-else type="caret-down" style="color: #f00"/>
  142. {{ Number(materialReportCardList.yearOnYearCompare * 100).toFixed(2) }}%
  143. </span>
  144. <span>
  145. 日环比
  146. <a-icon v-if="materialReportCardList.chainCompare >= 0" type="caret-up" style="color: green"/>
  147. <a-icon v-else type="caret-down" style="color: #f00"/>
  148. {{ Number(materialReportCardList.chainCompare * 100).toFixed(2) }}%
  149. </span>
  150. </div>
  151. </div>
  152. <div class="report-card-line"></div>
  153. <div class="report-card-radio">
  154. <span>昨日消耗:¥{{ materialReportCardList.yesterdayCost }}</span>
  155. </div>
  156. </a-card>
  157. </a-col>
  158. <a-col :sm="24" :md="12" :xl="6">
  159. <a-card title="视频上新数" class="material-report-card">
  160. <span slot="extra">
  161. <a-tooltip title="显示该筛选条件内上新视频总数" slot="action">
  162. <a-icon type="info-circle-o"/>
  163. </a-tooltip>
  164. </span>
  165. <div class="report-card-result">
  166. <div class="report-card-money">{{ materialReportCardList.videoTotal || 0 }}</div>
  167. <div
  168. class="accountIndexEchart"
  169. id="accountIndexEchart"
  170. style="width:100%; height:50px; margin:0 auto;"
  171. ref="accountIndexEchart"
  172. >
  173. </div>
  174. </div>
  175. <div class="report-card-line"></div>
  176. <div class="report-card-radio">
  177. <span>素材使用率:{{ Number(materialReportCardList.useCompare).toFixed(2) }}%</span>
  178. </div>
  179. </a-card>
  180. </a-col>
  181. <a-col :sm="24" :md="12" :xl="6">
  182. <a-card title="有效视频" class="material-report-card">
  183. <span slot="extra">
  184. <a-tooltip title="筛选时段内上线后一周内消耗大于等于5000的视频总数" slot="action">
  185. <a-icon type="info-circle-o"/>
  186. </a-tooltip>
  187. </span>
  188. <div class="report-card-result">
  189. <div class="report-card-money">{{ materialReportCardList.effectiveTotal || 0 }}</div>
  190. <div
  191. class="accountIndexEchart"
  192. id="effectiveVideoEcharts"
  193. style="width:100%; height:50px; margin:0 auto;"
  194. ref="effectiveVideoEcharts"
  195. >
  196. </div>
  197. </div>
  198. <div class="report-card-line"></div>
  199. <div class="report-card-radio">
  200. <span>素材有效率:{{ Number(materialReportCardList.effectiveCompare).toFixed(2) }}%</span>
  201. </div>
  202. </a-card>
  203. </a-col>
  204. <a-col :sm="24" :md="12" :xl="6">
  205. <a-card title="爆款视频" class="material-report-card">
  206. <span slot="extra">
  207. <a-tooltip title="筛选时段内上线后双周消耗大于等于5w的视频总数" slot="action">
  208. <a-icon type="info-circle-o"/>
  209. </a-tooltip>
  210. </span>
  211. <div class="report-card-result">
  212. <div class="report-card-money">{{ materialReportCardList.hotTotal }}</div>
  213. <div
  214. class="accountIndexEchart"
  215. id="popularVideoEcharts"
  216. style="width:100%; height:50px; margin:0 auto;"
  217. ref="popularVideoEcharts"
  218. >
  219. </div>
  220. </div>
  221. <div class="report-card-line"></div>
  222. <div class="report-card-radio">
  223. <span>
  224. 同比
  225. <a-icon v-if="materialReportCardList.hotYearOnYearCompare >= 0" type="caret-up" style="color: green"/>
  226. <a-icon v-else type="caret-down" style="color: #f00"/>
  227. {{ Number(materialReportCardList.hotYearOnYearCompare * 100).toFixed(2) }}%
  228. </span>
  229. <span>
  230. 日环比
  231. <a-icon v-if="materialReportCardList.hostCompare >= 0" type="caret-up" style="color: green"/>
  232. <a-icon v-else type="caret-down" style="color: #f00"/>
  233. {{ Number(materialReportCardList.hostCompare * 100).toFixed(2) }}%
  234. </span>
  235. </div>
  236. </a-card>
  237. </a-col>
  238. </a-row>
  239. <a-row :gutter="24" style="margin-top: 20px" id="getWidth">
  240. <a-col :xl="18">
  241. <a-card title="数据趋势" style="width: 100%" :bordered="false">
  242. <div class="echart">
  243. <div class="echartBody">
  244. <div
  245. id="echart"
  246. ref="echart"
  247. style="height: 350px"
  248. :style="{ width: (clientWidth / 24) * 18 - 48 - 24 + 'px' }"
  249. >
  250. </div>
  251. <a-empty
  252. style="width: 100%; height: 350px; position: absolute; top: 30%; z-index: 100; left: 0"
  253. v-if="chartList.length == 0"
  254. />
  255. </div>
  256. </div>
  257. </a-card>
  258. </a-col>
  259. <a-col :xl="6">
  260. <a-card title="标签占比" style="width: 100%" :bordered="false">
  261. <div class="echart">
  262. <div class="echartBody">
  263. <a-empty style="height: 350px; position: relative" />
  264. <!-- <div
  265. id="echartCircular"
  266. ref="echartCircular"
  267. style="height: 350px"
  268. :style="{ width: (clientWidth / 24) * 6 - 48 - 24 + 'px' }"
  269. >
  270. </div> -->
  271. </div>
  272. </div>
  273. </a-card>
  274. </a-col>
  275. </a-row>
  276. <a-row :gutter="24" style="margin-top: 20px">
  277. <a-col :xl="12">
  278. <a-card title="top素材排行榜" style="width: 100%; min-height: 700px" :bordered="false">
  279. <a-radio-group
  280. v-if="mediaDimension === 'b'"
  281. v-model="materialRankValue"
  282. style="margin-bottom: 15px;"
  283. @change="handleMaterialRanking"
  284. >
  285. <a-radio-button :value="0">内部</a-radio-button>
  286. <a-radio-button :value="1">素造</a-radio-button>
  287. </a-radio-group>
  288. <a slot="extra" @click="getMoreVideoList">查看更多</a>
  289. <div v-if="videoList.length > 0">
  290. <ul class="top-ul-style">
  291. <li v-for="(item, index) in videoList" :key="index">
  292. <div style="display: flex; position: relative; width: 80%; cursor: pointer">
  293. <span style="position: absolute; top: 50%; width: 40px; height: 40px; margin-top: -20px">
  294. <img :src="require('./image/' + (index + 1) + '.png')" alt="" style="width: 25px; height: auto"/>
  295. </span>
  296. <div
  297. style="
  298. width: 25%;
  299. height: 100%;
  300. text-align: center;
  301. background: #f2f2f2;
  302. margin-left: 40px;
  303. border-radius: 5px;
  304. position: relative;
  305. "
  306. >
  307. <div
  308. :style="{
  309. backgroundImage: 'url(' + (item.coverUrl || noImg) + ')',
  310. backgroundSize: 'cover',
  311. backgroundRepeat: 'no-repeat',
  312. backgroundPosition: 'center center',
  313. overflow: 'hidden',
  314. position: 'absolute',
  315. top: '0',
  316. zIndex: '0',
  317. }"
  318. class="showShare bg"
  319. @click="
  320. visibleVideo = true
  321. videoUrlShow = item.url
  322. "
  323. >
  324. </div>
  325. <img
  326. :src="item.coverUrl || noImg"
  327. style="width: auto; height: 100%; max-width: 100%; position: relative; z-index: 2"
  328. alt=""
  329. srcset=""
  330. @click="
  331. visibleVideo = true
  332. videoUrlShow = item.url
  333. "
  334. />
  335. </div>
  336. <div
  337. style="display: flex; flex-flow: column; justify-content: space-between; width: 60%"
  338. @click.stop="toDetail(item.signature)"
  339. >
  340. <p style="margin-left: 10px; color: #1890ff">
  341. {{ item.materialName ? item.materialName : '无素材名称' }}
  342. </p>
  343. <p style="margin-left: 10px; margin-bottom: 0" v-if="item.tag">
  344. <a-tag
  345. v-for="(items, index) in item.tag.split(',')"
  346. :key="index"
  347. style="margin-right: 5px"
  348. v-if="index <= 3"
  349. >
  350. {{ items }}
  351. </a-tag>
  352. </p>
  353. </div>
  354. </div>
  355. <div class="li-cost">
  356. <span>消耗</span>
  357. <span>{{ (item.charge ? item.charge : item.cost) | decimalsHandle }}</span>
  358. </div>
  359. </li>
  360. </ul>
  361. </div>
  362. <div v-else style="height: 200px;line-height: 200px;text-align: center;">
  363. <a-spin/>
  364. </div>
  365. </a-card>
  366. </a-col>
  367. <a-col :xl="12">
  368. <a-card title="top设计排行榜" style="width: 100%; min-height: 700px" :bordered="false">
  369. <a-radio-group v-model="designRankingValue" style="margin-bottom: 15px;" @change="handleDesignRanking">
  370. <a-radio-button :value="1">摄像</a-radio-button>
  371. <a-radio-button :value="2">剪辑</a-radio-button>
  372. <a-radio-button :value="3">编导</a-radio-button>
  373. </a-radio-group>
  374. <a-table
  375. :columns="columns"
  376. :data-source="designTopList"
  377. bordered
  378. size="middle"
  379. :loading="designTopLoading"
  380. :pagination="false"
  381. >
  382. <span slot="cost" slot-scope="text, records">{{ text | decimalsHandle }}</span>
  383. </a-table>
  384. </a-card>
  385. </a-col>
  386. </a-row>
  387. </a-spin>
  388. <a-modal title="查看视频" v-model="visibleVideo" :width="400" :footer="null">
  389. <video class="video" :src="videoUrlShow" controls="controls" style="width: 100%">
  390. 您的浏览器不支持 video 标签。
  391. </video>
  392. </a-modal>
  393. </div>
  394. </template>
  395. <script>
  396. import moment from 'moment';
  397. import {getAction, postAction, downFile, downFilePost} from '@/api/manage';
  398. import YoutTable from '@/components/youtTable/YoutTable';
  399. import ChartCard from '@/components/ChartCard';
  400. import Trend from '@/components/Trend';
  401. import {mapGetters} from 'vuex';
  402. import {stopOtherVideo, closeAllVideoFun} from '@/utils/videoControl'; // 停止除当前外的其他视频播放,及停止所有视频播放的方法
  403. var echarts = require('echarts');
  404. const columnsFixd = [
  405. {
  406. title: '排名',
  407. dataIndex: 'rowNumber',
  408. align: 'center',
  409. customRender:(t, r, index)=> {
  410.          return index + 1;
  411. }
  412. },
  413. {
  414. title: '设计人员',
  415. dataIndex: 'userName',
  416. align: 'center'
  417. },
  418. {
  419. title: '角色',
  420. dataIndex: 'roleName',
  421. align: 'center'
  422. },
  423. {
  424. title: '消耗(元)',
  425. dataIndex: 'cost',
  426. align: 'center',
  427. scopedSlots: {customRender: 'cost'}
  428. }
  429. ];
  430. export default {
  431. components: {
  432. YoutTable,
  433. ChartCard,
  434. Trend
  435. },
  436. data() {
  437. return {
  438. materialReportCardList: {},
  439. materialRankValue: 0,
  440. designRankingValue: 1,
  441. designTopLoading: false,
  442. noImg: require('@/assets/noImg.png'),
  443. visibleVideo: false,
  444. videoUrlShow: '',
  445. cost: '0',
  446. costLink: 0,
  447. videoTotal: '0',
  448. newVideo: 0,
  449. hotTotal: '0',
  450. xiaoTotal: '0',
  451. spinning: false,
  452. loading: false,
  453. chartList: [],
  454. videoList: [],
  455. designTopList: [],
  456. columns: [...columnsFixd], // table的表头
  457. columnsFixd,
  458. dateRanges: {
  459. 昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
  460. 近三天: [moment().subtract(3, 'days'), moment().subtract(1, 'days')],
  461. 近一周: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
  462. 近14天: [moment().subtract(14, 'days'), moment().subtract(1, 'days')],
  463. 近一月: [moment().subtract(1, 'months'), moment().subtract(1, 'days')],
  464. 近半年: [moment().subtract(6, 'months'), moment().subtract(1, 'days')],
  465. 近一年: [moment().subtract(12, 'months'), moment().subtract(1, 'days')]
  466. },
  467. dateValue: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
  468. dataDimension: 'a',
  469. mediaDimension: 'b',
  470. dataDimensionValue: [],
  471. dataDimensionList: [],
  472. specificLoading: false,
  473. order: 'descend',
  474. target: 'cost',
  475. clientWidth: 0,
  476. resetLoading: false,
  477. searchLoading: false
  478. }
  479. },
  480. watch: {
  481. visibleVideo(n, o) {
  482. if (!n) {
  483. stopOtherVideo();
  484. closeAllVideoFun();
  485. }
  486. }
  487. },
  488. methods: {
  489. ...mapGetters(['userInfo']),
  490. handleMaterialRanking(e) {
  491. this.materialRankValue = e.target.value;
  492. this.getVideoTopList();
  493. },
  494. handleDesignRanking(e) {
  495. this.designRankingValue = e.target.value;
  496. this.getDesignTopList();
  497. },
  498. initAccountIndexEchart(data) {
  499. let xData = data.videoList.length && data.videoList.map(item => item.time);
  500. let yData = data.videoList.length && data.videoList.map(item => item.count);
  501. let option = {
  502. tooltip: {
  503. trigger: 'axis'
  504. },
  505. grid: {
  506. left: '5px',
  507. top: 0,
  508. right: '5px',
  509. bottom: 0
  510. },
  511. xAxis: {
  512. type: 'category',
  513. show: false,
  514. boundaryGap: false,
  515. axisPointer: {
  516. type: 'none'
  517. },
  518. data: xData
  519. },
  520. yAxis: {
  521. type: 'value',
  522. show: false
  523. },
  524. series: [
  525. {
  526. name: '上新数',
  527. data: yData,
  528. type: 'line',
  529. smooth: true,
  530. showSymbol: false,
  531. xAxisIndex: 0,
  532. symbol: 'circle',
  533. lineStyle: {
  534. color: '#9907f5a6',
  535. width: 3
  536. },
  537. itemStyle: {
  538. color: '#9907f5a6',
  539. borderWidth: 2,
  540. borderColor: '#fff'
  541. },
  542. areaStyle: {
  543. color: {
  544. type: 'linear',
  545. x: 0,
  546. y: 0,
  547. x2: 0,
  548. y2: 1,
  549. colorStops: [
  550. {
  551. offset: 0, color: '#9907f5a6' // 0% 处的颜色
  552. },
  553. {
  554. offset: 1, color: 'white' // 100% 处的颜色
  555. }
  556. ]
  557. }
  558. }
  559. }
  560. ]
  561. };
  562. return option;
  563. },
  564. handleEffectiveVideoEcharts(data) {
  565. let xData = data.effectiveList.length && data.effectiveList.map(item => item.time);
  566. let yData = data.effectiveList.length && data.effectiveList.map(item => item.count);
  567. let option = {
  568. tooltip: {
  569. trigger: 'axis'
  570. },
  571. grid: {
  572. left: '5px',
  573. top: 0,
  574. right: '5px',
  575. bottom: 0
  576. },
  577. xAxis: {
  578. type: 'category',
  579. show: false,
  580. boundaryGap: false,
  581. axisPointer: {
  582. type: 'none'
  583. },
  584. data: xData
  585. },
  586. yAxis: {
  587. type: 'value',
  588. show: false
  589. },
  590. series: [
  591. {
  592. name: '上新数',
  593. data: yData,
  594. type: 'bar',
  595. smooth: true,
  596. showSymbol: false,
  597. xAxisIndex: 0,
  598. symbol: 'circle',
  599. lineStyle: {
  600. color: '#2461F1',
  601. width: 3
  602. },
  603. itemStyle: {
  604. color: '#2461F1',
  605. borderWidth: 2,
  606. borderColor: '#fff'
  607. },
  608. areaStyle: {
  609. color: {
  610. type: 'linear',
  611. x: 0,
  612. y: 0,
  613. x2: 0,
  614. y2: 1,
  615. colorStops: [
  616. {
  617. offset: 0, color: '#2461F1' // 0% 处的颜色
  618. },
  619. {
  620. offset: 1, color: 'white' // 100% 处的颜色
  621. }
  622. ]
  623. }
  624. }
  625. }
  626. ]
  627. };
  628. return option;
  629. },
  630. handlePopularVideoEcharts(data) {
  631. let xData = data.hotList.length && data.hotList.map(item => item.time);
  632. let yData = data.hotList.length && data.hotList.map(item => item.count);
  633. let option = {
  634. tooltip: {
  635. trigger: 'axis'
  636. },
  637. grid: {
  638. left: '5px',
  639. top: 0,
  640. right: '5px',
  641. bottom: 0
  642. },
  643. xAxis: {
  644. type: 'category',
  645. show: false,
  646. boundaryGap: false,
  647. axisPointer: {
  648. type: 'none'
  649. },
  650. data: xData
  651. },
  652. yAxis: {
  653. type: 'value',
  654. show: false
  655. },
  656. series: [
  657. {
  658. name: '上新数',
  659. data: yData,
  660. type: 'line',
  661. smooth: true,
  662. showSymbol: false,
  663. xAxisIndex: 0,
  664. symbol: 'circle',
  665. lineStyle: {
  666. color: '#2461F1',
  667. width: 3
  668. },
  669. itemStyle: {
  670. color: '#2461F1',
  671. borderWidth: 2,
  672. borderColor: '#fff'
  673. },
  674. areaStyle: {
  675. color: {
  676. type: 'linear',
  677. x: 0,
  678. y: 0,
  679. x2: 0,
  680. y2: 1,
  681. colorStops: [
  682. {
  683. offset: 0, color: '#2461F1' // 0% 处的颜色
  684. },
  685. {
  686. offset: 1, color: 'white' // 100% 处的颜色
  687. }
  688. ]
  689. }
  690. }
  691. }
  692. ]
  693. };
  694. return option;
  695. },
  696. filterOption(input, option) {
  697. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
  698. },
  699. getData() {
  700. this.spinning = true
  701. Promise.all([
  702. this.getSumData(),
  703. this.getChartDataList(),
  704. this.getVideoTopList(),
  705. this.getDesignTopList()
  706. ]).then((res) => {
  707. this.spinning = false;
  708. this.resetLoading = false;
  709. this.searchLoading = false;
  710. }).catch((error) => {
  711. this.spinning = false;
  712. this.resetLoading = false;
  713. this.searchLoading = false;
  714. this.$error({
  715. title: '页面数据加载出错',
  716. content: '请刷新重试或联系管理员查询'
  717. });
  718. });
  719. },
  720. getProjectList() {
  721. this.specificLoading = true;
  722. return new Promise((resolve, reject) => {
  723. this.postDataAction(
  724. '/overView/getProjects?userId=' + this.userInfo().id + '&mediaId=' + (this.mediaDimension == 'a' ? 1 : 2)
  725. ).then((res) => {
  726. this.specificLoading = false;
  727. if (res.success) {
  728. this.dataDimensionList = res.result;
  729. resolve(res.result);
  730. } else {
  731. reject(res.message);
  732. }
  733. });
  734. });
  735. },
  736. getSumData() {
  737. var that = this;
  738. return new Promise((resolve, reject) => {
  739. that
  740. .postDataAction('/overView/sumData', {
  741. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  742. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  743. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  744. projects: this.dataDimensionValue
  745. })
  746. .then((res) => {
  747. if (res.success) {
  748. console.log(res, 'res--res--res');
  749. this.materialReportCardList = res.result;
  750. this.initEchart('accountIndexEchart', this.initAccountIndexEchart(res.result));
  751. this.initEchart('effectiveVideoEcharts', this.handleEffectiveVideoEcharts(res.result));
  752. this.initEchart('popularVideoEcharts', this.handlePopularVideoEcharts(res.result));
  753. resolve(res.result);
  754. }
  755. else {
  756. reject(res.message);
  757. }
  758. });
  759. });
  760. },
  761. getChartDataList() {
  762. return new Promise((resolve, reject) => {
  763. this.postDataAction('/overView/chartData', {
  764. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  765. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  766. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  767. projects: this.dataDimensionValue
  768. }).then((res) => {
  769. if (res.success) {
  770. this.chartList = res.result;
  771. if (res.result.length == 0) {
  772. const myChart = echarts.init(document.getElementById('echart'));
  773. myChart.dispose();
  774. }
  775. else {
  776. this.initEchart('echart', this.handlerEchartOption(res.result));
  777. }
  778. resolve(res.result);
  779. } else {
  780. reject(res.message);
  781. }
  782. });
  783. });
  784. },
  785. getVideoTopList() {
  786. this.videoList = []
  787. return new Promise((resolve, reject) => {
  788. this.postDataAction('/overView/materialTop', {
  789. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  790. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  791. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  792. channelType: this.materialRankValue,
  793. projects: this.dataDimensionValue
  794. }).then(res => {
  795. if (res.success) {
  796. this.videoList = res.result;
  797. resolve(res.result);
  798. }
  799. else {
  800. reject(res.message);
  801. }
  802. });
  803. });
  804. },
  805. getMoreVideoList() {
  806. var params = {
  807. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  808. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  809. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  810. projects: this.dataDimensionValue
  811. };
  812. params = JSON.stringify(params);
  813. if (this.mediaDimension == 'a') {
  814. localStorage.setItem('TtmaterialParams', params);
  815. this.$router.push({path: '/materialReport/marterialTtList'});
  816. }
  817. else {
  818. localStorage.setItem('materialParams', params);
  819. this.$router.push({path: '/materialReport/marterialList'});
  820. }
  821. },
  822. toDetail(md5) {
  823. var params = {md5: md5, mediaId: this.mediaDimension == 'a' ? 1 : 2};
  824. localStorage.setItem('videoInfo', JSON.stringify(params));
  825. this.$router.push({
  826. path: '/materialReport/marterialDetail'
  827. });
  828. },
  829. getDesignTopList() {
  830. this.designTopLoading = true;
  831. const paramsData = {
  832. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  833. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  834. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  835. projects: this.dataDimensionValue,
  836. type: this.designRankingValue
  837. };
  838. this.postDataAction('/overView/designTop', paramsData).then(res => {
  839. if (res.success) {
  840. this.designTopLoading = false;
  841. this.designTopList = res.result;
  842. }
  843. });
  844. },
  845. getTagProportionAnalyseList() {
  846. return new Promise((resolve, reject) => {
  847. this.postDataAction('/overView/tagProportionAnalyse', {}).then((res) => {
  848. if (res.success) {
  849. resolve(res.result);
  850. } else {
  851. reject(res.message);
  852. }
  853. });
  854. });
  855. },
  856. handleSubmit() {
  857. this.spinning = true;
  858. this.searchLoading = true;
  859. this.getData();
  860. },
  861. resetSubmit() {
  862. this.resetLoading = true;
  863. this.dateValue = [moment().subtract(7, 'days'), moment()];
  864. this.dataDimension = 'a';
  865. this.mediaDimension = 'b';
  866. this.dataDimensionValue = [];
  867. this.getData();
  868. },
  869. //获取echart的值
  870. initEchart(idName, optionName) {
  871. var that = this;
  872. const chart = this.$refs[idName];
  873. if (chart) {
  874. const myChart = echarts.init(document.getElementById(idName));
  875. myChart.setOption(optionName);
  876. window.addEventListener('resize', function () {
  877. that.clientWidth = document.documentElement.clientWidth - 224;
  878. myChart.resize();
  879. });
  880. }
  881. },
  882. handlerEchartOption(data) {
  883. var option = {
  884. noDataLoadingOption: {
  885. text: '暂无数据',
  886. effect: 'bubble',
  887. effectOption: {
  888. effect: {
  889. n: 0,
  890. },
  891. },
  892. },
  893. // title: {
  894. // text: '折线图堆叠'
  895. // },
  896. tooltip: {
  897. trigger: 'axis',
  898. },
  899. // legend: {
  900. // data: ['邮件营销', '联盟广告', ]
  901. // },
  902. grid: {
  903. left: '3%',
  904. right: '4%',
  905. bottom: '3%',
  906. containLabel: true,
  907. },
  908. legend: {
  909. icon: 'circle',
  910. top: '5%',
  911. right: '5%',
  912. itemWidth: 6,
  913. itemGap: 20,
  914. textStyle: {
  915. color: '#556677',
  916. },
  917. },
  918. toolbox: {
  919. // feature: {
  920. // saveAsImage: {}
  921. // }
  922. },
  923. xAxis: {
  924. type: 'category',
  925. data: data.map((item) => {
  926. return item.statDate
  927. }),
  928. boundaryGap: false,
  929. // 坐标轴线
  930. axisLine: {
  931. show: false,
  932. lineStyle: {
  933. color: '#999',
  934. },
  935. },
  936. // 分割线
  937. splitLine: {
  938. show: true,
  939. lineStyle: {
  940. type: 'dashed',
  941. color: '#e5e5e5',
  942. },
  943. },
  944. },
  945. yAxis: {
  946. type: 'value',
  947. axisLine: {
  948. show: false,
  949. lineStyle: {
  950. color: '#999',
  951. },
  952. },
  953. splitLine: {
  954. lineStyle: {
  955. type: 'dashed',
  956. color: '#e5e5e5',
  957. },
  958. },
  959. },
  960. series: [
  961. {
  962. smooth: true,
  963. name: '消耗',
  964. type: 'line',
  965. stack: '总量',
  966. data: data.map((item) => {
  967. return item.cost.toFixed(3)
  968. }),
  969. symbol: 'circle',
  970. symbolSize: 6,
  971. lineStyle: {
  972. normal: {
  973. width: 2,
  974. // color: '#0bcd74'
  975. },
  976. },
  977. itemStyle: {
  978. borderColor: '#ffffff',
  979. borderWidth: 0,
  980. },
  981. },
  982. ],
  983. };
  984. return option;
  985. },
  986. handlerAgeOption(data) {
  987. const colorList = ['#58D5FF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF'];
  988. var option = {
  989. color: colorList,
  990. backgroundColor: '#fff',
  991. tooltip: {
  992. formatter: '{b}:{c}',
  993. },
  994. legend: {
  995. orient: 'horizontal',
  996. top: 'top',
  997. icon: 'circle',
  998. width: '100%',
  999. data: ['形式标签', '场景标签', '基调标签', '其他'],
  1000. },
  1001. series: [
  1002. {
  1003. name: '',
  1004. type: 'pie',
  1005. radius: ['40%', '70%'],
  1006. center: ['50%', '50%'],
  1007. data: [
  1008. { value: 0, name: '形式标签' },
  1009. { value: 0, name: '基调标签' },
  1010. { value: 0, name: '场景标签' },
  1011. { value: 0, name: '其他' },
  1012. ],
  1013. labelLine: {
  1014. length: 5,
  1015. length2: 5,
  1016. },
  1017. label: {
  1018. show: false,
  1019. position: 'center',
  1020. },
  1021. emphasis: {
  1022. label: {
  1023. show: true,
  1024. fontSize: '18',
  1025. fontWeight: 'bold',
  1026. },
  1027. },
  1028. labelLine: {
  1029. show: true,
  1030. },
  1031. itemStyle: {
  1032. borderRadius: 5,
  1033. color: (params) => {
  1034. return colorList[params.dataIndex]
  1035. },
  1036. },
  1037. },
  1038. ],
  1039. };
  1040. return option;
  1041. },
  1042. disabledDate(current) {
  1043. return current && current > moment().subtract(1, 'days');
  1044. },
  1045. mediaDimensionChange(e) {
  1046. if (e.target.value === 'b') {
  1047. this.materialRankValue = 0;
  1048. }
  1049. else {
  1050. this.materialRankValue = '';
  1051. }
  1052. this.dataDimensionList = [];
  1053. this.dataDimensionValue = [];
  1054. this.getProjectList();
  1055. },
  1056. },
  1057. mounted() {
  1058. this.clientWidth = document.documentElement.clientWidth - 224;
  1059. this.$nextTick(() => {
  1060. this.getProjectList();
  1061. this.getData();
  1062. });
  1063. },
  1064. activated() {
  1065. this.$nextTick(() => {
  1066. this.clientWidth = document.documentElement.clientWidth - 224;
  1067. });
  1068. }
  1069. };
  1070. </script>
  1071. <style lang="less" scoped>
  1072. .materialReport {
  1073. .material-report-card {
  1074. height: 220px;
  1075. /deep/ .ant-card-head {
  1076. border: none;
  1077. }
  1078. /deep/ .ant-card-body {
  1079. padding-top: 5px;
  1080. }
  1081. .report-card-result {
  1082. height: 88px;
  1083. }
  1084. .report-card-money {
  1085. font-size: 30px;
  1086. font-weight: bold;
  1087. }
  1088. .report-card-msg {
  1089. display: flex;
  1090. justify-content: space-between;
  1091. font-size: 14px;
  1092. margin-top: 20px;
  1093. }
  1094. .report-card-line {
  1095. width: 100%;
  1096. height: 1px;
  1097. margin-top: 20px;
  1098. background: #e8e8e8;
  1099. }
  1100. .report-card-radio {
  1101. display: flex;
  1102. justify-content: space-between;
  1103. margin-top: 12px;
  1104. font-size: 16px;
  1105. }
  1106. }
  1107. .option {
  1108. background: white;
  1109. padding: 20px;
  1110. display: flex;
  1111. justify-content: flex-start;
  1112. flex-wrap: wrap;
  1113. .item {
  1114. margin-right: 15px;
  1115. margin-bottom: 15px;
  1116. height: 32px;
  1117. line-height: 32px;
  1118. flex-shrink: 0;
  1119. span {
  1120. margin-right: 10px;
  1121. }
  1122. }
  1123. }
  1124. .echart {
  1125. margin-top: 20px;
  1126. padding: 0 20px 20px;
  1127. background: white;
  1128. .echart-header {
  1129. padding: 20px 0;
  1130. font-size: 15px;
  1131. font-weight: 600;
  1132. }
  1133. }
  1134. .tableBody {
  1135. margin-top: 20px;
  1136. }
  1137. }
  1138. </style>
  1139. <style>
  1140. .materialReport .card-containers {
  1141. overflow: hidden !important;
  1142. }
  1143. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-content {
  1144. margin-top: -16px !important;
  1145. }
  1146. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
  1147. background: #fff !important;
  1148. }
  1149. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar {
  1150. border-color: #fff !important;
  1151. }
  1152. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
  1153. border-color: transparent !important;
  1154. background: transparent !important;
  1155. }
  1156. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
  1157. border-color: #fff !important;
  1158. background: #fff !important;
  1159. }
  1160. </style>