Browse Source

feat:口播视频

chenjiaxin 3 weeks ago
parent
commit
9653450262

+ 1 - 1
.env.development

@@ -3,7 +3,7 @@ ENV = 'development'
 
 # base api
 
-VUE_APP_OAUTH_API = '/auth/'
+VUE_APP_OAUTH_API = '/backstage/auth/'
 VUE_APP_AI_API = '/ai/'
 
 # VUE_APP_OAUTH_API = '/auth/'

+ 1 - 1
.env.production

@@ -2,7 +2,7 @@
 ENV = 'production'
 
 # base api
-VUE_APP_OAUTH_API = '/auth/'
+VUE_APP_OAUTH_API = '/backstage/auth/'
 VUE_APP_AI_API = '/ai/'
 #静态资源
 VUE_APP_RESOURCE_URL = ''

+ 0 - 1
package.json

@@ -38,7 +38,6 @@
     "js-cookie": "2.2.0",
     "normalize.css": "7.0.0",
     "nprogress": "0.2.0",
-    "screenfull": "4.2.0",
     "sm-crypto": "^0.3.13",
     "stylus": "^0.54.5",
     "stylus-loader": "^3.0.2",

+ 5 - 5
src/api/video.js

@@ -1,16 +1,16 @@
 import request from '@/utils/request'
 
