Mermaid 与 PlantUML 使用指南:从入门到写出可维护的技术图表
如果你经常写技术文档、设计说明、接口文档或者架构方案,应该会遇到一个问题:图一旦多起来,就会越来越难维护。
传统画图工具适合一次性出图,但不太适合频繁修改。流程一变、接口一改、模块一重构,往往就得重新拖拽、对齐、导出。相比之下,Mermaid 和 PlantUML 这种"用文本生成图表"的方式更适合开发团队:它们可以纳入 Git、可以直接放进文档、可以复用,也更容易随着项目一起演进。
这篇文章会用教程式的方式,带你了解:
- Mermaid 和 PlantUML 分别是什么
- Mermaid 为什么会在 Markdown 中自动渲染
- 如何同时展示 Mermaid 渲染效果和源码
- Mermaid 与 PlantUML 的常见写法和适用场景
- 实际项目里该怎么选
1. 为什么要用文本画图
文本画图最大的价值,不是"更炫",而是"更容易维护"。
它有几个非常实际的优势:
- 图表内容可以直接纳入 Git 版本管理
- 修改成本低,适合频繁迭代的项目
- 可以直接嵌入 Markdown、Wiki、文档站点
- 团队成员可以像审查代码一样审查图表
- 图表不再是一次性图片,而是可持续维护的文档资产
如果你的工作里经常要写 README、接口说明、架构设计、系统流程,那么这类工具通常会比拖拽式画图工具更省心。
2. Mermaid 是什么
Mermaid 是一种基于文本语法生成图表的工具,常见于 Markdown 文档、知识库、静态文档站点以及部分编辑器预览环境中。
它的特点很适合入门:
- 语法比较简单,上手快
- 对流程图、时序图支持很好
- 非常适合写在 README 和技术文档里
- 和 Markdown 生态结合得很自然
先看一个最小示例。
2.1 渲染效果
#mermaid-svg-TafhnQtCqDFa0ijP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TafhnQtCqDFa0ijP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TafhnQtCqDFa0ijP .error-icon{fill:#552222;}#mermaid-svg-TafhnQtCqDFa0ijP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TafhnQtCqDFa0ijP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .marker.cross{stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TafhnQtCqDFa0ijP p{margin:0;}#mermaid-svg-TafhnQtCqDFa0ijP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label text{fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label span{color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label span p{background-color:transparent;}#mermaid-svg-TafhnQtCqDFa0ijP .label text,#mermaid-svg-TafhnQtCqDFa0ijP span{fill:#333;color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .node rect,#mermaid-svg-TafhnQtCqDFa0ijP .node circle,#mermaid-svg-TafhnQtCqDFa0ijP .node ellipse,#mermaid-svg-TafhnQtCqDFa0ijP .node polygon,#mermaid-svg-TafhnQtCqDFa0ijP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .rough-node .label text,#mermaid-svg-TafhnQtCqDFa0ijP .node .label text,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label,#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label{text-anchor:middle;}#mermaid-svg-TafhnQtCqDFa0ijP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .rough-node .label,#mermaid-svg-TafhnQtCqDFa0ijP .node .label,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label,#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label{text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .node.clickable{cursor:pointer;}#mermaid-svg-TafhnQtCqDFa0ijP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .arrowheadPath{fill:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TafhnQtCqDFa0ijP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TafhnQtCqDFa0ijP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster text{fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster span{color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TafhnQtCqDFa0ijP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP rect.text{fill:none;stroke-width:0;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape p,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label rect,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TafhnQtCqDFa0ijP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TafhnQtCqDFa0ijP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
用户登录
认证成功?
进入首页
提示错误信息
2.2 对应语法
markdown
```mermaid
flowchart TD
A[用户登录] --> B{认证成功?}
B -->|是| C[进入首页]
B -->|否| D[提示错误信息]
D --> A
```
2.3 这一段语法怎么看
flowchart TD表示这是一个流程图,方向是从上到下A[用户登录]表示一个矩形节点B{认证成功?}表示一个判断节点-->表示连接关系|是|、|否|表示边上的文字说明
如果你是第一次接触 Mermaid,建议先记住一个思路:先写节点,再写连接,最后补方向和说明文字。
3. Mermaid 为什么会在 Markdown 中自动渲染
很多人第一次看到 Mermaid 时都会疑惑:明明我写的是代码块,为什么页面上显示的是图?
原因其实很简单:Markdown 本身不会渲染 Mermaid,真正起作用的是"支持 Mermaid 的渲染环境"。
也就是说:
- 普通 Markdown 语法只负责保存文本结构
- 当预览器、编辑器或文档平台识别到代码块类型是
mermaid时 - 它会把这段文本交给 Mermaid 引擎渲染成图表
例如这段代码:
markdown
```mermaid
flowchart LR
A[前端] --> B[网关]
B --> C[服务A]
B --> D[服务B]
```
在不同环境里的表现可能不一样:
- 在普通 Markdown 查看器里,可能只会显示源码
- 在支持 Mermaid 的预览器里,会直接显示成图
常见支持场景包括:
- GitHub 的部分 Markdown 场景
- VuePress / VitePress / Docusaurus 文档站点
- 一些 Wiki 或知识库系统
- Typora、Obsidian 等支持 Mermaid 的编辑器
- 安装 Mermaid 扩展后的 VS Code 预览环境
4. 如何同时展示 Mermaid 图和源码
如果你只是写一个 mermaid 代码块,那么在支持 Mermaid 的环境里,读者通常只能看到渲染结果,而看不到原始语法。
如果你写的是教程文章,最推荐的方式是把内容分成两部分:
- 第一部分叫"渲染效果",用真正的
mermaid代码块 - 第二部分叫"对应语法",用
markdown代码块原样展示 Mermaid 源码
这样读者既能看懂图,也能学会怎么写。
4.1 推荐写法
渲染效果
#mermaid-svg-UiLnOaMLPc4XuSN7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UiLnOaMLPc4XuSN7 .error-icon{fill:#552222;}#mermaid-svg-UiLnOaMLPc4XuSN7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UiLnOaMLPc4XuSN7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .marker.cross{stroke:#333333;}#mermaid-svg-UiLnOaMLPc4XuSN7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UiLnOaMLPc4XuSN7 p{margin:0;}#mermaid-svg-UiLnOaMLPc4XuSN7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster-label text{fill:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster-label span{color:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster-label span p{background-color:transparent;}#mermaid-svg-UiLnOaMLPc4XuSN7 .label text,#mermaid-svg-UiLnOaMLPc4XuSN7 span{fill:#333;color:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .node rect,#mermaid-svg-UiLnOaMLPc4XuSN7 .node circle,#mermaid-svg-UiLnOaMLPc4XuSN7 .node ellipse,#mermaid-svg-UiLnOaMLPc4XuSN7 .node polygon,#mermaid-svg-UiLnOaMLPc4XuSN7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .rough-node .label text,#mermaid-svg-UiLnOaMLPc4XuSN7 .node .label text,#mermaid-svg-UiLnOaMLPc4XuSN7 .image-shape .label,#mermaid-svg-UiLnOaMLPc4XuSN7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-UiLnOaMLPc4XuSN7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .rough-node .label,#mermaid-svg-UiLnOaMLPc4XuSN7 .node .label,#mermaid-svg-UiLnOaMLPc4XuSN7 .image-shape .label,#mermaid-svg-UiLnOaMLPc4XuSN7 .icon-shape .label{text-align:center;}#mermaid-svg-UiLnOaMLPc4XuSN7 .node.clickable{cursor:pointer;}#mermaid-svg-UiLnOaMLPc4XuSN7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .arrowheadPath{fill:#333333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UiLnOaMLPc4XuSN7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UiLnOaMLPc4XuSN7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UiLnOaMLPc4XuSN7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster text{fill:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 .cluster span{color:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UiLnOaMLPc4XuSN7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UiLnOaMLPc4XuSN7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-UiLnOaMLPc4XuSN7 .icon-shape,#mermaid-svg-UiLnOaMLPc4XuSN7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UiLnOaMLPc4XuSN7 .icon-shape p,#mermaid-svg-UiLnOaMLPc4XuSN7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UiLnOaMLPc4XuSN7 .icon-shape .label rect,#mermaid-svg-UiLnOaMLPc4XuSN7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UiLnOaMLPc4XuSN7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UiLnOaMLPc4XuSN7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UiLnOaMLPc4XuSN7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 前端
网关
服务A
服务B
对应语法
markdown
```mermaid
flowchart LR
A[前端] --> B[网关]
B --> C[服务A]
B --> D[服务B]
```
4.2 为什么外层用了四个反引号
因为你要在 Markdown 里展示一段"带三个反引号的代码块",所以外层必须用更多反引号把它包起来。
否则 Markdown 会误以为内部的三个反引号已经结束了代码块。
这个技巧很实用,写教程时经常会用到。
5. Mermaid 常见用法
下面用"效果 + 语法 + 说明"的方式,分别看几个最常见的 Mermaid 图。
5.1 流程图
流程图是 Mermaid 最常见的用途之一,适合描述业务步骤、程序流程、审批逻辑等。
渲染效果
#mermaid-svg-FtXQogeVvSDqqqaF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FtXQogeVvSDqqqaF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FtXQogeVvSDqqqaF .error-icon{fill:#552222;}#mermaid-svg-FtXQogeVvSDqqqaF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FtXQogeVvSDqqqaF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FtXQogeVvSDqqqaF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FtXQogeVvSDqqqaF .marker.cross{stroke:#333333;}#mermaid-svg-FtXQogeVvSDqqqaF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FtXQogeVvSDqqqaF p{margin:0;}#mermaid-svg-FtXQogeVvSDqqqaF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FtXQogeVvSDqqqaF .cluster-label text{fill:#333;}#mermaid-svg-FtXQogeVvSDqqqaF .cluster-label span{color:#333;}#mermaid-svg-FtXQogeVvSDqqqaF .cluster-label span p{background-color:transparent;}#mermaid-svg-FtXQogeVvSDqqqaF .label text,#mermaid-svg-FtXQogeVvSDqqqaF span{fill:#333;color:#333;}#mermaid-svg-FtXQogeVvSDqqqaF .node rect,#mermaid-svg-FtXQogeVvSDqqqaF .node circle,#mermaid-svg-FtXQogeVvSDqqqaF .node ellipse,#mermaid-svg-FtXQogeVvSDqqqaF .node polygon,#mermaid-svg-FtXQogeVvSDqqqaF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FtXQogeVvSDqqqaF .rough-node .label text,#mermaid-svg-FtXQogeVvSDqqqaF .node .label text,#mermaid-svg-FtXQogeVvSDqqqaF .image-shape .label,#mermaid-svg-FtXQogeVvSDqqqaF .icon-shape .label{text-anchor:middle;}#mermaid-svg-FtXQogeVvSDqqqaF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FtXQogeVvSDqqqaF .rough-node .label,#mermaid-svg-FtXQogeVvSDqqqaF .node .label,#mermaid-svg-FtXQogeVvSDqqqaF .image-shape .label,#mermaid-svg-FtXQogeVvSDqqqaF .icon-shape .label{text-align:center;}#mermaid-svg-FtXQogeVvSDqqqaF .node.clickable{cursor:pointer;}#mermaid-svg-FtXQogeVvSDqqqaF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FtXQogeVvSDqqqaF .arrowheadPath{fill:#333333;}#mermaid-svg-FtXQogeVvSDqqqaF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FtXQogeVvSDqqqaF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FtXQogeVvSDqqqaF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FtXQogeVvSDqqqaF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FtXQogeVvSDqqqaF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FtXQogeVvSDqqqaF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FtXQogeVvSDqqqaF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FtXQogeVvSDqqqaF .cluster text{fill:#333;}#mermaid-svg-FtXQogeVvSDqqqaF .cluster span{color:#333;}#mermaid-svg-FtXQogeVvSDqqqaF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FtXQogeVvSDqqqaF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FtXQogeVvSDqqqaF rect.text{fill:none;stroke-width:0;}#mermaid-svg-FtXQogeVvSDqqqaF .icon-shape,#mermaid-svg-FtXQogeVvSDqqqaF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FtXQogeVvSDqqqaF .icon-shape p,#mermaid-svg-FtXQogeVvSDqqqaF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FtXQogeVvSDqqqaF .icon-shape .label rect,#mermaid-svg-FtXQogeVvSDqqqaF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FtXQogeVvSDqqqaF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FtXQogeVvSDqqqaF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FtXQogeVvSDqqqaF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
开始
读取配置
配置有效?
启动服务
输出错误并退出
结束
对应语法
markdown
```mermaid
flowchart TD
Start([开始]) --> Input[读取配置]
Input --> Check{配置有效?}
Check -->|是| Run[启动服务]
Check -->|否| Error[输出错误并退出]
Run --> End([结束])
Error --> End
```
语法说明
常见方向:
TD:从上到下LR:从左到右
常见节点写法:
A[矩形节点]A(圆角节点)A{判断节点}A([开始/结束])
5.2 时序图
时序图很适合描述接口调用、认证流程、服务交互和消息传递链路。
渲染效果
Database Backend Frontend User Database Backend Frontend User #mermaid-svg-iJVER4wluIazkAhP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iJVER4wluIazkAhP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iJVER4wluIazkAhP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iJVER4wluIazkAhP .error-icon{fill:#552222;}#mermaid-svg-iJVER4wluIazkAhP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iJVER4wluIazkAhP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iJVER4wluIazkAhP .marker.cross{stroke:#333333;}#mermaid-svg-iJVER4wluIazkAhP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iJVER4wluIazkAhP p{margin:0;}#mermaid-svg-iJVER4wluIazkAhP .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-iJVER4wluIazkAhP .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-iJVER4wluIazkAhP .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .sequenceNumber{fill:white;}#mermaid-svg-iJVER4wluIazkAhP #sequencenumber{fill:#333;}#mermaid-svg-iJVER4wluIazkAhP #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .messageText{fill:#333;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP .labelText,#mermaid-svg-iJVER4wluIazkAhP .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .loopText,#mermaid-svg-iJVER4wluIazkAhP .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-iJVER4wluIazkAhP .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-iJVER4wluIazkAhP .noteText,#mermaid-svg-iJVER4wluIazkAhP .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .actorPopupMenu{position:absolute;}#mermaid-svg-iJVER4wluIazkAhP .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-iJVER4wluIazkAhP .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP .actor-man circle,#mermaid-svg-iJVER4wluIazkAhP line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-iJVER4wluIazkAhP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 提交登录表单发送登录请求查询用户信息返回用户记录返回 Token登录成功
对应语法
markdown
```mermaid
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend
participant D as Database
U->>F: 提交登录表单
F->>B: 发送登录请求
B->>D: 查询用户信息
D-->>B: 返回用户记录
B-->>F: 返回 Token
F-->>U: 登录成功
```
语法说明
sequenceDiagram表示时序图participant用来声明参与者as可以给参与者设置显示名称->>表示发送消息-->>常用于返回结果
5.3 类图
Mermaid 也支持类图,适合做轻量级结构说明。
渲染效果
#mermaid-svg-Y0q3TApC3G5VOGjI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Y0q3TApC3G5VOGjI .error-icon{fill:#552222;}#mermaid-svg-Y0q3TApC3G5VOGjI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Y0q3TApC3G5VOGjI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Y0q3TApC3G5VOGjI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Y0q3TApC3G5VOGjI .marker.cross{stroke:#333333;}#mermaid-svg-Y0q3TApC3G5VOGjI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Y0q3TApC3G5VOGjI p{margin:0;}#mermaid-svg-Y0q3TApC3G5VOGjI g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Y0q3TApC3G5VOGjI g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster-label text{fill:#333;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster-label span{color:#333;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster-label span p{background-color:transparent;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster text{fill:#333;}#mermaid-svg-Y0q3TApC3G5VOGjI .cluster span{color:#333;}#mermaid-svg-Y0q3TApC3G5VOGjI .nodeLabel,#mermaid-svg-Y0q3TApC3G5VOGjI .edgeLabel{color:#131300;}#mermaid-svg-Y0q3TApC3G5VOGjI .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Y0q3TApC3G5VOGjI .label text{fill:#131300;}#mermaid-svg-Y0q3TApC3G5VOGjI .labelBkg{background:#ECECFF;}#mermaid-svg-Y0q3TApC3G5VOGjI .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Y0q3TApC3G5VOGjI .classTitle{font-weight:bolder;}#mermaid-svg-Y0q3TApC3G5VOGjI .node rect,#mermaid-svg-Y0q3TApC3G5VOGjI .node circle,#mermaid-svg-Y0q3TApC3G5VOGjI .node ellipse,#mermaid-svg-Y0q3TApC3G5VOGjI .node polygon,#mermaid-svg-Y0q3TApC3G5VOGjI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Y0q3TApC3G5VOGjI .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI g.clickable{cursor:pointer;}#mermaid-svg-Y0q3TApC3G5VOGjI g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Y0q3TApC3G5VOGjI g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Y0q3TApC3G5VOGjI .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Y0q3TApC3G5VOGjI .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Y0q3TApC3G5VOGjI .dashed-line{stroke-dasharray:3;}#mermaid-svg-Y0q3TApC3G5VOGjI .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-Y0q3TApC3G5VOGjI #compositionStart,#mermaid-svg-Y0q3TApC3G5VOGjI .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #compositionEnd,#mermaid-svg-Y0q3TApC3G5VOGjI .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #dependencyStart,#mermaid-svg-Y0q3TApC3G5VOGjI .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #dependencyStart,#mermaid-svg-Y0q3TApC3G5VOGjI .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #extensionStart,#mermaid-svg-Y0q3TApC3G5VOGjI .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #extensionEnd,#mermaid-svg-Y0q3TApC3G5VOGjI .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #aggregationStart,#mermaid-svg-Y0q3TApC3G5VOGjI .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #aggregationEnd,#mermaid-svg-Y0q3TApC3G5VOGjI .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #lollipopStart,#mermaid-svg-Y0q3TApC3G5VOGjI .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI #lollipopEnd,#mermaid-svg-Y0q3TApC3G5VOGjI .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Y0q3TApC3G5VOGjI .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-Y0q3TApC3G5VOGjI .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Y0q3TApC3G5VOGjI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Y0q3TApC3G5VOGjI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Y0q3TApC3G5VOGjI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} User
+String name
+login()
+logout()
Admin
+manageUser()
对应语法
markdown
```mermaid
classDiagram
class User {
+String name
+login()
+logout()
}
class Admin {
+manageUser()
}
User <|-- Admin
```
语法说明
classDiagram表示类图class User { ... }用来定义类+常表示公开成员<|--表示继承关系
如果类图只是简单展示结构,Mermaid 足够好用;但如果要表达更完整的 UML 关系,PlantUML 通常更强。
6. PlantUML 是什么
PlantUML 同样是一种"用文本生成图表"的工具,但它更偏向 UML 建模和工程化表达。
它的特点是:
- UML 图支持更完整
- 类图、用例图、组件图、部署图更强
- 更适合架构设计、系统分析、正式设计文档
- 语法能力更丰富,但学习成本也略高一些
先看一个最小示例。
plantuml
@startuml
Alice -> Bob: Hello
Bob --> Alice: Hi
@enduml
这会生成一个简单的时序图。
7. PlantUML 常见用法
7.1 基本结构
PlantUML 最常见的写法,是以 @startuml 开始,以 @enduml 结束。
plantuml
@startuml
actor User
participant Frontend
participant Backend
User -> Frontend: 登录
Frontend -> Backend: 验证账号密码
Backend --> Frontend: 返回结果
Frontend --> User: 展示登录结果
@enduml
这一对标记可以理解为:告诉 PlantUML,"下面这段内容是一张图的定义"。
7.2 类图
PlantUML 在类图方面非常强大,表达能力明显强于 Mermaid。
plantuml
@startuml
class User {
-id: Long
-name: String
+login()
+logout()
}
class Order {
-orderId: String
-amount: Decimal
+create()
+cancel()
}
User "1" --> "*" Order : owns
@enduml
你可以清晰表达:
- 属性与方法
- 访问修饰符
- 继承、实现、关联、聚合、组合
- 多重性关系
7.3 用例图
plantuml
@startuml
left to right direction
actor User
actor Admin
rectangle System {
usecase "登录" as UC1
usecase "查看订单" as UC2
usecase "管理用户" as UC3
}
User --> UC1
User --> UC2
Admin --> UC1
Admin --> UC3
@enduml
这种图很适合需求分析和系统建模阶段使用。
7.4 组件图
plantuml
@startuml
package "Web Layer" {
[Frontend]
[API Gateway]
}
package "Service Layer" {
[User Service]
[Order Service]
}
database "MySQL" as DB
[Frontend] --> [API Gateway]
[API Gateway] --> [User Service]
[API Gateway] --> [Order Service]
[User Service] --> DB
[Order Service] --> DB
@enduml
如果你要写系统架构说明、模块划分或服务依赖关系,这类图很有帮助。
8. Mermaid 和 PlantUML 怎么选
如果只用一句话概括:
- 想快速写文档、写流程说明、写 README,用 Mermaid
- 想严谨表达 UML、建模系统结构,用 PlantUML
更具体一点:
8.1 Mermaid 更适合
- Markdown 文档
- 轻量流程图
- 时序图
- 项目 README
- 前后端开发说明
- 团队知识库
8.2 PlantUML 更适合
- UML 建模
- 类图、组件图、部署图
- 架构设计文档
- 复杂系统关系表达
- 正式的分析与设计资料
可以简单理解为:
- Mermaid 偏"轻文档化"
- PlantUML 偏"强建模化"
9. 两者对比
| 对比项 | Mermaid | PlantUML |
|---|---|---|
| 上手难度 | 低 | 中 |
| 文档集成 | 很强 | 较强 |
| UML 支持完整度 | 一般 | 很强 |
| 流程图体验 | 很好 | 不错 |
| 类图能力 | 基础够用 | 非常强 |
| 架构建模能力 | 中等 | 很强 |
| 适合场景 | Markdown/文档说明 | 设计文档/架构建模 |
如果你的目标是"快速把图写进文档",Mermaid 往往更省事。
如果你的目标是"把系统结构表达得更完整、更专业",PlantUML 往往更合适。
10. 实际使用建议
在真实项目里,我比较推荐下面这种分工方式:
- README、接口文档、流程说明:优先用 Mermaid
- 领域模型、模块设计、部署结构:优先用 PlantUML
- 文档平台已经支持 Mermaid 时,尽量就近使用
- 需要长期沉淀设计资产时,优先考虑 PlantUML
一个很好记的经验是:
"用 Mermaid 管文档里的图,用 PlantUML 管设计里的图。"
11. 常见问题
11.1 Mermaid 和 PlantUML 能放进 Git 吗?
当然可以。它们本质上就是文本文件,非常适合版本管理。
11.2 它们能导出图片吗?
可以。常见方式包括:
- 编辑器插件导出
- 本地命令行工具导出
- 在线渲染工具导出
- 文档站点构建时自动渲染
11.3 哪个更适合新手?
Mermaid 更适合新手,因为语法更简单,和 Markdown 结合也更自然。
11.4 哪个更适合架构师或正式设计文档?
PlantUML 更适合,因为它对 UML 的支持更全面。
11.5 为什么我的 Mermaid 没有自动渲染?
最常见的原因不是语法写错,而是你当前使用的 Markdown 预览器本身不支持 Mermaid。
要实现自动渲染,通常需要满足以下条件之一:
- 编辑器原生支持 Mermaid
- 安装了 Mermaid 预览插件
- 文档平台已经启用了 Mermaid 渲染能力
如果你只是用普通的 Markdown 查看器直接打开文件,它通常只会把 Mermaid 当作普通代码块显示。
12. 结语
Mermaid 和 PlantUML 的核心价值,不是替代所有画图工具,而是让图表像代码一样可维护。
当你的项目开始重视文档质量、架构清晰度和团队协作效率时,这类工具的价值会越来越明显。Mermaid 适合快速表达,PlantUML 适合严谨建模。掌握它们之后,你会发现很多原来需要截图、拖拽、反复修改的图,现在几行文本就能完成。
如果你经常写技术文档,建议先掌握 Mermaid;如果你还需要输出更正式的系统设计资料,再进一步学习 PlantUML。
附:文中示例汇总
Mermaid 流程图效果
#mermaid-svg-TafhnQtCqDFa0ijP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TafhnQtCqDFa0ijP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TafhnQtCqDFa0ijP .error-icon{fill:#552222;}#mermaid-svg-TafhnQtCqDFa0ijP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TafhnQtCqDFa0ijP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TafhnQtCqDFa0ijP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .marker.cross{stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TafhnQtCqDFa0ijP p{margin:0;}#mermaid-svg-TafhnQtCqDFa0ijP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label text{fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label span{color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster-label span p{background-color:transparent;}#mermaid-svg-TafhnQtCqDFa0ijP .label text,#mermaid-svg-TafhnQtCqDFa0ijP span{fill:#333;color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .node rect,#mermaid-svg-TafhnQtCqDFa0ijP .node circle,#mermaid-svg-TafhnQtCqDFa0ijP .node ellipse,#mermaid-svg-TafhnQtCqDFa0ijP .node polygon,#mermaid-svg-TafhnQtCqDFa0ijP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .rough-node .label text,#mermaid-svg-TafhnQtCqDFa0ijP .node .label text,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label,#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label{text-anchor:middle;}#mermaid-svg-TafhnQtCqDFa0ijP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .rough-node .label,#mermaid-svg-TafhnQtCqDFa0ijP .node .label,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label,#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label{text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .node.clickable{cursor:pointer;}#mermaid-svg-TafhnQtCqDFa0ijP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .arrowheadPath{fill:#333333;}#mermaid-svg-TafhnQtCqDFa0ijP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TafhnQtCqDFa0ijP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TafhnQtCqDFa0ijP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster text{fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP .cluster span{color:#333;}#mermaid-svg-TafhnQtCqDFa0ijP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TafhnQtCqDFa0ijP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TafhnQtCqDFa0ijP rect.text{fill:none;stroke-width:0;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape p,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TafhnQtCqDFa0ijP .icon-shape .label rect,#mermaid-svg-TafhnQtCqDFa0ijP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TafhnQtCqDFa0ijP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TafhnQtCqDFa0ijP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TafhnQtCqDFa0ijP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
用户登录
认证成功?
进入首页
提示错误信息
Mermaid 流程图语法
markdown
```mermaid
flowchart TD
A[用户登录] --> B{认证成功?}
B -->|是| C[进入首页]
B -->|否| D[提示错误信息]
D --> A
```
Mermaid 时序图效果
Database Backend Frontend User Database Backend Frontend User #mermaid-svg-iJVER4wluIazkAhP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iJVER4wluIazkAhP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iJVER4wluIazkAhP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iJVER4wluIazkAhP .error-icon{fill:#552222;}#mermaid-svg-iJVER4wluIazkAhP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iJVER4wluIazkAhP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iJVER4wluIazkAhP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iJVER4wluIazkAhP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iJVER4wluIazkAhP .marker.cross{stroke:#333333;}#mermaid-svg-iJVER4wluIazkAhP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iJVER4wluIazkAhP p{margin:0;}#mermaid-svg-iJVER4wluIazkAhP .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-iJVER4wluIazkAhP .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-iJVER4wluIazkAhP .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .sequenceNumber{fill:white;}#mermaid-svg-iJVER4wluIazkAhP #sequencenumber{fill:#333;}#mermaid-svg-iJVER4wluIazkAhP #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-iJVER4wluIazkAhP .messageText{fill:#333;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP .labelText,#mermaid-svg-iJVER4wluIazkAhP .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .loopText,#mermaid-svg-iJVER4wluIazkAhP .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-iJVER4wluIazkAhP .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-iJVER4wluIazkAhP .noteText,#mermaid-svg-iJVER4wluIazkAhP .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-iJVER4wluIazkAhP .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-iJVER4wluIazkAhP .actorPopupMenu{position:absolute;}#mermaid-svg-iJVER4wluIazkAhP .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-iJVER4wluIazkAhP .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-iJVER4wluIazkAhP .actor-man circle,#mermaid-svg-iJVER4wluIazkAhP line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-iJVER4wluIazkAhP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 提交登录表单发送登录请求查询用户信息返回用户记录返回 Token登录成功
Mermaid 时序图语法
markdown
```mermaid
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend
participant D as Database
U->>F: 提交登录表单
F->>B: 发送登录请求
B->>D: 查询用户信息
D-->>B: 返回用户记录
B-->>F: 返回 Token
F-->>U: 登录成功
```
PlantUML 类图
plantuml
@startuml
class User {
-id: Long
-name: String
+login()
+logout()
}
class Order {
-orderId: String
-amount: Decimal
+create()
+cancel()
}
User "1" --> "*" Order : owns
@enduml
PlantUML 组件图
plantuml
@startuml
package "Web Layer" {
[Frontend]
[API Gateway]
}
package "Service Layer" {
[User Service]
[Order Service]
}
database "MySQL" as DB
[Frontend] --> [API Gateway]
[API Gateway] --> [User Service]
[API Gateway] --> [Order Service]
[User Service] --> DB
[Order Service] --> DB
@enduml