# 设计文档:健康装修科普 —— 可点击的原创全文 - 日期:2026-07-07 - 目标项目:`C:\code\空气质量预测\源码\用户端\iapip-web`(纯前端,不涉及后端/数据库) - 状态:已通过需求评审,待写实现计划 --- ## 1. 背景与目标 用户端首页(landing,`src/pages/landing/index.tsx`)的「健康装修科普」区块(`#news`)当前是 4 条**写死**的资讯数据(`tag/date/title/desc`),卡片上的「阅读全文→」**未绑定任何跳转**,顶部「全部文章」按钮误跳到预测页(`openPredict`)。 目标:让这 4 篇科普**真正可点击进入看全文**,内容为**原创、准确、标注来源**的科普文章,并提供一个「全部文章」列表页。**纯前端静态实现,不改数据库/后端。** --- ## 2. 范围 ### 2.1 纳入 - 共享文章内容模块(4 篇原创全文,结构化段落)。 - 文章详情页 `/article/:id`。 - 文章列表页 `/articles`。 - landing 接线:轮播卡片可点进详情、「全部文章」跳列表页。 ### 2.2 不纳入(YAGNI) - 后端文章表 / 管理端发布(内容静态即可,主题稳定)。 - 富文本 / markdown 渲染引擎(用结构化段落数组)。 - 文章配图(用现有 `img-ph` 占位或纯文本排版,不引入图片资源)。 - 评论、点赞、搜索、分页(列表仅 4 篇,无需分页)。 --- ## 3. 架构与数据源 单一数据源:新建 `src/common/articles.ts`,landing 轮播、列表页、详情页三处共用。 ### 3.1 类型与数据(`src/common/articles.ts`) ```ts export interface ArticleSection { heading?: string paragraphs: string[] } export interface Article { id: string // 稳定短 slug,如 'gb-standards' tag: string // 标签,如 '政策解读' date: string // 如 '专栏 · 2026.05' title: string summary: string // 卡片/列表摘要(沿用现有 desc 文案) body: ArticleSection[] sources?: string[] // 来源标注,如 ['GB/T 18883-2022 室内空气质量标准'] } export const articles: Article[] // 4 篇 export const getArticle = (id: string): Article | undefined ``` - `id` 用稳定 slug(`gb-standards` / `formaldehyde-release` / `summer-exceed` / `predict-before-cma`),便于 URL 可读且与顺序解耦。 - 每篇正文结尾统一附免责声明段落:「本文为科普整理,预测结果仅供参考,以 CMA 检测为准。」 ### 3.2 4 篇内容(原创撰写,标注来源) 沿用现有 4 主题,每篇约 400–700 字、2–4 个小标题: 1. `gb-standards` — 两大国标怎么读?GB/T 18883 与 GB 50325 的差别(依据两部国标:一为室内空气质量、一为民用建筑工程室内环境污染控制;限值与采样条件差异)。 2. `formaldehyde-release` — 新装住宅的甲醛,为什么能持续释放 3–15 年?(人造板脲醛树脂缓慢水解释放机理、受温湿度影响)。 3. `summer-exceed` — 夏天为什么更容易超标?温度与释放速率(温度升高释放速率增大,"冬测达标夏超标")。 4. `predict-before-cma` — 先预测,再决定要不要做 CMA 检测(CMA 检测成本,先预测定位高风险房间再针对性检测)。 > 内容为通用科学常识 + 国标依据,**原创撰写并标注来源**,无抄袭/版权风险。 --- ## 4. 页面 ### 4.1 文章详情页 `src/pages/article/index.tsx`(路由 `/article/:id`,`layout:false`) - `useParams` 取 `id` → `getArticle(id)`。 - 命中:渲染 顶部「← 返回首页」链接、标题、`tag · date` 元信息、`body` 分节(`heading` 为小标题,`paragraphs` 逐段)、`sources` 列表(若有)。 - 未命中:显示「文章不存在」+「返回首页」链接。 - 版式约束:`maxWidth` 约 760px 居中、正文行距舒适,风格与 landing/forum 页一致(内联样式即可,无需新增全局 CSS)。 ### 4.2 文章列表页 `src/pages/articles/index.tsx`(路由 `/articles`,`layout:false`) - 顶部「← 返回首页」+ 标题「健康装修科普」。 - 遍历 `articles`,每项显示 `tag`、`title`、`summary`、`date`,整项点击 → `/article/:id`。 ### 4.3 landing 接线(`src/pages/landing/index.tsx`) - 将本地 `news` 常量替换为从 `articles` 派生(或直接 `import { articles }` 后 `.slice(0,4)` 用于轮播),卡片渲染字段映射:`tag→tag`、`date→date`、`title→title`、`desc→summary`。 - 轮播卡片(`.cslide`)整卡与「阅读全文」`.cslide-more` 绑定 `onClick={() => history.push('/article/' + a.id)}`。 - 顶部「全部文章」按钮 `onClick` 由 `openPredict` 改为 `() => history.push('/articles')`。 - 保持现有轮播交互(自动轮播/左右切换/圆点)不变。 ### 4.4 路由(`.umirc.ts`) 在 landing/forum 路由附近新增两条公开路由: ```ts { name: '科普文章', path: '/articles', component: './articles', layout: false }, { name: '文章详情', path: '/article/:id', component: './article', layout: false }, ``` > 注意注册顺序与静态路径无冲突(`/articles` 与 `/article/:id` 前缀不同,互不遮蔽)。 --- ## 5. 数据流与错误处理 - 纯静态:页面直接 `import` 文章数据,无网络请求、无 loading 态。 - 未知 `id`:详情页显示兜底文案与返回链接,不抛错。 --- ## 6. 测试 - **类型检查**:`npx tsc --noEmit -p tsconfig.json` 仅剩既有的 2 条 eslint 类型根告警,新增文件零错误。 - **浏览器**: - landing 轮播卡片点击 → 进入对应 `/article/:id`,正文完整、分节正确、含来源与免责声明。 - landing「全部文章」→ `/articles` 列表,4 项齐全,点击任一进详情。 - 直接访问 `/#/article/不存在的id` → 显示「文章不存在」。 - landing 轮播自动播放/左右/圆点交互不受影响。 --- ## 7. 涉及文件清单 - 新建:`src/common/articles.ts` - 新建:`src/pages/article/index.tsx` - 新建:`src/pages/articles/index.tsx` - 修改:`src/pages/landing/index.tsx`(news 派生自 articles、卡片与「全部文章」接线) - 修改:`.umirc.ts`(新增 `/articles`、`/article/:id` 路由) --- ## 8. 风险与注意 - landing 现有 `news` 常量被 `articles` 取代,需保证轮播渲染字段一一对应,避免出现空白卡。 - 路由为 hash 模式(`/#/article/xxx`),slug 需 URL 友好(纯 ASCII kebab-case)。 - 修改 `.umirc.ts` 需重启前端 dev(配置变更不热更新)。