13 KiB
前端移动端适配指南
一、现状评估
1.1 项目技术栈
| 项目 | 当前状态 |
|---|---|
| UI 框架 | Element Plus(自带 el-row/el-col 响应式栅格) |
| CSS 框架 | 无(无 Tailwind、无 Bootstrap) |
| 响应式工具 | 手写媒体查询,仅 4/22 个 Vue 文件包含 @media |
| 移动端检测 | App.vue 和 RecommendForm.vue 各自实现了 window.innerWidth < 768 逻辑,未复用 |
| 断点体系 | 仅一个断点:max-width: 767px(手机),仅 App.vue 有平板断点(768–1024px) |
1.2 适配完成度
| 等级 | 文件数 | 占比 |
|---|---|---|
| ✅ 已适配 | 4 | 18% |
| ⚠️ 部分适配 | 3 | 14% |
| ❌ 未适配 | 15 | 68% |
已适配:App.vue、RecommendForm.vue、ChatCopyButton.vue、ChatSuggestions.vue
部分适配:ChatPage.vue、ChatSidebar.vue、ChatEmbed.vue
未适配:其余 15 个页面/组件
二、问题清单(按严重程度排序)
🔴 严重 — 移动端完全不可用
| 文件 | 问题 | 影响 |
|---|---|---|
RegisterPage.vue |
.register-card 硬编码 width: 400px,无媒体查询 |
<420px 屏幕水平溢出 |
RecommendDetailView.vue |
el-descriptions 强制 3 列;4 列 plan 表格;标题栏 3 个按钮 |
布局严重错乱 |
RecommendHistory.vue |
筛选栏最小宽度 ~560px;表格总宽 ~920px | 完全溢出 |
DashboardPage.vue |
KPI 卡片 el-col :span="6" 无 :xs 断点;快捷卡片 :span="8" |
4 列/3 列在手机上窄至 ~80px |
PermissionsPage.vue |
el-col :span="8" 和 :span="16" 无响应式断点 |
角色列表/权限面板在手机上不可用 |
DataSourcePage.vue |
同步日志弹窗 width="700px" |
所有手机屏幕溢出 |
🟠 高 — 移动端严重降级
| 文件 | 问题 |
|---|---|
ChatFilters.vue |
flex 无 wrap,筛选栏溢出;.filter-label 设了 white-space: nowrap |
RecommendResult.vue(组件) |
7 列表格无横向滚动;替换弹窗 width="600px" |
UsersPage.vue |
筛选栏溢出(固定 160px × 2 + 按钮);表格 ~870px;弹窗 480px |
StatsPage.vue |
el-col :span="12"/:span="8" 无响应式;筛选器固定宽度 |
TemplatePage.vue |
编辑弹窗 width="50%"(手机 ~180px);placeholder 行总宽 420px |
KBManagePage.vue |
筛选栏总宽 ~580px;状态弹窗 500px |
🟡 中 — 移动端可感知问题
| 文件 | 问题 |
|---|---|
ChatPage.vue |
侧边栏固定 240px,无平板适配 |
ChatEmbed.vue |
纠错弹窗 width="500px";消息列表/输入区 padding 不缩 |
PromptPage.vue |
创建弹窗 width="70%"(手机 ~252px,过窄) |
NotificationPage.vue |
弹窗 width="50%"(手机 ~180px,不可用) |
DepartmentPage.vue |
弹窗 width="500px" |
LoginLogsPage.vue |
筛选项固定宽度(150px/120px/280px) |
ChatLogsPage.vue |
筛选项固定宽度(200px/150px/280px) |
🟢 低 — 细节问题
| 文件 | 问题 |
|---|---|
LoginPage.vue |
背景装饰 .bg-decoration 可能在极窄屏幕造成溢出 |
ChatSidebar.vue |
移动端 max-height: 200px 过小(仅 ~3 个会话);删除按钮仅 hover 可见,触屏不可发现 |
三、根因分析
3.1 六大共性问题
- 无响应式框架 — 全靠手写 media query,覆盖率极低
- inline style 主导 — 大量页面用
style="width: 160px"等内联样式,无法通过媒体查询覆盖 - 弹窗宽度硬编码 —
el-dialog统一用固定像素(480–700px)或固定百分比(50%–70%),无移动端 override - 表格无响应式策略 — 多列表格总宽 870–920px,无横向滚动包裹、无列隐藏、无卡片视图
- 断点体系缺失 — 仅
max-width: 767px一个断点,无平板/大屏手机/横屏适配 - 移动端检测重复 —
App.vue和RecommendForm.vue各自实现isMobile逻辑
四、适配方案
4.1 断点体系(统一标准)
/* 手机竖屏 */
@media (max-width: 575px) { /* ... */ }
/* 手机横屏 / 大屏手机 */
@media (min-width: 576px) and (max-width: 767px) { /* ... */ }
/* 平板竖屏 */
@media (min-width: 768px) and (max-width: 1023px) { /* ... */ }
/* 桌面 */
@media (min-width: 1024px) { /* ... */ }
与 Element Plus 断点保持一致:xs(<768px)、sm(≥768px)、md(≥992px)、lg(≥1200px)。
4.2 全局 CSS 变量(建议新建 src/styles/responsive.css)
:root {
/* 间距 */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
/* 弹窗宽度 */
--dialog-width-sm: 90vw;
--dialog-width-md: 80vw;
--dialog-width-lg: 600px;
/* 表格 */
--table-scroll-max-width: calc(100vw - 48px);
}
@media (min-width: 768px) {
:root {
--dialog-width-sm: 500px;
--dialog-width-md: 600px;
--dialog-width-lg: 700px;
--table-scroll-max-width: 100%;
}
}
4.3 共享 Composable(新建 src/composables/useMobile.ts)
import { ref, onMounted, onUnmounted } from 'vue'
export function useMobile(breakpoint = 768) {
const isMobile = ref(window.innerWidth < breakpoint)
const isTablet = ref(window.innerWidth >= 768 && window.innerWidth < 1024)
const update = () => {
isMobile.value = window.innerWidth < breakpoint
isTablet.value = window.innerWidth >= 768 && window.innerWidth < 1024
}
onMounted(() => window.addEventListener('resize', update))
onUnmounted(() => window.removeEventListener('resize', update))
return { isMobile, isTablet }
}
五、逐页面修复方案
5.1 注册页 RegisterPage.vue
问题:卡片固定 400px 宽度 修复:
.register-card {
width: 400px;
}
@media (max-width: 575px) {
.register-card {
width: 92vw;
max-width: 400px;
}
}
el-form 的 label-width 改为响应式::label-width="isMobile ? '0px' : '80px'"(手机用 top label)。
5.2 推荐详情页 RecommendDetailView.vue
问题:3 列描述、4 列表格、标题栏 3 按钮 修复:
el-descriptions::column="isMobile ? 1 : 3"- 标题栏按钮:
flex-wrap: wrap或手机端折叠为下拉菜单 - plan 表格:外层加
<div style="overflow-x: auto">;手机端隐藏"推荐理由"列
5.3 推荐历史页 RecommendHistory.vue
问题:筛选栏溢出、表格过宽 修复:
- 筛选栏:
flex-wrap: wrap;筛选项用min-width: 120px; flex: 1替代固定宽度 - 表格:外层
<div style="overflow-x: auto">;手机端隐藏低优先级列(如"保单号"、"创建时间") - 或使用 Element Plus 的
el-tablescrollbar-always-on+ 设置列min-width
5.4 仪表盘 DashboardPage.vue
问题:KPI 4 列、快捷 3 列无响应式 修复:
<!-- KPI 卡片 -->
<el-col :xs="12" :sm="12" :md="6" v-for="item in kpiCards">
<!-- 快捷卡片 -->
<el-col :xs="12" :sm="8" :md="8" v-for="item in shortcutCards">
5.5 权限页 PermissionsPage.vue
问题:角色列表 8/权限 16 分割无响应式 修复:
<el-col :xs="24" :sm="8"> <!-- 角色列表 -->
<el-col :xs="24" :sm="16"> <!-- 权限面板 -->
手机端改为上下堆叠布局。
5.6 数据源页 DataSourcePage.vue
问题:同步日志弹窗 700px
修复:改为 width="var(--dialog-width-lg)" 或 width="min(700px, 90vw)"
5.7 聊天筛选 ChatFilters.vue
问题:flex 无 wrap,标签 nowrap 修复:
.chat-filters {
flex-wrap: wrap;
}
.filter-label {
white-space: normal; /* 允许换行 */
}
5.8 推荐结果组件 RecommendResult.vue
问题:7 列表格无滚动
修复:表格包裹 <div class="table-responsive">
.table-responsive {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
替换弹窗改为 width="min(600px, 90vw)"。
5.9 用户管理 UsersPage.vue
问题:筛选栏溢出、表格过宽、弹窗固定 修复:
- 筛选栏:
flex-wrap: wrap;筛选项flex: 1; min-width: 140px - 表格:
overflow-x: auto包裹;手机端隐藏部分列 - 弹窗:
width="min(480px, 90vw)"
5.10 统计页 StatsPage.vue
问题:el-col 无响应式、筛选器固定宽度
修复:
<el-col :xs="24" :sm="12" :md="8">
筛选器宽度改为 width: 100%(手机端)或 flex: 1; min-width: 120px。
5.11 模板页 TemplatePage.vue
问题:弹窗 50% 太窄;placeholder 行溢出 修复:
- 弹窗:改为
width="min(500px, 90vw)" - placeholder 行:
flex-wrap: wrap,每项min-width: 120px
5.12 提示词页 PromptPage.vue
问题:弹窗 70% 手机端过窄
修复:改为 width="min(600px, 90vw)"
5.13 通知页 NotificationPage.vue
问题:弹窗 50% 不可用
修复:改为 width="min(500px, 90vw)"
5.14 部门页 DepartmentPage.vue
问题:弹窗 500px
修复:改为 width="min(500px, 90vw)"
5.15 知识库管理 KBManagePage.vue
问题:筛选栏溢出、弹窗固定 修复:
- 筛选栏:
flex-wrap: wrap;筛选项flex: 1; min-width: 130px - 弹窗:
width="min(500px, 90vw)"
5.16 登录日志 LoginLogsPage.vue / 聊天日志 ChatLogsPage.vue
问题:筛选项固定宽度
修复:筛选项改为 width: 100%(手机端)或 flex: 1; min-width: 140px
5.17 聊天嵌入 ChatEmbed.vue
问题:纠错弹窗 500px、padding 不适配 修复:
- 弹窗:
width="min(500px, 90vw)" .message-list:手机端 padding 缩小为8px.input-area:手机端 padding 缩小为8px 12px
5.18 聊天侧边栏 ChatSidebar.vue
问题:手机端 max-height 过小;删除按钮 hover 不可发现 修复:
max-height从200px调整为240px或40vh- 删除按钮:手机端改为
opacity: 1(始终可见),或增加长按触发
5.19 登录页 LoginPage.vue
问题:背景装饰可能溢出
修复:.bg-decoration 加 display: none 在手机端
@media (max-width: 575px) {
.bg-decoration {
display: none;
}
}
六、弹窗适配规则(全局)
| 原写法 | 推荐写法 | 说明 |
|---|---|---|
width="700px" |
width="min(700px, 90vw)" |
大弹窗 |
width="600px" |
width="min(600px, 90vw)" |
中弹窗 |
width="500px" |
width="min(500px, 90vw)" |
小弹窗 |
width="480px" |
width="min(480px, 90vw)" |
表单弹窗 |
width="70%" |
width="min(600px, 90vw)" |
百分比在手机上过窄 |
width="50%" |
width="min(500px, 90vw)" |
百分比在手机上不可用 |
width="90%" |
✅ 可以保留 | 已是响应式写法 |
规则:所有
el-dialog的width使用min(固定值, 90vw)模式,确保手机端不超过 90% 视口宽度。
七、表格适配规则(全局)
7.1 横向滚动(最简单)
所有 el-table 外层包裹:
<div class="table-scroll-wrapper">
<el-table ...>
<!-- columns -->
</el-table>
</div>
.table-scroll-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
7.2 列优先级隐藏
@media (max-width: 767px) {
/* 隐藏低优先级列 — 通过 el-table 的 v-if 或 class 控制 */
.hide-on-mobile {
display: none;
}
}
或使用 Element Plus 的 el-table-column 的 show-overflow-tooltip + min-width 替代 width。
7.3 推荐的列宽策略
| 场景 | 策略 |
|---|---|
| 2–3 列表格 | 无需特殊处理 |
| 4–5 列表格 | overflow-x: auto 包裹 |
| 6+ 列表格 | overflow-x: auto + 手机端隐藏低优先级列 |
| 筛选栏 | flex-wrap: wrap + 筛选项 flex: 1; min-width: 120px |
八、筛选栏适配模板
所有筛选栏统一模式:
.filter-bar {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
}
.filter-item {
flex: 1;
min-width: 120px;
}
@media (max-width: 575px) {
.filter-bar {
gap: 8px;
}
.filter-item {
min-width: 100%;
}
}
九、实施优先级
Phase 1 — 核心页面(用户直接使用)
ChatPage.vue+ChatEmbed.vue+ChatSidebar.vue+ChatFilters.vueLoginPage.vue+RegisterPage.vueRecommendForm.vue+RecommendResult.vue+RecommendDetailView.vue+RecommendHistory.vue
Phase 2 — 管理后台
DashboardPage.vueUsersPage.vue+PermissionsPage.vue- 其余 admin 页面(
PromptPage、TemplatePage、StatsPage等)
Phase 3 — 全局优化
- 创建
src/composables/useMobile.ts,替换所有isMobile重复逻辑 - 创建
src/styles/responsive.css,统一 CSS 变量 - 创建
src/styles/table.css,统一表格滚动样式 - 创建
src/styles/dialog.css,统一弹窗响应式
十、验证清单
每个页面适配后,用以下方式验证:
- Chrome DevTools → 切换到 iPhone SE (375px) 查看
- Chrome DevTools → 切换到 iPhone 14 Pro (393px) 查看
- Chrome DevTools → 切换到 iPad (768px) 查看
- 检查无水平滚动条(除非是表格横向滚动)
- 弹窗在手机端可正常显示和操作
- 筛选栏在手机端可正常换行
- 表格在手机端可横向滚动
- 触屏设备上无 hover-only 的交互死角