@loom-framework/core 0.1.0-alpha.178 → 0.1.0-alpha.179

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ Loom 是**配置驱动的 AI 平台开发框架**——你描述需求,AI 通
17
17
 
18
18
  典型使用方式:
19
19
 
20
- 1. **用自然语言描述需求** — 告诉 Claude Code(或其它支持Skill的 Agent) 你要做什么(如"用 loom 开发一个错题管理平台"),Claude Code 会调用本 Skill 读取配置、生成页面、启动服务
20
+ 1. **用自然语言描述需求** — 告诉 Claude Code(或其它支持Skill的 Agent) 你要做什么(如"用 loom 开发一个告警管理平台"),Claude Code 会交互式地向你确认完整需求,然后调用本 Skill 读取配置、生成页面、启动服务
21
21
  2. **对话迭代** — 通过Claude Code 或 创建的项目 AI 对话面板改需求、加字段、调样式,AI 理解 loom 的工作方式,知道何时改配置、何时跑命令、何时直接改代码
22
22
  3. **日常运营** — 通过 AI 对话面板或 `loom data` CLI 查看、创建、更新数据
23
23
 
@@ -96,7 +96,7 @@ loom generate capabilities
96
96
 
97
97
  每次修改数据模型或 AI 按钮后,重新运行此命令即可更新 `references/` 下的自动生成内容,`SKILL.md` 中手动补充的内容不会被覆盖。
98
98
 
99
- 首次生成后,需要补充 `SKILL.md` 主文档中的 TODO 内容,AI 对话时才能正确理解项目业务语义:
99
+ 首次生成项目SKILL后,需要补充其 `SKILL.md` 主文档中的 TODO 内容,AI 对话时才能正确理解项目业务语义:
100
100
 
101
101
  1. **frontmatter `description`**:写入用户在 AI 对话中会说的触发短语。格式参考:
102
102
  ```
@@ -161,7 +161,7 @@ loom dev --frontend-port 8080 # 临时覆盖前端端口
161
161
 
162
162
  **`--force` 重建(默认)**:字段变更时直接 `--force` 重建页面,是最快最干净的方式,页面与配置立即同步。`--force` 会自动将旧页面备份到 `.loom/backup/<时间戳>/` 目录,如需恢复直接复制回来即可。
163
163
 
164
- **AI 增量更新(有定制时)**:如果用户说"保留我的定制"或明确表示页面有手动修改过,才让 AI 增量更新。告诉 AI 你改了什么(如"我在配置里加了一个学期字段"),AI 会精确添加新字段的列和表单项,保留定制代码。如果AI进行了定制化开发,务必将定制化开发内容更新到CLAUDE.md,使得后续新启动会话时Claude Code可掌握项目定制化情况。
164
+ **AI 增量更新(有定制时)**:如果用户说"保留我的定制"或明确表示页面有手动修改过,才让 AI 增量更新。告诉 AI 你改了什么(如"我在配置里加了一个严重等级字段"),AI 会精确添加新字段的列和表单项,保留定制代码。如果AI进行了定制化开发,务必将定制化开发内容更新到CLAUDE.md,使得后续新启动会话时Claude Code可掌握项目定制化情况。
165
165
 
166
166
  ```bash
167
167
  # 只改了 AI 按钮或 enum → 重启后端即可
