瀏覽代碼

添加直播间列表

lex 3 年之前
父節點
當前提交
802502bb73

+ 143 - 1
package-lock.json

@@ -20,6 +20,7 @@
         "js-storage": "^1.1.0",
         "lodash": "^4.17.21",
         "moment": "^2.29.1",
+        "plyr": "^3.7.2",
         "qs": "^6.8.0",
         "vant": "^2.12.21",
         "vconsole": "^3.3.4",
@@ -4298,6 +4299,11 @@
       "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=",
       "dev": true
     },
+    "node_modules/custom-event-polyfill": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
+      "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w=="
+    },
     "node_modules/cyclist": {
       "version": "0.2.2",
       "resolved": "https://registry.npm.taobao.org/cyclist/download/cyclist-0.2.2.tgz",
@@ -6144,7 +6150,71 @@
       "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.9.tgz",
       "integrity": "sha1-P17WZYPM1vQAtaANtvfoYTY+OI8=",
       "bundleDependencies": [
-        "node-pre-gyp"
+        "node-pre-gyp",
+        "abbrev",
+        "ansi-regex",
+        "aproba",
+        "are-we-there-yet",
+        "balanced-match",
+        "brace-expansion",
+        "chownr",
+        "code-point-at",
+        "concat-map",
+        "console-control-strings",
+        "core-util-is",
+        "debug",
+        "deep-extend",
+        "delegates",
+        "detect-libc",
+        "fs-minipass",
+        "fs.realpath",
+        "gauge",
+        "glob",
+        "has-unicode",
+        "iconv-lite",
+        "ignore-walk",
+        "inflight",
+        "inherits",
+        "ini",
+        "is-fullwidth-code-point",
+        "isarray",
+        "minimatch",
+        "minimist",
+        "minipass",
+        "minizlib",
+        "mkdirp",
+        "ms",
+        "needle",
+        "nopt",
+        "npm-bundled",
+        "npm-packlist",
+        "npmlog",
+        "number-is-nan",
+        "object-assign",
+        "once",
+        "os-homedir",
+        "os-tmpdir",
+        "osenv",
+        "path-is-absolute",
+        "process-nextick-args",
+        "rc",
+        "readable-stream",
+        "rimraf",
+        "safe-buffer",
+        "safer-buffer",
+        "sax",
+        "semver",
+        "set-blocking",
+        "signal-exit",
+        "string_decoder",
+        "string-width",
+        "strip-ansi",
+        "strip-json-comments",
+        "tar",
+        "util-deprecate",
+        "wide-align",
+        "wrappy",
+        "yallist"
       ],
       "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
       "dev": true,
@@ -8570,6 +8640,11 @@
         "json5": "lib/cli.js"
       }
     },
+    "node_modules/loadjs": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/loadjs/-/loadjs-4.2.0.tgz",
+      "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA=="
+    },
     "node_modules/locate-path": {
       "version": "2.0.0",
       "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz",
@@ -10011,6 +10086,24 @@
         "node": ">=4"
       }
     },
+    "node_modules/plyr": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmmirror.com/plyr/-/plyr-3.7.2.tgz",
+      "integrity": "sha512-I0ZC/OI4oJ0iWG9s2rrnO0YFO6aLyrPiQBq9kum0FqITYljwTPBbYL3TZZu8UJQJUq7tUWN18Q7ACwNCkGKABQ==",
+      "dependencies": {
+        "core-js": "^3.22.0",
+        "custom-event-polyfill": "^1.0.7",
+        "loadjs": "^4.2.0",
+        "rangetouch": "^2.0.1",
+        "url-polyfill": "^1.1.12"
+      }
+    },
+    "node_modules/plyr/node_modules/core-js": {
+      "version": "3.23.1",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.23.1.tgz",
+      "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w==",
+      "hasInstallScript": true
+    },
     "node_modules/portfinder": {
       "version": "1.0.21",
       "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.21.tgz",
@@ -10944,6 +11037,11 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/rangetouch": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz",
+      "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA=="
+    },
     "node_modules/raw-body": {
       "version": "2.4.0",
       "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz",
@@ -13222,6 +13320,11 @@
         "requires-port": "^1.0.0"
       }
     },
+    "node_modules/url-polyfill": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmmirror.com/url-polyfill/-/url-polyfill-1.1.12.tgz",
+      "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A=="
+    },
     "node_modules/url/node_modules/punycode": {
       "version": "1.3.2",
       "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz",
@@ -17986,6 +18089,11 @@
       "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=",
       "dev": true
     },
