index.vue 16 KB

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