first commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# DWS OpenNodes V1 协议说明
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
> 协议版本:`schemaVersion = "1.0"`,`catalogVersion = "dml-v1"`。
|
||||
|
||||
## 1. 协议用途
|
||||
|
||||
OpenNodes 是 DWS 白板命令使用的语义节点协议,提供两类能力:
|
||||
|
||||
- `dws whiteboard query`:返回稳定、可理解的页面和节点数据。
|
||||
- `dws whiteboard update`:接收受约束的节点描述,以 `append` 或
|
||||
`overwrite` 模式修改白板。
|
||||
|
||||
调用方只应依赖本文声明的语义字段和行为:
|
||||
|
||||
- `query` 不修改白板。
|
||||
- `update` 全部成功或全部回滚,不返回中间状态。
|
||||
- 未声明的存储字段、类型名称和处理过程不属于协议承诺。
|
||||
|
||||
OpenNodes V1 支持的节点类型、字段和读写范围见第 7 节。
|
||||
|
||||
DWS 负责身份认证和权限校验。Vector 资源准备使用 `dws doc media upload`,
|
||||
具体流程见白板命令参考。
|
||||
|
||||
## 2. 版本与兼容原则
|
||||
|
||||
| 字段 | 当前值 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| `schemaVersion` | `1.0` | 控制文档结构、节点字段和字段语义。 |
|
||||
| `catalogVersion` | `dml-v1` | 控制允许写入的 DML 几何、连接线标记和内置 icon 目录。 |
|
||||
|
||||
V1 采用严格校验:
|
||||
|
||||
- 必填字段缺失会失败。
|
||||
- 未声明字段会失败,不会被静默忽略。
|
||||
- query-only 字段出现在 update 中会以 `readOnlyField` 失败。
|
||||
- 不支持的节点类型、目录值或引用范围会失败。
|
||||
- `null` 不代表“使用默认值”;除非字段类型明确允许,否则会失败。
|
||||
|
||||
本文列出的请求枚举值都是协议字面量,调用方必须按文档中的大小写和拼写原样传入,
|
||||
不能自行转换或猜测。响应中未来可能增加可选字段,调用方应忽略不认识的响应字段。
|
||||
|
||||
调用方必须原样携带当前版本值。新增不兼容结构时应升级
|
||||
`schemaVersion`;修改 DML、marker 或 icon 目录时应评估并升级
|
||||
`catalogVersion`。
|
||||
|
||||
## 3. DWS 命令一览
|
||||
|
||||
| 命令 | 所需权限 | 效果 |
|
||||
| --- | --- | --- |
|
||||
| `dws whiteboard query --node ... --part-id ...` | 可查看白板 | 读取单页白板,不修改内容。 |
|
||||
| `dws whiteboard update --node ... --part-id ... --source ... --yes` | 可编辑白板 | 追加节点或整页重建;所有更新都需先取得用户确认。 |
|
||||
|
||||
DWS 当前只支持文字文档中已有的单页内嵌白板。命令不接收 `pageId`,也不提供
|
||||
创建页面、切换页面或按既有节点 ID 局部修改的能力。
|
||||
@@ -0,0 +1,288 @@
|
||||
# OpenNodes V1 — Query 请求、返回结构和节点公共字段
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
## 4. Query 协议
|
||||
|
||||
### 4.1 请求
|
||||
|
||||
```bash
|
||||
dws whiteboard query \
|
||||
--node <DOC_NODE_ID> \
|
||||
--part-id <WHITEBOARD_PART_ID> \
|
||||
--format json
|
||||
```
|
||||
|
||||
`query` 不接收请求体或 `pageId`。`--node` 和 `--part-id` 的发现规则见
|
||||
[白板命令参考](../../whiteboard.md)。CLI 会把服务返回的 `resultJson` JSON
|
||||
字符串解析成对象。
|
||||
|
||||
### 4.2 返回结构
|
||||
|
||||
```ts
|
||||
interface OpenNodesDocument {
|
||||
schemaVersion: "1.0";
|
||||
catalogVersion: "dml-v1";
|
||||
pages: OpenPage[];
|
||||
}
|
||||
|
||||
interface OpenPage {
|
||||
id: string;
|
||||
nodes: OpenNode[];
|
||||
}
|
||||
```
|
||||
|
||||
DWS 当前只支持单页白板,因此 `pages` 固定包含一个页面。调用方仍应从返回值读取
|
||||
页面 `id`,但不能把它作为 `pageId` 传给 DWS 命令。
|
||||
|
||||
母版节点不会作为独立页面返回,而会合并到引用它的页面 `nodes` 中,并带有:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "master",
|
||||
"writeSupport": "readOnly",
|
||||
"unsupportedFeatures": ["node.source.master"]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 节点公共字段
|
||||
|
||||
`type` 的完整公开枚举如下。前一组可由 update 创建,后一组仅供 query 返回:
|
||||
|
||||
```ts
|
||||
type WritableOpenNodeType =
|
||||
| "shape"
|
||||
| "text"
|
||||
| "connector"
|
||||
| "stickyNote"
|
||||
| "frame"
|
||||
| "group"
|
||||
| "vector"
|
||||
| "icon"
|
||||
| "path";
|
||||
|
||||
type ReadOnlyOpenNodeType =
|
||||
| "image"
|
||||
| "pdf"
|
||||
| "media"
|
||||
| "webLink"
|
||||
| "table"
|
||||
| "chart"
|
||||
| "uml"
|
||||
| "swimlane"
|
||||
| "mind"
|
||||
| "timer"
|
||||
| "placeholder"
|
||||
| "unknown";
|
||||
|
||||
type OpenNodeType = WritableOpenNodeType | ReadOnlyOpenNodeType;
|
||||
```
|
||||
|
||||
每个 query 节点都包含以下公共字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `string` | 白板中真实、稳定的节点 ID。 |
|
||||
| `type` | `OpenNodeType` | OpenNodes 公开语义类型,取值见上方枚举。 |
|
||||
| `parentId` | `string?` | group/frame 父节点 ID。无父节点时省略。 |
|
||||
| `children` | `string[]?` | group/frame 的直接子节点 ID,由服务端推导。 |
|
||||
| `x`、`y` | `number` | 有父节点时相对父节点;否则相对页面。单位为 px。 |
|
||||
| `width`、`height` | `number` | 节点包围盒尺寸,单位为 px。连接线允许其中一个为 `0`。 |
|
||||
| `angle` | `number` | 归一化到 `[0, 360)` 的角度。 |
|
||||
| `absoluteBounds` | `OpenBounds` | 页面坐标系中的绝对包围盒。 |
|
||||
| `layer` | `background \| normal \| foreground` | 节点所在层。 |
|
||||
| `zIndex` | `number` | 同一父节点、同一 layer 内的非负顺序,值越小越靠后。 |
|
||||
| `hidden` | `boolean` | 节点是否隐藏。 |
|
||||
| `locked` | `boolean` | 节点是否锁定。 |
|
||||
| `source` | `page \| master` | 节点来自当前页面还是母版。 |
|
||||
| `writeSupport` | `readWrite \| readOnly` | 当前节点能否由 V1 update 表达。 |
|
||||
| `unsupportedFeatures` | `string[]?` | 只读原因;`readWrite` 节点省略。 |
|
||||
|
||||
公共结构和各节点分支定义如下;分支中的字段含义与写入限制见第 7 节:
|
||||
|
||||
```ts
|
||||
interface OpenPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface OpenBounds {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
angle: number;
|
||||
}
|
||||
|
||||
interface OpenNodeBase {
|
||||
id: string;
|
||||
type: OpenNodeType;
|
||||
parentId?: string;
|
||||
children?: string[];
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
angle: number;
|
||||
absoluteBounds: OpenBounds;
|
||||
layer: "background" | "normal" | "foreground";
|
||||
zIndex: number;
|
||||
hidden: boolean;
|
||||
locked: boolean;
|
||||
source: "page" | "master";
|
||||
writeSupport: "readWrite" | "readOnly";
|
||||
unsupportedFeatures?: string[];
|
||||
}
|
||||
|
||||
interface OpenShapeNode extends OpenNodeBase {
|
||||
type: "shape";
|
||||
geometry: `dml:${string}`;
|
||||
adjustments?: Record<string, number>;
|
||||
text?: OpenText;
|
||||
style?: OpenNodeStyle;
|
||||
}
|
||||
|
||||
interface OpenTextNode extends OpenNodeBase {
|
||||
type: "text";
|
||||
text: OpenText;
|
||||
style?: OpenNodeStyle;
|
||||
}
|
||||
|
||||
interface OpenConnectorNode extends OpenNodeBase {
|
||||
type: "connector";
|
||||
start: OpenConnectorEndpoint;
|
||||
end: OpenConnectorEndpoint;
|
||||
routing: OpenConnectorRouting;
|
||||
waypoints?: OpenPoint[];
|
||||
style?: OpenNodeStyle;
|
||||
resolvedPath: OpenResolvedConnectorPath;
|
||||
}
|
||||
|
||||
interface OpenStickyNoteNode extends OpenNodeBase {
|
||||
type: "stickyNote";
|
||||
text?: OpenText;
|
||||
style?: OpenNodeStyle;
|
||||
creator?: {
|
||||
displayName?: string;
|
||||
hasAvatar?: boolean;
|
||||
};
|
||||
tags?: Array<{
|
||||
id: string;
|
||||
text: string;
|
||||
background: OpenPaint;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface OpenFrameNode extends OpenNodeBase {
|
||||
type: "frame";
|
||||
title?: {
|
||||
text: OpenText;
|
||||
box: { width: number; height: number };
|
||||
};
|
||||
style?: OpenNodeStyle;
|
||||
presentationOrder?: number;
|
||||
resizeMode: "free" | "fixedAspectRatio";
|
||||
}
|
||||
|
||||
interface OpenGroupNode extends OpenNodeBase {
|
||||
type: "group";
|
||||
children: string[];
|
||||
}
|
||||
|
||||
interface OpenVectorNode extends OpenNodeBase {
|
||||
type: "vector";
|
||||
resource: OpenVectorResource;
|
||||
}
|
||||
|
||||
interface OpenIconNode extends OpenNodeBase {
|
||||
type: "icon";
|
||||
catalogId: string;
|
||||
}
|
||||
|
||||
interface OpenPathNode extends OpenNodeBase {
|
||||
type: "path";
|
||||
path: OpenPathData;
|
||||
style?: OpenNodeStyle;
|
||||
}
|
||||
|
||||
interface OpenReadOnlyNode extends OpenNodeBase {
|
||||
type: ReadOnlyOpenNodeType;
|
||||
writeSupport: "readOnly";
|
||||
unsupportedFeatures: string[];
|
||||
}
|
||||
|
||||
type OpenNode =
|
||||
| OpenShapeNode
|
||||
| OpenTextNode
|
||||
| OpenConnectorNode
|
||||
| OpenStickyNoteNode
|
||||
| OpenFrameNode
|
||||
| OpenGroupNode
|
||||
| OpenVectorNode
|
||||
| OpenIconNode
|
||||
| OpenPathNode
|
||||
| OpenReadOnlyNode;
|
||||
```
|
||||
|
||||
query 中 `icon.catalogId` 使用 `string`,是为了让无法映射到当前目录的既有图标仍可
|
||||
被诊断;update 只能传入 7.10 节 `OpenIconCatalogId` 中列出的值。
|
||||
|
||||
### 4.4 Query 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"pages": [
|
||||
{
|
||||
"id": "page",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "real-node-id",
|
||||
"type": "text",
|
||||
"x": 120,
|
||||
"y": 80,
|
||||
"width": 240,
|
||||
"height": 48,
|
||||
"angle": 0,
|
||||
"absoluteBounds": {
|
||||
"x": 120,
|
||||
"y": 80,
|
||||
"width": 240,
|
||||
"height": 48,
|
||||
"angle": 0
|
||||
},
|
||||
"layer": "normal",
|
||||
"zIndex": 0,
|
||||
"hidden": false,
|
||||
"locked": false,
|
||||
"source": "page",
|
||||
"writeSupport": "readWrite",
|
||||
"text": {
|
||||
"blocks": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"horizontalAlign": "left",
|
||||
"runs": [
|
||||
{
|
||||
"text": "Hello OpenNodes",
|
||||
"marks": {
|
||||
"fontSize": 16,
|
||||
"color": "#223344"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"verticalAlign": "center",
|
||||
"padding": [2, 4],
|
||||
"plainText": "Hello OpenNodes",
|
||||
"writeSupport": "readWrite"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,249 @@
|
||||
# OpenNodes V1 — Update 信封、Append/Overwrite 和公共写入字段
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
## 5. Update 协议
|
||||
|
||||
### 5.1 请求信封
|
||||
|
||||
```ts
|
||||
interface OpenNodesUpdateRequest {
|
||||
overwrite?: boolean;
|
||||
source: {
|
||||
schemaVersion: "1.0";
|
||||
catalogVersion: "dml-v1";
|
||||
nodes: OpenNodeWrite[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
字段含义:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `overwrite` | 否 | `false` 或省略为 append;`true` 为 overwrite。 |
|
||||
| `source.schemaVersion` | 是 | 必须为 `1.0`。 |
|
||||
| `source.catalogVersion` | 是 | 必须为 `dml-v1`。 |
|
||||
| `source.nodes` | 是 | 本次创建的节点数组。append 至少一个;overwrite 允许空数组。 |
|
||||
|
||||
`source` 不能直接使用 query 返回的 `OpenNodesDocument`,也不接受 `pages`。
|
||||
DWS 不接受 `pageId`;传入会在 CLI 本地校验阶段失败。
|
||||
|
||||
V1 没有“按真实节点 ID patch 既有节点”的语义。`source.nodes` 中的每一项都会
|
||||
创建一个新节点,`id` 仅是本次请求内建立父子关系和连接线引用的临时 ID:
|
||||
append 是新增节点,overwrite 是整页删除后重新创建。
|
||||
|
||||
### 5.2 Append 与 Overwrite
|
||||
|
||||
> **注意:** `overwrite: true` 是破坏性操作,会删除当前白板页面的全部自有
|
||||
> 节点。调用前应先 query 并确认影响范围;`nodes: []` 会清空页面。不希望删除
|
||||
> 既有内容时,应使用 append。
|
||||
|
||||
| 行为 | append | overwrite |
|
||||
| --- | --- | --- |
|
||||
| `overwrite` | `false` 或省略 | `true` |
|
||||
| 空 `nodes` | 禁止 | 允许,用于清空当前页面 |
|
||||
| 当前页面旧节点 | 全部保留 | 删除页面自有节点后创建新节点 |
|
||||
| 母版节点 | 保留 | 保留 |
|
||||
| 页面级设置 | 保留 | 保留 |
|
||||
| 原子性 | 全部成功或全部回滚 | 全部成功或全部回滚 |
|
||||
|
||||
overwrite 会替换当前页面的全部自有节点,不要求旧节点本身可由 OpenNodes V1
|
||||
写入。因此页面中存在 image、PDF、复杂文本等只读节点,不会单独阻止清空页面。
|
||||
|
||||
overwrite 会在删除前执行安全预检;以下情况会拒绝执行:
|
||||
|
||||
- 节点被锁定:`lockedNode`。
|
||||
- 节点不允许被删除:`deleteForbidden`。
|
||||
- 页面包含无法安全保留或清理的关联数据:`unknownMetadataReference`。
|
||||
- 目标节点未能完整删除:`deleteFailed`。
|
||||
|
||||
与被删除节点绑定且有明确清理规则的关联数据会随节点清理;无法安全保留或清理的
|
||||
关联数据会使 overwrite 失败。
|
||||
|
||||
overwrite 只替换当前页面节点,不会重建页面,也不会修改主题等页面级设置。
|
||||
白板已有的主题会被保留;白板没有有效主题时也不会自动添加。调用方应使用
|
||||
已配置有效主题的白板,或者显式提供不依赖主题的颜色。
|
||||
|
||||
### 5.3 成功结果
|
||||
|
||||
```ts
|
||||
interface DWSWhiteboardUpdateResponse {
|
||||
success: true;
|
||||
nodeId: string;
|
||||
partId: string;
|
||||
resultJson: {
|
||||
mode: "append" | "overwrite";
|
||||
createdNodeIds: string[];
|
||||
idMap: Record<string, string>;
|
||||
deletedNodeCount: number;
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| `success` | `true` 表示本次 DWS 调用成功。 |
|
||||
| `nodeId` | 输入的文档节点 ID。 |
|
||||
| `partId` | 输入的白板标识。 |
|
||||
| `resultJson.mode` | 实际执行的模式。 |
|
||||
| `resultJson.createdNodeIds` | 按请求节点顺序返回真实节点 ID。 |
|
||||
| `resultJson.idMap` | 请求中显式临时 ID 到真实节点 ID 的映射。 |
|
||||
| `resultJson.deletedNodeCount` | append 恒为 `0`;overwrite 为删除的页面自有节点数。 |
|
||||
| `resultJson.message` | 供人阅读的结果摘要,不应作为机器判断依据。 |
|
||||
|
||||
响应可能增加其他可选字段;Agent 不应依赖本节未声明的字段。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"nodeId": "DOC_NODE_ID",
|
||||
"partId": "WHITEBOARD_PART_ID",
|
||||
"resultJson": {
|
||||
"mode": "append",
|
||||
"createdNodeIds": ["generated-title-id", "generated-body-id"],
|
||||
"idMap": {
|
||||
"title": "generated-title-id",
|
||||
"body": "generated-body-id"
|
||||
},
|
||||
"deletedNodeCount": 0,
|
||||
"message": "Created 2 Whiteboard nodes"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. Update 公共节点字段
|
||||
|
||||
V1 可写节点公共字段如下:
|
||||
|
||||
```ts
|
||||
interface OpenNodeWriteBase {
|
||||
id?: string;
|
||||
layer?: "background" | "normal" | "foreground";
|
||||
zIndex?: number;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
interface OpenChildNodeWriteBase extends OpenNodeWriteBase {
|
||||
parentId?: string;
|
||||
}
|
||||
|
||||
interface OpenSizedNodeWriteBase extends OpenChildNodeWriteBase {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
angle?: number;
|
||||
}
|
||||
|
||||
interface OpenShapeNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "shape";
|
||||
geometry: `dml:${string}`;
|
||||
text?: OpenTextWrite;
|
||||
style?: OpenNodeStyleWrite;
|
||||
}
|
||||
|
||||
interface OpenTextNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "text";
|
||||
text: OpenTextWrite;
|
||||
style?: OpenNodeStyleWrite;
|
||||
}
|
||||
|
||||
interface OpenConnectorNodeWrite extends OpenNodeWriteBase {
|
||||
type: "connector";
|
||||
start: OpenConnectorEndpointWrite;
|
||||
end: OpenConnectorEndpointWrite;
|
||||
routing: OpenConnectorRouting;
|
||||
waypoints?: OpenPoint[];
|
||||
style?: OpenNodeStyleWrite;
|
||||
}
|
||||
|
||||
interface OpenStickyNoteNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "stickyNote";
|
||||
text?: OpenTextWrite;
|
||||
style?: OpenNodeStyleWrite;
|
||||
}
|
||||
|
||||
interface OpenFrameNodeWrite extends OpenNodeWriteBase {
|
||||
type: "frame";
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
angle?: 0;
|
||||
title?: {
|
||||
text: OpenTextWrite;
|
||||
box?: { width: number; height: number };
|
||||
};
|
||||
style?: OpenNodeStyleWrite;
|
||||
presentationOrder?: number;
|
||||
resizeMode?: "free" | "fixedAspectRatio";
|
||||
}
|
||||
|
||||
interface OpenGroupNodeWrite extends OpenChildNodeWriteBase {
|
||||
id: string;
|
||||
type: "group";
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface OpenVectorNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "vector";
|
||||
resource: OpenManagedVectorResourceWrite;
|
||||
}
|
||||
|
||||
interface OpenIconNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "icon";
|
||||
catalogId: OpenIconCatalogId;
|
||||
}
|
||||
|
||||
interface OpenPathNodeWrite extends OpenSizedNodeWriteBase {
|
||||
type: "path";
|
||||
path: OpenPathDataWrite;
|
||||
style?: OpenNodeStyleWrite;
|
||||
}
|
||||
|
||||
type OpenNodeWrite =
|
||||
| OpenShapeNodeWrite
|
||||
| OpenTextNodeWrite
|
||||
| OpenConnectorNodeWrite
|
||||
| OpenStickyNoteNodeWrite
|
||||
| OpenFrameNodeWrite
|
||||
| OpenGroupNodeWrite
|
||||
| OpenVectorNodeWrite
|
||||
| OpenIconNodeWrite
|
||||
| OpenPathNodeWrite;
|
||||
```
|
||||
|
||||
上面的联合类型是 update 的字段白名单。各辅助结构和完整枚举值在第 7 节定义;
|
||||
未出现在对应分支中的字段不能发送。
|
||||
|
||||
| 字段 | 规则 |
|
||||
| --- | --- |
|
||||
| `id` | 可选的请求级临时 ID;非空、区分大小写、在请求内唯一。被引用时必须提供。 |
|
||||
| `type` | 必填,必须是 V1 可写类型。 |
|
||||
| `parentId` | 可选,引用同一请求中 group/frame 的临时 ID。 |
|
||||
| `x`、`y` | 除 connector 外必填;有父节点时为父节点相对坐标。 |
|
||||
| `width`、`height` | shape/text/stickyNote/frame/vector/icon/path 必填且大于 `0`;group/connector 只读。 |
|
||||
| `angle` | 可选,默认 `0`;frame 只允许 `0`;group/connector 只读。 |
|
||||
| `layer` | 可选;frame 默认 `background`,其他节点默认 `normal`。 |
|
||||
| `zIndex` | 可选的非负整数;相同值时按请求顺序稳定排序。 |
|
||||
| `hidden` | 可选布尔值,默认 `false`。 |
|
||||
|
||||
以下 query 字段禁止写回:
|
||||
|
||||
`children`、`absoluteBounds`、`locked`、`source`、`writeSupport`、
|
||||
`unsupportedFeatures`。
|
||||
|
||||
关系规则:
|
||||
|
||||
- `parentId` 只能引用同一请求中的 group 或 frame。
|
||||
- frame 和 connector 必须是页面直属节点,不能带 `parentId`。
|
||||
- group 可以嵌套,也可以放在 frame 中。
|
||||
- `children` 始终由各子节点的 `parentId` 推导。
|
||||
- 父子关系不能成环。
|
||||
- group 必须有临时 `id`、至少两个直接子节点,且不能全部隐藏。
|
||||
@@ -0,0 +1,395 @@
|
||||
# OpenNodes V1 — 支持矩阵、富文本和样式
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
## 7. 节点类型
|
||||
|
||||
### 7.1 支持矩阵
|
||||
|
||||
| `type` | query | update | 主要字段 |
|
||||
| --- | --- | --- | --- |
|
||||
| `shape` | 支持 | 支持 | `geometry`、`text?`、`style?` |
|
||||
| `text` | 支持 | 支持 | `text`、`style?` |
|
||||
| `connector` | 支持 | 支持 | `start`、`end`、`routing`、`waypoints?`、`style?` |
|
||||
| `stickyNote` | 支持 | 支持 | `text?`、`style?` |
|
||||
| `frame` | 支持 | 支持 | `title?`、`style?`、`presentationOrder?`、`resizeMode?` |
|
||||
| `group` | 支持 | 支持 | 子关系通过 `parentId` 表达 |
|
||||
| `image` | 支持 | 只读 | 仅公共字段 |
|
||||
| `vector` | 支持 | 支持 | `resource` |
|
||||
| `icon` | 支持 | 支持 | `catalogId` |
|
||||
| `path` | 支持 | 支持 | `path`、`style?` |
|
||||
| `pdf` | 支持 | 只读 | 仅公共字段 |
|
||||
| `media` | 支持 | 只读 | 仅公共字段 |
|
||||
| `webLink` | 支持 | 只读 | 仅公共字段 |
|
||||
| `table` | 支持 | 只读 | 仅公共字段 |
|
||||
| `chart` | 支持 | 只读 | 仅公共字段 |
|
||||
| `uml` | 支持 | 只读 | 仅公共字段 |
|
||||
| `swimlane` | 支持 | 只读 | 仅公共字段 |
|
||||
| `mind` | 支持 | 只读 | 仅公共字段 |
|
||||
| `timer` | 支持 | 只读 | 仅公共字段 |
|
||||
| `placeholder` | 支持 | 只读 | 仅公共字段 |
|
||||
| `unknown` | 支持 | 只读 | 未识别或尚未定义独立语义的节点统一映射到此类型 |
|
||||
|
||||
表中标记为只读的类型仍会完整返回公共几何、层级和顺序信息,但 update 提交会以
|
||||
`nodeTypeUnsupported` 失败。
|
||||
|
||||
`timer`、`table`、`webLink` 不支持 V1 update。query 仅返回这些节点的公共几何、
|
||||
层级、顺序和诊断字段,不承诺完整业务字段。文字 run 中的 `link` 是富文本能力,
|
||||
不属于 `webLink` 节点,V1 支持读写。
|
||||
|
||||
`webLink` 只保留只读查询;OpenNodes V1 不支持创建或重建该节点。
|
||||
|
||||
### 7.2 Text
|
||||
|
||||
query 和 update 均支持普通段落、无序列表、有序列表、多 block、多 run 和文字
|
||||
链接:
|
||||
|
||||
```ts
|
||||
interface OpenTextRun {
|
||||
text: string;
|
||||
marks?: {
|
||||
fontFamily?: string;
|
||||
fontSize?: number;
|
||||
bold?: boolean;
|
||||
italic?: boolean;
|
||||
underline?: boolean;
|
||||
strike?: boolean;
|
||||
color?: string;
|
||||
highlight?: string;
|
||||
};
|
||||
link?: { url: string };
|
||||
}
|
||||
|
||||
interface OpenTextBlock {
|
||||
type: "paragraph" | "bulletList" | "orderedList";
|
||||
horizontalAlign?: "left" | "center" | "right";
|
||||
runs: OpenTextRun[];
|
||||
}
|
||||
|
||||
interface OpenTextWrite {
|
||||
blocks: OpenTextBlock[];
|
||||
verticalAlign?: "top" | "center" | "bottom";
|
||||
padding?: number | [number, number];
|
||||
}
|
||||
|
||||
interface OpenText extends OpenTextWrite {
|
||||
plainText: string;
|
||||
writeSupport: "readWrite" | "readOnly";
|
||||
unsupportedFeatures?: string[];
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- `blocks.length >= 1`,每个 block 的 `type` 必须是 `paragraph`、
|
||||
`bulletList` 或 `orderedList`。
|
||||
- 每个 block 都必须满足 `runs.length >= 1`。
|
||||
- run 的 `text` 不能包含 `\r`、`\n`、U+2028 或 U+2029。换行和列表项使用
|
||||
独立 block 表达;每一段或每个列表项应写成一个 block,而不是把原始换行符
|
||||
放进单个 run。
|
||||
- 每个 `bulletList` / `orderedList` block 表示一个列表项;服务端会把连续且同类的
|
||||
block 解释为同一个列表中的多个列表项。
|
||||
- `link.url` 长度必须为 `1..2048`,不能包含控制字符、`<`、`>`。支持无 scheme
|
||||
的相对/裸链接,以及 `http`、`https`、`mailto`、`tel`、`dingtalk` scheme;
|
||||
`javascript:`、`data:` 等可执行或未知 scheme 会被拒绝。
|
||||
- 相邻且 URL 相同的 linked run 会呈现为同一个链接,同时保留各 run 自己的 marks。
|
||||
- `fontSize > 0`,padding 各项必须大于等于 `0`。
|
||||
- `plainText`、文本级 `writeSupport` 和 `unsupportedFeatures` 是 query-only。
|
||||
- text 节点必须提供 `text`;shape 和 stickyNote 的 `text` 可省略。
|
||||
- 受支持的 paragraph、列表、链接、多 run 都保持
|
||||
`writeSupport = "readWrite"`;未知 list style、非法链接、未支持的 block 或
|
||||
run marks 会令文本和所属节点变为 `readOnly`。
|
||||
|
||||
下面的文本会显示为两个段落,第一段由两个不同样式的 run 组成:
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"horizontalAlign": "left",
|
||||
"runs": [
|
||||
{
|
||||
"text": "OpenNodes ",
|
||||
"marks": { "fontSize": 18, "bold": true, "color": "#2563EB" }
|
||||
},
|
||||
{
|
||||
"text": "rich text",
|
||||
"marks": { "fontSize": 18, "italic": true, "color": "#0F172A" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "paragraph",
|
||||
"horizontalAlign": "right",
|
||||
"runs": [
|
||||
{
|
||||
"text": "第二段",
|
||||
"marks": { "fontSize": 16, "underline": true, "color": "#047857" }
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"verticalAlign": "center",
|
||||
"padding": [4, 8]
|
||||
}
|
||||
```
|
||||
|
||||
同一 `OpenTextWrite` 结构适用于独立 text 节点、shape 文本、stickyNote 文本和
|
||||
frame title。
|
||||
|
||||
下面三个 block 会生成两个无序列表项,其中第二项包含文字链接:
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "bulletList",
|
||||
"runs": [{ "text": "准备输入数据" }]
|
||||
},
|
||||
{
|
||||
"type": "bulletList",
|
||||
"runs": [
|
||||
{
|
||||
"text": "查看钉钉文档",
|
||||
"marks": { "underline": true },
|
||||
"link": { "url": "https://alidocs.dingtalk.com" }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "orderedList",
|
||||
"runs": [{ "text": "执行生成" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
颜色接受以下 CSS 形式:3/4/6/8 位十六进制、颜色名,以及
|
||||
`rgb()`、`rgba()`、`hsl()`、`hsla()`、`oklch()`、`lab()`、`lch()`、
|
||||
`color()`。字符串最长 128 字符,不能包含控制字符、`<`、`>` 或 `;`。
|
||||
这里只接受可独立解析的字面量;依赖外部样式上下文的 `var()`、`calc()`、
|
||||
`color-mix()` 等动态表达式不属于 V1。颜色名必须是标准 CSS named color,
|
||||
任意字母串不会被当成颜色。
|
||||
|
||||
### 7.3 Style
|
||||
|
||||
query 可表达:
|
||||
|
||||
- `none`、`solid`、`theme`、线性渐变、径向渐变和图片 paint。
|
||||
- shadow、blur 和 unknown effect。
|
||||
|
||||
V1 update 支持 `none`、`solid`、`theme`、线性渐变、九方向径向渐变,以及
|
||||
单个自定义 shadow。主题明暗参数和渐变色标位置使用 `0~100` 的百分比,
|
||||
不会归一化成 `0~1`:
|
||||
|
||||
```ts
|
||||
type OpenRadialGradientPosition =
|
||||
| "topLeft"
|
||||
| "topCenter"
|
||||
| "topRight"
|
||||
| "centerLeft"
|
||||
| "center"
|
||||
| "centerRight"
|
||||
| "bottomLeft"
|
||||
| "bottomCenter"
|
||||
| "bottomRight";
|
||||
|
||||
interface OpenColorStop {
|
||||
offset: number;
|
||||
color: string;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
interface OpenImagePaint {
|
||||
type: "image";
|
||||
resource: {
|
||||
kind: "managed" | "external" | "embedded" | "unresolved";
|
||||
resourceId?: string;
|
||||
};
|
||||
intrinsicWidth: number;
|
||||
intrinsicHeight: number;
|
||||
}
|
||||
|
||||
type OpenPaint =
|
||||
| { type: "none" }
|
||||
| { type: "solid"; color: string; opacity?: number }
|
||||
| {
|
||||
type: "theme";
|
||||
token: string;
|
||||
lumMod?: number;
|
||||
lumOff?: number;
|
||||
resolvedColor?: string;
|
||||
}
|
||||
| {
|
||||
type: "linearGradient";
|
||||
angle: number;
|
||||
stops: OpenColorStop[];
|
||||
}
|
||||
| {
|
||||
type: "radialGradient";
|
||||
position: OpenRadialGradientPosition | "custom";
|
||||
stops: OpenColorStop[];
|
||||
}
|
||||
| OpenImagePaint;
|
||||
|
||||
type OpenEffect =
|
||||
| {
|
||||
type: "shadow";
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
blur: number;
|
||||
color: string;
|
||||
opacity: number;
|
||||
}
|
||||
| { type: "blur"; blur: number }
|
||||
| { type: "unknown" };
|
||||
|
||||
interface OpenNodeStyle {
|
||||
opacity?: number;
|
||||
fill?: OpenPaint;
|
||||
stroke?: {
|
||||
paint: OpenPaint;
|
||||
width?: number;
|
||||
dash?: number[];
|
||||
lineCap?: "butt" | "round" | "square";
|
||||
lineJoin?: "miter" | "round" | "bevel";
|
||||
};
|
||||
effects?: OpenEffect[];
|
||||
writeSupport: "readWrite" | "readOnly";
|
||||
unsupportedFeatures?: string[];
|
||||
}
|
||||
|
||||
interface OpenColorStopWrite {
|
||||
offset: number; // [0, 100],百分比
|
||||
color: string;
|
||||
opacity?: number; // [0, 1]
|
||||
}
|
||||
|
||||
type OpenPaintWrite =
|
||||
| { type: "none" }
|
||||
| { type: "solid"; color: string; opacity?: number }
|
||||
| {
|
||||
type: "theme";
|
||||
token: string;
|
||||
lumMod?: number; // [0, 100],默认 100
|
||||
lumOff?: number; // [0, 100],默认 0
|
||||
}
|
||||
| {
|
||||
type: "linearGradient";
|
||||
angle: number;
|
||||
stops: OpenColorStopWrite[];
|
||||
}
|
||||
| {
|
||||
type: "radialGradient";
|
||||
position: OpenRadialGradientPosition;
|
||||
stops: OpenColorStopWrite[];
|
||||
};
|
||||
|
||||
interface OpenShadowEffectWrite {
|
||||
type: "shadow";
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
blur: number;
|
||||
color: string;
|
||||
opacity: number;
|
||||
}
|
||||
|
||||
interface OpenNodeStyleWrite {
|
||||
opacity?: number;
|
||||
fill?: OpenPaintWrite;
|
||||
stroke?: {
|
||||
paint: OpenPaintWrite;
|
||||
width?: number;
|
||||
dash?: number[];
|
||||
lineCap?: "butt" | "round" | "square";
|
||||
lineJoin?: "miter" | "round" | "bevel";
|
||||
};
|
||||
effects?: OpenShadowEffectWrite[];
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- opacity 范围为 `[0, 1]`。
|
||||
- solid paint 的 `color` 与 `opacity` 在 query 后仍保持独立字段,不会合并为
|
||||
动态 CSS 表达式。
|
||||
- theme 的 `token` 必须能在当前白板主题中解析;
|
||||
`lumMod`、`lumOff` 范围均为 `[0, 100]`。token 不存在时在
|
||||
Request graph 阶段返回 `themeTokenNotFound`,不会写出部分节点。
|
||||
token 长度为 `1~64`,首尾不能有空白,也不能包含空白、控制字符、
|
||||
`<`、`>` 或 `;`。
|
||||
- query 的 theme paint 还会返回按当前白板主题计算出的 query-only
|
||||
`resolvedColor`。调用方写入时只传 `token/lumMod/lumOff`,不传
|
||||
`resolvedColor`。
|
||||
- 渐变必须至少有一个 stop;`offset` 范围为 `[0, 100]`,单位是百分比。
|
||||
- 线性渐变 `angle` 范围为 `[0, 360]`。
|
||||
- 径向渐变只接受上述九宫格位置。query 遇到九宫格以外的位置时返回
|
||||
`position: "custom"` 并将该节点标为只读。
|
||||
- `effects` 最多包含一个 `shadow`;`offsetX/offsetY` 必须是有限数,
|
||||
`blur >= 0`,shadow opacity 范围为 `[0, 1]`。
|
||||
- stroke width 和 dash 各项必须大于等于 `0`。
|
||||
- 一旦提供 stroke,`stroke.paint` 必填。
|
||||
- 样式级 `writeSupport` 和 `unsupportedFeatures` 是 query-only。
|
||||
- 能在当前白板主题中解析且明暗参数合法的 theme paint 可写。无法解析的主题
|
||||
token、越界的主题明暗参数、image paint、blur、unknown effect、叠加 effect
|
||||
或自定义径向位置会令节点只读;受支持的 theme、渐变和单个 shadow 本身不会
|
||||
令节点只读。
|
||||
|
||||
主题色示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"fill": {
|
||||
"type": "theme",
|
||||
"token": "ac3",
|
||||
"lumMod": 20,
|
||||
"lumOff": 80
|
||||
},
|
||||
"stroke": {
|
||||
"paint": {
|
||||
"type": "theme",
|
||||
"token": "sk1",
|
||||
"lumMod": 80,
|
||||
"lumOff": 20
|
||||
},
|
||||
"width": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
示例中的 `ac3`、`sk1` 只是主题 token 示例,不是所有白板都可用的全局枚举。
|
||||
调用方只能使用已确认可由当前白板主题解析的 token;无法确认时应改用
|
||||
`solid` 颜色。
|
||||
|
||||
DWS 不提供新增、修改或切换主题的命令。当前白板没有有效主题时,应改用
|
||||
`solid`。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"fill": {
|
||||
"type": "linearGradient",
|
||||
"angle": 35,
|
||||
"stops": [
|
||||
{ "offset": 0, "color": "#1677ff", "opacity": 0.4 },
|
||||
{ "offset": 100, "color": "#69b1ff" }
|
||||
]
|
||||
},
|
||||
"effects": [
|
||||
{
|
||||
"type": "shadow",
|
||||
"offsetX": 8,
|
||||
"offsetY": 8,
|
||||
"blur": 19,
|
||||
"color": "rgba(93,190,172,1)",
|
||||
"opacity": 0.5
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
未传 `style` 时使用节点类型的默认样式。调用方如需稳定的视觉结果,应显式传入
|
||||
`fill` 和 `stroke`。
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
# OpenNodes V1 — Shape、Text、Sticky note、Frame、Group 和 Connector
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
### 7.4 Shape
|
||||
|
||||
shape 必须提供 `geometry`,格式为 `dml:<name>`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "shape-1",
|
||||
"type": "shape",
|
||||
"x": 100,
|
||||
"y": 80,
|
||||
"width": 160,
|
||||
"height": 100,
|
||||
"geometry": "dml:roundRect",
|
||||
"style": {
|
||||
"fill": {
|
||||
"type": "solid",
|
||||
"color": "#DCEEFF"
|
||||
},
|
||||
"stroke": {
|
||||
"paint": {
|
||||
"type": "solid",
|
||||
"color": "#225588"
|
||||
},
|
||||
"width": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
query 可能返回 `adjustments`,但 V1 update 不支持写入;带 adjustments 的
|
||||
shape 会标为只读。`dml-v1` 的完整 geometry 目录见附录 A。
|
||||
|
||||
### 7.5 Text node 与 Sticky note
|
||||
|
||||
text node 使用公共几何、必填 `text` 和可选 `style`。
|
||||
|
||||
stickyNote 使用公共几何、可选 `text` 和可选 `style`。省略 `text` 时创建空
|
||||
便签。query 还可能返回:
|
||||
|
||||
- `creator`:创建者展示信息。
|
||||
- `tags`:标签 ID、文本和背景 paint。
|
||||
|
||||
这两个字段是 query-only;存在 creator 或 tags 的 stickyNote 会被标为只读。
|
||||
|
||||
### 7.6 Frame
|
||||
|
||||
frame 的 update 结构见第 6 节 `OpenFrameNodeWrite`。
|
||||
|
||||
约束:
|
||||
|
||||
- frame 必须是页面直属节点,不能带 `parentId`。
|
||||
- angle 只允许 `0`。
|
||||
- `presentationOrder` 是非负整数,并且不能和已有或本次创建的 frame 冲突。
|
||||
- frame 的子节点通过子节点 `parentId` 引用 frame 临时 ID。
|
||||
- frame 不能包含 frame 或 connector。
|
||||
- frame 默认 layer 为 `background`。
|
||||
|
||||
### 7.7 Group
|
||||
|
||||
group 的写入字段只有公共字段中的 `id`、`parentId?`、`x`、`y`、`layer?`、
|
||||
`zIndex?` 和 `hidden?`。其 width、height、angle 和 children 都由服务端根据
|
||||
子节点推导。
|
||||
|
||||
group 必须:
|
||||
|
||||
- 提供临时 `id`。
|
||||
- 至少包含两个直接子节点。
|
||||
- 至少有一个直接子节点可见。
|
||||
|
||||
group 的任一子节点为只读时,query 会把 group 一并标为只读。
|
||||
|
||||
### 7.8 Connector
|
||||
|
||||
connector 的几何由端点和路由推导,因此 update 不能提供 `x`、`y`、
|
||||
`width`、`height` 或 `angle`。
|
||||
|
||||
query 的连接线结构如下:
|
||||
|
||||
```ts
|
||||
type OpenConnectorRouting =
|
||||
| "straight"
|
||||
| "polyline"
|
||||
| "curve"
|
||||
| "orthogonal";
|
||||
|
||||
interface OpenConnectorMarker {
|
||||
catalogId: string;
|
||||
}
|
||||
|
||||
type OpenConnectorAnchor =
|
||||
| {
|
||||
mode: "fixed";
|
||||
side: "top" | "right" | "bottom" | "left";
|
||||
position: OpenPoint;
|
||||
}
|
||||
| {
|
||||
mode: "fixed";
|
||||
side: "custom";
|
||||
position: OpenPoint;
|
||||
};
|
||||
|
||||
type OpenConnectorEndpoint =
|
||||
| {
|
||||
type: "point";
|
||||
point: OpenPoint;
|
||||
marker: OpenConnectorMarker;
|
||||
}
|
||||
| {
|
||||
type: "node";
|
||||
nodeRef: { scope: "document"; id: string };
|
||||
anchor: OpenConnectorAnchor;
|
||||
resolvedPoint: OpenPoint;
|
||||
marker: OpenConnectorMarker;
|
||||
};
|
||||
|
||||
interface OpenBezierSegment {
|
||||
start: OpenPoint;
|
||||
control1: OpenPoint;
|
||||
control2: OpenPoint;
|
||||
end: OpenPoint;
|
||||
}
|
||||
|
||||
type OpenResolvedConnectorPath =
|
||||
| { type: "polyline"; points: OpenPoint[] }
|
||||
| { type: "bezier"; segments: OpenBezierSegment[] };
|
||||
```
|
||||
|
||||
update 端点有两种形式:
|
||||
|
||||
```ts
|
||||
type OpenConnectorEndpointWrite =
|
||||
| {
|
||||
type: "point";
|
||||
point: { x: number; y: number };
|
||||
marker?: { catalogId: "none" | "arrow.open" | "arrow.filled" };
|
||||
}
|
||||
| {
|
||||
type: "node";
|
||||
nodeRef: { scope: "request"; id: string };
|
||||
anchor?:
|
||||
| { mode: "auto" }
|
||||
| {
|
||||
mode: "fixed";
|
||||
side: "top" | "right" | "bottom" | "left";
|
||||
};
|
||||
marker?: { catalogId: "none" | "arrow.open" | "arrow.filled" };
|
||||
};
|
||||
```
|
||||
|
||||
query 的 marker `catalogId` 使用 `string`,以便返回无法映射的既有 marker;
|
||||
update 只接受上面列出的 `"none"`、`"arrow.open"`、`"arrow.filled"`。
|
||||
|
||||
路由规则:
|
||||
|
||||
| `routing` | `waypoints` |
|
||||
| --- | --- |
|
||||
| `straight` | 禁止提供,包括空数组。 |
|
||||
| `polyline` | 必须至少提供一个。 |
|
||||
| `curve` | 可选。 |
|
||||
| `orthogonal` | 可选;显式点路径的相邻线段必须水平或垂直。 |
|
||||
|
||||
其他约束:
|
||||
|
||||
- 所有 point 和 waypoint 都使用页面绝对坐标。
|
||||
- node 端点只能引用同一请求中的 shape、text、stickyNote、frame、group 或 path。
|
||||
- node 端点不能引用隐藏节点、connector 或 query 中既有节点。
|
||||
- update 引用范围固定为 `scope: "request"`;query 返回的节点引用范围为
|
||||
`scope: "document"`,不能直接回写。
|
||||
- 同一连接线的两端不能引用同一个节点。
|
||||
- 零长度或无效路径会被拒绝。
|
||||
- marker 省略时默认为 `none`。
|
||||
- anchor 省略时按 `auto` 处理。
|
||||
|
||||
query 额外返回服务端解析后的:
|
||||
|
||||
- node 端点 `resolvedPoint`。
|
||||
- fixed anchor 的归一化 `position`。
|
||||
- `resolvedPath`,类型为 polyline points 或 cubic bezier segments。
|
||||
- 由真实路径推导的 `absoluteBounds`。
|
||||
|
||||
这些解析字段都是 query-only。
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
# OpenNodes V1 — Vector、Icon 和 Path
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
### 7.9 Vector(已上传 SVG/矢量资源)
|
||||
|
||||
`vector` 表示已经通过 `dws doc media upload` 获得稳定引用的 SVG/矢量图片。
|
||||
OpenNodes 只接收上传结果中的资源引用,不接收本地路径或原始 SVG/XML 内容。
|
||||
|
||||
上传时必须使用与后续白板更新相同的文档 `nodeId`:
|
||||
|
||||
```bash
|
||||
dws doc media upload \
|
||||
--node <DOC_NODE_ID> \
|
||||
--file ./icon.svg \
|
||||
--mime-type image/svg+xml \
|
||||
--format json
|
||||
```
|
||||
|
||||
将上传结果的 `resourceId` 和 `resourceUrl` 分别写入
|
||||
`resource.resourceId` 和 `resource.url`。
|
||||
|
||||
Update 必须提供完整的托管资源信息:
|
||||
|
||||
```ts
|
||||
interface OpenManagedVectorResourceWrite {
|
||||
kind: "managed";
|
||||
resourceId: string;
|
||||
url: string;
|
||||
}
|
||||
```
|
||||
|
||||
完整节点结构见第 6 节 `OpenVectorNodeWrite`。
|
||||
|
||||
`resource` 字段规则:
|
||||
|
||||
| 字段 | 必填 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| `kind` | 是 | 当前只允许固定值 `managed`,表示资源已经通过 DWS 上传。 |
|
||||
| `resourceId` | 是 | 资源稳定 ID,长度 1~256,只允许字母、数字、`.`、`_`、`:`、`-`。 |
|
||||
| `url` | 是 | 已上传资源地址,最长 4096;必须包含且只能包含一个同值的 `resourceId` 查询参数。 |
|
||||
|
||||
`url` 必须直接使用 `dws doc media upload` 返回的 `resourceUrl`,不得自行拼装
|
||||
或修改。
|
||||
|
||||
以下内容会被拒绝:
|
||||
|
||||
- 原始 SVG/XML、`data:`、`blob:`、`http:` URL。
|
||||
- `//host/path` 协议相对地址,以及自行构造或修改的其他相对地址。
|
||||
- 含空白、控制字符、反斜杠、fragment 或用户凭证的 URL。
|
||||
- URL 缺少 `resourceId`、重复出现 `resourceId`,或者 URL 中 ID 与显式
|
||||
`resource.resourceId` 不一致。
|
||||
- `resource` 缺失、字段不完整、`kind` 不是 `managed`,或包含未知字段。
|
||||
|
||||
完整 Append 示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "uploaded-svg-1",
|
||||
"type": "vector",
|
||||
"x": 100,
|
||||
"y": 80,
|
||||
"width": 240,
|
||||
"height": 180,
|
||||
"angle": 0,
|
||||
"resource": {
|
||||
"kind": "managed",
|
||||
"resourceId": "0c1c94e1-f9af-4228-b32f-42bbd1555253",
|
||||
"url": "https://resources.example.com/assets/opaque-path?resourceId=0c1c94e1-f9af-4228-b32f-42bbd1555253"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overwrite": false
|
||||
}
|
||||
```
|
||||
|
||||
示例中的 `resources.example.com` 是占位域名,实际调用必须使用
|
||||
`dws doc media upload` 返回的 `resourceUrl`。
|
||||
|
||||
`resourceId` 同时显式出现并包含在 URL 中,用于校验资源身份与地址是否一致。
|
||||
两者必须来自同一次 `dws doc media upload` 结果。
|
||||
|
||||
Query 的 `resource` 可能是:
|
||||
|
||||
```ts
|
||||
type OpenVectorResource =
|
||||
| { kind: "managed"; resourceId: string; url: string }
|
||||
| { kind: "external" | "embedded" | "unresolved" };
|
||||
```
|
||||
|
||||
- 能识别为托管资源的引用返回完整 `managed` 信息。
|
||||
- HTTP(S) 外链但不满足托管资源契约时返回 `external`。
|
||||
- `data:`/`blob:` 返回 `embedded`。
|
||||
- 其他缺失或无法识别的地址返回 `unresolved`。
|
||||
- 非 `managed` 资源会令节点只读,并分别产生
|
||||
`vector.resource.external`、`vector.resource.embedded` 或
|
||||
`vector.resource.unresolved`。
|
||||
|
||||
V1 vector update 不接受 `style`。既有节点包含 V1 无法表达的 fill、stroke、
|
||||
opacity、effect 或 adjustments 时,query 仍可读取资源和几何,但节点会标为只读。
|
||||
不影响资源内容的兼容性装饰不会单独令节点变为只读。
|
||||
|
||||
DWS 会校验资源引用。上传与 `whiteboard update` 必须使用同一个文档
|
||||
`nodeId`;不要跨文档复用资源,也不要使用临时 `uploadUrl`。
|
||||
|
||||
### 7.10 Icon(内置图标)
|
||||
|
||||
`icon` 表示内置图标。OpenNodes 使用版本化的 `catalogId` 作为稳定标识,
|
||||
允许值见下列类型定义和附录 B。
|
||||
|
||||
Update 结构:
|
||||
|
||||
```ts
|
||||
type OpenIconCatalogId =
|
||||
| `emoji/${
|
||||
| "happy"
|
||||
| "smile"
|
||||
| "laugh"
|
||||
| "fighting"
|
||||
| "like"
|
||||
| "ok"
|
||||
| "please"
|
||||
| "face-plam"
|
||||
| "tears-of-joy"
|
||||
| "cry"
|
||||
| "question"
|
||||
| "face-with-sweat"
|
||||
| "bloody-nose"
|
||||
| "doggy"}`
|
||||
| `tools/${
|
||||
| "pad"
|
||||
| "blue-note"
|
||||
| "yellow-notes"
|
||||
| "chart"
|
||||
| "chart-2"
|
||||
| "pencil"
|
||||
| "pen"
|
||||
| "bag"
|
||||
| "rocket"
|
||||
| "fire"
|
||||
| "gold"
|
||||
| "light"
|
||||
| "pin"
|
||||
| "red-flag"
|
||||
| "tea"
|
||||
| "island"
|
||||
| "ball"
|
||||
| "lucky-fish"
|
||||
| "coffee"
|
||||
| "milky-tea"
|
||||
| "pan"}`
|
||||
| `priority/priority-${1 | 2 | 3 | 4 | 5 | 6 | 7}`
|
||||
| `task/${
|
||||
| "task-start"
|
||||
| "task-oct"
|
||||
| "task-3oct"
|
||||
| "task-half"
|
||||
| "task-5oct"
|
||||
| "task-7oct"
|
||||
| "task-done"}`;
|
||||
```
|
||||
|
||||
完整节点结构见第 6 节 `OpenIconNodeWrite`。
|
||||
|
||||
完整 Append 示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "pencil-icon",
|
||||
"type": "icon",
|
||||
"x": 100,
|
||||
"y": 80,
|
||||
"width": 48,
|
||||
"height": 48,
|
||||
"catalogId": "tools/pencil"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overwrite": false
|
||||
}
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- `catalogId` 必填,格式为 `<group>/<name>`,并且必须精确命中附录 B 的
|
||||
`dml-v1` allowlist;大小写、连字符和历史拼写都不能自行修正。
|
||||
- 当前目录有 `emoji`、`tools`、`priority`、`task` 四组,共 49 项。
|
||||
- update 只接受 `catalogId`,不接受 `group`、`name`、`style` 或 `resource`。
|
||||
- 内置 icon 不需要调用方上传资源,也不需要 `resourceId`。
|
||||
- 任意已上传 SVG 或自定义图标应使用 `vector`,并按 7.9 节提供完整
|
||||
`resource` 信息,不能伪造一个 icon `catalogId`。
|
||||
- icon 可以作为 group/frame 子节点;V1 connector 的 node 端点当前仍不接受
|
||||
icon 作为目标。
|
||||
|
||||
Query 返回相同的 `catalogId`。既有 icon 无法映射到当前目录时,节点仍会以
|
||||
`type: "icon"` 返回以便诊断,但 `writeSupport` 为 `readOnly`,原因包含
|
||||
`icon.catalogId`。非默认 opacity、filter/effect、text 或 adjustments 同样会令节点
|
||||
只读。
|
||||
|
||||
### 7.11 Path(自由画笔)
|
||||
|
||||
`path` 表示自由画笔轨迹。OpenNodes 保留两组互相独立的尺寸:
|
||||
|
||||
- 节点公共 `width` / `height` 是画布上的实际渲染尺寸,缩放节点时会变化。
|
||||
- `path.intrinsicWidth` / `path.intrinsicHeight` 是 SVG path 自身的坐标空间尺寸,
|
||||
表示 `path.data` 使用的内部坐标空间。
|
||||
|
||||
```ts
|
||||
interface OpenPathData {
|
||||
data: string;
|
||||
intrinsicWidth: number;
|
||||
intrinsicHeight: number;
|
||||
}
|
||||
|
||||
type OpenPathDataWrite = OpenPathData;
|
||||
```
|
||||
|
||||
完整 update 节点结构见第 6 节 `OpenPathNodeWrite`。query 和 update 的 `path`
|
||||
字段结构相同,但 update 仍必须满足下方命令子集和大小限制。
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "freehand-stroke",
|
||||
"type": "path",
|
||||
"x": 120,
|
||||
"y": 100,
|
||||
"width": 500,
|
||||
"height": 150,
|
||||
"path": {
|
||||
"data": "M0,75 Q50,0 100,75 Q150,150 200,75 Q250,0 300,75 Q350,150 400,75 Q450,0 500,75",
|
||||
"intrinsicWidth": 500,
|
||||
"intrinsicHeight": 150
|
||||
},
|
||||
"style": {
|
||||
"fill": { "type": "none" },
|
||||
"stroke": {
|
||||
"paint": { "type": "solid", "color": "#7C3AED" },
|
||||
"width": 10,
|
||||
"lineCap": "round",
|
||||
"lineJoin": "round"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
下面是一个仍然只使用 V1 命令子集、但包含 12 段二次贝塞尔曲线的蝴蝶轮廓。
|
||||
它显式回到起点,因此不需要使用尚未支持的 `Z`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "complex-butterfly-path",
|
||||
"type": "path",
|
||||
"x": 1500,
|
||||
"y": 1215,
|
||||
"width": 500,
|
||||
"height": 420,
|
||||
"path": {
|
||||
"data": "M250,180 Q210,105 145,70 Q55,25 35,110 Q10,195 125,220 Q35,275 80,355 Q125,415 210,315 Q235,285 250,250 Q265,285 290,315 Q375,415 420,355 Q465,275 375,220 Q490,195 465,110 Q445,25 355,70 Q290,105 250,180",
|
||||
"intrinsicWidth": 500,
|
||||
"intrinsicHeight": 420
|
||||
},
|
||||
"style": {
|
||||
"opacity": 0.96,
|
||||
"fill": {
|
||||
"type": "solid",
|
||||
"color": "#EDE9FE",
|
||||
"opacity": 0.72
|
||||
},
|
||||
"stroke": {
|
||||
"paint": {
|
||||
"type": "solid",
|
||||
"color": "#6D28D9"
|
||||
},
|
||||
"width": 8,
|
||||
"lineCap": "round",
|
||||
"lineJoin": "round"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
V1 path 写入约束如下:
|
||||
|
||||
- `data` 必须是一个绝对 `M`,后跟至少一个显式写出的绝对 `Q`;不接受相对命令,
|
||||
也不接受 `L`、`C`、`A`、`Z` 等通用 SVG 命令。
|
||||
- 所有命令参数必须完整且为有限数值;单节点 `data` 最长 1 MiB,最多 50,000 个
|
||||
命令。
|
||||
- `intrinsicWidth` 和 `intrinsicHeight` 必须为有限正数;它们不要求等于节点的
|
||||
`width` 和 `height`。
|
||||
- 未传 `style` 时,默认使用透明填充、`#222222` 描边、宽度 5,以及 round
|
||||
line cap/join。需要稳定视觉结果时仍应显式传入 `style`。
|
||||
- path 可以作为 group/frame 的子节点,也可以作为同一 update 请求中 connector
|
||||
的 node 端点。
|
||||
|
||||
query 会把其他能够解析的 SVG path 保留为 `type: "path"`,但标记为
|
||||
`readOnly`,原因包含 `path.commands`;超出上述 V1 限制时使用
|
||||
`path.data.size` 或 `path.commands.limit`。既有 path 带 text、adjustments、非
|
||||
`nonzero` fillRule 或 V1 无法表达的样式时也会只读。仅包含不影响画笔几何的
|
||||
兼容性信息时,不会因此变为只读。theme stroke 遵循通用 style 契约:query 会
|
||||
保留 token 和明暗参数;只要 token 能在当前白板主题中解析,就可以按 theme
|
||||
paint 回写。
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
# OpenNodes V1 — Update 示例、回写规则、错误模型和 writeSupport
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
## 8. Update 示例
|
||||
|
||||
### 8.1 Append 一个文本节点
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "title",
|
||||
"type": "text",
|
||||
"x": 120,
|
||||
"y": 80,
|
||||
"width": 240,
|
||||
"height": 48,
|
||||
"text": {
|
||||
"blocks": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"horizontalAlign": "left",
|
||||
"runs": [
|
||||
{
|
||||
"text": "Hello OpenNodes",
|
||||
"marks": {
|
||||
"fontSize": 16,
|
||||
"color": "#223344"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"verticalAlign": "center",
|
||||
"padding": [2, 4]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 Append 两个形状和一条引用连接线
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "left",
|
||||
"type": "shape",
|
||||
"x": 80,
|
||||
"y": 100,
|
||||
"width": 120,
|
||||
"height": 80,
|
||||
"geometry": "dml:roundRect"
|
||||
},
|
||||
{
|
||||
"id": "right",
|
||||
"type": "shape",
|
||||
"x": 360,
|
||||
"y": 100,
|
||||
"width": 120,
|
||||
"height": 80,
|
||||
"geometry": "dml:roundRect"
|
||||
},
|
||||
{
|
||||
"id": "line",
|
||||
"type": "connector",
|
||||
"start": {
|
||||
"type": "node",
|
||||
"nodeRef": {
|
||||
"scope": "request",
|
||||
"id": "left"
|
||||
},
|
||||
"anchor": {
|
||||
"mode": "fixed",
|
||||
"side": "right"
|
||||
}
|
||||
},
|
||||
"end": {
|
||||
"type": "node",
|
||||
"nodeRef": {
|
||||
"scope": "request",
|
||||
"id": "right"
|
||||
},
|
||||
"anchor": {
|
||||
"mode": "fixed",
|
||||
"side": "left"
|
||||
},
|
||||
"marker": {
|
||||
"catalogId": "arrow.filled"
|
||||
}
|
||||
},
|
||||
"routing": "straight"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 Overwrite 整页
|
||||
|
||||
```json
|
||||
{
|
||||
"overwrite": true,
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "replacement",
|
||||
"type": "text",
|
||||
"x": 120,
|
||||
"y": 80,
|
||||
"width": 240,
|
||||
"height": 48,
|
||||
"text": {
|
||||
"blocks": [
|
||||
{
|
||||
"type": "paragraph",
|
||||
"runs": [
|
||||
{
|
||||
"text": "Replacement content"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.4 清空当前页面
|
||||
|
||||
```json
|
||||
{
|
||||
"overwrite": true,
|
||||
"source": {
|
||||
"schemaVersion": "1.0",
|
||||
"catalogVersion": "dml-v1",
|
||||
"nodes": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9. Query 数据不能直接回写
|
||||
|
||||
query 是完整可读投影,update 是受约束的创建协议,两者不是对称 JSON:
|
||||
|
||||
| Query 字段/能力 | Update 处理方式 |
|
||||
| --- | --- |
|
||||
| 真实 `id` | 只能作为请求级临时 ID;不能引用既有 document 节点。 |
|
||||
| `children` | 删除,通过子节点 `parentId` 重建。 |
|
||||
| `absoluteBounds` | 删除;普通节点使用 `x/y/width/height`,connector 使用端点和路由字段。 |
|
||||
| `locked`、`source`、`writeSupport`、`unsupportedFeatures` | 删除,均为 query-only。 |
|
||||
| 文本 `plainText` | 删除,由服务端根据 paragraph 和 run 重新计算。 |
|
||||
| 多 paragraph、列表、多 run、文字链接 | 可以保留;每个 block 必须是受支持类型,且 run 内不能包含原始换行符。 |
|
||||
| 未知 list style、非法链接或未支持的 block/marks | 需要移除或降级为受支持的 block/run。 |
|
||||
| theme paint | 保留 `token/lumMod/lumOff`,删除 query-only `resolvedColor`;token 必须能在当前白板主题中解析。 |
|
||||
| image paint | 需要降级成受支持的 paint,或不更新该节点。 |
|
||||
| 受支持的 linear/radial gradient、单个 shadow | 可以保留;gradient offset 使用 `0~100`,radial `custom` 不能回写。 |
|
||||
| blur、unknown 或叠加 effects | 需要删除、降级成单个 shadow,或不更新该节点。 |
|
||||
| connector `scope: "document"` | 不能回写;改为引用同一请求节点的 `scope: "request"`。 |
|
||||
| connector `resolvedPoint`、`position`、`resolvedPath` | 删除,均由服务端重新计算。 |
|
||||
| shape `adjustments` | V1 不支持写入。 |
|
||||
| stickyNote `creator`、`tags` | V1 不支持写入。 |
|
||||
|
||||
即使 query 节点显示 `writeSupport = "readWrite"`,update 仍会对版本、目录、
|
||||
字段和请求关系做完整校验。调用方不应跳过 update 错误处理。
|
||||
|
||||
## 10. 错误模型
|
||||
|
||||
### 10.1 顶层错误码
|
||||
|
||||
| 错误码 | 含义 |
|
||||
| --- | --- |
|
||||
| `invalidRequest.whiteboard.schemaInvalid` | JSON、字段或节点 schema 不合法。 |
|
||||
| `invalidRequest.whiteboard.catalogVersionUnsupported` | catalogVersion 不受支持。 |
|
||||
| `invalidRequest.whiteboard.validationFailed` | 节点间引用、父子关系或路径关系不合法。 |
|
||||
| `invalidRequest.whiteboard.emptySource` | append 的 nodes 为空。 |
|
||||
| `invalidRequest.whiteboard.overwriteUnsafe` | overwrite 安全预检失败。 |
|
||||
|
||||
### 10.2 DWS 错误输出
|
||||
|
||||
远端校验失败时,DWS 以统一 CLI 错误结构返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"category": "api",
|
||||
"reason": "business_error",
|
||||
"server_key": "whiteboard",
|
||||
"server_error_code": "invalidRequest.whiteboard.validationFailed",
|
||||
"message": "Whiteboard request graph is invalid",
|
||||
"trace_id": "TRACE_ID"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
部分服务错误会使用更宽泛的 `invalidRequest.inputArgs.invalid`。Agent 应结合
|
||||
`server_error_code` 和 `message` 修正输入;需要排障时保留 `trace_id`。JSON 或
|
||||
信封级错误可能由 CLI 本地返回,不一定包含 `server_key` 和 `trace_id`。
|
||||
|
||||
校验类错误不可通过原样重试恢复。常见原因包括:
|
||||
|
||||
- Schema:缺少字段、未知字段、类型或枚举值错误、提交 query-only 字段、
|
||||
节点类型不支持。
|
||||
- 请求关系:临时 ID 重复、引用不存在、父子关系非法、连接线目标不支持、
|
||||
路径退化或主题 token 不存在。
|
||||
- Overwrite 预检:锁定节点、禁止删除、关联数据无法安全处理或删除失败。
|
||||
|
||||
任一阶段失败都不会保留部分更新。
|
||||
|
||||
## 11. writeSupport 的含义
|
||||
|
||||
`writeSupport` 表示当前 query 节点是否能由 V1 update 无损表达,不代表用户
|
||||
权限,也不代表 overwrite 是否允许移除该既有节点。
|
||||
|
||||
以下 `unsupportedFeatures` 均为对外返回的诊断枚举值:
|
||||
|
||||
- `node.source.master`、`node.locked`、`node.role`、`node.placeholder`、
|
||||
`node.extras`、`node.ability`。
|
||||
- `node.type.image`、`node.type.pdf`、`node.type.media`、
|
||||
`node.type.webLink`、`node.type.table`、`node.type.chart`、
|
||||
`node.type.uml`、`node.type.swimlane`、`node.type.mind`、
|
||||
`node.type.timer`、`node.type.placeholder`、`node.type.unknown`。
|
||||
- `text.list.unsupported`、`text.link.unsupported`、`text.block.unsupported`、
|
||||
`text.lineBreak.unsupported`、`text.marks.unsupported`、
|
||||
`text.color.unsupported`、`text.highlight.unsupported`。
|
||||
- `style.fill.color`、`style.fill.opacity`、`style.fill.theme.token`、
|
||||
`style.fill.theme.unresolved`、`style.fill.theme.modifier`、
|
||||
`style.fill.theme.opacity`、
|
||||
`style.fill.gradient.angle`、`style.fill.gradient.offset`、
|
||||
`style.fill.gradient.color`、`style.fill.gradient.opacity`、
|
||||
`style.fill.gradient.position`、`style.fill.image`。
|
||||
- `style.stroke.color`、`style.stroke.opacity`、`style.stroke.theme.token`、
|
||||
`style.stroke.theme.unresolved`、
|
||||
`style.stroke.theme.modifier`、`style.stroke.theme.opacity`、
|
||||
`style.stroke.gradient.angle`、`style.stroke.gradient.offset`、
|
||||
`style.stroke.gradient.color`、`style.stroke.gradient.opacity`、
|
||||
`style.stroke.gradient.position`、`style.stroke.image`。
|
||||
- `style.effects`。
|
||||
- `shape.adjustments`、`stickyNote.creator`、`stickyNote.tags`。
|
||||
- `vector.resource.external`、`vector.resource.embedded`、
|
||||
`vector.resource.unresolved`、`vector.fill`、`vector.stroke`、
|
||||
`vector.opacity`、`vector.effect`、`vector.adjustments`。
|
||||
- `icon.catalogId`、`icon.opacity`、`icon.effect`、`icon.text`、
|
||||
`icon.adjustments`。
|
||||
- `path.commands`、`path.data.size`、`path.commands.limit`、`path.text`、
|
||||
`path.fillRule`、`path.adjustments`。
|
||||
- `connector.parent`、`connector.marker.unsupported`、
|
||||
`connector.target.unexposed`、`connector.target.unsupported`、
|
||||
`connector.anchor.unresolved`、`connector.anchor.custom`、
|
||||
`connector.selfLoop`。
|
||||
- `group.angle`、`group.children.minimum`、`group.children.hidden`、
|
||||
`group.child.readOnly`。
|
||||
- `frame.angle`、`frame.child.frame`、`frame.child.readOnly`。
|
||||
|
||||
调用方应把 `unsupportedFeatures` 当作诊断信息,不应把当前枚举穷举写死为
|
||||
业务逻辑。真正可写与否以 `writeSupport` 和 update 校验结果为准。
|
||||
@@ -0,0 +1,61 @@
|
||||
# OpenNodes V1 — dml-v1 Geometry 和 Icon 完整目录
|
||||
|
||||
> 本文件是 DWS OpenNodes V1 协议的拆分章节。按需读取入口见
|
||||
> [协议索引](../open-nodes-v1.md)。
|
||||
|
||||
## 附录 A:dml-v1 geometry 目录
|
||||
|
||||
写入时在以下名称前加 `dml:`,例如 `rect` 写成 `dml:rect`。当前目录共
|
||||
183 项,目录版本由 `catalogVersion = "dml-v1"` 标识。
|
||||
|
||||
```text
|
||||
accentBorderCallout1 accentBorderCallout2 accentBorderCallout3
|
||||
accentCallout1 accentCallout2 accentCallout3 actionButtonBackPrevious
|
||||
actionButtonBeginning actionButtonBlank actionButtonDocument actionButtonEnd
|
||||
actionButtonForwardNext actionButtonHelp actionButtonHome
|
||||
actionButtonInformation actionButtonMovie actionButtonReturn actionButtonSound
|
||||
active allGeneralization arc attribute bentArrow bentUpArrow bevel bind blockArc
|
||||
borderCallout1 borderCallout2 borderCallout3 bracePair bracketPair callout1
|
||||
callout2 callout3 can chevron chord circularArrow cloud cloudCallout comment
|
||||
component control convert corner cube curvedDownArrow curvedLeftArrow
|
||||
curvedRightArrow curvedUpArrow dataStorage decagon delete diagStripe diamond
|
||||
dodecagon donut doubleWave downArrow downArrowCallout ellipse ellipseRibbon
|
||||
ellipseRibbon2 entity entitySet flowChartAlternateProcess flowChartCollate
|
||||
flowChartConnector flowChartDecision flowChartDelay flowChartDisplay
|
||||
flowChartDocument flowChartExtract flowChartInputOutput flowChartInternalStorage
|
||||
flowChartMagneticDisk flowChartMagneticDrum flowChartMagneticTape
|
||||
flowChartManualInput flowChartManualOperation flowChartMerge
|
||||
flowChartMultidocument flowChartOffpageConnector flowChartOnlineStorage
|
||||
flowChartOr flowChartPredefinedProcess flowChartPreparation
|
||||
flowChartPunchedCard flowChartPunchedTape flowChartSort
|
||||
flowChartSummingJunction flowChartTerminator foldedCorner frame generalization
|
||||
halfFrame heart heptagon hexagon history homePlate horizontalDivCircle
|
||||
horizontalScroll irregularSeal1 irregularSeal2 leftArrow leftArrowCallout
|
||||
leftBrace leftBracket leftRightArrow leftRightArrowCallout leftRightUpArrow
|
||||
leftUpArrow lightningBolt mathDivide mathEqual mathMinus mathMultiply
|
||||
mathNotEqual mathPlus moon multiClass multiValuedAttribute noSmoking node
|
||||
nonIsoscelesTrapezoid notchedRightArrow octagon parallelogram pentagon person
|
||||
pie plaque plus quadArrow quadArrowCallout receiveSignal rect relationship
|
||||
ribbon ribbon2 rightArrow rightArrowCallout rightBrace rightBracket round1Rect
|
||||
round2DiagRect round2SameRect roundRect rtTriangle smileyFace snip1Rect
|
||||
snip2DiagRect snip2SameRect snipRoundRect star10 star12 star16 star24 star32
|
||||
star4 star5 star6 star7 star8 stripedRightArrow sun teardrop triangle upArrow
|
||||
upArrowCallout upDownArrow user uturnArrow verticalDivCircle verticalScroll
|
||||
wave weakEntitySet weakRelationship wedgeEllipseCallout wedgeRectCallout
|
||||
wedgeRoundRectCallout
|
||||
```
|
||||
|
||||
## 附录 B:dml-v1 icon 目录
|
||||
|
||||
写入时必须使用完整的 `<group>/<name>`。当前共 4 组 49 项,目录版本由
|
||||
`catalogVersion = "dml-v1"` 标识。
|
||||
|
||||
| group | 数量 | name(组成 `group/name`) |
|
||||
| --- | ---: | --- |
|
||||
| `emoji` | 14 | `happy`、`smile`、`laugh`、`fighting`、`like`、`ok`、`please`、`face-plam`、`tears-of-joy`、`cry`、`question`、`face-with-sweat`、`bloody-nose`、`doggy` |
|
||||
| `tools` | 21 | `pad`、`blue-note`、`yellow-notes`、`chart`、`chart-2`、`pencil`、`pen`、`bag`、`rocket`、`fire`、`gold`、`light`、`pin`、`red-flag`、`tea`、`island`、`ball`、`lucky-fish`、`coffee`、`milky-tea`、`pan` |
|
||||
| `priority` | 7 | `priority-1`、`priority-2`、`priority-3`、`priority-4`、`priority-5`、`priority-6`、`priority-7` |
|
||||
| `task` | 7 | `task-start`、`task-oct`、`task-3oct`、`task-half`、`task-5oct`、`task-7oct`、`task-done` |
|
||||
|
||||
注意:`emoji/face-plam` 是 V1 保留的历史兼容枚举值,拼写虽然异常但属于协议值;
|
||||
传入 `emoji/face-palm` 会被拒绝。
|
||||
Reference in New Issue
Block a user