feat:移除了弹窗,服务器添加sls

This commit is contained in:
2026-09-08 22:39:45 +08:00
commit 6a295f9a7a
4082 changed files with 1322534 additions and 0 deletions

View File

@ -0,0 +1,74 @@
<p align="center">
<img src="./assets/readme/hero.png" width="100%" alt="oil-frontend从用户任务出发修改产品前端真正出错的位置">
</p>
<p align="center">
一套约束 AI 产品前端实现的 Agent Skill。
</p>
<p align="center">
<code>任务与对象</code> · <code>状态与范围</code> · <code>界面与空间</code> · <code>组件与代码</code>
</p>
## 为什么需要这个 Skill
AI 编写的前端通常可以运行,也可能通过类型检查和构建。实际问题常出现在用户开始操作以后:它可能沿用错误的旧实现,在列表里堆满字段和按钮,把局部请求处理成全页 loading或者在共享组件外继续补 CSS。改动次数增加以后界面含义、数据状态和代码归属会逐渐分离。
`oil-frontend` 让 Agent 在设计、实现、重构和评审产品前端时,按照同一套顺序判断问题。
## 它会处理的五个重点
### 1. 先确认用户任务和业务对象
AI 容易从已有字段、组件和页面结构继续拼接。Skill 要求先确认用户要完成的任务、页面管理的业务对象、字段所有者和完成结果,再决定使用列表、表格、选择器、表单、弹窗或完整工作区。
项目原有模式本身错误时,不继续复制。
### 2. 删除无效信息和伪操作
每段文字、图标和动作都必须帮助用户识别、比较、判断、操作或理解结果。没有这些作用的 UUID、内部枚举、`3 selected`、重复流程说明、通用 AI 图标和装饰性强调边会被删除。
每个可见动作都必须产生真实的数据变化、导航或结果。表单只收集当前任务需要的数据,不默认增加草稿、预览、重置、步骤条和重复确认。
### 3. 保证数据、状态和作用域真实
同一业务数据只保留一个权威来源。选择器不能把当前分页当作全部候选;查询条件、列表、总数和分页必须属于同一次响应;单项请求只锁定对应对象,不阻塞整个页面。
异步操作成功后再关闭弹窗,失败时保留当前对象、用户输入和操作上下文。
### 4. 让界面结构和代码各自归位
列表负责识别和比较,详情负责完整内容,编辑器负责修改。尺寸由内容和父容器决定,每个页面、弹窗和表格都需要明确自己的滚动范围。
页面负责组合组件负责自身视觉和状态。组件、Hook、函数、类型、样式和测试按业务归属组织共享组件的问题在共享层处理不在页面使用位置反复覆盖样式。
### 5. 修改源头并完成迁移
Agent 会先检查数据流、父布局、共享组件和全部使用位置再修改真正产生问题的实现。新实现接管以后删除旧组件、旧状态、旧类型、旧样式、fallback 和 legacy 逻辑。
验证不会停在类型检查、Lint 或构建通过。Agent 还要检查本次改动涉及的状态、数据范围、视口和共享实现使用位置。
## 它怎么读取规则
产品前端相关的实现、修改、重构和评审会自动触发这个 Skill。触发后先只读取 [SKILL.md](SKILL.md) 判断任务范围,再按需读取对应参考规则;不相关的任务不会继续加载其他文件。
## 安装
[oil-oil/oil-frontend](https://github.com/oil-oil/oil-frontend) 安装这个 skill
## 使用
安装后可以直接提出前端修改任务,也可以明确写出:
```text
使用 $oil-frontend 检查并修改这个前端模块。
```
## 不包含的内容
- 不规定具体框架、状态库、CSS 方案或固定目录模板。
- 不处理纯构建、部署、依赖升级、安全和后端任务。
## License
[MIT](LICENSE)

View File

@ -0,0 +1,148 @@
---
name: oil-frontend
description: 用于实现、修改、重构或评审产品前端。当前任务涉及页面、组件、交互、表单、状态、数据流、Hook、类型、CSS、前端代码组织或共享实现时自动触发。触发后先阅读 SKILL.md 判断相关范围,只读取与当前任务直接相关的参考文件;如果改动与产品前端无关则停止使用。纯构建、部署、依赖升级、安全、后端任务,以及只解释前端概念而不处理项目实现的请求,不触发。
---
# Oil Frontend
先识别用户任务、业务对象和数据来源,再删除无效内容,建立正确的信息、状态、代码归属和共享实现。
## 始终遵守
- 从真实用户任务、业务对象和完成结果出发;可见内容只保留能够帮助识别、比较、判断、操作或理解结果的信息。
- 一个用户意图只执行一次,动作必须产生真实结果;数据、操作、忙碌和提交边界保持一致,失败时保留当前对象、位置和已输入内容。
- 常见任务沿用用户已有认知;资源浏览默认展示,编辑必须明确触发,表单只收集当前任务必需且归当前对象所有的数据。
- 图标、强调方式和固定尺寸都必须表达稳定含义;不使用通用 AI 装饰、无意义强调边或只适配当前实例的尺寸制造层级。
- 同一业务数据和同一含义只保留一个权威来源;优先修复数据流、父布局和共享实现,不在页面使用位置反复打补丁。
- 按业务归属组织组件、Hook、函数、类型、样式和测试单模块代码就近放置只有稳定跨模块复用时才进入共享层。
- 遇到复杂逻辑,先检查项目已有能力和成熟库;已有依赖不合适时,可以引入维护良好、与项目兼容的新库,不手写已有成熟方案覆盖的核心能力。简单逻辑直接实现,不为少量代码引入新依赖。
- 项目历史不是正确性的证明错误模式应被替换相关使用位置完成迁移后删除旧代码、fallback、legacy 逻辑和失效状态。
## 参考文件读取顺序
1. 触发后先只阅读本文件,明确任务、对象和改动范围,不预先读取参考文件。
2. 如果任务不涉及用户可见界面、前端状态与数据流、组件实现或前端代码组织,停止使用本 Skill。
3. 简单局部改动默认只读取一个主要规则;只有任务还需要另一个独立判断时,才读取第二个规则。
4. 不因关键词出现、文件内链接或“保险起见”继续读取规则。一个任务看似命中多行时,先选择真正负责当前决定的那一行。
| 当前任务 | 主要规则 | 仅在这些情况补充 |
| --- | --- | --- |
| 模块边界、组件、Hook、函数、类型、CSS 或共享实现 | [组件与代码组织](references/component-contract.md) | 需要新增检查时读 [自动化](references/automation-contract.md) |
| 新增或改变文案、动作含义、图标、点击反馈或视觉强调 | [信息与动作](references/information-and-action-contract.md) | 涉及对象身份、图片或选择器时读 [资源识别](references/resource-recognition-contract.md) |
| 列表、卡片、详情、表格或批量操作 | [集合与详情](references/collection-and-detail-contract.md) | 涉及资源身份时读 [资源识别](references/resource-recognition-contract.md);涉及编辑时读 [交互与编辑](references/interaction-and-editing-contract.md) |
| 表单、选择、编辑或多步工作流 | [交互与编辑](references/interaction-and-editing-contract.md) | 涉及保存范围和流程连续性时读 [数据与操作范围](references/scope-and-state-integrity-contract.md) |
| 查询、请求、保存、数据范围或异步状态 | [数据与操作范围](references/scope-and-state-integrity-contract.md)、[状态与加载](references/state-and-loading-contract.md) | 涉及共享数据源或 Hook 时读 [组件与代码组织](references/component-contract.md) |
| 改变页面尺寸、分栏、滚动、弹窗结构或响应式行为 | [视口与弹窗](references/viewport-and-dialog-contract.md) | 涉及下拉、菜单、提示等依附触发器的浮层时读 [弹层](references/overlay-contract.md) |
以下情况不触发额外读取:
- 只移动现有控件,且不改变文案、动作含义或反馈时,不读取信息与动作规则。
- 只调整普通父子容器归属,且不改变尺寸、滚动、弹窗或响应式行为时,不读取视口与弹窗规则。
- 参考文件中的链接只说明相关规则的位置,不表示必须继续读取。
## 术语速查
本文件和参考规则中的核心词汇,按这里的定义理解:
- **资源身份**:让用户认出"这是哪个对象"的最小信息组合——图片 + 名称 + 一个区分字段。例:成员列表显示"头像 + 姓名 + 部门",而不是"uuid + 类型标签"。
- **伪操作**:看似可用、实际不产生真实结果的控件。例:点"保存"只改了本地 state、刷新即丢失删除按钮永久 disabled 占位。
- **单个组件的视觉补丁**:在页面使用共享组件的位置,只给这一个组件补样式。例:`<Dialog className="h-[640px]">``!important` 覆盖、页面专属选择器改组件内部。正确做法是修共享组件本身,或新增按用途命名的组件变体。
- **按用途命名的组件变体variant**:用“为什么不同”命名。例:`variant="destructive"``size="compact"` 合格;`variant="blue"``variant="userListPage"` 不合格。
- **主导动作**:当前页面、弹窗或操作区域中完成主要任务的那一个操作。同一区域最多一个高强调按钮。
- **提交边界**:一次修改何时真正生效——即时生效、自动保存、显式统一提交,或仅临时预览。
- **忙碌范围**:请求进行中需要防止重复操作的最小区域。单项请求只锁定该项,不用全页遮罩。
- **已提交查询快照**:由同一次响应共同确定的查询条件、列表、结果总数和分页信息。新查询完成前,旧快照仍属于旧条件。
- **同类批量任务**:对一批同类对象重复填写相同字段的任务,如批量排期、批量改价。
- **可编辑工作表**:为同类批量任务让多行持续处于编辑态的表格。与之相对的是资源列表:默认展示,编辑必须明确触发。
## 决策顺序
改动前依次回答。
任务与对象:
1. 用户当前要完成什么任务,什么结果表示完成?
2. 页面管理哪个核心对象,字段分别归谁所有?
3. 当前是浏览、比较、选择还是编辑,是否沿用用户熟悉的结构和术语?
数据与范围:
4. 数据来自完整集合、当前可见集合还是搜索结果?
5. 操作、忙碌状态和提交边界分别影响什么范围;远程查询条件与当前列表是否已经属于同一次已提交结果?
6. 用户靠哪些信息区分相邻对象?
7. 能否删除文字、步骤、确认、重复输入或系统已经知道的字段?
8. 哪些信息属于集合,哪些只属于详情?
结构与状态:
9. 当前页面、弹窗或操作区域的主导动作是什么?
10. 首屏、滚动容器和弹层边界分别由谁负责?
11. loading、empty、filtered-empty、queued、processing、error、ready 如何互斥?
落点:
12. 是否已有正确归属的模块、组件、Hook、函数、类型、统一设计变量或样式最终应修改哪个数据源、父布局或共享实现
无法明确回答时,先停止添加界面元素:向用户提出最关键的 12 个问题;无法提问时按最小可验证范围实施,并在输出中声明所做的假设。
## 执行流程
### 1. 还原事实
- 搜索项目已有的模块、组件、Hook、函数、类型、统一设计变量和样式确认相同含义是否已经存在正确实现。
- 找出所有使用共享组件的页面和组件,以及相同数据的其他入口。
- 评审请求只给证据与建议;用户要求修改时才实施。
### 2. 明确范围
- 明确核心对象、字段所有者、数据集合、操作范围、忙碌范围和提交边界。
- 区分页面结构问题、组件默认行为、页面使用方式错误和数据流错误。
### 3. 先删除
- 删除不影响判断的内容、重复状态、重复入口、重复确认和只针对单个组件的视觉补丁。
- 删除没有真实状态变化或不能真正保存数据的伪操作。
- 删除已经被新实现替代的旧组件、旧函数、旧类型、旧状态、fallback、legacy 逻辑、旧样式和失效引用。
### 4. 选择结构
- 先检查项目中同类任务页面和共享容器组件的既定用法;只有既有模式符合本规范时才沿用,否则按真实任务重新选择结构。
- 根据浏览、比较、选择、批量配置或深度编辑任务,选择列表、表格、工作表、选择器、弹窗或完整工作区。
- 让列表负责识别和比较,让详情负责完整内容,让编辑器负责修改。
### 5. 修复真正出错的位置
- 优先修复数据范围、操作范围、父布局、共享组件默认行为和含义稳定的组件变体。
- 重复出现的资源身份、菜单、弹层、加载、弹窗和操作栏使用共享组件。
- 只有职责、输入输出和行为稳定重复时才抽象;不要因为局部结构相似就复制组件,也不要用大量页面开关制造万能组件。
- 既有共享组件、函数、样式或数据流本身错误时,在授权范围内直接修复或替换真正出错的共享实现,并处理所有受影响的使用位置;不要为了兼容历史继续新增错误实现。
- 无法在当前范围内全部改完时,停止扩大旧模式,明确报告还剩哪些旧使用位置以及这次改到哪里,不得声称已经统一。
- 修复可重复检测的问题时,同步补齐或优化项目内的 lint、测试或检查规则见 [automation-contract.md](references/automation-contract.md));小改动不为此前置搭建自动化。
- 不修改无关区域。
### 6. 验证
- 运行项目现有且与改动相关的类型检查、Lint、测试或构建。
- 简单局部改动只检查修改位置、直接行为和最近的使用位置,不展开完整状态矩阵。
- 改动涉及共享组件、数据范围、异步状态、表单流程、滚动、响应式或多个页面时,再检查受影响的状态、数据范围、代表性视口和全部使用位置。
- 只报告已验证项、未验证项和阻断原因。
## 独立自检
仅当前端评审涉及多个页面、所有使用共享组件的位置、多种视口或状态,或大范围规则调整时,才派发无历史上下文的独立自检。单页面、单组件、单截图和局部差异由主 Agent 直接检查。
独立自检只接收检查对象、范围和 `oil-frontend`,不接收对话历史、既有结论、问题猜测、预期答案或修复方案。
## 输出要求
先给结论,再给证据。只输出:
1. 具体问题;
2. 应删除的内容;
3. 正确的信息、动作和空间结构;
4. 应修改的模块、共享组件或数据流;
5. 已验证和未验证项。
禁止使用"提升体验""更现代""更直观"等不能指导实现的描述。
除非用户明确要求,或问题直接阻断可见的主要流程,否则不主动输出键盘操作或无障碍检查清单。

