diff --git a/OL-LearnPlatform-Frontend b/OL-LearnPlatform-Frontend deleted file mode 160000 index 96c6f62..0000000 --- a/OL-LearnPlatform-Frontend +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 96c6f6254ac8ada76c63f2b88e30a143b6d115b8 diff --git a/docs/DPlayer-Integration-Guide.md b/docs/DPlayer-Integration-Guide.md new file mode 100644 index 0000000..cac318a --- /dev/null +++ b/docs/DPlayer-Integration-Guide.md @@ -0,0 +1,320 @@ +# DPlayer 集成指南 + +## 什么是 DPlayer? + +**DPlayer** 是由 [DIYGod](https://github.com/DIYGod) 开发的一个开源的 HTML5 视频播放器,具有以下特点: + +- 🎨 **界面美观**:现代化的设计风格 +- 🎯 **轻量级**:体积小,加载快 +- 🌏 **中文友好**:由中国开发者开发,中文文档完善 +- 🎮 **功能丰富**:支持弹幕、快捷键、倍速播放等 +- 📱 **移动端适配**:响应式设计,支持移动设备 + +## 主要功能特性 + +### 基础功能 +- ✅ 播放/暂停控制 +- ✅ 音量控制 +- ✅ 进度条拖拽 +- ✅ 全屏切换 +- ✅ 倍速播放 (0.5x - 2x) + +### 高级功能 +- 🎯 键盘快捷键支持 +- 🎨 自定义主题色 +- 📝 右键菜单自定义 +- 🎵 音频可视化 +- 📱 移动端手势支持 + +### 格式支持 +- MP4 +- WebM +- Ogg +- HLS (.m3u8) +- FLV +- 更多格式通过插件支持 + +## 安装和集成 + +### 方法1:CDN 引入(推荐用于快速测试) + +```html + + + +``` + +### 方法2:NPM 安装(推荐用于生产环境) + +```bash +npm install dplayer +``` + +然后在组件中导入: + +```javascript +import DPlayer from 'dplayer' +import 'dplayer/dist/DPlayer.min.css' +``` + +## 基础使用 + +### 创建播放器 + +```javascript +const player = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'video.mp4', + type: 'auto' + }, + autoplay: false, + theme: '#007bff', + lang: 'zh-cn' +}) +``` + +### 事件监听 + +```javascript +player.on('play', () => { + console.log('视频开始播放') +}) + +player.on('pause', () => { + console.log('视频暂停') +}) + +player.on('ended', () => { + console.log('视频播放结束') +}) + +player.on('error', () => { + console.log('播放出错') +}) +``` + +## 配置选项 + +### 基础配置 + +```javascript +const options = { + container: document.getElementById('dplayer'), // 容器元素 + video: { + url: 'video.mp4', // 视频地址 + type: 'auto', // 视频类型:auto, normal, hls, flv + defaultQuality: 0, // 默认画质 + pic: 'poster.jpg', // 封面图 + thumbnails: 'thumbnails.jpg' // 缩略图 + }, + autoplay: false, // 自动播放 + theme: '#007bff', // 主题色 + lang: 'zh-cn', // 语言:zh-cn, en + hotkey: true, // 启用快捷键 + preload: 'auto', // 预加载:auto, metadata, none + volume: 0.8, // 默认音量 + playbackSpeed: [0.5, 0.75, 1, 1.25, 1.5, 2], // 倍速选项 + contextmenu: [ // 右键菜单 + { + text: '关于 DPlayer', + link: 'https://github.com/DIYGod/DPlayer' + } + ] +} +``` + +### 高级配置 + +```javascript +const advancedOptions = { + // 弹幕配置 + danmaku: { + id: 'dplayer-danmaku', + api: 'https://api.prprpr.me/dplayer/', + token: 'token', + maximum: 1000, + addition: ['https://api.prprpr.me/dplayer/bilibili?aid=4157142'], + user: 'DIYGod', + bottom: '15%', + unlimited: true + }, + + // 字幕配置 + subtitle: { + url: 'subtitle.vtt', + type: 'webvtt', + fontSize: '20px', + bottom: '10%', + color: '#fff' + }, + + // 画质切换 + video: { + url: [ + { + name: '1080P', + url: 'video-1080p.mp4' + }, + { + name: '720P', + url: 'video-720p.mp4' + } + ], + defaultQuality: 0 + } +} +``` + +## 在 Vue 项目中使用 + +### 创建 DPlayer 组件 + +```vue + + + + + +``` + +## 样式定制 + +### 自定义主题色 + +```css +/* 修改播放器主题色 */ +.dplayer { + --dplayer-theme: #007bff; +} + +/* 自定义进度条颜色 */ +.dplayer .dplayer-bar-wrap .dplayer-bar .dplayer-played { + background: #007bff; +} + +/* 自定义控制按钮颜色 */ +.dplayer .dplayer-icons .dplayer-icon { + color: #fff; +} + +.dplayer .dplayer-icons .dplayer-icon:hover { + color: #007bff; +} +``` + +### 响应式设计 + +```css +/* 移动端适配 */ +@media (max-width: 768px) { + .dplayer { + font-size: 14px; + } + + .dplayer .dplayer-icons .dplayer-icon { + font-size: 16px; + } +} +``` + +## 快捷键支持 + +DPlayer 默认支持以下快捷键: + +- `空格键` - 播放/暂停 +- `←` - 后退 10 秒 +- `→` - 前进 10 秒 +- `↑` - 音量 +10% +- `↓` - 音量 -10% +- `F` - 全屏切换 +- `M` - 静音切换 + +## 与 CKPlayer 对比 + +| 特性 | CKPlayer | DPlayer | +|------|----------|---------| +| 界面美观度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | +| 功能丰富度 | ⭐⭐⭐ | ⭐⭐⭐⭐ | +| 移动端支持 | ⭐⭐⭐ | ⭐⭐⭐⭐ | +| 中文支持 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | +| 社区活跃度 | ⭐⭐ | ⭐⭐⭐⭐ | +| 文档质量 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | +| 学习成本 | ⭐⭐⭐⭐ | ⭐⭐⭐ | + +## 总结 + +**DPlayer 是一个优秀的视频播放器选择**,特别适合: + +- 🎯 需要美观界面的项目 +- 🌏 中文用户群体 +- 📱 重视移动端体验 +- 🎨 需要自定义主题的项目 +- ⚡ 追求轻量级解决方案 + +相比当前的 CKPlayer,DPlayer 提供了更好的用户体验和更丰富的功能,是升级视频播放器的理想选择。 diff --git a/package-lock.json b/package-lock.json index 8c58b83..07b7c68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@vicons/ionicons5": "^0.13.0", "axios": "^1.11.0", "ckplayer": "^3.1.2", + "dplayer": "^1.27.1", "naive-ui": "^2.42.0", "pinia": "^3.0.3", "quill": "^2.0.3", @@ -1777,6 +1778,12 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/balloon-css": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/balloon-css/-/balloon-css-1.2.0.tgz", + "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==", + "license": "MIT" + }, "node_modules/birpc": { "version": "2.5.0", "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.5.0.tgz", @@ -2139,6 +2146,28 @@ "node": ">=0.4.0" } }, + "node_modules/dplayer": { + "version": "1.27.1", + "resolved": "https://registry.npmmirror.com/dplayer/-/dplayer-1.27.1.tgz", + "integrity": "sha512-2laBMXs5V1B9zPwJ7eAIw/OBo+Xjvy03i4GHTk3Cg+IWbrq8rKMFO0fFr6ClAYotYOCcFGOvaJDkOZcgKllsCA==", + "license": "MIT", + "dependencies": { + "axios": "1.2.3", + "balloon-css": "^1.0.3", + "promise-polyfill": "8.3.0" + } + }, + "node_modules/dplayer/node_modules/axios": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.2.3.tgz", + "integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -3207,6 +3236,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/promise-polyfill": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index 5645edd..20655dc 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@vicons/ionicons5": "^0.13.0", "axios": "^1.11.0", "ckplayer": "^3.1.2", + "dplayer": "^1.27.1", "naive-ui": "^2.42.0", "pinia": "^3.0.3", "quill": "^2.0.3", diff --git a/public/images/profile/folder.png b/public/images/profile/folder.png new file mode 100644 index 0000000..7d72984 Binary files /dev/null and b/public/images/profile/folder.png differ diff --git a/public/images/profile/search.png b/public/images/profile/search.png new file mode 100644 index 0000000..eb5deec Binary files /dev/null and b/public/images/profile/search.png differ diff --git a/public/images/studys/study1.png b/public/images/studys/study1.png index d7cc1b4..2d3f818 100644 Binary files a/public/images/studys/study1.png and b/public/images/studys/study1.png differ diff --git a/public/images/studys/study2.png b/public/images/studys/study2.png index dadc8bf..916c23f 100644 Binary files a/public/images/studys/study2.png and b/public/images/studys/study2.png differ diff --git a/public/images/studys/study3.png b/public/images/studys/study3.png deleted file mode 100644 index ce2964f..0000000 Binary files a/public/images/studys/study3.png and /dev/null differ diff --git a/public/images/studys/切片 42@2x.png b/public/images/studys/切片 42@2x.png new file mode 100644 index 0000000..f17218c Binary files /dev/null and b/public/images/studys/切片 42@2x.png differ diff --git a/public/logo/云师大.jpg b/public/logo/云师大.jpg new file mode 100644 index 0000000..4a01488 Binary files /dev/null and b/public/logo/云师大.jpg differ diff --git a/public/logo/德宏师范.jpg b/public/logo/德宏师范.jpg new file mode 100644 index 0000000..4bb3554 Binary files /dev/null and b/public/logo/德宏师范.jpg differ diff --git a/public/logo/曲靖师范.jpg b/public/logo/曲靖师范.jpg new file mode 100644 index 0000000..3fc86a4 Binary files /dev/null and b/public/logo/曲靖师范.jpg differ diff --git a/public/subtitle/sample.vtt b/public/subtitle/sample.vtt new file mode 100644 index 0000000..a052802 --- /dev/null +++ b/public/subtitle/sample.vtt @@ -0,0 +1,46 @@ +WEBVTT + +00:00:01.000 --> 00:00:04.000 +欢迎使用 DPlayer 视频播放器 + +00:00:05.000 --> 00:00:08.000 +这是一个功能强大的 HTML5 视频播放器 + +00:00:09.000 --> 00:00:12.000 +支持多种格式和丰富的功能 + +00:00:13.000 --> 00:00:16.000 +包括倍速播放、清晰度切换等 + +00:00:17.000 --> 00:00:20.000 +感谢使用 DPlayer! + +00:00:21.000 --> 00:00:24.000 +由 DIYGod 开发维护 + +00:00:25.000 --> 00:00:28.000 +开源免费,功能强大 + +00:00:29.000 --> 00:00:32.000 +支持中文字幕显示 + +00:00:33.000 --> 00:00:36.000 +界面美观,用户体验优秀 + +00:00:37.000 --> 00:00:40.000 +移动端适配良好 + +00:00:41.000 --> 00:00:44.000 +支持键盘快捷键操作 + +00:00:45.000 --> 00:00:48.000 +可以自定义主题和样式 + +00:00:49.000 --> 00:00:52.000 +支持弹幕功能 + +00:00:53.000 --> 00:00:56.000 +社区活跃,文档完善 + +00:00:57.000 --> 00:01:00.000 +感谢您的使用! diff --git a/public/top/顶部icon1.png b/public/top/顶部icon1.png index ed17af9..2ee48b5 100644 Binary files a/public/top/顶部icon1.png and b/public/top/顶部icon1.png differ diff --git a/public/top/顶部icon2.png b/public/top/顶部icon2.png index 13246ba..05eb283 100644 Binary files a/public/top/顶部icon2.png and b/public/top/顶部icon2.png differ diff --git a/public/top/顶部icon3.png b/public/top/顶部icon3.png index 70c62ff..75d1cd0 100644 Binary files a/public/top/顶部icon3.png and b/public/top/顶部icon3.png differ diff --git a/public/top/顶部icon4.png b/public/top/顶部icon4.png index 8911f2f..7de3d0f 100644 Binary files a/public/top/顶部icon4.png and b/public/top/顶部icon4.png differ diff --git a/public/top/顶部icon5.png b/public/top/顶部icon5.png index a67e9c3..7ba9a66 100644 Binary files a/public/top/顶部icon5.png and b/public/top/顶部icon5.png differ diff --git a/src/assets/fonts/Alibaba_PuHuiTi_2.0_55_Regular_85_Bold.ttf b/src/assets/fonts/Alibaba_PuHuiTi_2.0_55_Regular_85_Bold.ttf new file mode 100644 index 0000000..05c3f88 Binary files /dev/null and b/src/assets/fonts/Alibaba_PuHuiTi_2.0_55_Regular_85_Bold.ttf differ diff --git a/src/components/VideoPlayerUpgraded.vue b/src/components/VideoPlayerUpgraded.vue new file mode 100644 index 0000000..a88f3d8 --- /dev/null +++ b/src/components/VideoPlayerUpgraded.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/src/components/auth/LoginModal.vue b/src/components/auth/LoginModal.vue index e0a91e4..8a7f194 100644 --- a/src/components/auth/LoginModal.vue +++ b/src/components/auth/LoginModal.vue @@ -38,7 +38,7 @@ @@ -249,7 +249,7 @@ export default { border: 1px solid #D8D8D8; border-radius: 6px; font-size: 12px; - color: #D9D9D9; + color: #000; background: #fff; transition: all 0.2s; } diff --git a/src/components/auth/RegisterModal.vue b/src/components/auth/RegisterModal.vue index 1b7a81d..2d49995 100644 --- a/src/components/auth/RegisterModal.vue +++ b/src/components/auth/RegisterModal.vue @@ -46,7 +46,7 @@ @@ -287,12 +287,13 @@ export default { .form-input { min-width: 278px; + width: 278px; height: 41px; padding: 0 16px 0 30px; border: 1px solid #D8D8D8; border-radius: 6px; font-size: 12px; - color: #D9D9D9; + color: #000; background: #fff; transition: all 0.2s; } diff --git a/src/components/course/DPlayerVideo.vue b/src/components/course/DPlayerVideo.vue new file mode 100644 index 0000000..6e91918 --- /dev/null +++ b/src/components/course/DPlayerVideo.vue @@ -0,0 +1,418 @@ + + + + + diff --git a/src/components/layout/AppHeader.vue b/src/components/layout/AppHeader.vue index 80d77fb..63e9dab 100644 --- a/src/components/layout/AppHeader.vue +++ b/src/components/layout/AppHeader.vue @@ -39,9 +39,9 @@ AI体验 - @@ -126,8 +126,6 @@ import { useI18n } from 'vue-i18n' import { useUserStore } from '@/stores/user' import { - PersonOutline, - LogOutOutline, MenuOutline, CloseOutline } from '@vicons/ionicons5' @@ -189,7 +187,12 @@ const userMenuOptions = computed(() => [ { label: '个人中心', key: 'profile', - icon: () => h(PersonOutline) + icon: () => h('div', { class: 'custom-icon' }, '👤') + }, + { + label: '切换教师端', + key: 'teacher', + icon: () => h('div', { class: 'custom-icon' }, '👨‍🏫') }, { type: 'divider' @@ -197,7 +200,7 @@ const userMenuOptions = computed(() => [ { label: '退出登录', key: 'logout', - icon: () => h(LogOutOutline) + icon: () => h('div', { class: 'custom-icon' }, '🚪') } ]) @@ -244,6 +247,12 @@ const handleUserMenuSelect = (key: string) => { window.location.reload(); }) break + case 'teacher': + // 切换教师端逻辑 + console.log('切换到教师端') + // 这里可以添加切换教师端的逻辑,比如跳转到教师端页面 + router.push('/teacher') + break case 'logout': userStore.logout() router.push('/') @@ -305,370 +314,418 @@ onUnmounted(() => { max-width: none; margin: 0; padding: 0 30px; - height: 100%; + height: 64px; background: white; - position: relative; - z-index: 1001; -} - -/* Logo区域 */ -.logo-section { - flex-shrink: 0; - margin-right: 40px; -} - -.logo { - display: flex; - align-items: center; - cursor: pointer; - gap: 8px; -} - -.logo:hover { - opacity: 0.8; -} - -.logo-image { - width: 72px; - height: 61px; - object-fit: contain; -} - -.nav-icon { - max-width: 12px; - max-height: 12px; - width: auto; - height: auto; - margin-right: 4px; - object-fit: contain; -} - -/* AI图标样式 */ -.ai-icon { - max-width: 34px; - max-height: 34px; - margin-right: 0; -} - -.action-icon { - max-width: 18px; - max-height: 18px; - width: auto; - height: auto; - object-fit: contain; -} - - - -/* 导航菜单 */ -.nav-menu { - display: flex; - align-items: center; - gap: 30px; - flex: 1; - margin-right: 40px; -} - -.nav-item { - display: flex; - align-items: center; - justify-content: center; - padding: 8px 12px; - font-size: 14px; - font-weight: 400; - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - color: #000; - cursor: pointer; - transition: all 0.2s; - white-space: nowrap; - position: relative; - height: 24px; -} - -/* 两个字的导航项:首页 */ -.nav-item:nth-child(1) { - width: 36px; -} - -/* 四个字的导航项:热门好课、专题训练、师资力量、精选资源 */ -.nav-item:nth-child(2), -.nav-item:nth-child(3), -.nav-item:nth-child(4), -.nav-item:nth-child(5) { - width: 72px; -} - -/* 两个字的导航项:活动 */ -.nav-item:nth-child(6) { - width: 36px; - padding-right: 16px; - /* 为HOT标签留出空间 */ -} - -/* AI导航项 */ -.nav-item:nth-child(7) { - /* width: 50px; - height: 40px; */ - background-image: url('/images/ai/ai-bg.png'); - background-repeat: no-repeat; - background-size: cover; - background-position: center; -} - -.nav-item:nth-child(8) { - padding: 0; -} - -.nav-item.active .nav-item-ai { - background: linear-gradient(90deg, #0FAAFF, #79DEFF); - -webkit-background-clip: text; - background-clip: text; - color: transparent; - -webkit-text-fill-color: transparent; - font-weight: bold; -} - -.nav-item-ai:hover { - background: linear-gradient(90deg, #0FAAFF, #79DEFF); - -webkit-background-clip: text; - background-clip: text; - color: transparent; - -webkit-text-fill-color: transparent; - font-weight: bold; -} - -.nav-item:hover { - color: #0084CD; -} - -.nav-item.active { - color: #0084CD; - font-weight: 400; - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - position: relative; -} - -.nav-item.active::after { - content: ''; - position: absolute; - bottom: -6px; - left: 50%; - transform: translateX(-50%); - width: 30px; - height: 2px; - background-color: #0084CD; - border-radius: 1px; -} - -.new-badge { - position: absolute; - top: -10px; - right: -22px; - max-width: 28px; - max-height: 28px; - width: auto; - height: auto; - object-fit: contain; - z-index: 10; -} - - - -/* 搜索区域 */ -.search-section { - display: flex; - align-items: center; - margin-right: 40px; -} - -.search-box { - border-left: 1px solid #ececec; - border-right: 1px solid #ececec; - display: flex; - align-items: center; - padding: 22px 16px; - width: 280px; - transition: all 0.2s; -} - -/* .search-box:hover { - background: #eeeeee; -} */ - -.search-icon { - max-width: 18px; - max-height: 18px; - width: auto; - height: auto; - margin-right: 8px; - object-fit: contain; -} - -.search-input { - flex: 1; - border: none; - background: transparent; - outline: none; - font-size: 14px; - color: #333; -} - -.search-input::placeholder { - color: #999; -} - -/* 移动端汉堡菜单按钮 */ -.mobile-menu-toggle { - display: none; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - cursor: pointer; - border-radius: 6px; - transition: background-color 0.2s; -} - -.mobile-menu-toggle:hover { - background: rgba(0, 0, 0, 0.05); -} - -/* 右侧操作区域 */ -.header-actions { - display: flex; - align-items: center; - gap: 10px; - flex-shrink: 0; -} - -.action-item { - display: flex; - align-items: center; - gap: 4px; - padding: 6px 8px; - font-size: 13px; - color: #000; - cursor: pointer; - border-radius: 4px; - transition: all 0.2s; - white-space: nowrap; -} - -.action-item:hover { - color: #1890ff; - background: #f0f8ff; -} - -/* 语言切换器 */ -.language-switcher { - position: relative; - cursor: pointer; -} - -.language-dropdown { - position: absolute; - top: 100%; - left: 0; - right: 0; - background: white; - border: 1px solid #e8e8e8; - border-radius: 6px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - z-index: 1000; - margin-top: 4px; - min-width: 120px; -} - -.language-option { - padding: 8px 12px; - font-size: 13px; - color: #666; - cursor: pointer; - transition: all 0.2s; - border-bottom: 1px solid #f5f5f5; -} - -.language-option:last-child { - border-bottom: none; -} - -.language-option:hover { - background: #f0f8ff; - color: #1890ff; -} - -.language-text { - white-space: nowrap; -} - -/* 认证按钮 */ -.auth-buttons { - display: flex; - align-items: center; - gap: 12px; -} - -.auth-combined-btn { - display: flex; - align-items: center; - background: #0088D1; - color: white; - border-radius: 5px; - padding: 8px 10px; - font-size: 12px; - font-weight: 400; - cursor: pointer; - transition: all 0.2s; -} - -.auth-combined-btn:hover { - background: #40a9ff; -} - -.auth-login, -.auth-register { - padding: 0 8px; - cursor: pointer; - transition: all 0.2s; -} - -.auth-login:hover, -.auth-register:hover { - opacity: 0.8; -} - -.auth-divider { - color: rgba(255, 255, 255, 0.6); - margin: 0 4px; - font-weight: 300; -} - -/* 用户菜单 */ -.user-menu { - display: flex; - align-items: center; -} - -.user-info { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 12px; - border-radius: 6px; - cursor: pointer; - transition: background 0.2s; -} - -.user-info:hover { - background: #f0f8ff; -} - -.username { - font-size: 14px; - color: #333; - white-space: nowrap; -} - + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1001; + } + + /* Logo区域 */ + .logo-section { + flex-shrink: 0; + margin-right: 40px; + } + + .logo { + display: flex; + align-items: center; + cursor: pointer; + gap: 8px; + } + + .logo:hover { + opacity: 0.8; + } + + .logo-image { + width: 72px; + height: 61px; + object-fit: contain; + } + + .nav-icon { + max-width: 12px; + max-height: 12px; + width: auto; + height: auto; + margin-right: 4px; + object-fit: contain; + } + + /* AI图标样式 */ + .ai-icon { + max-width: 34px; + max-height: 34px; + margin-right: 0; + } + + .action-icon { + max-width: 18px; + max-height: 18px; + width: auto; + height: auto; + object-fit: contain; + } + + + + /* 导航菜单 */ + .nav-menu { + display: flex; + align-items: center; + gap: 30px; + flex: 1; + margin-right: 40px; + } + + .nav-item { + display: flex; + align-items: center; + justify-content: center; + padding: 8px 12px; + font-size: 14px; + font-weight: 400; + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + color: #000; + cursor: pointer; + transition: all 0.2s; + white-space: nowrap; + position: relative; + height: 24px; + } + + /* 两个字的导航项:首页 */ + .nav-item:nth-child(1) { + width: 36px; + } + + /* 四个字的导航项:热门好课、专题训练、师资力量、精选资源 */ + .nav-item:nth-child(2), + .nav-item:nth-child(3), + .nav-item:nth-child(4), + .nav-item:nth-child(5) { + width: 72px; + } + + /* 两个字的导航项:活动 */ + .nav-item:nth-child(6) { + width: 36px; + padding-right: 16px; + /* 为HOT标签留出空间 */ + } + + /* AI导航项 */ + .nav-item:nth-child(7) { + /* width: 50px; + height: 40px; */ + background-image: url('/images/ai/ai-bg.png'); + background-repeat: no-repeat; + background-size: cover; + background-position: center; + } + + .nav-item:nth-child(8) { + padding: 0; + } + + .nav-item.active .nav-item-ai { + background: linear-gradient(90deg, #0FAAFF, #79DEFF); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + font-weight: bold; + } + + .nav-item-ai:hover { + background: linear-gradient(90deg, #0FAAFF, #79DEFF); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + font-weight: bold; + } + + .nav-item:hover { + color: #0084CD; + } + + .nav-item.active { + color: #0084CD; + font-weight: 400; + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + position: relative; + } + + .nav-item.active::after { + content: ''; + position: absolute; + bottom: -6px; + left: 50%; + transform: translateX(-50%); + width: 30px; + height: 2px; + background-color: #0084CD; + border-radius: 1px; + } + + .new-badge { + position: absolute; + top: -10px; + right: -22px; + max-width: 28px; + max-height: 28px; + width: auto; + height: auto; + object-fit: contain; + z-index: 10; + } + + + + /* 搜索区域 */ + .search-section { + display: flex; + align-items: center; + margin-right: 40px; + } + + .search-box { + /* border-left: 1px solid #ececec; + border-right: 1px solid #ececec; */ + display: flex; + align-items: center; + padding: 22px 16px; + width: 280px; + transition: all 0.2s; + } + + /* .search-box:hover { + background: #eeeeee; + } */ + + .search-icon { + max-width: 18px; + max-height: 18px; + width: auto; + height: auto; + margin-right: 8px; + object-fit: contain; + } + + .search-input { + flex: 1; + border: none; + background: transparent; + outline: none; + font-size: 14px; + color: #333; + } + + .search-input::placeholder { + color: #999; + } + + /* 移动端汉堡菜单按钮 */ + .mobile-menu-toggle { + display: none; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + cursor: pointer; + border-radius: 6px; + transition: background-color 0.2s; + } + + .mobile-menu-toggle:hover { + background: rgba(0, 0, 0, 0.05); + } + + /* 右侧操作区域 */ + .header-actions { + display: flex; + align-items: center; + gap: 10px; + flex-shrink: 0; + } + + .action-item { + display: flex; + align-items: center; + gap: 4px; + padding: 6px 8px; + font-size: 13px; + color: #000; + cursor: pointer; + border-radius: 4px; + transition: all 0.2s; + white-space: nowrap; + } + + .action-item:hover { + color: #1890ff; + background: #f0f8ff; + } + + /* 语言切换器 */ + .language-switcher { + position: relative; + cursor: pointer; + } + + .language-dropdown { + position: absolute; + top: 100%; + left: 0; + right: 0; + background: white; + border: 1px solid #e8e8e8; + border-radius: 6px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + z-index: 1000; + margin-top: 4px; + min-width: 120px; + } + + .language-option { + padding: 8px 12px; + font-size: 13px; + color: #666; + cursor: pointer; + transition: all 0.2s; + border-bottom: 1px solid #f5f5f5; + } + + .language-option:last-child { + border-bottom: none; + } + + .language-option:hover { + background: #f0f8ff; + color: #1890ff; + } + + .language-text { + white-space: nowrap; + } + + /* 认证按钮 */ + .auth-buttons { + display: flex; + align-items: center; + gap: 12px; + } + + .auth-combined-btn { + display: flex; + align-items: center; + background: #0088D1; + color: white; + border-radius: 5px; + padding: 8px 10px; + font-size: 12px; + font-weight: 400; + cursor: pointer; + transition: all 0.2s; + } + + .auth-combined-btn:hover { + background: #40a9ff; + } + + .auth-login, + .auth-register { + padding: 0 8px; + cursor: pointer; + transition: all 0.2s; + } + + .auth-login:hover, + .auth-register:hover { + opacity: 0.8; + } + + .auth-divider { + color: rgba(255, 255, 255, 0.6); + margin: 0 4px; + font-weight: 300; + } + + /* 用户菜单 */ + .user-menu { + display: flex; + align-items: center; + } + + .user-info { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + border-radius: 6px; + cursor: pointer; + transition: background 0.2s; + } + + .user-info:hover { + background: #f0f8ff; + } + + .username { + font-size: 14px; + color: #333; + white-space: nowrap; + } + + /* 美化用户菜单样式 */ + :deep(.n-dropdown-menu) { + border-radius: 8px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + border: 1px solid #f0f0f0; + padding: 8px 0; + } + + :deep(.n-dropdown-option) { + padding: 12px 16px; + font-size: 14px; + color: #333; + transition: all 0.2s ease; + border-radius: 0; + } + + :deep(.n-dropdown-option:hover) { + background: linear-gradient(135deg, #f0f8ff, #e6f4ff); + color: #1890ff; + } + + :deep(.n-dropdown-option .n-dropdown-option-icon) { + margin-right: 12px; + font-size: 14px; + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + } + + .custom-icon { + font-size: 14px; + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + } + + /* 分割线样式 */ + :deep(.n-dropdown-divider) { + margin: 8px 0; + border-color: #f0f0f0; + } /* 大屏幕 */ @media (min-width: 1200px) { diff --git a/src/components/layout/AppLayout.vue b/src/components/layout/AppLayout.vue index db7357a..150d462 100644 --- a/src/components/layout/AppLayout.vue +++ b/src/components/layout/AppLayout.vue @@ -40,7 +40,7 @@ import AppFooter from './AppFooter.vue' padding: 0; background: #fff; /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */ - position: sticky; + position: fixed; top: 0; z-index: 1000; flex-shrink: 0; @@ -66,12 +66,19 @@ import AppFooter from './AppFooter.vue' .header { height: 56px; } -} - -@media (max-width: 480px) { - .header { - height: 52px; - } + .content { + padding-top: 56px; + } + } + + @media (max-width: 480px) { + .header { + height: 52px; + } + + .content { + padding-top: 52px; + } } /* 全屏模式样式现在在App.vue中统一管理 */ diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 93d44b6..853772f 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -7,7 +7,7 @@ "resources": "精选资源", "about": "活动", "languageSwitch": "切换语言", - "learningCenter": "学习中心", + "learningCenter": "积分中心", "management": "管理端", "login": "登录", "register": "注册", diff --git a/src/main.ts b/src/main.ts index d68f7bb..24bc150 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ import '@/assets/fonts/AlimamaShuHeiTi-Bold.ttf' import '@/assets/fonts/文道潮黑.ttf' import '@/assets/fonts/庞门正道标题体3.0.ttf' import '@/assets/fonts/DouyinSansBold.otf' +import '@/assets/fonts/Alibaba_PuHuiTi_2.0_55_Regular_85_Bold.ttf' // Naive UI import { diff --git a/src/router/index.ts b/src/router/index.ts index 4bd4e29..d72c8a4 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -23,6 +23,7 @@ import ExamNotice from '@/views/ExamNotice.vue' import ExamSubmitted from '@/views/ExamSubmitted.vue' import TestSections from '@/views/TestSections.vue' import LocalVideoDemo from '@/views/LocalVideoDemo.vue' +import DPlayerTest from '@/views/DPlayerTest.vue' import SpecialTraining from '@/views/SpecialTraining.vue' import SpecialTrainingDetail from '@/views/SpecialTrainingDetail.vue' import HelpCenter from '@/views/HelpCenter.vue' @@ -250,6 +251,14 @@ const routes: RouteRecordRaw[] = [ title: '本地视频播放演示' } }, + { + path: '/dplayer-test', + name: 'DPlayerTest', + component: DPlayerTest, + meta: { + title: 'DPlayer 测试页面' + } + }, { path: '/course/:courseId/practice/:sectionId', name: 'Practice', diff --git a/src/views/Activities.vue b/src/views/Activities.vue index 7a2d259..7ea0a69 100644 --- a/src/views/Activities.vue +++ b/src/views/Activities.vue @@ -289,7 +289,7 @@ onMounted(() => { margin: auto; width: 1420px; display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(4, 1fr); gap: 20px; } diff --git a/src/views/Ai.vue b/src/views/Ai.vue index 0534b43..f321847 100644 --- a/src/views/Ai.vue +++ b/src/views/Ai.vue @@ -420,6 +420,11 @@ onMounted(() => { diff --git a/src/views/DPlayerTest.vue b/src/views/DPlayerTest.vue new file mode 100644 index 0000000..a1583d0 --- /dev/null +++ b/src/views/DPlayerTest.vue @@ -0,0 +1,502 @@ + + + + + diff --git a/src/views/HelpCenter.vue b/src/views/HelpCenter.vue index 4633fdd..8654c68 100644 --- a/src/views/HelpCenter.vue +++ b/src/views/HelpCenter.vue @@ -225,6 +225,13 @@ onActivated(() => { \ No newline at end of file diff --git a/src/views/Profile.vue b/src/views/Profile.vue index f6cfaeb..117286b 100644 --- a/src/views/Profile.vue +++ b/src/views/Profile.vue @@ -14,7 +14,7 @@ - {{ userStore.user?.username || '用户名' }} + {{ userStore.user?.nickname || userStore.user?.username || '用户名' }}
@@ -22,72 +22,81 @@ -
- + 我的课程
-
- + 我的作业
-
- + 我的考试
-
- + 我的练习
-
- + 我的活动
-
- + 我的关注
-
- + 我的消息
-
- + 我的资料
-
- + 我的下载 @@ -238,7 +247,7 @@ fontSize: '14px' }"> {{ detailAssignment.status === '未完成' || detailAssignment.status === '待提交' ? '未完成' : - (detailAssignment.status === '已完成' ? '已完成' : '541人已完成') }} + (detailAssignment.status === '已完成' ? '已完成' : '541人已完成') }}
@@ -361,7 +370,7 @@ 上传作业
- 重新编辑 + 重新编辑
@@ -667,7 +676,7 @@
{{ activity.status === 'ongoing' ? '进行中' : '已结束' - }} + }}
@@ -957,8 +966,7 @@ @@ -978,9 +986,7 @@
@@ -1244,6 +1250,7 @@ const userStore = useUserStore() type TabType = 'courses' | 'homework' | 'exam' | 'practice' | 'activity' | 'follows' | 'message' | 'materials' | 'download' const activeTab = ref('courses') +const hoveredTab = ref(null) const activeCourseTab = ref('all') // 作业筛选状态 @@ -2486,6 +2493,11 @@ const handleDownloadTabChange = (tab: string) => { // 筛选后的下载文件 const filteredDownloadFiles = computed(() => { + // 如果在子目录中,显示空内容(因为目前没有子目录的文件数据) + if (isInSubDirectory.value) { + return [] + } + let files = downloadFiles.filter(file => file.category === activeDownloadTab.value) if (downloadFilter.type !== 'all') { @@ -2507,10 +2519,14 @@ const toggleFileMenu = (fileId: number) => { } const handleFileClick = (file: any) => { - if (file.type === 'folder' && file.name === '图片') { - // 点击图片文件夹,进入子目录 + if (file.type === 'folder') { + // 点击任何文件夹,进入子目录 isInSubDirectory.value = true - currentPath.value = ['课件', '图片'] + currentPath.value = ['课件', file.name] + message.info(`进入文件夹:${file.name}`) + } else { + // 点击文件,显示文件详情或下载 + message.info(`打开文件:${file.name}`) } } @@ -2536,12 +2552,9 @@ const getFileIcon = (fileId?: number) => { ] const index = (fileId || 0) % homeworkImages.length return homeworkImages[index] - } else if (isInSubDirectory.value) { - // 子目录使用子目录图标 - return 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPngf45333052202c303acc2c06223c26b820d330459ce2d452a21a3132fbbeab442' } else { // 默认文件夹图标 - return 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng5548891b00234027dbe6dadafbd83596d616261421c0587a85652dc194b2d5ef' + return '/images/profile/folder.png' } } @@ -2930,9 +2943,8 @@ onActivated(() => { /* 去掉背景色 */ border-radius: 0.6vw; /* 12px转换为vw */ - margin: 2.55vh 0; + margin: 2.55vh 0 0 0; /* 去掉左右边距,因为父容器已经居中 */ - padding: 1.04vh 0; /* 20px 0转换 */ display: flex; flex-direction: column; @@ -2967,7 +2979,7 @@ onActivated(() => { /* 自适应高度 */ min-height: 3vh; /* 设置最小高度,让盒子更大 */ - margin: 1.5vh; + margin: 1.5vh 0 0 0; /* 减小间距:从2.34vh减少到1.5vh */ display: flex; align-items: center; @@ -4186,9 +4198,9 @@ onActivated(() => { } .course-name { - margin-top: 10px; - margin-left: 83px; - color: #999999; + /* margin-top: 10px; */ + margin-left: 5px; + color: #497087; } .course-name span { @@ -5744,7 +5756,7 @@ onActivated(() => { /* 0 0 16px 0转换 */ line-height: 1.4; padding: 0 1.04vw; - /* 添加左右内边距 */ + font-weight: 700; } .activity-details { @@ -6172,7 +6184,7 @@ onActivated(() => { /* height: 5.21vh; */ padding: 0.52vh 0.57vw; /* 100px转换为vh,进一步增加高度 */ - background: url('https://lanhu-oss-2537-2.lanhuapp.com/SketchPng9491a7fe5bdac8e8a88de63907163bd6b8a259824f56a3c76784ba6cdc7bc32b') 100% no-repeat; + background: #F5F8FB; background-size: 100% 100%; margin-top: 0.26vh; /* 5px转换为vh */ @@ -7058,6 +7070,7 @@ onActivated(() => { box-sizing: border-box; display: flex; align-items: center; + padding-left: 15px; } .password-form-input { @@ -7609,7 +7622,7 @@ onActivated(() => { /* 4px转换为vw,减小图标和文字间距 */ padding: 0.52vh 0.73vw; /* 10px 14px转换 */ - font-size: 10px; + font-size: 12px; /* 14px转换为vw */ font-family: Helvetica, 'Microsoft YaHei', Arial, sans-serif; color: #000; @@ -8066,7 +8079,7 @@ onActivated(() => { width: 80px; height: 23px; border: none; - font-size: 10px; + font-size: 12px; cursor: pointer; transition: all 0.3s ease; white-space: nowrap; diff --git a/src/views/TeacherDetail.vue b/src/views/TeacherDetail.vue index a11172d..6e69508 100644 --- a/src/views/TeacherDetail.vue +++ b/src/views/TeacherDetail.vue @@ -201,7 +201,200 @@ const loadCourses = async () => { await new Promise(resolve => setTimeout(resolve, 500)) // 筛选逻辑 - let filteredCourses: Course[] = [] // 暂时使用空数组,后续可以从API获取 + let filteredCourses: Course[] = [ + { + id: '1', + title: '教育心理学基础课程', + description: '本课程深入讲解教育心理学的基本理论和实践应用,帮助学生理解学习过程中的心理机制。', + thumbnail: '/images/courses/course1.png', + price: 0, + currency: 'CNY', + rating: 4.8, + ratingCount: 125, + studentsCount: 1250, + duration: '12小时43分钟', + totalLessons: 54, + level: 'beginner', + language: 'zh-CN', + category: { id: 1, name: '教育培训', slug: 'education-training' }, + tags: ['心理学', '教育', '基础'], + skills: ['心理分析', '教育理论'], + requirements: ['无特殊要求'], + objectives: ['掌握教育心理学基础理论'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '资深教育心理学专家', + rating: 4.8, + studentsCount: 1250, + coursesCount: 6, + experience: '15年', + education: ['云南师范大学', '教育心理学博士'], + certifications: ['高级心理咨询师', '教育技术专家'] + }, + status: 'published', + createdAt: '2024-01-15T10:00:00Z', + updatedAt: '2024-01-15T10:00:00Z' + }, + { + id: '2', + title: '现代教育技术应用', + description: '探索现代教育技术在课堂教学中的应用,包括多媒体教学、在线教育平台等。', + thumbnail: '/images/courses/course2.png', + price: 0, + currency: 'CNY', + rating: 4.6, + ratingCount: 89, + studentsCount: 890, + duration: '10小时20分钟', + totalLessons: 42, + level: 'intermediate', + language: 'zh-CN', + category: { id: 2, name: '技术应用', slug: 'tech-application' }, + tags: ['教育技术', '多媒体', '在线教育'], + skills: ['多媒体制作', '在线教学'], + requirements: ['基础计算机操作'], + objectives: ['掌握现代教育技术应用'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '资深教育技术专家', + rating: 4.6, + studentsCount: 890, + coursesCount: 6, + experience: '15年', + education: ['云南师范大学', '教育技术博士'], + certifications: ['高级教育技术专家', '多媒体制作师'] + }, + status: 'published', + createdAt: '2024-02-20T14:30:00Z', + updatedAt: '2024-02-20T14:30:00Z' + }, + { + id: '3', + title: '课程设计与开发', + description: '学习如何设计和开发高质量的课程内容,包括教学目标制定、教学内容组织等。', + thumbnail: '/images/courses/course3.png', + price: 0, + currency: 'CNY', + rating: 4.7, + ratingCount: 67, + studentsCount: 567, + duration: '15小时30分钟', + totalLessons: 68, + level: 'advanced', + language: 'zh-CN', + category: { id: 3, name: '课程设计', slug: 'course-design' }, + tags: ['课程设计', '教学开发', '教育'], + skills: ['课程规划', '教学设计'], + requirements: ['教育理论基础'], + objectives: ['掌握课程设计方法'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '课程设计专家' + }, + status: 'published', + createdAt: '2024-03-10T09:15:00Z', + updatedAt: '2024-03-10T09:15:00Z' + }, + { + id: '4', + title: '教育研究方法论', + description: '系统介绍教育研究的基本方法和技巧,培养学生进行教育研究的能力。', + thumbnail: '/images/courses/course4.png', + price: 0, + currency: 'CNY', + rating: 4.5, + ratingCount: 43, + studentsCount: 432, + duration: '8小时15分钟', + totalLessons: 36, + level: 'intermediate', + language: 'zh-CN', + category: { id: 4, name: '研究方法', slug: 'research-methods' }, + tags: ['研究方法', '教育', '学术'], + skills: ['研究设计', '数据分析'], + requirements: ['统计学基础'], + objectives: ['掌握教育研究方法'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '教育研究专家' + }, + status: 'published', + createdAt: '2024-01-25T16:45:00Z', + updatedAt: '2024-01-25T16:45:00Z' + }, + { + id: '5', + title: '学生心理辅导技巧', + description: '学习如何对学生进行心理辅导,掌握基本的心理咨询和辅导技巧。', + thumbnail: '/images/courses/course5.png', + price: 0, + currency: 'CNY', + rating: 4.9, + ratingCount: 78, + studentsCount: 678, + duration: '6小时45分钟', + totalLessons: 28, + level: 'beginner', + language: 'zh-CN', + category: { id: 5, name: '心理辅导', slug: 'psychological-counseling' }, + tags: ['心理辅导', '学生', '技巧'], + skills: ['心理咨询', '沟通技巧'], + requirements: ['心理学基础'], + objectives: ['掌握心理辅导技巧'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '心理咨询专家' + }, + status: 'published', + createdAt: '2024-02-05T11:20:00Z', + updatedAt: '2024-02-05T11:20:00Z' + }, + { + id: '6', + title: '教育评估与测量', + description: '学习教育评估的基本理论和方法,掌握教育测量的技术和工具。', + thumbnail: '/images/courses/course5.png', + price: 0, + currency: 'CNY', + rating: 4.4, + ratingCount: 34, + studentsCount: 345, + duration: '9小时20分钟', + totalLessons: 40, + level: 'advanced', + language: 'zh-CN', + category: { id: 6, name: '教育评估', slug: 'education-assessment' }, + tags: ['教育评估', '测量', '技术'], + skills: ['评估设计', '测量技术'], + requirements: ['教育统计学'], + objectives: ['掌握教育评估方法'], + instructor: { + id: 1, + name: '汪波', + avatar: '/images/Teachers/师资力量1.png', + title: '云南师范大学教授', + bio: '教育评估专家' + }, + status: 'published', + createdAt: '2024-03-15T13:10:00Z', + updatedAt: '2024-03-15T13:10:00Z' + } + ] // 使用模拟数据,后续可以从API获取 // 按学科筛选 if (selectedSubject.value !== '全部') { @@ -502,7 +695,7 @@ onMounted(() => { overflow: hidden; transition: transform 0.2s, box-shadow 0.2s; cursor: pointer; - min-height: 350px; + /* min-height: 350px; */ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); }