Files
aurora-admin/PLATFORMS.md
T
aurora-admin 5ee5d829a4
Regression / regression (push) Canceled after 0s
refactor(详情页+S8): 详情页减重(导航互斥/入口去重/i18n去重) + 品牌标识入库
本提交含两条并行工作线,因互相咬合(package.json scripts、regression.yml、
npm run build 链)无法按文件干净拆分,故合并为一次自洽提交。

## 详情页减重(本轮主任务:修复「AI 干太重」)

- 导航收敛:宽屏只用右侧目录、≤1200px 只用页内 sticky 导航,纯 CSS 媒体查询
  实现(不引入 JS 宽度监听)。此前两套导航同时可见,active 状态互相打架。
- 入口去重:标题区由「查看示例/在线测试/契约 JSON」三个减为「在线测试」一个;
  契约 JSON 归入实现资源;删除示例底部重复的「在线测试」。
- 示例工具栏:删除与目录锚点重复的示例下拉选择器;「全部展开代码」只在
  示例数 >1 时出现(103 个组件里 49 个仅 1 个示例,此前恒显示)。
- 重复文案:示例区两句同义导语合并为一句。
- 首页 CTA 由 5 个减为 2 个(浏览组件/快速开始),测试总览入口挂到已有的
  通过率统计卡上,不再另占 Hero 按钮。
