本提交含两条并行工作线,因互相咬合(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 断言其互斥),未删。
26 KiB
AGENTS.md · Kole UI 执行约定
给在此仓库工作的 AI 模型:这个文件是硬约束,不是建议。开始任何任务前先读完。 人类贡献者请看 CONTRIBUTING.md;任务清单看 ROADMAP.md。
一 · 这个仓库是什么
Kole UI Design System —— B 端中后台设计系统,两个平台 × 六个端(详见 PLATFORMS.md):
- PC 平台:103 个中后台组件 × 5 端(H5 原生 / React / Vue 2 / Vue 3 / CSS)
- 移动端平台:触屏优先组件 × 6 端(上述 5 端 + uni-app),与 PC 物理隔离
- PC × uni-app 端:把 PC 组件清单以 uni-app 实现(试点 3 / 103)
| 项 | 值 |
|---|---|
| PC 组件 | 103 |
| PC 端实现文件 | 515(frameworks/,103 × 5) |
| PC 契约 JSON | 103(.design_library/kole-ui/components/) |
| 设计令牌 | 75(colors_and_type.css)+ 移动端 15(--kole-m-*,@import PC 令牌) |
| i18n 字典 | 592 条(site/i18n.js;verify:i18n 卡重复键为 0) |
| PC 测试断言 | 1464 通过 / N/A 50(tests/,103 页;共 1514 条) |
| 移动端组件 | 47(导航 6 · 反馈 12 · 通用 5 · 数据展示 8 · 数据录入 16) |
| 移动端端实现文件 | 282(frameworks-mobile/,47 × 6 端) |
| 移动端测试断言 | 807 通过 / N/A 10(tests/mobile/,47 页;共 817 条) |
| PC × uni-app 试点 | 3(frameworks-uniapp-pc/,button / input / card) |
| 回归通过率 | PC 100%(八次连跑一致)· 移动端 100% |
新增组件/端之前先读 PLATFORMS.md —— 那里有两轴模型、目录命名映射、新增流程与隔离规则。
二 · 六条铁律(违反即返工)
1. 零运行时依赖
不引入 npm 运行时依赖。
# 验收:这条必须在所有改动后通过
# 注意:P2 之前 package.json 不存在,此时应输出 "n/a (no package.json yet)" 而非报错
node -e "
const fs=require('fs');
if(!fs.existsSync('package.json')) { console.log('n/a (no package.json yet)'); process.exit(0) }
const p=require('./package.json');
const deps=Object.keys(p.dependencies||{});
if(deps.length) { console.error('FAIL: 运行时依赖 ' + deps.join(', ')); process.exit(1) }
console.log('zero-dep OK');
"
devDependencies 可用(构建/测试工具),但要在 README 注明"CI 专用"。
2. build-site.ps1 必须 ASCII-only
PowerShell 5.1 按 ANSI 读无 BOM 文件 —— 脚本里出现非 ASCII 字面量会被静默损坏。
- 中文文案放 UTF-8 模板(
tests/_template.html等) - 输出用
[System.IO.File]::WriteAllText($path, $content, [System.Text.UTF8Encoding]::new($false))写无 BOM build-site.ps1只能在 Windows 跑;CI 需要构建时改用runs-on: windows-latest
构建链是两步,必须按序执行
npm run build:site # 等价于下面两步
# 1) powershell -NoProfile -ExecutionPolicy Bypass -File build-site.ps1
# 2) node tools/precompute.mjs
第 2 步不能省 —— build-site.ps1 会把 data.js 重写回全量(2026-09-20 实测 1166 KB),
tools/precompute.mjs 才做瘦身(同次实测 → 122 KB,把 css 源码移到 site/sources/<slug>/css.txt)。
只跑第 1 步会导致:data.js 变大、且 sourcesRef 字段消失 → 详情页代码区缺 CSS tab。
单独重跑只需 npm run precompute。
3. 改结构要改模板
tests/<slug>.html × 103 是生成物。改它们没用 —— 下次重跑会被覆盖。
| 想改 | 改哪里 |
|---|---|
| 测试页结构 | tests/_template.html → 重跑 run-tests.ps1 |
| 测试总览页 | tests/_index_template.html |
| 测试断言逻辑 | tests/_runtime.js(跨帧断言引擎) |
| 文档站 | site/app.js |
4. 改样式要改内嵌层
演示页的内嵌 <style> 才是实际生效的样式。
v1.4.0 的教训:花了几小时令牌化 frameworks/*.css(915 处),结果发现演示页不一定 link 它 —— 真正生效的是内嵌的 <style> 块(另 287 处)。
# 诊断:这个页面的样式从哪来
grep -o 'href="[^"]*\.css"' frameworks/Button.html
# 若无 frameworks/Button.css,说明样式在内嵌 <style> 里
5. data.json 是对外承诺
site/data.json 是对外承诺的「一次请求拿到全部」(原先由文档站的 For Agents 页公示,该页已于 2026-09-20 随 AI 消费模块一并移除,承诺本身不变)。可以拆 data.js(性能优化),但 data.json 必须保持完整。
破坏它是 breaking change。
6. 单次改动后必须跑回归
node site/dev-server.js & # 起服务(端口 3311)
# 浏览器打开 http://127.0.0.1:3311/tests/_collect.html
# 或:node tools/run-regression.mjs(需 playwright)
验收标准:100% / 0 失败 / 0 超时,且连跑八次一致。
为什么是八次:偶发问题(并发超时)在单次运行中可能不出现。项目的超时兜底逻辑已改为「重试一次 + 超时单列」,但连跑仍是最可靠的验证。
三 · 禁止事项
| 禁止 | 原因 | 正确做法 |
|---|---|---|
手工改 frameworks/ 里的样式让它"更好看" |
那是规范原文的忠实实现 | 改令牌,或走 ROADMAP 任务包 |
把移动端组件放进 frameworks/,或在移动端实现里用 PC 的类名/令牌 |
两端目录、类名(kole- vs kole-m-)、令牌(--kole- vs --kole-m-)是隔离边界;混放后 PC 的目录数、测试数、分发产物全会被污染 |
移动端一律写 frameworks-mobile/,见 PLATFORMS.md §一/§二;npm run verify:isolation 会拦 |
在 uni-app 端使用 document / window / PointerEvent / rpx(PC 列) |
小程序与 App 端没有 DOM,也没有 PointerEvent;rpx 是移动端语义 |
用 uni 基础组件 + @touch* 事件;移动列用 rpx、PC 列用 px;npm run verify:uniapp 会拦 |
直接改 PC 的 site/data.json / tests/report.json 来"顺便"容纳移动端数据 |
这两个是 PC 侧的对外承诺与证据 | 移动端另起 site/m/data.mobile.json / tests/mobile-report.json |
git reset --hard / git checkout . 清理 |
会丢用户改动 | git stash 或定向还原 |
改写 CHANGELOG.md 的历史条目 |
变更事实记录 | 只追加 [Unreleased] 或新版本段 |
改 tests/report.json 的数值 |
等于伪造证据 | 修实际问题后重跑生成 |
| 为通过验收而放宽断言判据 | v1.3.1 出现过这个诱惑 | 判据修正必须附理由 + 反例 |
| 在任务范围外顺手重构 | 范围蔓延让验收失焦 | 写成新任务包追加到 ROADMAP |
四 · 交付形态
每个任务完成时提交交付说明:
## <任务 ID> 完成说明
**验收输出**(原样粘贴命令输出,不要转述):
(命令 + 输出)
**改动文件**:
- <路径> — <做了什么>
**规划偏差**(若有):
- ROADMAP 写的 <X> → 实际的 <Y>,原因:<...>
**发现的新问题**(若有):
- <描述> → 已追加为 ROADMAP 任务包 <ID>
**回归**:100%(<通过>/<总数>)/ 八次连跑一致 / 0 超时
不要写「已完成」而不给证据。 这个项目的历史上有 6 次"文档声称完成但代码缺失",全部是靠实测发现的。
五 · 失败升级路径
按顺序处理,不要停下来等:
| 情况 | 处理 |
|---|---|
| 验收命令本身有错 | 修正它使其真实反映目标,在交付说明写明修了什么、为什么 |
| 目标不可达(依赖的服务/网络不可用) | 交付最强替代物 + 写明缺什么 |
| 发现 ROADMAP 有事实错误 | 以实测为准,修正规划并标注「⚠️ 规划修正」 |
| 发现规划未覆盖的新缺口 | 写成新任务包追加到 ROADMAP,不在原任务里顺手修 |
| 同一路径连续两次失败 | 换策略而非重试,记录两次失败的原因 |
六 · 关键文件地图
组件规范第一套/
├─ AGENTS.md ← 本文件(硬约束)
├─ PLATFORMS.md ← 平台 × 端两轴模型 + 隔离规则(新增组件/端前必读)
├─ ROADMAP.md ← 任务清单(任务包 + 验收命令)
├─ CHANGELOG.md ← 变更记录(build 时注入文档站)
├─ CONTRIBUTING.md ← 人类贡献指南
├─ TESTING.md ← 测试矩阵说明
├─ LICENSE ← MIT
│
├─ build-site.ps1 ← PC 文档站构建(ASCII-only!生成 data.js/data.json/薄壳/sitemap/令牌导出)
├─ run-tests.ps1 ← 重生成 103 个 PC 测试页
│
├─ frameworks/ ← PC:515 个实现文件(103 × 5 端)—— 只读,除非规格变更
├─ frameworks-mobile/ ← 移动端:282 个实现文件(47 × 6 端,含 .uniapp.vue)
├─ frameworks-uniapp-pc/ ← PC × uni-app 端:3 个试点 SFC
│
├─ .design_library/kole-ui/ ← PC 设计库
│ ├─ colors_and_type.css ← 75 个设计令牌(改色的唯一入口,两端共用)
│ ├─ components.css ← 6 核心组件样式聚合
│ ├─ css.json ← 结构化令牌(For Agents 消费)
│ ├─ components/*.json ← 103 份契约(含 unknowns/doNotInvent)
│ └─ specs/组件1~10.txt ← 规范原文(CRLF!读时用 split(/\r?\n/))
│
├─ .design_library/kole-ui-mobile/ ← 移动端设计库(与 PC 隔离)
│ ├─ colors_and_type.css ← @import PC 令牌 + 15 个 --kole-m-* 触控/安全区令牌
│ ├─ components/index.json ← 移动端索引(6 端声明 + 隔离规则)
│ ├─ components/*.json ← 5 份契约(sourceKind: authored-spec)
│ └─ spec/移动端规格.md ← 移动端规格原文(契约的授权来源,**无外部规范**)
├─ .design_library/kole-ui-uniapp/index.json ← PC × uni-app 索引(试点 3 / 103)
│
├─ site/
│ ├─ app.js ← PC 文档站全部逻辑(History API 路由 SPA)
│ ├─ index.html ← SPA 壳:内联脚本按 URL 反推站点根,资源用绝对地址写出
│ ├─ i18n.js ← 330 条中英字典(中文源串作键)
│ ├─ data.js / data.json ← PC 构建产物(勿手改;data.json 是对外承诺)
│ ├─ examples/<slug>.json ← 逐示例用法片段(构建期生成,按组件懒加载)
│ │ 一个使用场景 = 标题 + 预览隐藏计划 + 四端调用代码,
│ │ 出处标注 demo-mapped / demo-data / api-derived(见 tools/lib/demo-examples.mjs)
│ ├─ tokens/ ← 令牌导出(CSS / W3C DTCG / Figma)
│ ├─ components/*.html ← 103 个静态薄壳(SEO 入口)
│ └─ m/ ← 移动端文档站(静态页,不进 PC 路由表)
│ ├─ style.css ← 自包含样式(不引 site/style.css)
│ ├─ _index_template.html ← 总览页模板(改结构改这里)
│ ├─ _guide_template.html ← 快速开始(三步接入 / 6 端示例 / 常见问题)
│ ├─ _platform_template.html ← 平台与端(两轴矩阵 / 映射表 / 隔离规则 / 门禁命令)
│ ├─ _tokens_template.html ← 设计令牌(--kole-m-* 表 + 继承令牌表)
│ ├─ _component_template.html ← 组件页模板(14 小节,改结构改这里)
│ ├─ index/guide/design/faq/changelog/platform.html ← 生成物(六页:与 PC 同名同序的指南页)
│ ├─ data.mobile.json ← 移动端自包含数据(18 × 6 端源码,生成物)
│ └─ component/<slug>.html ← 逐组件文档页(生成物:API / 6 端源码 / 令牌 / 回归状态)
│
└─ tests/
├─ _template.html ← PC 测试页模板(改结构改这里)
├─ _runtime.js ← 跨帧断言引擎(**两端共用**)
├─ _behaviors.js ← PC 行为库(6 试点组件)
├─ _collect.html ← PC 零依赖批量回归收集器
├─ report.json ← PC 回归报告(生成物)
├─ <slug>.html × 103 ← PC 生成物
└─ mobile/ ← 移动端测试
├─ _template.html ← 移动端测试页模板(375×640 设备帧)
├─ _behaviors.js ← 移动端行为库(含 swipe-sets-class / swipe-sets-attr / pull-triggers)
├─ _collect.html ← 移动端收集器(读 site/m/data.mobile.json)
└─ <slug>.html × 5 ← 生成物(tests/mobile-report.json 为移动端回归报告)
构建与门禁脚本(移动端相关):tools/build-mobile.mjs(移动端全部产物:数据 / 文档站四页 + 组件页 / 测试页 / dist/mobile/**;写入守卫只允许 site/m/ tests/mobile/ dist/mobile/)、tools/build-uniapp.mjs(PC×uni-app 产物,守卫只允许 dist/uniapp-pc/)、tools/verify-mobile-isolation.mjs(30 条隔离断言:PC 零污染 / 移动端自洽 / 分发隔离)、tools/verify-uniapp.mjs(9 条 uni-app 静态断言 × 21 个 SFC)、tools/verify-uniapp-build.mjs(11 条真实编译断言:隔离目录装 @dcloudio → 搭最小工程 → 21 个 SFC 编译到 H5 + mp-weixin → 断言产物含契约声明的类名)、tools/verify-mobile-docs.mjs(12 条文档完整性断言:14 小节齐全 / 侧栏列全 / 契约 API ↔ 4 个框架端源码逐名一致 / 变体类名在 CSS 里真实存在)、tools/verify-mobile-site.mjs(118 条浏览器实测:200 / 0 控制台错误 / 演示帧真渲染 / 令牌生效 / 320–768px 无横向溢出)、tools/run-mobile-regression.mjs(移动端回归,报告含逐页 pageResults)。
逐示例用法片段(npm run verify:examples):tools/lib/demo-examples.mjs 在构建期做三件事 —— 切场景(extractExamples)、提 class↔prop 映射(extractClassPropMap)、生成四端用法片段(buildSnippets);tools/verify-examples.mjs 复核落地产物(片段里的 prop 必须能指到 API/源码、class 必须在组件 CSS 里、预览隐藏路径必须能解析到 demo 页 DOM)。判据只认「能指到源码某处」的事实,不做启发式打分。
七 · 已知陷阱速查
| 陷阱 | 现象 | 解法 |
|---|---|---|
| 规范文件是 CRLF | 正则 /^#{3}/ 匹配不到行尾,标题解析全失败 |
split(/\r?\n/) 先归一化 |
| PS5.1 写文件带 BOM | 严格 JSON 解析器(node require)直接失败 | WriteAllText + UTF8Encoding($false) |
| 演示页 DOM 由内联脚本生成 | 静态抽快照得到空 DOM | 用 iframe 载真实页面跨帧断言 |
| 并发 iframe 抢主线程 | 偶发超时被误记为失败 | 已修:超时重试 + 超时单列(见 _collect.html) |
| 深层路由刷新 404 | /site/component/button/h5 磁盘上没有这个文件,只有前端能渲染 |
三处回落缺一不可:nginx.conf 的 location /site/、site/dev-server.js 的 isSpaRoute、Pages 发布包的 404.html;tools/verify-site-routing.mjs 会静态卡这四处 |
| 站点目录改名 / SPA 壳里写相对路径 | 深层 URL 下相对路径全部按深层目录解析(CSS 与 data.js 静默 404) |
站点根从 pathname 里第一段 /site/ 反推(site/index.html 内联脚本 + app.js 的 SITE_BASE 两处,必须同规则);资源一律 base + 'xxx' 绝对地址写出 —— 静态相对路径会被预扫描器按深层 URL 先白取一次(实测 2 个 404 + 2 条控制台报错,data.js 整份重下) |
| 改令牌组件不变 | 改的是没被加载的文件 | 改内嵌 <style>(铁律 4) |
| 逐示例代码区常显后主题对比度门禁变红 | 代码块借 --kole-color-tooltip-bg,该令牌暗色下是浅色(tooltip 反色),而代码文字与语法高亮是固定浅色 → 浅压浅;此前代码区默认收起、verify-theme 的对比度抽查扫不到,改成常显后立刻暴露 |
深色下给代码区补 html.kole-dark .ex-code { background: var(--kole-color-page-bg) };语法高亮调色板按深底实测选(hl-tag 8.24 / hl-kw 7.35:1 等,全部 ≥4.5:1)。新增常显代码块时同步跑 npm run verify:theme |
演示页脚本钩子 id 混进用法代码 |
例:<button class="btn" id="demo-toggle"> 里的 id 是演示脚本 getElementById 用的钩子,用户复制后无用且误导 |
构建期用 extractDemoIds() 收集脚本引用过的 id,buildSnippets 里剔除;同理 data-behavior/data-assert 是测试钩子,一律不进片段 |
$themes / $schema 在 PS 里 |
被当变量展开成 null,报"Null 键" | 用引号包裹键名 '$themes' |
Write-Output "...{}..." -f $n |
{} 被当格式占位符 |
改写措辞或转义 |
.dockerignore 的 *.md / *.png 等 glob |
只匹配构建上下文根目录,嵌套路径照样进镜像(实测:sub/nested.md 仍被 COPY) |
嵌套一律写 **/*.md;排除目录写完整相对路径 |
| 手工拷贝部署目录 | 修复被下一次拷贝覆盖(absolute_redirect off 就是这样丢的),且 .dockerignore 不随行导致规范原文入镜像 |
走 §九 的 tools/pack-deploy.mjs,不要手工拷贝 |
| 部署后浏览器仍跑旧 JS | 静态资源无 Cache-Control 时浏览器会启发式缓存(实测:页面内 fetch 能取到新 app.js,<script src> 却用缓存) |
nginx 已加 Cache-Control: no-cache(带 ETag 复验 304);升级前遗留的旧缓存需强刷一次 |
KOLE_PORT 默认 13311 与文档里的隧道端口撞车 |
tools/verify-dev-server.mjs 报 EADDRINUSE 并失败 |
隧道开着时用 KOLE_PORT=13511 node tools/verify-dev-server.mjs |
| 新增类名 / 令牌 / 组件导出名时随手起前缀 | 这三类前缀都是品牌缩写,不是任意命名:类 kole-、令牌 --kole-、导出名 Kole*(如 KoleButton)。v2.0.0 起统一;此前是 aa- + Input 组件的 au-,导出名是 Aa* |
新增一律沿用 kole- / --kole- / Kole*;批量改名或查残留用 tools/migrate-brand-kole-ui.mjs(--dry-run 预演 / --verify 扫残留)。补规则时用 --only=<子串>:全量重跑会把「刻意记录旧名」的对照表(本表、CHANGELOG 2.0.0 段)也改写掉 |
| 把「对外实测事实」当成品牌词一起批量替换 | 例:aurora-admin-design 未被占用(当时实测)被改成 kole-ui 未被占用 —— 事实变成未核验断言(v2.0.0 改名时真的踩到) |
品牌词可替换,记录了外部状态的名字只能新增核验:还原旧名 + 补一次新名的实测并写明日期 |
| 新增顶层目录后忘了加进 dev-server 白名单 | 页面在浏览器里 403(frameworks-mobile/NavBar.html 实测),但直接用相对路径打开文件是好的,容易误判成"构建没产出" |
site/dev-server.js 的 PUBLIC_ROOTS + isPublicPath() 两处都要加(本次新增 frameworks-mobile、frameworks-uniapp-pc);nginx 走 location / 全放行,不需要改 |
| 本地 3311 上还挂着改动前启动的 dev-server | 新目录一律 403 / 新页面 404,日志里是 EADDRINUSE(新实例根本没起来),而老实例照常服务旧代码 |
site/dev-server.js 已改为端口占用自动回退(最多 10 档)并在启动时打印全部入口(PC 站 / 移动端站 / 两个测试总览 / 两个收集器);要固定端口用 KOLE_PORT=13511 node site/dev-server.js,再用 REG_BASE=http://127.0.0.1:<实际端口> 跑回归与门禁 |
| 顶栏 UI 改动后忘了同步「按文字量计算」的验证脚本 | verify-nav-responsive.mjs 的字体容忍度元素清单仍指向已不存在的 .fw-label,余量被报得偏乐观(少算一个元素) |
改顶栏文字承载元素时同步该清单(本次 .fw-label/#fw-select → .fw-cur/.fw-menu .fw-opt);判据不放松,只是让测量对象跟着 UI 走 |
同一页并列展示多个 position: fixed 的移动端组件 |
全部叠在视口同一位置,演示页"看起来只渲染了一个" | 展示框加 transform: translateZ(0)(或任何 transform/filter)建立包含块,fixed 就以该框为基准;本次 TabBar / ActionSheet 演示页用此法,组件 CSS 保持 fixed 不变 |
| 静态门禁把注释当成违规代码 | 「注释里解释为什么不用 PointerEvent」被判成 PointerEvent 违规(本次 3 个文件误报);\brpx\b 也匹配不到 100rpx(0 与 r 之间没有词边界) |
门禁先剥注释(<!-- -->、/* */、行首 //)再判;单位判据写 [0-9]rpx\b。判据修正的理由已写进 tools/verify-uniapp.mjs 注释 |
八 · 当前状态
版本:v1.0.0 | 回归:PC 100%(1464 通过 / 0 失败 / N/A 50,共 1514 条断言,103 页)· 移动端 100%(807 通过 / 0 失败 / N/A 10,共 817 条,47 页)| 下一阶段:ROADMAP 的 S7 移动端批次
已完成的里程碑:
- v1.3.0 验收链路修复(测试页从空 DOM 误报改为 iframe 真实渲染)
- v1.3.1 无障碍与令牌合规(回归 85.1% → 100%)
- v1.3.2 契约全量 79/79 + 令牌导出三格式
- v1.3.3 中英双语 i18n
- v1.4.0 组件层全面令牌化(1202 处)
- v1.4.1 四轮审计 + 回归偶发根治
- v2.0.0 品牌重命名 Kole UI(1373 文件 / 约 2.9 万处;类名前缀
aa-+au-→kole-,令牌--au-→--kole-,包名kole-ui,破坏性变更)
当前缺口(详见 ROADMAP 的 G1-G8):
无 LICENSE(已补)、无分发机制、CI 无测试、暗色模式是假的、跨端一致性无验证、data.js 1MB、RTL 未支持、断言偏结构。
九 · 部署(192.168.5.7)
当前形态(2026-09-20 实测):容器 kole-ui-showcase / 镜像 kole-ui-showcase:latest,端口 127.0.0.1:3311 -> 80。
只监听回环——局域网直连 192.168.5.7:3311 会超时,这是有意的;公网入口是 https://kole-ui.mymoyu.top(经服务器上的 frp 隧道指向同一容器),所以除 SSH 隧道外还有这一条公网访问路径。不要靠改绑定或挂反代来解决"打不开"。
本机访问(Windows,已实测可用):
ssh -o ExitOnForwardFailure=yes -N -L 13311:127.0.0.1:3311 root@192.168.5.7
# 然后浏览器打开 http://127.0.0.1:13311/site/
本地用 13311 而不是 3311,是为了不和 node site/dev-server.js(本地也占 3311)抢端口。
想要局域网/其它设备直接访问:那是一次显式的暴露变更(改 compose 绑定为 0.0.0.0:3311),并且 Docker 发布端口会绕过 ufw 规则 —— 需要明确许可后再做。
部署目录:/opt/aurora-admin(= docker build 上下文,必须含 Dockerfile / nginx.conf / .dockerignore / docker-compose.yml / sitemap.xml + 4 个内容目录)。目录名仍是改名前的,容器/镜像已随仓库切到 kole-ui-showcase —— 刻意不重命名目录,mv 同名替换即可,避免动 compose 项目标识。
标准流程(不要在服务器上手工拼文件):
# 1) 本地打包(.dockerignore 是排除规则的唯一真源,含硬断言)
# 先带公网基址构建:不带 SITE_URL_BASE 时 build-site.ps1 会把 sitemap 写成占位域名
# (tools/release.mjs 的既有约定是「占位禁正式发布」)。
SITE_URL_BASE=https://kole-ui.mymoyu.top/ npm run build:site
node tools/pack-deploy.mjs --tar # -> dist-deploy/kole-ui-deploy.tar.gz
# 2) 上传 + 备份现状
# scp 到 /tmp/kole-ui-deploy.tar.gz
# ssh: tar czf /root/kole-ui-backup-$(date +%Y%m%d-%H%M).tgz -C /opt aurora-admin
# 同时给现役镜像打回滚标签:docker tag kole-ui-showcase:latest kole-ui-showcase:pre-<日期>
# 3) 解到暂存目录、核对、替换、重建
cd /opt && mkdir -p aurora-admin.staged \
&& tar xzf /tmp/kole-ui-deploy.tar.gz -C aurora-admin.staged --strip-components=1
ls -a aurora-admin.staged # 必须无 specs/ agent-reports/ preview/ ui_kits/
# 逐字节核对(包内哈希取自本地 `find dist-deploy/kole-ui -type f -exec sha256sum {} +`)
# 远端:cd /opt/aurora-admin.staged && find . -type f -exec sha256sum {} + | sort -k2
# 两边路径前缀归一后 diff,必须 0 行差异
mv aurora-admin aurora-admin.prev-<日期> && mv aurora-admin.staged aurora-admin
cd /opt/aurora-admin && docker compose build && docker compose up -d
# 4) 验收(五条必须全中)
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3311/.design_library/kole-ui/specs/ # 404(目录级;单文件请求也是 404)
curl -sI http://127.0.0.1:3311/ | grep -i '^Location' # /site/
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3311/sitemap.xml # 200
curl -sI http://127.0.0.1:3311/healthz | grep -ci '^content-type' # 1
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3311/site/component/button/h5 # 200(SPA 深层路由)
# 版本核对
curl -s http://127.0.0.1:3311/site/data.json | grep -o '"version": *"[^"]*"' | head -1 # 期望当前版本
部署前必读:
- 本工作区可能有并发构建/审计任务在写
site/、frameworks/。打包前后各查一次产物哈希:若打包后又被改写,线上快照就落后于源码——要么等稳定后重发,要么在交付说明里写明。2026-09-20 本轮部署中真的踩到(app.js在打包后 1 分钟被改过)。 REG_BASE不设置时tools/run-regression.mjs打的是http://127.0.0.1:3311——隧道开着时那就是线上旧版,会给出"回归 100%"的假绿灯。验证本地构建请先KOLE_PORT=3399 node site/dev-server.js,再REG_BASE=http://127.0.0.1:3399 node tools/run-regression.mjs。
铁律:任何"只改服务器、不回写仓库"的修复都会在下次部署时丢失——nginx.conf 的 absolute_redirect off 已经因此丢过一次。先改仓库,再走打包流程。