From 49e4d6e9a6511265752a682c5a3f021e6aebfb7f Mon Sep 17 00:00:00 2001 From: chendelian <116870791@qq.com> Date: Fri, 14 Aug 2026 10:17:17 +0800 Subject: [PATCH] docs: default visible columns contract (v1.0.79) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 沉淀 _jiangchang_tables.default_visible_columns_json:技能声明默认展示列;未配置全显;用户改「列」后本机覆盖;与 visible=0 硬隐藏区分。 Co-authored-by: Cursor --- CHANGELOG.md | 7 +++++ SKILL.md | 2 +- references/ACTIONS.md | 1 + references/SCHEMA.md | 40 +++++++++++++++++++++++++++- scripts/db/display_metadata.py | 30 +++++++++++++++++---- tests/test_display_metadata.py | 48 ++++++++++++++++++++++++++++++++++ tests/test_docs_standards.py | 2 ++ 7 files changed, 123 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f546fd0..6a517df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ - 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节 - 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段 +## 1.0.79 + +- 沉淀数据管理表级「默认展示列」契约:`_jiangchang_tables.default_visible_columns_json` +- 已配置则宿主默认只显示名单列;未配置全显;用户改过「列」后以本机偏好为准 +- 与 `_jiangchang_columns.visible=0` 硬隐藏区分:默认隐藏仍可在「列」面板勾回 +- `upsert_table_metadata` / 旧库幂等 `ALTER` 已支持该字段(见 `references/SCHEMA.md`) + ## 1.0.78 - 反哺 RPA 有界就绪等待约定:状态等待统一用 kit `poll_until`(需 `jiangchang-platform-kit>=1.2.11`) diff --git a/SKILL.md b/SKILL.md index 6209913..9d5265c 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 技能开发模板(通用业务版) description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。" -version: 1.0.78 +version: 1.0.79 author: 深圳匠厂科技有限公司 metadata: openclaw: diff --git a/references/ACTIONS.md b/references/ACTIONS.md index e9cc58d..5ffd824 100644 --- a/references/ACTIONS.md +++ b/references/ACTIONS.md @@ -473,6 +473,7 @@ HINT: - 臆造 `sortOrder` / `order` / `priority` 等字段指望宿主排序(模板 Schema `additionalProperties: false` 会拒收)。 - 依赖或宣传表顶栏「更多操作」溢出菜单(宿主已取消该能力)。 - 把「表格行数据默认排序」与按钮顺序混淆——行排序见 [`SCHEMA.md`](SCHEMA.md) 的 `default_sort_json`。 +- 把「默认展示列」与 `visible=0` 硬隐藏混淆——默认展示列见 [`SCHEMA.md`](SCHEMA.md) 的 `default_visible_columns_json`。 - 新增 `row-context-menu` 等 placement,或要求技能再维护一份与 `row` 平行的菜单清单。 ### Action 类型 × placements(常见示例,不是限制) diff --git a/references/SCHEMA.md b/references/SCHEMA.md index c9eaf95..040834c 100644 --- a/references/SCHEMA.md +++ b/references/SCHEMA.md @@ -139,6 +139,7 @@ metadata: | `visible` | 是 | `1` 在宿主数据管理中展示 / `0` 隐藏 | | `readonly` | 是 | `1` 整张表只读;`0` 允许宿主根据字段权限执行写操作 | | `default_sort_json` | 否 | 数据管理**默认行排序**(见下节);空则宿主用内置默认 | +| `default_visible_columns_json` | 否 | 数据管理**默认展示列**(见下节);空则全显 | #### 表级默认排序 `default_sort_json`(宿主支持) @@ -171,12 +172,49 @@ upsert_table_metadata( ) ``` +#### 表级默认展示列 `default_visible_columns_json`(宿主支持) + +技能可声明该表在数据管理表格中的**默认展示列**(软默认,不是硬隐藏): + +- **已配置**:首次打开(用户尚未改过「列」)只显示名单中的列;其余列仍在「列」面板中,用户可勾回 +- **未配置 / 空 / 无效**:显示全部 schema 可见列(与今日行为一致) +- **用户改过「列」或表头「隐藏此列」后**:以本机偏好为准;「恢复默认列布局」后重新回到技能默认(若有) + +JSON 数组(物理列名;也可写 `{"column":"col"}` 对象,宿主同样接受): + +```json +["stat_type","period","stage","ops_count","timeout_ratio"] +``` + +规则: + +- 列名必须是该表真实列,且 `_jiangchang_columns.visible=1`(硬隐藏列本来就不进表格) +- 与 `visible=0` **不同**:`visible=0` = 列从数据管理 schema /「列」面板移除;本字段只影响默认勾选状态 +- 名单为空或全部无效时,宿主 fail-open:全显 +- 通过 `upsert_table_metadata(..., default_visible_columns_json=...)` 写入;旧库由 `init_display_metadata_tables` 幂等 `ALTER` 补列 + +示例(时效统计:默认不展示编号与时间戳列): + +```python +upsert_table_metadata( + cursor, + table_name="timeliness_stats", + display_name="时效统计", + readonly=1, + default_visible_columns_json=( + '["stat_type","period","stage","ops_count",' + '"timeout_open","timeout_done","timeout_total","timeout_ratio"]' + ), +) +``` + 禁止: - 使用中文真实表名 - 使用 `_schema_meta` 作为新的正式契约 - 只写英文物理名而不写中文 `display_name` - 让元数据引用不存在的表 +- 用 `visible=0` 假装「默认不展示但用户还能勾出来」(那是硬隐藏,勾不回来) ### `_jiangchang_columns` 字段级标准 @@ -187,7 +225,7 @@ upsert_table_metadata( | `display_name` | 是 | 用户可见的中文字段名(表头与表单标签);保持简短 | | `description` | 否 | 字段说明(给人看的短文案);**宿主在新增/编辑表单标签下方展示**(见下节);不要塞进 `display_name` | | `display_order` | 否 | 兼容字段,默认保持 `NULL` | -| `visible` | 是 | 是否在数据管理表格中展示 | +| `visible` | 是 | 是否进入数据管理 schema /「列」面板(`0` = **硬隐藏**,用户无法勾回;默认不展示但可勾回请用表级 `default_visible_columns_json`) | | `searchable` | 是 | 是否参与搜索 | | `editable` | 是 | `1` 业务字段允许宿主用于新增和编辑;`0` 系统/只读字段 | | `display_type` | 否 | 字段渲染类型;稳定取值见下节「表单与展示:稳定字段类型」 | diff --git a/scripts/db/display_metadata.py b/scripts/db/display_metadata.py index 674a334..e3a1ea5 100644 --- a/scripts/db/display_metadata.py +++ b/scripts/db/display_metadata.py @@ -25,7 +25,8 @@ CREATE TABLE IF NOT EXISTS _jiangchang_tables ( sort_order INTEGER, visible INTEGER NOT NULL DEFAULT 1, readonly INTEGER NOT NULL DEFAULT 0, - default_sort_json TEXT + default_sort_json TEXT, + default_visible_columns_json TEXT ) """ @@ -89,6 +90,10 @@ def _ensure_jiangchang_tables_columns(cursor) -> None: cols = {str(row[1]) for row in cursor.fetchall()} if "default_sort_json" not in cols: cursor.execute("ALTER TABLE _jiangchang_tables ADD COLUMN default_sort_json TEXT") + if "default_visible_columns_json" not in cols: + cursor.execute( + "ALTER TABLE _jiangchang_tables ADD COLUMN default_visible_columns_json TEXT" + ) def init_display_metadata_tables(cursor) -> None: @@ -106,27 +111,42 @@ def upsert_table_metadata( visible: int = 1, readonly: int = 0, default_sort_json: str | None = None, + default_visible_columns_json: str | None = None, ) -> None: """写入表级元数据。 default_sort_json: 宿主数据管理默认排序,JSON 数组,例如 '[{"column":"sent_at","direction":"desc"},{"column":"id","direction":"desc"}]' 为空则宿主回退到 updated_at → created_at → 主键。 + + default_visible_columns_json: 宿主数据管理默认展示列,JSON 字符串数组,例如 + '["stat_type","period","stage"]' + 为空则全显;用户改过「列」后以本机偏好为准(软默认,区别于 visible=0 硬隐藏)。 """ cursor.execute( """ INSERT INTO _jiangchang_tables ( - table_name, display_name, description, visible, readonly, default_sort_json + table_name, display_name, description, visible, readonly, + default_sort_json, default_visible_columns_json ) - VALUES (?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(table_name) DO UPDATE SET display_name = excluded.display_name, description = excluded.description, visible = excluded.visible, readonly = excluded.readonly, - default_sort_json = excluded.default_sort_json + default_sort_json = excluded.default_sort_json, + default_visible_columns_json = excluded.default_visible_columns_json """, - (table_name, display_name, description, visible, readonly, default_sort_json), + ( + table_name, + display_name, + description, + visible, + readonly, + default_sort_json, + default_visible_columns_json, + ), ) diff --git a/tests/test_display_metadata.py b/tests/test_display_metadata.py index 514b1ae..d51657e 100644 --- a/tests/test_display_metadata.py +++ b/tests/test_display_metadata.py @@ -507,6 +507,54 @@ metadata: self.assertIn("seed_column_metadata_batch", text) self.assertIn("valid_column_names", text) + def test_default_visible_columns_json_upsert_and_migrate(self) -> None: + conn = sqlite3.connect(":memory:") + try: + from db.display_metadata import ( + init_display_metadata_tables, + upsert_table_metadata, + ) + + cur = conn.cursor() + # Simulate pre-1.0.79 table without the new column. + cur.execute( + """ + CREATE TABLE _jiangchang_tables ( + table_name TEXT PRIMARY KEY, + display_name TEXT NOT NULL, + description TEXT, + sort_order INTEGER, + visible INTEGER NOT NULL DEFAULT 1, + readonly INTEGER NOT NULL DEFAULT 0, + default_sort_json TEXT + ) + """ + ) + init_display_metadata_tables(cur) + cur.execute("PRAGMA table_info('_jiangchang_tables')") + cols = {str(row[1]) for row in cur.fetchall()} + self.assertIn("default_visible_columns_json", cols) + + payload = '["stat_type","period","stage"]' + upsert_table_metadata( + cur, + table_name="timeliness_stats", + display_name="时效统计", + readonly=1, + default_visible_columns_json=payload, + ) + conn.commit() + cur.execute( + """ + SELECT default_visible_columns_json + FROM _jiangchang_tables + WHERE table_name = 'timeliness_stats' + """ + ) + self.assertEqual(cur.fetchone()[0], payload) + finally: + conn.close() + if __name__ == "__main__": unittest.main() diff --git a/tests/test_docs_standards.py b/tests/test_docs_standards.py index 3d82da4..32c267b 100644 --- a/tests/test_docs_standards.py +++ b/tests/test_docs_standards.py @@ -344,6 +344,8 @@ class TestDocsStandards(unittest.TestCase): "DEFAULT", "description", "文件 / 图片上传", + "default_visible_columns_json", + "默认展示列", ): self.assertIn(marker, text, msg=f"SCHEMA.md missing {marker!r}")