Browse Source

音频管理,视频管理

cxmo 7 months ago
parent
commit
8413d4d89a

+ 111 - 0
src/components/ImageUpload.vue

@@ -0,0 +1,111 @@
+<script setup>
+import { ref, reactive, watch } from 'vue'
+import { Plus } from '@element-plus/icons-vue'
+
+const props = defineProps({
+    width:{
+        type:String,
+        default:'120px'
+    },
+    height:{
+        type:String,
+        default:'120px'
+    },
+    imgUrl:{
+        type:String,
+        default:''
+    },
+    text:{
+        type:String,
+        default:'点击上传图片'
+    }
+})
+
+let uploadKey = ref(0)
+
+const emits = defineEmits(['upload','remove','showImage'])
+function handleUploadImg(file) {
+    emits('upload', file)
+}
+function handleRemove() {
+    emits('remove')
+}
+function showImage(){
+    emits('showImage',[this.imgUrl])
+}
+</script>
+
+<template>
+    <el-upload action="" accept="image/*" :http-request="handleUploadImg" :show-file-list="false"
+        :key="uploadKey">
+        <div class="upload-box" :style="{'width':props.width,'height':props.height}">
+            <template v-if="!imgUrl.length">
+                <!-- <i class="el-icon-plus" style="font-size: 24px;"></i> -->
+                <el-icon :size="24"><Plus /></el-icon>
+                <p class="form-hint">{{ text }}</p>
+            </template>
+            <template v-else>
+                <img class="upload-img" :src="imgUrl" alt="配图">
+                <span class="upload-mask" @click.stop="showImage">
+                    <span class="mask-icon" @click.stop="handleRemove">
+                        <i class="el-icon-delete"></i>
+                    </span>
+                </span>
+            </template>
+        </div>
+    </el-upload>
+</template>
+
+<style scoped lang="scss">
+.el-upload {
+        .upload-box {
+            position: relative;
+            /* width: 120px;
+            height: 120px; */
+            background-color: #F5F7F9;
+            border: 1px dashed #DCDFE6;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            box-sizing: border-box;
+            padding: 4px;
+            overflow: hidden;
+
+            &:hover {
+                border: 1px dashed #3375e1;
+
+                .upload-mask {
+                    opacity: 1;
+                }
+            }
+            .form-hint {
+                margin-top: 10px;
+                color: #999999;
+            }
+
+            .upload-img,
+            .upload-mask {
+                width: 100%;
+                height: 100%;
+            }
+            .upload-mask {
+                position: absolute;
+                left: 0;
+                top: 0;
+                cursor: default;
+                text-align: center;
+                color: #fff;
+                opacity: 0;
+                font-size: 20px;
+                background-color: rgba(0, 0, 0, .5);
+                transition: opacity .3s;
+                z-index: 2;
+                line-height: 120px;
+                .mask-icon {
+                    cursor: pointer;
+                }
+            }
+        }
+    }
+</style>

+ 15 - 3
src/styles/element.scss

@@ -5,18 +5,30 @@
     background-color: var(--el-color-primary);
     padding: var(--el-dialog-padding-primary);
     color: #fff;
+    position: relative;
 
     .el-dialog__title {
       color: #fff;
+      font-size: 16px;
     }
 
-    .el-dialog__headerbtn .el-dialog__close {
-      color: #fff;
+    .el-dialog__headerbtn {
+        top: 50%;
+        transform: translateY(-50%);
+        font-size: 22px;
+        .el-dialog__close {
+            color: #fff;
+        }
     }
   }
 
   .el-dialog__body {
-    padding: var(--el-dialog-padding-primary);
+    padding: 30px 60px;
+    padding-bottom: 0;
+  }
+  .el-dialog__footer{
+    padding: 40px;
+    text-align: center;
   }
 }
 

+ 56 - 3
src/views/media/AudioList.vue

@@ -1,13 +1,66 @@
 <script setup>
 import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import MediaUpload from './components/MediaUpload.vue';
+
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+})
+
+const tableColumns = [
+    {label:'音频名称',key:'name',},
+    {label:'研究员',key:'author',},
+    {label:'标签',key:'label',},
+    {label:'添加时间',key:'time',width:250,sortable:true}
+]
+let mediaUploadShow = ref(false)
 </script>
 
 <template>
-    <div>
-        音频管理
+    <div class="audio-list-wrap">
+        <div class="top-box">
+            <el-button @click="mediaUploadShow = true">上传音频</el-button>
+            <el-input style="width:400px;margin-left: auto;" placeholder="音频名称" v-model="tableQuery.keyWord" :prefix-icon="Search" clearable></el-input>
+        </div>
+        <div class="table-box">
+            <el-table stripe border :data="tableData">
+                <el-table-column 
+                    align="center"
+                    v-for="column in tableColumns" :key="column.key"
+                    :prop="column.key" :label="column.label" :sortable="column.sortable" :width="column.width">
+
+                </el-table-column>
+                <el-table-column label="操作">
+
+                </el-table-column>
+            </el-table>
+            <el-pagination
+                background
+                layout="total,prev,pager,next,jumper"
+                :current-page="tableQuery.page"
+                :page-size="tableQuery.pageSize"
+                :total="tableQuery.totals"
+                @current-change="handlePageChange"
+                style=" justify-content: flex-end;border:1px solid #ebeef5;border-top: none;"
+            />
+        </div>
     </div>
+    <MediaUpload
+        v-model:show="mediaUploadShow"
+        mediaType="audio"
+        modifyType="add"
+    ></MediaUpload>
 </template>
 
 <style scoped lang="scss">
