txw/txw-mhzc-web/docs/responsive-adaptation-implementation-plan.md
2026-05-26 15:38:01 +08:00

416 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 门户全终端自适应技术实现方案
> 项目:`txw-mhzc-web`Vue 2.6 + vue-cli 4 + TDesign Vue + Less
> 目标:移动端重新排版 + 平板/桌面/超宽屏统一自适应,兼顾视觉一致性与可用性
> 参考站点:[上海市企业走出去综合服务平台](https://segg.sh.gov.cn/)(固定版心 + 断点响应,非整页 scale
> 版本v1.0 | 2026-05-26
---
## 一、方案总览与原则
### 1.1 技术路线(推荐)
采用 **「CSS 设计令牌 + 断点媒体查询 + 流式布局」** 为主、**「路由级 scale 画布」** 为辅的 **混合方案**
| 场景 | 策略 | 说明 |
|------|------|------|
| 门户主站home2、fwsc、gxnlpt、qych 等) | 响应式重排 | 与 [segg.sh.gov.cn](https://segg.sh.gov.cn/) 同类政务门户一致 |
| 固定画布子系统iframe 大屏、部分 mhNewMain | 可选 `scale` | 仅 `meta.fixedCanvas === true` 的路由启用 |
| 禁止 | 全站整页 `transform: scale` | 手机端字糊、触控区缩小、弹层错位 |
**视觉一致性** 指:品牌色、版心对齐关系、模块层级、间距节奏在各断点可预测变化,而非「桌面缩小版像素级一致」。
### 1.2 与现有代码的关系
仓库内已具备基础能力,实施时 **优先激活与统一**,避免重复引入重型框架:
| 资产 | 路径 | 状态 |
|------|------|------|
| 断点常量 | `src/pages/index/styles/breakpoints.less` | 已定义 |
| 版心 / 栅格变量 | `src/pages/index/styles/page-layout.less` | 已定义 |
| 移动端全局样式 | `src/pages/index/styles/mobile-adaptation.less` | **需在 `main.js` 引入** |
| 验证清单 | `docs/test-reports/mobile-adaptation-checklist.md` | 已存在 |
| 大屏 scale 试验 | `app.vue` / `mhNewMain.vue` | 与门户主流程隔离 |
---
## 二、开源方案调研与对比(第一部分交付)
### 2.1 筛选标准
- 持续维护(近 12 个月有 release 或活跃 commit
- 社区文档完善、Issue 可检索
- 兼容 iOS 12+、Android 8+、Chrome / Safari / Edge 近两代
- 轻量化:不强制替换 Vue 技术栈
- 集成成本低:与 Vue CLI 4、Less、TDesign 共存
### 2.2 方案分类说明
自适应实现分四类,**门户类项目通常只需 A + 少量 D**
- **A. CSS 响应式体系**断点、Grid/Flex、CSS 变量)— 主推
- **B. 构建期单位转换**px→vw/rem— 活动页/H5 子模块可选
- **C. 运行时整页 scale**autofit、v-scale-screen— 仅大屏/数据可视化
- **D. JS 能力增强**断点检测、懒加载、resize 节流)— 辅助
以下 **不推荐** 作为门户主方案全量引入Bootstrap 全量、Element UI 第二套组件库、整站 rem flexibleamfe-flexible— 与现有 TDesign + Less 变量体系冲突且收益低。
### 2.3 对比清单
| 方案 | 类型 | 维护 / 生态 | 核心特性 | 适用场景 | 集成流程(概要) | 优点 | 缺点 |
|------|------|-------------|----------|----------|------------------|------|------|
| **原生 CSS + 项目令牌**`page-layout` / `breakpoints` | A | 标准、零依赖 | 变量、@media、Grid、clamp | **门户全站(首选)** | 已有;补 `main.js` 引入 `mobile-adaptation.less` | 可控、无运行时开销、与 Figma 1440 对齐 | 需逐页改样式 |
| **TDesign Vue Row/Col + 断点** | A | 腾讯维护 | 24 栅格、`xs/sm/md/lg` | 表单、列表、后台区块 | 已依赖,按文档包一层 | 与组件库一致 | 需熟悉 TDesign 断点 API |
| **Tailwind CSS**(项目已部分引入) | A | 活跃 | 工具类、响应式前缀 `md:` | 局部快速排版 | `vue.config` 配 PostCSS避免与 Less 变量双主源 | 开发快 | 与 Less 混用易混乱,需约束使用范围 |
| **postcss-px-to-viewport-modern** | B | 活跃 fork | 设计稿 px 自动转 vw | 375 宽 H5 活动页 | `vue.config.js``css.loaderOptions.postcss` | 一稿多宽省事 | 不适合 1200 版心门户;与变量体系冲突 |
| **postcss-pxtorem** + lib-flexible | B | 经典但大屏少用 | rem 等比 | 老 H5 | flexible 脚本 + postcss | 移动端成熟 | Vue2 门户性价比低 |
| **autofit.js** | C | 活跃 | 整页 scale、ignore 节点 | 1920 固定画布大屏 | `mounted``autofit.init({ dw, dh, el })` | 接入极简 | 门户手机不可用 |
| **v-scale-screen@1.x** | C | 活跃 | Vue 2.6 组件包裹 scale | 可视化大屏页 | `Vue.use` + 包一层 template | 与 Vue 集成好 | 仅适合大屏路由 |
| **@fit-screen/vue** | C | 中等 | Vue2/3 scale 封装 | 同上 | 需 `@vue/composition-api` | 类型友好 | Vue 2.6 多一层依赖 |
| **@vueuse/core` `useBreakpoints`** | D | 极活跃 | `matchMedia` 响应式 | 需 JS 切换布局时 | Vue 2.7+ 原生2.6 用 composition-api | API 优雅 | Vue 2.6 需额外插件 |
| **vue-mq / vue-screen** | D | 一般 | 断点 inject | 少量组件切换 | 注册插件 + `$mq` | 简单 | 维护不如 VueUse |
| **Container Queries**(原生 CSS | A | 浏览器已普及 | 按父容器宽度适配卡片 | 卡片、侧栏模块 | `@container` + `container-type` | 比纯 vw 稳 | 需 postcss 插件做旧版兜底(可选) |
### 2.4 本项目推荐组合(集成成本最低)
```
主路径page-layout.less + breakpoints.less + mobile-adaptation.less + 各页 @media
组件层TDesign Grid / Drawer移动菜单
增强层v-lazy已有清单+ resize 节流 + ECharts resize
隔离路径meta.fixedCanvas 路由 → autofit 或 v-scale-screen可选
```
**不引入** 新的 UI 框架;**不** 全站 postcss-px-to-viewport**不** 全站 scale。
---
## 三、断点设计规范
### 3.1 断点表(与 Figma / 现有 Less 对齐)
| 令牌 | 范围 | 设备 | 版心 / 列数策略 |
|------|------|------|-----------------|
| `xs` | 0 359px | 小屏手机 | 100% 宽gutter 12px栅格 1 列 |
| `sm` | 360 480px | 常规手机 | 100% 宽gutter 16px栅格 1 列 |
| `md` | 481 767px | 大屏手机 / 小平板竖屏 | 100% 宽gutter 1636px栅格 12 列 |
| `lg` | 768 1023px | 平板 | max-width 100%,部分 2 列 |
| `xl` | 1024 1279px | 小桌面 | 版心可 100% 或保留 padding 40px |
| `2xl` | 1280 1439px | 标准桌面Figma 1440 画布) | `--page-content-max-width: 1200px` |
| `3xl` | 1440 1919px | 宽桌面 | 版心 1200 居中,两侧留白随屏宽增加 |
| `4xl` | ≥ 1920px | 超宽屏 | 版心仍 1200**禁止** 无限制拉伸内容区 |
Less 常量(已有,建议扩展):
```less
// breakpoints.less
@mq-mobile-xs-max: 360px;
@mq-mobile-sm-max: 480px;
@mq-mobile-max: 767px;
@mq-tablet-max: 1023px;
@mq-desktop-sm-max: 1279px;
@mq-desktop-max: 1439px;
@mq-ultrawide-min: 1920px;
```
### 3.2 媒体查询书写约定
1. **移动优先(推荐新代码)**:默认手机样式 → `min-width` 逐级增强。
2. **桌面优先(兼容旧代码)**:保持现有 `max-width` 块,逐步迁移。
3. **禁止** 同一属性在多个断点反复覆盖且无变量来源。
4. 断点内只改 **CSS 变量****布局模式**列数、flex-direction避免魔法数字散落。
### 3.3 设计令牌扩展(`:root`
`page-layout.less` 按断点扩展(示例):
```less
// 平板
@media (min-width: 768px) and (max-width: 1023px) {
:root {
--portal-services-fwsc-cols: 2;
--page-section-padding-y: 48px;
}
}
// 超宽屏:版心不变,仅增大「出血背景」感知
@media (min-width: 1920px) {
:root {
--page-content-max-width: 1200px; /* 保持 */
}
}
```
---
## 四、流式布局适配逻辑
### 4.1 版心模型(与 segg 类门户一致)
```
┌──────────────────────────────────────────── viewport ────┐
│ margin-auto │
│ ┌──────────────── page-content-max 1200 ─────────────┐ │
│ │ gutter │ content aligned to nav logo │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
- 容器:`.page-content-wrap` / `.page-nav-inner`(已有)
- 宽度:`width: 100%` + `max-width: var(--page-content-max-width)`
- 小屏:`--page-content-max-width: 100%``mobile-adaptation.less` 已定义)
### 4.2 栅格与模块列数
| 模块 | ≥1280 | 7681279 | 481767 | ≤480 |
|------|-------|----------|---------|------|
| 服务中心四宫格 | 4 列 | 2 列 | 2 列 | 1 列 |
| 共性能力卡片 | 34 列 | 2 列 | 2 列 | 1 列 |
| 页脚链接组 | 横排 | 横排/折行 | 纵排 | 纵排 |
| 首页 Hero 搜索 | 横排 | 横排 | 纵排 | 纵排home2 已部分实现) |
实现方式:
```less
.portal-services-grid {
display: grid;
grid-template-columns: repeat(var(--portal-services-fwsc-cols, 4), minmax(0, 1fr));
gap: var(--portal-services-grid-gap, 24px);
}
```
### 4.3 超宽屏策略
- **内容区不随 4K 变宽**:保持 1200px 版心,避免行长过长。
- **全宽背景** 使用 `.home-section-bleed()`(已有 mixin铺满视口。
- **装饰性大图** 使用 `max-width: 100%` + 居中,而非拉伸版心。
### 4.4 大屏固定画布(可选子路由)
`route.meta.layout === 'fixed-canvas'`
```js
scale = Math.min(innerWidth / DESIGN_W, innerHeight / DESIGN_H)
```
与门户响应式 **路由级隔离**,避免 `app.vue` 全局 scale 影响主站。
---
## 五、弹性图片与媒体资源
### 5.1 图片
| 策略 | 实现 |
|------|------|
| 响应式尺寸 | `max-width: 100%; height: auto;`mobile-adaptation 已有) |
| 分辨率适配 | `<img srcset="..." sizes="(max-width: 768px) 100vw, 1200px">` 对 Banner/大图 |
| 懒加载 | `loading="lazy"``v-lazy`(见 checklist |
| 格式 | 优先 WebP构建或 CDNPNG 用于透明图标 |
| 艺术方向 | 窄屏可选裁切图(`picture` + `source media` |
### 5.2 视频 / 背景
- 首页 Banner 视频:窄屏降低 `preload`,必要时 `poster` 静帧。
- CSS 背景:`background-size: cover; background-position: center;`
- 避免固定 `1920px` 背景宽导致小屏横向滚动(参考政务站仅背景层用 1920 的情况)。
### 5.3 图标与 SVG
- 图标优先 SVG / iconfont随字号 `em` 缩放。
- Font Awesome 已引入,控制只打包使用子集(长期优化)。
---
## 六、响应式交互适配策略
### 6.1 导航
| 断点 | 行为 |
|------|------|
| ≥768px | 横排菜单(`new-nav` / `nav/index2` |
| <768px | 隐藏横菜单汉堡 + Drawer/侧滑`mobile-menu-item` 样式已有 |
### 6.2 触控与表单WCAG 2.5 目标尺寸)
- 可点击区域 ** 48×48px**`mobile-adaptation.less`
- 输入框 `font-size: 16px` 防止 iOS 聚焦放大
- `touch-action: pan-y` 于主滚动容器减少误触横向滑动
### 6.3 弹层与固定元素
- TDesign `Dialog` / `Drawer`窄屏优先 `placement` 全屏或底部抽屉
- **避免** 在带 `transform` scale 祖先内挂 `position: fixed` 弹层
- 返回顶部悬浮客服小屏抬高 `bottom`避开安全区
```css
padding-bottom: env(safe-area-inset-bottom, 0);
```
### 6.4 JS 辅助(按需)
```js
// utils/breakpoint.js
export const BP = { mobile: 768, tablet: 1024, desktop: 1280 }
export function getDeviceClass() {
const w = window.innerWidth
if (w < BP.mobile) return 'is-mobile'
if (w < BP.tablet) return 'is-tablet'
if (w < BP.desktop) return 'is-desktop-sm'
return 'is-desktop'
}
```
用于ECharts `resize`是否加载重动画Tab 横滑 vs 下拉
### 6.5 图表ECharts
```js
window.addEventListener('resize', throttle(() => chart.resize(), 200))
```
移动端 legend 改底部减小 `grid` 边距 `@media` `getDeviceClass()` 分支配置 option
---
## 七、性能优化措施
| | 措施 |
|----|------|
| CSS | 断点样式集中在 `mobile-adaptation.less`避免每组件重复 `@media` |
| 图片 | 懒加载 + 合适尺寸首屏 LCP 图不用 lazy |
| JS | `resize` / `scroll` 监听必须 throttle200300ms |
| 字体 | 子集化或系统字体栈回退减少 FOUT |
| 长列表 | 虚拟滚动TDesign Table 大数据或分页 |
| 动画 | `prefers-reduced-motion: reduce` 关闭非必要动效 |
| 构建 | 路由懒加载已有 vue-router按页拆分 CSS |
---
## 八、落地实施路线图
### 阶段 0基线1 天)
- [ ] `main.js` 增加`import './styles/mobile-adaptation.less'`
- [ ] 确认 `public/index.html` viewport`width=device-width, initial-scale=1`
- [ ] 移除或路由隔离 `app.vue` 未使用的全局 scale 逻辑
- [ ] 统一断点新代码引用 `breakpoints.less` 变量
### 阶段 1全局与导航23 天)
- [ ] 导航移动 Drawer + 桌面横栏双态完整联调
- [ ] `page-layout.less`补齐 tablet / ultrawide 变量
- [ ] 页脚面包屑窄屏折行
### 阶段 2核心页面重排58 天)
checklist 顺序
1. `home2/index.vue` 合并零散 `@media` 到变量驱动
2. `fwsc` 四宫格 + 列表筛选堆叠
3. `gxnlpt` 侧栏置顶 + 卡片单列
4. `qych` 法案区块与卡片
每页完成即在 `mobile-adaptation-checklist.md` 打勾
### 阶段 3大屏与回归2 天)
- [ ] 1280 / 1920 / 2560 版心居中与背景出血
- [ ] 固定画布子路由若有单独测 scale
- [ ] 桌面回归与改版前 1280 对齐
### 阶段 4验收
- 真机iOS SafariAndroid Chrome宽度 320 / 390 / 414
- 桌面1280144019202560
- 工具Chrome DevTools + Lighthouse 移动端评分
---
## 九、目录与文件规范(建议)
```
src/pages/index/styles/
breakpoints.less # 断点常量(唯一来源)
page-layout.less # 版心、间距令牌
mobile-adaptation.less # 全局移动端 @media
mixins/
responsive.less # .respond-to(@bp) 等 mixin可选新建
src/pages/index/utils/
breakpoint.js # 设备类名 / matchMedia可选
docs/
responsive-adaptation-implementation-plan.md # 本文档
test-reports/mobile-adaptation-checklist.md # 验收清单
```
### Less mixin 示例(可选)
```less
.respond-to(@max) when (default()) {
@media screen and (max-width: @max) {
@content();
}
}
// 使用
.respond-to(@mq-mobile-max) {
.foo { flex-direction: column; }
}
```
---
## 十、风险与决策记录
| 风险 | 缓解 |
|------|------|
| 双轨样式桌面 scale + 移动重排冲突 | 路由 meta 明确 `layout: portal \| fixed-canvas` |
| TDesign 组件窄屏溢出 | 表格外包 `.table-scroll-x { overflow-x: auto }` |
| 旧页大量魔法 `@media` | 逐页迁移不一次性重写 |
| 超宽屏内容过宽 | 严格 max-width 1200不改用 scale 撑满 |
---
## 十一、附录:快速集成示例
### A. 启用全局移动端样式
```js
// main.js
import './styles/page-layout.less';
import './styles/mobile-adaptation.less';
```
### B. 页面内仅补结构差异
```vue
<template>
<div class="page-content-wrap portal-page">
<section class="portal-services-grid">...</section>
</div>
</template>
```
列数由 `--portal-services-fwsc-cols` 控制不在组件内写死 `width: 280px`
### C. 可选大屏路由autofit
```js
// 仅 fixed-canvas 布局的 mounted
import autofit from 'autofit.js'
autofit.init({ dw: 1920, dh: 1080, el: '#fixed-canvas-root', resize: true })
```
---
## 十二、结论
- **移动端重新排版**依赖 **CSS 变量 + 断点 + Grid/Flex**激活并扩展现有 `mobile-adaptation.less`逐页改造核心视图
- **大屏/超宽屏****版心锁定 + 背景出血** [segg.sh.gov.cn](https://segg.sh.gov.cn/) 同类**不用** 整站 scale
- **开源框架**不新增重型 UI 框架可选 **autofit / v-scale-screen** 仅服务固定画布子系统主站以 **原生响应式 + TDesign** 为准
本文档为实施依据具体排期可与 `mobile-adaptation-checklist.md` 联合跟踪