diff --git a/src/components/auth/LoginModal.vue b/src/components/auth/LoginModal.vue index 728e043..a920ab1 100644 --- a/src/components/auth/LoginModal.vue +++ b/src/components/auth/LoginModal.vue @@ -38,7 +38,7 @@ @@ -48,6 +48,7 @@ export default { diff --git a/src/components/auth/RegisterModal.vue b/src/components/auth/RegisterModal.vue index 2d49995..2d16be0 100644 --- a/src/components/auth/RegisterModal.vue +++ b/src/components/auth/RegisterModal.vue @@ -46,7 +46,7 @@ @@ -56,6 +56,7 @@ export default { diff --git a/src/components/course/DPlayerVideo.vue b/src/components/course/DPlayerVideo.vue index 6e91918..f832b37 100644 --- a/src/components/course/DPlayerVideo.vue +++ b/src/components/course/DPlayerVideo.vue @@ -88,18 +88,51 @@ const loadDPlayer = (): Promise => { return } - // 加载 CSS - const cssLink = document.createElement('link') - cssLink.rel = 'stylesheet' - cssLink.href = 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.css' - document.head.appendChild(cssLink) + // 尝试多个CDN源 + const cdnSources = [ + { + css: 'https://unpkg.com/dplayer@1.27.1/dist/DPlayer.min.css', + js: 'https://unpkg.com/dplayer@1.27.1/dist/DPlayer.min.js' + }, + { + css: 'https://cdn.bootcdn.net/ajax/libs/dplayer/1.27.1/DPlayer.min.css', + js: 'https://cdn.bootcdn.net/ajax/libs/dplayer/1.27.1/DPlayer.min.js' + }, + { + css: 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.css', + js: 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js' + } + ] - // 加载 JS - const script = document.createElement('script') - script.src = 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js' - script.onload = () => resolve() - script.onerror = () => reject(new Error('Failed to load DPlayer')) - document.head.appendChild(script) + let currentIndex = 0 + + const tryLoadFromCDN = () => { + if (currentIndex >= cdnSources.length) { + reject(new Error('All CDN sources failed to load DPlayer')) + return + } + + const source = cdnSources[currentIndex] + + // 加载 CSS + const cssLink = document.createElement('link') + cssLink.rel = 'stylesheet' + cssLink.href = source.css + document.head.appendChild(cssLink) + + // 加载 JS + const script = document.createElement('script') + script.src = source.js + script.onload = () => resolve() + script.onerror = () => { + console.warn(`Failed to load DPlayer from ${source.js}, trying next CDN...`) + currentIndex++ + tryLoadFromCDN() + } + document.head.appendChild(script) + } + + tryLoadFromCDN() }) } @@ -278,12 +311,13 @@ onUnmounted(() => { position: relative; width: 100%; height: 578px; - background: #000; + background: transparent; } .dplayer-wrapper { width: 100%; height: 100%; + background: transparent; } .video-placeholder { @@ -298,7 +332,7 @@ onUnmounted(() => { background-size: cover; background-position: center; background-repeat: no-repeat; - background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: transparent; color: white; cursor: pointer; } @@ -310,8 +344,9 @@ onUnmounted(() => { left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.4); + background: rgba(0, 0, 0, 0.3); z-index: 1; + border-radius: 12px; } .placeholder-content { diff --git a/src/router/index.ts b/src/router/index.ts index df2ac2e..4d14738 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -196,6 +196,14 @@ const routes: RouteRecordRaw[] = [ }, // 首页与课程 + { + path: '/service-agreement', + name: 'ServiceAgreement', + component: () => import('@/views/ServiceAgreement.vue'), + meta: { + title: '服务协议与隐私政策' + } + }, { path: '/', name: 'Home', diff --git a/src/views/Ai.vue b/src/views/Ai.vue index f321847..8939207 100644 --- a/src/views/Ai.vue +++ b/src/views/Ai.vue @@ -2818,4 +2818,242 @@ button:active { line-height: 18px; margin-top: 25px; } + +/* 响应式设计 */ +@media (max-width: 1200px) { + .page { + width: 100% !important; + max-width: 1200px; + margin: 0 auto; + } + + .block_1 { + width: 100% !important; + height: auto !important; + } + + .section_1 { + width: 100% !important; + height: auto !important; + padding: 0 20px; + } + + .text-wrapper_2 { + text-align: center; + margin-bottom: 30px; + } + + .group_3 { + flex-wrap: wrap; + justify-content: center; + gap: 10px; + margin-bottom: 30px; + } + + .group_6 { + flex-direction: column; + gap: 20px; + } + + .group_27 { + flex-direction: column; + gap: 20px; + } +} + +@media (max-width: 1024px) { + .section_1 { + padding: 0 20px; + } + + .group_6 { + flex-direction: column; + gap: 20px; + } + + .group_12 { + flex-direction: column; + gap: 20px; + } + + .group_21 { + flex-direction: column; + gap: 20px; + } + + /* 调整卡片宽度 */ + .box_5, .group_13, .group_18, .group_20, .group_22, .group_23 { + width: 100% !important; + } +} + +@media (max-width: 768px) { + .section_1 { + padding: 0 15px; + } + + .text_13 { + font-size: 28px !important; + } + + .text_14 { + font-size: 16px !important; + } + + .group_3 { + flex-direction: column; + align-items: center; + gap: 15px; + } + + .group_6 { + gap: 15px; + } + + .box_5 { + width: 100% !important; + } + + .group_27 { + flex-direction: column; + gap: 15px; + } + + .box_18, .box_20, .box_21, .box_22 { + width: 100% !important; + margin-bottom: 15px; + } + + /* 调整图片尺寸 */ + .image_7, .image_8, .image_9, .image_10, .image_11, + .image_12, .image_13, .image_14, .image_15, .image_16, + .image_17, .image_18 { + width: 100% !important; + height: auto !important; + max-height: 200px; + object-fit: cover; + } + + /* 左侧导航区域调整 */ + .group_5 { + flex-direction: column; + align-items: center; + gap: 10px; + margin-bottom: 20px; + } + + /* 项目卡片调整 */ + .group_12 { + flex-direction: column; + gap: 20px; + } + + .group_13 { + width: 100% !important; + } + + .group_18, .group_20 { + width: 100% !important; + margin-bottom: 20px; + } + + /* 底部导航调整 */ + .group_21 { + flex-direction: column; + gap: 20px; + } + + .group_22, .group_23 { + width: 100% !important; + } +} + +@media (max-width: 480px) { + .section_1 { + padding: 0 10px; + } + + .text_13 { + font-size: 24px !important; + } + + .text_14 { + font-size: 14px !important; + } + + .group_3 { + gap: 10px; + } + + .group_6, .group_27 { + gap: 10px; + } + + /* 文字大小调整 */ + .text_19, .text_20, .text_32, .text_35, .text_38, .text_41 { + font-size: 14px !important; + white-space: normal !important; + word-wrap: break-word; + } + + .text_33, .text_36, .text_39, .text_42, .text_47, .text_50, .text_53, .text_56 { + font-size: 12px !important; + line-height: 1.4 !important; + white-space: normal !important; + word-wrap: break-word; + } + + /* 按钮和交互元素调整 */ + .image-text_1, .image-text_2, .image-text_3, .image-text_15, .image-text_16 { + padding: 8px !important; + min-height: 40px; + } + + /* 卡片内边距调整 */ + .box_5, .box_11, .box_13, .box_18, .box_19, .box_20, .box_21, .box_22 { + padding: 15px !important; + } + + /* 标题文字换行 */ + .paragraph_1, .paragraph_2, .paragraph_3, .paragraph_4 { + white-space: normal !important; + word-wrap: break-word; + line-height: 1.3 !important; + } +} + +/* 通用响应式修复 */ +@media (max-width: 1920px) { + /* 修复所有固定宽度元素 */ + .page, .block_1, .section_1, .group_1, .group_2 { + width: 100% !important; + max-width: 100vw; + } + + /* 确保内容不会溢出 */ + * { + max-width: 100%; + box-sizing: border-box; + } + + /* 图片响应式 */ + img { + max-width: 100%; + height: auto; + } + + /* 文本容器响应式 */ + .text-wrapper_2, .text-group_1, .text-group_2, .text-group_3, + .text-group_13, .text-group_14, .text-group_15, .text-group_16, + .text-group_19, .text-group_20, .text-group_21, .text-group_22, + .text-group_23, .text-group_24, .text-group_25, .text-group_26, + .text-group_27, .text-group_28, .text-group_29, .text-group_30, + .text-group_31, .text-group_32, .text-group_33, .text-group_34, + .text-group_35, .text-group_36, .text-group_37, .text-group_38, + .text-group_39, .text-group_40, .text-group_41, .text-group_42, + .text-group_43 { + width: auto !important; + max-width: 100%; + } +} \ No newline at end of file diff --git a/src/views/Faculty.vue b/src/views/Faculty.vue index e8453cd..c230257 100644 --- a/src/views/Faculty.vue +++ b/src/views/Faculty.vue @@ -38,13 +38,15 @@
-
+
-
+

课程介绍:

主讲课程为《Python语言程序设计》、《动画原理与实现》、《虚拟现实技术与应用》等。

@@ -135,6 +137,16 @@ const toggleCourseInfo = (teacherId: number) => { } } +// 鼠标悬停显示课程信息 +const showCourseInfo = (teacherId: number) => { + expandedTeacherId.value = teacherId +} + +// 鼠标离开隐藏课程信息 +const hideCourseInfo = (teacherId: number) => { + expandedTeacherId.value = null +} + // 筛选标签数据 const filterTabs = ref([ { id: 'all', name: '全部' }, @@ -586,11 +598,13 @@ height: 37px; /* box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); */ z-index: 10; transform: translateY(100%); - transition: transform 0.3s ease-out; + opacity: 0; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); } .course-info-box.active { transform: translateY(0); + opacity: 1; } .course-info-content { @@ -627,10 +641,7 @@ height: 37px; box-shadow: -2px -2px 4px rgba(0, 0, 0, 0.1); } */ -.faculty-card:hover .course-info-box, -.course-info-box:hover { - transform: translateY(0); -} +/* 移除冲突的hover样式,改用JavaScript控制 */ /* 箭头按钮旋转动画 */ /* .card-arrow { diff --git a/src/views/Home.vue b/src/views/Home.vue index 2411ddd..68ba811 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -6,7 +6,7 @@

中小学教师人工智能素养提升在线学习平台

为教师量身定制,帮助教师快速掌握AI技术、教学应用与伦理规范,赋能智慧课堂

- +
@@ -538,7 +538,25 @@ const router = useRouter() const courseStore = useCourseStore() // @ts-ignore const userStore = useUserStore() -const { loginModalVisible, registerModalVisible, handleAuthSuccess } = useAuth() +const { loginModalVisible, registerModalVisible, handleAuthSuccess: originalHandleAuthSuccess } = useAuth() + +// 自定义认证成功处理,登录后跳转到个人中心 +const handleAuthSuccess = () => { + originalHandleAuthSuccess() + // 登录成功后跳转到个人中心 + router.push('/profile') +} + +// 跳转到个人中心页面(需要登录检查) +const goToCoursesPage = () => { + if (userStore.isLoggedIn) { + // 已登录,跳转到个人中心 + router.push('/profile') + } else { + // 未登录,显示登录模态框 + loginModalVisible.value = true + } +} // 跳转到课程详情页面 const goToCourseDetail = async (courseId: string) => { diff --git a/src/views/Profile.vue b/src/views/Profile.vue index 20a39c5..a33bdae 100644 --- a/src/views/Profile.vue +++ b/src/views/Profile.vue @@ -2290,7 +2290,7 @@ const isMessageTab = computed(() => activeTab.value === 'message') // 处理菜单选择 const handleMenuSelect = (key: TabType) => { activeTab.value = key - message.info(`切换到${getTabTitle(key)}`) + // message.info(`切换到${getTabTitle(key)}`) } // 获取状态文本 @@ -4280,6 +4280,44 @@ onActivated(() => { padding: 16px; min-height: 240px; } + + /* 考试标题在小屏幕上给分数留出空间并允许换行 */ + .exam-title { + padding-right: 80px; /* 给分数徽章留出空间 */ + word-wrap: break-word; + word-break: break-word; + white-space: normal; + } + + /* 分数徽章保持在右上角不换行 */ + .exam-score-badge { + position: absolute; + top: 16px; + right: 16px; + white-space: nowrap; + } +} + +/* 更小屏幕的适配 */ +@media (max-width: 480px) { + .exam-card { + padding: 12px; + min-height: 220px; + } + + .exam-title { + padding-right: 70px; /* 给分数徽章留出更多空间 */ + font-size: 14px; + } + + .exam-score-badge { + top: 12px; + right: 12px; + } + + .score-text { + font-size: 16px; + } } /* 简化的作业卡片样式 */ diff --git a/src/views/ServiceAgreement.vue b/src/views/ServiceAgreement.vue new file mode 100644 index 0000000..309632b --- /dev/null +++ b/src/views/ServiceAgreement.vue @@ -0,0 +1,185 @@ + + + + +