Przeglądaj źródła

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_scrm_adminUI

caoliqin 1 miesiąc temu
rodzic
commit
aa781d9ee4

+ 45 - 0
src/api/course/videoResource.js

@@ -0,0 +1,45 @@
+import request from '@/utils/request'
+
+// 查询视频资源列表
+export function listVideoResource(query) {
+  return request({
+    url: '/course/videoResource/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询视频资源详细
+export function getVideoResource(resourceId) {
+  return request({
+    url: '/course/videoResource/' + resourceId,
+    method: 'get'
+  })
+}
+
+// 新增视频资源
+export function addVideoResource(data) {
+  return request({
+    url: '/course/videoResource',
+    method: 'post', 
+    data: data
+  })
+}
+
+// 修改视频资源
+export function updateVideoResource(data) { 
+  return request({
+    url: '/course/videoResource',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除视频资源
+export function deleteVideoResource(resourceId) {
+  return request({
+    url: '/course/videoResource/' + resourceId,
+    method: 'delete'
+  })
+}
+

+ 167 - 10
src/components/VideoUpload/index.vue

@@ -16,8 +16,8 @@
         >
           <el-button slot="trigger" size="small" type="primary" >选取视频</el-button>
           <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">点击上传</el-button>
-<!--          <el-progress style="margin-top: 10px;" :key="'线路一'" class="progress" :text-inside="true" :stroke-width="18" :percentage="txProgress" status="success"></el-progress>-->
-<!--          <el-progress style="margin-top: 10px;" :key="'线路二'" class="progress" :text-inside="true" :stroke-width="18" :percentage="hwProgress" status="success"></el-progress>-->
+          <!-- 仅当showControl为true时显示视频库选取按钮 -->
+          <el-button v-if="showControl" style="margin-left: 10px;" size="small" type="success" @click="openVideoLibrary">视频库选取</el-button>
           <!-- 线路一 -->
           <div class="progress-container">
             <span class="progress-label">线路一</span>
@@ -53,13 +53,71 @@
       <div v-if="fileKey">文件Key: {{ fileKey }}</div>
       <div v-if="fileSize">文件大小(MB): {{ (fileSize / (1024 * 1024)).toFixed(2) }} MB</div>
     </el-form-item>
-    <el-form-item label="播放线路"  >
+    <!-- 仅当showControl为true时显示播放线路选择器 -->
+    <el-form-item v-if="showControl" label="播放线路">
       <el-radio-group v-model="localUploadType">
         <el-radio :label="1" >线路一</el-radio>
         <el-radio :label="2" >线路二</el-radio>
         <!--        <el-radio :label="3" >线路三</el-radio>-->
       </el-radio-group>
     </el-form-item>
+
+    <!-- 视频库选择对话框 -->
+    <el-dialog title="视频库选择" :visible.sync="libraryOpen" width="900px" append-to-body>
+      <!-- 搜索条件 -->
+      <el-form :inline="true" :model="libraryQueryParams" class="library-search">
+        <el-form-item label="素材名称">
+          <el-input
+            v-model="libraryQueryParams.resourceName"
+            placeholder="请输入素材名称"
+            clearable
+            size="small"
+            @keyup.enter.native="handleLibraryQuery"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleLibraryQuery">搜索</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetLibraryQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <!-- 视频列表 -->
+      <el-table v-loading="libraryLoading" :data="libraryList" @row-click="handleLibrarySelect" highlight-current-row>
+        <el-table-column label="素材名称" align="center" prop="resourceName" />
+        <el-table-column label="文件名称" align="center" prop="fileName" />
+        <el-table-column label="缩略图" align="center">
+          <template slot-scope="scope">
+            <el-popover
+              placement="right"
+              title=""
+              trigger="hover"
+            >
+              <img alt="" slot="reference" :src="scope.row.thumbnail" style="width: 80px; height: 50px" />
+              <img alt="" :src="scope.row.thumbnail" style="max-width: 150px;" />
+            </el-popover>
+          </template>
+        </el-table-column>
+        <el-table-column label="视频时长" align="center">
+          <template slot-scope="scope">
+            <span>{{ formatDuration(scope.row.duration) }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 分页 -->
+      <pagination
+        v-show="libraryTotal>0"
+        :total="libraryTotal"
+        :page.sync="libraryQueryParams.pageNum"
+        :limit.sync="libraryQueryParams.pageSize"
+        @pagination="getLibraryList"
+      />
+
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="confirmVideoSelection">确 定</el-button>
+        <el-button @click="cancelVideoSelection">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -69,8 +127,13 @@ import {getThumbnail} from "@/api/course/userVideo";
 import TcVod from "vod-js-sdk-v6";
 import { uploadObject } from "@/utils/cos.js";
 import { uploadToOBS } from "@/utils/obs.js";
+import Pagination from "@/components/Pagination";
+import { listVideoResource } from '@/api/course/videoResource';
 
 export default {
+  components: {
+    Pagination
+  },
   props: {
     videoUrl: {
       type: String,
@@ -116,6 +179,12 @@ export default {
       type: Number,
       default: 0,
     },
+
+    // 使用一个变量控制显示,默认为true显示所有控制项
+    showControl: {
+      type: Boolean,
+      default: true,
+    }
   },
   data() {
     return {
@@ -125,8 +194,8 @@ export default {
       duration: 0,
       fileId: "",
       uploadTypeOptions: [
-        { dictLabel: "线路一", dictValue: 1 }, //腾讯pcdn
-        { dictLabel: "线路二", dictValue: 2 }, //华为云obs
+        { dictLabel: "线路一", dictValue: 1 }, // 腾讯pcdn
+        { dictLabel: "线路二", dictValue: 2 }, // 华为云obs
         // { dictLabel: "华为云VOD", dictValue: 4 },
         // { dictLabel: "腾讯云VOD", dictValue: 5 },
       ],
@@ -135,7 +204,17 @@ export default {
       hwProgress: 0,
       uploadLoading: false,
       uploadKey: 0,
-      // thumbnail: '',
+      // 视频库选择相关数据
+      libraryOpen: false,
+      libraryLoading: false,
+      libraryTotal: 0,
+      libraryList: [],
+      selectedVideo: null,
+      libraryQueryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        resourceName: null
+      }
     };
   },
   watch: {
@@ -148,10 +227,15 @@ export default {
     },
   },
   methods: {
+    // 打开视频库对话框
+    openVideoLibrary() {
+      this.libraryOpen = true;
+      this.selectedVideo = null;
+      this.getLibraryList();
+    },
     handleChange(file, fileList) {
       this.fileList = fileList;
       this.getVideoDuration(file.raw);
-
     },
     getVideoDuration(file) {
       const video = document.createElement("video");
@@ -242,12 +326,77 @@ export default {
       console.log(file, fileList.length);
     },
     resetUpload() {
+      // 重置内部状态
       this.txProgress = 0;
-      this.hwProgress=0;
+      this.hwProgress = 0;
       this.fileList = [];
       this.uploadKey++;
     },
-  },
+    /** 查询视频库列表 */
+    getLibraryList() {
+      this.libraryLoading = true;
+      listVideoResource(this.libraryQueryParams).then(response => {
+        this.libraryList = response.rows;
+        this.libraryTotal = response.total;
+        this.libraryLoading = false;
+      });
+    },
+    /** 搜索视频库按钮操作 */
+    handleLibraryQuery() {
+      this.libraryQueryParams.pageNum = 1;
+      this.getLibraryList();
+    },
+    /** 重置视频库查询按钮操作 */
+    resetLibraryQuery() {
+      this.libraryQueryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        resourceName: null
+      };
+      this.handleLibraryQuery();
+    },
+    /** 视频库选择行点击 */
+    handleLibrarySelect(row) {
+      this.selectedVideo = row;
+    },
+    /** 格式化视频时长 */
+    formatDuration(seconds) {
+      if (!seconds) return '00:00';
+
+      const minutes = Math.floor(seconds / 60);
+      const remainingSeconds = seconds % 60;
+
+      return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+    },
+    /** 确认选择视频 */
+    confirmVideoSelection() {
+      if (!this.selectedVideo) {
+        this.$message.warning("请选择一个视频");
+        return;
+      }
+
+      // 更新组件内部数据
+      this.$emit("update:fileName", this.selectedVideo.fileName);
+      this.$emit("update:thumbnail", this.selectedVideo.thumbnail);
+      this.$emit("update:line_1", this.selectedVideo.line1);
+      this.$emit("update:line_2", this.selectedVideo.line2);
+      this.$emit("update:line_3", this.selectedVideo.line3);
+      this.$emit("update:fileSize", this.selectedVideo.fileSize);
+      this.$emit("update:fileKey", this.selectedVideo.fileKey);
+      this.$emit("update:uploadType", this.selectedVideo.uploadType);
+      this.$emit("video-duration", this.selectedVideo.duration);
+
+      // 设置预览URL
+      this.$emit("update:videoUrl", this.selectedVideo.videoUrl);
+
+      this.libraryOpen = false;
+    },
+    /** 取消视频选择 */
+    cancelVideoSelection() {
+      this.libraryOpen = false;
+      this.selectedVideo = null;
+    }
+  }
 };
 </script>
 
@@ -258,9 +407,17 @@ export default {
 
 .progress-label {
   display: block;
-  //margin-bottom: 5px;
   font-weight: bold;
   font-size: 13px;
   color: #303331; /* 标签颜色,可以根据需要调整 */
 }
+
+/* 视频库选择对话框样式 */
+.library-search {
+  margin-bottom: 15px;
+}
+
+.el-table .el-table__row:hover {
+  cursor: pointer;
+}
 </style>

+ 343 - 0
src/views/course/videoResource/index.vue

@@ -0,0 +1,343 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="素材名称" prop="resourceName">
+        <el-input
+          v-model="queryParams.resourceName"
+          placeholder="请输入素材名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:resource:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:resource:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:resource:remove']"
+        >删除</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="resourceList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="主键ID" align="center" prop="id" />
+      <el-table-column label="素材名称" align="center" prop="resourceName" />
+      <el-table-column label="文件名称" align="center" prop="fileName" />
+      <el-table-column label="缩略图" align="center">
+        <template slot-scope="scope">
+          <el-popover
+              placement="right"
+              title=""
+              trigger="hover"
+          >
+            <img alt="" slot="reference" :src="scope.row.thumbnail" style="width: 80px; height: 50px" />
+            <img alt="" :src="scope.row.thumbnail" style="max-width: 150px;" />
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="文件大小" align="center">
+        <template slot-scope="scope">
+          <span>{{ (scope.row.fileSize / (1024 * 1024)).toFixed(2) }} MB</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="视频时长" align="center">
+        <template slot-scope="scope">
+          <span>{{ formatDuration(scope.row.duration) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:resource:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:resource:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改视频素材库对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="素材名称" prop="resourceName">
+          <el-input v-model="form.resourceName" placeholder="请输入素材名称" />
+        </el-form-item>
+
+        <!-- 使用VideoUpload组件 -->
+        <video-upload
+          ref="videoUpload"
+          :type = "1"
+          :isPrivate = "1"
+          :video-url.sync="form.videoUrl"
+          :file-key.sync="form.fileKey"
+          :file-size.sync="form.fileSize"
+          :file-name.sync="form.fileName"
+          :line_1.sync="form.line1"
+          :line_2.sync="form.line2"
+          :line_3.sync="form.line3"
+          :thumbnail.sync="form.thumbnail"
+          :upload-type.sync="form.uploadType"
+          :show-control="false"
+          @video-duration="handleVideoDuration"
+        ></video-upload>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listVideoResource, getVideoResource, addVideoResource, updateVideoResource, deleteVideoResource } from '@/api/course/videoResource'
+import VideoUpload from '@/components/VideoUpload'
+
+export default {
+  name: 'VideoResource',
+  components: {
+    VideoUpload
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 视频素材库表格数据
+      resourceList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        resourceName: null
+      },
+      // 表单参数
+      form: {
+        id: null,
+        resourceName: null,
+        fileName: null,
+        thumbnail: null,
+        line1: null,
+        line2: null,
+        line3: null,
+        duration: null,
+        uploadType: null,
+        fileSize: null,
+        fileKey: null,
+        videoUrl: null
+      },
+      // 表单校验
+      rules: {
+        resourceName: [
+          { required: true, message: "素材名称不能为空", trigger: "blur" }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询视频素材库列表 */
+    getList() {
+      this.loading = true;
+      listVideoResource(this.queryParams).then(response => {
+        this.resourceList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        resourceName: null,
+        fileName: null,
+        thumbnail: null,
+        line1: null,
+        line2: null,
+        line3: null,
+        duration: null,
+        uploadType: null,
+        fileSize: null,
+        fileKey: null,
+        videoUrl: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加视频素材库";
+      // 打开对话框后,使用nextTick确保组件已渲染
+      this.$nextTick(() => {
+        if (this.$refs.videoUpload) {
+          this.$refs.videoUpload.resetUpload();
+        }
+      });
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getVideoResource(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改视频素材库";
+        // 打开对话框后,使用nextTick确保组件已渲染
+        this.$nextTick(() => {
+          if (this.$refs.videoUpload) {
+            this.$refs.videoUpload.resetUpload();
+          }
+        });
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateVideoResource(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          } else {
+            addVideoResource(this.form).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              }
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除视频素材库编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return deleteVideoResource(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 处理视频时长 */
+    handleVideoDuration(duration) {
+      this.form.duration = duration;
+    },
+    /** 格式化视频时长 */
+    formatDuration(seconds) {
+      if (!seconds) return '00:00';
+
+      const minutes = Math.floor(seconds / 60);
+      const remainingSeconds = seconds % 60;
+
+      return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
+    }
+  }
+}
+</script>
+
+<style>
+/* 自定义表格样式 */
+.el-table .video-cell {
+  padding: 5px;
+}
+
+/* 设置删除和修改按钮的间距 */
+.el-button + .el-button {
+  margin-left: 5px;
+}
+</style>