index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. <template>
  2. <div style="font-size: 0; background-color: #fff">
  3. <img
  4. :src="
  5. 'https://cxzx.smcic.net/zhoubao/assets/tv' + $route.query.date + '.jpg'
  6. "
  7. width="100%"
  8. class="content"
  9. style="margin-bottom: 1em; display: block"
  10. alt=""
  11. />
  12. <p
  13. class="content"
  14. :style="
  15. 'font-weight: 700;word-break: normal;text-align: justify; padding: 0.5em 3px;font-size: ' +
  16. fontSize +
  17. 'px;'
  18. "
  19. v-html="title.desc"
  20. ></p>
  21. <div :style="'height: ' + fontSize + 'px;'"></div>
  22. <div class="tv-list" :style="'font-size:' + fontSize + 'px'">
  23. <div class="content">
  24. <!-- <div class="titleTop">
  25. <p v-text="title.company"></p>
  26. <p v-text="title.name"></p>
  27. <p v-text="title.title"></p>
  28. </div> -->
  29. <div class="itemHead">
  30. <van-row>
  31. <van-col span="4" class="td"> 省排名 </van-col>
  32. <van-col span="6" class="td"> 频道 </van-col>
  33. <van-col span="5">
  34. <van-popover
  35. v-model="fene"
  36. trigger="click"
  37. @select="fene = !fene"
  38. >
  39. <div style="padding: 5px">
  40. 市场份额=本频道收视率/所有频道收视率
  41. </div>
  42. <template #reference>
  43. <p class="td">市场份额</p>
  44. </template>
  45. </van-popover>
  46. </van-col>
  47. <!-- td2 :style="width > 667 ? 'line-height: 2.5em' : 'line-height: 1.5em'" -->
  48. <van-col span="7">
  49. <van-popover
  50. v-model="shichang"
  51. trigger="click"
  52. @select="shichang = !shichang"
  53. >
  54. <div style="padding: 5px">
  55. 市场份额=本频道收视率/所有频道收视率
  56. </div>
  57. <template #reference>
  58. <p class="td">周人均时长(分)</p>
  59. </template>
  60. </van-popover>
  61. </van-col>
  62. <van-col span="2" class="td">
  63. <img
  64. src="../../../assets/image/shou.gif"
  65. width="26px"
  66. alt=""
  67. style="vertical-align: middle; transform: rotate(45deg)"
  68. />
  69. </van-col>
  70. </van-row>
  71. </div>
  72. <div v-for="(v, o) in platfromData || []" :key="v.name">
  73. <div
  74. style="border-bottom: 1px dashed #eee; margin: 11px 0 0 0"
  75. v-if="o === 50"
  76. ></div>
  77. <van-row
  78. :style="v.shanxi_channel ? 'background: #F5DEB3' : ''"
  79. class="item"
  80. @click="() => showPopup(o)"
  81. >
  82. <van-col
  83. span="4"
  84. :class="{ td: true }"
  85. :style="{ color: color[o] || '#000', fontWeight: 600 }"
  86. >
  87. {{ v.rank }}
  88. </van-col>
  89. <van-col
  90. :style="v.shanxi_channel ? 'font-weight: 600' : ''"
  91. span="6"
  92. :class="{ td: true }"
  93. >
  94. {{ v.channelname }}
  95. </van-col>
  96. <van-col span="5" :class="{ td: true }">
  97. {{ formatNum(v.occrate, 2) }}%
  98. <van-icon
  99. v-if="v.occrate_change !== '相等'"
  100. name="down"
  101. :color="v.occrate_change === '上升' ? '#f00' : '#04c15f'"
  102. :class="{ rise: v.occrate_change === '上升' }"
  103. />
  104. </van-col>
  105. <van-col span="7" :class="{ td: true }">
  106. {{ timeFormat(v.user_duration) }}
  107. <van-icon
  108. v-if="v.user_duration_change !== '相等'"
  109. name="down"
  110. :color="v.user_duration_change === '上升' ? '#f00' : '#04c15f'"
  111. :class="{ rise: v.user_duration_change === '上升' }"
  112. />
  113. </van-col>
  114. <van-col span="2" class="td" style="cursor: pointer">
  115. <van-icon name="arrow" />
  116. </van-col>
  117. </van-row>
  118. </div>
  119. <van-popup
  120. :style="{ height: '100%', width: '100%' }"
  121. position="right"
  122. v-model="show"
  123. >
  124. <div class="main">
  125. <van-cell
  126. title-style="flex: 3"
  127. :title="ratios.schedulename"
  128. :label="ratios.channelname"
  129. >
  130. <div
  131. @click="show = false"
  132. :style="
  133. 'float:left;color: #5470c6;word-break: normal;text-align: justify;cursor:pointer;font-size:' +
  134. fontSize +
  135. 'px'
  136. "
  137. >
  138. <van-icon name="revoke" />
  139. 返回
  140. </div>
  141. <div
  142. :style="
  143. 'width: 100%; text-align: center;font-size:' + fontSize + 'px'
  144. "
  145. >
  146. {{ ratios.channelname }}
  147. </div>
  148. </van-cell>
  149. <van-cell-group title="视听收视新指标">
  150. <van-row>
  151. <van-col span="7" class="td" style="text-align: right">
  152. 收视总时长:
  153. </van-col>
  154. <van-col span="5" class="td">
  155. {{ ratios.timecount }}小时
  156. </van-col>
  157. <van-col
  158. span="12"
  159. class="td"
  160. :style="
  161. ratios.timecount_ring > 0 ? 'color: red' : 'color: #04c15f'
  162. "
  163. >
  164. {{ ratios.timecount_compare }}
  165. </van-col>
  166. <van-col span="7" class="td" style="text-align: right">
  167. 收视总次数:
  168. </van-col>
  169. <van-col span="5" class="td">
  170. {{ ratios.hitcount }}
  171. </van-col>
  172. <van-col
  173. span="12"
  174. class="td"
  175. :style="
  176. ratios.hitcount_ring > 0 ? 'color: red' : 'color: #04c15f'
  177. "
  178. >
  179. {{ ratios.hitcount_compare }}
  180. </van-col>
  181. <van-col span="7" class="td" style="text-align: right">
  182. 周活跃户数:
  183. </van-col>
  184. <van-col span="5" class="td">
  185. {{ ratios.usrcount }}
  186. </van-col>
  187. <van-col
  188. span="12"
  189. class="td"
  190. :style="
  191. ratios.usrcount_ring > 0 ? 'color: red' : 'color: #04c15f'
  192. "
  193. >
  194. {{ ratios.usrcount_compare }}
  195. </van-col>
  196. <van-col span="7" class="td" style="text-align: right">
  197. 周接触频次:
  198. </van-col>
  199. <van-col span="5" class="td">
  200. {{ formatType1(ratios.touchfreq, 2) }}次
  201. </van-col>
  202. <van-col
  203. span="12"
  204. class="td"
  205. :style="
  206. ratios.touchfreq_ring > 0 ? 'color: red' : 'color: #04c15f'
  207. "
  208. >
  209. {{ ratios.touchfreq_compare }}
  210. </van-col>
  211. </van-row>
  212. </van-cell-group>
  213. <van-cell-group title="传统指标">
  214. <van-row>
  215. <van-col span="7" class="td" style="text-align: right">
  216. 到达率:
  217. </van-col>
  218. <van-col span="7" class="td"
  219. >{{ formatNum(ratios.reachrate, 2) }}%
  220. </van-col>
  221. <van-col
  222. span="10"
  223. class="td"
  224. :style="
  225. ratios.reachrate_ring > 0 ? 'color: red' : 'color: #04c15f'
  226. "
  227. >
  228. {{ ratios.reachrate_compare }}
  229. </van-col>
  230. <van-col span="7" class="td" style="text-align: right">
  231. 周人均时长:
  232. </van-col>
  233. <van-col span="7" class="td"
  234. >{{ timeFormat(ratios.user_duration, 0) }}分钟
  235. </van-col>
  236. <van-col
  237. span="10"
  238. class="td"
  239. :style="
  240. ratios.user_duration_ring > 0
  241. ? 'color: red'
  242. : 'color: #04c15f'
  243. "
  244. >
  245. {{ ratios.user_duration_compare }}
  246. </van-col>
  247. <van-col span="7" class="td" style="text-align: right">
  248. 收视率:
  249. </van-col>
  250. <van-col span="7" class="td">
  251. {{ formatNum(ratios.watchrate, 2) }}%
  252. </van-col>
  253. <van-col
  254. span="10"
  255. class="td"
  256. :style="
  257. ratios.watchrate_ring > 0 ? 'color: red' : 'color: #04c15f'
  258. "
  259. >
  260. {{ ratios.watchrate_compare }}
  261. </van-col>
  262. <van-col span="7" class="td" style="text-align: right">
  263. 市场占有率:
  264. </van-col>
  265. <van-col span="7" class="td"
  266. >{{ formatNum(ratios.occrate, 2) }}%
  267. </van-col>
  268. <van-col
  269. span="10"
  270. class="td"
  271. :style="
  272. ratios.occrate_ring > 0 ? 'color: red' : 'color: #04c15f'
  273. "
  274. >
  275. {{ ratios.occrate_compare }}
  276. </van-col>
  277. <van-col span="7" class="td" style="text-align: right">
  278. 忠诚度:
  279. </van-col>
  280. <van-col span="7" class="td"
  281. >{{ formatNum(ratios.loyalty, 2) }}%
  282. </van-col>
  283. <van-col
  284. span="10"
  285. class="td"
  286. :style="
  287. ratios.loyalty_ring > 0 ? 'color: red' : 'color: #04c15f'
  288. "
  289. >
  290. {{ ratios.loyalty_compare }}
  291. </van-col>
  292. </van-row>
  293. </van-cell-group>
  294. <div ref="pie"></div>
  295. <div ref="day"></div>
  296. </div>
  297. <div class="bottom content">
  298. 本数据由<span style="color: red"
  299. >“陕西广电融媒体集团大数据平台”</span
  300. >提供。
  301. <p>
  302. 技术支持:
  303. <span style="white-space: nowrap">白帆13325452244 </span>
  304. <span style="white-space: nowrap">陈科18629350958。</span>
  305. </p>
  306. </div>
  307. </van-popup>
  308. </div>
  309. <p
  310. class="content"
  311. :style="
  312. 'font-weight: 700;word-break: normal;text-align: justify; padding: 0.5em 3px;font-size: ' + fontSize + 'px;'
  313. "
  314. v-html="title.dataSource"
  315. ></p>
  316. <div class="bottom content">
  317. 本数据由<span style="color: red">“陕西广电融媒体集团大数据平台”</span
  318. >提供。
  319. <p>
  320. 技术支持:
  321. <span style="white-space: nowrap">白帆13325452244 </span>
  322. <span style="white-space: nowrap">陈科18629350958。</span>
  323. </p>
  324. </div>
  325. </div>
  326. </div>
  327. </template>
  328. <script>
  329. // @ is an alias to /src
  330. import watermark from "watermark-package";
  331. import {
  332. Col as vanCol,
  333. Row as vanRow,
  334. Icon as vanIcon,
  335. Popup as vanPopup,
  336. cellGroup as vanCellGroup,
  337. Cell as vanCell,
  338. Popover as vanPopover,
  339. } from "vant";
  340. import "vant/lib/popover/style/index";
  341. import "vant/lib/cell-group/style/index";
  342. import "vant/lib/cell/style/index";
  343. import "vant/lib/popup/style/index";
  344. import "vant/lib/icon/style/index";
  345. import "vant/lib/col/style/index";
  346. import "vant/lib/row/style/index";
  347. // import {} from "../utils/tool";
  348. import Dayjs from "dayjs";
  349. import { jsonZhou } from "../../../api/index";
  350. import echarts from "../../../utils/echarts";
  351. export default {
  352. name: "tv-list",
  353. data() {
  354. return {
  355. shichang: false,
  356. fene: false,
  357. fontSize: 17,
  358. show: false,
  359. charts: undefined,
  360. ratios: {},
  361. platfromData: [],
  362. color: ["#ff0036", "#ff9b00", "#ffcc00"],
  363. echarts: undefined,
  364. dayEcharts: undefined,
  365. title: {},
  366. width: document.body.offsetWidth || 0,
  367. };
  368. },
  369. watch: {},
  370. mounted() {
  371. if (
  372. this.$route.query.auto !==
  373. "06fd56cdf5a6cfc3a2139cc8514d05aa0439ee8c1fb4d81145bc9647"
  374. )
  375. return;
  376. this.fontSize = (document.body.offsetWidth / 24).toFixed(2) - 0;
  377. if (document.body.offsetWidth > 677) this.fontSize = 22;
  378. watermark.setWaterMark({
  379. w_texts: ["陕西视听大数据"],
  380. w_options: {
  381. w_opacity: "0.1",
  382. },
  383. });
  384. const time = new Date(this.$route.query.date);
  385. let D = new Date(time);
  386. const lasetDay = new Dayjs(D.getTime() - D.getDay() * 86400000);
  387. const firstDay = new Dayjs(lasetDay - 6 * 86400000);
  388. jsonZhou({
  389. start: firstDay.format("YYYYMMDD"),
  390. end: lasetDay.format("YYYYMMDD"),
  391. time: Date.now(),
  392. })
  393. .then(res => {
  394. const title = {
  395. company: res.company || "",
  396. name: res.name || "",
  397. title: res.title || "",
  398. desc: res.desc || "",
  399. dataSource: res.dataSource || ""
  400. };
  401. this.title = title;
  402. this.platfromData = res.list || [];
  403. this.$emit("start", {
  404. status: 200,
  405. });
  406. })
  407. .catch(err => {
  408. this.$emit("start", {
  409. status: err,
  410. });
  411. });
  412. window.onresize = () => {
  413. const doc = document.body;
  414. const width = doc.offsetWidth - 32;
  415. let height = (width / 4) * 3;
  416. this.width = document.body.offsetWidth || 0;
  417. this.dayEcharts &&
  418. this.dayEcharts.resize({
  419. width,
  420. height: width,
  421. });
  422. this.echarts &&
  423. this.echarts.resize({
  424. width,
  425. height,
  426. });
  427. };
  428. },
  429. computed: {},
  430. methods: {
  431. formatType1(num, W) {
  432. let N = this.formatNum(num, W || 0);
  433. if (N >= 100000000) {
  434. N = (N / 100000000).toFixed(W || 0) - 0 + "亿";
  435. } else if (N >= 10000) {
  436. N = (N / 10000).toFixed(W || 0) - 0 + "万";
  437. } else {
  438. N = Number(N).toFixed(W || 0) - 0;
  439. }
  440. return N;
  441. },
  442. formatNum(num, w) {
  443. if (isNaN(num)) return 0;
  444. return Number(num).toFixed(w || 4) - 0;
  445. },
  446. formatType(num, W) {
  447. let N = this.formatNum(num, 2);
  448. let wei = "";
  449. if (N >= 100000000) {
  450. N = (N / 100000000).toFixed(W || 2);
  451. wei = "亿";
  452. } else if (N >= 10000) {
  453. N = (N / 10000).toFixed(W || 2);
  454. wei = "万";
  455. }
  456. N = N.toString().split(".");
  457. return {
  458. N: (N[0] || 0) * 1,
  459. P: N[1] || 0,
  460. wei,
  461. };
  462. },
  463. timeFormat(t, w) {
  464. const Time = t || 0;
  465. let out = Time.toFixed(w || 0) - 0;
  466. return out;
  467. },
  468. showPopup(i) {
  469. this.show = true;
  470. const reaios = JSON.parse(JSON.stringify(this.platfromData[i] || {}));
  471. reaios.hitcount = this.formatType1(reaios.hitcount, 1);
  472. reaios.usrcount = this.formatType1(reaios.usrcount, 1);
  473. reaios.timecount = this.formatType1(reaios.timecount / 60, 0);
  474. this.ratios = reaios;
  475. this.$nextTick(() => {
  476. this.upEcharts();
  477. this.dayEchartsFun();
  478. });
  479. },
  480. dayEchartsFun() {
  481. this.dayEcharts && this.dayEcharts.clear && this.dayEcharts.clear();
  482. if (!this.dayEcharts) {
  483. const doc = document.body;
  484. const width = doc.offsetWidth - 32;
  485. let height = (width / 4) * 3;
  486. if (height > 400) height = 400;
  487. this.dayEcharts = echarts.init(
  488. this.$refs.day,
  489. {},
  490. {
  491. width,
  492. height,
  493. }
  494. );
  495. }
  496. const key = [],
  497. value = [];
  498. this.ratios.detail_list.map(v => {
  499. let val = v.usrcount;
  500. key.push(v.dt);
  501. value.push(val);
  502. });
  503. this.dayEcharts.setOption({
  504. title: {
  505. text: "家庭户收视规模",
  506. subtext: this.ratios.usrcount_compare
  507. ? this.ratios.usrcount_compare + " 单位:户"
  508. : "单位:户",
  509. textStyle: {
  510. fontSize: this.fontSize * 1.05,
  511. },
  512. subtextStyle: {
  513. fontSize: this.fontSize,
  514. },
  515. },
  516. tooltip: {
  517. show: true,
  518. trigger: "axis",
  519. },
  520. xAxis: {
  521. type: "category",
  522. boundaryGap: false,
  523. data: key,
  524. axisLabel: {
  525. interval: 0,
  526. rotate: 60,
  527. },
  528. },
  529. grid: {
  530. right: "5px",
  531. left: "40px",
  532. },
  533. yAxis: {
  534. type: "value",
  535. axisLabel: {
  536. formatter: e => {
  537. const T = this.formatType(e);
  538. let out = T.N;
  539. if (T.P > 0) out += "." + (T.P - 0);
  540. out += T.wei;
  541. return out;
  542. },
  543. },
  544. },
  545. series: [
  546. {
  547. type: "line",
  548. data: value,
  549. },
  550. ],
  551. });
  552. },
  553. upEcharts() {
  554. this.echarts && this.echarts.clear && this.echarts.clear();
  555. if (!this.echarts) {
  556. const doc = document.body;
  557. const width = doc.offsetWidth - 32;
  558. let height = width;
  559. if (height > 667) height = 667;
  560. this.echarts = echarts.init(
  561. this.$refs.pie,
  562. {},
  563. {
  564. width,
  565. height,
  566. }
  567. );
  568. }
  569. this.echarts.setOption({
  570. title: {
  571. text: "观看时长用户分布",
  572. subtext: "单位:%",
  573. textStyle: {
  574. fontSize: this.fontSize * 1.05,
  575. },
  576. },
  577. color: [
  578. "#87cefa",
  579. "#00bfff",
  580. "#1e90ff",
  581. "#0000ff",
  582. "#00008b",
  583. "#191970",
  584. "#000080",
  585. "#0000cd",
  586. "#4169e1",
  587. "#6495ed",
  588. ],
  589. series: [
  590. {
  591. name: "Nightingale Chart",
  592. type: "pie",
  593. radius: [30, 70],
  594. center: ["50%", "50%"],
  595. emphasis: {
  596. //使用emphasis
  597. disable: false,
  598. scale: false, //不缩放
  599. scaleSize: 0, //为了防止失效直接设置未0
  600. },
  601. data: this.ratios.duration_list.map(v => {
  602. let bfb = (v.value * 100).toFixed(0) - 0;
  603. return {
  604. value: bfb,
  605. name: v.range + "\n 占比" + bfb + "%",
  606. };
  607. }),
  608. },
  609. ],
  610. });
  611. },
  612. },
  613. beforeUnmount() {},
  614. components: {
  615. vanCol,
  616. vanRow,
  617. vanIcon,
  618. vanPopup,
  619. vanCell,
  620. vanCellGroup,
  621. vanPopover,
  622. },
  623. };
  624. </script>
  625. <style scoped>
  626. .tv-list {
  627. background-color: #fff;
  628. padding: 5px;
  629. height: 100%;
  630. overflow-y: auto;
  631. box-sizing: border-box;
  632. }
  633. .bottom {
  634. border: 4px solid #0983a8;
  635. background-color: #cdcdcd;
  636. margin-top: 1em;
  637. padding: 10px;
  638. font-size: 0.85rem;
  639. padding-left: 5px;
  640. font-weight: 600;
  641. overflow: hidden;
  642. }
  643. .td {
  644. text-align: center;
  645. line-height: 2.5em;
  646. overflow: hidden;
  647. white-space: nowrap;
  648. text-overflow: ellipsis;
  649. }
  650. .td2 {
  651. line-height: 1.5em;
  652. white-space: initial;
  653. }
  654. .item {
  655. overflow: hidden;
  656. border-radius: 3px;
  657. margin-top: 11px;
  658. background-color: #f5f6f8;
  659. }
  660. .itemHead {
  661. margin-top: 0;
  662. background-color: #f5f6f8;
  663. }
  664. .main {
  665. padding: 0.5em;
  666. }
  667. .content {
  668. margin: 0 auto;
  669. max-width: 667px;
  670. }
  671. .rise {
  672. /* 上升 */
  673. transform: rotate(180deg);
  674. }
  675. .titleTop {
  676. padding: 1em 0;
  677. font-weight: 600;
  678. background-image: linear-gradient(to right, #014392, #008fc4, #00428c);
  679. color: #fff;
  680. text-align: center;
  681. }
  682. </style>
  683. <style>
  684. .van-cell-group__title {
  685. font-size: 1.1rem;
  686. padding-left: 8px;
  687. color: #000;
  688. font-weight: 600;
  689. }
  690. </style>