提交 23ee942b authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 d4e70689
...@@ -4,7 +4,7 @@ import httpRequest from '@/utils/axios' ...@@ -4,7 +4,7 @@ import httpRequest from '@/utils/axios'
// 获取Key // 获取Key
export function getPageKey() { export function getPageKey() {
return httpRequest.get('/api/log/api/v1/client/page-key') return httpRequest.get('/api/meta/api/v1/client/page-key')
} }
/** /**
...@@ -15,5 +15,5 @@ export function getPageKey() { ...@@ -15,5 +15,5 @@ export function getPageKey() {
*/ */
export function setMetaInfo(data: { event: string; action: string; data: string }) { export function setMetaInfo(data: { event: string; action: string; data: string }) {
return httpRequest.post('/api/log/api/v1/client/set-meta-info', data) return httpRequest.post('/api/meta/api/v1/client/set-meta-info', data)
} }
src/assets/images/icon_chapter.png

479 Bytes | W: | H:

src/assets/images/icon_chapter.png

586 Bytes | W: | H:

src/assets/images/icon_chapter.png
src/assets/images/icon_chapter.png
src/assets/images/icon_chapter.png
src/assets/images/icon_chapter.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_doc.png

1.8 KB | W: | H:

src/assets/images/icon_doc.png

913 Bytes | W: | H:

src/assets/images/icon_doc.png
src/assets/images/icon_doc.png
src/assets/images/icon_doc.png
src/assets/images/icon_doc.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_exam.png

441 Bytes | W: | H:

src/assets/images/icon_exam.png

548 Bytes | W: | H:

src/assets/images/icon_exam.png
src/assets/images/icon_exam.png
src/assets/images/icon_exam.png
src/assets/images/icon_exam.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_live.png

707 Bytes | W: | H:

src/assets/images/icon_live.png

850 Bytes | W: | H:

src/assets/images/icon_live.png
src/assets/images/icon_live.png
src/assets/images/icon_live.png
src/assets/images/icon_live.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_mp3.png

1.7 KB | W: | H:

src/assets/images/icon_mp3.png

938 Bytes | W: | H:

src/assets/images/icon_mp3.png
src/assets/images/icon_mp3.png
src/assets/images/icon_mp3.png
src/assets/images/icon_mp3.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_mp4.png

1.7 KB | W: | H:

src/assets/images/icon_mp4.png

809 Bytes | W: | H:

src/assets/images/icon_mp4.png
src/assets/images/icon_mp4.png
src/assets/images/icon_mp4.png
src/assets/images/icon_mp4.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_pdf.png

1.7 KB | W: | H:

src/assets/images/icon_pdf.png

774 Bytes | W: | H:

src/assets/images/icon_pdf.png
src/assets/images/icon_pdf.png
src/assets/images/icon_pdf.png
src/assets/images/icon_pdf.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_png.png

1.6 KB | W: | H:

src/assets/images/icon_png.png

774 Bytes | W: | H:

src/assets/images/icon_png.png
src/assets/images/icon_png.png
src/assets/images/icon_png.png
src/assets/images/icon_png.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_ppt.png

1.7 KB | W: | H:

src/assets/images/icon_ppt.png

862 Bytes | W: | H:

src/assets/images/icon_ppt.png
src/assets/images/icon_ppt.png
src/assets/images/icon_ppt.png
src/assets/images/icon_ppt.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_rar.png

657 Bytes | W: | H:

src/assets/images/icon_rar.png

788 Bytes | W: | H:

src/assets/images/icon_rar.png
src/assets/images/icon_rar.png
src/assets/images/icon_rar.png
src/assets/images/icon_rar.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_work.png

684 Bytes | W: | H:

src/assets/images/icon_work.png

751 Bytes | W: | H:

src/assets/images/icon_work.png
src/assets/images/icon_work.png
src/assets/images/icon_work.png
src/assets/images/icon_work.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icon_xls.png

