PlantUML Salt 表单、Form 表单、Json 视图:从数据到 UI
当你需要在文档里描述「长什么样的 UI」「数据是什么」「如何让用户填表」,PlantUML 三种专门图就能搞定——而无需画图工具、HTML 模板或专门的设计软件。
Salt(@startsalt)—— UI 线框图
Salt 是 PlantUML 最有用的「轻量级线框图」语言。它用 ASCII 框图就能画出真实可读的 UI:
1 2 3 4 5 6 7 8 9 10 11 12
| @startsalt {+ -------------------- | 订单详情 -------------------- 订单号:| "ORD-2026-001" 用户:| "Alice" 金额: | "299.00" . [取消] | [支付] } @endsalt
|
渲染出来就是一张 UI 线框:
|...| 文本输入框
[ ] 多选 / [X] 已选
{ } 窗体容器
.{...} 点线分组
+ 嵌套
. 空白垂直方向
完整可用语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @startsalt {+ 用户注册 .. 字段 | "值" ----------+-------- 用户名 | {"admin"} 密码 | {"pass"} -- 权限 | () 仅读 | () 读写 | (X) 管理员 通知 | [X] 邮件 | [ ] 短信 .. [确认] | [取消] } @endsalt
|
元素清单
| 元素 |
语法 |
渲染 |
| 文本输入框 |
[field] 或 "placeholder" |
可编辑框 |
| 已填值输入框 |
{"value"} |
填好的框 |
| 按钮 |
[button] |
按钮样式 |
| 单选 |
( ) / (X) |
圆圈空 / 圆圈实 |
| 多选 |
[ ] / [X] |
方框空 / 方框实 |
| 下拉 |
^single ^multi |
下拉选择 |
| 表格 |
{#col1, col2, ..., row1 \n row2, ...} |
表格 |
实战:登录表单
1 2 3 4 5 6 7 8 9 10 11
| @startsalt {+ 登录 ---- 账号: | "请输入邮箱" 密码: | "请输入密码" .. [^记住我] [登录] | [取消] } @endsalt
|
实战:用户设置页
1 2 3 4 5 6 7 8 9 10 11 12 13
| @startsalt {+ UserSettings { (基础 用户名: | {"alice"} 邮箱: | {"alice@example.com"} } { (权限 角色: | ( ) 成员 | ( ) 编辑 | (X) 管理员 } .. [保存] | [取消] } @endsalt
|
分组用 {} 嵌套。
实战:表格视图
1 2 3 4 5 6 7 8 9 10 11 12 13
| @startsalt {+ 订单列表 {#col1, col2, col3 列 A | 列 B | 列 C --- | ---- | ---- cell | cell | cell cell | cell | cell cell | cell | cell } .. [新增] | [导出] | [删除] } @endsalt
|
实战:标签页
1 2 3 4 5 6 7 8
| @startsalt {+ {/ <b>总览</b> | 设置 | 权限 | 历史 } { 当前页面内容 } .. [保存] | [取消] } @endsalt
|
实战:Markdown 嵌入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @startsalt {+ 文档编辑 == README.md 这个项目是一个 **富文本** 编辑器... 链接到 [PlantUML](https://plantuml.com) -- 分隔线 -- - 列表项 1 - 列表项 2 ```plantuml @startuml class Demo @enduml
|
==
}
@endsalt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| `==...==` 块里能写 Markdown,渲染成富文本。
## Form(@startform)—— 表单字段
`@startform` 是 Salt 的精简版,只画 form field:
```plantuml @startform {+ 提交反馈 姓名: | "请输入姓名" 邮箱: | "请输入邮箱" 反馈类型 | ( ) Bug | ( ) 功能 | (X) 建议 详细描述 | "..." .. [提交] | [取消] } @endform
|
跟 Salt 几乎一致但更轻。
JSON 视图(@startjson)
文档里展示 API 响应、配置文件的可视化:
API 响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @startjson { "code": 0, "message": "success", "data": { "user_id": 1024, "name": "Alice", "is_admin": false, "created_at": "2026-07-15T14:00:00Z", "permissions": [ "read", "write", "delete" ] } } @endjson
|
嵌套结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @startjson { "order": { "id": "ORD-001", "items": [ { "sku": "P1", "qty": 2, "price": 49.99 }, { "sku": "P2", "qty": 1, "price": 99.00 } ], "totals": { "subtotal": 198.98, "tax": 19.90, "total": 218.88 } } } @endjson
|
YAML 视图(@startyaml)
跟 @startjson 平行,YAML 风格:
1 2 3 4 5 6 7 8 9
| @startyaml --- server: port: 8080 timeout: 30s logging: level: info --- @endyaml
|
JSON 视图 —— 跟 UI 配对
最常见的 UI 文档就是「画面 + 数据」两图对照:
1 2 3 4 5 6 7 8 9 10 11
| @startsalt {+ 用户主页 {/ 个人 | 订单 | 收藏 } { 头像: | <img> 名字: | "Alice" 注册时间: | "2026-07-15" 简介: | "..." } } @endsalt
|
配套 JSON:
1 2 3 4 5 6 7 8 9
| @startjson { "user_id": 1024, "avatar_url": "https://cdn.example.com/avatars/1024.png", "name": "Alice", "created_at": "2026-07-15T14:00:00Z", "bio": "..." } @endjson
|
UI 元素和数据字段一一对应,文档清晰。
实战:完整登录文档
1 2 3 4 5 6
| docs/login/ login-ui.puml # @startsalt login-request.puml # @startjson POST /login 请求体 login-response.puml # @startjson POST /login 响应体 login-errors.puml # @startjson 错误响应 login-sequence.puml # @startuml sequence
|
5 个 .puml 文件覆盖完整的「登录 API + UI + 错误」文档。
错误代码展示
1 2 3 4 5 6 7 8 9 10
| @startjson { "code": 40001, "message": "invalid input", "errors": [ { "field": "email", "message": "必须为合法邮箱地址" }, { "field": "password", "message": "至少 8 个字符" } ] } @endjson
|
前端 form 校验错误提示文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @startsalt {+ 登录失败 账号: | "alice|" 密码: | "" . {# 错误 | 字段 ----- | ----- 必须为合法邮箱地址 | 账号 至少 8 个字符 | 密码 } .. [重试] } @endsalt
|
Salt 跨元素渲染
复杂 UI 用嵌套 {} + 表格 + 按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @startsalt {+ 后台 - 数据看板 {/ <b>实时</b> | 7 天 | 30 天 | 自定义 } { { 指标卡片 (7 天) { PV: 12,345 | UV: 4,567 | 转化: 3.2% | 跳出: 21% . [+添加] | [导出] } } { {# 热门页面, 页面 | PV | 占比 ----- | -- | ---- 首页 | 8000 | 35% 商品页 | 5000 | 22% 详情页 | 3000 | 13% } } } @endsalt
|
选最佳方案
| 需求 |
用什么 |
| 线框图 / UI 草图 |
@startsalt |
| 表单字段 |
@startform |
| API 响应 / 配置数据 |
@startjson |
| 配置文件 |
@startyaml |
| 时序 / 类 / 组件 |
标准 @startuml |
反模式
1. Salt 框进各种实际样式
1 2 3 4 5
| @startsalt {+ login email: | <input type="email" class="..."> } @endsalt
|
Salt 不支持富样式。要写复杂 UI 改用真实 HTML/CSS 模板或截图。
2. JSON 不带 @startjson
1 2 3 4 5 6
| @startuml { "code": 0, "data": [] } @enduml
|
不会自动展开,必须 @startjson。
3. 嵌套 UI 太深
1 2 3
| @startsalt {+ root { { { { {... deep nested ... } } } } } @endsalt
|
UI 超过 3 层嵌套,就用真实设计工具(Figma 等)。
评审 checklist
Salt
JSON
一句话总结
Salt 把「线框图」拉回到 ASCII 文本层面,跟时序图、JSON 数据图保持同样的可 diffable 风格——文档图跟代码一起进仓库,一起 review。