index.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <div class="yukang">
  3. <van-cell-group>
  4. <van-cell :title="'直播时间:' + base.live_time" />
  5. </van-cell-group>
  6. <div class="mainBody" style="padding-bottom: 50px">
  7. <div>
  8. <van-row>
  9. <van-col span="12" class="van-hairline--right">
  10. <div class="title">
  11. 性别
  12. </div>
  13. <canvas
  14. ref="chart"
  15. :width="canvasRegion.width / 2"
  16. :height="canvasRegion.height"
  17. ></canvas>
  18. </van-col>
  19. <van-col span="12">
  20. <div class="title">
  21. 年龄
  22. </div>
  23. <canvas
  24. ref="chartage"
  25. :width="canvasRegion.width / 2"
  26. :height="canvasRegion.height"
  27. ></canvas>
  28. </van-col>
  29. </van-row>
  30. <b-canvas
  31. keyName="value"
  32. :transposed="true"
  33. :height="300"
  34. :legend="true"
  35. :list="platformSort"
  36. ></b-canvas>
  37. </div>
  38. <!-- 实时走势 -->
  39. <c-canvas
  40. v-if="BulletChat.peopleList.length"
  41. :showListBtn="true"
  42. :list="BulletChat.peopleList"
  43. ></c-canvas>
  44. <c-canvas
  45. v-if="ScreenMan.peopleList.length"
  46. :list="ScreenMan.peopleList"
  47. :showListBtn="true"
  48. ></c-canvas>
  49. <c-canvas
  50. v-if="flow.peopleList.length"
  51. :showListBtn="true"
  52. :list="flow.peopleList"
  53. ></c-canvas>
  54. </div>
  55. </div>
  56. </template>
  57. <script>
  58. import cCanvas from "@/components/chart";
  59. import bCanvas from "@/components/bChart";
  60. import { getlive } from "@/api/getList.js";
  61. import { Col as vanCol, Row as vanRow, Cell as vanCell, CellGroup as vanCellGroup } from "vant";
  62. import "vant/lib/cell/style";
  63. import "vant/lib/cell-group/style";
  64. import "vant/lib/col/style";
  65. import "vant/lib/row/style";
  66. import F2 from "@antv/f2";
  67. export default {
  68. name: "App",
  69. components: {
  70. vanCellGroup,
  71. vanCell,
  72. cCanvas,
  73. bCanvas,
  74. vanCol,
  75. vanRow,
  76. },
  77. data() {
  78. return {
  79. canvasRegion: {
  80. width: 0,
  81. height: 0,
  82. },
  83. base: {},
  84. platformSort: [],
  85. BulletChat: { peopleList: [] },
  86. flow: { peopleList: [] },
  87. ScreenMan: { peopleList: [] },
  88. };
  89. },
  90. mounted() {
  91. let w = document.body.clientWidth || 0;
  92. let h = document.body.clientHeight / 3;
  93. this.canvasRegion = {
  94. width: w > 1200 ? 1200 : w,
  95. height: h,
  96. };
  97. },
  98. created() {
  99. let q = this.$route.query;
  100. getlive({
  101. topic: q.title,
  102. platform: q.platform,
  103. }).then(res => {
  104. let oriData = res || {};
  105. let trend = oriData.trend || {};
  106. this.base = {
  107. live_time: oriData.detail ? oriData.detail.time || "" : ""
  108. };
  109. let gender = [];
  110. let oriGender = oriData.fans.gender || [];
  111. for (let i = 0; i < oriGender.length; i++) {
  112. const v = oriGender[i];
  113. gender.push({
  114. name: v.gender,
  115. percent: v.rate.replace("%", "") * 1,
  116. a: "1",
  117. });
  118. }
  119. let age = [];
  120. let oriAge = oriData.fans.age || [];
  121. for (let i = 0; i < oriAge.length; i++) {
  122. const v = oriAge[i];
  123. age.push({
  124. name: v.item,
  125. percent: v.percent * 100,
  126. a: "1",
  127. });
  128. }
  129. this.pie(gender, "chart");
  130. this.pie(age, "chartage");
  131. let cityList = [];
  132. let oriCity = oriData.fans.area["全部"] || [];
  133. oriCity.map(v => {
  134. cityList.push({
  135. nickname: v.Name.replace("市", ""),
  136. value: v.Ratio.toFixed(2) - 0,
  137. });
  138. });
  139. this.platformSort = cityList;
  140. let flow = {
  141. title: "实时流量",
  142. subTitle: "",
  143. id: "id" + 10,
  144. canvasId: "canvasId" + 10,
  145. type: "line",
  146. yType: "value",
  147. xType: "time",
  148. peopleList: [],
  149. };
  150. let BulletChat = {
  151. title: "累计粉丝量",
  152. subTitle: "",
  153. id: "id" + 12,
  154. canvasId: "canvasId" + 12,
  155. type: "line",
  156. yType: "value",
  157. xType: "time",
  158. peopleList: [],
  159. };
  160. let ScreenMan = {
  161. title: "点赞走势",
  162. subTitle: "",
  163. id: "id" + 13,
  164. canvasId: "canvasId" + 13,
  165. type: "line",
  166. yType: "value",
  167. xType: "time",
  168. peopleList: [],
  169. };
  170. // 实时流量
  171. flow.subTitle =
  172. "在线人数峰值:" +
  173. ((trend.user || {}).user_count || 0) +
  174. " 出现时间:" +
  175. ((trend.user || {}).crawl_date || "") +
  176. " 平均人数:" +
  177. ((trend.user || {}).avg_user_count || 0);
  178. // 累计粉丝量
  179. BulletChat.subTitle =
  180. "粉丝峰值:" +
  181. ((trend.fans || {}).club_info_total_fans_count || 0) +
  182. " 出现在:" +
  183. ((trend.fans || {}).crawl_date || "");
  184. // 点赞走势
  185. ScreenMan.subTitle =
  186. "点赞峰值:" +
  187. ((trend.like || {}).add_like_count || 0) +
  188. " 出现在:" +
  189. ((trend.like || {}).crawl_date || "");
  190. // 趋势图数据
  191. for (let i = 0; i < (oriData.detail.watch || []).length; i++) {
  192. const v = (oriData.detail.watch || [])[i];
  193. let time = this.formatTime(v.x);
  194. flow.peopleList.push({
  195. value: v.watch || 0,
  196. type: "实时流量",
  197. date: time,
  198. });
  199. BulletChat.peopleList.push({
  200. value: v.bsc || 0,
  201. type: "弹幕数",
  202. date: time,
  203. });
  204. ScreenMan.peopleList.push({
  205. value: v.bsuc || 0,
  206. type: "弹幕人数",
  207. date: time,
  208. });
  209. }
  210. this.BulletChat = BulletChat;
  211. this.flow = flow;
  212. this.ScreenMan = ScreenMan;
  213. });
  214. },
  215. computed: {},
  216. methods: {
  217. pie(gender, ele) {
  218. const chart = new F2.Chart({
  219. el: this.$refs[ele],
  220. pixelRatio: window.devicePixelRatio,
  221. });
  222. chart.source(gender, {
  223. percent: {
  224. formatter: function formatter(val) {
  225. return val * 100 + "%";
  226. },
  227. },
  228. });
  229. chart.legend({
  230. position: "right",
  231. itemFormatter: function itemFormatter(val) {
  232. return val;
  233. },
  234. });
  235. chart.tooltip(false);
  236. chart.coord("polar", {
  237. transposed: true,
  238. radius: 0.85,
  239. });
  240. chart.axis(false);
  241. chart
  242. .interval()
  243. .position("a*percent")
  244. .color("name", [
  245. "#1890FF",
  246. "#13C2C2",
  247. "#2FC25B",
  248. "#FACC14",
  249. "#F04864",
  250. "#8543E0",
  251. ])
  252. .adjust("stack")
  253. .style({
  254. lineWidth: 1,
  255. stroke: "#fff",
  256. lineJoin: "round",
  257. lineCap: "round",
  258. })
  259. .animate({
  260. appear: {
  261. duration: 1200,
  262. easing: "bounceOut",
  263. },
  264. });
  265. chart.render();
  266. },
  267. formatTime(time) {
  268. let t = new Date(time);
  269. let hour = t.getHours();
  270. let min = t.getMinutes();
  271. let sec = t.getSeconds();
  272. hour = hour > 9 ? hour : '0' + hour;
  273. min = min > 9 ? min : '0' + min;
  274. sec = sec > 9 ? sec : '0' + sec;
  275. return hour + ":" + min + ":" + sec;
  276. },
  277. },
  278. };
  279. </script>
  280. <style lang="scss" scoped>
  281. .yukang {
  282. font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Helvetica Neue",
  283. Helvetica, Segoe UI, Arial, Roboto, "PingFang SC", "miui",
  284. "Hiragino Sans GB", "Microsoft Yahei", sans-serif;
  285. color: #2c3e50;
  286. font-weight: 400;
  287. .title {
  288. width: 100%;
  289. padding: 10px 16px;
  290. box-sizing: border-box;
  291. overflow: hidden;
  292. color: #323233;
  293. font-size: 14px;
  294. line-height: 24px;
  295. background-color: #fff;
  296. }
  297. .userType {
  298. position: relative;
  299. .textGroup {
  300. z-index: 1;
  301. position: absolute;
  302. overflow: hidden;
  303. top: 15px;
  304. right: 10px;
  305. font-size: 0;
  306. color: #1989fa;
  307. &::after {
  308. border-radius: 3px;
  309. border-color: #1989fa;
  310. }
  311. .text {
  312. padding: 0 3px;
  313. display: inline-block;
  314. text-align: center;
  315. cursor: pointer;
  316. font-size: 14px;
  317. }
  318. .act {
  319. background-color: #1989fa;
  320. color: #fff;
  321. }
  322. }
  323. }
  324. .title{
  325. color: #323233;
  326. font-size: 14px;
  327. }
  328. }
  329. </style>