materialReport.vue 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  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"><a-icon type="unordered-list" />素材大盘</span>
  54. </a-tab-pane>
  55. </a-tabs>
  56. <div class="option" style="justify-content: space-between">
  57. <div class="option" style="padding: 0">
  58. <div class="item">
  59. <span>日期选择</span>
  60. <a-range-picker
  61. v-model="dateValue"
  62. :ranges="dateRanges"
  63. :disabled-date="disabledDate"
  64. style="width: 250px"
  65. />
  66. </div>
  67. <div class="item">
  68. <span>媒体维度</span>
  69. <a-radio-group v-model="mediaDimension" @change="mediaDimensionChange">
  70. <a-radio-button value="b">快手</a-radio-button>
  71. <a-radio-button value="a">头条</a-radio-button>
  72. </a-radio-group>
  73. </div>
  74. <div class="item">
  75. <span>数据维度</span>
  76. <a-radio-group v-model="dataDimension" @change="changeDataDimension">
  77. <a-radio-button value="a">项目</a-radio-button>
  78. <a-radio-button value="b" :disabled="groupDisabled">设计组</a-radio-button>
  79. <a-radio-button value="c">设计人</a-radio-button>
  80. </a-radio-group>
  81. <a-select
  82. v-if="dataDimension != 'c'"
  83. v-model="dataDimensionValue"
  84. style="width: 300px; margin-left: 10px"
  85. :mode="dataDimension === 'a' ? 'multiple' : 'default'"
  86. :maxTagCount="2"
  87. :loading="specificLoading"
  88. :filterOption="filterOption"
  89. showSearch
  90. allowClear
  91. >
  92. <a-select-option
  93. v-if="dataDimensionList.length == 0 && specificLoading"
  94. value="no"
  95. disabled
  96. >
  97. 数据请求中,请稍后。。。
  98. </a-select-option>
  99. <a-select-option
  100. v-for="(item, index) in dataDimensionList"
  101. :key="index + 1"
  102. :value="item.projectId"
  103. >
  104. {{ item.projectName }}{{ item.leaderId ? '-' + item.leaderName : '' }}
  105. </a-select-option>
  106. </a-select>
  107. </div>
  108. </div>
  109. <div class="item" style="float: right">
  110. <a-button
  111. :loading="searchLoading"
  112. :disabled="dateValue.length == 0 || (dataDimension == 'b' && !dataDimensionValue)"
  113. type="primary"
  114. @click="handleSubmit"
  115. >
  116. 搜索
  117. </a-button>
  118. <a-button
  119. :disabled="spinning"
  120. :loading="resetLoading"
  121. style="margin-left: 15px"
  122. @click="resetSubmit"
  123. >
  124. 重置
  125. </a-button>
  126. </div>
  127. </div>
  128. </div>
  129. <a-spin :spinning="spinning">
  130. <a-row :gutter="24" style="margin-top: 20px">
  131. <a-col :sm="24" :md="12" :xl="6">
  132. <a-card class="material-report-card">
  133. <span slot="title">
  134. 总消耗
  135. <a-tooltip title="当前筛选条件内的素材总消耗" slot="action">
  136. <a-icon type="info-circle-o" />
  137. </a-tooltip>
  138. </span>
  139. <div class="report-card-result">
  140. <div class="report-card-money">
  141. {{ materialReportCardList.costTotal ? '¥' + materialReportCardList.costTotal : '-' }}
  142. </div>
  143. <div class="report-card-msg">
  144. <span>
  145. 同比
  146. <a-icon
  147. v-if="materialReportCardList.yearOnYearCompare >= 0"
  148. type="caret-up"
  149. style="color: #f00"
  150. />
  151. <a-icon v-else type="caret-down" style="color: green" />
  152. {{ Number(materialReportCardList.yearOnYearCompare * 100).toFixed(2) }}%
  153. </span>
  154. <span>
  155. 日环比
  156. <a-icon
  157. v-if="materialReportCardList.chainCompare >= 0"
  158. type="caret-up"
  159. style="color: #f00"
  160. />
  161. <a-icon v-else type="caret-down" style="color: green" />
  162. {{ Number(materialReportCardList.chainCompare * 100).toFixed(2) }}%
  163. </span>
  164. </div>
  165. </div>
  166. <div class="report-card-line"></div>
  167. <div class="report-card-radio">
  168. <span
  169. >昨日消耗:{{
  170. materialReportCardList.yesterdayCost
  171. ? '¥' + materialReportCardList.yesterdayCost
  172. : '-'
  173. }}</span
  174. >
  175. </div>
  176. </a-card>
  177. </a-col>
  178. <a-col :sm="24" :md="12" :xl="6">
  179. <a-card class="material-report-card">
  180. <span slot="title">
  181. 视频上新数
  182. <a-tooltip title="当前筛选条件内的视频上传数" slot="action">
  183. <a-icon type="info-circle-o" />
  184. </a-tooltip>
  185. </span>
  186. <div class="report-card-result">
  187. <div class="report-card-money">{{ accountIndexList.videoTotal | formatCurrency }}</div>
  188. <div
  189. v-if="timeShowEchartsStatus"
  190. id="accountIndexEchart"
  191. class="accountIndexEchart"
  192. style="width:100%; height:50px; margin:0 auto;"
  193. ref="accountIndexEchart"
  194. :style="{ width: (clientWidth / 24) * 6 - 48 - 24 + 'px' }"
  195. ></div>
  196. </div>
  197. <div class="report-card-line"></div>
  198. <div class="report-card-radio">
  199. <span
  200. >素材使用率:{{
  201. accountIndexList.useCompare
  202. ? Number(accountIndexList.useCompare * 100).toFixed(2)
  203. : '0.00'
  204. }}%</span
  205. >
  206. </div>
  207. </a-card>
  208. </a-col>
  209. <a-col :sm="24" :md="12" :xl="6">
  210. <a-card class="material-report-card">
  211. <span slot="title">
  212. 有效视频
  213. <a-tooltip title="筛选时段内上线后一周内消耗大于等于5000的视频总数" slot="action">
  214. <a-icon type="info-circle-o" />
  215. </a-tooltip>
  216. </span>
  217. <span slot="extra">
  218. <a @click="getMoreVideoList('materialQuality')">更多</a>
  219. </span>
  220. <!-- <span slot="extra">
  221. <a-tooltip title="筛选时段内上线后一周内消耗大于等于5000的视频总数" slot="action">
  222. <a-icon type="info-circle-o" />
  223. </a-tooltip>
  224. </span> -->
  225. <div class="report-card-result">
  226. <div class="report-card-money">{{ accountIndexList.effectiveTotal | formatCurrency }}</div>
  227. <div
  228. v-if="timeShowEchartsStatus"
  229. class="accountIndexEchart"
  230. id="effectiveVideoEcharts"
  231. style="width:100%; height:50px; margin:0 auto;"
  232. ref="effectiveVideoEcharts"
  233. :style="{ width: (clientWidth / 24) * 6 - 48 - 24 + 'px' }"
  234. ></div>
  235. </div>
  236. <div class="report-card-line"></div>
  237. <div class="report-card-radio">
  238. <span
  239. >素材有效率:{{
  240. accountIndexList.effectiveCompare
  241. ? Number(accountIndexList.effectiveCompare * 100).toFixed(2)
  242. : '0.00'
  243. }}%</span
  244. >
  245. </div>
  246. </a-card>
  247. </a-col>
  248. <a-col :sm="24" :md="12" :xl="6">
  249. <a-spin :spinning="spinningPopularVideoList">
  250. <a-card class="material-report-card">
  251. <span slot="title">
  252. 爆款视频
  253. <a-tooltip title="筛选时段内上线后双周消耗大于等于5w的视频总数" slot="action">
  254. <a-icon type="info-circle-o" />
  255. </a-tooltip>
  256. </span>
  257. <span slot="extra">
  258. <a @click="getMoreVideoList('materialType')">更多</a>
  259. </span>
  260. <div class="report-card-result">
  261. <div class="report-card-money">{{ popularVideoList.hotTotal | formatCurrency }}</div>
  262. <div
  263. v-if="timeShowEchartsStatus"
  264. class="accountIndexEchart"
  265. id="popularVideoEcharts"
  266. style="width:100%; height:50px; margin:0 auto;"
  267. ref="popularVideoEcharts"
  268. :style="{ width: (clientWidth / 24) * 6 - 48 - 24 + 'px' }"
  269. ></div>
  270. </div>
  271. <div class="report-card-line"></div>
  272. <div class="report-card-radio">
  273. <span> </span>
  274. <span>
  275. <a-radio-group v-model="videoType" @change="getPopularVideoData">
  276. <a-radio-button :value="0">不限</a-radio-button>
  277. <a-radio-button :value="1">制作</a-radio-button>
  278. <a-radio-button :value="2">真人</a-radio-button>
  279. </a-radio-group>
  280. </span>
  281. </div>
  282. </a-card>
  283. </a-spin>
  284. </a-col>
  285. </a-row>
  286. </a-spin>
  287. <a-spin :spinning="spinningMaterialGroupData">
  288. <a-row
  289. :gutter="24"
  290. style="margin-top: 20px"
  291. v-if="dataDimension == 'b' && materialGroupData.avgCost != null"
  292. >
  293. <a-col :sm="24" style="display:flex;">
  294. <a-card class="material-report-card-two" :bordered="false">
  295. <span slot="title">
  296. 组内人均消耗
  297. <a-tooltip title="当前筛选条件下小组人员的平均消耗" slot="action">
  298. <a-icon type="info-circle-o" />
  299. </a-tooltip>
  300. </span>
  301. <div class="report-card-result">
  302. <div class="report-card-money">
  303. {{ '¥' + decimalsHandle(materialGroupData.avgCost, 2) }}
  304. </div>
  305. </div>
  306. <div class="report-card-line"></div>
  307. </a-card>
  308. <a-card class="material-report-card-two" :bordered="false">
  309. <span slot="title">
  310. 组人效
  311. <a-tooltip title="当前筛选条件内的上传视频数 / 组总人数(编导+剪辑+摄像)" slot="action">
  312. <a-icon type="info-circle-o" />
  313. </a-tooltip>
  314. </span>
  315. <div class="report-card-result">
  316. <div class="report-card-money">{{ materialGroupData.peopleWork }}</div>
  317. </div>
  318. <div class="report-card-line"></div>
  319. </a-card>
  320. <a-card class="material-report-card-two" :bordered="false">
  321. <span slot="title">
  322. 创新视频数
  323. <a-tooltip title="当前筛选条件内的创新视频数" slot="action">
  324. <a-icon type="info-circle-o" />
  325. </a-tooltip>
  326. </span>
  327. <div class="report-card-result">
  328. <div class="report-card-money">{{ materialGroupData.innovativeVideoCount }}</div>
  329. </div>
  330. <div class="report-card-line"></div>
  331. </a-card>
  332. <a-card
  333. class="material-report-card-two"
  334. :bordered="false"
  335. v-if="materialGroupData.innovativeVideoCost != null"
  336. >
  337. <span slot="title">
  338. 创新视频消耗
  339. <a-tooltip title="当前筛选条件内的创新视频消耗" slot="action">
  340. <a-icon type="info-circle-o" />
  341. </a-tooltip>
  342. </span>
  343. <div class="report-card-result">
  344. <div class="report-card-money">
  345. {{ '¥' + decimalsHandle(materialGroupData.innovativeVideoCost, 2) }}
  346. </div>
  347. </div>
  348. <div class="report-card-line"></div>
  349. </a-card>
  350. <a-card
  351. class="material-report-card-two"
  352. :bordered="false"
  353. v-if="materialGroupData.avgMaterialCost != null"
  354. >
  355. <span slot="title">
  356. 上新素材平均消耗
  357. <a-tooltip title="当前筛选条件下小组内的上新素材平均消耗" slot="action">
  358. <a-icon type="info-circle-o" />
  359. </a-tooltip>
  360. </span>
  361. <div class="report-card-result">
  362. <div class="report-card-money">
  363. {{ '¥' + decimalsHandle(materialGroupData.avgMaterialCost, 2) }}
  364. </div>
  365. </div>
  366. <div class="report-card-line"></div>
  367. </a-card>
  368. </a-col>
  369. </a-row>
  370. </a-spin>
  371. <a-row :gutter="24" style="margin-top: 20px" id="getWidth">
  372. <a-col :xl="18">
  373. <a-spin :spinning="spinningChart">
  374. <a-card title="数据趋势" style="width: 100%" :bordered="false">
  375. <a-tabs v-model="active" @change="callback">
  376. <a-tab-pane key="cost" tab="消耗"> </a-tab-pane>
  377. <a-tab-pane key="active" tab="激活数"> </a-tab-pane>
  378. <a-tab-pane key="aclick" tab="曝光数"> </a-tab-pane>
  379. <!-- <a-tab-pane key="play_duration_3s" tab="3S播放率">
  380. </a-tab-pane> -->
  381. </a-tabs>
  382. <div class="echart">
  383. <div class="echartBody">
  384. <div
  385. id="echart"
  386. ref="echart"
  387. style="height: 350px"
  388. :style="{ width: (clientWidth / 24) * 18 - 48 - 24 + 'px' }"
  389. ></div>
  390. <a-empty
  391. v-if="chartList.length == 0"
  392. style="width: 100%; height: 350px; position: absolute; top: 30%; z-index: 100; left: 0"
  393. />
  394. </div>
  395. </div>
  396. </a-card>
  397. </a-spin>
  398. </a-col>
  399. <a-col :xl="6">
  400. <a-spin :spinning="spinningChartPie">
  401. <a-card style="width: 100%" :bordered="false">
  402. <span slot="title">
  403. 标签占比
  404. <a-radio-group
  405. v-model="labelType"
  406. @change="getLabelDataList"
  407. size="small"
  408. style="margin-left:10px"
  409. >
  410. <a-radio-button :value="0">素材数</a-radio-button>
  411. <a-radio-button :value="1">消耗</a-radio-button>
  412. </a-radio-group>
  413. </span>
  414. <a-tabs v-model="active" @change="callback" style="visibility:hidden;">
  415. <a-tab-pane key="cost" tab="消耗"> </a-tab-pane>
  416. <a-tab-pane key="active" tab="激活数"> </a-tab-pane>
  417. <a-tab-pane key="aclick" tab="曝光数"> </a-tab-pane>
  418. <a-tab-pane key="play_duration_3s" tab="3S播放率"> </a-tab-pane>
  419. </a-tabs>
  420. <div class="echart">
  421. <div class="echartBody">
  422. <!-- <a-empty style="height: 350px; position: relative" /> -->
  423. <div
  424. id="echartCircular"
  425. ref="echartCircular"
  426. style="height: 350px"
  427. :style="{ width: (clientWidth / 24) * 6 - 48 - 24 + 'px' }"
  428. >
  429. <a-empty
  430. style="width: 100%; height: 350px; position: absolute; top: 30%; z-index: 100; left: 0"
  431. />
  432. </div>
  433. </div>
  434. </div>
  435. </a-card>
  436. </a-spin>
  437. </a-col>
  438. </a-row>
  439. <a-row :gutter="24" style="margin-top: 20px">
  440. <a-col :xl="12">
  441. <a-card title="top素材排行榜" style="width: 100%; min-height: 720px" :bordered="false">
  442. <a-radio-group
  443. v-if="mediaDimension === 'b'"
  444. v-model="materialRankValue"
  445. style="margin-bottom: 15px;"
  446. @change="handleMaterialRanking"
  447. >
  448. <a-radio-button :value="0">内部</a-radio-button>
  449. <a-radio-button :value="1">素造</a-radio-button>
  450. </a-radio-group>
  451. <a slot="extra" @click="getMoreVideoList">查看更多</a>
  452. <div v-if="!signatureStatus && videoList.length > 0">
  453. <ul class="top-ul-style">
  454. <li v-for="(item, index) in videoList" :key="item.signature">
  455. <div style="display: flex; position: relative; width: 80%; cursor: pointer">
  456. <span
  457. style="position: absolute; top: 50%; width: 40px; height: 40px; margin-top: -20px"
  458. >
  459. <img
  460. :src="require('./image/' + (index + 1) + '.png')"
  461. alt=""
  462. style="width: 25px; height: auto"
  463. />
  464. </span>
  465. <div
  466. style="
  467. width: 25%;
  468. height: 100%;
  469. text-align: center;
  470. background: #f2f2f2;
  471. margin-left: 40px;
  472. border-radius: 5px;
  473. position: relative;
  474. "
  475. >
  476. <div
  477. :style="{
  478. backgroundImage: 'url(' + (item.coverUrl || noImg) + ')',
  479. backgroundSize: 'cover',
  480. backgroundRepeat: 'no-repeat',
  481. backgroundPosition: 'center center',
  482. overflow: 'hidden',
  483. position: 'absolute',
  484. top: '0',
  485. zIndex: '0'
  486. }"
  487. class="showShare bg"
  488. @click="
  489. visibleVideo = true
  490. videoUrlShow = item.url
  491. "
  492. ></div>
  493. <img
  494. :src="item.coverUrl || noImg"
  495. style="width: auto; height: 100%; max-width: 100%; position: relative; z-index: 2"
  496. srcset=""
  497. @click="
  498. visibleVideo = true
  499. videoUrlShow = item.url
  500. "
  501. />
  502. </div>
  503. <div
  504. style="display: flex; flex-flow: column; justify-content: space-between; width: 60%"
  505. @click.stop="toDetail(item.material_id)"
  506. >
  507. <p style="margin-left: 10px; color: #1890ff">
  508. {{ item.materialName ? item.materialName : '无素材名称' }}
  509. </p>
  510. <p v-if="item.tag" style="margin-left: 10px; margin-bottom: 0">
  511. <a-tag
  512. v-for="(items, val) in item.tag.split(',')"
  513. :key="val + 1"
  514. style="margin-right: 5px"
  515. v-if="val <= 3"
  516. >
  517. {{ items }}
  518. </a-tag>
  519. </p>
  520. </div>
  521. </div>
  522. <div class="li-cost">
  523. <span>消耗</span>
  524. <span>{{ (item.charge ? item.charge : item.cost) | decimalsHandle }}</span>
  525. </div>
  526. </li>
  527. </ul>
  528. </div>
  529. <a-empty v-else-if="!signatureStatus && videoList.length === 0" style="margin-top: 20%" />
  530. <div v-else style="height: 200px;line-height: 200px;text-align: center;">
  531. <a-spin />
  532. </div>
  533. <a-pagination size="small" :total="50" v-if="designTopList.length > 0" style="visibility:hidden;" />
  534. </a-card>
  535. </a-col>
  536. <a-col :xl="12">
  537. <a-card title="top设计排行榜" style="width: 100%; min-height: 720px" :bordered="false">
  538. <a-radio-group
  539. v-model="designRankingValue"
  540. style="margin-bottom: 15px;"
  541. @change="handleDesignRanking"
  542. >
  543. <a-radio-button :value="1">摄像</a-radio-button>
  544. <a-radio-button :value="2">剪辑</a-radio-button>
  545. <a-radio-button :value="3">编导</a-radio-button>
  546. </a-radio-group>
  547. <a-table
  548. :columns="columns"
  549. :data-source="designTopList"
  550. :loading="designTopLoading"
  551. :pagination="ipagination"
  552. bordered
  553. size="middle"
  554. >
  555. <span slot="cost" slot-scope="text, records">{{ text | decimalsHandle }}</span>
  556. </a-table>
  557. </a-card>
  558. </a-col>
  559. </a-row>
  560. <a-modal title="查看视频" v-model="visibleVideo" :width="400" :footer="null">
  561. <video class="video" :src="videoUrlShow" controls="controls" style="width: 100%">
  562. 您的浏览器不支持 video 标签。
  563. </video>
  564. </a-modal>
  565. </div>
  566. </template>
  567. <script>
  568. import moment from 'moment'
  569. import YoutTable from '@/components/youtTable/YoutTable'
  570. import ChartCard from '@/components/ChartCard'
  571. import Trend from '@/components/Trend'
  572. import { mapGetters } from 'vuex'
  573. import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
  574. var echarts = require('echarts')
  575. const columnsFixd = [
  576. {
  577. title: '排名',
  578. dataIndex: 'number',
  579. align: 'center'
  580. },
  581. {
  582. title: '设计人员',
  583. dataIndex: 'userName',
  584. align: 'center'
  585. },
  586. {
  587. title: '角色',
  588. dataIndex: 'roleName',
  589. align: 'center'
  590. },
  591. {
  592. title: '消耗(元)',
  593. dataIndex: 'cost',
  594. align: 'center',
  595. scopedSlots: { customRender: 'cost' }
  596. }
  597. ]
  598. const columnsTt = [
  599. {
  600. title: '排名',
  601. dataIndex: 'number',
  602. align: 'center'
  603. },
  604. {
  605. title: '设计人员',
  606. dataIndex: 'userName',
  607. align: 'center'
  608. },
  609. {
  610. title: '消耗(元)',
  611. dataIndex: 'cost',
  612. align: 'center',
  613. scopedSlots: { customRender: 'cost' }
  614. },
  615. {
  616. title: '爆款视频数',
  617. dataIndex: 'videoHotCount',
  618. align: 'center'
  619. }
  620. ]
  621. export default {
  622. components: {
  623. YoutTable,
  624. ChartCard,
  625. Trend
  626. },
  627. data() {
  628. return {
  629. spinningMaterialGroupData:false,
  630. ipagination: {
  631. current: 1,
  632. pageSize: 10,
  633. // pageSizeOptions: ['10', '20', '30'],
  634. showTotal: (total, range) => {
  635. return range[0] + '-' + range[1] + ' 共' + total + '条'
  636. },
  637. showQuickJumper: true,
  638. // showSizeChanger: true,
  639. pageSizeOptions: ['10', '30', '50'],
  640. total: 0,
  641. onChange: (current, pageSize) => {
  642. // 切换分页时的回调,
  643. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  644. this.ipagination.current = current
  645. this.ipagination.pageSize = pageSize
  646. this.getDesignTopList()
  647. }
  648. },
  649. active: 'cost',
  650. groupDisabled: false,
  651. timeShowEchartsStatus: true,
  652. signatureStatus: false,
  653. materialReportCardList: {},
  654. materialGroupData: {},
  655. accountIndexList: {},
  656. popularVideoList: {},
  657. materialRankValue: 0,
  658. designRankingValue: 1,
  659. designTopLoading: false,
  660. noImg: require('@/assets/noImg.png'),
  661. visibleVideo: false,
  662. videoUrlShow: '',
  663. cost: '0',
  664. spinning: false,
  665. spinningChart: false,
  666. spinningChartPie: false,
  667. loading: false,
  668. chartList: [],
  669. videoList: [],
  670. designTopList: [],
  671. columns: [...columnsFixd], // table的表头
  672. columnsFixd,
  673. dateRanges: {
  674. 昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
  675. 近三天: [moment().subtract(3, 'days'), moment().subtract(1, 'days')],
  676. 近一周: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
  677. 近14天: [moment().subtract(14, 'days'), moment().subtract(1, 'days')],
  678. 近一月: [moment().subtract(1, 'months'), moment().subtract(1, 'days')],
  679. 近半年: [moment().subtract(6, 'months'), moment().subtract(1, 'days')],
  680. 近一年: [moment().subtract(12, 'months'), moment().subtract(1, 'days')]
  681. },
  682. dateValue: [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
  683. videoType: 0,
  684. labelType: 0,
  685. dataDimension: 'a',
  686. mediaDimension: 'b',
  687. dataDimensionValue: [],
  688. dataDimensionList: [],
  689. specificLoading: false,
  690. clientWidth: 0,
  691. resetLoading: false,
  692. searchLoading: false,
  693. spinningPopularVideoList: false
  694. }
  695. },
  696. watch: {
  697. visibleVideo(n, o) {
  698. if (!n) {
  699. stopOtherVideo()
  700. closeAllVideoFun()
  701. }
  702. }
  703. },
  704. methods: {
  705. ...mapGetters(['userInfo']),
  706. handleMaterialRanking(e) {
  707. this.materialRankValue = e.target.value
  708. this.getVideoTopList()
  709. },
  710. handleDesignRanking(e) {
  711. this.designRankingValue = e.target.value
  712. this.ipagination.current = 1
  713. this.getDesignTopList()
  714. },
  715. initAccountIndexEchart(data) {
  716. let xData = data.videoList.length && data.videoList.map(item => item.time)
  717. let yData = data.videoList.length && data.videoList.map(item => item.count)
  718. let option = {
  719. tooltip: {
  720. trigger: 'axis'
  721. },
  722. grid: {
  723. left: '5px',
  724. top: 0,
  725. right: '5px',
  726. bottom: 0
  727. },
  728. xAxis: {
  729. type: 'category',
  730. show: false,
  731. boundaryGap: false,
  732. axisPointer: {
  733. type: 'none'
  734. },
  735. data: xData
  736. },
  737. yAxis: {
  738. type: 'value',
  739. show: false
  740. },
  741. series: [
  742. {
  743. name: '上新数',
  744. data: yData,
  745. type: 'line',
  746. smooth: true,
  747. showSymbol: false,
  748. xAxisIndex: 0,
  749. symbol: 'circle',
  750. lineStyle: {
  751. color: '#9907f5a6',
  752. width: 3
  753. },
  754. itemStyle: {
  755. color: '#9907f5a6',
  756. borderWidth: 2,
  757. borderColor: '#fff'
  758. },
  759. areaStyle: {
  760. color: {
  761. type: 'linear',
  762. x: 0,
  763. y: 0,
  764. x2: 0,
  765. y2: 1,
  766. colorStops: [
  767. {
  768. offset: 0,
  769. color: '#9907f5a6' // 0% 处的颜色
  770. },
  771. {
  772. offset: 1,
  773. color: 'white' // 100% 处的颜色
  774. }
  775. ]
  776. }
  777. }
  778. }
  779. ]
  780. }
  781. return option
  782. },
  783. handleEffectiveVideoEcharts(data) {
  784. let xData = data.effectiveList.length && data.effectiveList.map(item => item.time)
  785. let yData = data.effectiveList.length && data.effectiveList.map(item => item.count)
  786. let option = {
  787. tooltip: {
  788. trigger: 'axis'
  789. },
  790. grid: {
  791. left: '5px',
  792. top: 0,
  793. right: '5px',
  794. bottom: 0
  795. },
  796. xAxis: {
  797. type: 'category',
  798. show: false,
  799. boundaryGap: false,
  800. axisPointer: {
  801. type: 'none'
  802. },
  803. data: xData
  804. },
  805. yAxis: {
  806. type: 'value',
  807. show: false
  808. },
  809. series: [
  810. {
  811. name: '有效数',
  812. data: yData,
  813. type: 'bar',
  814. smooth: true,
  815. showSymbol: false,
  816. xAxisIndex: 0,
  817. symbol: 'circle',
  818. lineStyle: {
  819. color: '#2461F1',
  820. width: 3
  821. },
  822. itemStyle: {
  823. color: '#2461F1',
  824. borderWidth: 2,
  825. borderColor: '#fff'
  826. },
  827. areaStyle: {
  828. color: {
  829. type: 'linear',
  830. x: 0,
  831. y: 0,
  832. x2: 0,
  833. y2: 1,
  834. colorStops: [
  835. {
  836. offset: 0,
  837. color: '#2461F1' // 0% 处的颜色
  838. },
  839. {
  840. offset: 1,
  841. color: 'white' // 100% 处的颜色
  842. }
  843. ]
  844. }
  845. }
  846. }
  847. ]
  848. }
  849. return option
  850. },
  851. handlePopularVideoEcharts(data) {
  852. let xData = data.hotList.length && data.hotList.map(item => item.time)
  853. let yData = data.hotList.length && data.hotList.map(item => item.count)
  854. let option = {
  855. tooltip: {
  856. trigger: 'axis'
  857. },
  858. grid: {
  859. left: '5px',
  860. top: 0,
  861. right: '5px',
  862. bottom: 0
  863. },
  864. xAxis: {
  865. type: 'category',
  866. show: false,
  867. boundaryGap: false,
  868. axisPointer: {
  869. type: 'none'
  870. },
  871. data: xData
  872. },
  873. yAxis: {
  874. type: 'value',
  875. show: false
  876. },
  877. series: [
  878. {
  879. name: '爆款数',
  880. data: yData,
  881. type: 'line',
  882. smooth: true,
  883. showSymbol: false,
  884. xAxisIndex: 0,
  885. symbol: 'circle',
  886. lineStyle: {
  887. color: '#2461F1',
  888. width: 3
  889. },
  890. itemStyle: {
  891. color: '#2461F1',
  892. borderWidth: 2,
  893. borderColor: '#fff'
  894. },
  895. areaStyle: {
  896. color: {
  897. type: 'linear',
  898. x: 0,
  899. y: 0,
  900. x2: 0,
  901. y2: 1,
  902. colorStops: [
  903. {
  904. offset: 0,
  905. color: '#2461F1' // 0% 处的颜色
  906. },
  907. {
  908. offset: 1,
  909. color: 'white' // 100% 处的颜色
  910. }
  911. ]
  912. }
  913. }
  914. }
  915. ]
  916. }
  917. return option
  918. },
  919. filterOption(input, option) {
  920. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  921. },
  922. getData() {
  923. this.spinning = true
  924. this.spinningChart = true
  925. this.active = 'cost'
  926. this.getVideoTopList()
  927. this.getDesignTopList()
  928. this.getLabelDataList()
  929. this.getChartDataList()
  930. if (this.dataDimension == 'b') {
  931. this.getGroupData()
  932. }
  933. Promise.all([this.getSumData(), this.getAccountIndexData(), this.getPopularVideoData()])
  934. .then(res => {
  935. this.spinning = false
  936. this.resetLoading = false
  937. this.searchLoading = false
  938. })
  939. .catch(error => {
  940. this.spinning = false
  941. this.resetLoading = false
  942. this.searchLoading = false
  943. // this.$error({
  944. // title: '页面数据加载出错',
  945. // content: '请刷新重试或联系管理员查询'
  946. // });
  947. })
  948. },
  949. getProjectList() {
  950. this.specificLoading = true
  951. return new Promise((resolve, reject) => {
  952. this.postDataAction(
  953. process.env.VUE_APP_BASE_MATERIAL_URL +
  954. '/overView/V2/getProjects?userId=' +
  955. this.userInfo().id +
  956. '&mediaId=' +
  957. (this.mediaDimension == 'a' ? 1 : 2)
  958. ).then(res => {
  959. this.specificLoading = false
  960. if (res.success) {
  961. this.dataDimensionList = res.result
  962. // 找到重复的数据
  963. // const changeData = res.result.map(item => item.projectId);
  964. // let rep = [];
  965. // changeData.forEach((item,index)=>{
  966. // if(changeData.indexOf(item)!=index){ // 匹配数组元素第一个item位置和当前循环的index
  967. // let obj = {};
  968. // obj.key = (changeData.indexOf(item) + 1) + '|' + (index + 1); // 用'|'分隔两个重复项的下标
  969. // obj.value = item;
  970. // rep.push(obj);
  971. // }
  972. // });
  973. // console.log(rep, 'newArr--newArr');
  974. resolve(res.result)
  975. } else {
  976. reject(res.message)
  977. }
  978. })
  979. })
  980. },
  981. decimalsHandle(val, num) {
  982. if (val && typeof val != 'string') {
  983. if (val >= 0) {
  984. val = parseFloat(val).toFixed(num)
  985. let numberStr = val.toString()
  986. let str = numberStr.split('.')
  987. let str0 = str[0].split('').reverse()
  988. for (let i = 0; i < str0.length; i++) {
  989. if ((i + 1) % 4 === 0) {
  990. str0.splice(i, 0, ',')
  991. }
  992. }
  993. str0.reverse()
  994. let handleResult = ''
  995. for (let j = 0; j < str0.length; j++) {
  996. handleResult += str0[j]
  997. }
  998. return handleResult + '.' + str[1]
  999. } else {
  1000. val = parseFloat(val).toFixed(num)
  1001. let numberStr = val.toString()
  1002. let str = numberStr.split('.')
  1003. let str0 = str[0]
  1004. .substr(1)
  1005. .split('')
  1006. .reverse()
  1007. for (let i = 0; i < str0.length; i++) {
  1008. if ((i + 1) % 4 === 0) {
  1009. str0.splice(i, 0, ',')
  1010. }
  1011. }
  1012. str0.reverse()
  1013. let handleResult = ''
  1014. for (let j = 0; j < str0.length; j++) {
  1015. handleResult += str0[j]
  1016. }
  1017. return '-' + handleResult + '.' + str[1]
  1018. }
  1019. } else if (typeof val == 'string') {
  1020. return val
  1021. } else {
  1022. return 0
  1023. }
  1024. },
  1025. getSumData() {
  1026. let that = this
  1027. let params = {}
  1028. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1029. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1030. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1031. params.dimension =
  1032. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1033. params.userId = this.userInfo().id
  1034. if (this.dataDimension === 'a') {
  1035. params.projects = this.dataDimensionValue
  1036. } else if (this.dataDimension === 'b') {
  1037. params.leaderId = this.dataDimensionValue
  1038. } else {
  1039. params.designerId = this.userInfo().id
  1040. }
  1041. return new Promise((resolve, reject) => {
  1042. that.postDataAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/sumData', params).then(
  1043. res => {
  1044. if (res.success) {
  1045. let defaultList = res.result
  1046. if (this.mediaDimension === 'b') {
  1047. defaultList.costTotal = this.decimalsHandle(defaultList.costTotal, 3)
  1048. defaultList.yesterdayCost = this.decimalsHandle(defaultList.yesterdayCost, 3)
  1049. } else {
  1050. defaultList.costTotal = this.decimalsHandle(defaultList.costTotal, 2)
  1051. defaultList.yesterdayCost = this.decimalsHandle(defaultList.yesterdayCost, 2)
  1052. }
  1053. this.materialReportCardList = res.result
  1054. resolve(res.result)
  1055. } else {
  1056. reject(res.message)
  1057. }
  1058. }
  1059. )
  1060. })
  1061. },
  1062. getGroupData() {
  1063. if (this.dataDimension == 'b') {
  1064. this.spinningMaterialGroupData = true
  1065. let that = this
  1066. let params = {}
  1067. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1068. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1069. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1070. params.userId = this.userInfo().id
  1071. if (this.dataDimension === 'a') {
  1072. params.projects = this.dataDimensionValue
  1073. } else if (this.dataDimension === 'b') {
  1074. params.leaderId = this.dataDimensionValue
  1075. } else {
  1076. params.designerId = this.userInfo().id
  1077. }
  1078. return new Promise((resolve, reject) => {
  1079. that.postDataAction(
  1080. process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/getDesignerAvgData',
  1081. params
  1082. ).then(res => {
  1083. this.spinningMaterialGroupData = false
  1084. if (res.success) {
  1085. // let defaultList = res.result
  1086. // if (this.mediaDimension === 'b') {
  1087. // defaultList.costTotal = this.decimalsHandle(defaultList.costTotal, 3)
  1088. // defaultList.yesterdayCost = this.decimalsHandle(defaultList.yesterdayCost, 3)
  1089. // } else {
  1090. // defaultList.costTotal = this.decimalsHandle(defaultList.costTotal, 2)
  1091. // defaultList.yesterdayCost = this.decimalsHandle(defaultList.yesterdayCost, 2)
  1092. // }
  1093. this.materialGroupData = res.result
  1094. resolve(res.result)
  1095. } else {
  1096. reject(res.message)
  1097. }
  1098. })
  1099. })
  1100. }
  1101. },
  1102. getAccountIndexData() {
  1103. let that = this
  1104. let params = {}
  1105. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1106. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1107. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1108. params.dimension =
  1109. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1110. params.userId = this.userInfo().id
  1111. if (this.dataDimension === 'a') {
  1112. params.projects = this.dataDimensionValue
  1113. } else if (this.dataDimension === 'b') {
  1114. params.leaderId = this.dataDimensionValue
  1115. } else {
  1116. params.designerId = this.userInfo().id
  1117. }
  1118. return new Promise((resolve, reject) => {
  1119. that.postDataAction(
  1120. process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/sumDataVideoNewEffective',
  1121. params
  1122. ).then(res => {
  1123. if (res.success) {
  1124. this.accountIndexList = res.result
  1125. this.initEchart('accountIndexEchart', this.initAccountIndexEchart(res.result))
  1126. this.initEchart('effectiveVideoEcharts', this.handleEffectiveVideoEcharts(res.result))
  1127. resolve(res.result)
  1128. } else {
  1129. reject(res.message)
  1130. }
  1131. })
  1132. })
  1133. },
  1134. getPopularVideoData() {
  1135. let that = this
  1136. let params = {}
  1137. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1138. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1139. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1140. params.dimension =
  1141. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1142. params.userId = this.userInfo().id
  1143. params.type = this.videoType
  1144. if (this.dataDimension === 'a') {
  1145. params.projects = this.dataDimensionValue
  1146. } else if (this.dataDimension === 'b') {
  1147. params.leaderId = this.dataDimensionValue
  1148. } else {
  1149. params.designerId = this.userInfo().id
  1150. }
  1151. this.spinningPopularVideoList = true
  1152. return new Promise((resolve, reject) => {
  1153. that.postDataAction(
  1154. process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/sumDataVideoHot',
  1155. params
  1156. ).then(res => {
  1157. this.spinningPopularVideoList = false
  1158. if (res.success) {
  1159. this.popularVideoList = res.result
  1160. this.initEchart('popularVideoEcharts', this.handlePopularVideoEcharts(res.result))
  1161. resolve(res.result)
  1162. } else {
  1163. reject(res.message)
  1164. }
  1165. })
  1166. })
  1167. },
  1168. callback() {
  1169. this.initEchart('echart', this.handlerEchartOption(this.chartList, this.active))
  1170. },
  1171. getLabelDataList() {
  1172. this.spinningChartPie = true
  1173. let params = {}
  1174. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1175. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1176. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1177. params.dimension =
  1178. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1179. params.userId = this.userInfo().id
  1180. params.type = this.labelType
  1181. if (this.dataDimension === 'a') {
  1182. params.projects = this.dataDimensionValue
  1183. } else if (this.dataDimension === 'b') {
  1184. params.leaderId = this.dataDimensionValue
  1185. } else {
  1186. params.designerId = this.userInfo().id
  1187. }
  1188. return new Promise((resolve, reject) => {
  1189. this.postDataAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/labelRatio', params).then(
  1190. res => {
  1191. this.spinningChartPie = false
  1192. if (res.success) {
  1193. if (res.result) {
  1194. this.initEchart('echartCircular', this.handlerAgeOption(res.result))
  1195. } else {
  1196. const myChart = echarts.init(document.getElementById('echartCircular'))
  1197. myChart.dispose()
  1198. this.$nextTick(() => {
  1199. var html =
  1200. '<div class="ant-empty"><div class="ant-empty-image"><svg width="184" height="152" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg"><g fill="none" fillRule="evenodd"><g transform="translate(24 31.67)"><ellipse fillOpacity=".8" fill="#F5F5F7" cx="67.797" cy="106.89" rx="67.797" ry="12.668"></ellipse><path d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z" fill="#AEB8C2"></path><path d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z" fill="url(#linearGradient-1)" transform="translate(13.56)"></path><path d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z" fill="#F5F5F7"></path><path d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z" fill="#DCE0E6"></path></g><path d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z" fill="#DCE0E6"></path><g transform="translate(149.65 15.383)" fill="#FFF"><ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse><path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path></g></g></svg></div><p class="ant-empty-description">暂无数据</p></div>'
  1201. document.getElementById('echartCircular').innerHTML = html
  1202. document.getElementById('echartCircular').removeAttribute('_echarts_instance_')
  1203. })
  1204. }
  1205. resolve(res.result)
  1206. } else {
  1207. reject(res.message)
  1208. }
  1209. }
  1210. )
  1211. })
  1212. },
  1213. getChartDataList() {
  1214. let params = {}
  1215. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1216. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1217. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1218. params.dimension =
  1219. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1220. params.userId = this.userInfo().id
  1221. if (this.dataDimension === 'a') {
  1222. params.projects = this.dataDimensionValue
  1223. } else if (this.dataDimension === 'b') {
  1224. params.leaderId = this.dataDimensionValue
  1225. } else {
  1226. params.designerId = this.userInfo().id
  1227. }
  1228. return new Promise((resolve, reject) => {
  1229. this.postDataAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/chartData', params).then(
  1230. res => {
  1231. this.spinningChart = false
  1232. if (res.success) {
  1233. this.chartList = res.result
  1234. if (res.result.length == 0) {
  1235. const myChart = echarts.init(document.getElementById('echart'))
  1236. myChart.dispose()
  1237. } else {
  1238. this.initEchart('echart', this.handlerEchartOption(res.result, 'cost'))
  1239. }
  1240. resolve(res.result)
  1241. } else {
  1242. reject(res.message)
  1243. }
  1244. }
  1245. )
  1246. })
  1247. },
  1248. getVideoTopList() {
  1249. this.videoList = []
  1250. this.signatureStatus = true
  1251. let params = {}
  1252. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1253. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1254. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1255. params.dimension =
  1256. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1257. params.userId = this.userInfo().id
  1258. params.channelType = this.materialRankValue
  1259. if (this.dataDimension === 'a') {
  1260. params.projects = this.dataDimensionValue
  1261. } else if (this.dataDimension === 'b') {
  1262. params.leaderId = this.dataDimensionValue
  1263. } else {
  1264. params.designerId = this.userInfo().id
  1265. }
  1266. return new Promise((resolve, reject) => {
  1267. this.postDataAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/materialTop', params)
  1268. .then(res => {
  1269. this.signatureStatus = false
  1270. if (res.success) {
  1271. this.videoList = res.result || []
  1272. resolve(res.result)
  1273. } else {
  1274. reject(res.message)
  1275. }
  1276. })
  1277. .catch(error => {
  1278. this.signatureStatus = false
  1279. })
  1280. })
  1281. },
  1282. getMoreVideoList(data) {
  1283. localStorage.removeItem('TtmaterialParams')
  1284. localStorage.removeItem('materialParams')
  1285. var params = {
  1286. mediaId: this.mediaDimension == 'a' ? 1 : 2,
  1287. startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  1288. endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  1289. dataDimension: this.dataDimension,
  1290. mediaDimension: this.mediaDimension,
  1291. dateValue: this.dateValue,
  1292. dataDimensionValue: this.dataDimensionValue,
  1293. innovative: '',
  1294. materialType: '',
  1295. materialQuality: ''
  1296. }
  1297. if (data == 'materialQuality') {
  1298. params.materialQuality = 1
  1299. } else if (data == 'materialType') {
  1300. params.materialQuality = 0
  1301. params.materialType = this.videoType == 0 ? '' : this.videoType
  1302. }
  1303. params = JSON.stringify(params)
  1304. if (this.mediaDimension == 'a') {
  1305. localStorage.setItem('TtmaterialParams', params)
  1306. this.$router.push({ path: '/materialReport/marterialTtList' })
  1307. } else {
  1308. localStorage.setItem('materialParams', params)
  1309. this.$router.push({ path: '/materialReport/marterialList' })
  1310. }
  1311. },
  1312. toDetail(md5) {
  1313. let params = { md5: md5, mediaId: this.mediaDimension == 'a' ? 1 : 2 }
  1314. localStorage.setItem('videoInfo', JSON.stringify(params))
  1315. this.$router.push({
  1316. path: '/materialReport/marterialDetail'
  1317. })
  1318. },
  1319. getDesignTopList() {
  1320. this.designTopLoading = true
  1321. let params = {}
  1322. params.mediaId = this.mediaDimension === 'a' ? 1 : 2
  1323. params.startDate = this.dateValue.length === 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
  1324. params.endDate = this.dateValue.length === 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
  1325. params.dimension =
  1326. this.dataDimension === 'a' ? 'project' : this.dataDimension === 'b' ? 'designTeam' : 'designer'
  1327. params.userId = this.userInfo().id
  1328. params.type = this.designRankingValue
  1329. params.pageNumber = this.ipagination.current
  1330. params.pageSize = this.ipagination.pageSize
  1331. if (this.dataDimension === 'a') {
  1332. params.projects = this.dataDimensionValue
  1333. } else if (this.dataDimension === 'b') {
  1334. params.leaderId = this.dataDimensionValue
  1335. } else {
  1336. params.designerId = this.userInfo().id
  1337. }
  1338. // const paramsData = {
  1339. // startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
  1340. // endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
  1341. // mediaId: this.mediaDimension == 'a' ? 1 : 2,
  1342. // projects: this.dataDimensionValue,
  1343. // type: this.designRankingValue
  1344. // }
  1345. this.postDataAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/designTop', params).then(res => {
  1346. if (res.success) {
  1347. this.designTopLoading = false
  1348. this.designTopList = res.result.list
  1349. this.ipagination.total = res.result.total
  1350. } else {
  1351. this.designTopLoading = false
  1352. this.$message.error(this.message)
  1353. }
  1354. })
  1355. },
  1356. getTagProportionAnalyseList() {
  1357. return new Promise((resolve, reject) => {
  1358. this.postDataAction(
  1359. process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/tagProportionAnalyse',
  1360. {}
  1361. ).then(res => {
  1362. if (res.success) {
  1363. resolve(res.result)
  1364. } else {
  1365. reject(res.message)
  1366. }
  1367. })
  1368. })
  1369. },
  1370. handleSubmit() {
  1371. this.spinning = true
  1372. this.searchLoading = true
  1373. const dataOne = new Date(this.dateValue[0]).getTime()
  1374. const dataTwo = new Date(this.dateValue[1]).getTime()
  1375. if (dataTwo === dataOne) {
  1376. this.timeShowEchartsStatus = false
  1377. } else {
  1378. this.timeShowEchartsStatus = true
  1379. }
  1380. if (this.mediaDimension === 'b') {
  1381. this.columns = [...columnsFixd]
  1382. } else {
  1383. this.columns = [...columnsTt]
  1384. }
  1385. this.videoType = 0
  1386. this.labelType = 0
  1387. this.designRankingValue = 1
  1388. this.ipagination.current = 1
  1389. this.getData()
  1390. },
  1391. resetSubmit() {
  1392. this.resetLoading = true
  1393. this.dateValue = [moment().subtract(7, 'days'), moment()]
  1394. this.dataDimension = 'a'
  1395. this.mediaDimension = 'b'
  1396. this.dataDimensionValue = []
  1397. this.videoType = 0
  1398. this.labelType = 0
  1399. this.designRankingValue = 1
  1400. this.ipagination.current = 1
  1401. this.getData()
  1402. },
  1403. //获取echart的值
  1404. initEchart(idName, optionName) {
  1405. let that = this
  1406. const chart = this.$refs[idName]
  1407. if (chart) {
  1408. const myChart = echarts.init(document.getElementById(idName))
  1409. myChart.setOption(optionName)
  1410. window.addEventListener('resize', function() {
  1411. that.clientWidth = document.documentElement.clientWidth - 224
  1412. myChart.resize()
  1413. })
  1414. }
  1415. },
  1416. handlerEchartOption(data, typeShow) {
  1417. let option = {
  1418. noDataLoadingOption: {
  1419. text: '暂无数据',
  1420. effect: 'bubble',
  1421. effectOption: {
  1422. effect: {
  1423. n: 0
  1424. }
  1425. }
  1426. },
  1427. tooltip: {
  1428. trigger: 'axis'
  1429. // formatter: function(params) {
  1430. // if(typeShow == 'play_duration_3s'){
  1431. // return `${params[0].marker}${params[0].name}<br/>${params[0].seriesName}:${params[0].value}%`
  1432. // }else{
  1433. // return `${params[0].marker}${params[0].name}<br/>${params[0].seriesName}:${params[0].value}`
  1434. // }
  1435. // },
  1436. },
  1437. grid: {
  1438. left: '3%',
  1439. right: '4%',
  1440. bottom: '3%',
  1441. containLabel: true
  1442. },
  1443. legend: {
  1444. icon: 'circle',
  1445. top: '5%',
  1446. right: '5%',
  1447. itemWidth: 6,
  1448. itemGap: 20,
  1449. textStyle: {
  1450. color: '#556677'
  1451. }
  1452. },
  1453. xAxis: {
  1454. type: 'category',
  1455. data: data.map(item => {
  1456. return item.statDate
  1457. }),
  1458. boundaryGap: false,
  1459. // 坐标轴线
  1460. axisLine: {
  1461. show: false,
  1462. lineStyle: {
  1463. color: '#999'
  1464. }
  1465. },
  1466. // 分割线
  1467. splitLine: {
  1468. show: true,
  1469. lineStyle: {
  1470. type: 'dashed',
  1471. color: '#e5e5e5'
  1472. }
  1473. }
  1474. },
  1475. yAxis: {
  1476. type: 'value',
  1477. axisLine: {
  1478. show: false,
  1479. lineStyle: {
  1480. color: '#999'
  1481. }
  1482. },
  1483. splitLine: {
  1484. lineStyle: {
  1485. type: 'dashed',
  1486. color: '#e5e5e5'
  1487. }
  1488. }
  1489. },
  1490. series: [
  1491. {
  1492. smooth: true,
  1493. name:
  1494. typeShow == 'cost'
  1495. ? '消耗'
  1496. : typeShow == 'aclick'
  1497. ? '曝光数'
  1498. : typeShow == 'active'
  1499. ? '激活数'
  1500. : '3S播放率',
  1501. type: 'line',
  1502. stack: '总量',
  1503. data: data.map(item => {
  1504. switch (typeShow) {
  1505. case 'cost':
  1506. return item.cost.toFixed(3)
  1507. break
  1508. case 'aclick':
  1509. return item.aclick
  1510. break
  1511. case 'active':
  1512. return item.active
  1513. break
  1514. case 'play_duration_3s':
  1515. return item.play_duration_3s.slice(0, item.play_duration_3s.length - 1)
  1516. break
  1517. }
  1518. }),
  1519. symbol: 'circle',
  1520. symbolSize: 6,
  1521. lineStyle: {
  1522. normal: {
  1523. width: 2
  1524. }
  1525. },
  1526. itemStyle: {
  1527. borderColor: '#ffffff',
  1528. borderWidth: 0
  1529. }
  1530. }
  1531. ]
  1532. }
  1533. return option
  1534. },
  1535. handlerAgeOption(data) {
  1536. const colorList = ['#58D5FF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF']
  1537. let that = this
  1538. let option = {
  1539. color: colorList,
  1540. backgroundColor: '#fff',
  1541. tooltip: {
  1542. formatter: function(params) {
  1543. if (that.labelType == 0) {
  1544. return `${params.marker}${params.name}素材数: ${params.value}<br/>
  1545. ${params.marker}${params.name}素材数占比: ${params.percent}%`
  1546. } else {
  1547. return `${params.marker}${params.name}消耗: ${that.decimalsHandle(params.value, 2)}<br/>
  1548. ${params.marker}${params.name}消耗占比: ${params.percent}%`
  1549. }
  1550. }
  1551. },
  1552. legend: {
  1553. orient: 'horizontal',
  1554. top: 'top',
  1555. icon: 'circle',
  1556. width: '100%',
  1557. data: ['真人', '制作', '其他']
  1558. },
  1559. series: [
  1560. {
  1561. name: '',
  1562. type: 'pie',
  1563. radius: ['40%', '70%'],
  1564. center: ['50%', '50%'],
  1565. data: [
  1566. { value: data.reality, name: '真人' },
  1567. { value: data.making, name: '制作' },
  1568. { value: data.other, name: '其他' }
  1569. ],
  1570. labelLine: {
  1571. length: 5,
  1572. length2: 5
  1573. },
  1574. label: {
  1575. show: false,
  1576. position: 'center'
  1577. },
  1578. emphasis: {
  1579. label: {
  1580. show: true,
  1581. fontSize: '18',
  1582. fontWeight: 'bold'
  1583. }
  1584. },
  1585. labelLine: {
  1586. show: true
  1587. },
  1588. itemStyle: {
  1589. borderRadius: 5,
  1590. color: params => {
  1591. return colorList[params.dataIndex]
  1592. }
  1593. }
  1594. }
  1595. ]
  1596. }
  1597. return option
  1598. },
  1599. disabledDate(current) {
  1600. return current && current > moment().subtract(1, 'days')
  1601. },
  1602. changeDataDimension(e) {
  1603. this.materialGroupData = {}
  1604. if (e.target.value == 'c') {
  1605. this.dataDimensionValue = undefined
  1606. } else if (e.target.value == 'b') {
  1607. this.dataDimensionValue = ''
  1608. this.getDesignTeamList()
  1609. } else if (e.target.value == 'a') {
  1610. this.dataDimensionList = []
  1611. this.dataDimensionValue = []
  1612. this.getProjectList()
  1613. }
  1614. },
  1615. getDesignTeamList() {
  1616. this.specificLoading = true
  1617. this.dataDimensionList = []
  1618. var params = {}
  1619. params.mediaId = this.mediaDimension == 'a' ? 1 : 2
  1620. params.userId = this.userInfo().id
  1621. this.getAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/getDesignTeamList', params).then(
  1622. res => {
  1623. this.specificLoading = false
  1624. if (res.success) {
  1625. this.dataDimensionList = res.result.map(item => {
  1626. return {
  1627. ...item,
  1628. projectId: item.leaderId,
  1629. projectName: item.departName
  1630. }
  1631. })
  1632. let data = this.dataDimensionList.filter(i => {
  1633. return i.default
  1634. })
  1635. if (data.length == 1) {
  1636. this.dataDimensionValue = data[0].projectId
  1637. }
  1638. }
  1639. }
  1640. )
  1641. },
  1642. mediaDimensionChange(e) {
  1643. this.dataDimensionValue = undefined
  1644. if (e.target.value === 'b') {
  1645. this.materialRankValue = 0
  1646. } else {
  1647. this.materialRankValue = ''
  1648. }
  1649. if (this.dataDimension == 'b') {
  1650. this.getDesignTeamList()
  1651. } else {
  1652. this.dataDimensionList = []
  1653. this.dataDimensionValue = []
  1654. this.getProjectList()
  1655. }
  1656. }
  1657. },
  1658. mounted() {
  1659. this.clientWidth = document.documentElement.clientWidth - 224
  1660. this.$nextTick(() => {
  1661. this.getAction(process.env.VUE_APP_BASE_MATERIAL_URL + '/overView/V2/getRole', {
  1662. userId: this.userInfo().id
  1663. }).then(res => {
  1664. if (res.success) {
  1665. this.groupDisabled = !res.result.permissions
  1666. } else {
  1667. this.groupDisabled = true
  1668. }
  1669. })
  1670. this.getProjectList()
  1671. this.getData()
  1672. })
  1673. },
  1674. activated() {
  1675. this.$nextTick(() => {
  1676. this.clientWidth = document.documentElement.clientWidth - 224
  1677. })
  1678. }
  1679. }
  1680. </script>
  1681. <style lang="less" scoped>
  1682. .materialReport {
  1683. .material-report-card-two {
  1684. width: 25%;
  1685. ::v-deep * {
  1686. border: 0;
  1687. }
  1688. }
  1689. .material-report-card {
  1690. height: 220px;
  1691. ::v-deep .ant-card-head {
  1692. border: none;
  1693. }
  1694. ::v-deep .ant-card-body {
  1695. padding-top: 5px;
  1696. }
  1697. .report-card-result {
  1698. height: 88px;
  1699. }
  1700. .report-card-money {
  1701. font-size: 30px;
  1702. font-weight: bold;
  1703. }
  1704. .report-card-msg {
  1705. display: flex;
  1706. justify-content: space-between;
  1707. font-size: 14px;
  1708. margin-top: 20px;
  1709. }
  1710. .report-card-line {
  1711. width: 100%;
  1712. height: 1px;
  1713. margin-top: 20px;
  1714. background: #e8e8e8;
  1715. }
  1716. .report-card-radio {
  1717. display: flex;
  1718. justify-content: space-between;
  1719. margin-top: 12px;
  1720. font-size: 14px;
  1721. }
  1722. }
  1723. .option {
  1724. background: white;
  1725. padding: 20px;
  1726. display: flex;
  1727. justify-content: flex-start;
  1728. flex-wrap: wrap;
  1729. .item {
  1730. margin-right: 15px;
  1731. margin-bottom: 15px;
  1732. height: 32px;
  1733. line-height: 32px;
  1734. flex-shrink: 0;
  1735. span {
  1736. margin-right: 10px;
  1737. }
  1738. }
  1739. }
  1740. .echart {
  1741. margin-top: 20px;
  1742. padding: 0 20px 20px;
  1743. background: white;
  1744. .echart-header {
  1745. padding: 20px 0;
  1746. font-size: 15px;
  1747. font-weight: 600;
  1748. }
  1749. }
  1750. .tableBody {
  1751. margin-top: 20px;
  1752. }
  1753. }
  1754. </style>
  1755. <style>
  1756. .materialReport .card-containers {
  1757. overflow: hidden !important;
  1758. }
  1759. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-content {
  1760. margin-top: -16px !important;
  1761. }
  1762. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
  1763. background: #fff !important;
  1764. }
  1765. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar {
  1766. border-color: #fff !important;
  1767. }
  1768. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
  1769. border-color: transparent !important;
  1770. background: transparent !important;
  1771. }
  1772. .materialReport .card-containers > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
  1773. border-color: #fff !important;
  1774. background: #fff !important;
  1775. }
  1776. </style>