移动端适配
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<!-- 课程信息看板 -->
|
||||
<div class="course-info-panel">
|
||||
<div class="panel-container">
|
||||
<!-- 左侧:课程封面 -->
|
||||
<!-- 课程封面 -->
|
||||
<div class="course-cover">
|
||||
<img
|
||||
:src="courseItemVO.coverImage ? FILE_DOWNLOAD_URL + courseItemVO.coverImage : defaultCover"
|
||||
@@ -24,7 +24,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:课程信息 -->
|
||||
<!-- 课程信息 -->
|
||||
<div class="course-info">
|
||||
<div class="info-content">
|
||||
<!-- 课程标题 -->
|
||||
@@ -65,14 +65,6 @@
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="action-buttons">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="handleStartLearning"
|
||||
:loading="enrolling"
|
||||
>
|
||||
{{ isEnrolled ? '继续学习' : '开始学习' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="large"
|
||||
:plain="!isCollected"
|
||||
@@ -81,6 +73,15 @@
|
||||
<el-icon><Star /></el-icon>
|
||||
收藏课程
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="handleStartLearning"
|
||||
:loading="enrolling"
|
||||
>
|
||||
{{ isEnrolled ? '继续学习' : '开始学习' }}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -500,6 +501,13 @@ function formatDuration(minutes?: number): string {
|
||||
background: #FFFFFF;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
|
||||
// 移动端垂直布局
|
||||
@media (max-width: 768px) {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,6 +523,12 @@ function formatDuration(minutes?: number): string {
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
// 移动端全宽
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.course-info {
|
||||
@@ -529,6 +543,11 @@ function formatDuration(minutes?: number): string {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
// 移动端样式调整
|
||||
@media (max-width: 768px) {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.course-title {
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
@@ -634,6 +653,12 @@ function formatDuration(minutes?: number): string {
|
||||
align-items: center;
|
||||
gap: 27px;
|
||||
|
||||
// 移动端按钮布局 - 保持水平排列
|
||||
@media (max-width: 768px) {
|
||||
gap: 12px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
@@ -651,6 +676,12 @@ function formatDuration(minutes?: number): string {
|
||||
background: #d32f2f;
|
||||
border-color: #d32f2f;
|
||||
}
|
||||
|
||||
// 移动端等宽
|
||||
@media (max-width: 768px) {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.el-button--default {
|
||||
@@ -658,6 +689,12 @@ function formatDuration(minutes?: number): string {
|
||||
border-color: #86909C;
|
||||
color: #86909C;
|
||||
|
||||
// 移动端等宽
|
||||
@media (max-width: 768px) {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
<el-button circle :icon="Expand" />
|
||||
</div>
|
||||
|
||||
<!-- 移动端遮罩层(侧边栏展开时显示) -->
|
||||
<div v-if="isMobile && !sidebarCollapsed" class="mobile-overlay" @click="toggleSidebar"></div>
|
||||
|
||||
<!-- 左侧:章节目录 -->
|
||||
<div class="chapter-sidebar" :class="{ collapsed: sidebarCollapsed }">
|
||||
<div class="sidebar-header">
|
||||
@@ -179,7 +182,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { ref, computed, watch, onMounted, onBeforeUnmount, onUnmounted, nextTick } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {
|
||||
@@ -230,6 +233,7 @@ const currentChapterIndex = ref(0);
|
||||
const currentNodeIndex = ref(0);
|
||||
const sidebarCollapsed = ref(false);
|
||||
const activeChapters = ref<number[]>([0]);
|
||||
const isMobile = ref(false);
|
||||
const articleData = ref<any>(null);
|
||||
const contentAreaRef = ref<HTMLElement | null>(null);
|
||||
|
||||
@@ -348,8 +352,31 @@ watch(currentNode, async () => {
|
||||
onMounted(() => {
|
||||
// 不在这里启动定时器,等待学习记录加载完成后再启动
|
||||
// startLearningTimer(); 移到loadLearningRecord和createLearningRecord成功后
|
||||
|
||||
// 检查移动端并设置侧边栏默认状态
|
||||
checkMobile();
|
||||
window.addEventListener('resize', checkMobile);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', checkMobile);
|
||||
});
|
||||
|
||||
// 检查是否为移动端
|
||||
function checkMobile() {
|
||||
const wasMobile = isMobile.value;
|
||||
isMobile.value = window.innerWidth < 768;
|
||||
|
||||
// 如果是初始化或从桌面端切换到移动端,默认收起侧边栏
|
||||
if (isMobile.value && (!wasMobile || wasMobile === undefined)) {
|
||||
sidebarCollapsed.value = true;
|
||||
}
|
||||
// 如果从移动端切换到桌面端,默认展开侧边栏
|
||||
else if (!isMobile.value && wasMobile) {
|
||||
sidebarCollapsed.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopLearningTimer();
|
||||
saveLearningProgress();
|
||||
@@ -1074,6 +1101,21 @@ function handleBack() {
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-overlay {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.chapter-sidebar {
|
||||
width: 320px;
|
||||
background: #fff;
|
||||
@@ -1086,6 +1128,22 @@ function handleBack() {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 移动端适配
|
||||
@media (max-width: 768px) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
width: 280px; // 移动端稍窄一些
|
||||
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
|
||||
|
||||
&.collapsed {
|
||||
left: -280px; // 滑出屏幕外
|
||||
width: 280px; // 保持宽度用于动画
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -898,26 +898,163 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
// 移动端响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.task-detail {
|
||||
.back-header {
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
.task-content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.task-info {
|
||||
.task-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
.task-info-card {
|
||||
.task-info-section {
|
||||
.task-title {
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.task-meta {
|
||||
.meta-row {
|
||||
flex-direction: column;
|
||||
.task-description {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.task-meta {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 16px; // 垂直间距8px,水平间距16px
|
||||
align-items: center;
|
||||
|
||||
.meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap; // 防止单个meta-item内部换行
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
color: #6B7280;
|
||||
}
|
||||
|
||||
.creator-avatar,
|
||||
.meta-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.meta-divider {
|
||||
display: none; // 移动端隐藏分隔线
|
||||
}
|
||||
}
|
||||
|
||||
// 关键修改:统计卡片改为2x2网格布局
|
||||
.task-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
|
||||
.stat-card {
|
||||
width: 100%;
|
||||
height: 88px;
|
||||
padding: 16px 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #E5E7EB;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
.stat-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: #6B7280;
|
||||
font-weight: 500;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #1F2937;
|
||||
line-height: 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
.meta-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
flex-shrink: 0;
|
||||
object-fit: contain;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-section {
|
||||
padding: 16px 20px;
|
||||
height: auto;
|
||||
margin-top: 16px;
|
||||
|
||||
.progress-header {
|
||||
.progress-label,
|
||||
.progress-value {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar-container .progress-bar {
|
||||
height: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-stats {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
.task-content-section {
|
||||
margin-top: 16px;
|
||||
|
||||
.course-card,
|
||||
.resource-card {
|
||||
margin-top: 16px;
|
||||
|
||||
:deep(.el-card__header) {
|
||||
padding: 16px;
|
||||
|
||||
.card-header {
|
||||
.header-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.item-count {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,6 +1062,37 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
.resource-item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 16px;
|
||||
gap: 12px;
|
||||
|
||||
.course-index,
|
||||
.resource-index {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.course-info,
|
||||
.resource-info {
|
||||
width: 100%;
|
||||
|
||||
.course-name-row,
|
||||
.resource-name-row {
|
||||
.course-name,
|
||||
.resource-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.course-meta,
|
||||
.resource-meta {
|
||||
margin-top: 8px;
|
||||
|
||||
.progress-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.course-action,
|
||||
.resource-action {
|
||||
@@ -932,6 +1100,8 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
|
||||
.el-button {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user