@@ -255,8 +255,8 @@ export default defineConfig({
255
255
  {
256
256
  id: 'analyze', // 带变量的示例
257
257
  label: { 'zh-CN': '分析', 'en-US': 'Analyze' },
258
- prompt: '分析{{questionContent}},错误答案:{{wrongAnswer}}',
259
- placement: 'wrong_questions', // 可选:限制按钮只出现在指定模型页面,逗号分隔多个模型名;省略则出现在所有页面
258
+ prompt: '分析告警原因:{{description}},当前状态:{{status}}',
259
+ placement: 'alerts', // 可选:限制按钮只出现在指定模型页面,逗号分隔多个模型名;省略则出现在所有页面
260
260
  }],
261
261
  dashboards: [{ // 可选:数据概览,widget/图表类型/筛选配置详见 references/dashboard.md
262
262
  name: 'overview', // 必填:唯一标识
@@ -330,8 +330,8 @@ export default defineConfig({
330
330
 
331
331
  所有面向用户的展示字段均支持 `LocaleString` 格式:`string | Record<string, string>`。
332
332
 
333
- - **简单写法**:`description: '科目'` — 所有语言显示相同文本
334
- - **多语言写法**:`description: { 'zh-CN': '科目', 'en-US': 'Subject' }` — 切换语言时自动翻译
333
+ - **简单写法**:`description: '级别'` — 所有语言显示相同文本
334
+ - **多语言写法**:`description: { 'zh-CN': '级别', 'en-US': 'Level' }` — 切换语言时自动翻译
335
335
  - **enum 值**:`enum` 始终是存储值(不分语言),显示文本通过 `enumLabels` 翻译
336
336
  - **回退规则**:请求的 locale → `'zh-CN'` → 第一个可用值
337
337
 
@@ -22,15 +22,15 @@ Loom 项目的主要交互方式是**和 AI 对话**。你告诉 AI 想要什么
22
22
 
23
23
  ## 第一个项目
24
24
 
25
- 假设你要做一个**错题管理平台**。
25
+ 假设你要做一个**告警管理平台**。
26
26
 
27
27
  ### 第 1 步:告诉 AI 你的想法
28
28
 
29
29
  在 Claude Code 中说:
30
30
 
31
- > 用 loom 创建一个错题管理平台,项目名 wrong-questions,filesystem 适配器。
32
- > 需要两个模型:错题记录(科目、题目内容、错误答案、正确答案、错误类型、是否掌握)和复习计划(错题ID、计划日期、状态)。
33
- > AI 按钮要能分析错因和出类似题。
31
+ > 用 loom 创建一个告警管理平台,项目名 alert-manager,filesystem 适配器。
32
+ > 需要两个模型:告警记录(级别、描述、来源、严重度、状态)和处理记录(告警ID、处理人、处理时间、状态)。
33
+ > AI 按钮要能分析告警根因和生成处置建议。
34
34
 
35
35
  AI 会读取 Loom Skill,自动执行:
36
36
 
@@ -51,9 +51,9 @@ loom dev
51
51
  ```
52
52
 
53
53
  打开 http://localhost:5173 ,你的平台已经能用了:
54
- - 顶部导航有「错题记录」和「复习计划」页面
54
+ - 顶部导航有「告警记录」和「处理记录」页面
55
55
  - 每个页面有新增、编辑、删除、筛选
56
- - 错题记录每行有 AI 按钮:分析错因、出类似题
56
+ - 告警记录每行有 AI 按钮:分析根因、生成处置建议
57
57
  - 右侧 AI 面板可以自然语言操作数据
58
58
 
59
59
  ### 第 3 步:继续和 AI 聊
@@ -62,11 +62,11 @@ loom dev
62
62
 
63
63
  | 你说的 | AI 做的 |
64
64
  |-------|--------|
65
- | "帮我记一道数学错题,3+5=7,正确答案是8" | 用 `loom data write` 创建记录 |
66
- | "看看哪些错题还没掌握" | 查数据并展示 |
65
+ | "帮我记一条告警,服务器CPU过载,当前状态未处理" | 用 `loom data write` 创建记录 |
66
+ | "看看哪些告警还没处理" | 查数据并展示 |
67
67
  | "把这个页面改成卡片布局" | 修改页面 TSX |
68
- | "加一个学期字段" | 改 loom.config.ts + 改页面 + 更新 Skill references |
69
- | "加一个科目分布的饼图" | 修改 Dashboard 页面 |
68
+ | "加一个严重等级字段" | 改 loom.config.ts + 改页面 + 更新 Skill references |
69
+ | "加一个级别分布的饼图" | 修改 Dashboard 页面 |
70
70
 
71
71
  这些操作在终端 Claude Code 和页面对话框里都能做。
72
72
 
@@ -81,7 +81,7 @@ loom dev
81
81
  | 新增数据模型 | 需要生成新页面 | 改配置 → `loom generate capabilities` + `loom generate page <Name> --model <model>` → 重启后端 |
82
82
  | 新增/删除字段 | 需要 | 改配置 → AI 更新页面(推荐)或 `--force` 重建 → `loom generate capabilities` 更新 Skill |
83
83
 
84
- **推荐:AI 辅助迭代**。告诉 AI 你改了什么(比如"我在配置里加了一个学期字段"),AI 会在页面中精确添加新字段的列和表单项,**保留你之前做的视觉定制代码**。
84
+ **推荐:AI 辅助迭代**。告诉 AI 你改了什么(比如"我在配置里加了一个严重等级字段"),AI 会在页面中精确添加新字段的列和表单项,**保留你之前做的视觉定制代码**。
85
85
 
86
86
  **谨慎使用 `--force`**。它会用最新配置全量覆盖页面,之前对页面做的任何定制修改都会丢失。
87
87
 
@@ -89,7 +89,7 @@ loom dev
89
89
  # 只改了 AI 按钮或 enum → 重启后端即可,不用碰页面
90
90
  # 加了新字段 → 让 AI 更新页面
91
91
  # 想重来一个干净页面 → --force
92
- loom generate page WrongQuestions --model wrong_questions --force
92
+ loom generate page Alerts --model alerts --force
93
93
  ```
94
94
 
95
95
  页面不存在时直接 `loom generate page` 即可,不需要 `--force`。
@@ -150,22 +150,22 @@ export default defineConfig({
150
150
 
151
151
  每个项目的 `.claude/skills/<项目名>/SKILL.md` 是 AI 理解你业务的入口。`loom generate capabilities` 生成骨架(`references/` 下的内容自动维护),但 SKILL.md 主文档需要你补充三个地方:
152
152
 
153
- 1. **description**:写用户会说的话,如 `"记录错题", "查看错题", "分析错因"`
153
+ 1. **description**:写用户会说的话,如 `"记录告警", "查看告警", "分析根因"`
154
154
  2. **Overview**:2-3 句话描述平台做什么
155
155
  3. **Usage Scenarios**:5-10 个典型用户请求及对应的 `loom data` 命令
156
156
 
157
- 补充后,AI 在终端和对话框里都能理解"帮我查数学错题"这类业务请求。
157
+ 补充后,AI 在终端和对话框里都能理解"帮我查未处理告警"这类业务请求。
158
158
 
159
159
  ## 数据操作
160
160
 
161
161
  不打开页面也能操作数据。你可以自己跑命令,也可以让 AI 跑:
162
162
 
163
163
  ```bash
164
- loom data read wrong_questions --filter '{"subject":"数学"}' --limit 10
165
- loom data write wrong_questions --data '{"subject":"数学","questionContent":"3+5=?","wrongAnswer":"7","correctAnswer":"8"}'
166
- loom data update wrong_questions --id rec_xxx --data '{"isMastered":true}'
167
- loom data delete wrong_questions --id rec_xxx
168
- loom data schema wrong_questions # 查看字段结构
164
+ loom data read alerts --filter '{"level":"critical"}' --limit 10
165
+ loom data write alerts --data '{"level":"critical","description":"CPU使用率超过95%","source":"monitor","status":"open"}'
166
+ loom data update alerts --id rec_xxx --data '{"status":"resolved"}'
167
+ loom data delete alerts --id rec_xxx
168
+ loom data schema alerts # 查看字段结构
169
169
  ```
170
170
 
171
171
  ## 后端扩展
@@ -47,7 +47,7 @@ export default defineConfig({
47
47
  field: 'score', // aggregate 为 sum/avg/min/max 时必填:数值字段名
48
48
  filter: { status: 'active' }, // 可选:聚合前筛选条件
49
49
  groupBy: 'category', // 可选:分组字段(string/enum/date/boolean)
50
- crossGroupBy: 'grade', // 可选:第二分组字段,用于二维图表
50
+ crossGroupBy: 'source', // 可选:第二分组字段,用于二维图表
51
51
  interval: 'month', // 可选:date 字段分组粒度 minute|hour|day|week|month(默认 month)
52
52
  dateField: 'createdAt', // 可选:单组件日期筛选字段,覆盖 dashboard 级 defaultDateField
53
53
  }]
@@ -61,7 +61,7 @@ export default defineConfig({
61
61
  |------|------|------|
62
62
  | `aggregate` | `count\|sum\|avg\|min\|max\|ratio` | 聚合方式。`ratio` = 符合 filter 条件的记录数/总记录数,用于 gauge/liquid/stat 百分比 |
63
63
  | `field` | string | 聚合目标字段。仅 aggregate 为 sum/avg/min/max 时需要 |
64
- | `filter` | object | 筛选条件,键值对。如 `{isMastered: true}` 筛选已掌握的记录 |
64
+ | `filter` | object | 筛选条件,键值对。如 `{isResolved: true}` 筛选已处理的记录 |
65
65
  | `groupBy` | string | 主分组字段。string/enum 字段按值分组计数;boolean 字段自动映射为"是/否";date 字段按 interval 分段 |
66
66
  | `crossGroupBy` | string | 第二分组维度。配合 groupBy 使用,产生交叉分组数据,用于二维图表 |
67
67
  | `interval` | `minute\|hour\|day\|week\|month` | date 字段的分组粒度,仅 groupBy 指向 date 字段时有效 |
@@ -81,7 +81,7 @@ export default defineConfig({
81
81
  ```typescript
82
82
  {
83
83
  field: 'subject', // 必填:筛选字段名
84
- label: { 'zh-CN': '科目' }, // 必填:显示标签,支持多语言
84
+ label: { 'zh-CN': '级别' }, // 必填:显示标签,支持多语言
85
85
  type: 'select', // 必填:当前仅支持 'select'('dateRange' 已定义但暂未实现)
86
86
  options: ['语文', '数学'], // 可选:select 类型的选项。省略则从数据中自动提取去重值
87
87
  }
@@ -94,11 +94,11 @@ export default defineConfig({
94
94
  ```typescript
95
95
  dashboards: [{
96
96
  name: 'overview',
97
- models: ['wrong_questions'],
97
+ models: ['alerts'],
98
98
  defaultDateField: 'createdAt', // 启用日期范围筛选
99
99
  filterDimensions: [ // 启用 select 下拉筛选(日期范围用 defaultDateField)
100
- { field: 'subject', label: { 'zh-CN': '科目', 'en-US': 'Subject' }, type: 'select' },
101
- { field: 'difficulty', label: { 'zh-CN': '难度', 'en-US': 'Difficulty' }, type: 'select' },
100
+ { field: 'subject', label: { 'zh-CN': '级别', 'en-US': 'Level' }, type: 'select' },
101
+ { field: 'difficulty', label: { 'zh-CN': '严重度', 'en-US': 'Severity' }, type: 'select' },
102
102
  ],
103
103
  layout: [/* ... */],
104
104
  }]
@@ -111,28 +111,28 @@ dashboards: [{
111
111
  | type | 中文名称 | 必填字段 | 典型配置 | 生成效果 |
112
112
  |------|---------|---------|---------|---------|
113
113
  | `stat` | 统计卡片 | — | `{ aggregate: "count" }` 或 `{ aggregate: "avg", field: "score" }` 或 `{ aggregate: "ratio", filter: { passed: true } }` | Ant Design Statistic 数值卡片 |
114
- | `gauge` | 仪表盘 | `aggregate: "ratio"` + `filter` | `{ aggregate: "ratio", filter: { isMastered: true } }` | G2 仪表盘(百分比进度) |
115
- | `liquid` | 水波图 | `aggregate: "ratio"` + `filter` | `{ aggregate: "ratio", filter: { isMastered: true } }` | G2 水波图(百分比进度) |
114
+ | `gauge` | 仪表盘 | `aggregate: "ratio"` + `filter` | `{ aggregate: "ratio", filter: { isResolved: true } }` | G2 仪表盘(百分比进度) |
115
+ | `liquid` | 水波图 | `aggregate: "ratio"` + `filter` | `{ aggregate: "ratio", filter: { isResolved: true } }` | G2 水波图(百分比进度) |
116
116
 
117
- > **说明**:gauge 和 liquid 使用 `aggregate: "ratio"` + `filter` 来计算百分比(如掌握率 = 已掌握数/总数),ratio 自动算出 0-1 之间的值。
117
+ > **说明**:gauge 和 liquid 使用 `aggregate: "ratio"` + `filter` 来计算百分比(如处理率 = 已处理数/总数),ratio 自动算出 0-1 之间的值。
118
118
 
119
119
  #### 占比类 — 展示分布构成
120
120
 
121
121
  | type | 中文名称 | 必填字段 | 典型配置 | 生成效果 |
122
122
  |------|---------|---------|---------|---------|
123
123
  | `pie` | 饼图 | `groupBy` (enum/string) | `{ groupBy: "subject" }` | G2 饼图(分布占比) |
124
- | `ring` | 环形图 | `groupBy` (boolean/enum) | `{ groupBy: "difficulty" }` 或 `{ groupBy: "isMastered" }` | G2 环形图(占比对比,boolean 自动映射"是/否") |
124
+ | `ring` | 环形图 | `groupBy` (boolean/enum) | `{ groupBy: "difficulty" }` 或 `{ groupBy: "isResolved" }` | G2 环形图(占比对比,boolean 自动映射"是/否") |
125
125
  | `treemap` | 矩形树图 | `groupBy` + 可选 `crossGroupBy` | `{ groupBy: "subject" }` 或 `{ groupBy: "subject", crossGroupBy: "difficulty" }` | G2 矩形树图(层级占比,有 crossGroupBy 则两层) |
126
126
 
127
127
  #### 对比类 — 跨类别比较
128
128
 
129
129
  | type | 中文名称 | 必填字段 | 典型配置 | 生成效果 |
130
130
  |------|---------|---------|---------|---------|
131
- | `bar` | 条形图 | `groupBy` | `{ groupBy: "errorType" }` | G2 条形图(横向分类对比) |
132
- | `stacked_bar` | 堆叠条形图 | `groupBy` + `crossGroupBy` | `{ groupBy: "subject", crossGroupBy: "errorType" }` | G2 堆叠条形图(组成+对比) |
131
+ | `bar` | 条形图 | `groupBy` | `{ groupBy: "source" }` | G2 条形图(横向分类对比) |
132
+ | `stacked_bar` | 堆叠条形图 | `groupBy` + `crossGroupBy` | `{ groupBy: "subject", crossGroupBy: "source" }` | G2 堆叠条形图(组成+对比) |
133
133
  | `grouped_bar` | 分组条形图 | `groupBy` + `crossGroupBy` | `{ groupBy: "subject", crossGroupBy: "difficulty" }` | G2 分组条形图(并列对比) |
134
134
  | `radar` | 雷达图 | `groupBy` | `{ groupBy: "subject" }` | G2 雷达图(多维度闭合多边形) |
135
- | `funnel` | 漏斗图 | `groupBy` | `{ groupBy: "errorType" }` | G2 漏斗图(阶段转化,柱条宽度反映数值) |
135
+ | `funnel` | 漏斗图 | `groupBy` | `{ groupBy: "source" }` | G2 漏斗图(阶段转化,柱条宽度反映数值) |
136
136
 
137
137
  #### 趋势类 — 时间维度变化
138
138
 
@@ -146,7 +146,7 @@ dashboards: [{
146
146
  | type | 中文名称 | 必填字段 | 典型配置 | 生成效果 |
147
147
  |------|---------|---------|---------|---------|
148
148
  | `scatter` | 散点图 | `groupBy` | `{ groupBy: "subject" }` | G2 散点图(相关性/分布) |
149
- | `heatmap` | 热力图 | `groupBy` + `crossGroupBy` | `{ groupBy: "subject", crossGroupBy: "grade" }` | G2 热力图(密度/交叉分析,颜色深浅表示数量) |
149
+ | `heatmap` | 热力图 | `groupBy` + `crossGroupBy` | `{ groupBy: "subject", crossGroupBy: "source" }` | G2 热力图(密度/交叉分析,颜色深浅表示数量) |
150
150
 
151
151
  ## 执行 generate dashboard
152
152
 
@@ -171,63 +171,63 @@ cd frontend && pnpm add @antv/g2
171
171
 
172
172
  ## 完整配置示例
173
173
 
174
- 以小学生错题管理平台为例,展示所有 15 种图表的配置:
174
+ 以小学生告警管理平台为例,展示所有 15 种图表的配置:
175
175
 
176
176
  ```typescript
177
177
  import { defineConfig } from '@loom-framework/core';
178
178
 
179
179
  export default defineConfig({
180
- project: { name: 'wrong-questions' },
180
+ project: { name: 'alert-manager' },
181
181
  data: { /* ... */ },
182
182
  dashboards: [{
183
183
  name: 'overview',
184
- description: { 'zh-CN': '错题数据概览', 'en-US': 'Overview' },
185
- models: ['wrong_questions', 'review_plans'],
184
+ description: { 'zh-CN': '告警数据概览', 'en-US': 'Overview' },
185
+ models: ['alerts', 'alert_handlers'],
186
186
  defaultDateField: 'createdAt',
187
187
  filterDimensions: [
188
- { field: 'subject', label: { 'zh-CN': '科目', 'en-US': 'Subject' }, type: 'select' },
189
- { field: 'difficulty', label: { 'zh-CN': '难度', 'en-US': 'Difficulty' }, type: 'select' },
188
+ { field: 'subject', label: { 'zh-CN': '级别', 'en-US': 'Level' }, type: 'select' },
189
+ { field: 'difficulty', label: { 'zh-CN': '严重度', 'en-US': 'Severity' }, type: 'select' },
190
190
  ],
191
191
  layout: [
192
192
  {
193
193
  row: [
194
- { type: 'stat', title: { 'zh-CN': '错题总数', 'en-US': 'Total Questions' }, model: 'wrong_questions', aggregate: 'count', span: 4 },
195
- { type: 'stat', title: { 'zh-CN': '掌握率', 'en-US': 'Mastery Rate' }, model: 'wrong_questions', aggregate: 'ratio', filter: { isMastered: true }, span: 4 },
196
- { type: 'gauge', title: { 'zh-CN': '掌握率仪表盘', 'en-US': 'Mastery Gauge' }, model: 'wrong_questions', aggregate: 'ratio', filter: { isMastered: true }, span: 6 },
197
- { type: 'liquid', title: { 'zh-CN': '掌握率水波图', 'en-US': 'Mastery Liquid' }, model: 'wrong_questions', aggregate: 'ratio', filter: { isMastered: true }, span: 5 },
198
- { type: 'stat', title: { 'zh-CN': '平均复习次数', 'en-US': 'Avg Reviews' }, model: 'wrong_questions', aggregate: 'avg', field: 'reviewCount', span: 5 }
194
+ { type: 'stat', title: { 'zh-CN': '告警总数', 'en-US': 'Total Alerts' }, model: 'alerts', aggregate: 'count', span: 4 },
195
+ { type: 'stat', title: { 'zh-CN': '处理率', 'en-US': 'Resolution Rate' }, model: 'alerts', aggregate: 'ratio', filter: { isResolved: true }, span: 4 },
196
+ { type: 'gauge', title: { 'zh-CN': '处理率仪表盘', 'en-US': 'Resolution Gauge' }, model: 'alerts', aggregate: 'ratio', filter: { isResolved: true }, span: 6 },
197
+ { type: 'liquid', title: { 'zh-CN': '处理率水波图', 'en-US': 'Resolution Liquid' }, model: 'alerts', aggregate: 'ratio', filter: { isResolved: true }, span: 5 },
198
+ { type: 'stat', title: { 'zh-CN': '平均处理时长', 'en-US': 'Avg Resolution Time' }, model: 'alerts', aggregate: 'avg', field: 'resolutionTime', span: 5 }
199
199
  ]
200
200
  },
201
201
  {
202
202
  row: [
203
- { type: 'pie', title: { 'zh-CN': '科目分布', 'en-US': 'By Subject' }, model: 'wrong_questions', groupBy: 'subject', span: 8 },
204
- { type: 'ring', title: { 'zh-CN': '难度分布', 'en-US': 'By Difficulty' }, model: 'wrong_questions', groupBy: 'difficulty', span: 8 },
205
- { type: 'bar', title: { 'zh-CN': '错误类型分布', 'en-US': 'By Error Type' }, model: 'wrong_questions', groupBy: 'errorType', span: 8 }
203
+ { type: 'pie', title: { 'zh-CN': '级别分布', 'en-US': 'By Level' }, model: 'alerts', groupBy: 'subject', span: 8 },
204
+ { type: 'ring', title: { 'zh-CN': '严重度分布', 'en-US': 'By Severity' }, model: 'alerts', groupBy: 'difficulty', span: 8 },
205
+ { type: 'bar', title: { 'zh-CN': '告警来源分布', 'en-US': 'By Source' }, model: 'alerts', groupBy: 'source', span: 8 }
206
206
  ]
207
207
  },
208
208
  {
209
209
  row: [
210
- { type: 'line', title: { 'zh-CN': '错题录入趋势', 'en-US': 'Questions Trend' }, model: 'wrong_questions', groupBy: 'createdAt', interval: 'month', span: 12 },
211
- { type: 'area', title: { 'zh-CN': '复习计划趋势', 'en-US': 'Review Plans Trend' }, model: 'review_plans', groupBy: 'createdAt', interval: 'month', span: 12 }
210
+ { type: 'line', title: { 'zh-CN': '告警趋势', 'en-US': 'Alerts Trend' }, model: 'alerts', groupBy: 'createdAt', interval: 'month', span: 12 },
211
+ { type: 'area', title: { 'zh-CN': '处理记录趋势', 'en-US': 'Handlers Trend' }, model: 'alert_handlers', groupBy: 'createdAt', interval: 'month', span: 12 }
212
212
  ]
213
213
  },
214
214
  {
215
215
  row: [
216
- { type: 'radar', title: { 'zh-CN': '各科目概览', 'en-US': 'Subject Overview' }, model: 'wrong_questions', groupBy: 'subject', span: 8 },
217
- { type: 'stacked_bar', title: { 'zh-CN': '科目×错误类型', 'en-US': 'Subject × Error Type' }, model: 'wrong_questions', groupBy: 'subject', crossGroupBy: 'errorType', span: 8 },
218
- { type: 'grouped_bar', title: { 'zh-CN': '科目×难度', 'en-US': 'Subject × Difficulty' }, model: 'wrong_questions', groupBy: 'subject', crossGroupBy: 'difficulty', span: 8 }
216
+ { type: 'radar', title: { 'zh-CN': '各级别概览', 'en-US': 'Level Overview' }, model: 'alerts', groupBy: 'subject', span: 8 },
217
+ { type: 'stacked_bar', title: { 'zh-CN': '级别×错误类型', 'en-US': 'Level × Error Type' }, model: 'alerts', groupBy: 'subject', crossGroupBy: 'source', span: 8 },
218
+ { type: 'grouped_bar', title: { 'zh-CN': '级别×严重度', 'en-US': 'Level × Severity' }, model: 'alerts', groupBy: 'subject', crossGroupBy: 'difficulty', span: 8 }
219
219
  ]
220
220
  },
221
221
  {
222
222
  row: [
223
- { type: 'scatter', title: { 'zh-CN': '科目分布散点', 'en-US': 'Subject Scatter' }, model: 'wrong_questions', groupBy: 'subject', span: 8 },
224
- { type: 'funnel', title: { 'zh-CN': '错误类型漏斗', 'en-US': 'Error Type Funnel' }, model: 'wrong_questions', groupBy: 'errorType', span: 8 },
225
- { type: 'treemap', title: { 'zh-CN': '科目×难度树图', 'en-US': 'Subject × Difficulty Tree' }, model: 'wrong_questions', groupBy: 'subject', crossGroupBy: 'difficulty', span: 8 }
223
+ { type: 'scatter', title: { 'zh-CN': '级别分布散点', 'en-US': 'Level Scatter' }, model: 'alerts', groupBy: 'subject', span: 8 },
224
+ { type: 'funnel', title: { 'zh-CN': '告警来源漏斗', 'en-US': 'Source Funnel' }, model: 'alerts', groupBy: 'source', span: 8 },
225
+ { type: 'treemap', title: { 'zh-CN': '级别×严重度树图', 'en-US': 'Level × Severity Tree' }, model: 'alerts', groupBy: 'subject', crossGroupBy: 'difficulty', span: 8 }
226
226
  ]
227
227
  },
228
228
  {
229
229
  row: [
230
- { type: 'heatmap', title: { 'zh-CN': '科目×年级热力图', 'en-US': 'Subject × Grade Heatmap' }, model: 'wrong_questions', groupBy: 'subject', crossGroupBy: 'grade', span: 24 }
230
+ { type: 'heatmap', title: { 'zh-CN': '级别×年级热力图', 'en-US': 'Level × Grade Heatmap' }, model: 'alerts', groupBy: 'subject', crossGroupBy: 'source', span: 24 }
231
231
  ]
232
232
  }
233
233
  ]
@@ -243,11 +243,11 @@ export default defineConfig({
243
243
  2. 使用 `/antv-g2-chart` skill 生成 G2 v5 Spec 代码
244
244
  3. 添加 `<DashboardChart spec={...} />` 组件
245
245
 
246
- 示例——追加一个科目×年级的堆叠柱状图:
246
+ 示例——追加一个级别×年级的堆叠柱状图:
247
247
 
248
248
  ```tsx
249
249
  // 在已有的 Dashboard 页面中追加
250
- const subjectGradeData = useCrossGroupChartData(wrongQuestionsList, { groupBy: 'subject', crossGroupBy: 'grade' });
250
+ const levelSourceData = useCrossGroupChartData(alertsList, { groupBy: 'level', crossGroupBy: 'source' });
251
251
 
252
252
  <DashboardChart spec={{
253
253
  type: 'interval',
@@ -79,7 +79,7 @@ aiButtons: [{
79
79
  label: { 'zh-CN': '总结', 'en-US': 'Summarize' }, // required: LocaleString, button text
80
80
  icon: 'FileTextOutlined', // optional: Ant Design icon component name
81
81
  prompt: '请总结以下内容', // required: supports {{var}} placeholders, replaced with current row field values
82
- placement: 'wrong_questions', // optional: limit to specific model pages, comma-separated; omit for all pages
82
+ placement: 'alerts', // optional: limit to specific model pages, comma-separated; omit for all pages
83
83
  }]
84
84
  ```
85
85
 
@@ -99,6 +99,10 @@ ai: {
99
99
  authToken: 'sk-xxx', // optional: ANTHROPIC_AUTH_TOKEN, passed via --settings
100
100
  baseUrl: 'https://api.example.com', // optional: ANTHROPIC_BASE_URL, passed via --settings
101
101
  isDefault: true, // optional: default model for new chats
102
+ tier: "max",
103
+ tags: [
104
+ "自然语言"
105
+ ]
102
106
  },
103
107
  ],
104
108
  },
@@ -148,9 +152,9 @@ ui: {
148
152
  ```typescript
149
153
  relations: [{
150
154
  name: 'question_reviews', // required: unique relation identifier
151
- label: { 'zh-CN': '复习记录', 'en-US': 'Review Records' }, // optional: LocaleString
152
- from: 'wrong_questions', // required: source model name
153
- to: 'review_plans', // required: target model name
155
+ label: { 'zh-CN': '处理记录', 'en-US': 'Handler Records' }, // optional: LocaleString
156
+ from: 'alerts', // required: source model name
157
+ to: 'alert_handlers', // required: target model name
154
158
  foreignKey: 'questionId', // required: foreign key field in target model
155
159
  type: 'hasMany', // required: 'hasOne' | 'hasMany' | 'manyToMany'
156
160
  through: 'enrollments', // optional: pivot model for manyToMany
@@ -215,8 +219,8 @@ enumLabel(schema, 'status', 'active') // → '激活'
215
219
 
216
220
  All user-facing string fields support `LocaleString` format: `string | Record<string, string>`.
217
221
 
218
- - **Simple**: `description: '科目'` — same text for all locales
219
- - **Multi-locale**: `description: { 'zh-CN': '科目', 'en-US': 'Subject' }` — auto-translated on locale switch
222
+ - **Simple**: `description: '级别'` — same text for all locales
223
+ - **Multi-locale**: `description: { 'zh-CN': '级别', 'en-US': 'Level' }` — auto-translated on locale switch
220
224
  - **Fallback**: requested locale → `'zh-CN'` → first available value
221
225
 
222
226
  Supported fields: `project.description`, `ModelSchema.description`, `FieldDefinition.description`, `AIButtonConfig.label`, `DashboardConfig.description`, `DashboardWidget.title`, `RelationConfig.label`, `DashboardFilterDimension.label`
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Login page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/login-page.tsx
6
6
  */
7
7
  export declare function loginPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Login page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/login-page.tsx
6
6
  */
7
7
  export function loginPageTemplate() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Model Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/model-management-page.tsx
6
6
  */
7
7
  export declare function modelManagementPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Model Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/model-management-page.tsx
6
6
  */
7
7
  export function modelManagementPageTemplate() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NotificationCenter page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/NotificationCenter.tsx
6
6
  */
7
7
  export declare function notificationCenterPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NotificationCenter page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/NotificationCenter.tsx
6
6
  */
7
7
  export function notificationCenterPageTemplate() {
@@ -98,6 +98,13 @@ function NotificationCenterPage() {
98
98
  width: 80,
99
99
  render: (type: string) => <Tag color={NOTIFICATION_TYPE_COLORS[type] || 'default'}>{t(\`notification.type.\${type}\`)}</Tag>,
100
100
  },
101
+ {
102
+ title: t('field.createdAt'),
103
+ dataIndex: 'createdAt',
104
+ key: 'createdAt',
105
+ width: 140,
106
+ render: (val: string) => <Tooltip title={new Date(val).toLocaleString(undefined, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}><Typography.Text type="secondary">{formatTime(val)}</Typography.Text></Tooltip>,
107
+ },
101
108
  {
102
109
  title: t('notification.colTitle'),
103
110
  dataIndex: 'title',
@@ -122,13 +129,6 @@ function NotificationCenterPage() {
122
129
  width: 90,
123
130
  render: (source: string) => <Tag color={NOTIFICATION_SOURCE_COLORS[source] || 'default'}>{t(\`notification.source.\${source}\`) || source}</Tag>,
124
131
  },
125
- {
126
- title: t('field.createdAt'),
127
- dataIndex: 'createdAt',
128
- key: 'createdAt',
129
- width: 140,
130
- render: (val: string) => <Typography.Text type="secondary">{formatTime(val)}</Typography.Text>,
131
- },
132
132
  {
133
133
  title: t('common.action'),
134
134
  key: 'action',
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NotificationDetail page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/NotificationDetail.tsx
6
6
  */
7
7
  export declare function notificationDetailPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * NotificationDetail page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/NotificationDetail.tsx
6
6
  */
7
7
  export function notificationDetailPageTemplate() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Process Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/process-management-page.tsx
6
6
  */
7
7
  export declare function processManagementPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Process Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/process-management-page.tsx
6
6
  */
7
7
  export function processManagementPageTemplate() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Skill Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/skill-management-page.tsx
6
6
  */
7
7
  export declare function skillManagementPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Skill Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/components/pages/skill-management-page.tsx
6
6
  */
7
7
  export function skillManagementPageTemplate() {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * User Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/user-management-page.tsx
6
6
  */
7
7
  export declare function userManagementPageTemplate(): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * User Management page template
3
3
  *
4
- * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.178 — DO NOT EDIT MANUALLY.
4
+ * GENERATED by scripts/generate-templates.ts — v0.1.0-alpha.179 — DO NOT EDIT MANUALLY.
5
5
  * Source: packages/frontend-antd/src/auth/user-management-page.tsx
6
6
  */
7
7
  export function userManagementPageTemplate() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loom-framework/core",
3
- "version": "0.1.0-alpha.178",
3
+ "version": "0.1.0-alpha.179",
4
4
  "description": "Loom framework - DataAdapter, Capability Generator, config system, backend server, CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",