+    "custom-event-polyfill": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
+      "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w=="
+    },
     "cyclist": {
       "version": "0.2.2",
       "resolved": "https://registry.npm.taobao.org/cyclist/download/cyclist-0.2.2.tgz",
@@ -21466,6 +21574,11 @@
         }
       }
     },
+    "loadjs": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/loadjs/-/loadjs-4.2.0.tgz",
+      "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA=="
+    },
     "locate-path": {
       "version": "2.0.0",
       "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz",
@@ -22647,6 +22760,25 @@
       "dev": true,
       "optional": true
     },
+    "plyr": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmmirror.com/plyr/-/plyr-3.7.2.tgz",
+      "integrity": "sha512-I0ZC/OI4oJ0iWG9s2rrnO0YFO6aLyrPiQBq9kum0FqITYljwTPBbYL3TZZu8UJQJUq7tUWN18Q7ACwNCkGKABQ==",
+      "requires": {
+        "core-js": "^3.22.0",
+        "custom-event-polyfill": "^1.0.7",
+        "loadjs": "^4.2.0",
+        "rangetouch": "^2.0.1",
+        "url-polyfill": "^1.1.12"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "3.23.1",
+          "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.23.1.tgz",
+          "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w=="
+        }
+      }
+    },
     "portfinder": {
       "version": "1.0.21",
       "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.21.tgz",
@@ -23418,6 +23550,11 @@
       "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=",
       "dev": true
     },
+    "rangetouch": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz",
+      "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA=="
+    },
     "raw-body": {
       "version": "2.4.0",
       "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz",
@@ -25355,6 +25492,11 @@
         "requires-port": "^1.0.0"
       }
     },
