feat:增加移动端布局

This commit is contained in:
2026-08-03 15:49:37 +08:00
parent 94afc1519c
commit 7ae51438f4
9 changed files with 132 additions and 106 deletions

View File

@@ -220,49 +220,6 @@ const submitForm = async () => {
.md-editor {
height: auto;
}
.generate-question {
display: flex;
flex-direction: column;
gap: 10px;
.generate-action {
display: flex;
align-items: center;
gap: 10px;
}
}
.question-list {
display: flex;
flex-direction: column;
gap: 10px;
.question-card {
.el-card__body {
display: flex;
flex-direction: column;
gap: 10px;
}
.question-title {
font-weight: 600;
}
.question-options {
padding-left: 16px;
}
.question-answer {
color: #67c23a;
font-size: 13px;
}
.question-action {
text-align: right;
}
}
}
}
}
</style>

View File

@@ -15,9 +15,11 @@
</div>
<div class="card-actions">
<el-button type="primary" :icon="Edit" @click="editClick(file)">编辑</el-button>
<el-button type="primary" v-if="!appStore.isMobile"
:icon="Edit" @click="editClick(file)">编辑</el-button>
<el-button type="primary" :icon="Aim" @click="trainClick(file)">训练</el-button>
<el-button type="danger" :icon="Delete">删除</el-button>
<el-button type="danger" v-if="!appStore.isMobile"
:icon="Delete">删除</el-button>
</div>
</div>
@@ -30,6 +32,7 @@ import { Delete, Edit, Picture, Document, Aim } from '@element-plus/icons-vue'
import { useLibraryStore } from '@/stores/library.ts'
import { usePracticeStore } from '@/stores/practice.ts'
import { useQuestionStore } from '@/stores/question.ts'
import { useAppStore } from '@/stores/app.ts'
import type { ILibraryFile } from '@/types/library.ts'
import LibraryFilter from '@/components/Library/LibraryFilter.vue'
import { computed } from 'vue'
@@ -40,6 +43,7 @@ import { ElLoading, ElMessage } from 'element-plus'
const libraryStore = useLibraryStore()
const practiceStore = usePracticeStore()
const questionStore = useQuestionStore()
const appStore = useAppStore()
const filterLibraryFileList = computed(() => {
const subject = libraryStore.selectedSubject

View File

@@ -119,7 +119,7 @@ const addMistakeList = async () => {
gap: 16px;
.question-list {
padding: 10px;
padding: 0 10px;
background: #fff;
border-radius: 12px;

16
src/layout/AppLogo.vue Normal file
View File

@@ -0,0 +1,16 @@
<template>
<div class="logo" @click="refreshClick">
<span v-if="!appStore.isCollapse">🧠 智能学习助手</span>
<span v-else>🧠</span>
</div>
</template>
<script setup lang="ts">
import { useAppStore } from '@/stores/app.ts'
const appStore = useAppStore()
const refreshClick = () => {
location.reload()
}
</script>

35
src/layout/AppMenu.vue Normal file
View File

@@ -0,0 +1,35 @@
<template>
<el-menu
:default-active="route.path"
:collapse="appStore.isCollapse"
:collapse-transition="false"
router
class="side-menu"
>
<el-menu-item index="/library">
<el-icon><Reading /></el-icon>
<template #title>知识库</template>
</el-menu-item>
<el-menu-item index="/exam">
<el-icon><EditPen /></el-icon>
<template #title>考试中心</template>
</el-menu-item>
<el-menu-item index="/mistakes">
<el-icon><Notebook /></el-icon>
<template #title>错题本</template>
</el-menu-item>
<el-menu-item index="/stats">
<el-icon><DataLine /></el-icon>
<template #title>数据统计</template>
</el-menu-item>
</el-menu>
</template>
<script setup lang="ts">
import { DataLine, EditPen, Notebook, Reading } from '@element-plus/icons-vue'
import { useRoute } from 'vue-router'
import { useAppStore } from '@/stores/app.ts'
const route = useRoute()
const appStore = useAppStore()
</script>

View File

@@ -1,50 +1,29 @@
<template>
<el-container class="layout-container">
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '64px' : '150px'" class="aside">
<!-- Logo -->
<div class="logo" @click="refreshClick">
<span v-if="!isCollapse">🧠 智能学习助手</span>
<span v-else>🧠</span>
</div>
<el-drawer
v-if="appStore.isMobile"
v-model="appStore.drawerVisible"
direction="ltr"
size="180px"
:with-header="false"
>
<app-logo />
<app-menu />
</el-drawer>
<!-- 菜单 -->
<el-menu
:default-active="route.path"
:collapse="isCollapse"
:collapse-transition="false"
router
class="side-menu"
>
<el-menu-item index="/library">
<el-icon><Reading /></el-icon>
<template #title>知识库</template>
</el-menu-item>
<el-menu-item index="/exam">
<el-icon><EditPen /></el-icon>
<template #title>考试中心</template>
</el-menu-item>
<el-menu-item index="/mistakes">
<el-icon><Notebook /></el-icon>
<template #title>错题本</template>
</el-menu-item>
<el-menu-item index="/stats">
<el-icon><DataLine /></el-icon>
<template #title>数据统计</template>
</el-menu-item>
</el-menu>
<el-aside v-else :width="appStore.isCollapse ? '64px' : '150px'" class="aside">
<app-logo />
<app-menu />
</el-aside>
<el-container>
<!-- 顶部栏 -->
<el-header class="header">
<div class="header-left">
<!-- 折叠按钮 -->
<el-icon class="collapse-btn" @click="isCollapse = !isCollapse">
<Fold v-if="!isCollapse" />
<el-icon class="collapse-btn" @click="collapseClick">
<Fold v-if="!appStore.isCollapse" />
<Expand v-else />
</el-icon>
<!-- 面包屑 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>{{ route.meta.title }}</el-breadcrumb-item>
@@ -52,13 +31,11 @@
</div>
<div class="header-right">
<!-- 通知铃铛 -->
<el-badge :value="3">
<el-icon :size="18"><Bell /></el-icon>
</el-badge>
<!-- 用户信息 -->
<el-dropdown>
<el-dropdown trigger="click">
<el-avatar :size="32" class="avatar"></el-avatar>
<template #dropdown>
<el-dropdown-menu>
@@ -84,16 +61,33 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import AppLogo from '@/layout/AppLogo.vue'
import AppMenu from '@/layout/AppMenu.vue'
import { useRoute } from 'vue-router'
import { useAppStore } from '@/stores/app.ts'
import { ElMessageBox } from 'element-plus'
import { Reading, EditPen, Notebook, DataLine, Fold, Expand, Bell } from '@element-plus/icons-vue'
import { Fold, Expand, Bell } from '@element-plus/icons-vue'
import { onMounted, onUnmounted } from 'vue'
const route = useRoute()
const isCollapse = ref(false)
const appStore = useAppStore()
const refreshClick = () => {
location.reload()
const checkScreen = () => {
appStore.isMobile = window.innerWidth < 768
}
onMounted(() => {
checkScreen()
window.addEventListener('resize', checkScreen)
})
onUnmounted(() => {
window.removeEventListener('resize', checkScreen)
})
const collapseClick = () => {
// appStore.isCollapse = !appStore.isCollapse
appStore.drawerVisible = !appStore.drawerVisible
}
// 退出登录
@@ -116,21 +110,27 @@ const handleLogout = () => {
border-right: 1px solid #e2e8f0;
transition: width 0.3s;
overflow: hidden;
}
.logo {
height: 56px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 600;
color: #14b8a6;
border-bottom: 1px solid #e2e8f0;
cursor: pointer;
}
.logo {
height: 56px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 600;
color: #14b8a6;
border-bottom: 1px solid #e2e8f0;
cursor: pointer;
}
.side-menu {
border-right: none;
.side-menu {
border-right: none;
}
.el-drawer {
.el-drawer__body {
padding: 0;
}
}

11
src/stores/app.ts Normal file
View File

@@ -0,0 +1,11 @@
import { defineStore } from 'pinia'
export const useAppStore = defineStore('app', {
state: () => ({
isMobile: false,
isCollapse: false,
drawerVisible: false
}),
actions: {
}
})

View File

@@ -3,7 +3,7 @@
<div class="view-header">
<div class="view-content">
<h2 class="view-title">考试中心</h2>
<p class="view-subtitle">按学科进行综合检验模拟真实考试环境</p>
<p class="view-subtitle">模拟真实考试环境</p>
</div>
<el-button type="primary" :icon="Aim" @click="examClick">开始考试</el-button>
</div>

View File

@@ -3,9 +3,10 @@
<div class="view-header">
<div class="view-content">
<h2 class="view-title">知识库</h2>
<p class="view-subtitle">管理学习资料查看 AI 解析结果</p>
<p class="view-subtitle">管理学习资料</p>
</div>
<el-button type="primary" :icon="Plus" @click="addFileClick">新增资料</el-button>
<el-button v-if="!appStore.isMobile"
type="primary" :icon="Plus" @click="addFileClick">新增资料</el-button>
</div>
<library-file-list />
@@ -24,10 +25,12 @@ import LibraryFileDialog from '@/components/Library/LibraryFileDialog.vue'
import LibraryFileTrainDialog from '@/components/Library/LibraryFileTrainDialog.vue'
import LibraryFileContentDialog from '@/components/Library/LibraryFileContentDialog.vue'
import { useLibraryStore } from '@/stores/library.ts'
import { useAppStore } from '@/stores/app.ts'
import { Plus } from '@element-plus/icons-vue'
import { onMounted } from 'vue'
const libraryStore = useLibraryStore()
const appStore = useAppStore()
onMounted(async () => {
await libraryStore.queryFileList()