|
@@ -0,0 +1,401 @@
|
|
|
+<script setup>
|
|
|
+import { computed, nextTick, onMounted , ref , watch} from 'vue';
|
|
|
+import { useRoute , useRouter} from "vue-router";
|
|
|
+import {apiClassifyList,apiTagList,apiVideoList} from '@/api/trainingVideoApi';
|
|
|
+import { ArrowLeftBold, ArrowRightBold, Search } from '@element-plus/icons-vue';
|
|
|
+import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+let classifyList = ref([]) //分类列表
|
|
|
+let choosedClassify = ref({ClassifyId:0}) //所选分类
|
|
|
+let choosedSubClassify = ref({ClassifyId:0}) //所选二级分类
|
|
|
+let isClassifyListExpand = ref(false) //分类列表是否展开
|
|
|
+let tagList = ref([]) //标签列表
|
|
|
+let choosedTags = ref([]) //所选标签
|
|
|
+let isTagListExpand = ref(false) //标签列表是否展开
|
|
|
+let videoList = ref([]) //视频列表
|
|
|
+let total = ref(0) //视频总数
|
|
|
+let currentIndex = ref(1) //列表页
|
|
|
+let keyword = ref('') //搜索词
|
|
|
+let selectValue = ref('New') //select筛选项
|
|
|
+
|
|
|
+let classifyWidth = 0 //分类列表宽度
|
|
|
+let tagWidth = 0 //标签列表宽度
|
|
|
+let boxWidth = 0 //列表父级的宽度
|
|
|
+
|
|
|
+let beforeMounted = ref(false)
|
|
|
+
|
|
|
+function getClassifyList(){
|
|
|
+ apiClassifyList().then(res=>{
|
|
|
+ if(res.code!==200) return
|
|
|
+ classifyList.value = res.data&&res.data.List||[]
|
|
|
+ nextTick(()=>{
|
|
|
+ classifyWidth = document.querySelector(".classify-box .list").scrollWidth
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+function getTagList(){
|
|
|
+ apiTagList().then(res=>{
|
|
|
+ if(res.code!==200) return
|
|
|
+ tagList.value = res.data||[]
|
|
|
+ nextTick(()=>{
|
|
|
+ tagWidth = document.querySelector(".tag-box .list").scrollWidth
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function changeClassify(classify,type){
|
|
|
+ if(type==='sub'){
|
|
|
+ choosedSubClassify.value = classify
|
|
|
+ choosedClassify.value = classifyList.value.find(i=>i.ClassifyId===classify.ParentId)
|
|
|
+ }else{
|
|
|
+ choosedClassify.value = classify
|
|
|
+ choosedSubClassify.value = {ClassifyId:0}
|
|
|
+ }
|
|
|
+ handleCurrentChange(1)
|
|
|
+}
|
|
|
+
|
|
|
+function changeTags(tag){
|
|
|
+ const {TagId} = tag
|
|
|
+ const index = choosedTags.value.findIndex(i=>i.TagId===TagId)
|
|
|
+ if(index!==-1){
|
|
|
+ choosedTags.value.splice(index,1)
|
|
|
+ }else{
|
|
|
+ choosedTags.value.push(tag)
|
|
|
+ }
|
|
|
+}
|
|
|
+watch(
|
|
|
+ ()=>choosedTags.value.length,
|
|
|
+ ()=>{
|
|
|
+ handleCurrentChange(1)
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+let currentClassifyId = computed(()=>{
|
|
|
+ return choosedSubClassify.value.ClassifyId||choosedClassify.value.ClassifyId
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+function getVideoList(){
|
|
|
+ apiVideoList({
|
|
|
+ page_size:15,
|
|
|
+ current_index:currentIndex.value,
|
|
|
+ keyword:keyword.value,
|
|
|
+ is_new:selectValue.value==='New',
|
|
|
+ is_hot:selectValue.value==='Hot',
|
|
|
+ classify_id:currentClassifyId.value,
|
|
|
+ tag_ids:choosedTags.value.map(i=>i.TagId).join(',')
|
|
|
+ }).then(res=>{
|
|
|
+ if(res.code!==200) return
|
|
|
+ if(res.data){
|
|
|
+ videoList.value = res.data.list||[]
|
|
|
+ total.value = res.data.page.total||0
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+function changePage(type){
|
|
|
+ const page = currentIndex.value
|
|
|
+ if(type==='minus'){
|
|
|
+ if(page===1) return
|
|
|
+ handleCurrentChange(page-1)
|
|
|
+ }
|
|
|
+ if(type==='add'){
|
|
|
+ if(page===Math.ceil(total.value/15)) return
|
|
|
+ handleCurrentChange(page+1)
|
|
|
+ }
|
|
|
+}
|
|
|
+function handleCurrentChange(page){
|
|
|
+ currentIndex.value = page
|
|
|
+ getVideoList()
|
|
|
+}
|
|
|
+
|
|
|
+function gotoVideoDetail(video){
|
|
|
+ const { VideoCode } = video
|
|
|
+ const {bus_code} = route.query
|
|
|
+ router.push({
|
|
|
+ path:'/video/detail',
|
|
|
+ query:{
|
|
|
+ video_code:VideoCode,
|
|
|
+ bus_code:bus_code||''
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(()=>{
|
|
|
+ getClassifyList()
|
|
|
+ getTagList()
|
|
|
+ getVideoList()
|
|
|
+ beforeMounted.value = true
|
|
|
+ boxWidth = document.querySelector(".select").offsetWidth
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="video-list-wrap">
|
|
|
+ <div class="select-wrap">
|
|
|
+ <div class="classify-box select">
|
|
|
+ <span style="align-self:flex-start;white-space: nowrap;padding-top: 8px;">分类:</span>
|
|
|
+ <div class="list" :class="{'expand':isClassifyListExpand}">
|
|
|
+ <span class="list-item" :class="{'active':choosedClassify.ClassifyId===0}"
|
|
|
+ @click="changeClassify({ClassifyId:0})">全部</span>
|
|
|
+ <el-popover v-for="item in classifyList" :key="item.ClassifyId" :width="220">
|
|
|
+ <div class="sub-list" v-if="item.Children.length">
|
|
|
+ <span class="list-item" :class="{'active':choosedSubClassify.ClassifyId===subItem.ClassifyId}"
|
|
|
+ v-for="subItem in item.Children" :key="subItem.ClassifyId"
|
|
|
+ @click="changeClassify(subItem,'sub')">
|
|
|
+ {{subItem.ClassifyName}}</span>
|
|
|
+ </div>
|
|
|
+ <template #reference>
|
|
|
+ <span class="list-item" :class="{'active':choosedClassify.ClassifyId===item.ClassifyId}"
|
|
|
+ @click="changeClassify(item)">{{item.ClassifyName}}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ <div class="expand-btn" v-show="boxWidth<=classifyWidth" @click="isClassifyListExpand = !isClassifyListExpand">
|
|
|
+ {{isClassifyListExpand?'收起':'展开'}}
|
|
|
+ <el-icon :class="{'expand':isClassifyListExpand}"><ArrowRightBold /></el-icon>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="tag-box select">
|
|
|
+ <span style="align-self:flex-start;white-space: nowrap;padding-top: 8px;">标签:</span>
|
|
|
+ <div class="list" :class="{'expand':isTagListExpand}">
|
|
|
+ <span class="list-item" :class="{'active':choosedTags.length===0}"
|
|
|
+ @click="choosedTags = []">全部</span>
|
|
|
+ <span class="list-item" :class="{'active':choosedTags.findIndex(i=>i.TagId===item.TagId)!==-1}"
|
|
|
+ v-for="item in tagList" :key="item.TagId" @click="changeTags(item)">{{item.TagName}}</span>
|
|
|
+ </div>
|
|
|
+ <div class="expand-btn" v-show="boxWidth<=tagWidth" @click="isTagListExpand = !isTagListExpand">
|
|
|
+ {{isTagListExpand?'收起':'展开'}}
|
|
|
+ <el-icon :class="{'icon-expand':isTagListExpand}"><ArrowRightBold /></el-icon>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="select-box">
|
|
|
+ <!-- <el-select v-model="selectValue" placeholder="Select" size="large" @change="handleCurrentChange(1)">
|
|
|
+ <el-option label="最新" value="New"/>
|
|
|
+ <el-option label="最热" value="Hot"/>
|
|
|
+ </el-select> -->
|
|
|
+ <el-radio-group v-model="selectValue" size="large" @change="handleCurrentChange(1)" fill="#0052D9">
|
|
|
+ <el-radio-button label="New">最新</el-radio-button>
|
|
|
+ <el-radio-button label="Hot">最热</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ <span class="path" style="margin-left: 20px;">
|
|
|
+ <span>{{choosedClassify.ClassifyName||''}}
|
|
|
+ <span v-if="choosedSubClassify.ClassifyId">/</span>
|
|
|
+ {{choosedSubClassify.ClassifyName||''}}
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ <div class="quick-pagination">
|
|
|
+ <span>{{currentIndex}}/{{Math.ceil(total/15)}}</span>
|
|
|
+ <el-icon @click="changePage('minus')"><ArrowLeftBold /></el-icon>
|
|
|
+ <el-icon @click="changePage('add')"><ArrowRightBold /></el-icon>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="list-wrap">
|
|
|
+ <div class="list-box">
|
|
|
+ <div class="list-item" v-for="item in videoList" :key="item.VideoId" @click="gotoVideoDetail(item)">
|
|
|
+ <div class="list-image" :style="{background:`no-repeat top/contain url('${item.CoverImg}')`}"></div>
|
|
|
+ <h4 class="word-ellipsis">{{item.Title}}</h4>
|
|
|
+ <div class="tag-box">
|
|
|
+ <span class="tag-item" v-for="tag in item.Tags" :key="tag.TagId">{{tag.TagName}}</span>
|
|
|
+ </div>
|
|
|
+ <p class="word-ellipsis" style="color:#999999;text-overflow: ellipsis;">{{item.Introduce}} </p>
|
|
|
+ <div class="other">
|
|
|
+ <span>{{item.PublishTime}}</span>
|
|
|
+ <el-icon style="margin-left: auto;margin-right:5px;"><VideoPlay /></el-icon>{{item.ViewTotal}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="empty-hint" v-if="videoList.length===0" style="width:100%;text-align: center;color: #999999;">
|
|
|
+ <img src="~@/assets/img/nodata.png" alt="" style="width: 200px;"/>
|
|
|
+ <p>{{keyword?`没有找到与“${keyword}”相关的课程`:'暂无课程'}}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="page-box">
|
|
|
+ <el-config-provider :locale="zhCn">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentIndex"
|
|
|
+ layout="total,->,prev,pager,next,jumper"
|
|
|
+ :page-size="15"
|
|
|
+ :total="total"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ >
|
|
|
+ </el-pagination>
|
|
|
+ </el-config-provider>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ <!-- teleport search -->
|
|
|
+ <Teleport to=".layout-header-other" v-if="beforeMounted">
|
|
|
+ <div class="search-box">
|
|
|
+ <el-input placeholder="搜索感兴趣的视频课程" size="large" clearable style="width:280px;"
|
|
|
+ :prefix-icon="Search" v-model.trim="keyword" @input="handleCurrentChange(1)"></el-input>
|
|
|
+ </div>
|
|
|
+ </Teleport>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.video-list-wrap{
|
|
|
+ /* padding:30px 120px 30px 120px; */
|
|
|
+ box-sizing: border-box;
|
|
|
+ background-color:#F2F6FA;
|
|
|
+ height: calc(100vh - 60px);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ .select-wrap{
|
|
|
+ background-color: #fff;
|
|
|
+ padding:30px 120px;
|
|
|
+ }
|
|
|
+ .select{
|
|
|
+ display: flex;
|
|
|
+ margin-bottom:20px;
|
|
|
+ position:relative;
|
|
|
+ &:last-child{
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ .expand-btn{
|
|
|
+ position: absolute;
|
|
|
+ left:100%;
|
|
|
+ top:0;
|
|
|
+ bottom: 0;
|
|
|
+ padding:8px;
|
|
|
+ /* background-color: #F2F6FA; */
|
|
|
+ /* border: 1px solid gray; */
|
|
|
+ white-space: nowrap;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+ .el-icon{
|
|
|
+ font-size: 14px;
|
|
|
+ color:#0052D9;
|
|
|
+ vertical-align: bottom;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .icon-expand{
|
|
|
+ transform: rotate(90deg);
|
|
|
+ }
|
|
|
+ .list{
|
|
|
+ flex:1;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ overflow-x: hidden;
|
|
|
+ margin-left: 15px;
|
|
|
+ gap: 10px;
|
|
|
+ /* height:35px; */
|
|
|
+ &.expand{
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ .list-item{
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+ cursor: pointer;
|
|
|
+ &.active,&:hover{
|
|
|
+ color:#fff;
|
|
|
+ background-color:#0052D9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .select-box{
|
|
|
+ padding:0 120px;
|
|
|
+ margin-top: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ :deep(.el-radio-button__inner:hover){
|
|
|
+ color: #0052D9 !important;
|
|
|
+ }
|
|
|
+ .quick-pagination{
|
|
|
+ margin-left: auto;
|
|
|
+ font-size: 14px;
|
|
|
+ .el-icon{
|
|
|
+ margin-left: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .list-wrap{
|
|
|
+ padding:20px 120px;
|
|
|
+ flex: 1;
|
|
|
+ background-color: #f2f6fa;
|
|
|
+ overflow-y: auto;
|
|
|
+ }
|
|
|
+ .list-box{
|
|
|
+ overflow-y: auto;
|
|
|
+ width:100%;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 20px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ .list-item{
|
|
|
+ width:19%;
|
|
|
+ min-width: 225px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding:10px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius:8px;
|
|
|
+ cursor: pointer;
|
|
|
+ .list-image{
|
|
|
+ width:100%;
|
|
|
+ height:0;
|
|
|
+ padding-bottom:67%;
|
|
|
+ }
|
|
|
+ h4{
|
|
|
+ margin:10px 0;
|
|
|
+ }
|
|
|
+ .tag-box{
|
|
|
+ .tag-item{
|
|
|
+ background-color: #ECF2FE;
|
|
|
+ color:#0052D9;
|
|
|
+ padding:4px;
|
|
|
+ text-align: center;
|
|
|
+ margin-right:10px;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .other{
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .page-box{
|
|
|
+ background-color: #fff;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding:12px 120px;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+.el-popper{
|
|
|
+ .sub-list{
|
|
|
+ padding: 5px;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ .list-item{
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+ cursor: pointer;
|
|
|
+ &.active,&:hover{
|
|
|
+ color:#fff;
|
|
|
+ background-color:#0052D9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|