View File

@ -0,0 +1,74 @@
# 项目检查与规则维护
> 只有任务需要新增或调整 Lint、测试、CI 或项目检查规则时读取;只读评审和普通局部实现不读。
## 原则
Skill 不携带通用执行脚本。检查规则、测试和 CI 配置必须根据当前项目的框架、组件体系和工具链生成,并保存在项目仓库中。
只读评审不得执行 Onboarding、安装依赖或修改配置。用户授权实现时才允许接入或调整自动化。
## 首次接入
首次在项目中实施 `oil-frontend` 时,先检查:
- 语言、前端框架和包管理器;
- 已有 lint、CSS 检查、组件测试和 CI
- 共享组件、样式和页面目录;
- 是否已存在前端规则、命令或回归测试。
优先扩展已有工具:
| 问题类型 | 项目原生落点 |
| --- | --- |
| JSX、模板和导入结构 | ESLint 或当前模板 linter |
| CSS 归属和值约束 | Stylelint没有时才新增项目内轻量检查 |
| 组件默认行为 | 组件实现与组件测试 |
| 数据集合、忙碌范围和提交边界 | 组件测试、集成测试或状态模型测试 |
| 信息价值和层级判断 | Agent Review不程序化 |
首次接入只添加当前技术栈能够稳定判断的最小规则集。已有存量违规先报告和分批修复,不通过大量例外让规则失效,也不直接把噪声规则接入 CI。
项目已经定义浏览组件和编辑容器后,可以优先检查两类稳定问题:资源浏览组件内直接平铺表单控件,以及使用 `readOnly` / `disabled` 输入框展示普通信息。可编辑工作表必须由项目声明的工作表组件或含义稳定的标记承载;不要用逐行忽略注释放行。
项目已经提供共享 Button、EmptyState 和加载组件后可以检查使用按钮的位置手工插入加载动画、Loading 嵌套在 EmptyState以及页面绕过共享组件声明独立加载动画。只检查项目能够明确识别的组件和容器不按类名包含 `loading` 做宽泛拦截。
项目已经定义共享弹层、资源选择器和分页查询后,可以检查:页面自行实现浮层定位、选择器直接复用浏览分页结果、单项操作复用全局 busy以及筛选变化后仍保留不可见批量选择。优先用组件或状态测试保护行为不根据组件名和变量名做猜测。
## 持续演进
后续每次发现真实产品前端问题时:
1. 修复共享组件、父布局或数据流中真正出错的位置;
2. 判断该问题能否由源码结构、组件行为或页面几何稳定识别;
3. 搜索同类使用位置和历史问题,确认不是单个页面偶然情况;
4. 选择项目已有的 ESLint、CSS 检查或组件测试;
5. 增加一个修复前失败的回归样例,并保留至少一个合法样例;
6. 扫描存量代码;规则干净后再设为 error存在合理例外时收窄规则
7. 将检查接入项目现有 lint、test 和 CI不建立第二套重复入口。
发现误报、漏报或迫使使用组件的页面增加例外时,立即优化或降级规则,不能为了保留规则而扭曲组件设计。
## 规则门槛
只有同时满足以下条件才新增或加强规则:
- 输入和失败条件可以明确描述;
- 对多个页面、组件或状态使用同一判断;
- 不依赖页面名称、产品文案或一次截图;
- 不使用固定列数、固定行高或固定文案长度代替 UX 判断;
- 不全面禁止 CSS 数值、宽度或高度;只拦截项目能够确认属于实例补丁、绕过统一设计变量或破坏共享布局规则的写法;
- 能提供命中样例和合法样例;
- 误报不会迫使使用组件的页面增加局部样式或忽略注释。
能由共享组件默认行为彻底消除的问题,优先修组件;只有需要防止使用组件的页面绕过本规范时才补规则。
## 完成条件
首次接入或规则更新完成后,报告:
- 使用了项目中的哪个原生工具;
- 新增或修改了哪些规则及其保护的回归;
- 扫描了哪些范围;
- 存量违规和未覆盖情况;
- 哪些检查已进入 CI哪些仍为 warning。