-
+.audio-list-wrap{
+    .top-box{
+        display: flex;
+        margin-bottom: 20px;
+    }
+}
 </style>

+ 62 - 3
src/views/media/VideoList.vue

@@ -1,13 +1,72 @@
 <script setup>
 import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import MediaUpload from './components/MediaUpload.vue';
+
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+})
+const tableData = ref([])
+function handlePageChange(){}
+
+const tableColumns = [
+    {label:'视频封面',key:'cover',},
+    {label:'视频名称',key:'name',},
+    {label:'研究员',key:'author',},
+    {label:'标签',key:'label',},
+    {label:'添加时间',key:'time',width:250,sortable:true}
+]
+
+let mediaUploadShow = ref(false)
 </script>
 
 <template>
-    <div>
-        视频管理
+    <div class="video-list-wrap">
+        <div class="top-box">
+            <el-button @click="mediaUploadShow = true">上传视频</el-button>
+            <el-input style="width:400px;margin-left: auto;" placeholder="视频名称" v-model="tableQuery.keyWord" :prefix-icon="Search" clearable></el-input>
+        </div>
+        <div class="table-box">
+            <el-table stripe border :data="tableData">
+                <el-table-column 
+                    align="center"
+                    v-for="column in tableColumns" :key="column.key"
+                    :prop="column.key" :label="column.label" :sortable="column.sortable" :width="column.width">
+
+                </el-table-column>
+                <el-table-column label="操作">
+
+                </el-table-column>
+            </el-table>
+            <el-pagination
+                background
+                layout="total,prev,pager,next,jumper"
+                :current-page="tableQuery.page"
+                :page-size="tableQuery.pageSize"
+                :total="tableQuery.totals"
+                @current-change="handlePageChange"
+                style=" justify-content: flex-end;border:1px solid #ebeef5;border-top: none;"
+            />
+        </div>
     </div>
+    <MediaUpload
+        v-model:show="mediaUploadShow"
+        mediaType="video"
+        modifyType="add"
+        ImageUploadWidth="192px"
+        ImageUploadHeight="108px"
+    ></MediaUpload>
 </template>
 
 <style scoped lang="scss">
-
+.video-list-wrap{
+    .top-box{
+        display: flex;
+        margin-bottom: 20px;
+    }
+}
 </style>

+ 13 - 0
src/views/media/components/MediaPlayer.vue

@@ -0,0 +1,13 @@
+<script setup>
+import { ref, reactive } from 'vue'
+</script>
+
+<template>
+    <div>
+
+    </div>
+</template>
+
+<style scoped lang="scss">
+
+</style>

+ 93 - 0
src/views/media/components/MediaUpload.vue

@@ -0,0 +1,93 @@
+<script setup>
+import { ref, reactive, computed } from 'vue'
+
+
+const show = defineModel('show', { type: Boolean, default: false })
+const props = defineProps({
+    mediaType:{
+        type:String,
+        default:'audio',//audio or video
+    },
+    modifyType:{
+        type:String,
+        default:'add',//add or edit
+    },
+    ImageUploadWidth:{
+        type:String,
+        default:'120px'
+    },
+    ImageUploadHeight:{
+        type:String,
+        default:'120px'
+    },
+})
+const mediaName = computed(()=>{
+    return {'audio':'音频','video':'视频'}[props.mediaType]
+})
+const dialogTitle = computed(()=>{
+    return {'add':'上传','edit':'编辑',}[props.modifyType]+mediaName.value
+})
+
+//点击上传按钮
+const uploadRef = ref(null)
+function handleUpload(){
+    uploadRef.value?.$el.getElementsByTagName('input')[0].click()
+}
+function handleUploadMedia(){}
+
+function handleSave(){}
+</script>
+
+<template>
+    <el-dialog v-model="show" :title="dialogTitle" width="530px" draggable>
+        <div class="content-wrap">
+            <el-form label-width="95px" label-position="left">
+                <el-form-item prop="mediaUrl" class="upload-form-item">
+                    <el-input placeholder="请上传文件">
+                        <template #append>
+                            <el-button @click="handleUpload">上传{{mediaName}}</el-button>
+                            <el-upload
+                                ref="uploadRef"
+                                action=""
+                                accept="application/pdf"
+                                :http-request="handleUploadMedia"
+                                :show-file-list="false"
+                                style="display: flex;"
+                            >
+                            </el-upload>
+                        </template>
+                    </el-input>
+                </el-form-item>
+                <el-form-item label="照片" v-if="props.mediaType==='video'">
+                    <ImageUpload
+                        :width="ImageUploadWidth"
+                        :height="ImageUploadHeight"
+                    ></ImageUpload>
+                </el-form-item>
+                <el-form-item :label="`${mediaName}名称`">
+                    <el-input></el-input>
+                </el-form-item>
+                <el-form-item label="研究员名称">
+                    <el-select></el-select>
+                </el-form-item>
+                <el-form-item label="标签">
+                    <el-cascader style="width: 100%;"></el-cascader>
+                </el-form-item>
+            </el-form>
+        </div>
+        <template #footer>
+            <div class="footer-wrap">
+                <el-button type="primary" plain size="large" @click="show = false">取消</el-button>
+                <el-button type="primary" size="large" @click="handleSave">保存</el-button>
+            </div>
+        </template>
+    </el-dialog>
+</template>
+
+<style scoped lang="scss">
+.content-wrap{
+    .upload-form-item{
+        margin-left: -95px;
+    }
+}
+</style>