liyongli 1 an în urmă
părinte
comite
b1375362b8
3 a modificat fișierele cu 514 adăugiri și 19 ștergeri
  1. 6 0
      src/router/index.js
  2. 458 0
      src/views/Jugou/Jugouout.vue
  3. 50 19
      webpack.dll.js

+ 6 - 0
src/router/index.js

@@ -55,6 +55,12 @@ const routes = [
     component: () =>
       import(/* webpackChunkName: "jugou" */ "../views/Jugou/Jugou.vue"),
   },
+  {
+    path: "/jugouout",
+    name: "jugouout",
+    component: () =>
+      import(/* webpackChunkName: "jugouout" */ "../views/Jugou/Jugouout.vue"),
+  },
   {
     path: "/radio",
     name: "Radio",

+ 458 - 0
src/views/Jugou/Jugouout.vue

@@ -0,0 +1,458 @@
+<template>
+  <div class="Jugou">
+    <el-loading></el-loading>
+    <el-card>
+      <div style="padding: 0 100px">
+        <div style="position: relative">
+          <video
+            controls
+            autoplay
+            ref="video"
+            @timeupdate="timeupdate"
+            @error="videoerror"
+            @canplay="videoload"
+            :src="videoUrl"
+          />
+          <img
+            v-show="videoerrorStart"
+            class="videoerror"
+            src="../../assets/img/videoerror.png"
+          />
+        </div>
+        <div style="position: relative">
+          <div
+            class="chart"
+            ref="chart"
+            style="width: 100%; min-height: 300px"
+          ></div>
+          <div class="lineinfobackground" :style="'left:' + leftNum + 'px'">
+            <div style="position: relative; width: 100%; height: 100%">
+              <div class="line"></div>
+              <el-row style="padding: 10px 0 0 20px">
+                <el-col :span="6">
+                  <span class="icon" style="background-color: #e05c5c"></span>
+                  流入
+                </el-col>
+                <el-col :span="6">
+                  <span class="icon" style="background-color: #6ab581"></span>
+                  流出
+                </el-col>
+                <el-col :span="12">
+                  <span class="iconLine"></span>
+                  收视率%
+                  <div style="float: right; padding: 0 5px 0 0">
+                    {{ tof(nowItem.audienceRating, 4) }}%
+                  </div>
+                </el-col>
+              </el-row>
+              <div style="padding: 5px 20px">
+                当前时间:{{
+                  nowItem.date ? nowItem.date.split(' ')[1] || '' : ''
+                }}
+                <div style="float: right">
+                  人数: {{ formateNum(nowItem.uv) }}
+                </div>
+              </div>
+              <el-row>
+                <el-col :span="12">
+                  <div style="padding: 0 20px">
+                    流入排行
+                    <div>
+                      <div
+                        style="font-size: 12px; line-height: 22px"
+                        v-for="(item, i) in left"
+                        :key="i"
+                        v-text="item"
+                      ></div>
+                    </div>
+                  </div>
+                </el-col>
+                <el-col :span="12">
+                  <div style="padding: 0 20px">
+                    流出排行
+                    <div>
+                      <div
+                        style="font-size: 12px; line-height: 22px"
+                        v-for="(item, i) in right"
+                        :key="i"
+                        v-text="item"
+                      ></div>
+                    </div>
+                  </div>
+                </el-col>
+              </el-row>
+            </div>
+          </div>
+        </div>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+// @ is an alias to /src
+import { defaultAjax } from '@/api/index';
+import config from '@/config/index';
+
+import { markRaw } from 'vue';
+const ElLoading = require('element-plus/lib/el-loading/index');
+import 'element-plus/lib/theme-chalk/el-loading.css';
+
+import * as echarts from 'echarts';
+
+let sec = 0,
+  timeout = undefined,
+  isplay = false,
+  isClick = false,
+  stepNum = 6.8,
+  page = 0;
+export default {
+  name: 'Channel',
+  data() {
+    return {
+      videoerrorStart: false,
+      leftNum: 50,
+      videoUrl: '',
+      myChart: undefined,
+      orgLi: [],
+      nowItem: {},
+      left: [],
+      right: [],
+      load: undefined,
+    };
+  },
+  mounted() {
+    this.list = [
+      {
+        channelId: 1,
+        channelName: '陕西卫视',
+        videoUrl: '/video/20230814/1.mp4',
+        dataUrl:
+          'https://smcic-bigdata.oss-cn-chengdu.aliyuncs.com/live-flow/channel/20230814/channel-1.json',
+        dt: '2023-08-14',
+        channelStatus: 0,
+        isDefault: 1,
+      },
+    ];
+    this.getData();
+  },
+  computed: {},
+  methods: {
+    getData() {
+      if (!this.load) this.load = ElLoading.default.service();
+      let item = this.list[0];
+      this.videoUrl = config.base.Intranet + '/minio' + item.videoUrl;
+      defaultAjax({
+        url: item.dataUrl,
+      })
+        .then(res => {
+          this.load.close();
+          let org = res || {},
+            li = [];
+          Object.keys(org).map(v => {
+            org[v].date = v;
+            li.push(org[v]);
+          });
+          if (!li.length) return;
+          this.orgLi = li;
+          this.nowItem = li[0];
+          this.left = li[0].lrTop || [];
+          this.right = li[0].lcTop || [];
+          return this.chart();
+        })
+        .catch(() => {
+          this.load.close();
+        });
+    },
+    tof(num, t) {
+      return Number(num * 100).toFixed(t || 2);
+    },
+    chart() {
+      if (!this.myChart) {
+        this.myChart = markRaw(echarts.init(this.$refs.chart));
+        this.myChart.resize({
+          height: 300,
+        });
+        this.myChart.on('datazoom', () => {
+          if (isClick) return;
+          isClick = true;
+          let funisplay = !this.$refs.video.paused;
+          if (timeout) clearTimeout(timeout), (timeout = undefined);
+          this.$refs.video.pause();
+          this.leftNum = 50;
+          timeout = setTimeout(() => {
+            clearTimeout(timeout);
+            timeout = undefined;
+            isClick = false;
+            //  拖拽后的事件
+            isplay = funisplay;
+            this.leftNum = 50;
+            this.$refs.video.currentTime =
+              this.myChart.getOption().dataZoom[0].startValue;
+            if (isplay) this.$refs.video.play();
+            else this.$refs.video.pause();
+          }, 200);
+        });
+      }
+      let timeAll = [],
+        Irdata = [],
+        Icdata = [],
+        audienceRating = [];
+      this.orgLi.map(v => {
+        v.date && timeAll.push(v.date.split(' ')[1] || '');
+        Icdata.push(-1 * v.lc);
+        Irdata.push(v.lr);
+        audienceRating.push(v.audienceRating * 100);
+      });
+      this.myChart.setOption({
+        dataZoom: [
+          {
+            maxSpan: 10,
+            minSpan: 5,
+            type: 'slider',
+            brushSelect: false,
+            // zoomLock: false,
+            show: true,
+            realtime: true,
+            start: stepNum * page,
+            end: stepNum * (page + 1),
+            zoomOnMouseWheel: false,
+            height: '30',
+            top: '85%',
+            handleIcon:
+              'path://M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
+            handleSize: 15,
+            textStyle: {
+              color: '#c5c6cc',
+            },
+            dataBackground: {
+              lineStyle: {
+                color: '#fff',
+              },
+              areaStyle: {
+                color: '#8b51a8',
+              },
+            },
+          },
+        ],
+        xAxis: {
+          data: timeAll,
+          position: 'top',
+          silent: false,
+          axisLabel: {
+            interval: 'auto',
+            color: '#000',
+            rotate: '-90',
+          },
+        },
+        yAxis: [
+          {
+            scale: false,
+            nameGap: 6,
+            inverse: false,
+            name: '流入流出',
+            nameLocation: 'start',
+            splitArea: {
+              show: false,
+            },
+            splitLine: {
+              show: false,
+            },
+            axisLabel: {
+              color: '#000',
+              formatter: function (value) {
+                let v = value;
+                if (v < 0) v *= -1;
+                return v;
+              },
+            },
+            axisTick: {
+              show: false,
+            },
+            axisLine: {
+              show: false,
+            },
+            nameTextStyle: {
+              color: '#000',
+            },
+          },
+          {
+            scale: true,
+            nameGap: 6,
+            type: 'value',
+            name: '收视率%',
+            nameLocation: 'start',
+            splitLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+            axisLine: {
+              show: false,
+            },
+            axisLabel: {
+              color: '#000',
+            },
+            nameTextStyle: {
+              color: '#000',
+            },
+          },
+        ],
+        grid: {
+          left: 50,
+          right: 50,
+        },
+        series: [
+          {
+            name: '流入',
+            type: 'bar',
+            yAxisIndex: 0,
+            stack: 'one',
+            data: Irdata,
+            sampling: 'lttb',
+            emphasis: {
+              focus: 'series',
+            },
+            itemStyle: {
+              color: '#df5a5a',
+            },
+          },
+          {
+            name: '流出',
+            type: 'bar',
+            yAxisIndex: 0,
+            sampling: 'lttb',
+            stack: 'one',
+            data: Icdata,
+            emphasis: {
+              focus: 'series',
+            },
+            itemStyle: {
+              color: '#6ab581',
+            },
+          },
+          {
+            name: '收视率%',
+            type: 'line',
+            yAxisIndex: 1,
+            smooth: true,
+            showSymbol: false,
+            data: audienceRating,
+            lineStyle: {
+              width: 1,
+              color: '#50abfd',
+            },
+          },
+        ],
+      });
+    },
+    timeupdate(v) {
+      if (sec === Math.floor(v.srcElement.currentTime)) return;
+      sec = Math.floor(v.srcElement.currentTime);
+      let width = this.$refs.chart.offsetWidth - 100;
+      let item = this.orgLi[sec] || {};
+      let s = this.myChart.getOption().dataZoom[0].startValue,
+        e = this.myChart.getOption().dataZoom[0].endValue;
+      let iW = width / (e - s),
+        cheng = sec - s < 0 ? 0 : sec - s;
+      let step = iW * cheng > width ? 0 : iW * cheng;
+      if (!item.lrTop) return;
+      this.nowItem = item;
+      this.left = item.lrTop || [];
+      this.right = item.lcTop || [];
+      this.leftNum = 50 + step;
+      if (iW * cheng <= width) return;
+      page++;
+      this.myChart.setOption({
+        dataZoom: {
+          start: stepNum * page,
+          end: stepNum * (page + 1),
+        },
+      });
+    },
+    videoerror() {
+      this.videoerrorStart = true;
+    },
+    videoload() {
+      this.videoerrorStart = false;
+    },
+    formateNum(n) {
+      let num = n;
+      if (isNaN(n)) num = '0';
+      else if (n >= 100000000)
+        num =
+          ((n / 100000000).toFixed(2) - 0 + '').replace(
+            /\B(?=(?:\d{3})+\b)/g,
+            ','
+          ) + '亿';
+      else if (n >= 10000)
+        num =
+          ((n / 10000).toFixed(2) - 0 + '').replace(
+            /\B(?=(?:\d{3})+\b)/g,
+            ','
+          ) + '万';
+      else num = (num + '').replace(/\B(?=(?:\d{3})+\b)/g, ',');
+      return num;
+    },
+  },
+  components: {},
+};
+</script>
+
+<style>
+.Jugou {
+  min-width: 1149px;
+  padding: 10px 12px;
+}
+
+.Jugou video {
+  width: 100%;
+  height: 500px;
+  background-color: #000;
+}
+.Jugou .lineinfobackground {
+  font-size: 12px;
+  border-radius: 9px;
+  position: absolute;
+  width: 345px;
+  height: 200px;
+  top: 30px;
+  left: 50px;
+  background: rgba(0, 0, 0, 0.5);
+  transform: translateX(-50%);
+  color: #fff;
+  /* opacity: 0.5; */
+}
+.Jugou .lineinfobackground .line {
+  position: absolute;
+  width: 2px;
+  height: 120%;
+  margin-top: -5%;
+  margin-left: 50%;
+  background-color: #888;
+}
+.Jugou .lineinfobackground .icon {
+  display: inline-block;
+  width: 30px;
+  height: 10px;
+  border-radius: 10px;
+}
+.Jugou .lineinfobackground .iconLine {
+  background-color: #50abfd;
+  display: inline-block;
+  width: 30px;
+  height: 2px;
+  vertical-align: middle;
+  border-radius: 10px;
+}
+.Jugou .videoerror {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+video::-webkit-media-controls-timeline {
+  display: none;
+}
+</style>

+ 50 - 19
webpack.dll.js

@@ -1,27 +1,27 @@
-const path = require("path");
-const webpack = require("webpack");
-const terserWebpackPlugin = require("terser-webpack-plugin");
+const path = require('path');
+const webpack = require('webpack');
+const terserWebpackPlugin = require('terser-webpack-plugin');
 
-const { CleanWebpackPlugin } = require("clean-webpack-plugin");
+const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 
 module.exports = {
-  mode: "production",
+  mode: 'production',
   entry: {
     vue: [
-      "axios",
-      "core-js",
-      "echarts",
-      "echarts-wordcloud",
-      "element-plus",
-      "js-sha256",
-      "vue",
-      "vue-router",
+      'axios',
+      'core-js',
+      'echarts',
+      'echarts-wordcloud',
+      'element-plus',
+      'js-sha256',
+      'vue',
+      'vue-router',
     ],
   },
   output: {
-    path: path.resolve(__dirname, "dll"),
-    filename: "dll_[name].js",
-    library: "dll_[name]",
+    path: path.resolve(__dirname, 'dll'),
+    filename: 'dll_[name].js',
+    library: 'dll_[name]',
   },
   optimization: {
     minimizer: [
@@ -32,11 +32,42 @@ module.exports = {
   },
   plugins: [
     new CleanWebpackPlugin({
-      path: path.join(__dirname, "./dll"),
+      path: path.join(__dirname, './dll'),
     }),
     new webpack.DllPlugin({
-      name: "dll+[name]",
-      path: path.resolve(__dirname, "./dll/[name].manifest.json"),
+      name: 'dll+[name]',
+      path: path.resolve(__dirname, './dll/[name].manifest.json'),
     }),
   ],
 };
+
+const a = [
+  {
+    value: 'zhinan',
+    label: '指南',
+    children: [
+      {
+        value: 'shejiyuanze',
+        label: '设计原则',
+        children: [
+          {
+            value: 'yizhi',
+            label: '一致',
+          },
+          {
+            value: 'fankui',
+            label: '反馈',
+          },
+          {
+            value: 'xiaolv',
+            label: '效率',
+          },
+          {
+            value: 'kekong',
+            label: '可控',
+          },
+        ],
+      }
+    ],
+  }
+];