1.5 KB | W: | H:

src/assets/images/icon_xls.png

895 Bytes | W: | H:

src/assets/images/icon_xls.png
src/assets/images/icon_xls.png
src/assets/images/icon_xls.png
src/assets/images/icon_xls.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -79,3 +79,21 @@ textarea:focus { ...@@ -79,3 +79,21 @@ textarea:focus {
:root { :root {
--main-color: #aa1941; --main-color: #aa1941;
} }
.el-tabs__item {
--el-font-size-base: 16px;
padding: 0 20px !important;
min-width: 60px;
font-weight: 400;
text-align: center;
}
.el-tabs__item.is-active {
font-weight: 500;
}
.el-tabs__active-bar {
padding: 0 20px;
margin-left: -20px;
}
.el-tabs__nav-wrap::after {
height: 1px !important;
}
...@@ -31,7 +31,7 @@ function show(fileType: string) { ...@@ -31,7 +31,7 @@ function show(fileType: string) {
display: inline-block; display: inline-block;
img { img {
margin-right: 10px; margin-right: 10px;
width: 14px; width: 16px;
} }
} }
</style> </style>
...@@ -18,7 +18,7 @@ export default { name: 'AppMain' } ...@@ -18,7 +18,7 @@ export default { name: 'AppMain' }
overflow: hidden; overflow: hidden;
} }
.app-main-inner { .app-main-inner {
max-width: 1440px; /* max-width: 1440px; */
height: 100%; height: 100%;
margin: 0 auto; margin: 0 auto;
} }
......
...@@ -49,7 +49,7 @@ function handleTop(data: CourseListItemType) { ...@@ -49,7 +49,7 @@ function handleTop(data: CourseListItemType) {
</script> </script>
<template> <template>
<div class="course-item" :class="{ 'is-active': isActive }"> <div class="course-item" :class="{ 'is-active': isActive, 'is-top': !!data.is_top }">
<el-tooltip :content="!!data.is_top ? '取消置顶' : '置顶'"> <el-tooltip :content="!!data.is_top ? '取消置顶' : '置顶'">
<div class="course-item__top" :class="{ 'is-active': !!data.is_top }" @click="handleTop(data)"></div> <div class="course-item__top" :class="{ 'is-active': !!data.is_top }" @click="handleTop(data)"></div>
</el-tooltip> </el-tooltip>
...@@ -60,13 +60,17 @@ function handleTop(data: CourseListItemType) { ...@@ -60,13 +60,17 @@ function handleTop(data: CourseListItemType) {
</div> </div>
<div class="course-item-main"> <div class="course-item-main">
<h2 class="course-item__name">{{ data.name }}</h2> <h2 class="course-item__name">{{ data.name }}</h2>
<div class="course-item-progress">总进度<el-progress :percentage="parseFloat(data.schedule)" /></div>
</div> </div>
</div> </div>
<div class="course-item-progress">
总进度<el-progress :stroke-width="4" :percentage="parseFloat(data.schedule)" />
</div>
</router-link> </router-link>
<div class="course-item-ft"> <div class="course-item-ft">
<div class="course-item-playlist" v-if="data.section?.watch_video_length"> <div class="course-item-playlist" v-if="data.section?.watch_video_length">
<p class="t1">{{ data.section.name }}</p> <p class="t1">
<el-tooltip :content="data.section.name">{{ data.section.name }}</el-tooltip>
</p>
<p class="t2">已观看{{ data.section.schedule }}%</p> <p class="t2">已观看{{ data.section.schedule }}%</p>
<router-link :to="`/course/player?${targetUrlQuery}`" target="_blank"> <router-link :to="`/course/player?${targetUrlQuery}`" target="_blank">
<el-button type="primary" round>点击观看</el-button> <el-button type="primary" round>点击观看</el-button>
...@@ -83,9 +87,13 @@ function handleTop(data: CourseListItemType) { ...@@ -83,9 +87,13 @@ function handleTop(data: CourseListItemType) {
padding: 12px; padding: 12px;
margin: 20px 0; margin: 20px 0;
border: 1px solid #e6e6e6; border: 1px solid #e6e6e6;
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.12);
border-radius: 6px; border-radius: 6px;
&.is-top {
background: rgba(247, 248, 250, 0.39);
}
&:hover,
&.is-active { &.is-active {
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.12);
background: rgba(247, 248, 250, 1); background: rgba(247, 248, 250, 1);
} }
} }
...@@ -110,8 +118,8 @@ function handleTop(data: CourseListItemType) { ...@@ -110,8 +118,8 @@ function handleTop(data: CourseListItemType) {
} }
.course-item-pic { .course-item-pic {
position: relative; position: relative;
width: 90px; width: 108px;
height: 90px; height: 72px;
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden;
img { img {
...@@ -123,9 +131,9 @@ function handleTop(data: CourseListItemType) { ...@@ -123,9 +131,9 @@ function handleTop(data: CourseListItemType) {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
padding: 0 2px; padding: 0 4px;
font-size: 10px; font-size: 10px;
line-height: 16px; line-height: 18px;
color: #dbdbdb; color: #dbdbdb;
background: rgba(0, 0, 0, 0.39); background: rgba(0, 0, 0, 0.39);
border-radius: 0px 4px 0px 4px; border-radius: 0px 4px 0px 4px;
...@@ -149,7 +157,7 @@ function handleTop(data: CourseListItemType) { ...@@ -149,7 +157,7 @@ function handleTop(data: CourseListItemType) {
} }
} }
.course-item-progress { .course-item-progress {
margin-top: 10px; margin-top: 8px;
display: flex; display: flex;
align-items: center; align-items: center;
color: #999; color: #999;
...@@ -157,10 +165,13 @@ function handleTop(data: CourseListItemType) { ...@@ -157,10 +165,13 @@ function handleTop(data: CourseListItemType) {
:deep(.el-progress) { :deep(.el-progress) {
flex: 1; flex: 1;
margin-left: 5px; margin-left: 5px;
.el-progress__text {
font-size: 12px !important;
}
} }
} }
.course-item-ft { .course-item-ft {
margin-top: 10px; margin-top: 8px;
font-size: 12px; font-size: 12px;
line-height: 20px; line-height: 20px;
color: #535353; color: #535353;
......
...@@ -192,12 +192,18 @@ const filterList = computed(() => { ...@@ -192,12 +192,18 @@ const filterList = computed(() => {
} }
.el-checkbox-button { .el-checkbox-button {
margin-bottom: 10px; margin-bottom: 10px;
--el-checkbox-button-checked-text-color: var(--el-color-primary);
--el-checkbox-button-checked-bg-color: #f7e9ec;
--el-checkbox-button-checked-border-color: var(--el-color-primary);
--el-checkbox-button-border-color: #adadad;
} }
.el-checkbox-button__inner { .el-checkbox-button__inner {
padding: 10px 20px; padding: 10px 20px;
border: 1px solid #adadad !important; border-left: var(--el-border);
border-radius: 18px !important; border-radius: 18px !important;
box-shadow: none !important; &:hover {
border-color: var(--el-checkbox-button-checked-border-color);
}
} }
} }
</style> </style>
...@@ -41,7 +41,7 @@ function formatDuration(duration: number | undefined) { ...@@ -41,7 +41,7 @@ function formatDuration(duration: number | undefined) {
<template> <template>
<div class="course-player-chapter"> <div class="course-player-chapter">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab" stretch>
<el-tab-pane label="章节" name="chapter"> <el-tab-pane label="章节" name="chapter">
<dl v-for="(item, index) in chapterList" :key="item.id"> <dl v-for="(item, index) in chapterList" :key="item.id">
<dt> <dt>
...@@ -84,15 +84,16 @@ function formatDuration(duration: number | undefined) { ...@@ -84,15 +84,16 @@ function formatDuration(duration: number | undefined) {
float: none; float: none;
display: flex; display: flex;
} }
:deep(.el-tabs__active-bar) {
display: none;
}
:deep(.el-tabs__item) { :deep(.el-tabs__item) {
flex: 1;
height: 40px; height: 40px;
font-size: 16px; font-size: 16px;
line-height: 40px; line-height: 40px;
color: #fff; color: #89898b;
text-align: center;
&.is-active { &.is-active {
color: var(--main-color); color: #fff;
} }
} }
dl { dl {
......
...@@ -56,7 +56,8 @@ function toggleCollection(data: CourseResourceType) { ...@@ -56,7 +56,8 @@ function toggleCollection(data: CourseResourceType) {
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { function canDownload(type: number) {
return [4, 10, 11].includes(type) // return [4, 10, 11].includes(type)
return [4].includes(type)
} }
// 下载资源 // 下载资源
function downloadFile(data: CourseResourceType) { function downloadFile(data: CourseResourceType) {
......
...@@ -4,7 +4,9 @@ import type { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js' ...@@ -4,7 +4,9 @@ import type { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js'
import { throttle } from 'lodash' import { throttle } from 'lodash'
import { useStorage, useElementVisibility } from '@vueuse/core' import { useStorage, useElementVisibility } from '@vueuse/core'
import { Swiper, SwiperSlide } from 'swiper/vue' import { Swiper, SwiperSlide } from 'swiper/vue'
import { Navigation } from 'swiper'
import 'swiper/css' import 'swiper/css'
import 'swiper/css/navigation'
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue' import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
import { getCoursePlayInfo, getVideoRecords, uploadVideoRecords } from '../api' import { getCoursePlayInfo, getVideoRecords, uploadVideoRecords } from '../api'
import { useLog } from '@/composables/useLog' import { useLog } from '@/composables/useLog'
...@@ -266,67 +268,75 @@ onUnmounted(() => { ...@@ -266,67 +268,75 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<div ref="playerWrapperRef" :style="resource ? `height: 510px` : ''"> <div class="course-player-wrapper">
<div class="player-box" :class="{ 'is-pinned': !playerIsVisible }"> <div ref="playerWrapperRef" :style="resource ? `height: 510px` : ''">
<AppVideoPlayer <div class="player-box" :class="{ 'is-pinned': !playerIsVisible }">
:options="options" <AppVideoPlayer
:src="src" :options="options"
@ready="onReady" :src="src"
@loadeddata="onLoadedData" @ready="onReady"
@timeupdate="onTimeUpdate" @loadeddata="onLoadedData"
@seeked="onSeeked" @timeupdate="onTimeUpdate"
@ended="onEnded" @seeked="onSeeked"
style="width: 100%; height: 100%" @ended="onEnded"
v-if="src" style="width: 100%; height: 100%"
></AppVideoPlayer> v-if="src"
></AppVideoPlayer>
</div>
</div> </div>
<!-- 设置 -->
<teleport to=".vjs-control-bar" v-if="isReady">
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" :show-arrow="false" width="40px">
<template #reference>
<button class="vjs-hd-control vjs-control vjs-button" type="button">
<span class="vjs-icon-hd"></span>
</button>
</template>
<ul class="video-definition">
<li
v-for="(item, index) in currentPlayList"
:key="index"
:class="{ 'is-active': item.PlayURL === src.src }"
@click="changeSrc(item)"
>
{{ item.DefinitionName }}
</li>
</ul>
</el-popover>
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" :show-arrow="false" width="140px">
<template #reference>
<button class="vjs-cog-control vjs-control vjs-button" type="button">
<span class="vjs-icon-cog"></span>
</button>
</template>
<ul class="video-actions">
<li>始终跳过片头 <el-switch size="small" v-model="isSkip"></el-switch></li>
<li>连续播放 <el-switch size="small" v-model="isAutoPlayNext"></el-switch></li>
</ul>
</el-popover>
</teleport>
<swiper :slidesPerView="'auto'" :spaceBetween="30" navigation :modules="[Navigation]">
<swiper-slide
v-for="item in sectionVideoList"
:key="item.id"
class="video-item"
:class="{ 'is-active': item.resource_id === resourceId }"
@click="changeResource(item)"
>
<div class="video-item-pic">
<img :src="item.info?.cover" />
</div>
<p>{{ item.info.name }}</p>
</swiper-slide>
</swiper>
</div> </div>
<!-- 设置 -->
<teleport to=".vjs-control-bar" v-if="isReady">
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" :show-arrow="false" width="40px">
<template #reference>
<button class="vjs-hd-control vjs-control vjs-button" type="button">
<span class="vjs-icon-hd"></span>
</button>
</template>
<ul class="video-definition">
<li
v-for="(item, index) in currentPlayList"
:key="index"
:class="{ 'is-active': item.PlayURL === src.src }"
@click="changeSrc(item)"
>
{{ item.DefinitionName }}
</li>
</ul>
</el-popover>
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" :show-arrow="false" width="140px">
<template #reference>
<button class="vjs-cog-control vjs-control vjs-button" type="button">
<span class="vjs-icon-cog"></span>
</button>
</template>
<ul class="video-actions">
<li>始终跳过片头 <el-switch size="small" v-model="isSkip"></el-switch></li>
<li>连续播放 <el-switch size="small" v-model="isAutoPlayNext"></el-switch></li>
</ul>
</el-popover>
</teleport>
<swiper :slidesPerView="'auto'" :spaceBetween="30">
<swiper-slide
v-for="item in sectionVideoList"
:key="item.id"
class="video-item"
:class="{ 'is-active': item.resource_id === resourceId }"
@click="changeResource(item)"
>
<img :src="item.info?.cover" />
<p>{{ item.info.name }}</p>
</swiper-slide>
</swiper>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.course-player-wrapper {
margin-bottom: 40px;
border-bottom: 1px solid #e2e2e2;
}
.player-box { .player-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
...@@ -355,36 +365,43 @@ onUnmounted(() => { ...@@ -355,36 +365,43 @@ onUnmounted(() => {
.video-item { .video-item {
position: relative; position: relative;
margin: 20px 0; margin: 20px 0;
width: 200px; width: 238px;
height: 100px;
border-radius: 5px;
cursor: pointer; cursor: pointer;
overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
p { p {
position: absolute; padding: 0 8px;
left: 0;
right: 0;
bottom: 0;
padding: 0 10px;
font-size: 14px; font-size: 14px;
line-height: 30px; line-height: 30px;
color: #fff; color: #333;
background-color: rgba(0, 0, 0, 0.5);
text-align: center;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
&:hover,
&.is-active {
img {
transform: scale(1.05);
}
p {
color: var(--main-color);
}
}
}
.video-item-pic {
width: 100%;
height: 148px;
border-radius: 10px;
box-sizing: border-box;
overflow: hidden;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
} transition: all 0.25s ease-in-out;
&.is-active {
border: 2px solid var(--main-color);
} }
} }
.video-definition { .video-definition {
font-size: 12px; font-size: 12px;
li { li {
...@@ -422,4 +439,14 @@ onUnmounted(() => { ...@@ -422,4 +439,14 @@ onUnmounted(() => {
padding: 0; padding: 0;
margin-bottom: -12px !important; margin-bottom: -12px !important;
} }
:deep(.swiper-button-next),
:deep(.swiper-button-prev) {
margin-top: -30px;
--swiper-navigation-size: 14px;
width: 34px;
height: 34px;
color: #fff;
background: #303133;
border-radius: 50%;
}
</style> </style>
...@@ -78,7 +78,8 @@ function toggleCollection(resource: CourseResourceType, section: CourseSectionTy ...@@ -78,7 +78,8 @@ function toggleCollection(resource: CourseResourceType, section: CourseSectionTy
} }
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { function canDownload(type: number) {
return [4, 10, 11].includes(type) // return [4, 10, 11].includes(type)
return [4].includes(type)
} }
// 下载资源 // 下载资源
function downloadFile(data: CourseResourceType) { function downloadFile(data: CourseResourceType) {
...@@ -113,10 +114,16 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha ...@@ -113,10 +114,16 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
<template> <template>
<el-collapse class="course-chapters" v-model="chapterIds" v-if="chapterList.length"> <el-collapse class="course-chapters" v-model="chapterIds" v-if="chapterList.length">
<el-collapse-item :name="item.id" v-for="item in chapterList" :key="item.id"> <el-collapse-item :name="item.id" v-for="item in chapterList" :key="item.id">
<template #title><i class="icon-chapter"></i>{{ item.name }}</template> <template #title
><i class="icon-chapter"></i>
<p class="chapter-title">{{ item.name }}</p></template
>
<el-collapse class="course-sections" v-model="sectionIds"> <el-collapse class="course-sections" v-model="sectionIds">
<el-collapse-item :name="section.id" v-for="section in item.sections" :key="section.id"> <el-collapse-item :name="section.id" v-for="section in item.sections" :key="section.id">
<template #title><i class="icon-chapter"></i>{{ section.name }}</template> <template #title
><i class="icon-chapter"></i>
<p class="section-title">{{ section.name }}</p></template
>
<ul> <ul>
<li class="course-resource-item" v-for="resource in section.resources" :key="resource.id"> <li class="course-resource-item" v-for="resource in section.resources" :key="resource.id">
<p> <p>
...@@ -175,6 +182,7 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha ...@@ -175,6 +182,7 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
color: #666;
} }
a { a {
&:hover { &:hover {
...@@ -217,8 +225,8 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha ...@@ -217,8 +225,8 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
.icon-chapter { .icon-chapter {
margin-right: 10px; margin-right: 10px;
display: inline-block; display: inline-block;
width: 12px; width: 16px;
height: 14px; height: 20px;
background: url(@/assets/images/icon_chapter.png) no-repeat; background: url(@/assets/images/icon_chapter.png) no-repeat;
background-size: contain; background-size: contain;
} }
...@@ -237,6 +245,16 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha ...@@ -237,6 +245,16 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
border-bottom: none; border-bottom: none;
} }
} }
.chapter-title {
font-size: 16px;
font-weight: 500;
color: #333333;
}
.section-title {
font-size: 14px;
font-weight: 400;
color: #333333;
}
.el-collapse { .el-collapse {
border-top: none; border-top: none;
border-bottom: none; border-bottom: none;
......
...@@ -4,6 +4,8 @@ import CourseListItem from '../components/CourseListItem.vue' ...@@ -4,6 +4,8 @@ import CourseListItem from '../components/CourseListItem.vue'
import type { CourseListParamsType, CourseListItemType } from '../types' import type { CourseListParamsType, CourseListItemType } from '../types'
import { getCourseList } from '../api' import { getCourseList } from '../api'
const router = useRouter()
const route = useRoute()
// 列表参数 // 列表参数
const listParams = reactive<CourseListParamsType>({ id: '', semester_ids: [], elective_types: [] }) const listParams = reactive<CourseListParamsType>({ id: '', semester_ids: [], elective_types: [] })
let courseList = $ref<CourseListItemType[]>([]) let courseList = $ref<CourseListItemType[]>([])
...@@ -15,6 +17,11 @@ function fetchList() { ...@@ -15,6 +17,11 @@ function fetchList() {
}) })
getCourseList(params).then(res => { getCourseList(params).then(res => {
courseList = res.data.data courseList = res.data.data
const [first] = courseList
// 进入第一个课程详情页
if (first && route.path === '/course') {
router.push({ path: '/course/view', query: { course_id: first.course_id, semester_id: first.semester_id } })
}
}) })
} }
// 筛选 // 筛选
......
...@@ -160,10 +160,12 @@ function toggleSidebar() { ...@@ -160,10 +160,12 @@ function toggleSidebar() {
.course-player-aside { .course-player-aside {
position: relative; position: relative;
width: 258px; width: 258px;
margin-left: 20px;
background-color: #1f1e24; background-color: #1f1e24;
transition: width 0.3s ease-in-out; transition: width 0.1s;
&.is-hidden { &.is-hidden {
width: 0; width: 0;
margin-left: 0;
} }
} }
.course-player-aside__inner { .course-player-aside__inner {
...@@ -173,10 +175,10 @@ function toggleSidebar() { ...@@ -173,10 +175,10 @@ function toggleSidebar() {
} }
.toggle-button { .toggle-button {
position: absolute; position: absolute;
top: 238px; top: 235px;
left: -17px; left: -20px;
width: 34px; width: 40px;
height: 34px; height: 40px;
font-size: 14px; font-size: 14px;
border-radius: 50%; border-radius: 50%;
background: #303133; background: #303133;
...@@ -187,13 +189,27 @@ function toggleSidebar() { ...@@ -187,13 +189,27 @@ function toggleSidebar() {
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
// 右半圆 // 右半圆
clip: rect(0px 34px 34px 17px); clip: rect(0px 40px 40px 20px);
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
&.is-hidden { &.is-hidden {
// 左半圆 // 左半圆
clip: rect(0px 17px 34px 0px); clip: rect(0px 20px 40px 0px);
justify-content: flex-start; justify-content: flex-start;
} }
} }
:deep(.el-tabs__item) {
--el-font-size-base: 16px;
padding: 0 20px !important;
min-width: 60px;
font-weight: 400;
text-align: center;
&.is-active {
font-weight: 500;
}
}
:deep(.el-tabs__active-bar) {
padding: 0 20px;
margin-left: -20px;
}
</style> </style>
...@@ -76,11 +76,16 @@ function showInfo(title: string, content: string) { ...@@ -76,11 +76,16 @@ function showInfo(title: string, content: string) {
<li>{{ detail.credit }}学分</li> <li>{{ detail.credit }}学分</li>
<li v-if="detail.semester">{{ detail.semester.name }}</li> <li v-if="detail.semester">{{ detail.semester.name }}</li>
</ul> </ul>
<el-button round @click="showInfo('课程简介', detail.represent)" v-if="detail.represent">课程简介</el-button> <el-button round @click="showInfo('课程简介', detail.represent)" :disabled="!detail.represent"
<el-button round @click="showInfo('预备知识', detail.previous_preparation)" v-if="detail.previous_preparation" >课程简介</el-button
>
<el-button
round
@click="showInfo('预备知识', detail.previous_preparation)"
:disabled="!detail.previous_preparation"
>预备知识</el-button >预备知识</el-button
> >
<el-button round @click="showInfo('授课目标', detail.target)" v-if="detail.target">授课目标</el-button> <el-button round @click="showInfo('授课目标', detail.target)" :disabled="!detail.target">授课目标</el-button>
</div> </div>
<div class="course-lecturers" v-if="detail.lecturers?.length"> <div class="course-lecturers" v-if="detail.lecturers?.length">
<el-carousel <el-carousel
...@@ -95,9 +100,13 @@ function showInfo(title: string, content: string) { ...@@ -95,9 +100,13 @@ function showInfo(title: string, content: string) {
<h2>{{ item.name }}</h2> <h2>{{ item.name }}</h2>
<el-popover :width="400" trigger="hover" v-if="item.summarize"> <el-popover :width="400" trigger="hover" v-if="item.summarize">
<template #reference> <template #reference>
<div v-html="item.summarize" style="height: 66px; overflow: hidden"></div> <div
class="lecturer-item__content"
v-html="item.summarize"
style="height: 66px; overflow: hidden"
></div>
</template> </template>
<div v-html="item.summarize"></div> <div class="lecturer-item__content" v-html="item.summarize"></div>
</el-popover> </el-popover>
</div> </div>
</el-carousel-item> </el-carousel-item>
...@@ -209,7 +218,17 @@ function showInfo(title: string, content: string) { ...@@ -209,7 +218,17 @@ function showInfo(title: string, content: string) {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
line-height: 27px; line-height: 27px;
color: #333333; color: #333;
}
.lecturer-item__content {
font-size: 14px !important;
font-weight: 400;
line-height: 24px !important;
color: #666666;
:deep(p) {
font-size: 14px !important;
line-height: 24px !important;
}
} }
} }
......
...@@ -75,7 +75,8 @@ function toggleCollection(data: CollectionType) { ...@@ -75,7 +75,8 @@ function toggleCollection(data: CollectionType) {
} }
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { function canDownload(type: number) {
return [1, 3, 4].includes(type) // return [1, 3, 4].includes(type)
return [1].includes(type)
} }
// 下载资源 // 下载资源
function downloadFile(data: CollectionType) { function downloadFile(data: CollectionType) {
......
...@@ -40,10 +40,10 @@ function handleUpdate() { ...@@ -40,10 +40,10 @@ function handleUpdate() {
<el-tab-pane label="待处理" name="1" lazy></el-tab-pane> <el-tab-pane label="待处理" name="1" lazy></el-tab-pane>
<el-tab-pane label="已处理" name="2" lazy></el-tab-pane> <el-tab-pane label="已处理" name="2" lazy></el-tab-pane>
</el-tabs> </el-tabs>
<el-collapse v-if="dataset.list.length"> <el-collapse v-if="dataset.list.length" style="border-top: 0">
<el-collapse-item v-for="item in dataset.list" :name="item.id" :key="item.id"> <el-collapse-item v-for="item in dataset.list" :name="item.id" :key="item.id">
<template #title> <template #title>
<el-button type="primary" size="small" round style="margin-right: 10px" v-if="item.status === 1" <el-button type="primary" size="small" plain round style="margin-right: 10px" v-if="item.status === 1"
>待处理</el-button >待处理</el-button
> >
<el-button color="#E8E8E8" size="small" round style="margin-right: 10px" v-if="item.status === 2" <el-button color="#E8E8E8" size="small" round style="margin-right: 10px" v-if="item.status === 2"
......
...@@ -15,7 +15,7 @@ httpRequest.interceptors.request.use( ...@@ -15,7 +15,7 @@ httpRequest.interceptors.request.use(
function (config) { function (config) {
// 权限接口单独签名 // 权限接口单独签名
// https://gitlab.ezijing.com/root/api-documents/-/blob/master/ezijing_permissions/%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81.md // https://gitlab.ezijing.com/root/api-documents/-/blob/master/ezijing_permissions/%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81.md
if (config.url && /^\/api\/learn|^\/api\/log/.test(config.url)) { if (config.url && /^\/api\/learn|^\/api\/meta/.test(config.url)) {
// 默认参数 // 默认参数
const defaultHeaders = { const defaultHeaders = {
timestamp: Date.now(), timestamp: Date.now(),
......
...@@ -30,11 +30,6 @@ export default defineConfig(({ mode }) => ({ ...@@ -30,11 +30,6 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem')) cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
}, },
proxy: { proxy: {
'/api/log': {
target: 'http://api.ezijing.com:9501',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/log/, '')
},
'/api': 'https://saas-learn.ezijing.com' '/api': 'https://saas-learn.ezijing.com'
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论