- 统一详情取数:抽出 fetchDetail/loadDetail 作为 details/*.json 的唯一路径,
  FAQ 不再自行 fetch 一遍,与组件页共用缓存与失败兜底。

## i18n

- 删除 12 组重复键(含整段 FAQ 说明),字典 604 → 585 唯一键。
- 删除本次改动产生的 6 个死键。
- verify-i18n.mjs 新增 `unique dictionary keys` 断言:重复键在对象字面量里
  是静默的后值覆盖,此前无从发现;现由门禁拦住。

## 文档事实修正(实测为准)

- TESTING/CONTRIBUTING:79 → 103 组件;旧断言数改为回指 tests/report.json。
- PLATFORMS:移动端 108 文件/18 端 → 282 文件/47 端;契约 5 → 47;
  令牌 17 → 15;uni-app SFC 21 → 50。
- AGENTS:断言 1405/18 页 → 1464/103 页(PC)、807/47 页(移动端)。
- package.json:YOUR-ACCOUNT 占位 → gitea 实址与 kole-ui.mymoyu.top。

## 品牌标识(并行会话成果,一并入库)

- brand-mark.json 收归真源,build:brand 生成 favicon 与单色 SVG;
  PC 与移动端共用资产,verify:brand 24 条断言。
- regression.yml 增加 verify:brand 步骤。

## 门禁与验收

新增工具:verify-component-page.mjs(86 条真实浏览器断言,随详情页改造同步
更新为「只允许一套导航可见」)、verify-brand-mark.mjs、lib/i18n-dead-keys.mjs
(只读诊断)。

回归:PC 100%(1464/1464,103 页,N/A 50)· 移动端 100%(807/807,47 页)。
门禁:component-page 86 · i18n 17 · brand 24 · routes all · smoke all ·
theme OK · isolation 31 · nav all · examples 9 · api-docs 10 · mobile-docs 12。

已知未做:i18n 另有约 44 条历史死键(非本次产生),已记为 ROADMAP S8-P6;
顶栏与悬浮区的两个主题入口为刻意设计(verify-theme 断言其互斥),未删。
2026-09-22 23:56:05 +08:00

145 lines
12 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.
# Kole UI · 平台与端(Platforms & Ends)
> **这份文件回答一个问题**:这个仓库里「PC 端 / 移动端 / H5 / Vue / uni-app」到底是什么关系,
> 新加一个组件或一个端时该往哪里放。
> 硬约束(隔离规则)在 §三,违反会被 `tools/verify-mobile-isolation.mjs` 直接拦下。
> 移动端的隔离细节另见 `.design_library/kole-ui-mobile/spec/移动端规格.md` §〇。
---
## 一 · 两轴模型
组件库按**两个正交的轴**组织,不要把它们混成一条列表:
| 轴 | 取值 | 决定什么 |
|---|---|---|
| **平台 platform** | `pc` | `mobile` | **组件清单与命名空间**。两端要的组件本来就不一样:PC 是中后台(表格/树/穿梭框/筛选面板),移动端是触屏优先(导航栏/标签栏/动作面板/下拉刷新/滑动单元格)。两套清单**不重叠**(有断言:slug 不得撞名) |
| **端 end** | `css` | `html`(H5 原生) | `jsx`(React) | `vue2` | `vue3` | `uniapp` | **同一组件在某个技术栈里的实现**。同一个组件在若干端上逐端实现,行为与视觉必须一致 |
矩阵长这样(✅ = 本次已交付,⬜ = 规划中):
| 平台 ↓ / 端 → | css | html(H5 原生) | jsx(React) | vue2 | vue3 | uniapp |
|---|---|---|---|---|---|---|
| **pc**(103 个中后台组件) | ✅ 103 | ✅ 103 | ✅ 103 | ✅ 103 | ✅ 103 | ⬜ **3 / 103 试点**(ROADMAP S7-P26) |
| **mobile**(47 个移动端组件) | ✅ 47 | ✅ 47 | ✅ 47 | ✅ 47 | ✅ 47 | ✅ **47 / 47** |
**uni-app 要单独说清楚**:它是一个「端」,不是第三个平台。
- **移动端 × uni-app**(`frameworks-mobile/<Prefix>.uniapp.vue`)→ 目标 `app-plus`(App)/ `mp-weixin`(微信小程序)/ `h5`。
用 uni 基础组件(`view`/`text`/`input`)+ `rpx` + **touch 事件**(小程序与 App 端没有 PointerEvent)。
- **PC 端 × uni-app**(`frameworks-uniapp-pc/<Prefix>.uniapp.vue`)→ 目标是 H5(PC 浏览器)与 PC 容器。
类名与 PC 的 `frameworks/*.css` **逐字一致**,令牌用 PC 的 `--kole-*`,尺寸保持 **px**(`rpx` 是移动端语义)。
- 也就是说「uni-app 移动端」与「uni-app PC 端」是**同一个端在两条平台列上的两份实现**,共享技术栈、不共享组件清单。
---
## 二 · 目录与命名映射
| 维度 | pc | mobile |
|---|---|---|
| 实现目录 | `frameworks/`(515 文件 = 103 × 5 端) | `frameworks-mobile/`(282 文件 = 47 × 6 端) |
| PC×uni-app 实现目录 | `frameworks-uniapp-pc/`(试点 3) | — |
| 契约 | `.design_library/kole-ui/components/*.json`(103) | `.design_library/kole-ui-mobile/components/*.json`(47) |
| 索引(唯一真源) | `.design_library/kole-ui/components/index.json` | `.design_library/kole-ui-mobile/components/index.json` |
| PC×uni-app 索引 | `.design_library/kole-ui-uniapp/index.json` | — |
| 令牌 | `--kole-*`(75) | `--kole-m-*`(15)+ **@import PC 令牌**(颜色/字体/圆角/阴影同源) |
| 类名 | `kole-` / 既有短名(`btn`) | `kole-m-`(状态类统一 `is-*`) |
| 导出名 | `KoleButton` | `KoleMNavBar` |
| 测试页 | `tests/<slug>.html`(103,生成物入库) | `tests/mobile/<slug>.html`(47,生成物入库) |
| 回归报告 | `tests/report.json` | `tests/mobile-report.json` |
| 文档站 | `site/`(SPA + History API 路由) | `site/m/`(**静态页**,不进 PC 路由表) |
| 自包含数据 | `site/data.json`(对外承诺,103) | `site/m/data.mobile.json`(移动端承诺,47 × 6 端源码) |
| 分发产物 | `dist/components|react|vue3|vue2` | `dist/mobile/*`;PC×uni-app → `dist/uniapp-pc/*` |
| 构建 | `build-site.ps1` + `tools/build-dist.mjs` | `tools/build-mobile.mjs`(Node,跨平台) |
| 门禁 | `tools/verify-cross-platform.mjs` 等 | `tools/verify-mobile-isolation.mjs` · `tools/verify-uniapp.mjs` · `tools/verify-mobile-docs.mjs` · `tools/verify-mobile-site.mjs` |
**为什么 token 前缀是 `--kole-m-` 而不是把移动端令牌也塞进 PC 令牌文件**:颜色、字体、圆角、阴影两端必须一致(改一处两端同时变),所以移动端令牌层 `@import` PC 令牌文件;而触控尺寸、安全区、移动端字号是移动端独有,放在 `--kole-m-*` 里。**PC 令牌文件一个字节都没改**。
---
## 三 · 隔离规则(硬约束)
1. 移动端实现**只能**在 `frameworks-mobile/`;PC 实现**只能**在 `frameworks/`。两端文件数有断言(515 / 30)。
2. 移动端类名只能是 `kole-m-<name>` 或状态类 `is-<state>`;移动端样式不得出现硬编码十六进制颜色。
3. 移动端样式只能引用 `--kole-*` 或 `--kole-m-*` 令牌,且令牌必须真实存在。
4. **PC 侧的目录、数据、测试、分发里不得出现任何移动端痕迹**(零 `kole-m-` 命中、零 `frameworks-mobile/` 引用)。
5. 移动端构建脚本自带写入守卫:`tools/build-mobile.mjs` 只允许写 `site/m/`、`tests/mobile/`、`dist/mobile/`;`tools/build-uniapp.mjs` 只允许写 `dist/uniapp-pc/`。越界直接抛错退出。
6. PC 的 `site/data.json` 承诺(一次请求拿到全部 PC 组件)保持不变;移动端另起 `site/m/data.mobile.json`,两端互不引用。
**门禁命令**(CI 里都跑):
```bash
npm run verify:isolation # 28 条隔离断言(PC 零污染 / 移动端自洽 / 分发隔离)
npm run verify:uniapp # 9 条 uni-app 静态断言(8 个 SFC)
npm run regression # PC 回归(100% 才过)
npm run regression:mobile # 移动端回归(100% 才过)
```
---
## 四 · 新增一个移动端组件的标准流程
1. 在 `.design_library/kole-ui-mobile/spec/移动端规格.md` 补一节(用途 / anatomy / 变体维度 / 状态 / 交互与触控 / 无障碍 / doNotInvent / unknowns)——**规格是契约的授权来源,先写规格再写代码**。
2. 在 `.design_library/kole-ui-mobile/components/index.json` 的 `components` 里登记:`slug`(不得与 PC 的 103 个撞名)、`frameworksPrefix`、`category`、`specSection`、`contract`、`files`(6 个端的文件名,**必须全部声明**)。
3. 写 6 个端实现到 `frameworks-mobile/`:`<Prefix>.css` / `.html`(演示页,含 `.demo` 容器与 `data-assert`/`data-behavior`)/ `.jsx` / `.vue2.vue` / `.vue3.vue` / `.uniapp.vue`。
4. 写契约 `.design_library/kole-ui-mobile/components/<slug>.json`:`sourceKind: "authored-spec"`、`provenance: "authored-in-repo"`,`usageHints`/`anatomy` 逐字取自规格。
5. `npm run build:mobile` → 生成 `site/m/**`、`tests/mobile/**`、`dist/mobile/**`(生成物入库)。
6. `npm run verify:isolation && npm run verify:uniapp && npm run regression:mobile`,三条全绿才算完成。
### 新增一个端
在索引的 `ends` 里加一项、给每个组件补对应文件、在 `build-mobile.mjs` 里加该端的产物导出(并在 `package.json` 的 `exports` 补 `./mobile/<end>`)。若该端有运行时约束(如 uni-app 无 DOM),**必须**给它加静态门禁(参照 `tools/verify-uniapp.mjs`)。
---
## 五 · 构建 / 测试 / 分发 / 部署
### 访问方式(本地)
```bash
npm run serve # 默认 http://127.0.0.1:3311;端口被占用会自动改用 3312/3313…(最多 10 档并打印实际端口)
KOLE_PORT=13511 npm run serve # 需要固定端口时(隧道/CI/验证脚本用固定端口,显式指定则**不回退**)
```
启动后控制台直接给出全部入口(不用记路径):
| 入口 | URL |
|---|---|
| PC 文档站 | `/site/` |
| 移动端文档站 | `/site/m/` |
| PC 组件总览 | `/site/overview` |
| PC 测试总览 | `/tests/index.html` |
| 移动端测试总览 | `/tests/mobile/index.html` |
| 回归收集器(PC / 移动端) | `/tests/_collect.html` · `/tests/mobile/_collect.html` |
**站内切换**(不用手改 URL):PC 侧栏第一组是「平台」——`PC 端组件`(当前)/ `移动端组件`(整页跳到移动端静态站);
移动端站的**左栏**有对称的「平台」组(`PC 端组件` / `移动端组件`,带副标题与「当前」角标)。
两端的平台入口都**只有左栏一处** —— 移动端站顶栏原有一个 `[PC 端] [移动端]` 分段控件,与左栏指向同一跳转
(实测两条链接 href 均为 `../index.html`),2026-09-20 去重时删除;PC 顶栏从来没有过这个控件。
移动端链接带 `.html` 扩展名,SPA 路由拦截器会放行(见 §三 规则 5)。
跑验证时把端口对齐:`REG_BASE=http://127.0.0.1:<实际端口> node tools/run-regression.mjs`(PC 与移动端 runner 同此约定)。
### 构建与产物
```bash
npm run build # = build-dist(PC)+ build-mobile(移动端)+ build-uniapp(PC×uni-app)
npm run build:mobile # 只重建移动端(索引改了必须重跑,否则页面与数据是旧的)
```
- **文档站**:PC 是 SPA(`site/app.js` 按 pathname 渲染);移动端是**静态站** `site/m/`,不注册进 PC 路由表 —— 改 PC 路由不会影响移动端页面,反之亦然。
- **测试**:两端共用断言引擎 `tests/_runtime.js`(矩阵断言同口径);行为动词分开:PC 用 `tests/_behaviors.js`,移动端用 `tests/mobile/_behaviors.js`(含 `swipe-sets-class` / `swipe-sets-attr` / `pull-triggers` 三个触控动词)。**两端行为库互不加载**。
- **部署**:`tools/pack-deploy.mjs` 的 `CONTENT_DIRS` 已含 `frameworks-mobile` 与 `frameworks-uniapp-pc`,并新增硬断言(移动端实现文件数 / 文档页数 / 测试页数 / 3 个 uni-app 试点 —— **全部按索引组件数算**,新增组件自动跟随,不需要改断言);`Dockerfile` 同步两条 `COPY`;移动端规格原文(`.design_library/kole-ui-mobile/spec`)与 PC 规格同策略**不进镜像**。
- **分发**:PC 消费 `kole-ui`(`./components/*`、`./react` …);移动端消费 `kole-ui/mobile`(`./mobile/components/*`、`./mobile/react|vue3|vue2|uniapp`);PC×uni-app 消费 `kole-ui/uniapp-pc/*`。**PC 用户拿到零移动端字节**。
---
## 六 · 现状与未覆盖(诚实清单)
| 项 | 状态 |
|---|---|
| 移动端组件数 | **47**(导航 6 · 反馈 12 · 通用 5 · 数据展示 8 · 数据录入 16)。权威清单见 `.design_library/kole-ui-mobile/components/index.json`(47 项)与 `frameworks-mobile/`(282 文件 = 47 × 6 端) |
| PC × uni-app | **3 / 103 试点**(button / input / card)。全量转换见 ROADMAP S7-P26 |
| uni-app 真实编译 | ✅ **已执行**:`npm run verify:uniapp-build` 把 50 个 SFC(移动端 47 + PC 3)真实编译到 **H5 与微信小程序**,含「契约声明的类名都进了产物」断言。依赖装在 `.tmp/uniapp-build`(gitignore),主仓库零运行时依赖不变。**App 端(app-plus)仍未覆盖** —— 需 HBuilderX 云端打包,命令行无法完成 |
| 移动端 SEO 薄壳 / sitemap | **未做**:`site/m/component/<slug>.html` 是静态页可索引,但根 `sitemap.xml` 只收 PC URL。见 ROADMAP S7-P27 |
| 移动端文档站导航 | **四页(总览 / 快速开始 / 平台与端 / 设计令牌)+ 逐组件页(14 小节,对齐 TDesign 范式:演示按 01/02 分组、每块独立预览 + 原文代码、Props 必传列、CSS 变量表、相似组件表)+ 共用左栏导航**:开发指南 5 项 + 组件按分类分组;**顶栏与左栏与 PC 同结构**(logo 含副标题 + 版本下拉 + 同名主导航 5 项 + 主题三态图标,跨站生效;左栏三段式:平台 / 开发指南 / 组件 N 按 PC 分类);顶栏 60px、内容在 1180px 容器内居中、激活项带 2px 底部指示条 —— 逐项对齐 PC 顶栏。**平台入口只在左栏**(2026-09-20 去重:顶栏原有的 `[PC 端][移动端]` 分段控件与左栏重复)。桌面恒定展开、≤1000px 自动收起。未做中英双语(PC 有 330 条 i18n 字典) |