View File

@ -0,0 +1,93 @@
# 列表、详情与表格规则
> 当任务涉及列表、卡片、详情、表格或批量操作时读取;字段编辑和数据请求由对应规则负责。
## 列表与详情
列表只回答:
- 有哪些资源;
- 它们有什么决策相关的差异;
- 用户应该打开哪一个。
列表项只保留:
- 资源身份;
- 一个影响判断的状态;
- 完成当前比较所需的最小字段集合;
- 主体点击目标;
- “更多”入口。
详情承载:
- 完整媒体预览;
- 分析、证据和错误原因;
- 关联资源;
- 编辑、保存和确认流程;
- 历史与低频设置。
禁止:
- 把完整分析摘要放进列表;
- 卡片主体和 `View` 按钮执行同一动作;
- 在卡片页脚平铺重命名、刷新和删除;
- 列表媒体暴露完整播放控件。
## 卡片列表还是展示表格
按当前任务和对象内容选择,不按页面形式偏好选择:
- 用户需要横向比较同一字段在多个对象间的差异(数值、状态、日期、价格)时,表格的比较效率更高。
- 用户主要通过图片和内容差异识别、挑选对象,字段不适合横向比较时,使用卡片或列表。
- 每行主要内容是长文、完整媒体或复杂预览时,使用卡片或列表,不压缩进表格行。
- 单对象深度创作使用详情页或完整工作区,不使用集合表格。
- 行内操作多于比较信息时,使用列表或卡片承载身份和入口,把完整操作移入详情。
- 两者都可以且既有结构符合本规范时,沿用项目中同类集合页面的结构;既有结构本身导致识别、动作或空间问题时,修复或替换该模式并修改相关页面,不再复制错误。
- 同一项目中同一类对象只保留一种主要集合形态;卡片与表格视图切换只在用户确实需要两种任务模式时提供。
## 表格信息
一行对应一个真实业务对象。第一个稳定内容列使用统一资源身份组件;复选框、序号等工具列可以位于其前。其他列必须回答:
- 与其他对象有什么决策相关差异;
- 当前处于什么状态;
- 哪个字段需要直接修改;
- 当前可执行什么操作。
没有明确答案的列删除。不要把详情字段逐列搬进表格。
## 单元格结构
- 一个单元格只承担一种主要职责:识别、比较、状态、编辑或操作。
- 同一行的可编辑单元格使用相同高度、垂直结构和对齐基线。
- 单元格使用稳定、可快速横向扫描的主次层级;新增层级不再帮助比较时移入单行编辑器或详情。
- 单元格出现多个独立操作或完整预览时,移入单行编辑器。
- 禁止在单元格内拼装“预览 + 状态 + 数量 + 操作”的迷你卡片。
- 影响多个字段的动作属于行级操作或编辑器,不得附着在某个字段列中。
- 空资源没有可识别图片时,不保留大缩略图槽或装饰性占位。
## 表格操作
- 只有存在真实批量动作时才显示多选框。
- 编辑器修改原行对象,返回后状态仍在原行。
- 低频管理操作进入行末“更多”。
- 行点击打开详情时,单元格控件不得同时触发行点击。
- 排序和筛选只用于确实需要比较或缩小范围的字段。
- 状态只在固定列中表达一次。
- 行级动作进入固定操作列,不在字段内容下方形成第二排按钮。
- 展示表格列数超出目标视口的比较能力时,删除低价值列或移入详情。
- 可编辑工作表按任务阶段组织相邻列,并固定身份列与操作列;横向滚动遵循 [视口与弹窗规则](viewport-and-dialog-contract.md#滚动由谁负责)。
- 集合内媒体只提供轻量预览;播放对象离开当前筛选或分页时停止播放,除非页面提供始终可见的播放控制。
对象跨阶段的更新与派生规则遵循 [数据与操作范围规则](scope-and-state-integrity-contract.md#流程连续性)。
## 检查
- 不打开详情能否选出目标资源?
- 列表是否泄漏详情内容?
- 是否存在重复查看入口?
- 每一列是否影响比较、状态、编辑或操作?
- 是否为了表格形式而保留无用列?
- 同一行是否出现不同的单元格结构和操作基线?
- 是否存在迷你卡片、第二排控件或不参与判断的辅助文字?
- 是否存在两套重复对象或状态?

View File

@ -0,0 +1,112 @@
# 组件、代码组织与视觉系统规则
> 当任务涉及模块、组件、Hook、函数、类型、数据来源、样式归属或旧实现清理时读取。
## 决策顺序
遇到视觉或交互问题时依次检查:
1. 项目是否已有相同含义且符合本规范的组件、函数、统一设计变量或样式;
2. 页面是否用了错误组件;
3. 父级布局是否给了错误尺寸、对齐或定位;
4. 组件默认样式或状态逻辑是否错误;
5. 现有组件变体是否足够;
6. 是否存在稳定的重复职责,足以新增共享实现;
7. 所有使用位置和旧实现是否需要同步处理。
未完成搜索,也未检查组件选择、父布局和默认行为前,不新增组件、函数、样式或组件变体。
## 系统分工
- 统一设计变量负责跨产品复用的颜色、字号、间距、圆角、阴影和动效含义。
- 基础与共享组件负责自身视觉、交互反馈和完整状态,不由页面逐项重画。
- 业务组件负责组合稳定的业务对象和交互,不把业务差异塞进基础组件。
- 格式化、校验和数据转换等逻辑使用输入相同就返回相同结果的函数;请求、保存和导航由负责业务操作的代码处理,不藏进只负责展示的组件。
- 页面负责取得当前数据和路由信息、安排区域并组合组件,不复制组件内部逻辑。
同一含义只保留一个实现来源。结构相似不等于职责相同;只有职责、输入输出和行为都稳定一致时才共享。
## 模块与代码组织
- 按业务对象或功能模块组织代码,不按文件类型把整个项目拆散。
- 只服务一个模块的组件、Hook、函数、类型、样式和测试放在该模块附近多个模块稳定复用后才移入共享层。
- Hook 负责状态和副作用组合;无副作用的格式化、校验和转换使用普通函数;请求和持久化由数据访问或业务操作代码负责。
- 业务类型由拥有该数据的模块定义,组件输入类型放在组件附近,接口请求与响应类型放在接口层;相同含义不重复声明。
- 共享层不得依赖具体业务模块;跨模块使用公开入口,不直接引用对方内部文件。
- 既有目录混乱时,不继续复制错误模式。为当前改动确定正确归属,迁移相关代码、更新引用并删除旧文件;无法一次完成时明确剩余范围。
## 数据来源
- 同一业务数据只保留一个权威来源;服务端结果、缓存、全局状态、表单草稿和派生视图各自只承担明确职责,不维护能够独立修改的重复副本。
- 能从权威来源计算的值直接派生。只有未提交编辑确实需要时才保留本地草稿,并明确初始化、提交和丢弃边界。
## 既有实现与历史包袱
- 既有实现只有在职责、行为、数据和样式归属正确时才值得复用;存在时间长、使用页面多或位于共享目录,都不能证明它是正确模式。
- 既有实现持续产生局部补丁、重复状态、影响无关页面的样式、业务开关或不一致行为时,停止在新位置继续使用它。
- 在授权范围内优先修复或替换真正出错的共享实现,处理所有受影响的使用位置后删除旧实现;为纠正问题,可以有计划地改变旧接口、结构或样式组织。
- 新实现已经接管且使用位置完成迁移后删除旧分支、fallback、legacy 适配层、旧类型、旧状态和失效开关。只有仍有真实兼容对象时才暂时保留,并明确删除条件。
- 无法在当前范围内全部改完时,不得继续复制错误模式;明确记录还剩哪些旧使用位置、这次改到哪里以及后续如何清理,不靠长期保留两套实现来掩盖问题。
## 允许
- 在共享组件内部维护视觉样式。
- 使用含义明确的组件属性,例如 `variant``size``state``loading``destructive`
- 由布局容器控制网格、排列、区域间距和响应式结构。
- 使用正式组件属性或 `data-state` 表达状态。
- 为重复交互建立共享组件。
- 复用已有的格式化、校验和数据转换函数。
- 弹窗内部结构由共享组件和按用途命名的组件变体负责;只有任务实际改变弹窗尺寸、滚动或结构时,才读取 [视口与弹窗规则](viewport-and-dialog-contract.md#弹窗结构)。
- 在交互组件内部统一维护 pointer、hover、active 和 disabled 状态。
## 禁止
- 在使用组件的位置直接写只服务于当前页面的视觉样式。
- 为共享组件传入视觉型 `className` 后覆盖颜色、尺寸、圆角、阴影或内部布局。
- `!important` 修补组件实例。
- 页面专属选择器侵入共享组件内部。
- 使用任意数值绕过统一设计变量。
- 用页面名、业务对象名或视觉结果命名组件变体。
- 为一个实例增加没有稳定含义的组件变体。
- 复制组件后只改一点样式。
- 复制函数后改名,或在多个组件中分别维护相同转换和校验。
- 用大量页面名称、业务布尔开关和条件分支制造万能组件。
- 把请求、保存或导航藏进纯展示组件。
- 在 CSS 修复前不检查页面结构、父级布局和组件调用。
- 在使用弹窗的页面重排共享弹窗的标题区、内容区和操作区,或重新定义其高度和滚动方式。
- 在使用共享组件的页面为单个组件补固定宽高。
- 让业务组件样式无边界地累积在一个全局样式文件中。
## 视觉一致性
- 新页面沿用项目中符合本规范的统一设计变量、组件、布局模式和状态表达,不建立页面专属的设计语言。
- 一致性同时包括颜色、字号、间距、信息密度、动作层级、状态位置、图标含义和交互反馈,不能只统一其中一项。
- 业务差异通过内容、组合和稳定含义表达;不要通过任意视觉值制造差异。
## 样式归属与清理
- 每段样式必须归属于基础规则、共享组件或明确的业务模块;页面只负责区域布局,不接管组件内部视觉。
- 项目已有的样式组织方式符合归属边界时才沿用;如果业务样式无边界集中、互相覆盖或无法随组件删除,就停止扩大全局文件,重新建立组件或业务模块的样式归属。
- 删除或改名页面结构、样式类、状态或组件变体时,同步删除不再生效的选择器、状态样式、响应式规则、引用和样式文件。
- 新实现能够运行不代表改动完成;旧组件、旧函数和旧样式已经清理,所有受影响的使用位置已经检查,才算完成。
## 新增组件变体的门槛
同时满足以下条件才新增:
- 差异表达稳定含义,不是页面身份;
- 存在多个使用位置,或明确属于组件公共状态;
- 属性名称能说明使用原因,而非视觉结果;
- 默认行为仍适用于多数场景;
- 能用组件级验证覆盖。
组件变体应说明“为什么存在差异”,不能只说明颜色、数值、页面或业务对象。
## 尺寸由谁负责
- 页面布局容器负责区域分配,共享组件负责自身稳定尺寸。
- 使用共享组件的页面不得为单个组件补固定宽高;只有任务实际改变固定尺寸、滚动或视口边界时,才读取 [视口与弹窗规则](viewport-and-dialog-contract.md#内容驱动尺寸)。
## 修改后的审查
修改共享组件、函数或样式后,搜索全部使用位置,检查默认方式、受影响的使用场景和旧实现,并报告未验证项。

View File

@ -0,0 +1,126 @@
# 信息与动作规则
> 当任务涉及可见文案、动作层级、图标、点击反馈或视觉强调时读取;数据范围和空间布局由对应规则负责。
## 可见信息
每段文字和每个视觉元素必须至少完成一项职责:
- 标识当前对象;
- 区分相邻对象;
- 表达当前状态;
- 说明无法从结构推断的规则、限制或风险;
- 说明可执行动作;
- 反馈动作结果。
不承担这些职责就删除。
当对象、操作顺序、控件和反馈已经通过界面结构清楚表达时,不再用说明文案重复解释流程。添加帮助文字前,先检查能否通过更准确的标题、按钮文案、布局、默认值或状态反馈直接解决;不能用长说明掩盖结构和动作关系不清。
只有以下信息不能从当前界面可靠推断时才补充说明:
- 非共识的业务规则;
- 系统限制或数据作用范围;
- 容易造成真实损失的误操作风险;
- 危险或不可逆动作的具体后果。
必须删除:
- 重复页面标题、重复状态和重复入口;
- 重述按钮含义的段落;
- 解释显而易见布局的文字;
- 不影响下一步动作、作用范围或结果判断的状态复述,如 `3 selected``20 items``Filter applied`
- 仅用于填空的说明、徽章和图标;
- 原始数据库 ID、内部枚举、存储路径和系统时间戳等实现信息除非它们直接用于当前判断、搜索、复制或排障。
空状态只说明为空的原因,并提供一个恢复动作。同一创建或恢复意图不能同时出现在页面 Header 和空状态中。
即使实现信息确有用途,也只能作为辅助信息或按需复制项,不得取代用户能够识别的名称、图片和区分字段。
## 容器强调边
左侧或顶部的彩色强调边、色带和装饰性轨道属于强调边卡片accent-border card视觉语言源自 callout、引用块和状态提示。它会主动争夺注意力不应成为普通卡片、列表项或内容分组的默认装饰。
- 只有强调边持续表达可复用的状态、类别、选择或告警含义时才使用。
- 分类文字、图标或状态已经表达同一信息时,删除重复的强调边。
- 不为制造层次、填补空白或让相邻卡片“看起来不同”而给每项配置不同颜色的强调边。
- 普通集合优先使用对齐、留白、文字层级、轻量分隔线或背景差异建立结构。
- 项目确有符合本规范的稳定提示、引用、告警或选中模式时,由共享组件和按用途命名的组件变体统一维护;页面不得临时拼装彩色边线。
## 用户已有认知
- 常见的浏览、选择、编辑、保存、删除、返回和关闭任务使用用户已经理解的结构和动作含义。
- 同一对象、状态和动作在不同页面使用相同名称;不得用不同术语包装同一件事。
- 不改变共识图标和动作的惯常含义,也不为普通任务创造自定义手势或新操作模型。
- 只有标准模式无法表达真实任务时才新增交互模式,并明确显示它的对象、动作和结果。
## 动作层级
| 层级 | 用途 | 呈现 |
| --- | --- | --- |
| 主操作 | 完成当前页面、弹窗或操作区域的主要任务 | 一个高强调文字按钮 |
| 次级操作 | 高频但非主要 | 低强调文字按钮 |
| 管理操作 | 重命名、重新处理、复制、可撤销删除 | “更多”菜单 |
| 危险操作 | 永久删除或其他不可恢复、高损失操作 | 菜单分隔 + 确认 |
| 导航操作 | 返回、关闭、翻页 | 上下文明确时可用共识图标 |
同一页面、弹窗或操作区域出现两个高强调按钮时,重新判断主任务。批量工作台可以同时提供不同任务动作,但只能有一个与当前阶段直接相关的主导动作。
## 上下文操作与按需呈现
不是所有操作都需要始终平铺显示。根据当前对象和用户正在进行的任务,只显示此刻需要的操作:
- 主操作、关键状态和完成当前任务必须先发现的入口保持可见。
- 卡片、列表项或表格行中的次级操作,可以在 hover、聚焦或选中当前项后显示。
- 重命名、复制、重新处理等低频管理操作优先放入“更多”菜单,不在每一项中长期平铺。
- 操作出现前预留稳定位置,不挤压文字,也不让列表或卡片发生布局跳动。
- 触屏设备没有 hover 时,通过点击选中当前项,或使用始终可见的“更多”入口提供相同操作。
- 不隐藏用户必须先发现,才能理解当前状态或完成主要任务的操作。
## 按钮与图标
- 使用能够说明结果的“动作 + 对象”文案,避免只有“处理”“管理”“继续”等无法判断结果的词。
- 图标只有在能加快识别,并明确表达对象、动作、状态或结果时才使用;移除后不影响理解和扫描的图标应删除,不为标题、标签、菜单项或卡片机械配图标。
- 同一图标保持相同含义图标与文字同时出现时表达同一件事。非共识图标必须显示文字tooltip 不能代替标签;纯图标只用于上下文明确的共识动作。
- AI 只是实现方式时,图标表达摘要、翻译、生成图片、转写、编辑等实际动作或结果,不额外叠加通用 AI 标记。
- 星星、闪光、机器人、脑形和魔法棒不作为生成、增强、助手等功能的默认图标;只有表达收藏、真实机器人或 Agent 对象等本来含义,或项目已有不违背本规范的稳定含义时才使用。
- AI 身份本身影响用户判断时优先显示明确名称、模型、Logo 或真实 Agent 身份不用抽象的“AI 图标”代替对象。
- `Check` 只表示选中、确认、保存或完成,不表示查看;`Refresh` 只表示刷新、重试或重新分析,对象不明确时显示文字。
- 状态不得做成看似可点击的按钮。
## 点击区域与鼠标反馈
- 所有可点击按钮、链接、卡片、表格行、菜单项、选择器选项、分页项和上传区域必须显示 `cursor: pointer`
- `cursor: pointer` 必须覆盖完整点击区域,不只覆盖图标或文字。
- 点击区域必须有可见 hover 反馈,例如背景、边框或文字颜色变化。
- 按下状态必须与 hover 有区别。
- 禁用控件不是可点击区域,使用禁用视觉和 `cursor: not-allowed`
- 非交互卡片、标签、状态和装饰图标不得显示 pointer。
- 整张卡片可点击时,卡片根节点负责 pointer 和 hover不要让用户猜只有哪一小块能点。
- 卡片或表格行内存在独立控件时,各控件保持自己的点击范围,不触发外层点击。
pointer、hover、active 和 disabled 样式由共享组件负责,使用组件的页面不得逐个补充。
## “更多”菜单
- 菜单项显示文字。
- 点击外部关闭菜单。
- 删除与普通操作分隔。
- 当前状态不允许的操作直接隐藏;不要留下无法解释的灰色图标。
- 菜单触发器与菜单项都显示 `cursor: pointer`
## 检查
- 删除某段文字后,用户是否仍能正确判断?
- 删除流程说明后,用户是否仍能通过对象、顺序、控件和反馈完成任务?如果不能,问题来自真实规则还是界面结构不清?
- 图标是否要求用户猜含义?
- 每个图标是否有明确职责,移除无意义图标后是否仍能正常理解和扫描?
- AI 功能的图标是否表达真实动作或对象,还是只使用了星星、机器人、脑形等通用装饰?
- 所有可点击区域是否显示 pointer 和 hover
- pointer 是否误加到不可点击内容?
- 低频操作是否仍平铺在主界面?
- 次级操作是否只在相关对象进入 hover、聚焦或选中状态后出现触屏设备是否有同等入口
- 按需出现的操作是否造成文字位移或布局跳动?
- 是否展示了不能帮助识别、判断或操作的实现信息?
- 容器左侧或顶部的强调边是否表达稳定含义,还是只在重复标签或装饰页面?
- 常见任务是否要求用户重新学习术语或操作方式?

View File

@ -0,0 +1,110 @@
# 展示、编辑与表单规则
> 当任务涉及展示与编辑切换、表单、行内编辑、批量工作表或选择流程时读取;纯浏览结构由列表与详情规则负责。
## 展示态与编辑态
资源列表和只读详情使用文字、资源身份、图片和状态组件。表单控件、上传区及保存操作只在用户明确开始修改、选择,或进入以批量配置为核心的工作表后出现。
禁止:
- 用只读或禁用的表单控件展示普通信息;
- 让资源列表、卡片和只读详情默认处于编辑态;
- 为每个字段长期显示选择器、保存按钮或第二排操作;
- 同时显示字段值和负责修改该值的完整控件;
- 把多个字段的编辑器塞进资源列表组件。
## 行内编辑门槛
普通资源列表只有同时满足以下条件才使用行内编辑:
- 高频修改;
- 只影响一个字段;
- 输入短且验证简单;
- 不依赖其他字段;
- 结果可立即理解;
- 失败或撤销不影响其他步骤。
不满足任一条件时,从行末进入单行编辑器、工作流弹窗或详情页。一次只让正在编辑的区域进入编辑态。
## 表单克制
表单是完成一次数据提交的输入结构,不是为了显得完整而增加的工作流。
- 只收集完成当前任务必需且无法可靠获得的数据。
- 系统已经知道、上一步已经提供、能够继承或可靠推导的信息直接带入;只有字段属于当前任务对象且当前表单负责修改时才允许编辑,否则展示来源并使用负责维护这份数据的页面或共享编辑器修改。
- 相关字段使用一个清楚的提交边界;禁止逐字段编辑和逐字段保存。
- 简单任务不拆成多步骤表单;高级设置仅在影响当前任务且用户主动需要时展开。
- 不默认增加自动保存、草稿、重置、预览、步骤条、字符计数或第二套确认。只有任务状态、错误代价或字段依赖明确需要时才增加。
- 优先使用输入约束、候选范围和合理默认值防止无效输入,不用更多操作步骤代替防错。
- 错误在可修正的位置说明,提交失败保留已输入内容,不清空表单或要求重新开始。
表单复杂度只由字段依赖、错误代价和提交边界决定,不由已有数据库字段数量决定。
## 可编辑工作表
当前任务本身是连续配置多个同类任务时,可以让多行持续处于编辑态,但必须同时满足:
- 行代表同一种任务对象,字段和保存语义一致;
- 用户需要跨行比较并连续填写相同字段;
- 修改即时生效或拥有统一提交边界,不要求每行重复保存;
- 单元格只放当前阶段的高频字段,复杂依赖、完整预览和高级设置进入单行编辑器;
- 控件高度、主次信息、状态位置和操作位置在所有行保持一致;
- 横向滚动只发生在表格容器内,关键身份列和操作列保持可见。
不要因为页面里出现多个输入框就判定交互错误。先判断它是资源列表,还是用户明确进入的批量工作台。
## 组件分工
| 当前任务 | 使用组件 |
| --- | --- |
| 识别和比较资源 | 资源身份、图片、文字、状态 |
| 选择资源 | 展示当前值的触发器 + 按需打开的资源选择器 |
| 修改单个简单字段 | 明确触发的局部编辑器 |
| 修改多个相关字段 | 表单弹窗、单行编辑器或详情编辑模式 |
| 浏览详情 | 展示组件;提供一个明确的“编辑”入口 |
资源列表中的选择器关闭后恢复为资源身份展示;可编辑工作表的选择触发器可以持续可见,但展开选项仍按需出现。
## 数据归属
先确定字段属于哪个业务对象,再决定编辑入口:
- 负责维护这份数据的页面或共享编辑器负责修改完整数据;
- 使用这份数据的页面默认展示来源对象和当前值;
- 使用这份数据的页面可以选择本次任务需要的子集,但不得复制来源对象的完整编辑表单;
- 需要修改来源数据时,打开同一个共享编辑器或前往负责维护这份数据的页面;
- 返回原页面后保留当前位置、任务数据和最新值。
禁止在多个页面分别维护同一字段的编辑逻辑、校验和保存入口。
## 选择与候选
- 存在明确默认选择时,先按 [资源识别规则](resource-recognition-contract.md#已选结果) 展示当前选择,通过“更改选择”按需打开选择器;展开候选后隐藏只读摘要,禁止同时重复显示同一批对象。
- 只有“比较并选择”是当前主要任务时,才默认展开选项列表。
- 候选集合默认用于识别、比较和选择,不把每个候选渲染成完整表单。
- 选择候选与编辑候选是两个状态;一次只打开一个候选编辑器。
- 批量接受无需修改的候选,不强迫用户逐个进入编辑。
## 删除重复操作
- 选择结果已经即时生效时,不再要求额外保存。
- 存在显式保存时,修改只提交一次;不要再增加同义确认。
- 可撤销的普通操作不增加确认弹窗。
- 危险或不可恢复操作只确认一次。
不得为同一次决定增加多个同义确认步骤。只有动作分别改变不同业务状态时才能同时存在。
跨步骤数据带入、返回位置和原对象更新统一遵循 [数据与操作范围规则](scope-and-state-integrity-contract.md#流程连续性)。
## 审查
- 用户尚未表达修改意图时,为什么会看到表单控件?
- 这个控件是在展示值,还是确实允许当前步骤修改值?
- 能否用一次点击替代“选择 → 确认 → 保存”?
- 同一动作是否同时存在于卡片、单元格、页脚和弹窗?
- 是否展示或要求填写了系统已经知道、能够继承或可靠推导的信息?
- 是否因为“可能有用”增加了字段、步骤、预览、保存或确认?
- 表单复杂度是否来自真实字段依赖和错误代价,而不是数据库字段数量?
- 普通列表的行内编辑是否满足门槛?批量工作表是否满足本文件列出的条件?
- 编辑结束后是否仍能快速跨行比较?

View File

@ -0,0 +1,42 @@
# 下拉菜单与浮层规则
> 当任务涉及下拉选择、菜单、日期面板、提示、上下文菜单或其他依附触发器的浮层时读取;完整弹窗、抽屉和页面布局由视口与弹窗规则负责。
## 由谁负责
- 定位、碰撞检测、层级、尺寸边界和关闭行为由共享弹层组件负责。
- 使用弹层的页面只提供触发器、内容和使用场景,不传当前位置专用的偏移或宽高。
- 表格、卡片和滚动容器不负责约束浮层边界。
## 定位与视口
- 浮层优先贴近触发器,并在空间不足时翻转或移动。
- 始终保留视口安全边距,不得让根页面产生水平滚动。
- 位于可能裁切内容的滚动容器内时,使用能够脱离该裁切边界的渲染层。
- 页面滚动、容器滚动和视口尺寸变化后重新计算位置。
- 触发器离开页面、被卸载或失去当前上下文时关闭浮层。
- 多个浮层同时存在时,使用共享层级体系,不在页面实例中临时提高层级。
## 尺寸
- 普通下拉默认与触发器保持明确宽度关系,并受当前视口最大可用宽度限制。
- 名称和辅助信息按资源身份规则截断,不能依靠内容固有宽度撑大浮层。
- 高度由内容决定;超过视口可用空间时只让浮层内容区滚动。
- 紧凑菜单按内容宽度,不吸收页面剩余空间。
- 内容超出普通下拉能够清楚承载的范围时,按 [视口与弹窗规则](viewport-and-dialog-contract.md#承载方式弹窗抽屉与完整页面) 选择弹窗或完整工作区,不继续扩大普通下拉。
## 交互边界
- 单选在完成选择后关闭;多选在显式完成或点击外部时关闭。
- 浮层内操作不得意外触发底层卡片、表格行或页面操作。
- 禁用项不显示可点击反馈。
- 状态提示和帮助说明不得遮挡主操作或阻止用户关闭浮层。
## 检查
- 触发器位于视口四周时,浮层是否仍完整可见?
- 浮层是否被表格、弹窗或滚动容器裁切?
- 长名称是否撑大浮层或根页面?
- 滚动和缩放后是否仍对齐当前触发器?
- 浮层关闭后是否留下遮罩、滚动锁或不可见点击层?
- 是否因内容复杂度过高而应该改用弹窗或完整工作区?

View File

@ -0,0 +1,88 @@
# 资源识别规则
> 当任务涉及图片、对象身份、资源选择器或相邻对象区分时读取;列表结构和编辑流程由对应规则负责。
## 上层模型
集合界面的信息流按以下顺序设计:
`识别对象 → 比较差异 → 判断状态 → 执行动作 → 查看详情`
不要从数据库字段或现有组件出发决定展示内容。先判断用户需要如何区分对象,再选择最小信息集合。
## 最小识别单元
按以下优先级组合资源身份:
1. **视觉身份**头像、封面、缩略图、Logo、产品图或媒体帧
2. **主名称**:用户实际用于称呼和搜索的名称;
3. **区分字段**:在同名或相似资源间最有辨识度的一个字段;
4. **有效状态**:会影响选择、判断或操作的状态。
能用图片和名称准确区分时,不再增加次级信息。只有在相邻对象仍可能混淆或状态会改变选择时,才继续增加信息。
禁止用以下内容充当主要身份:
- 原始数据库 ID
- 无法阅读的长文件名;
- 所有对象都相同的类型标签;
- 装饰性图标;
- 截断后彼此相同的文本;
- 只显示状态而不显示对象。
## 图片优先
资源存在有辨识度的图片时:
- 在列表、表格、选择器选项和已选结果中使用;
- 对同一资源使用一致裁切和比例;
- 使用真实缩略图,不用通用媒体图标代替;
- 加载失败时使用稳定的兜底图片,并保留名称;
- 不为没有识别价值的对象强行生成装饰图。
图片不能是唯一身份。始终保留可读名称。
## 选择器
选择器首先是资源识别器,不是字符串下拉框。
### 选项
每个选项使用:
- 图片或视觉身份;
- 主名称;
- 必要区分字段;
- 仅在影响可选性时显示状态。
不要只显示名称,除非名称在当前集合中天然唯一且清晰。
### 已选结果
收起后的触发器必须继续显示足够身份信息,让用户无需重新打开选择器就能确认选择:
- 保留图片;
- 保留主名称;
- 名称不足以区分时保留区分字段;
- 不只显示内部值、占位符或勾号。
### 搜索
- 搜索覆盖界面上用于识别的名称与区分字段。
- 结果高亮匹配信息,但不改变资源身份结构。
- 数据量较大时提供搜索;不要要求用户浏览长列表。
- 无结果时说明搜索条件未匹配,不把它误写成资源集合为空。
## 共享组件
建立统一资源身份组件。组件内部负责图片、兜底内容、主名称、区分字段和截断规则;使用组件的页面只传资源数据和使用场景,不传局部视觉样式。
## 审查问题
- 不打开详情,能否区分相邻资源?
- 移除某字段后是否仍能正确识别?
- 是否遗漏了已有且更有辨识度的图片?
- 图片是否真实参与识别?
- 是否展示了所有对象都相同的信息?
- 选择器收起后能否确认当前对象?
- 同一资源在不同位置是否保持相同身份结构?

View File

@ -0,0 +1,92 @@
# 数据与操作范围规则
> 当任务涉及数据集合、查询结果、操作范围、忙碌范围、保存结果或流程连续性时读取;视觉呈现由对应界面规则负责。
## 先明确范围
实现交互前明确:
| 范围 | 必须回答 |
| --- | --- |
| 对象 | 当前查看或修改哪个业务对象? |
| 数据 | 使用完整可选集合、当前可见集合还是搜索结果? |
| 操作 | 本次动作影响单项、选中项、当前集合还是全局? |
| 忙碌 | 哪个最小区域需要防止重复操作? |
| 提交 | 修改即时生效、自动保存、统一提交还是临时预览? |
| 结果 | 成功后更新原对象、导航到哪里、保留什么上下文? |
范围无法明确时先提问;无法提问时不猜测全局范围,只按最小可验证范围实施并声明假设。
## 数据集合完整性
- 浏览集合可以分页;资源选择器必须获得完整可选集合,或提供覆盖完整集合的服务端搜索。
- 禁止把浏览页当前分页结果直接当作工作流的全部可选资源。
- 已选资源暂时不在当前分页或筛选结果中时,仍要保留可识别的当前值。
- 区分 `empty`(资源集合本身为空)、`filtered-empty`(筛选或搜索无结果)和 `error`(数据加载失败);具体文案仍应说明是筛选还是搜索未匹配,并提供对应恢复动作。
- 筛选和搜索只改变当前视图,不得悄悄改变已保存的业务关系。
## 查询视图一致性
远程筛选、搜索、排序或分页触发集合变化时,区分用户刚发出的查询与当前已经展示的已提交查询快照。
- 列表、结果总数、分页范围和已提交查询必须来自同一次响应,并在同一更新边界内生效。
- 新查询返回前可以保留旧快照,但触发控件或集合容器必须明确表达 `refreshing`;不得把旧内容无标记地解释为新查询结果。
- 查询控件可以立即显示用户刚选择的条件,但必须同时显示 `refreshing`,直到对应结果提交;否则继续显示旧的已提交条件。
- 请求失败时保留旧快照和查询上下文,并就近显示失败;不得用 `empty` 或新查询的 `0` 覆盖仍然可用的旧结果。
- 用户连续改变条件时只提交最新查询的结果,过期响应不得覆盖新的查询上下文。
## 操作与忙碌范围
- 单项请求只锁定该项及其直接操作,不阻塞无关对象、页面或导航。
- 局部上传、保存、重试和删除不得复用无法区分对象的全局 busy。
- 批量操作默认只作用于当前可见选择;存在隐藏选择时,清除隐藏选择或明确显示数量和作用范围。
- 筛选变化后不得静默操作用户看不见的对象。
- 并发操作必须分别表达状态,不能让一个请求覆盖另一个请求的结果。
- 异步结果返回时确认对象和上下文仍匹配,避免旧请求覆盖用户的新选择。
## 动作真实性
每个可见动作必须对应以下至少一项:
- 持久化的数据变化;
- 明确的临时预览;
- 可观察的任务状态变化;
- 导航或详情展开;
- 可观察的本地或平台结果,例如复制到剪贴板、下载、导出或播放;
- 可恢复的错误处理。
禁止:
- 展示没有持久化能力的编辑、保存、批准或删除;
- 自动保存已经生效时继续显示虚假的未保存状态或重复保存按钮;
- 只修改内存却用已完成文案暗示数据已经保存;
- 成功后复制第二套对象,导致后续阶段维护不同来源;
- 用禁用按钮长期占位解释当前状态。
临时预览必须明确其范围;失败时保留用户已经输入的内容和当前位置。
## 示例与兜底数据
- 示例、演示和兜底数据必须与真实资源明确区分。
- 没有真实写入能力时隐藏编辑、删除、发布等写操作。
- 兜底数据只能保证流程可理解,不能伪造已经成功持久化的状态。
- 真实数据恢复后,兜底对象不得继续参与选择、统计或批量操作。
## 流程连续性
- 对象身份和生命周期未改变时,跨阶段继续更新原对象,不复制成第二套状态源。
- 动作确实生成独立版本、发布记录或产出资源时可以创建新对象,但必须明确关联来源,不能复制并继续维护同一份状态。
- 上一步选择和输入自动带入下一步。
- 关闭详情或编辑器后返回原位置,并显示最新状态。
- 操作完成后不要求用户重新搜索、重新选择或重复确认同一对象。
## 检查
- 选择器的数据是否覆盖全部可选资源?
- 查询条件、列表、总数和分页是否属于同一个已提交查询快照?
- 单项请求是否错误锁定了无关区域?
- 筛选后批量操作是否包含不可见对象?
- 每个编辑、保存和确认是否真实改变状态?
- 自动保存和显式保存是否重复?
- 示例数据是否被误当成真实可写资源?
- 操作完成后是否继续更新原对象并保留上下文?

View File

@ -0,0 +1,107 @@
# 状态与加载规则
> 当任务涉及 loading、refreshing、empty、error、processing、异步确认或后台长任务时读取数据归属和操作范围由数据与操作范围规则负责。
## 状态矩阵
| 范围 | Loading | Empty | Error | Processing | Ready |
| --- | --- | --- | --- | --- | --- |
| 应用启动 / 路由 | 品牌全局加载组件 | 不适用 | 全局恢复入口 | 不适用 | 应用骨架 |
| 页面 / 集合 | 与最终布局同构的顶部骨架 | 原因 + 一个恢复动作 | 错误说明 + 重试 | 单项状态留在对象上 | 正常内容 |
| 面板 / 弹窗 | 局部骨架并保持尺寸 | 局部空状态 | 局部重试 | 状态文字和必要进度 | 正常详情 |
| 按钮提交 | 共享按钮 `loading` 状态 | 不适用 | 就近错误反馈 | 防重复提交 | 成功结果 |
| 长任务单项 | 不使用持续 spinner | 不适用 | 失败原因 + 恢复动作 | 等待 / 处理中 | 完成 |
## 状态词汇
- `loading`:首次获取当前区域的数据,尚无可保留内容。
- `refreshing`:当前区域已有可保留内容,正在获取新的查询结果。
- `ready`:当前区域已有可使用内容。
- `empty`:资源集合本身为空。
- `filtered-empty`:资源集合可能存在,但当前筛选或搜索没有匹配结果。
- `processing`:当前区域的操作正在执行。
- `queued`:长任务已被接受,正在等待执行。
- `error`:当前区域加载或操作失败,并需要解释或恢复动作。
界面文案可以本地化,但状态判断、组件属性和验证报告统一使用以上词汇。
## 硬性规则
- 禁止大面积 spinner、旋转环和无内容遮罩。
- 禁止把页面加载误做成居中的空状态。
- 禁止让有限骨架占满剩余视口并漂在内容区中央。
- 禁止让骨架复制与最终布局无关的通用矩形。
- 禁止用 spinner 长期表达后台任务状态。
- 禁止同时显示 loading 与 empty或 processing 与 “no results”。
- 禁止把 loading 放入 EmptyState 或复用空状态容器。
- 同一对象和同一范围只显示一种加载反馈。
- 禁止在每个页面自行实现加载动画。
- 禁止异步确认一提交就关闭弹窗,再让用户从未变化的底层界面猜测请求是否完成。
## 全局加载
全局加载只负责应用初始化或路由级切换。使用唯一共享组件,保持品牌信号和稳定位置。全局组件自行拥有视觉,不复用按钮、列表或单项任务的局部进度组件。页面不得覆写其视觉,也不得把它替换为集合骨架。
## 加载结构由谁负责
- 共享骨架原语只负责颜色、圆角和动画,不负责猜测页面结构。
- 被加载的共享业务组件或布局组件负责骨架的页面结构、数量、尺寸和排列。
- 骨架复用最终组件对应的内容区域、相对比例和内容轨道,不复制会造成额外滚动的最小宽度、固定高度或完整数据量。
- 禁止让万能加载器根据粗粒度布局名称猜测页面结构。
- 可以由共享业务组件提供 `loading` 状态或同目录骨架组件;禁止使用组件的页面重新发明动画。
## 页面与集合骨架
骨架必须:
- 位于最终内容出现的位置;
- 保留最终页面中稳定存在的 Header、Toolbar、表头和容器只替换尚未返回的数据
- 由最终资源卡片、列表行、表格行或面板结构组合;
- 保持内容轨道宽度;
- 从顶部开始;
- 高度由占位内容决定,不用剩余视口高度把有限行数拉成整屏;
- 不得产生最终内容之外的滚动;宽表骨架压缩展示当前视口可见的列,不复刻完整表格的最小宽度;
- 在数据到达后不产生明显布局位移。
## 加载范围
| 情况 | 呈现 |
| --- | --- |
| 首次加载且没有旧数据 | 与最终内容同构的骨架 |
| 刷新、筛选或翻页且已有数据 | 保留同一已提交查询快照,在触发控件或容器上表达 `refreshing`;列表与总数在新响应完成后一起更新 |
| 按钮提交 | 按钮自身的 `loading` 状态 |
| 单个资源加载 | 只更新对应资源、媒体槽或状态位置 |
| 后台长任务 | 对象状态和必要进度,不持续占用操作控件 |
不要因为局部请求清空整个页面,也不要为同一请求同时显示活动图标、骨架、进度条和状态文字。
## 按钮加载
按钮加载由共享操作组件拥有。组件需:
- 保持原按钮宽度;
- 保留或稳定表达原动作;
- 禁用重复提交;
- 使用紧凑、非旋转或品牌一致的进度信号。
禁止在使用组件的位置手工插入加载动画、改内边距或写临时宽度。
## 异步确认弹窗
删除、移除、撤销、发布、保存等需要等待请求结果的确认动作,必须遵守同一生命周期:
1. 提交后保持弹窗、确认对象和影响说明不变,确认按钮进入共享 `loading` 状态并阻止重复提交。
2. 请求没有真实取消能力时,处理中禁用取消、关闭、点击遮罩和 `Escape` 关闭;不能让弹窗消失后请求仍在后台继续。
3. 只有请求成功且原界面的可见状态已经提交或刷新后,才关闭弹窗。不得先关闭弹窗,再等待列表、详情或状态可能更新。
4. 请求失败时保持弹窗和原对象,恢复确认按钮,并在弹窗内或紧邻操作的位置显示可恢复的错误;不得要求用户重新找到对象并再次打开确认流程。
5. 只有动作明确转为可观察的 `queued` / `processing` 长任务,且原界面已经显示对应对象状态时,弹窗才可以在任务最终完成前关闭。
这套生命周期由共享确认弹窗和负责业务请求的数据流共同保证。页面不得只关闭本地弹窗状态而丢弃仍在处理的对象,也不得用全页 busy 代替确认按钮的局部反馈。
## 后台任务
后台长任务应成为对象生命周期:
`queued → processing → ready | error`
列表显示短状态;详情显示解释、进度、错误和恢复动作。状态变化不得要求用户靠观察 spinner 猜测。

View File

@ -0,0 +1,196 @@
# 页面尺寸与弹窗规则
> 当任务涉及页面或弹窗尺寸、分栏、滚动、承载方式或响应式布局时读取;依附触发器的浮层由下拉菜单与浮层规则负责。
## 目录
- [核心模型](#核心模型)
- [单屏信息预算](#单屏信息预算)
- [水平与垂直布局](#水平与垂直布局)
- [内容驱动尺寸](#内容驱动尺寸)
- [滚动由谁负责](#滚动由谁负责)
- [弹窗结构](#弹窗结构)
- [操作栏](#操作栏)
- [承载方式:弹窗、抽屉与完整页面](#承载方式弹窗抽屉与完整页面)
- [响应式](#响应式)
- [审查问题](#审查问题)
## 核心模型
先确定四个问题:
1. 首屏必须让用户看到什么;
2. 内容如何决定尺寸并受视口约束;
3. 哪个区域拥有滚动;
4. 主操作固定在哪里。
空间设计按以下顺序进行:
`删除非必要信息 → 使用水平空间 → 压缩重复间距 → 指定滚动区 → 才允许增加页面长度`
## 单屏信息预算
首屏优先显示:
- 当前对象身份;
- 当前任务或关键预览;
- 影响决策的状态;
- 主要操作;
- 完成任务必需的输入。
以下内容可以滚动或进入详情:
- 历史记录;
- 完整分析和证据;
- 低频设置;
- 帮助说明;
- 次要关联信息。
不要为了“单屏”缩小到难以阅读。目标是减少无意义滚动,让用户在首屏完成主要判断和操作。
## 水平与垂直布局
宽屏优先并列展示可以同时参考的信息:
- 媒体预览 + 配置;
- 资源身份 + 详情;
- 主工作区 + 辅助检查;
- 表格 + 行级预览。
只有存在阅读顺序依赖时才纵向堆叠。不要把短字段、操作区和预览全部纵向排列,制造不必要页面高度。
分栏需满足:
- 主区宽度高于辅区;
- 文本保持可读行长;
- 两栏分别只在确有独立浏览需求时滚动;
- 窄屏按任务顺序折叠为单列;
- 主操作在布局变化后仍保持稳定位置。
## 内容驱动尺寸
默认让内容、Flex/Grid 和父容器边界决定尺寸,不为当前页面实例写“刚好适配截图”的固定宽高。
优先使用:
- 内容固有尺寸;
- 可伸缩轨道和剩余空间分配;
- 最小值、最大值和比例约束;
- 明确的父容器边界;
- 必要时的纵横比。
紧凑控件按内容占用空间;搜索、正文、主工作区等明确需要扩展的区域才吸收剩余空间。不要让分页、状态、数量或短选择器因父级布局自动拉满。
高度默认由内容撑开。需要限制时设置最大高度并指定滚动区不通过固定高度制造空白。Flex/Grid 子项应允许在父级边界内收缩,避免长内容撑破页面。
只有以下情况才使用固定尺寸:
- 稳定点击区域或控件规格;
- 图标、头像、缩略图等共享视觉规格;
- 媒体比例;
- 虚拟化或几何计算依赖;
- 防止关键布局跳动;
- 视口安全边距。
固定尺寸必须说明保护的行为,并优先由共享组件、统一设计变量或布局规则负责。删除固定尺寸不会破坏行为时,改回内容驱动。
## 滚动由谁负责
每个表面默认只指定一个主滚动容器:
- 应用外壳固定时,让主内容区滚动;
- 普通页面由主内容区滚动;
- 弹窗由 Body 滚动;
- 表格仅在自身容器中横向滚动;
- 独立面板只有在用户确实需要分别浏览时才拥有内部滚动,并必须具有明确任务边界和尺寸边界。
所有滚动容器必须具有明确尺寸边界。Grid 或 Flex 子项需要 `min-height: 0` / `min-width: 0`,避免内容撑破父容器。
禁止:
- `body`、页面内容和弹窗同时滚动;
- 弹窗整体滚动导致标题和操作消失;
- 无尺寸上限的内容把弹窗推出视口;
- 页面整体出现水平滚动条;
- 为解决溢出直接添加 `overflow: auto`
- 多层嵌套滚动却没有独立任务边界。
## 弹窗结构
存在正文和操作的弹窗必须使用共享 Header / Body / Footer 三段式结构。
共享弹窗需要满足:
- 弹窗根容器使用“内容上限 + 动态视口边界”,不能依靠固定高度填满屏幕;
- Header 固定顶部,拥有标题、必要身份和关闭入口;
- Body 使用剩余空间并作为唯一纵向滚动区;
- Footer 固定底部,完整跨越弹窗内容宽度;
- Header 和 Footer 使用稳定边界及组件内间距;
- 使用弹窗的页面不得自行覆盖弹窗内部布局。
该差异应成为含义明确的共享组件变体,不使用页面专属样式类修补。
## 操作栏
弹窗存在保存、完成、确认或取消动作时:
- 所有完成当前弹窗任务的操作放入 Footer
- 主操作位于右侧并保持最高强调;
- 取消或返回紧邻主操作,使用次级样式;
- 危险确认与普通操作明确分隔;
- 提示、计数或校验摘要可放 Footer 左侧;
- Footer 不随 Body 滚动;
- 内容区按钮只处理局部内容,不承担完成整个弹窗的任务。
纯阅读详情没有提交动作时可以只保留关闭入口,不为形式完整强加 Footer。
## 承载方式:弹窗、抽屉与完整页面
先检查项目已有的表面组件和同类任务页面;既有用法符合当前任务和本规范时才沿用,否则依据以下因素修复或替换共享承载方式。
弹窗适合:
- 自包含的短任务:确认、简短表单、预览 + 配置;
- 任务有明确的完成边界,完成后回到原页面位置和对象。
- 宽度由内容复杂度决定:确认使用窄弹窗,常规表单使用中等宽度,预览 + 配置使用宽弹窗或双栏;不通过继续扩大弹窗承载已经符合完整页面条件的任务。
抽屉适合:
- 用户需要保持底层列表、表格或画布的位置和当前对象可见;
- 任务是对当前选中对象的补充查看或编辑,例如行详情、筛选面板、辅助配置;
- 内容以单向浏览或单侧编辑为主,不需要多区域并行。
完整页面或工作区适合:
- 多步骤、复杂创作、大量媒体或多层导航;
- 任务本身就是用户的主要目的地,而不是某个页面的附属动作;
- 内容需要两个以上主要滚动区,或用户需要频繁在多个区域间切换。
其他约束:
- 不在一个模态弹窗上继续叠加第二个模态弹窗;菜单、下拉和 tooltip 不计入模态层级。需要第二层完整任务时升级为抽屉或页面。
- 项目没有抽屉组件时,不为单次需求引入新表面;确有需要时先建共享组件再在页面使用。
- 承载方式确定后,关闭或返回必须回到原位置和原对象。
## 响应式
- 使用动态视口高度,避免移动端地址栏造成溢出。
- 保留视口安全边距。
- 双栏在宽度不足时改单列。
- 移动端 Footer 可堆叠或让主操作占满宽度,但仍固定在弹窗底部。
- 检查长名称、校验错误和移动端输入面板出现后是否溢出或遮挡操作。
## 审查问题
- 首屏是否能完成主要判断或动作?
- 是否在纵向堆叠本可并列的信息?
- 哪些区域按内容尺寸,哪些区域吸收剩余空间?
- 每个固定宽高保护了什么行为?
- 谁拥有页面的纵向滚动?
- 是否出现意外的第二层滚动?
- 弹窗 Header 和 Footer 是否始终可见?
- Footer 是否为弹窗直接结构,而非某个内容列的子元素?
- 操作按钮是否稳定出现在底部栏?
- 内容变长后是否只滚动 Body
- 宽表格是否只在自身容器横向滚动?
- 当前任务是否已经复杂到应该使用独立页面?