Initial commit: OneOS prototype workspace baseline.
Include weekly report and other prototype sources with project tooling config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
48
.claude/skills/canvas-workspace/SKILL.md
Normal file
48
.claude/skills/canvas-workspace/SKILL.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: canvas-workspace
|
||||
description: 当任务涉及 Axhub 画布、Excalidraw 文件、画布节点、批注、截图、画布图片、原型/文档/主题嵌入节点或 AI 生成节点时使用。
|
||||
---
|
||||
|
||||
# Canvas Workspace — 画布工作区
|
||||
|
||||
当任务涉及 Axhub 画布时使用本技能。每个原型拥有自己的 Excalidraw 画布文件:
|
||||
|
||||
```text
|
||||
src/prototypes/<prototype-name>/canvas.excalidraw
|
||||
src/prototypes/<prototype-name>/canvas-assets/
|
||||
```
|
||||
|
||||
本技能用于按 Axhub Make 约定读取和写入画布,重点关注 `customData`、嵌入资源节点、批注、图片文件和 AI 生成节点。
|
||||
|
||||
## 读取顺序
|
||||
|
||||
1. 用户指定画布名或画布链接时,先从名称或链接定位对应的 `canvas.excalidraw`。
|
||||
2. 查看 `elements`、`files` 和元素的 `customData`。
|
||||
3. 只有元素引用了持久化截图或图片文件时,才读取 `canvas-assets/`。
|
||||
4. CLI 用于获取当前浏览器会话信息或截图。
|
||||
|
||||
## 参考文档
|
||||
|
||||
- 文件路径、读写规则、CLI 命令和关系检查:`references/canvas-read-write.md`
|
||||
- Axhub 专属节点和 `customData` 字段:`references/axhub-nodes.md`
|
||||
- Excalidraw 图形结构与布局基础:`references/excalidraw-basics.md`
|
||||
- JSON 元素结构模板:`references/element-templates.md`
|
||||
|
||||
## 默认规则
|
||||
|
||||
- 优先直接编辑 `.excalidraw` JSON。
|
||||
- 元素 `id` 必须唯一,并尽量沿用现有文件的 ID 风格。
|
||||
- 修改元素时同步更新 `version`、`versionNonce` 和 `updated`。
|
||||
- 结构性改动后检查绑定、容器、分组和 Frame 引用。
|
||||
- 除非用户需求要求修改,否则保留已有 Axhub `customData`。
|
||||
- 创建或替换 prototype 预览节点时,画布上的节点尺寸与网页内部视口要分开处理:节点可以用较小可视尺寸避免占满画布,但网页仍按真实浏览器尺寸设计,通过 `customData.embedContentScale` 缩放显示。
|
||||
|
||||
## 回复要求
|
||||
|
||||
完成画布相关工作后,说明:
|
||||
|
||||
- 画布文件路径。
|
||||
- 修改了什么,或读取到了什么。
|
||||
- 相关节点 ID 或批注。
|
||||
- 是否使用了本地图片或 `canvas-assets/`。
|
||||
- 如果当前环境能确定,给出画布确认链接。
|
||||
4
.claude/skills/canvas-workspace/agents/openai.yaml
Normal file
4
.claude/skills/canvas-workspace/agents/openai.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "画布工作区"
|
||||
short_description: "在 Axhub 画布上绘图、构思方案、整理节点,读取批注、截图或图片"
|
||||
default_prompt: "使用 $canvas-workspace 读取或整理 Axhub 画布内容。"
|
||||
155
.claude/skills/canvas-workspace/references/axhub-nodes.md
Normal file
155
.claude/skills/canvas-workspace/references/axhub-nodes.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Axhub 画布节点
|
||||
|
||||
Axhub 画布节点本质上是标准 Excalidraw 元素,Axhub 扩展信息存放在 `customData` 中。
|
||||
|
||||
## 通用字段
|
||||
|
||||
| 字段 | 含义 |
|
||||
| --- | --- |
|
||||
| `customData.title` | 面向用户的节点标题 |
|
||||
| `customData.previewUrl` | 预览模式中渲染的 URL |
|
||||
| `customData.openUrl` | 节点操作中打开的 URL |
|
||||
| `customData.previewKind` | 渲染类型,例如 `web`、`doc`、`image`、`none`、`ai-image-generator`、`prototype-generator` |
|
||||
| `customData.resourceType` | 资源类型:`prototype`、`doc` 或 `theme` |
|
||||
| `customData.resourceId` | 项目 metadata 中的资源 id 或名称 |
|
||||
| `customData.embedViewMode` | `link` 表示紧凑链接卡片,`preview` 表示渲染嵌入预览 |
|
||||
| `customData.embedContentScale` | 预览内容缩放比例,例如 `0.5` 表示画布节点按 50% 显示,但 iframe 使用 2 倍视口渲染 |
|
||||
| `customData.screenshotUrl` | 运行时已捕获的持久化预览截图 URL |
|
||||
| `customData.annotation` | 元素批注文本 |
|
||||
| `customData.annotationUpdatedAt` | 批注更新时间,ISO 8601 格式 |
|
||||
|
||||
## 嵌入资源节点
|
||||
|
||||
嵌入资源使用 `type: "embeddable"`。
|
||||
|
||||
### 原型节点
|
||||
|
||||
通过 `customData.resourceType: "prototype"` 识别;也可以结合指向原型的 `link` 或 `previewUrl` 判断。
|
||||
|
||||
常见字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "embeddable",
|
||||
"link": "/?resourceType=prototype&resourceId=<prototype-id>&view=demo&sidebar=collapsed",
|
||||
"customData": {
|
||||
"title": "原型标题",
|
||||
"previewUrl": "http://localhost:<port>/prototypes/<prototype-id>",
|
||||
"openUrl": "/?resourceType=prototype&resourceId=<prototype-id>&view=demo&sidebar=collapsed",
|
||||
"previewKind": "web",
|
||||
"resourceType": "prototype",
|
||||
"resourceId": "<prototype-id>",
|
||||
"embedViewMode": "link"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
由 AI 原型生成能力产出的原型节点还可能包含:
|
||||
|
||||
```json
|
||||
{
|
||||
"generatedBy": "axhub-prototype-generator",
|
||||
"sourceTaskId": "<task-id>",
|
||||
"prompt": "<prompt>"
|
||||
}
|
||||
```
|
||||
|
||||
### 文档节点
|
||||
|
||||
通过 `customData.type: "axhub-doc"` 或 `customData.resourceType: "doc"` 识别。
|
||||
|
||||
常见字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "embeddable",
|
||||
"link": "/api/markdown-file?path=<encoded-path>",
|
||||
"customData": {
|
||||
"type": "axhub-doc",
|
||||
"title": "文档标题",
|
||||
"previewUrl": "/api/markdown-file?path=<encoded-path>",
|
||||
"previewKind": "doc",
|
||||
"resourceType": "doc",
|
||||
"resourceId": "<doc-id>",
|
||||
"embedViewMode": "link"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 主题节点
|
||||
|
||||
通过 `customData.resourceType: "theme"` 或 `customData.type: "axhub-theme"` 识别。
|
||||
|
||||
主题节点与原型/文档节点使用相同的 `embeddable` 结构,`resourceType` 为 `theme`,`previewKind` 通常为 `web` 或 `none`。
|
||||
|
||||
## AI 生成节点
|
||||
|
||||
AI 生成节点是图片元素。占位图或生成图片数据保存在 `files[fileId]`。
|
||||
|
||||
### AI 图片生成节点
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "image",
|
||||
"fileId": "axhub-ai-image-placeholder-v2",
|
||||
"customData": {
|
||||
"type": "axhub-ai-image-generator",
|
||||
"title": "AI 生成图片",
|
||||
"previewKind": "ai-image-generator"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AI 图片结果节点
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "image",
|
||||
"fileId": "<image-id>",
|
||||
"customData": {
|
||||
"type": "axhub-ai-image",
|
||||
"generatedBy": "axhub-ai-image",
|
||||
"sourceTaskId": "<task-id>",
|
||||
"prompt": "<prompt>",
|
||||
"previewKind": "image"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
多张生成图片可能共享同一个 `groupIds` 值。
|
||||
|
||||
### AI 原型生成节点
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "image",
|
||||
"fileId": "axhub-prototype-generator-placeholder-v1",
|
||||
"customData": {
|
||||
"type": "axhub-prototype-generator",
|
||||
"title": "AI 生成原型",
|
||||
"previewKind": "prototype-generator"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
生成完成后,占位节点会被替换为原型嵌入节点,并带有 `generatedBy: "axhub-prototype-generator"`。
|
||||
|
||||
AI 生成原型替换节点的推荐尺寸:
|
||||
|
||||
- 不要把网页内部布局做小;页面代码仍按正常浏览器视口设计。
|
||||
- `previewUrl`、`openUrl`、`link` 使用客户端原型运行时地址,例如 `/prototypes/<prototypeId>` 或带 hash/page 的同源 runtime URL;不要使用 Make 管理端首页 deep link,例如 `/?p=...` 或 `/?resourceType=prototype...`。
|
||||
- 为了避免画布被完整桌面尺寸占满,推荐生成节点可视尺寸为 `720 x 450`。
|
||||
- 同时设置 `customData.embedSizePreset: "desktop"`、`customData.embedContentScale: 0.5`、`customData.storedPreviewSize: { "width": 720, "height": 450 }`。这样画布显示为 720x450,iframe 与截图按 1440x900 视口渲染。
|
||||
- 新生成的 prototype embeddable 可设置 `customData.captureScreenshotOnMount: true`,让宿主首次渲染后自动捕获预览截图。截图成功后宿主会清除此字段并写入 `screenshotUrl`,不要手写 `screenshotUrl`。
|
||||
|
||||
## 图片文件
|
||||
|
||||
图片元素通过 `files[element.fileId]` 读取图片数据。
|
||||
|
||||
原型嵌入节点如果存在 `customData.screenshotUrl`,优先使用该截图地址。截图文件常见位置:
|
||||
|
||||
```text
|
||||
src/prototypes/<prototype-name>/canvas-assets/embed-<elementId>.png
|
||||
```
|
||||
|
||||
截图缓存不等同于页面实现素材;只有用户明确要求把它作为素材使用时,才把它当作实现资产处理。
|
||||
122
.claude/skills/canvas-workspace/references/canvas-read-write.md
Normal file
122
.claude/skills/canvas-workspace/references/canvas-read-write.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 画布读写能力参考
|
||||
|
||||
面向使用 Skill 的 Agent:优先读写本地 `.excalidraw` 文件。用户指定画布名或画布链接时,直接定位本地画布文件;CLI 用于获取当前浏览器会话信息或截图。
|
||||
|
||||
## 快速判断
|
||||
|
||||
| 目标 | 优先方式 |
|
||||
|------|----------|
|
||||
| 读取画布元素、批注、节点信息 | 直接读 `.excalidraw` |
|
||||
| 修改画布内容 | 直接改 `.excalidraw` |
|
||||
| 从用户给的画布链接定位元素 | 从链接提取画布名和元素 ID,再读文件 |
|
||||
| 获取当前浏览器里画布的截图 | `axhub-make canvas screenshot` |
|
||||
| 查看当前浏览器连接了哪些画布 | `axhub-make canvas info` |
|
||||
|
||||
## 文件位置
|
||||
|
||||
常见路径:
|
||||
|
||||
```text
|
||||
src/prototypes/<prototype-name>/canvas.excalidraw
|
||||
src/prototypes/<prototype-name>/canvas-assets/embed-<elementId>.png
|
||||
```
|
||||
|
||||
`.excalidraw` 是 JSON。主要关注:
|
||||
|
||||
- `elements`:所有画布元素。
|
||||
- `files`:嵌入图片数据或图片元信息。
|
||||
- `appState.gridSize`:整理/对齐时参考。
|
||||
|
||||
## 读取画布
|
||||
|
||||
读取过程以本地 JSON 为准。
|
||||
|
||||
最常用字段:
|
||||
|
||||
| 字段 | 用途 |
|
||||
|------|------|
|
||||
| `id` | 元素唯一标识,链接定位和截图文件名会用到 |
|
||||
| `type` | 元素类型,如 `text`、`image`、`embeddable`、`arrow` |
|
||||
| `x` / `y` / `width` / `height` | 位置和尺寸 |
|
||||
| `isDeleted` | 为 true 时跳过 |
|
||||
| `link` | 嵌入节点链接 |
|
||||
| `customData` | 批注、标题、截图地址等 Axhub 扩展信息 |
|
||||
| `fileId` | 图片元素对应的 `files[fileId]` |
|
||||
|
||||
识别常见节点:
|
||||
|
||||
| 类型 | 判断方式 |
|
||||
|------|----------|
|
||||
| 原型节点 | `type == "embeddable"` 且 `customData.resourceType == "prototype"`,或 `link`/`previewUrl` 指向原型 |
|
||||
| 文档节点 | `type == "embeddable"` 且 `customData.type == "axhub-doc"` 或 `customData.resourceType == "doc"` |
|
||||
| 主题节点 | `type == "embeddable"` 且 `customData.resourceType == "theme"` 或 `customData.type == "axhub-theme"` |
|
||||
| AI 图片生成节点 | `type == "image"` 且 `customData.type == "axhub-ai-image-generator"` |
|
||||
| AI 图片结果节点 | `type == "image"` 且 `customData.type == "axhub-ai-image"` |
|
||||
| AI 原型生成节点 | `type == "image"` 且 `customData.type == "axhub-prototype-generator"` |
|
||||
| 图片元素 | `type == "image"` |
|
||||
| 批注元素 | `customData.annotation` 有值 |
|
||||
|
||||
Axhub 节点字段见 `axhub-nodes.md`。
|
||||
|
||||
## CLI 读取
|
||||
|
||||
CLI 面向当前浏览器会话。读取元素、节点和批注时仍以 `.excalidraw` 文件为准。
|
||||
|
||||
查看当前浏览器连接的画布:
|
||||
|
||||
```bash
|
||||
axhub-make canvas info
|
||||
```
|
||||
|
||||
获取当前画布截图:
|
||||
|
||||
```bash
|
||||
axhub-make canvas screenshot -o ./canvas.png
|
||||
axhub-make canvas screenshot -c prototypes/my-proto/canvas -o ./canvas.png
|
||||
```
|
||||
|
||||
## 从链接定位
|
||||
|
||||
用户可能给一个带节点 ID 的画布链接。处理步骤:
|
||||
|
||||
1. 从 URL 中提取画布名和元素 ID。
|
||||
2. 找到对应 `.excalidraw` 文件。
|
||||
3. 在 `elements` 中找同 ID 元素。
|
||||
4. 如果是原型节点,预览截图通常在 `canvas-assets/embed-<elementId>.png`。
|
||||
5. 如果是图片元素,按 `fileId` 找 `files[fileId]`。
|
||||
6. 如果是嵌入节点,结合 `customData.resourceType`、`customData.previewUrl` 和 `customData.screenshotUrl` 判断资源来源。
|
||||
|
||||
## 写入画布
|
||||
|
||||
直接修改 `.excalidraw` 的 `elements` 数组。
|
||||
|
||||
### 添加元素
|
||||
|
||||
追加到 `elements`。必须有唯一 `id`,推荐沿用现有格式:`<timestamp>-<random>`。
|
||||
|
||||
### 修改元素
|
||||
|
||||
更新目标字段后,同时更新:
|
||||
|
||||
- `version` 加 1
|
||||
- `versionNonce` 换成新的随机整数
|
||||
- `updated` 设为当前毫秒时间戳
|
||||
|
||||
### 删除元素
|
||||
|
||||
默认直接从 `elements` 中移除。不要为了删除而设置 `isDeleted: true`,这会让画布文件持续膨胀。
|
||||
|
||||
如果遇到历史遗留的 `isDeleted: true` 元素,读取时跳过;整理画布时可以一并移除。
|
||||
|
||||
### 关系检查
|
||||
|
||||
修改连接、容器、分组时检查引用是否仍然存在:
|
||||
|
||||
- `boundElements`
|
||||
- `containerId`
|
||||
- `startBinding` / `endBinding`
|
||||
- `groupIds`
|
||||
|
||||
## 热更新
|
||||
|
||||
保存 `.excalidraw` 后,打开中的画布会通过热更新同步。完成画布写入时,交付说明里标明画布文件路径和改动内容。
|
||||
234
.claude/skills/canvas-workspace/references/element-templates.md
Normal file
234
.claude/skills/canvas-workspace/references/element-templates.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# Excalidraw 元素模板
|
||||
|
||||
只记录 Agent 写画布时最常用的最小字段。不要复制过大的完整元素样例;优先沿用现有画布里的同类元素字段,再按这里补关键字段。
|
||||
|
||||
## 通用规则
|
||||
|
||||
- 每个元素必须有唯一 `id`,推荐 `<timestamp>-<random>`。
|
||||
- 新元素设置 `version: 1`、新的 `versionNonce`、当前毫秒 `updated`。
|
||||
- 默认 `roughness: 0`、`opacity: 100`、`strokeStyle: "solid"`。
|
||||
- 删除元素时直接从 `elements` 移除,不新写 `isDeleted: true`。
|
||||
- 修改绑定、容器、分组时同步检查引用是否存在。
|
||||
|
||||
## 基础形状
|
||||
|
||||
矩形、椭圆、菱形共用这类结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "rectangle",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 200,
|
||||
"height": 100,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#a5d8ff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"roundness": { "type": 3 },
|
||||
"seed": 100001,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"boundElements": null,
|
||||
"link": null,
|
||||
"locked": false
|
||||
}
|
||||
```
|
||||
|
||||
把 `type` 改为 `ellipse` 或 `diamond` 即可。圆角:直角用 `roundness: null`,圆角用 `{ "type": 3 }`。
|
||||
|
||||
## 文本
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "text",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 220,
|
||||
"height": 28,
|
||||
"text": "标题",
|
||||
"originalText": "标题",
|
||||
"fontSize": 20,
|
||||
"fontFamily": 3,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"seed": 100002,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null
|
||||
}
|
||||
```
|
||||
|
||||
`text` 和 `originalText` 保持一致,且只放纯文本。
|
||||
|
||||
## 箭头与线
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "arrow",
|
||||
"x": 300,
|
||||
"y": 150,
|
||||
"width": 200,
|
||||
"height": 0,
|
||||
"points": [[0, 0], [200, 0]],
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"strokeColor": "#1e1e1e",
|
||||
"strokeWidth": 2,
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"seed": 100003,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null
|
||||
}
|
||||
```
|
||||
|
||||
线条用 `type: "line"`,并把 `endArrowhead` 设为 `null`。
|
||||
|
||||
绑定到元素时:
|
||||
|
||||
```json
|
||||
{
|
||||
"startBinding": { "elementId": "<source-id>", "focus": 0, "gap": 1 },
|
||||
"endBinding": { "elementId": "<target-id>", "focus": 0, "gap": 1 }
|
||||
}
|
||||
```
|
||||
|
||||
同时在被绑定元素的 `boundElements` 中添加箭头引用。
|
||||
|
||||
## 原型节点
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "embeddable",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 1440,
|
||||
"height": 900,
|
||||
"link": "/?resourceType=prototype&resourceId=<prototype-id>&view=demo&sidebar=collapsed",
|
||||
"customData": {
|
||||
"title": "原型标题",
|
||||
"previewUrl": "http://localhost:<port>/prototypes/<prototype-id>",
|
||||
"openUrl": "/?resourceType=prototype&resourceId=<prototype-id>&view=demo&sidebar=collapsed",
|
||||
"previewKind": "web",
|
||||
"resourceType": "prototype",
|
||||
"resourceId": "<prototype-id>",
|
||||
"embedViewMode": "link",
|
||||
"embedSizePreset": "desktop"
|
||||
},
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"roundness": { "type": 3 },
|
||||
"seed": 200001,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"boundElements": null
|
||||
}
|
||||
```
|
||||
|
||||
截图字段由运行时维护。不要手写 `screenshotUrl`,除非正在修复已有截图缓存。
|
||||
|
||||
## 文档节点
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "embeddable",
|
||||
"x": 500,
|
||||
"y": 100,
|
||||
"width": 420,
|
||||
"height": 640,
|
||||
"link": "/api/markdown-file?path=<url-encoded-absolute-path>",
|
||||
"customData": {
|
||||
"type": "axhub-doc",
|
||||
"title": "文档标题",
|
||||
"previewUrl": "/api/markdown-file?path=<url-encoded-absolute-path>",
|
||||
"previewKind": "doc",
|
||||
"resourceType": "doc",
|
||||
"resourceId": "<doc-id>",
|
||||
"embedViewMode": "link"
|
||||
},
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"roundness": { "type": 3 },
|
||||
"seed": 300001,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"boundElements": null
|
||||
}
|
||||
```
|
||||
|
||||
`path` 参数必须 URL 编码。
|
||||
|
||||
## Frame
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<id>",
|
||||
"type": "frame",
|
||||
"x": 80,
|
||||
"y": 80,
|
||||
"width": 600,
|
||||
"height": 400,
|
||||
"name": "功能模块",
|
||||
"strokeColor": "#bbb",
|
||||
"backgroundColor": "transparent",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"seed": 400001,
|
||||
"version": 1,
|
||||
"versionNonce": 1234567890,
|
||||
"updated": 1778336862857,
|
||||
"groupIds": [],
|
||||
"frameId": null
|
||||
}
|
||||
```
|
||||
|
||||
子元素通过 `frameId` 引用 frame 的 `id`。
|
||||
|
||||
## 批注
|
||||
|
||||
给任意元素补:
|
||||
|
||||
```json
|
||||
{
|
||||
"customData": {
|
||||
"annotation": "这里需要确认",
|
||||
"annotationUpdatedAt": "2026-05-11T09:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# Excalidraw 基础指导
|
||||
|
||||
这份只说明如何把内容组织成 Excalidraw 图,不规定 Axhub 画布流程。基础思路参考 `excalidraw-diagram-generator`:先判断图类型,再抽取元素、关系和复杂度,最后生成清晰布局。
|
||||
|
||||
参考来源:https://www.skills.sh/github/awesome-copilot/excalidraw-diagram-generator
|
||||
|
||||
## 先判断图类型
|
||||
|
||||
| 用户意图 | 适合图形 |
|
||||
|----------|----------|
|
||||
| 流程、步骤、审批、状态流转 | 流程图 |
|
||||
| 模块关系、依赖、信息结构 | 关系图 |
|
||||
| 概念拆解、头脑风暴 | 思维导图 |
|
||||
| 系统、页面、组件、服务结构 | 架构图 |
|
||||
| 数据输入、处理、输出 | 数据流图 |
|
||||
| 多角色协作流程 | 泳道图 |
|
||||
|
||||
如果画布内容涉及真实图片、UI 设计稿或素材,先按用户目标确认它是画布参考、画布节点,还是项目实现素材。
|
||||
|
||||
## 抽取信息
|
||||
|
||||
动手画之前先明确:
|
||||
|
||||
- 关键元素:节点、步骤、角色、页面、模块。
|
||||
- 关系:先后、依赖、父子、输入输出、跳转。
|
||||
- 复杂度:元素太多时拆成多个 Frame 或多张图。
|
||||
- 主次:优先画主路径,细节放到旁边补充。
|
||||
|
||||
## 布局原则
|
||||
|
||||
- 流程图:从左到右或从上到下。
|
||||
- 关系图:核心元素居中,相关元素围绕或分组。
|
||||
- 架构图:按层级、职责或数据流分区。
|
||||
- 思维导图:中心主题 + 4-6 个主分支。
|
||||
- 泳道图:角色用列或行,活动放进对应泳道。
|
||||
|
||||
相关内容使用 Frame 分组,组内元素用 `frameId` 归属到对应 Frame。
|
||||
|
||||
## 控制复杂度
|
||||
|
||||
- 单张图优先控制在 20 个核心元素以内。
|
||||
- 复杂请求先画高层图,再按模块拆详细图。
|
||||
- 避免把长文档逐句搬进画布;画结构和决策点。
|
||||
- 颜色只表达语义,不做装饰。
|
||||
|
||||
## 与 Axhub 规范的边界
|
||||
|
||||
- 画布文件仍写入 `src/prototypes/<prototype-name>/canvas.excalidraw`。
|
||||
- 字体、颜色、节点、资源和交付口径仍按本技能主文档与其他 references 执行。
|
||||
Reference in New Issue
Block a user