Files
jiapu/docs/superpowers/specs/2026-07-30-site-news-design.md
T
fizzleaf 309598bfa6 feat(api): 添加帮助中心反馈系统和VIP服务功能
- 在ApiClient中新增submitFeedback、myFeedback、helpArticles、helpArticleDetail、
  siteArticles、promotions、vipPackages、createVipOrder、vipOrders等方法
- 添加帮助文章和站点资讯的参数验证逻辑
- 更新测试文件添加新的API方法测试用例
- 在HTML页面中添加反馈、帮助和VIP服务相关页面的脚本引用
- 更新加入家谱页面为完整的申请流程界面
- 修改资讯详情页面为站点资讯展示页面
- 更新AxiosRequestUtil中认证处理逻辑
- 添加世系树渲染的HTML生成函数用于页面复用
- 更新文档中的API契约说明和页面规划
2026-07-30 16:04:48 +08:00

171 lines
7.9 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.
# 官网资讯 PC 接口对接设计
## 1. 目标
把现有静态 `news.html``article-detail.html` 接入后端已经存在的 PC 站点文章接口,形成“资讯列表 → 文章详情”的公开只读闭环。
本批只处理官网资讯,不修改关于我们、家族文化、隐私政策、用户协议、姓氏百科及个人中心谱文 CRUD。
## 2. 契约来源
后端只读项目:`D:\WorkSpace\Java\Genealogy`
接口:
| method | path | 参数 | 响应 |
| --- | --- | --- | --- |
| GET | `/genealogy/pc/site/articles` | Query `articleType?``limit?` | 直接 `SiteArticleVo[]` |
该操作在 YAML 中标记为 `security: []`,后端 `PcSiteContentController` 也没有页面侧登录要求。本批按公开接口处理:`ApiClient` 为该请求设置 `auth: false`,不携带或读取登录 token;公共请求层仍自动携带基础 `clientid` Header。
后端没有站点文章单条详情接口。详情页必须重新读取文章列表,再按 URL 中由列表链接产生的 `articleId` 精确匹配;不存在时显示明确的未找到状态,不得回退到第一条文章。
## 3. SQL 冻结值
文章类型字典 `gen_site_article_type`
| 值 | 含义 |
| --- | --- |
| `news` | 新闻,默认 |
| `notice` | 公告 |
| `download` | 下载 |
`gen_site_article` 的页面相关约束:
| 字段 | SQL 约束 |
| --- | --- |
| `article_id` | `BIGINT NOT NULL`,主键 |
| `article_type` | `varchar(50) NOT NULL DEFAULT 'news'` |
| `article_title` | `varchar(200) NOT NULL` |
| `article_summary` | `varchar(500) DEFAULT ''` |
| `article_content` | `text`,可空 |
| `cover_oss_id` | `BIGINT`,可空 |
| `external_url` | `varchar(500) DEFAULT ''` |
| `publish_time` | `datetime`,可空 |
| `sort_order` | `BIGINT NOT NULL DEFAULT 0` |
| `status` | `char(1) NOT NULL DEFAULT '0'``0` 正常、`1` 停用 |
| `remark` | `varchar(500) DEFAULT NULL` |
服务端只返回正常状态记录,按 `sortOrder ASC``publishTime DESC``articleId DESC` 排序。正数 `limit` 最大按 100 执行;本批固定发送 `limit=100`
## 4. 前端 owner
| 文件 | 职责 |
| --- | --- |
| `utils/ApiClient.js` | 唯一拥有 `/genealogy/pc/site/articles` 请求路径、Query 白名单与枚举校验 |
| `utils/AxiosRequestUtil.js` | 确保 `auth: false` 的公开请求不携带 token,且其 401 不清理用户在其他页面建立的登录态 |
| `public/js/site-news-pages.js` | 唯一拥有站点文章响应规范化、列表/详情渲染、URL ID 解析和页面初始化 |
| `news.html` | 只提供资讯列表、分类入口及加载/空/失败挂载点 |
| `article-detail.html` | 只提供公开文章详情挂载点 |
不得复用 `public/js/article-pages.js`。该脚本属于登录后的家谱谱文 CRUD,契约、权限和数据结构均不同。
## 5. 页面数据流
### 5.1 资讯列表
1. `news.html` 初始化读取 URL Query `articleType`
2. Query 为空时不发送 `articleType`,读取全部三类文章;非空时只接受 `news/notice/download`
URL 中出现其他值时显示“资讯分类无效”且不发请求。
3. 请求固定携带 `limit=100`
4. 每个列表项使用响应中的字符串 `articleId` 生成 `article-detail.html?articleId=...`
5. 分类入口只生成本地固定链接:
- 全部:`news.html`
- 新闻:`news.html?articleType=news`
- 公告:`news.html?articleType=notice`
- 下载:`news.html?articleType=download`
6. 空数组显示“当前暂无资讯”;畸形响应或网络失败显示区域错误,不跳转。
### 5.2 文章详情
1. `articleId` 只能来自 URL Query,并按非零十进制字符串校验,禁止转成 JavaScript Number。
2. 页面调用同一个文章列表接口,固定 `limit=100`,不制造不存在的单条详情路径。
3. 只接受 `articleId` 完全相同的文章。
4. 缺失或非法 ID 显示“资讯编号无效”;合法但未匹配显示“资讯不存在或已下线”。
5. 页面不提供 ID 输入框、编辑、发布、删除、状态切换或 OSS ID 输入。
## 6. 字段分类与展示
| 字段 | 分类 | 页面使用 |
| --- | --- | --- |
| `articleId` | I | 列表链接和详情精确匹配;不直接展示 |
| `articleType` | R | 显示中文类型标签;只接受 SQL 字典枚举 |
| `articleTitle` | R | 列表和详情标题,必须非空 |
| `articleSummary` | R | 列表摘要和详情导语,可空 |
| `articleContent` | R | 详情正文,可空 |
| `coverOssId` | I | 没有文件 URL 契约,不显示、不拼接、不手填 |
| `externalUrl` | R | 仅接受绝对 HTTP/HTTPS;合法时显示“查看外部内容” |
| `publishTime` | R | 可空;按后端 `yyyy-MM-dd HH:mm:ss` 文本安全展示 |
| `sortOrder` | I | 仅后端排序,不展示 |
| `status` | I | 只接受 `0`,其他值使整批响应失败 |
| `remark` | I | 后台备注,不展示 |
`articleType` 是列表页 Query 时分类为 S,由用户点击固定分类入口产生;`limit=100` 分类为 A,由系统自动提交。
## 7. 安全与渲染
- 所有业务 ID 始终保持字符串。
- 标题、摘要、正文、类型和时间全部 HTML 转义。
- 正文只保留换行,不执行后端返回的 HTML、脚本或事件属性。
- `externalUrl` 只允许绝对 `http:``https:`,并使用 `target="_blank"``rel="noopener noreferrer"`
- 任一列表元素缺少稳定 ID、合法类型、标题或正常状态时,整批响应失败。
- 响应不接受分页对象、`rows` 包装或旧字段别名。
- 页面公开访问,请求显式使用 `auth: false`;公开请求的 401/403 不清理既有 token,也不跳转登录页。
## 8. HTML 迁移
`news.html` 删除两条硬编码新闻和固定分类卡片,改为:
- `data-site-news-page`
- `data-site-news-list`
- `data-site-news-status`
- 固定四个分类链接
- 加载完整 API 基础脚本和 `public/js/site-news-pages.js`
`article-detail.html` 保留现有视觉结构,将硬编码示例正文改为:
- `data-site-article-page`
- `data-site-article-detail`
- `data-site-article-status`
- 加载 `public/js/site-news-pages.js`
现有 `notice-detail.html` 本批不改。后端的公告也是 `SiteArticleVo`,统一进入 `article-detail.html`,避免维护两个详情模板。
## 9. 错误与空状态
| 场景 | 行为 |
| --- | --- |
| 列表空数组 | 显示“当前暂无资讯” |
| 列表响应畸形 | 显示“资讯列表响应无效” |
| 网络或业务失败 | 显示“资讯读取失败,请稍后重试” |
| 详情 ID 缺失或非法 | 显示“资讯编号无效”且不请求 |
| 详情未匹配 | 显示“资讯不存在或已下线” |
| 危险外链 | 不渲染外链入口,正文仍可查看 |
| 401/403 | 作为公开内容读取失败处理,不清理登录态、不跳转 |
## 10. 测试与验收
必须以 TDD 覆盖:
1. `ApiClient` 使用公开 PC path,只发送 `articleType/limit`,设置 `auth: false`,拒绝非法类型与超范围 limit。
2. 公共请求即使收到 401 也不清理既有登录 token。
3. 长 ID 保持字符串,非法安全整数被拒绝。
4. `SiteArticleVo` 全字段规范化与直接数组校验。
5. 任一非法元素使整批失败。
6. 列表链接只使用响应 ID,页面无手填 ID/OSS ID。
7. 详情精确匹配,不回退。
8. 正文转义、换行保留、危险外链拒绝。
9. `news.html``article-detail.html` 加载新脚本,且不加载家谱谱文 CRUD 脚本。
10. 先运行资讯专项测试,再运行全量 `node --test tests/*.test.js`
11. 使用浏览器验证公开列表、分类链接、详情或真实空状态,控制台无业务错误。
## 11. 明确不做
- 不修改后端。
- 不新增文章管理能力。
- 不接 APP 或后台管理接口。
- 不把 `coverOssId` 猜成文件 URL。
- 不接 `about/privacy/agreement` 固定页面。
- 不修改 `culture.html` 和首页文章卡片;它们作为后续独立批次。
- 不修改法律页“待法务确认”状态。