-export function fetchOralVideoList(data) {
+export function fetchOralVideoList(params) {
   return request({
     url: '/videoInfo/page',
     method: 'get',
-    aiVideoInfoPageParam: data
+    params
   })
 }
-export function deleteOralVideoList(params) {
+export function deleteOralVideoList(data) {
   return request({
     url: '/videoInfo/delete',
-    method: 'delete',
-    params
+    method: 'post',
+    data
   })
 }

+ 1 - 3
src/components/Breadcrumb/index.vue

@@ -44,9 +44,7 @@ export default {
       let matched = this.$route.matched.filter(item => item.name);
       const first = matched[0];
       if (first && first.name !== "index") {
-        matched = [{ path: "/index", meta: { title: "dashboard" } }].concat(
-          matched
-        );
+        matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched);
       }
       this.levelList = matched;
     }

+ 63 - 41
src/components/Screenfull/index.vue

@@ -1,16 +1,19 @@
 <template>
-  <div class="screenfull-box">
-    <svg-icon
-      class="screenfull-svg"
-      :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
-      @click="click"
-    />
+  <div class="screenfull-container" @click="click">
+    <el-tooltip
+      effect="dark"
+      :content="isFullscreen ? '退出全屏' : '全屏'"
+      placement="bottom"
+    >
+      <i
+        :class="isFullscreen ? 'el-icon-close' : 'el-icon-full-screen'"
+        class="screenfull-icon"
+      />
+    </el-tooltip>
   </div>
 </template>
 
 <script>
-import screenfull from "screenfull";
-
 export default {
   name: "Screenfull",
   data() {
@@ -19,51 +22,70 @@ export default {
     };
   },
   mounted() {
-    this.init();
+    document.addEventListener("fullscreenchange", this.fullscreenChange);
+    document.addEventListener("webkitfullscreenchange", this.fullscreenChange);
+    document.addEventListener("mozfullscreenchange", this.fullscreenChange);
+    document.addEventListener("MSFullscreenChange", this.fullscreenChange);
   },
   beforeDestroy() {
-    this.destroy();
+    document.removeEventListener("fullscreenchange", this.fullscreenChange);
+    document.removeEventListener(
+      "webkitfullscreenchange",
+      this.fullscreenChange
+    );
+    document.removeEventListener("mozfullscreenchange", this.fullscreenChange);
+    document.removeEventListener("MSFullscreenChange", this.fullscreenChange);
   },
   methods: {
-    click() {
-      console.log("click");
-      if (!screenfull.enabled) {
-        this.$message({
-          message: "you browser can not work",
-          type: "warning"
-        });
-        return false;
-      }
-      screenfull.toggle();
-    },
-    change() {
-      this.isFullscreen = screenfull.isFullscreen;
-    },
-    init() {
-      if (screenfull.enabled) {
-        screenfull.on("change", this.change);
-      }
+    fullscreenChange() {
+      this.isFullscreen = !!(
+        document.fullscreenElement ||
+        document.webkitFullscreenElement ||
+        document.mozFullScreenElement ||
+        document.msFullscreenElement
+      );
     },
-    destroy() {
-      if (screenfull.enabled) {
-        screenfull.off("change", this.change);
+    click() {
+      const element = document.documentElement;
+      try {
+        if (!this.isFullscreen) {
+          if (element.requestFullscreen) {
+            element.requestFullscreen();
+          } else if (element.webkitRequestFullscreen) {
+            element.webkitRequestFullscreen();
+          } else if (element.mozRequestFullScreen) {
+            element.mozRequestFullScreen();
+          } else if (element.msRequestFullscreen) {
+            element.msRequestFullscreen();
+          }
+        } else {
+          if (document.exitFullscreen) {
+            document.exitFullscreen();
+          } else if (document.webkitExitFullscreen) {
+            document.webkitExitFullscreen();
+          } else if (document.mozCancelFullScreen) {
+            document.mozCancelFullScreen();
+          } else if (document.msExitFullscreen) {
+            document.msExitFullscreen();
+          }
+        }
+        this.isFullscreen = !this.isFullscreen;
+      } catch (err) {
+        this.$message.error("浏览器不支持全屏");
       }
     }
   }
 };
 </script>
 
-<style scoped>
-.screenfull-box {
-  height: 100%;
+<style lang="scss" scoped>
+.screenfull-container {
+  cursor: pointer;
   display: flex;
   align-items: center;
-}
-.screenfull-svg {
-  display: inline-block;
-  cursor: pointer;
-  fill: #5a5e66;
-  width: 20px;
-  height: 20px;
+  .screenfull-icon {
+    font-size: 20px;
+    color: #000;
+  }
 }
 </style>

+ 13 - 5
src/components/VideoPlayer/index.vue

@@ -2,7 +2,7 @@
   <div class="video-player-container">
     <el-dialog
       :visible.sync="dialogVisible"
-      :title="title"
+      :title="videoTitle"
       width="800px"
       @close="handleClose"
     >
@@ -10,6 +10,8 @@
         ref="videoPlayer"
         class="video-player"
         :src="videoUrl"
+        autoplay
+        muted
         controls
         controlsList="nodownload"
       >
@@ -24,11 +26,11 @@ export default {
   name: "VideoPlayer",
   props: {
     videoUrl: {
-      type: String,
-      required: true
+      type: [String, null],
+      default: null
     },
-    title: {
-      type: String,
+    videoTitle: {
+      type: [String, null],
       default: "视频播放"
     }
   },
@@ -40,6 +42,12 @@ export default {
   methods: {
     show() {
       this.dialogVisible = true;
+      this.$nextTick(() => {
+        const video = this.$refs.videoPlayer;
+        if (video) {
+          video.muted = false;
+        }
+      });
     },
     handleClose() {
       const video = this.$refs.videoPlayer;

+ 12 - 0
src/constants/index.js

@@ -0,0 +1,12 @@
+// 审核状态
+export const auditStatus = [
+  { value: 0, label: '待审核' },
+  { value: 1, label: '审核通过' },
+  { value: 2, label: '审核拒绝' }
+];
+
+export default {
+  auditStatus
+}
+
+

+ 0 - 203
src/layout/MenuDoubleLayer.vue

@@ -1,203 +0,0 @@
-<template>
-  <el-container>
-    <el-aside width="120px">
-      <!-- 一级分类 -->
-      <sidebar class="sidebar-container" @retParentMenu="byChildByParent" />
-    </el-aside>
-    <el-container>
-      <el-header class="header">
-        <navbar :nameshow="nameshow" @helpcenterEvent="showhelp" />
-      </el-header>
-      <el-main>
-        <div :class="{ hasTagsView: needTagsView }" class="main-container">
-          <div :class="{ 'fixed-header': fixedHeader }">
-            <div class="left_main">
-              <!-- 子菜单 -->
-              <SubSidebar
-                class="sidebar-container1"
-                v-if="currRouter"
-                :currRouterData="currRouter"
-              />
-              <div
-                id="main_work"
-                :class="currRouter ? 'min_width' : 'max_width'"
-              >
-                <tags-view
-                  v-if="needTagsView"
-                  @retParentMenu="byChildByParent"
-                />
-                <app-main />
-              </div>
-              <div v-show="showhelped === 'true'" class="helpcenter">
-                <help-word />
-              </div>
-            </div>
-          </div>
-          <right-panel v-if="showSettings">
-            <settings />
-          </right-panel>
-        </div>
-      </el-main>
-    </el-container>
-  </el-container>
-</template>
-
-<script>
-import RightPanel from "@/components/RightPanel";
-import { AppMain, Navbar, Settings, Sidebar, TagsView } from "./components";
-import SubSidebar from "./components/subSidebar";
-import ResizeMixin from "./mixin/ResizeHandler";
-import sidebarA from "./components/SidebarA";
-import { mapState } from "vuex";
-
-export default {
-  name: "Layout",
-  components: {
-    AppMain,
-    Navbar,
-    RightPanel,
-    Settings,
-    Sidebar,
-    SubSidebar,
-    TagsView,
-    sidebarA
-  },
-  mixins: [ResizeMixin],
-  computed: {
-    ...mapState({
-      sidebar: state => state.app.sidebar,
-      device: state => state.app.device,
-      showSettings: state => state.settings.showSettings,
-      needTagsView: state => state.settings.tagsView,
-      fixedHeader: state => state.settings.fixedHeader
-    }),
-    classObj() {
-      return {
-        hideSidebar: !this.sidebar.opened,
-        openSidebar: this.sidebar.opened,
-        withoutAnimation: this.sidebar.withoutAnimation,
-        mobile: this.device === "mobile"
-      };
-    }
-  },
-  data() {
-    return {
-      sidebarType: 1,
-      currRouter: null,
-      nameshow: false,
-      showhelped: false
-    };
-  },
-
-  methods: {
-    handleClickOutside() {
-      this.$store.dispatch("app/closeSideBar", {
-        withoutAnimation: false
-      });
-    },
-    byChildByParent(currRouter) {
-      this.currRouter = currRouter;
-      if (currRouter === null) {
-        this.nameshow = false;
-      } else {
-        this.nameshow = true;
-      }
-    },
-    showhelp(data) {
-      this.showhelped = data;
-    }
-  }
-};
-</script>
-
-<style lang="scss" scoped>
-@import "../styles/mixin.scss";
-@import "../styles/variables.scss";
-::v-deep .el-main {
-  padding: 0;
-}
-
-.el-header {
-  padding: 0;
-  position: fixed;
-  width: -webkit-calc(100% - #{$sideBarWidth});
-  width: -moz-calc(100% - #{$sideBarWidth});
-  width: calc(100% - #{$sideBarWidth});
-  top: 0;
-  z-index: 1000;
-}
-
-.el-main {
-  margin-top: 50px;
-}
-
-.app-wrapper {
-  @include clearfix;
-  position: relative;
-  height: 100%;
-  width: 100%;
-  &.mobile.openSidebar {
-    position: fixed;
-    top: 0;
-  }
-}
-
-.drawer-bg {
-  background: #000;
-  opacity: 0.3;
-  width: 100%;
-  top: 0;
-  height: 100%;
-  position: absolute;
-  z-index: 999;
-}
-
-.fixed-header {
-  position: fixed;
-  top: 0;
-  right: 0;
-  z-index: 9;
-  width: calc(100% - #{$sideBarWidth});
-  transition: width 0.28s;
-}
-
-.hideSidebar .fixed-header {
-  width: calc(100% - 54px);
-}
-
-.mobile .fixed-header {
-  width: 100%;
-}
-
-.helpcenter {
-  flex: 1.5;
-  margin-left: 10px;
-  margin-right: -20px;
-  margin-top: 10px;
-  border-radius: 5px;
-  box-shadow: 0 0 5px rgba(100, 100, 100, 0.2);
-}
-
-.min_width {
-  width: calc(100vw - 250px);
-}
-
-.max_width {
-  width: calc(100vw - 130px);
-}
-
-.left_main {
-  display: flex;
-  padding: 0px 20px;
-  background-color: #f8f8f8;
-  height: calc(100vh - 50px);
-  overflow: hidden;
-  padding-right: 10px;
-}
-
-#main_work {
-  margin-top: 10px;
-  /*overflow-y: scroll;*/
-  height: calc(100vh - 100px);
-}
-</style>

+ 12 - 6
src/layout/MenuSingleLayer.vue

@@ -1,12 +1,15 @@
 <template>
   <el-container>
-    <el-aside width="230px" style="margin-bottom: 20px">
+    <el-aside :width="sidebar.opened ? '230px' : '64px'">
       <sidebarA class="sidebar-container" />
     </el-aside>
     <el-container>
-      <el-header class="header">
+      <el-header
+        class="header"
+        :style="{ width: `calc(100% - ${sidebar.opened ? '230px' : '64px'})` }"
+      >
         <!-- 头部 导航 -->
-        <navbar :nameshow="nameshow" @helpcenterEvent="showhelp" />
+        <navbar :nameshow="nameshow" />
       </el-header>
       <el-main>
         <div :class="{ hasTagsView: needTagsView }" class="main-container">
@@ -103,11 +106,14 @@ export default {
 .el-header {
   padding: 0;
   position: fixed;
-  width: -webkit-calc(100% - #{$sideBarWidth});
-  width: -moz-calc(100% - #{$sideBarWidth});
-  width: calc(100% - #{$sideBarWidth});
+  transition: width 0.3s;
   top: 0;
   z-index: 1000;
+  transition: width 0.3s;
+
+  &.hideSidebar {
+    width: calc(100% - 64px);
+  }
 }
 
 .el-main {

+ 33 - 25
src/layout/components/Navbar.vue

@@ -1,29 +1,16 @@
 <template>
   <div class="navbar">
     <!-- 面包屑 -->
-    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
+    <div class="left-menu">
+      <div class="hamburger-container" @click="toggleSideBar">
+        <i
+          :class="[sidebar.opened ? 'el-icon-s-fold' : 'el-icon-s-unfold']"
+        ></i>
+      </div>
+      <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
+    </div>
+
     <div class="right-menu">
-      <!-- 切换语言 -->
-      <!-- <el-dropdown
-        class="avatar-container right-menu-item hover-effect"
-        trigger="click"
-        @command="changeLanguage"
-      >
-        <div>
-          <svg-icon style="color:#fff;font-size:20px" icon-class="language" />
-        </div>
-        <el-dropdown-menu slot="dropdown">
-          <el-dropdown-item command="zh" :disabled="'zh' === $i18n.locale"
-            >中文</el-dropdown-item
-          >
-          <el-dropdown-item command="en" :disabled="'en' === $i18n.locale"
-            >en</el-dropdown-item
-          >
-          <el-dropdown-item command="ja" :disabled="'ja' === $i18n.locale"
-            >日本語</el-dropdown-item
-          >
-        </el-dropdown-menu>
-      </el-dropdown> -->
       <screenfull />
       <el-dropdown
         class="avatar-container right-menu-item hover-effect"
@@ -113,6 +100,10 @@ export default {
 </style>
 <style lang="scss" scoped>
 .navbar {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
   height: 54px;
   overflow: hidden;
   position: relative;
@@ -120,6 +111,18 @@ export default {
   -webkit-box-shadow: 0 2px 20px 0 rgba(15, 12, 70, 0.1);
   box-shadow: 0 2px 20px 0 rgba(15, 12, 70, 0.1);
   color: #000;
+  .left-menu {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    margin-left: 10px;
+    .hamburger-container {
+      i {
+        font-size: 20px;
+        cursor: pointer;
+      }
+    }
+  }
   .breadcrumb-container {
     float: left;
     margin-left: 10px;
@@ -132,6 +135,8 @@ export default {
     float: right;
     height: 100%;
     line-height: 50px;
+    display: flex;
+    flex-direction: row;
     &:focus {
       outline: none;
     }
@@ -154,7 +159,8 @@ export default {
       }
     }
     .avatar-container {
-      margin-right: 50px;
+      margin-right: 35px;
+      margin-left: 10px;
       .avatar-wrapper {
         position: relative;
         height: 100%;
@@ -162,10 +168,12 @@ export default {
         align-items: center;
         .user-avatar {
           cursor: pointer;
-          width: 40px;
-          height: 40px;
+          width: 36px;
+          height: 36px;
           border-radius: 50%;
           margin-right: 10px;
+          border: 1px solid #ddd;
+          object-fit: cover;
         }
         .el-icon-caret-bottom {
           cursor: pointer;

+ 9 - 17
src/layout/components/SidebarA/Item.vue

@@ -1,15 +1,15 @@
 <script>
 export default {
-  name: 'MenuItem',
+  name: "MenuItem",
   functional: true,
   props: {
     icon: {
       type: String,
-      default: ''
+      default: ""
     },
     title: {
       type: String,
-      default: ''
+      default: ""
     }
   },
   render(h, context) {
@@ -17,25 +17,17 @@ export default {
     const vnodes = [];
 
     if (icon) {
-      if (icon.includes('el-icon')) {
-        vnodes.push(<i class={[icon, 'sub-el-icon']} />)
+      if (icon.includes("el-icon")) {
+        vnodes.push(<i class={[icon, "sub-el-icon"]} />);
       } else {
-        vnodes.push(<svg-icon icon-class={icon}/>)
+        vnodes.push(<svg-icon icon-class={icon} />);
       }
     }
 
     if (title) {
-      vnodes.push(<span slot='title'>{(title)}</span>)
+      vnodes.push(<span slot="title">{title}</span>);
     }
-    return vnodes
+    return vnodes;
   }
-}
+};
 </script>
-
-<style scoped>
-.sub-el-icon {
-  color: currentColor;
-  width: 1em;
-  height: 1em;
-}
-</style>

+ 0 - 1
src/layout/components/SidebarA/SidebarItem.vue

@@ -39,7 +39,6 @@
         :is-nest="true"
         :item="child"
         :base-path="resolvePath(child.path)"
-        class="nest-menu"
       />
     </el-submenu>
   </div>

+ 31 - 12
src/layout/components/SidebarA/index.vue

@@ -1,15 +1,18 @@
 <template>
-  <div :class="{ 'has-logo': showLogo }" style="width: 230px;">
-    <!-- <logo :collapse="isCollapse" /> -->
-    <h3 class="title">歌莉娅AI口播视频管理平台</h3>
+  <div :class="{ 'has-logo': showLogo }" :style="sidebarStyle">
+    <div class="logo-container">
+      <img
+        v-show="isCollapse"
+        src="../../../../static/login/img/goelie-b.png"
+        class="sidebar-logo"
+      />
+      <h3 class="title" v-show="!isCollapse">歌莉娅AI口播视频管理平台</h3>
+    </div>
     <el-scrollbar wrap-class="scrollbar-wrapper">
       <el-menu
         :default-active="activeMenu"
         :collapse="isCollapse"
-        :background-color="variables.menuBg"
-        :text-color="variables.menuText"
         :unique-opened="false"
-        :active-text-color="variables.menuActiveText"
         :collapse-transition="false"
         mode="vertical"
       >
@@ -27,7 +30,6 @@
 <script>
 import { mapGetters } from "vuex";
 import SidebarItem from "./SidebarItem";
-import variables from "@/styles/variables.scss";
 
 export default {
   components: { SidebarItem },
@@ -45,18 +47,35 @@ export default {
     showLogo() {
       return this.$store.state.settings.sidebarLogo;
     },
-    variables() {
-      return variables;
-    },
     isCollapse() {
-      return false;
+      return !this.sidebar.opened;
+    },
+    sidebarStyle() {
+      return {
+        width: this.isCollapse ? "64px !important;" : "230px;",
+        transition: "width 0.3s"
+      };
     }
   }
 };
 </script>
 <style lang="scss" scoped>
+.logo-container {
+  height: 60px;
+  padding: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  .sidebar-logo {
+    width: 32px;
+    height: 32px;
+    object-fit: contain;
+  }
+}
+
 .title {
-  color: #000;
+  color: #000000cc;
   font-size: 17px;
   text-align: center;
 }

+ 14 - 23
src/layout/index.vue

@@ -1,33 +1,24 @@
 <template>
-	<div class="app-wrapper">
-
-    <el-container v-if="sidebarType === 1">
+  <div class="app-wrapper">
+    <el-container>
       <MenuSingleLayer />
     </el-container>
-		<el-container v-if="sidebarType === 2">
-      <MenuDoubleLayer />
-		</el-container>
-	</div>
+  </div>
 </template>
 
 <script>
-	import MenuSingleLayer from "./MenuSingleLayer";
-	import MenuDoubleLayer from "./MenuDoubleLayer";
-
+import MenuSingleLayer from "./MenuSingleLayer";
 
-	export default {
-		name: 'Layout',
-		components: {
-      MenuSingleLayer,
-      MenuDoubleLayer
-		},
+export default {
+  name: "Layout",
+  components: {
+    MenuSingleLayer
+  },
 
-		data() {
-			return {
-			}
-		},
+  data() {
+    return {};
+  },
 
-		methods: {}
-	}
+  methods: {}
+};
 </script>
-

+ 3 - 8
src/main.js

@@ -2,6 +2,7 @@ import Vue from 'vue'
 import 'normalize.css/normalize.css' // A modern alternative to CSS resets
 
 import ElementUI from 'element-ui'
+import('./styles/indexA.scss')
 //import 'element-ui/lib/theme-chalk/index.css'
 //babel只能处理语法上的转化,而一些新的API他是没有办法处理的,
 // 比如Promise这些,这就需要babel-polyfill去处理这些新的API。
@@ -9,19 +10,13 @@ import ElementUI from 'element-ui'
 import 'babel-polyfill'
 
 
-let sidebarType = 1;
-if (sidebarType === 1) {
-  import('./styles/indexA.scss')
-} else {
-  import('./styles/index.scss')
-}
 
 import App from './App'
 import router from './router'
 import store from './store'
 
 import './icons' // icon
-// import './permission' // router permission control
+import './permission' // router permission control
 
 import './plugins/element.js'
 import Highlight from './utils/highlight' //高亮
@@ -34,7 +29,7 @@ Vue.use(Highlight);
 // });
 Vue.use(ElementUI);
 
-Vue.prototype.sidebarType = sidebarType; //挂载到Vue实例上面
+
 
 //关闭开放环境提示
 Vue.config.productionTip = false;

+ 2 - 1
src/permission.js

@@ -35,7 +35,8 @@ router.beforeEach(async (to, from, next) => {
             { routerPath: "/auth" },
             { routerPath: "/auth/user" },
             { routerPath: "/auth/role" },
-            { routerPath: "/inventory" }]
+            { routerPath: "/video" },
+            { routerPath: "/video/oralVideo" }]
           const accessRoutes = await store.dispatch('permission/generateRoutes', data);
           router.addRoutes(accessRoutes);
           next({ ...to, replace: true })

+ 2 - 2
src/router/index.js

@@ -23,7 +23,7 @@ export const constantRoutes = [
     name: "index",
     hidden: true,
     meta: {
-      title: "dashboard"
+      title: "首页"
     },
     children: [
       {
@@ -38,8 +38,8 @@ import videoRouter from "./modules/video";
 
 
 export const asyncRoutes = [
-  userAuthRouter,
   videoRouter,
+  userAuthRouter,
 ];
 
 

+ 4 - 4
src/router/modules/userAuth.js

@@ -7,13 +7,13 @@ const userAuthRouter = {
   component: Layout,
   redirect: "/auth/user",
   name: "permissions",
-  meta: { title: "permissions", icon: "organization" },
+  meta: { title: "权限管理", icon: "el-icon-user-solid" },
   children: [
     {
       path: "user",
       component: () => import("@/views/auth/user/userIndex"),
       name: "userIndex",
-      meta: { title: "userList", icon: "" }
+      meta: { title: "用户列表", icon: "" }
     },
     {
       path: "changePassword",
@@ -37,13 +37,13 @@ const userAuthRouter = {
       path: "role",
       component: () => import("@/views/auth/role/roleIndex"),
       name: "roleIndex",
-      meta: { title: "roleManagement" }
+      meta: { title: "角色管理" }
     },
     {
       path: "res",
       component: () => import("@/views/auth/res/resIndex"),
       name: "resIndex",
-      meta: { title: "resourceManagement" }
+      meta: { title: "资源管理" }
     }
   ]
 };

+ 4 - 4
src/router/modules/video.js

@@ -6,14 +6,14 @@ const videoRouter = {
   path: "/video",
   component: Layout,
   redirect: "/video/oralVideo",
-  name: "video",
-  meta: { title: "video", icon: "templet" },
+  name: "内容管理",
+  meta: { title: "内容管理", icon: "el-icon-video-camera-solid" },
   children: [
     {
       path: "oralVideo",
       component: () => import("@/views/video/oral-video.vue"),
-      name: "oralVideo",
-      meta: { title: "oralVideo" }
+      name: "口播视频",
+      meta: { title: "口播视频" }
     }
   ]
 };

+ 1 - 1
src/settings.js

@@ -1,5 +1,5 @@
 module.exports = {
-  title: '口播视频管理平台',
+  title: '歌莉娅AI口播视频管理平台',
 
   /**
    * @type {boolean} true | false

+ 7 - 6
src/store/modules/user.js

@@ -68,11 +68,11 @@ const actions = {
       }).then(
         response => {
           const { data } = response;
-          const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJCIiwibG9naW5JZCI6MTU0MzgzNzg2Mzc4ODg3OTg3MSwicm5TdHIiOiJzeXo2NENGdTdQN3Jsa1RYbEx0TzZxSFNwV2U5eUwyRyIsInVzZXJJZCI6MTU0MzgzNzg2Mzc4ODg3OTg3MSwidXNlck5hbWUiOiLotoXmmJ_ovrAiLCJkZXB0SWQiOjE1NDM4NDI5MzQyNzAzOTQzNjh9.e3kZ1Nt534N6reeFompPdOVSFQzgz8JtSu7WZbDRna0"
-          commit('SET_TOKEN', token);
-          setToken(token);
-          // commit('SET_TOKEN', data.accessToken);
-          // setToken(data.accessToken);
+          // const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJCIiwibG9naW5JZCI6MTU0MzgzNzg2Mzc4ODg3OTg3MSwicm5TdHIiOiJzeXo2NENGdTdQN3Jsa1RYbEx0TzZxSFNwV2U5eUwyRyIsInVzZXJJZCI6MTU0MzgzNzg2Mzc4ODg3OTg3MSwidXNlck5hbWUiOiLotoXmmJ_ovrAiLCJkZXB0SWQiOjE1NDM4NDI5MzQyNzAzOTQzNjh9.e3kZ1Nt534N6reeFompPdOVSFQzgz8JtSu7WZbDRna0"
+          // commit('SET_TOKEN', token);
+          // setToken(token);
+          commit('SET_TOKEN', data.accessToken);
+          setToken(data.accessToken);
           resolve();
         }).catch(error => {
           reject(error);
@@ -105,7 +105,8 @@ const actions = {
         // const btns = data.perms;
         // sessionStorage.setItem('userBtns', btns);
         //头像
-        commit('SET_AVATAR', data.avatar);
+        const avatar = data.avatar || 'https://testdgxcx-oss.gloria.com.cn/goelia-ai/avata.png';
+        commit('SET_AVATAR', avatar);
         //用户名
         if (response.name) {
           commit('SET_LOGINNAME', response.name);

+ 15 - 208
src/styles/sidebar.scss

@@ -5,78 +5,9 @@
   }
 
   // 侧边栏
-  .sidebar-container1 {
-    transition: width 0.28s;
-    z-index: 998;
-    overflow: hidden;
-    margin-left: -20px;
-    //  margin-top: 10px;
-    margin-right: 10px;
-    width: 125px;
-    //reset element-ui css
-    .horizontal-collapse-transition {
-      transition: 0s width ease-in-out, 0s padding-left ease-in-out,
-        0s padding-right ease-in-out;
-    }
-    .scrollbar-wrapper {
-      overflow-x: hidden !important;
-      .el-scrollbar__view {
-        height: 100%;
-        padding: 10px 5px;
-      }
-    }
-    .el-scrollbar__bar.is-vertical {
-      right: 0px;
-    }
-    .is-horizontal {
-      display: none;
-    }
-    a {
-      display: inline-block;
-      width: 100%;
-      overflow: hidden;
-    }
-    .svg-icon {
-      margin-right: 16px;
-    }
-    .el-menu {
-      border: none;
-      height: 100%;
-      width: 100% !important;
-      padding: 10px 5px;
-      .el-menu-item {
-        width: 99%;
-        height: 42px;
-        line-height: 42px;
-        padding: 0;
-        padding-left: 15px !important;
-      }
-      .el-menu-item:hover {
-        border-radius: 6px;
-        background-color: #e9eaf0 !important;
-      }
-      .el-menu-item.is-active {
-        border-radius: 6px;
-        background-color: #e9eaf0 !important;
-      }
-      .el-menu-item.is-active:after {
-        content: "";
-        float: right;
-        width: 0;
-        height: 0;
-        border-color: transparent transparent transparent #000;
-        border-style: solid;
-        border-width: 4px 0 4px 6px;
-        position: absolute;
-        right: 7px;
-        top: 16px;
-      }
-    }
-  }
   .sidebar-container {
-    transition: width 0.28s;
-    width: $sideBarWidth !important;
-    background-color: $menuBg;
+    transition: width 0.3s;
+    width: inherit;
     height: 100%;
     position: fixed;
     font-size: 0px;
@@ -113,154 +44,30 @@
       display: inline-block;
       width: 100%;
       height: 100%;
-      //    padding: 5px 0;
       overflow: hidden;
     }
     .svg-icon {
       margin-right: 10px;
     }
-    .el-menu {
-      border: none;
-      height: 100%;
-      width: 100% !important;
-      .el-menu-item {
-        height: 43px;
-        line-height: 43px;
-      }
-      .el-menu-item:hover {
-        color: #ffffff !important;
-      }
-      .el-menu-item.is-active:after {
-        content: "";
-        width: 4px;
-        background: #fff;
-        border-radius: 2px;
-        position: absolute;
-        right: 5px;
-        top: 25%;
-        bottom: 25%;
-      }
-    }
-    // menu hover
-    .submenu-title-noDropdown,
-    .el-submenu__title {
-      &:hover {
+    .el-menu-item {
+      &.is-active {
         background-color: $menuHover !important;
-      }
-    }
-    .is-active > .el-submenu__title {
-      color: $subMenuActiveText !important;
-    }
-    & .nest-menu .el-submenu > .el-submenu__title,
-    & .el-submenu .el-menu-item {
-      min-width: $sideBarWidth !important;
-      background-color: $subMenuBg !important;
-      &:hover {
-        background-color: $subMenuHover !important;
-      }
-    }
-    & .el-submenu .is-active {
-      background-color: $subMenuHover !important;
-    }
-  }
-  .hideSidebar {
-    .sidebar-container {
-      width: 54px !important;
-    }
-    .main-container {
-      margin-left: 54px;
-    }
-    .submenu-title-noDropdown {
-      padding: 0 !important;
-      position: relative;
-      .el-tooltip {
-        padding: 0 !important;
-        .svg-icon {
-          margin-left: 20px;
-        }
-      }
-    }
-    .el-submenu {
-      overflow: hidden;
-      & > .el-submenu__title {
-        padding: 0 !important;
-        .svg-icon {
-          margin-left: 20px;
-        }
-        .el-submenu__icon-arrow {
-          display: none;
-        }
+        color: $menuActiveText !important;
       }
     }
     .el-menu--collapse {
-      .el-submenu {
-        & > .el-submenu__title {
-          & > span {
-            height: 0;
-            width: 0;
-            overflow: hidden;
-            visibility: hidden;
-            display: inline-block;
-          }
-        }
+      .el-menu-item span,
+      .el-submenu > .el-submenu__title span {
+        height: 0;
+        width: 0;
+        overflow: hidden;
+        visibility: hidden;
+        display: inline-block;
       }
-    }
-  }
-  .el-menu--collapse .el-menu .el-submenu {
-    min-width: $sideBarWidth !important;
-  }
-  // mobile responsive
-  .mobile {
-    .main-container {
-      margin-left: 0px;
-    }
-    .sidebar-container {
-      transition: transform 0.28s;
-      width: $sideBarWidth !important;
-    }
-    &.hideSidebar {
-      .sidebar-container {
-        pointer-events: none;
-        transition-duration: 0.3s;
-        transform: translate3d(-$sideBarWidth, 0, 0);
+      .el-menu-item .el-submenu__icon-arrow,
+      .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
+        display: none;
       }
     }
   }
-  .withoutAnimation {
-    .main-container,
-    .sidebar-container {
-      transition: none;
-    }
-  }
-}
-
-// when menu collapsed
-.el-menu--vertical {
-  & > .el-menu {
-    .svg-icon {
-      margin-right: 16px;
-    }
-  }
-  .nest-menu .el-submenu > .el-submenu__title,
-  .el-menu-item {
-    &:hover {
-      // you can use $subMenuHover
-      background-color: $menuHover !important;
-    }
-  }
-  // the scroll bar appears when the subMenu is too long
-  > .el-menu--popup {
-    max-height: 100vh;
-    overflow-y: auto;
-    &::-webkit-scrollbar-track-piece {
-      background: #d3dce6;
-    }
-    &::-webkit-scrollbar {
-      width: 6px;
-    }
-    &::-webkit-scrollbar-thumb {
-      background: #99a9bf;
-      border-radius: 20px;
-    }
-  }
 }

+ 16 - 16
src/styles/variables.scss

@@ -1,12 +1,12 @@
 // base color
-$blue:#324157;
-$light-blue:#3A71A8;
-$red:#C03639;
-$pink: #E65D6E;
-$green: #30B08F;
-$tiffany: #4AB7BD;
-$yellow:#FEC171;
-$panGreen: #30B08F;
+$blue: #324157;
+$light-blue: #3a71a8;
+$red: #c03639;
+$pink: #e65d6e;
+$green: #30b08f;
+$tiffany: #4ab7bd;
+$yellow: #fec171;
+$panGreen: #30b08f;
 
 // sidebar
 // $menuText:#757993;       //未选中字体颜色
@@ -15,20 +15,20 @@ $panGreen: #30B08F;
 // $menuActiveText:#ffffff;         //选中字体颜色
 // $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
 
-$menuText:#666666;       //未选中字体颜色
-$menuActiveText:#fff ;         //选中字体颜色
-$subMenuActiveText:#fff; // https://github.com/ElemeFE/element/issues/12951
+$menuText: #666666; //未选中字体颜色
+$menuActiveText: #fff; //选中字体颜色
+$subMenuActiveText: #fff; // https://github.com/ElemeFE/element/issues/12951
 
 //$menuBg:#f0f3f7;
-// $menuBg:#22242f; 
+// $menuBg:#22242f;
 // $menuHover:#22242f;
-$menuBg:#ffffff;    //   菜单背景色
-$menuHover:#ffffff;
+$menuBg: #ffffff; //   菜单背景色
+$menuHover: #000;
 
 // $subMenuBg:#1f2d3d;
 // $subMenuHover:#001528;
-$subMenuBg:#AE8877;
-$subMenuHover:#AE8877;
+$subMenuBg: #ae8877;
+$subMenuHover: #fff;
 
 $sideBarWidth: 120px;
 

+ 6 - 4
src/styles/variablesSingleLayer.scss

@@ -14,15 +14,17 @@ $panGreen: #30b08f;
 // //$menuActiveText:#f27158;
 // $menuActiveText:#ffffff;         //选中字体颜色
 // $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
-$menuText: #666666; //未选中字体颜色
-$menuActiveText: #ae8877; //选中字体颜色
-$subMenuActiveText: #ae8877; // https://github.com/ElemeFE/element/issues/12951
+$menuText: #fff; //未选中字体颜色
+$menuActiveText: #fff; //选中字体颜色
+$menuActiveBg: #000; //选中字体颜色
+$subMenuText: #303133;
+$subMenuActiveText: #fff; // https://github.com/ElemeFE/element/issues/12951
 
 //$menuBg:#f0f3f7;
 // $menuBg:#22242f;    //   菜单背景色
 // $menuHover:#22242f;
 $menuBg: #ffffff; //   菜单背景色
-$menuHover: #ffffff;
+$menuHover: #000;
 
 // $subMenuBg:#1f2d3d;
 // $subMenuHover:#001528;

+ 19 - 4
src/utils/downloadUtil.js

@@ -1,10 +1,26 @@
+import { Message } from 'element-ui'
+
 export default {
   // 新增视频下载方法
   async videoDownload(url, fileName) {
     try {
+      // 检查URL是否合法
+      if (!url) {
+        Message.error('下载地址不能为空');
+        return false;
+      }
+
+      // 检查文件类型
+      const fileType = url.toLowerCase().split('.').pop();
+      if (!['mp4', 'mov'].includes(fileType)) {
+        Message.error('只支持下载 MP4 或 MOV 格式的文件');
+        return false;
+      }
+
       const response = await fetch(url);
       if (!response.ok) {
-        throw new Error('下载失败');
+        Message.error('下载失败');
+        return false;
       }
 
       const blob = await response.blob();
@@ -15,11 +31,10 @@ export default {
       $link.click();
       document.body.removeChild($link);
       URL.revokeObjectURL($link.href);
-
       return true;
     } catch (error) {
-      console.error('视频下载错误:', error);
-      throw new Error('视频下载失败');
+      Message.error(error);
+      return false;
     }
   }
 }

+ 24 - 10
src/utils/index.js

@@ -23,7 +23,7 @@ export function parseTime(time, cFormat) {
   const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
     let value = formatObj[key];
     // Note: getDay() returns 0 on Sunday
-    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
+    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
     if (result.length > 0 && value < 10) {
       value = '0' + value
     }
@@ -243,7 +243,7 @@ export function getTime(type) {
 export function debounce(func, wait, immediate) {
   let timeout, args, context, timestamp, result;
 
-  const later = function() {
+  const later = function () {
     // 据上一次触发时间间隔
     const last = +new Date() - timestamp;
 
@@ -260,7 +260,7 @@ export function debounce(func, wait, immediate) {
     }
   };
 
-  return function(...args) {
+  return function (...args) {
     context = this;
     timestamp = +new Date();
     const callNow = immediate && !timeout;
@@ -312,10 +312,24 @@ export function randomString(len) {
 
 
 //排序
-export function sortKey(array,key){
-    return array.sort(function(a,b){
-      var x = a[key];
-      var y = b[key];
-      return ((x<y)?-1:(x>y)?1:0)
-    });
- }
+export function sortKey(array, key) {
+  return array.sort(function (a, b) {
+    var x = a[key];
+    var y = b[key];
+    return ((x < y) ? -1 : (x > y) ? 1 : 0)
+  });
+}
+
+/**
+ * 根据key和options匹配对应的value
+ * @param {String|Number} key 需要匹配的键值
+ * @param {Array} options 选项数组,格式为 [{value: 1, label: '选项1'}, ...]
+ * @param {String} valueKey 选项值的键名,默认为 'value'
+ * @param {String} labelKey 选项标签的键名,默认为 'label'
+ * @returns {String|undefined} 匹配到的标签值
+ */
+export function getValueByKey(key, options = [], valueKey = 'value', labelKey = 'label') {
+  if (key === undefined || key === null || !options.length) return '';
+  const target = options.find(item => item[valueKey] === key);
+  return target ? target[labelKey] : '';
+}

+ 14 - 14
src/utils/request.js

@@ -39,20 +39,20 @@ service.interceptors.response.use(
         res = JSON.parse(res)
       }
       // 用户模块  先隐藏
-      // if (res.code === 401) {
-      //   Message.closeAll();
-      //   MessageBox.confirm(res.msg, '确定登出', {
-      //     confirmButtonText: '重新登录',
-      //     cancelButtonText: '取消',
-      //     type: 'warning'
-      //   }).then(() => {
-      //     store.dispatch('FedLogOut').then(() => {
-      //       location.reload() // 为了重新实例化vue-router对象 避免bug
-      //     })
-      //   })
-      // } else {
-      //   return Promise.reject('error');
-      // }
+      if (res.code === 401) {
+        Message.closeAll();
+        MessageBox.confirm(res.msg, '确定登出', {
+          confirmButtonText: '重新登录',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          store.dispatch('FedLogOut').then(() => {
+            location.reload() // 为了重新实例化vue-router对象 避免bug
+          })
+        })
+      } else {
+        return Promise.reject('error');
+      }
     } else {
       return response.data
     }

+ 24 - 23
src/views/login/index.vue

@@ -161,29 +161,29 @@ export default {
       });
     },
     handleLogin() {
-      this.$router.push({
-        path: "/",
-        query: this.otherQuery
-      });
-      // this.$refs.loginForm.validate(valid => {
-      //   if (valid) {
-      //     this.loading = true;
-      //     this.$store
-      //       .dispatch("user/login", this.loginForm)
-      //       .then(() => {
-      //         this.$router.push({
-      //           path: this.redirect || "/",
-      //           query: this.otherQuery
-      //         });
-      //         this.loading = false;
-      //       })
-      //       .catch(() => {
-      //         this.loading = false;
-      //       });
-      //   } else {
-      //     return false;
-      //   }
+      // this.$router.push({
+      //   path: "/",
+      //   query: this.otherQuery
       // });
+      this.$refs.loginForm.validate(valid => {
+        if (valid) {
+          this.loading = true;
+          this.$store
+            .dispatch("user/login", this.loginForm)
+            .then(() => {
+              this.$router.push({
+                path: this.redirect || "/",
+                query: this.otherQuery
+              });
+              this.loading = false;
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+        } else {
+          return false;
+        }
+      });
     },
     getOtherQuery(query) {
       return Object.keys(query).reduce((acc, cur) => {
@@ -265,6 +265,7 @@ input::-webkit-input-placeholder {
       object-fit: cover;
       object-position: 41%;
       border-radius: 10px 0px 0px 10px;
+      box-shadow: -5px 5px 10px rgba(0, 0, 0, 0.4);
     }
   }
   .login-form {
@@ -273,7 +274,7 @@ input::-webkit-input-placeholder {
     height: 513px;
     background: rgba(255, 255, 255, 0.8);
     border-radius: 0px 10px 10px 0px;
-    opacity: 1;
+    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.4);
   }
   .login-btn {
     width: 100%;

+ 140 - 74
src/views/video/oral-video.vue

@@ -62,8 +62,6 @@
       fit
       highlight-current-row
     >
-      <el-table-column align="center" type="index" />
-
       <el-table-column
         label="视频ID"
         min-width="100"
@@ -75,8 +73,20 @@
         label="视频标题"
         min-width="150"
         align="center"
-        prop="actAmount"
+        prop="videoTitle"
+      />
+      <el-table-column
+        label="视频封面"
+        min-width="110"
+        align="center"
+        prop="videoImg"
       >
+        <template slot-scope="scope">
+          <div class="video" @click="handlePlay(scope.row)">
+            <img :src="scope.row.videoImg" class="video-img" />
+            <i class="el-icon-video-play" />
+          </div>
+        </template>
       </el-table-column>
       <el-table-column label="SKU" min-width="100" align="center" prop="sku" />
 
@@ -86,48 +96,51 @@
         align="center"
         prop="skuId"
       />
-      <!-- <el-table-column
+      <el-table-column
         label="审核状态"
         min-width="100"
         align="center"
-        prop="reserveAmount"
-      />
+        prop="reviewStatus"
+      >
+        <template slot-scope="scope">
+          {{ getValueByKey(scope.row.reviewStatus, auditStatus) }}
+        </template>
+      </el-table-column>
+
       <el-table-column
         label="审核时间"
         min-width="100"
         align="center"
-        prop="reserveAmount"
+        prop="reviewTime"
       />
       <el-table-column
         label="审核人"
         min-width="100"
         align="center"
-        prop="reserveAmount"
+        prop="reviewer"
       />
       <el-table-column
         label="发布状态"
         min-width="100"
         align="center"
-        prop="reserveAmount"
-      />
+        prop="publishStatus"
+      >
+        <template slot-scope="scope">
+          {{ getValueByKey(scope.row.publishStatus, auditStatus) }}
+        </template>
+      </el-table-column>
       <el-table-column
         label="发布时间"
         min-width="100"
         align="center"
-        prop="reserveAmount"
+        prop="publishTime"
       />
       <el-table-column
         label="发布人"
         min-width="100"
         align="center"
-        prop="reserveAmount"
+        prop="publisher"
       />
-      <el-table-column
-        label="审核状态"
-        min-width="100"
-        align="center"
-        prop="reserveAmount"
-      /> -->
       <el-table-column
         label="关联热词"
         min-width="100"
@@ -141,12 +154,12 @@
         align="center"
         prop="liveTime"
       />
-      <el-table-column
+      <!-- <el-table-column
         label="直播场次"
         min-width="100"
         align="center"
         prop="liveSession"
-      />
+      /> -->
       <el-table-column
         label="直播中控"
         min-width="120"
@@ -174,25 +187,41 @@
         align="center"
         prop="createTime"
       />
-      <el-table-column label="操作" align="center" min-width="80" fixed="right">
+      <el-table-column
+        label="操作"
+        align="center"
+        min-width="250"
+        fixed="right"
+      >
         <template slot-scope="scope">
-          <el-button
-            type="danger"
-            size="mini"
-            @click="handleDownload(scope.row)"
-          >
-            下载
-          </el-button>
-          <el-button type="danger" size="mini" @click="handlePlay(scope.row)">
-            播放
-          </el-button>
-          <el-button
-            type="danger"
-            size="mini"
-            @click="handleDelete(scope.row.id)"
-          >
-            删除
-          </el-button>
+          <div class="button">
+            <el-button
+              type="primary"
+              :loading="
+                scope.row && scope.row.id
+                  ? downloadingRows[scope.row.id]
+                  : false
+              "
+              size="mini"
+              @click="handleDownload(scope.row)"
+            >
+              下载
+            </el-button>
+            <el-button
+              type="success"
+              size="mini"
+              @click="handlePlay(scope.row)"
+            >
+              播放
+            </el-button>
+            <el-button
+              type="danger"
+              size="mini"
+              @click="handleDelete(scope.row.id)"
+            >
+              删除
+            </el-button>
+          </div>
         </template>
       </el-table-column>
     </el-table>
@@ -206,13 +235,22 @@
       pos="btmRight"
       @retPage="retPage"
     />
+    <!-- 视频播放 -->
+    <video-player
+      ref="videoPlayer"
+      :video-url="currentVideoUrl"
+      :video-title="currentVideoTitle"
+      @close="handlePlayerClose"
+    />
   </div>
 </template>
 
 <script>
 import waves from "@/directive/waves";
 import swPage from "@/views/common/swPage";
-import { getToken } from "@/utils/auth";
+import { auditStatus } from "@/constants/index";
+import { getValueByKey } from "@/utils/index";
+// import { getToken } from "@/utils/auth";
 import { fetchOralVideoList, deleteOralVideoList } from "@/api/video";
 import downloadUtil from "@/utils/downloadUtil";
 import VideoPlayer from "@/components/VideoPlayer";
@@ -228,52 +266,33 @@ export default {
   },
   data() {
     return {
+      auditStatus,
       tableKey: 0,
       list: [],
       total: 0,
       listLoading: false,
-      uploadVisible: false,
-      uploadData: {
-        warehouseCode: ""
-      },
-      //TODO 下载路径
-      uploadUrl: process.env.VUE_APP_OMS_API + "/inventory/uploadExcel",
+      downloadingRows: {},
       listQuery: {
         page: 1,
         limit: 20,
-        skuCode: "",
-        partnumber: "",
-        warehouseId: null
+        videoTitle: null
       },
-      //仓库列表
-      warehouses: [],
-      dataWarehouses: [],
-      baseURL: process.env.VUE_APP_OMS_API //把url前面的域名拿出来
+      currentVideoUrl: null,
+      currentVideoTitle: null
     };
   },
   //页面创建的时候执行
   created() {
-    // this.getList();
-    // this.getWareHouseInfo();
-  },
-  computed: {
-    // 计算属性的 getter
-    headers: function() {
-      return {
-        "X-Token": getToken()
-      };
-    }
+    this.getList();
   },
   methods: {
+    getValueByKey,
     getList() {
       this.listLoading = true;
-      if (!this.listQuery.warehouseId) {
-        this.listQuery.warehouseId = null;
-      }
       fetchOralVideoList(this.listQuery).then(res => {
         if (200 == res.code) {
           this.total = res.data.total;
-          this.list = res.data.list;
+          this.list = res.data.rows;
         }
         this.listLoading = false;
       });
@@ -288,22 +307,31 @@ export default {
     },
     // 视频下载
     async handleDownload(row) {
-      const { videoUrl, videoName } = row;
+      const { videoUrl, videoTitle, id, sku } = row;
+      this.$set(this.downloadingRows, id, true);
       try {
-        await downloadUtil.videoDownload(videoUrl, videoName);
-        this.$message.success("下载成功");
+        const title = sku ? videoTitle + "_" + sku : videoTitle;
+        const res = await downloadUtil.videoDownload(videoUrl, title);
+        if (res) {
+          this.$message.success("下载成功");
+        }
       } catch (error) {
         this.$message.error(error.message);
+      } finally {
+        this.$set(this.downloadingRows, id, false);
       }
     },
     // 视频播放
     handlePlay(row) {
-      if (!row.videoUrl) {
+      const { videoUrl, videoTitle } = row;
+      ``;
+      if (!videoUrl) {
         this.$message.error("视频地址不存在");
         return;
       }
-      this.currentVideoUrl = row.videoUrl;
-      this.currentVideoTitle = row.videoTitle || "视频播放";
+      this.currentVideoUrl =
+        "https://cdn.shopify.com/videos/c/o/v/a1f2197c35ed4c4985f953af47cb68f0.mp4";
+      this.currentVideoTitle = videoTitle;
       this.$refs.videoPlayer.show();
     },
     handlePlayerClose() {
@@ -312,12 +340,13 @@ export default {
     },
     handleDelete(row) {
       //删除
-      this.$confirm("是否删除该记录?", "提示", {
+      this.$confirm("是否删除该视频?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
       }).then(() => {
-        deleteOralVideoList(row.id).then(() => {
+        const { id } = row;
+        deleteOralVideoList({ idList: [id] }).then(() => {
           this.$notify({
             title: "成功",
             message: "删除成功",
@@ -335,4 +364,41 @@ export default {
 
 <style rel="stylesheet/scss" lang="scss" scoped>
 @import "../../styles/layout.scss";
+.button {
+  .el-button {
+    margin-bottom: 10px;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+.video {
+  position: relative;
+  display: flex;
+  align-content: center;
+  justify-content: center;
+  &-img {
+    width: 60px;
+    height: 60px;
+    border: 1px solid #eee;
+    object-fit: cover;
+    cursor: pointer;
+  }
+  i {
+    width: 60px;
+    height: 60px;
+    position: absolute;
+    top: 85%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    font-size: 20px;
+    font-weight: bold;
+    color: #ae8877;
+    opacity: 0;
+    cursor: pointer;
+    &:hover {
+      opacity: 1;
+    }
+  }
+}
 </style>

BIN
static/login/img/goelia-bg1.png


BIN
static/login/img/goelie-b.png


+ 1 - 1
vue.config.js

@@ -52,7 +52,7 @@ module.exports = {
       //   }
       // }
       "/": {
-        target: "http://10.41.3.106:9093/app/backstage",
+        target: "http://10.41.3.106:9093/app",
         changeOrigin: true
       },
     }