diff --git a/CHANGELOG.md b/CHANGELOG.md index d4e9a7f..02987f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ - 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节 - 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段 +## 1.0.111 + +- 沉淀数据管理呈现加法:同一 `cellPresentation.enabled` 支持单元格、整行、整列、行列交叉区域(闭集 tone) +- 新增 `_jiangchang_grid_presentation` 契约 / Schema / 示例;v1 `cells[]` 保持不变;禁止整表 `all`×`all`;整行色只涂表格、不铺到详情字段 +- 内部隐藏表补上两张呈现旁路表;模板默认仍不启用着色 + ## 1.0.110 - 数据管理侧栏除了生成出来的 HTML 快照,也会直接显示安装包里 `assets/html/pages/` 的页面,装完就有,不用点生成 diff --git a/SKILL.md b/SKILL.md index 0a9b5c6..211919b 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 技能开发模板(通用业务版) description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。" -version: 1.0.110 +version: 1.0.111 author: 深圳匠厂科技有限公司 metadata: openclaw: @@ -42,7 +42,7 @@ allowed-tools: - **用户可见文案**:数据管理弹窗 / 任务中心文案须全中文产品用语;勿把 `pickCount`、`async`、`pending`、CLI 子命令写进弹窗(见 `references/ACTIONS.md`「用户可见文案」)。 - **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**。心智上多数为 sync,仅长任务 / RPA 标 async;宿主省略该字段时按 sync。每个 Action **仍必须**显式写 `sync` 或 `async`。 - **`policy`(可选)**:需要按用户/角色控制数据管理按钮或行列时,在 `actions.json` 顶层启用 Data Policy,由技能 `policy` CLI 输出 Snapshot;**未启用 = 与今日一致(L0)**。详见 `references/POLICY.md`。用户/角色数据源(飞书/库/API)属技能内部,宿主不托管。 -- **`cellPresentation`(可选)**:需要数据管理「某格特殊标色/强调」时启用;技能按当前数据写入呈现(语义 tone),宿主映射主题样式;**未启用 = P0 无标色**。用途不限(超时、预警、驳回等)。详见 `references/CELL_PRESENTATION.md`。 +- **`cellPresentation`(可选)**:需要数据管理「某格 / 整行 / 整列 / 区域」特殊标色时启用;技能按当前数据写入呈现(语义 tone),宿主映射主题样式;**未启用 = P0 无标色**。用途不限(超时、预警、驳回等)。详见 `references/CELL_PRESENTATION.md`。 - **业务行生命周期(有处理队列时)**:对某一行做生成/触达/私信等处理时,默认只操作「可操作」角色状态;开始抢占「进行中」;结束回写成功或失败(失败带原因);重做靠人工改回可操作。状态名由本技能自定。详见 `references/WORK_ITEM_STATUS.md`。 - **同步数据**写技能本地库、不生成导出文件;**导出当前表**由宿主数据管理负责;文件型特殊报告才另做 `export-*`(落 `output/`);**HTML**:壳子页放 `assets/html/pages/`,快照写 `html/` 并用固定 Action id `render-html`;页面用 `jiangchang.call` 调已声明命令(见 `references/ACTIONS.md`)。 - **准备 vs 执行(适用则拆)**:若技能存在「先写入/准备本地数据」与「再对外产生副作用」两段,Agent 必须能分开触发;禁止默认绑成不可拆的一步。一键无准备态的技能可跳过本条。 diff --git a/assets/examples/README.md b/assets/examples/README.md index 4b68735..3313371 100644 --- a/assets/examples/README.md +++ b/assets/examples/README.md @@ -3,6 +3,7 @@ - `version-response.json`:`python main.py version` 成功时 stdout 单行对象的形状参考。 - `skill-policy-snapshot.*.example.json`:Data Policy Snapshot 形状参考(见 `references/POLICY.md`)。 - `skill-cell-presentation.example.json`:数据管理单元格呈现文档形状参考(见 `references/CELL_PRESENTATION.md`)。 +- `skill-grid-presentation.example.json`:数据管理整行 / 整列 / 区域呈现文档形状参考(见 `references/CELL_PRESENTATION.md`)。 - `render-html.action.example.json`:HTML 报告「重新生成」Action 形状参考(固定 id `render-html`;见 `references/ACTIONS.md`)。 - `lookup-action.example.json`:Action 内联 Lookup 形状参考(单选 + `multiple: true` 多选并列;跨表引用勿填编号;见 `references/ACTIONS.md`「跨表引用:Lookup」)。 - `visible-when-action.example.json`:Action 参数字段条件显隐 `visibleWhen` 形状参考(互斥模式联动;见 `references/ACTIONS.md`「字段条件显隐」;≠ Policy L3)。 diff --git a/assets/examples/skill-grid-presentation.example.json b/assets/examples/skill-grid-presentation.example.json new file mode 100644 index 0000000..0c3670c --- /dev/null +++ b/assets/examples/skill-grid-presentation.example.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "skill": "your-skill-slug", + "table": "business_records", + "rowKey": "id", + "generatedAt": "2026-08-10T06:00:00Z", + "rules": [ + { + "ruleKey": "qty-low-rows", + "rows": ["42", "99"], + "columns": "all", + "tone": "danger", + "message": "库存低于安全线", + "alert": true + }, + { + "ruleKey": "status-column", + "rows": "all", + "columns": ["status"], + "tone": "warning", + "message": "待审核" + }, + { + "ruleKey": "overdue-print-region", + "rows": ["7", "8"], + "columns": ["print_done_at", "ship_done_at"], + "tone": "danger", + "message": "环节到期未填", + "alert": true + } + ] +} diff --git a/assets/schemas/skill-actions.schema.json b/assets/schemas/skill-actions.schema.json index 0438321..c3c37f6 100644 --- a/assets/schemas/skill-actions.schema.json +++ b/assets/schemas/skill-actions.schema.json @@ -28,7 +28,7 @@ }, "cellPresentation": { "$ref": "#/$defs/cellPresentationDeclaration", - "description": "可选。启用数据管理单元格呈现(P1)。缺省或不 enabled = P0,宿主不读标色。详见 references/CELL_PRESENTATION.md。" + "description": "可选。启用数据管理呈现(P1:格子/行/列/区域)。缺省或不 enabled = P0,宿主不读标色。详见 references/CELL_PRESENTATION.md。" } }, "$defs": { diff --git a/assets/schemas/skill-cell-presentation.schema.json b/assets/schemas/skill-cell-presentation.schema.json index 983c48f..9ebbcf3 100644 --- a/assets/schemas/skill-cell-presentation.schema.json +++ b/assets/schemas/skill-cell-presentation.schema.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://openclaw.local/skill-template/skill-cell-presentation.schema.json", "title": "SkillCellPresentationDocument", - "description": "匠厂数据管理「单元格呈现」文档(schemaVersion 1)。技能按业务规则为「某表某行某列」声明语义 tone(非任意 CSS);宿主映射主题样式。用途不限(时效超时、库存预警、状态异常、必填缺失等)。详见 references/CELL_PRESENTATION.md。", + "description": "匠厂数据管理「单元格呈现」文档(schemaVersion 1)。技能按业务规则为「某表某行某列」声明语义 tone(非任意 CSS);宿主映射主题样式。整行/整列/区域见 skill-grid-presentation.schema.json,同一 cellPresentation.enabled。用途不限(时效超时、库存预警、状态异常、必填缺失等)。详见 references/CELL_PRESENTATION.md。", "type": "object", "required": ["schemaVersion", "skill", "table", "rowKey", "cells"], "additionalProperties": false, diff --git a/assets/schemas/skill-grid-presentation.schema.json b/assets/schemas/skill-grid-presentation.schema.json new file mode 100644 index 0000000..1d70f85 --- /dev/null +++ b/assets/schemas/skill-grid-presentation.schema.json @@ -0,0 +1,93 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://openclaw.local/skill-template/skill-grid-presentation.schema.json", + "title": "SkillGridPresentationDocument", + "description": "匠厂数据管理「Grid Presentation」文档(schemaVersion 1)。技能按业务规则为 rows×columns 声明语义 tone(整行、整列、区域或单格);禁止 all×all。非任意 CSS。与 skill-cell-presentation.schema.json(v1 cells[])并存,同一 cellPresentation.enabled。详见 references/CELL_PRESENTATION.md。", + "type": "object", + "required": ["schemaVersion", "skill", "table", "rowKey", "rules"], + "additionalProperties": false, + "properties": { + "schemaVersion": { + "type": "integer", + "const": 1 + }, + "skill": { + "type": "string", + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "minLength": 1, + "description": "与 SKILL.md metadata.openclaw.slug / actions.json skill 一致" + }, + "table": { + "type": "string", + "minLength": 1, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "业务表物理名(snake_case)" + }, + "rowKey": { + "type": "string", + "minLength": 1, + "pattern": "^[a-z][a-z0-9_]*$", + "description": "用于匹配行的业务表列名(如 id);rules[].rows 的 id 取自该列" + }, + "generatedAt": { + "type": "string", + "minLength": 1, + "description": "可选。ISO-8601 或技能约定的生成时间,便于排障" + }, + "rules": { + "type": "array", + "description": "当前应对该表生效的 grid 规则;空数组 = 该表无 grid 呈现(清除旧行/列/区域样式)。同 ruleKey 由 UNIQUE 约束覆盖。", + "items": { "$ref": "#/$defs/ruleItem" } + } + }, + "$defs": { + "tone": { + "type": "string", + "enum": ["danger", "warning", "info", "success", "muted"], + "description": "语义色板(闭集)。宿主映射到底色/字色/左边线等;禁止技能下发原始 CSS 或任意 hex。" + }, + "axisTarget": { + "description": "\"all\" = 该轴全部;非空字符串数组 = 有限集合(行 id 或列名)", + "oneOf": [ + { "type": "string", "const": "all" }, + { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + } + ] + }, + "ruleItem": { + "type": "object", + "required": ["ruleKey", "rows", "columns", "tone"], + "additionalProperties": false, + "not": { + "properties": { + "rows": { "const": "all" }, + "columns": { "const": "all" } + }, + "required": ["rows", "columns"] + }, + "properties": { + "ruleKey": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "本表内唯一。建议稳定业务键(重算时覆盖同一条)" + }, + "rows": { "$ref": "#/$defs/axisTarget" }, + "columns": { "$ref": "#/$defs/axisTarget" }, + "tone": { "$ref": "#/$defs/tone" }, + "message": { + "type": "string", + "maxLength": 500, + "description": "可选。悬停/无障碍说明(短文案);不要塞长报告" + }, + "alert": { + "type": "boolean", + "description": "可选,默认 false。true = 按本条规则计入进页/同步提醒(不按命中格子数)" + } + } + } + } +} diff --git a/development/CHECKLIST.md b/development/CHECKLIST.md index 57d452e..7b8d4d9 100644 --- a/development/CHECKLIST.md +++ b/development/CHECKLIST.md @@ -149,6 +149,7 @@ checklist_version: 1.0 - [ ] A6-12 **P2** `display_type: boolean` 的展示列推荐同时配置 `options_json` 中文 label(如 停用/启用),避免仅靠宿主默认「是/否」;无 boolean 列 → **N/A** - [ ] A6-13 **P0** 新技能**不得**创建 `task_logs`;过程/进度/业务结果走运行日志、任务中心、业务表(见 `LOGGING.md`、`SCHEMA.md`) - [ ] A6-14 **P0** 废弃用户可见表时:`drop_deprecated_user_table` 物理删表 + 清元数据;**禁止**只删元数据留物理表;有迁移时须提供旧库回归测试(见 `SCHEMA.md`、`tests/samples/test_table_deprecation_migration.py.sample`) +- [ ] A6-15 **P1** 若启用 `cellPresentation`:旁路表不得出现在数据管理侧栏;整行着色不得铺到详情每个字段;禁止 `all`×`all`;tone 闭集。未启用 → **N/A**(见 `references/CELL_PRESENTATION.md`) --- diff --git a/development/SKILL_ACTION_RUNTIME.md b/development/SKILL_ACTION_RUNTIME.md index 54a5d17..4b5383b 100644 --- a/development/SKILL_ACTION_RUNTIME.md +++ b/development/SKILL_ACTION_RUNTIME.md @@ -21,7 +21,7 @@ 1. **宿主管调度,技能管业务** — 不自行实现任务中心 / Job 轮询 / 后台守护进程。 2. **单业务内核、多入口** — 数据管理、定时任务、Agent、技能详情与直接 CLI 复用同一 domain service;禁止按入口复制业务逻辑。 -3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **`visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** Policy L3 行态 `visibleWhen` 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`bind.selectionMode`**(见 ACTIONS.md):表勾选如何驱动 Action(`required` / `none` / `optional`);省略 = 宿主按 `$selection.ids` / `batch` 推断。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格语义标色;省略 = P0。**用户可见文案**(见 ACTIONS.md「用户可见文案」):弹窗 `description` / 确认黄条 / 参数说明 / 任务失败 `message` 须全中文产品用语;Agent 路由勿塞进弹窗。 +3. **五职责正交** — `placements` / `bind.tables` / `executionProfile` / `entrypoint` / domain service 各管一事(见 ACTIONS.md)。可选第六轴 **policy**(见 `references/POLICY.md`):未启用 = L0 与今日一致。可选 **`hostEffects` / `steps`**(见 ACTIONS.md):数据管理交互前后的 UI/级联编排;省略 = 不额外改 UI(匠厂宿主 ≥2.8.5)。可选 **`hoverHint`**(见 ACTIONS.md):数据管理工具栏悬停;省略 = 不显示,不回退说明或确认黄条。可选 **`visibleWhen`**(见 ACTIONS.md):Action 参数表单字段条件显隐;省略 = 字段始终平铺;**勿与** Policy L3 行态 `visibleWhen` 混淆;**勿**用其藏映射主键。可选 **`pathRoot`**(见 ACTIONS.md):`file`/`directory` 原生选路对话框起始目录(相对技能数据根;省略默认 `{skill_data}/input`)。可选 **`bind.labelColumn`**(见 ACTIONS.md):选择摘要可读标签列;省略 = 宿主常见列名启发。可选 **`bind.selectionMode`**(见 ACTIONS.md):表勾选如何驱动 Action(`required` / `none` / `optional`);省略 = 宿主按 `$selection.ids` / `batch` 推断。可选 **`revealInForm`**(见 ACTIONS.md):有「已选择」时仍强制显示某 `readOnly` 字段;省略 = 映射只读默认不占 form 参数区(仍提交)。可选 **`cellPresentation`**(见 `references/CELL_PRESENTATION.md`):单元格/整行/整列/区域语义标色;省略 = P0。**用户可见文案**(见 ACTIONS.md「用户可见文案」):弹窗 `description` / 确认黄条 / 参数说明 / 任务失败 `message` 须全中文产品用语;Agent 路由勿塞进弹窗。 4. **长耗时建议 async** — 开浏览器、RPA、HTTP 大文件下载等建议 `executionProfile: "async"`,进**任务中心**;这是对**方法**的选择,**不**限制可以出现在哪些 placement / 入口。 5. **Agent:短 CLI / 长 Action** — 短查询可用共享 Python bash CLI;长任务 / RPA **禁止** `exec` + `process poll`,必须 `run_skill_action`。 6. **进度走 Journal** — `emit` / `video.add_step` → Run Journal;UI / Skill Run Card / 任务中心展示;**不靠 stdout 流**。 diff --git a/references/ACTIONS.md b/references/ACTIONS.md index d7eac6c..480db06 100644 --- a/references/ACTIONS.md +++ b/references/ACTIONS.md @@ -77,7 +77,7 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表** | `skill` | 是 | 必须与 `SKILL.md` 的 `metadata.openclaw.slug` 一致 | | `actions` | 是 | Action 数组,每项 `id` 唯一;**数组相对顺序**决定数据管理 toolbar / row / batch 技能按钮的展示顺序(见下节) | -模板最小示例见 [`assets/actions.json`](../assets/actions.json);JSON Schema 见 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json)。可选 Data Policy 见 [`POLICY.md`](POLICY.md) 与 [`assets/schemas/skill-policy-snapshot.schema.json`](../assets/schemas/skill-policy-snapshot.schema.json)。可选单元格呈现见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md) 与 [`assets/schemas/skill-cell-presentation.schema.json`](../assets/schemas/skill-cell-presentation.schema.json)。 +模板最小示例见 [`assets/actions.json`](../assets/actions.json);JSON Schema 见 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json)。可选 Data Policy 见 [`POLICY.md`](POLICY.md) 与 [`assets/schemas/skill-policy-snapshot.schema.json`](../assets/schemas/skill-policy-snapshot.schema.json)。可选单元格/整行/整列呈现见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md)、[`assets/schemas/skill-cell-presentation.schema.json`](../assets/schemas/skill-cell-presentation.schema.json) 与 [`assets/schemas/skill-grid-presentation.schema.json`](../assets/schemas/skill-grid-presentation.schema.json)。 ## 六职责正交(必读) @@ -91,7 +91,7 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表** | **`hoverHint`** | **可选**:数据管理**工具栏悬停**文案 | 不决定短按钮名;不决定点下去弹不弹窗;**不回退** `description` / `confirmation.message`;省略 = 不显示悬停。当前宿主实现为顶栏技能按钮 | | **`inputSchema.visibleWhen`** | **可选**:Action **参数表单**字段条件显隐(先选模式再出对应参数) | **不是** Data Policy L3 行态 `visibleWhen`;不决定 placements;旧宿主忽略则字段平铺全显 | | **`hostEffects` / `steps`** | **可选**:数据管理交互跑完前后,宿主要不要刷新表 / 清选区 / 级联删等 | 不决定业务写什么;**省略 = 宿主不额外改 UI**(≥2.8.5 起不再硬编码 mutation 后刷新);cron/agent 忽略 | -| **`cellPresentation`** | **可选**:某表某行某列的语义标色/强调(tone + 说明) | 不替代业务列;不下发 CSS;用途不限(超时、预警、驳回等);见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md) | +| **`cellPresentation`** | **可选**:某表某格 / 整行 / 整列 / 区域的语义标色/强调(tone + 说明) | 不替代业务列;不下发 CSS;用途不限(超时、预警、驳回等);见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md) | | **`policy` / Snapshot** | **可选**:当前身份在数据管理下允许哪些 Action / 宿主内置能力 / 行列范围 | 不替代 placements;不替代 domain 写路径鉴权;多数技能不配 = L0 全开 | | **`entrypoint`** | 实际执行哪个 CLI 命令与参数 | 不写业务逻辑 | | **domain service** | **真正完成什么业务** | 不感知 toolbar / cron / agent 来源 | @@ -102,14 +102,14 @@ Action 是否提供、挂哪些 `placements`,由本技能 **入口定位表** | 层级 | 稳定字段 / 能力 | |------|----------------| -| 顶层 | `schemaVersion`、`skill`、`actions`;可选 **`policy`**(Data Policy 启用块);可选 **`cellPresentation`**(单元格呈现启用块) | +| 顶层 | `schemaVersion`、`skill`、`actions`;可选 **`policy`**(Data Policy 启用块);可选 **`cellPresentation`**(格子/行/列/区域呈现启用块) | | action | `id`、`label`、`description`、`placements`、`entrypoint`、**`executionProfile`(必填)**;可选 `hoverHint`、`inputSchema`、`confirmation`、**`interaction`**、**`interactionByPlacement`**、**`bind`**、**`replaces`**、**`hostEffects`**、**`steps`**、**`authz`**(仅文档提示) | | entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) | | placements | `toolbar`、`row`、`batch`、`skill-detail`、`agent`、`cron`;仅 `replaces` 时可为空数组 | | **replaces** | 可选 `"create"` \| `"update"` \| `"delete"` \| `"import"` — 接管默认新增/编辑/删除/导入(须 `bind.tables`) | | **bind** | `{ "tables": ["business_table"] }`;可选 `inputMapping`、`columnMapping`、**`labelColumn`**、**`selectionMode`**(行内/批量预填、选择摘要标签、勾选驱动模式,见下节) | | **policy** | 可选;`enabled` + `entrypoint`(推荐 `policy` CLI);见 POLICY.md。未启用 = L0 | -| **cellPresentation** | 可选;`{ "enabled": true }` 时宿主应加载单元格呈现;见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md)。未启用 = P0 | +| **cellPresentation** | 可选;`{ "enabled": true }` 时宿主应加载格子与 grid 呈现;见 [`CELL_PRESENTATION.md`](CELL_PRESENTATION.md)。未启用 = P0 | | inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive`、`readOnly`、可选 **`revealInForm`**;可选 `display_type` / `format`(含 `file` / `directory` 等);可选 **`pathRoot`**(file/directory 起始目录,相对技能数据根);可选 **`visibleWhen`**(字段条件显隐,见专节) | | confirmation | `{ "message": "..." }` — **风险文案**(confirm/form 弹窗黄条;agent 元数据);**不是**「要不要弹窗」的开关 | | **hoverHint** | 可选字符串。数据管理**工具栏悬停**文案;与 `description` / `confirmation.message` **独立**。省略则不显示悬停,不回退。短名已够懂时不要写。需宿主已支持该字段;当前实现为顶栏技能按钮,不含宿主内置删除/刷新/新增/导入/导出 | diff --git a/references/CELL_PRESENTATION.md b/references/CELL_PRESENTATION.md index a5c9fca..077504e 100644 --- a/references/CELL_PRESENTATION.md +++ b/references/CELL_PRESENTATION.md @@ -1,9 +1,9 @@ # 数据管理单元格呈现(Cell Presentation)契约(v1.0) -> **状态:正式契约 v1.0(`schemaVersion` 1)。** -> **目标:** 冻结「技能声明某表某行某列的语义呈现 → 宿主映射主题样式」的通用能力,供任意业务场景复用。 +> **状态:正式契约 v1.0(`cells[]` 文档 `schemaVersion` 1)+ 加法 Grid Presentation。** +> **目标:** 冻结「技能声明语义呈现 → 宿主映射主题样式」的通用能力:某一格、整行、整列、若干行×若干列,供任意业务场景复用。 > **非目标:** 超时/SLA 专用字段;技能下发任意 CSS / 任意色值;宿主实现业务规则引擎。 -> **配套 Schema:** [`../assets/schemas/skill-cell-presentation.schema.json`](../assets/schemas/skill-cell-presentation.schema.json)。 +> **配套 Schema:** [`../assets/schemas/skill-cell-presentation.schema.json`](../assets/schemas/skill-cell-presentation.schema.json)(格子)、[`../assets/schemas/skill-grid-presentation.schema.json`](../assets/schemas/skill-grid-presentation.schema.json)(行/列/区域)。 相关正交轴见 [`ACTIONS.md`](ACTIONS.md)、[`POLICY.md`](POLICY.md)、[`SCHEMA.md`](SCHEMA.md)。 @@ -11,9 +11,17 @@ ## 0. 一句话 -技能可以声明:**哪张业务表、哪一行、哪一列**需要特殊标色/强调(语义 `tone` + 可选说明)。 +技能可以声明:**哪张业务表**上,**哪些行 × 哪些列**需要特殊标色/强调(语义 `tone` + 可选说明)。 + +| 想涂什么 | 怎么声明 | +|----------|----------| +| 某一格 | 一行 × 一列(v1 `cells[]` 或一条格子规则) | +| 整行 | 若干行 × 该轴全部列 | +| 整列 | 该轴全部行 × 若干列 | +| 区域 | 若干行 × 若干列 | + 用途不限:时效超时未填、库存预警、状态异常、必填缺失、审核驳回等。 -**不是**「再加一列超时文字」;强调落在**真正要关注的业务格子**上。 +**不是**「再加一列超时文字」;强调落在**真正要关注的业务格子或行**上。 --- @@ -22,9 +30,20 @@ | 档位 | 技能行为 | 宿主行为 | |------|----------|----------| | **P0(默认)** | 不写呈现数据 / 未启用 | 数据管理表格与今日一致,无特殊标色 | -| **P1** | 按规则写入呈现文档或推荐旁路表 | 渲染对应单元格的语义样式;可选汇总 `alert: true` 做进页提醒 | +| **P1** | 按规则写入呈现文档或推荐旁路表 | 渲染对应格子 / 行 / 列 / 区域的语义样式;可选汇总 `alert: true` 做进页提醒 | -多数技能保持 **P0**。需要视觉强调时再启用。 +多数技能保持 **P0**。需要视觉强调时再启用。模板 `actions.json` **默认不启用**。 + +--- + +## 0.2 宿主能力 + +| 能力 | 旁路表 | 宿主 | +|------|--------|------| +| 格子着色 | `_jiangchang_cell_presentation` | 既有宿主即可 | +| 整行 / 整列 / 区域 | `_jiangchang_grid_presentation` | 需已读取该表(匠厂数据管理已支持)。**旧宿主忽略该表**,格子着色仍有效 | + +同一开关 `cellPresentation.enabled` 同时打开两张旁路表。未建表 = 该通道为空,宿主忽略。 --- @@ -32,17 +51,17 @@ | 角色 | 负责 | 不负责 | |------|------|--------| -| **技能** | 按**当前业务数据**算出哪些格子要强调;在数据变更后**重算**并覆盖旧结果 | 不写宿主 CSS;不把强调文案污染进业务真值列冒充「变红」 | -| **宿主** | 读取呈现结果,按闭集 `tone` 映射主题样式;可选 Toast/提醒汇总 | 不理解「提前 3 天交单」等业务规则;不为单个技能写死样式 | +| **技能** | 按**当前业务数据**算出哪些格子/行/列要强调;在数据变更后**重算**并覆盖旧结果 | 不写宿主 CSS;不把强调文案污染进业务真值列冒充「变红」 | +| **宿主** | 读取呈现结果,按闭集 `tone` 映射主题样式;按几何涂表格;可选 Toast/提醒汇总 | 不理解「提前 3 天交单」等业务规则;不为单个技能写死样式 | **派生状态(重要):** 呈现是计算结果,不是粘性开关。 用户补填数据 / 同步刷新后技能重算 → 该项消失 → **样式与提醒自然关闭**。不要单独维护「已关闭提醒」状态机(除非产品另做「忽略此条」能力,本契约不冻结)。 --- -## 2. 文档形状(冻) +## 2. 格子文档形状(冻,`schemaVersion` 1) -技能产出一份 **Cell Presentation Document**(可落库、可 CLI 打印,形状相同),须符合 Schema。 +技能产出一份 **Cell Presentation Document**(可落库、可 CLI 打印,形状相同),须符合格子 Schema。v1 **只描述某一格**;整行/整列用 §2.1。 ```json { @@ -71,14 +90,14 @@ | 字段 | 必填 | 说明 | |------|------|------| -| `schemaVersion` | 是 | 固定 `1` | +| `schemaVersion` | 是 | 固定 `1`(本形状不升版本) | | `skill` | 是 | 与 slug 一致 | | `table` | 是 | 当前文档作用的业务表 | | `rowKey` | 是 | 行匹配列(`id` / `feishu_record_id` 等) | | `generatedAt` | 否 | 排障用 | -| `cells` | 是 | 数组;**空数组 = 该表清除全部特殊呈现** | +| `cells` | 是 | 数组;**空数组 = 该表清除全部格子呈现** | -### 2.1 `cells[]` 项 +### 2.0 `cells[]` 项 | 字段 | 必填 | 说明 | |------|------|------| @@ -91,6 +110,74 @@ 同一 `(rowId, column)` 多条:宿主可**后者覆盖前者**。 `column` 对用户不可见(policy 打码 / 列隐藏)时:宿主可仍应用样式,或跳过——**推荐跳过不可见列的强调**,避免泄露「有问题」的存在感(技能仍可写,宿主按可见性过滤)。 +### 2.1 Grid 文档形状(加法,独立 Schema) + +整行 / 整列 / 区域用 **Grid Presentation Document**(`rules[]`)。与 `cells[]` **并存**,不替代、不升 `cells` 的 `schemaVersion`。 + +统一几何:**`rows` × `columns`**。某一侧为 `"all"`(或省略,落库时写成 JSON `"all"`)= 该轴全部。禁止两侧都是全部(见 §4.2)。 + +```json +{ + "schemaVersion": 1, + "skill": "your-skill-slug", + "table": "business_records", + "rowKey": "id", + "generatedAt": "2026-08-10T06:00:00Z", + "rules": [ + { + "ruleKey": "qty-low-rows", + "rows": ["42", "99"], + "columns": "all", + "tone": "danger", + "message": "库存低于安全线", + "alert": true + }, + { + "ruleKey": "status-column", + "rows": "all", + "columns": ["status"], + "tone": "warning", + "message": "待审核" + }, + { + "ruleKey": "overdue-print-region", + "rows": ["7", "8"], + "columns": ["print_done_at", "ship_done_at"], + "tone": "danger", + "message": "环节到期未填", + "alert": true + } + ] +} +``` + +| 字段 | 必填 | 说明 | +|------|------|------| +| `schemaVersion` | 是 | 固定 `1` | +| `skill` / `table` / `rowKey` | 是 | 同格子文档;`rowKey` 用于匹配 `rows` 里的 id | +| `rules` | 是 | 数组;**空数组 = 该表清除全部 grid 规则** | + +#### `rules[]` 项 + +| 字段 | 必填 | 说明 | +|------|------|------| +| `ruleKey` | 是 | 本表内唯一(建议稳定业务键,便于重算覆盖) | +| `rows` | 是 | `"all"` 或行 id 字符串数组(对应 `rowKey` 列值) | +| `columns` | 是 | `"all"` 或业务列名数组 | +| `tone` | 是 | 见 §3 | +| `message` | 否 | ≤500 | +| `alert` | 否 | 默认 `false`;按**规则条数**计提醒,不按命中格子数 | + +| `rows` × `columns` | 宿主 scope | +|--------------------|-----------| +| 1 行 × 1 列 | `cell` | +| 若干行 × 若干列(非单格) | `region` | +| 若干行 × `"all"` | `row`(整行) | +| `"all"` × 若干列 | `column`(整列) | +| `"all"` × `"all"` | **禁止**,宿主丢弃该规则 | + +完整 JSON 例见 [`../assets/examples/skill-grid-presentation.example.json`](../assets/examples/skill-grid-presentation.example.json)。 + --- ## 3. `tone` 闭集(冻) @@ -106,13 +193,13 @@ **禁止:** 技能下发原始 `#RRGGBB`、任意 CSS class、内联 style。 以后若扩展色板,只能**追加新 tone token** 并升契约,不能开放任意色值。 -「技能配置什么就显示什么」在本契约中的含义是:技能选择 **哪一格 + 哪个 tone + 什么说明**;**像素级颜色由宿主主题决定**,以保证多技能 UI 一致与安全。 +「技能配置什么就显示什么」在本契约中的含义是:技能选择 **哪一格/行/列 + 哪个 tone + 什么说明**;**像素级颜色由宿主主题决定**,以保证多技能 UI 一致与安全。 --- ## 4. 推荐持久化(给宿主实现) -v1 **推荐**技能将「当前表」的呈现写入用户库旁路表(与业务表分离,**不是**多余业务超时列): +v1 **推荐**技能将「当前表」的**格子**呈现写入用户库旁路表(与业务表分离,**不是**多余业务超时列): ```sql CREATE TABLE IF NOT EXISTS _jiangchang_cell_presentation ( @@ -130,19 +217,60 @@ CREATE TABLE IF NOT EXISTS _jiangchang_cell_presentation ( ); ``` +### 4.1 整行 / 整列 / 区域(`_jiangchang_grid_presentation`) + +```sql +CREATE TABLE IF NOT EXISTS _jiangchang_grid_presentation ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + table_name TEXT NOT NULL, + rule_key TEXT NOT NULL, + row_key TEXT NOT NULL DEFAULT '', + rows_json TEXT NOT NULL, + columns_json TEXT NOT NULL, + tone TEXT NOT NULL, + message TEXT, + alert INTEGER NOT NULL DEFAULT 0, + generated_at TEXT, + updated_at INTEGER NOT NULL DEFAULT (unixepoch()), + UNIQUE (table_name, rule_key) +); +``` + +`rows_json` / `columns_json` 存 JSON:字符串 `"all"`,或 id / 列名数组(如 `["42","99"]`)。 +`row_key`:有限行集合时必填(与文档 `rowKey` 相同,如 `id`);整列(`rows_json = "all"`)可空字符串。 + +两张表都列入技能 `INTERNAL_METADATA_TABLES`(见 `scripts/db/display_metadata.py`),**不得**作为业务表出现在数据管理侧栏。模板 **不**在 `init_db()` 里默认建这两张表;技能用到时再 `CREATE`。 + +### 4.2 冲突与特异性 + +同一格被多条规则命中时,宿主按 **格子 > 区域 > 行 > 列** 取胜。同级后者覆盖前者。 + +宿主先加载 grid 规则,再加载 v1 `cells[]`(同级时 **v1 格子仍赢**),因此旧技能只写 `cells[]` 的行为不变。 + +**禁止 `all` × `all`**(会把整张表涂满)。技能不要写;宿主遇到则丢弃该规则。 + +### 4.3 表格 vs 详情 + +| 表面 | 整行(scope=`row`) | 格子 / 列 / 区域 | +|------|-------------------|------------------| +| 数据管理表格 | 给整行(`