+    "url-polyfill": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmmirror.com/url-polyfill/-/url-polyfill-1.1.12.tgz",
+      "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A=="
+    },
     "use": {
       "version": "3.1.1",
       "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz",

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "js-storage": "^1.1.0",
     "lodash": "^4.17.21",
     "moment": "^2.29.1",
+    "plyr": "^3.7.2",
     "qs": "^6.8.0",
     "vant": "^2.12.21",
     "vconsole": "^3.3.4",

+ 97 - 0
src/components/video.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="video-container">
+    <video
+      ref="video"
+      :src="src"
+      :class="className"
+      :preload="preload"
+      :poster="poster"
+      :style="styleValue"
+    />
+  </div>
+</template>
+<script>
+import Plyr from "plyr";
+import "plyr/dist/plyr.css";
+import { browser } from "@/common/common";
+export default {
+  name: "video-player",
+  props: {
+    setting: {
+      type: Object,
+      default: () => {},
+    },
+    className: String,
+    styleValue: String,
+    src: String,
+    poster: String,
+    controls: Boolean,
+    height: String,
+    fullscreen: Boolean,
+    preload: {
+      type: String,
+      default: "auto",
+    },
+    currentTime: {
+      type: Boolean,
+      default: true,
+    },
+    playLarge: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  data() {
+    return {
+      player: null,
+    };
+  },
+  mounted() {
+    this.init();
+  },
+  updated() {
+    this.init();
+  },
+  methods: {
+    init() {
+      let controls = ["play", "progress", "captions"];
+      if (this.playLarge) {
+        controls.push("play-large");
+      }
+      console.log(this.currentTime, "1212");
+      if (this.currentTime) {
+        controls.push("current-time");
+      }
+      if (browser().android || this.fullscreen) {
+        controls.push("fullscreen");
+      }
+      this.player = new Plyr(this.$refs.video, {
+        controls: controls,
+        ...this.setting,
+      });
+      this.player.elements.container
+        ? (this.player.elements.container.style.height = this.height || "2rem")
+        : null;
+
+      this.player.on("play", () => {
+        this.$emit("play");
+      });
+    },
+    onpause() {
+      this.player.pause();
+    },
+  },
+  beforeDestroy() {
+    // this.player.destroy();
+    this.player.pause();
+    this.player.src = "";
+    this.player.restart();
+    // window.stop();
+  },
+};
+</script>
+<style lang="less" scoped>
+.video-container {
+  --plyr-color-main: #01c1b5;
+}
+</style>

+ 196 - 127
src/router/teacherRouter.js

@@ -6,8 +6,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'CallNames'*/ "@/views/teacher/CallNames.vue"),
     meta: {
       descrition: "点名",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/attendance",
@@ -18,8 +18,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "历史考勤统计",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/bookingset",
@@ -30,8 +30,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "试听课设置",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/teachingschool",
@@ -42,8 +42,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "教学点设置",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/teachingset",
@@ -54,8 +54,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "教学点设置",
-      weight: 2 // 页面权重
-    }
+      weight: 2, // 页面权重
+    },
   },
   {
     path: "/business",
@@ -64,8 +64,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'Business'*/ "@/views/teacher/Business.vue"),
     meta: {
       descrition: "业务",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/approval",
@@ -74,8 +74,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'Approval'*/ "@/views/teacher/Approval.vue"),
     meta: {
       descrition: "需我审批",
-      weight: 2 // 页面权重
-    }
+      weight: 2, // 页面权重
+    },
   },
   {
     path: "/ccme",
@@ -84,8 +84,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'CcMe'*/ "@/views/teacher/CcMe.vue"),
     meta: {
       descrition: "抄送我的",
-      weight: 3 // 页面权重
-    }
+      weight: 3, // 页面权重
+    },
   },
   {
     path: "/istarted",
@@ -94,8 +94,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'IStarted'*/ "@/views/teacher/IStarted.vue"),
     meta: {
       descrition: "我发起的",
-      weight: 4 // 页面权重
-    }
+      weight: 4, // 页面权重
+    },
   },
   {
     path: "/starteddetail",
@@ -106,8 +106,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "我发起的",
-      weight: 5 // 页面权重
-    }
+      weight: 5, // 页面权重
+    },
   },
   {
     path: "/periodadjust",
@@ -118,8 +118,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "课程调整",
-      weight: 6 // 页面权重
-    }
+      weight: 6, // 页面权重
+    },
   },
   {
     path: "/periodchange",
@@ -130,8 +130,8 @@ let teacherRouter = [
       ),
     meta: {
       descrition: "课时交换",
-      weight: 7 // 页面权重
-    }
+      weight: 7, // 页面权重
+    },
   },
   {
     path: "/leave",
@@ -140,8 +140,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'Leave'*/ "@/views/teacher/Leave.vue"),
     meta: {
       descrition: "请假",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/vipapply",
@@ -150,8 +150,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'VIPApply'*/ "@/views/teacher/VIPApply.vue"),
     meta: {
       descrition: "VIP课程班申请",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/order",
@@ -160,8 +160,8 @@ let teacherRouter = [
       import(/* webpackChunkName:'order'*/ "@/views/teacher/order.vue"),
     meta: {
       descrition: "订单列表",
-      weight: 1 // 页面权重
-    }
+      weight: 1, // 页面权重
+    },
   },
   {
     path: "/privacy",
@@ -170,8 +170,8 @@ let teacherRouter = [
       import(/* webpackChunkName: "privacy" */ "@/views/teacher/privacy"),
     meta: {
       descrition: "隐私协议",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/studyReport",
@@ -180,28 +180,32 @@ let teacherRouter = [
       import(/* webpackChunkName: "privacy" */ "@/views/teacher/studyReport"),
     meta: {
       descrition: "学习报告",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/studyReportNew",
     name: "studyReportNew",
     component: () =>
-      import(/* webpackChunkName: "privacy" */ "@/views/teacher/studyReportNew"),
+      import(
+        /* webpackChunkName: "privacy" */ "@/views/teacher/studyReportNew"
+      ),
     meta: {
       descrition: "学习报告",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/reportDetailNew",
     name: "reportDetailNew",
     component: () =>
-      import(/* webpackChunkName: "privacy" */ "@/views/teacher/reportDetailNew"),
+      import(
+        /* webpackChunkName: "privacy" */ "@/views/teacher/reportDetailNew"
+      ),
     meta: {
       descrition: "学习报告",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/reportDetail",
@@ -210,8 +214,8 @@ let teacherRouter = [
       import(/* webpackChunkName: "privacy" */ "@/views/teacher/reportDetail"),
     meta: {
       descrition: "学习报告",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/tobeReport",
@@ -220,110 +224,175 @@ let teacherRouter = [
       import(/* webpackChunkName: "privacy" */ "@/views/teacher/tobeReport"),
     meta: {
       descrition: "待完成月报",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/visitList",
     name: "visitList",
     component: () =>
-      import(/* webpackChunkName: "visitList" */ "@/views/visitManager/visitList"),
+      import(
+        /* webpackChunkName: "visitList" */ "@/views/visitManager/visitList"
+      ),
     meta: {
       descrition: "回访记录",
-      weight: 8 // 页面权重
-    }
+      weight: 8, // 页面权重
+    },
   },
   {
     path: "/addVisit",
     name: "addVisit",
     component: () =>
-      import(/* webpackChunkName: "addVisit" */ "@/views/visitManager/addVisit"),
+      import(
+        /* webpackChunkName: "addVisit" */ "@/views/visitManager/addVisit"
+      ),
     meta: {
       descrition: "回访记录",
-      weight: 8 // 页面权重
-    }
-  }, {
+      weight: 8, // 页面权重
+    },
+  },
+  {
     path: "/visitDetail",
     name: "visitDetail",
     component: () =>
-      import(/* webpackChunkName: "visitDetail" */ "@/views/visitManager/visitDetail"),
+      import(
+        /* webpackChunkName: "visitDetail" */ "@/views/visitManager/visitDetail"
+      ),
     meta: {
       descrition: "回访记录",
-      weight: 8 // 页面权重
-    }
-  }, {
-    path: '/rules',
-    name: 'rules',
-    component: () => import(/* webpackChunkName:'UserProtocol'*/'@/views/rules/index.vue'),
-    meta: {
-        descrition: '签到签到课酬扣减规则',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/assistCenter',
-    name: 'assistCenter',
-    component: () => import(/* webpackChunkName:'assistCenter'*/'@/views/rules/assistCenter.vue'),
-    meta: {
-        descrition: '帮助中心',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/specialDetail',
-    name: 'specialDetail',
-    component: () => import(/* webpackChunkName:'specialDetail'*/'@/views/teacher/specialDetail.vue'),
-    meta: {
-        descrition: '系统通知',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/special',
-    name: 'special',
-    component: () => import(/* webpackChunkName:'special'*/'@/views/teacher/special.vue'),
-    meta: {
-        descrition: '系统通知列表',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/trainStatistics',
-    name: 'trainStatistics',
-    component: () => import(/* webpackChunkName:'trainStatistics'*/'@/views/trainStatistics/index.vue'),
-    meta: {
-        descrition: '训练统计',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/trainDetail',
-    name: 'trainDetail',
-    component: () => import(/* webpackChunkName:'trainDetail'*/'@/views/trainStatistics/trainDetail.vue'),
-    meta: {
-        descrition: '评测详情',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/activeProgram',
-    name: 'activeProgram',
-    component: () => import(/* webpackChunkName:'activeProgram'*/'@/views/activeProgram/index.vue'),
-    meta: {
-        descrition: '活动方案',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/activeDetail',
-    name: 'activeDetail',
-    component: () => import(/* webpackChunkName:'activeDetail'*/'@/views/activeProgram/activeDetail.vue'),
-    meta: {
-        descrition: '活动详情',
-        weight: 3 // 页面权重
-    }
-  }, {
-    path: '/program',
-    name: 'program',
-    component: () => import(/* webpackChunkName:'program'*/'@/views/activeProgram/program.vue'),
-    meta: {
-        descrition: '活动详情',
-        weight: 3 // 页面权重
-    }
-  }
+      weight: 8, // 页面权重
+    },
+  },
+  {
+    path: "/rules",
+    name: "rules",
+    component: () =>
+      import(/* webpackChunkName:'UserProtocol'*/ "@/views/rules/index.vue"),
+    meta: {
+      descrition: "签到签到课酬扣减规则",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/assistCenter",
+    name: "assistCenter",
+    component: () =>
+      import(
+        /* webpackChunkName:'assistCenter'*/ "@/views/rules/assistCenter.vue"
+      ),
+    meta: {
+      descrition: "帮助中心",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/specialDetail",
+    name: "specialDetail",
+    component: () =>
+      import(
+        /* webpackChunkName:'specialDetail'*/ "@/views/teacher/specialDetail.vue"
+      ),
+    meta: {
+      descrition: "系统通知",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/special",
+    name: "special",
+    component: () =>
+      import(/* webpackChunkName:'special'*/ "@/views/teacher/special.vue"),
+    meta: {
+      descrition: "系统通知列表",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/trainStatistics",
+    name: "trainStatistics",
+    component: () =>
+      import(
+        /* webpackChunkName:'trainStatistics'*/ "@/views/trainStatistics/index.vue"
+      ),
+    meta: {
+      descrition: "训练统计",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/trainDetail",
+    name: "trainDetail",
+    component: () =>
+      import(
+        /* webpackChunkName:'trainDetail'*/ "@/views/trainStatistics/trainDetail.vue"
+      ),
+    meta: {
+      descrition: "评测详情",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/activeProgram",
+    name: "activeProgram",
+    component: () =>
+      import(
+        /* webpackChunkName:'activeProgram'*/ "@/views/activeProgram/index.vue"
+      ),
+    meta: {
+      descrition: "活动方案",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/activeDetail",
+    name: "activeDetail",
+    component: () =>
+      import(
+        /* webpackChunkName:'activeDetail'*/ "@/views/activeProgram/activeDetail.vue"
+      ),
+    meta: {
+      descrition: "活动详情",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/program",
+    name: "program",
+    component: () =>
+      import(
+        /* webpackChunkName:'program'*/ "@/views/activeProgram/program.vue"
+      ),
+    meta: {
+      descrition: "活动详情",
+      weight: 3, // 页面权重
+    },
+  },
+  {
+    path: "/liveRoomList",
+    name: "liveRoomList",
+    component: () =>
+      import(
+        /* webpackChunkName: "liveRoomList" */ "@/views/liveActive/liveRoomList"
+      ),
+    meta: {
+      clearAuth: 1,
+      descrition: "直播间",
+      weight: 8, // 页面权重
+    },
+  },
+  {
+    path: "/previewVideo",
+    name: "previewVideo",
+    component: () =>
+      import(
+        /* webpackChunkName: "previewVideo" */ "@/views/liveActive/model/previewVideo"
+      ),
+    meta: {
+      clearAuth: 1,
+      descrition: "直播视频列表",
+      weight: 8, // 页面权重
+    },
+  },
 ];
 
 export default teacherRouter;

+ 17 - 0
src/views/liveActive/api.js

@@ -0,0 +1,17 @@
+import request from "@/helpers/request";
+
+export const queryPageStudent = (data) => {
+  return request({
+    url: "/imLiveBroadcastRoom/queryPage",
+    method: "post",
+    data,
+  });
+};
+
+export const queryRoomDetail = (data) => {
+  return request({
+    url: "/imLiveRoomVideo/queryList",
+    method: "get",
+    params: data,
+  });
+};

+ 29 - 0
src/views/liveActive/images/audio.svg

@@ -0,0 +1,29 @@
+<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
+<svg width="55" height="80" viewBox="0 0 55 80" xmlns="http://www.w3.org/2000/svg" fill="#FFF">
+    <g transform="matrix(1 0 0 -1 0 80)">
+        <rect width="10" height="20" rx="3">
+            <animate attributeName="height"
+                 begin="0s" dur="4.3s"
+                 values="20;45;57;80;64;32;66;45;64;23;66;13;64;56;34;34;2;23;76;79;20" calcMode="linear"
+                 repeatCount="indefinite" />
+        </rect>
+        <rect x="15" width="10" height="80" rx="3">
+            <animate attributeName="height"
+                 begin="0s" dur="2s"
+                 values="80;55;33;5;75;23;73;33;12;14;60;80" calcMode="linear"
+                 repeatCount="indefinite" />
+        </rect>
+        <rect x="30" width="10" height="50" rx="3">
+            <animate attributeName="height"
+                 begin="0s" dur="1.4s"
+                 values="50;34;78;23;56;23;34;76;80;54;21;50" calcMode="linear"
+                 repeatCount="indefinite" />
+        </rect>
+        <rect x="45" width="10" height="30" rx="3">
+            <animate attributeName="height"
+                 begin="0s" dur="2s"
+                 values="30;45;13;80;56;72;45;76;34;23;67;30" calcMode="linear"
+                 repeatCount="indefinite" />
+        </rect>
+    </g>
+</svg>

二進制
src/views/liveActive/images/icon_person.png


二進制
src/views/liveActive/images/icon_video.png


二進制
src/views/liveActive/images/video_default.png


+ 271 - 0
src/views/liveActive/liveRoomList.vue

@@ -0,0 +1,271 @@
+<template>
+  <div class="live-room" style="min-height: 100vh; overflow: hidden">
+    <!-- 78 -->
+    <van-sticky
+      offset-top="0"
+      style="height: 44px; width: 100%"
+      :style="{ height: params.liveState != '1' ? '78px' : '44px' }"
+    >
+      <van-tabs
+        v-model="params.liveState"
+        color="#01C1B5"
+        line-width="16px"
+        line-height="4px"
+        @change="onSearch"
+      >
+        <van-tab name="1" title="直播中"></van-tab>
+        <van-tab name="0" title="未开始"> </van-tab>
+        <van-tab name="2" title="已结束"> </van-tab>
+      </van-tabs>
+
+      <div
+        v-if="params.liveState != '1'"
+        class="titleWrap week"
+        style="height: 22px; line-height: 22px; padding: 12px 0.14rem 0"
+        @click="showCalendar = true"
+      >
+        <div class="calendar" :class="showCalendar ? 'active' : ''">
+          <div>{{ params.startTime }}~{{ params.endTime }}</div>
+        </div>
+      </div>
+    </van-sticky>
+
+    <van-calendar
+      v-model="showCalendar"
+      :minDate="minDate"
+      color="#01C1B5"
+      :default-date="[
+        dayjs(params.startTime).toDate(),
+        dayjs(params.endTime).toDate(),
+      ]"
+      type="range"
+      @confirm="onConfirm"
+      :first-day-of-week="1"
+      get-container="body"
+    />
+
+    <van-list
+      v-model="loading"
+      v-if="dataShow"
+      style="margin-top: 0.15rem"
+      key="ing"
+      :finished="finished"
+      finished-text=" "
+      :immediate-check="false"
+      @load="getList()"
+    >
+      <div v-for="(item, index) in dataList" :key="index">
+        <live-room :item="item" />
+      </div>
+    </van-list>
+    <m-empty v-else msg="暂无数据" />
+  </div>
+</template>
+
+<script>
+import liveRoom from "./model/liveRoom";
+import MEmpty from "@/components/MEmpty";
+import { queryPageStudent } from "./api";
+import dayjs from "dayjs";
+
+const startTime = dayjs().startOf("month").format("YYYY-MM-DD");
+const endTime = dayjs().endOf("month").format("YYYY-MM-DD");
+export default {
+  components: { liveRoom, MEmpty },
+  data() {
+    const query = this.$route.query;
+    const s = sessionStorage.getItem("liveRoomListTab");
+    return {
+      minDate: new Date(2000, 0, 1),
+      showCalendar: false,
+      dataList: [],
+      dataLoading: false,
+      dataShow: true,
+      loading: false,
+      finished: false,
+      params: {
+        endTime: endTime,
+        startTime: startTime,
+        page: 1,
+        rows: 20,
+        liveState: query.t == 0 ? "0" : s || "1",
+      },
+      hiddenProperty: null,
+      pageStatusTimer: null, // 页面判断
+    };
+  },
+  mounted() {
+    this.hiddenProperty =
+      "hidden" in document
+        ? "hidden"
+        : "webkitHidden" in document
+        ? "webkitHidden"
+        : "mozHidden" in document
+        ? "mozHidden"
+        : null;
+    this.visibilityChangeEvent = this.hiddenProperty.replace(
+      /hidden/i,
+      "visibilitychange"
+    );
+    document.addEventListener(
+      this.visibilityChangeEvent,
+      this.onVisibilityChange
+    );
+
+    document.title = "直播间";
+    this.getList();
+  },
+  methods: {
+    dayjs,
+    onVisibilityChange() {
+      // console.log("onVisibilityChange", document[this.hiddenProperty]);
+      // console.log("hidden", document.hidden);
+      // console.log("visibilityState", document.visibilityState);
+      if (!document[this.hiddenProperty]) {
+        clearInterval(this.pageStatusTimer);
+        this.onSearch();
+      } else {
+        this.pageStatusTimer = setInterval(() => {
+          if (!document[this.hiddenProperty]) {
+            clearInterval(this.pageStatusTimer);
+            this.onSearch();
+          }
+        }, 1000);
+      }
+    },
+    onConfirm(date) {
+      let [start, end] = date;
+      this.params.startTime = dayjs(start).format("YYYY-MM-DD");
+      this.params.endTime = dayjs(end).format("YYYY-MM-DD");
+      this.showCalendar = false;
+      this.onSearch();
+    },
+    onSearch() {
+      sessionStorage.setItem("liveRoomListTab", this.params.liveState);
+      this.dateShow = true;
+      this.loading = false;
+      this.finished = false;
+      this.params.page = 1;
+      this.dataList = [];
+      this.getList();
+    },
+    async getList() {
+      try {
+        if (this.dataLoading) return;
+        this.dataLoading = true;
+        const { startTime, endTime, ...more } = this.params;
+        const tempParams = {
+          ...more,
+        };
+        if (this.params.liveState != "1") {
+          tempParams.startTime = startTime;
+          tempParams.endTime = endTime;
+        }
+        const res = await queryPageStudent(tempParams);
+        this.dataLoading = false;
+        let result = res.data;
+        this.loading = false;
+        // 如果列表有值且,在请求在第一页时
+        if (this.dataList.length > 0 && result.pageNo == 1) {
+          return;
+        }
+        this.dataList.push(...(result.rows || []));
+        if (this.params.page >= Math.ceil(result.total / this.params.rows)) {
+          this.finished = true;
+        }
+        this.params.page++;
+        if (this.dataList.length <= 0) {
+          this.dataShow = false;
+        } else {
+          this.dataShow = true;
+        }
+      } catch {
+        //
+      }
+    },
+  },
+  beforeDestroy() {
+    clearInterval(this.pageStatusTimer);
+    document.removeEventListener(
+      this.visibilityChangeEvent,
+      this.onVisibilityChange
+    );
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.live-room {
+  /deep/.van-tabs__nav {
+    background-color: #f5f5f5 !important;
+  }
+  /deep/.van-tab {
+    font-size: 0.16rem;
+  }
+  /deep/.van-sticky {
+    height: inherit !important;
+    position: fixed;
+    width: 100%;
+  }
+  /deep/.van-button--small {
+    height: 28px;
+  }
+}
+.titleWrap.week {
+  background: #f5f5f5;
+  justify-content: space-between;
+  .calendar {
+    font-size: 0.14rem;
+    position: relative;
+    &::after {
+      right: -0.14rem;
+    }
+  }
+  div {
+    display: inline-flex;
+    flex-direction: row;
+    align-items: center;
+    font-size: 0.14rem;
+  }
+  .active {
+    color: #01c1b5;
+  }
+}
+.active.calendar::after {
+  transform: rotate(-225deg) !important;
+  margin-top: -2px;
+}
+.calendar::after {
+  position: absolute;
+  top: 50%;
+  right: -4px;
+  margin-top: -6px;
+  border: 4px solid;
+  border-top-color: transparent;
+  border-top-style: solid;
+  border-top-width: 4px;
+  border-right-color: transparent;
+  border-right-style: solid;
+  border-right-width: 4px;
+  border-bottom-color: #01c1b5;
+  border-bottom-style: solid;
+  border-bottom-width: 4px;
+  border-left-color: #01c1b5;
+  border-left-style: solid;
+  border-left-width: 4px;
+  border-image-source: initial;
+  border-image-slice: initial;
+  border-image-width: initial;
+  border-image-outset: initial;
+  border-image-repeat: initial;
+  border-color: transparent transparent #01c1b5 #01c1b5;
+  border-top-color: transparent;
+  border-right-color: transparent;
+  border-bottom-color: #01c1b5;
+  border-left-color: #01c1b5;
+  -webkit-transform: rotate(-45deg);
+  transform: rotate(-45deg);
+  opacity: 0.8;
+  content: "";
+}
+</style>

+ 127 - 0
src/views/liveActive/model/liveRoom.vue

@@ -0,0 +1,127 @@
+<template>
+  <div>
+    <van-cell-group class="cell-group" :border="false">
+      <van-cell center style="border-radius: 0.1rem !important">
+        <template #title>
+          <div class="title">
+            <img src="../images/icon_video.png" alt="" />
+            <p class="van-ellipsis" style="width: 2.8rem">
+              {{ item.roomTitle }}
+            </p>
+          </div>
+        </template>
+        <template #label>
+          直播内容:{{ item.liveRemark }} <br />
+          <template v-if="item.liveState != 1">
+            直播时间:{{ item.liveStartTime }}
+          </template>
+        </template>
+      </van-cell>
+      <van-cell center style="border-radius: 0.1rem !important">
+        <template #title>
+          <div class="username">
+            <img src="../images/icon_person.png" />
+            <span>主讲人:{{ item.speakerName }}</span>
+          </div>
+        </template>
+
+        <van-button
+          round
+          size="small"
+          color="#FF806F"
+          v-if="item.liveState == 1"
+          @click="onDetail"
+        >
+          <img class="svg" src="../images/audio.svg" alt="" />
+          进入直播
+        </van-button>
+
+        <van-button
+          round
+          size="small"
+          type="info"
+          style="min-width: 68px"
+          v-if="item.liveState == 2"
+          @click="onDetail"
+        >
+          查看回放
+        </van-button>
+      </van-cell>
+    </van-cell-group>
+    <van-popup v-model="videoStatus" round style="width: 90%" closeable>
+      <preview-video v-if="videoStatus" :videoList="videoList" />
+    </van-popup>
+  </div>
+</template>
+
+<script>
+import { postMessage } from "@/helpers/native-message";
+import previewVideo from "./previewVideo";
+export default {
+  components: { previewVideo },
+  props: ["item"],
+  data() {
+    return {
+      videoStatus: false,
+      videoList: [],
+      src: "",
+    };
+  },
+  methods: {
+    async onDetail() {
+      const item = this.item;
+      if (item.liveState == 1) {
+        postMessage({
+          api: "enterLiveRoom",
+          content: { roomId: item.roomUid },
+        });
+      } else if (item.liveState == 2) {
+        this.$router.push("/previewVideo?roomUid=" + item.roomUid);
+
+        this.videoStatus = true;
+      }
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.cell-group {
+  margin: 0.12rem 0.14rem;
+  overflow: hidden !important;
+  border-radius: 0.1rem !important;
+  /deep/.van-cell__label {
+    // line-height: 1.5;
+  }
+}
+.title {
+  display: flex;
+  align-items: center;
+  font-size: 0.16rem;
+  font-weight: 500;
+  color: #000000;
+  line-height: 1.2;
+  padding-top: 0.1rem;
+  padding-bottom: 0.05rem;
+  img {
+    width: 0.22rem;
+    height: 0.22rem;
+    margin-right: 0.08rem;
+  }
+}
+.svg {
+  width: 0.12rem;
+  height: 0.09rem;
+}
+.username {
+  display: flex;
+  align-items: center;
+  font-size: 0.13rem;
+  color: #ff806f;
+  img {
+    width: 0.12rem;
+    height: 0.15rem;
+    margin-right: 0.05rem;
+  }
+}
+</style>

+ 144 - 0
src/views/liveActive/model/previewVideo.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="previewVideo">
+    <div class="h2 flex-center">视频列表</div>
+
+    <div class="video-list">
+      <div
+        class="video-item"
+        v-for="(item, index) in videoList"
+        :key="index"
+        @click="onDetail(item)"
+      >
+        <!-- <videoPlayer
+          class="ql-video video"
+          height="100%"
+          preload="auto"
+          :playLarge="false"
+          :src="`${item.url}#t=1`"
+          @play="onPlay(index)"
+          :ref="`video${index}`"
+        ></videoPlayer> -->
+        <img src="../images/video_default.png" class="video" />
+        <p class="time">{{ item.createdTime }}</p>
+      </div>
+      <MEmpty
+        v-if="!videoStatus"
+        msg="暂无视频"
+        style="width: 100%; margin-bottom: 0.1rem"
+      />
+
+      <van-popup v-model="videoPopup" style="width: 90%" closeable>
+        <videoPlayer
+          v-if="videoPopup"
+          class="ql-video"
+          height="1.915rem"
+          :src="videoSrc"
+        ></videoPlayer>
+      </van-popup>
+    </div>
+  </div>
+</template>
+
+<script>
+import MEmpty from "@/components/MEmpty";
+import videoPlayer from "@/components/video";
+import { queryRoomDetail } from "../api";
+export default {
+  components: {
+    videoPlayer,
+    MEmpty,
+  },
+  data() {
+    const query = this.$route.query;
+    return {
+      roomUid: query.roomUid,
+      videoStatus: true,
+      videoList: [],
+      videoPopup: false,
+      videoSrc: "",
+    };
+  },
+  // props: ["videoList"],
+  mounted() {
+    document.title = "视频列表";
+    this.getVideoList();
+  },
+  methods: {
+    onDetail(item) {
+      this.videoPopup = true;
+      this.videoSrc = item.url + "#t=1";
+    },
+    async getVideoList() {
+      try {
+        this.videoStatus = true;
+        const res = await queryRoomDetail({ roomUid: this.roomUid });
+        const result = res.data;
+        this.videoList = result || [];
+        this.videoStatus = this.videoList.length > 0;
+      } catch {
+        //
+      }
+    },
+    onPlay(index) {
+      // #t=1
+      console.log(index, "index");
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.flex-center {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+/deep/.icon_nodata {
+  margin-top: 0.2rem !important;
+}
+.previewVideo {
+  min-height: calc(100vh - 0.44rem);
+  padding: 0.22rem 0.16rem;
+}
+.h2 {
+  margin-bottom: 0.1rem;
+  font-size: 0.18rem;
+  font-weight: 500;
+  color: #333333;
+  &::before {
+    display: inline-block;
+    content: " ";
+    width: 4px;
+    height: 17px;
+    background: #01c1b5;
+    border-radius: 3px;
+    margin-right: 0.07rem;
+  }
+}
+.video-list {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+.video-item {
+  width: 48%;
+  margin-bottom: 0.1rem;
+  .video {
+    width: 100%;
+    height: 1rem;
+    background: #d8d8d8;
+    border-radius: 0.1rem;
+    overflow: hidden;
+    vertical-align: middle;
+  }
+  .time {
+    font-size: 0.12rem;
+    color: #666666;
+    line-height: 0.28rem;
+  }
+  /deep/.plyr {
+    min-width: 100%;
+  }
+}
+</style>