用途:统一流程图制作标准,确保任何功能的流程图都能:
- 100% 还原真实业务逻辑(包括分支、回流、异常路径)
- 清晰展示三端联动(operate / control / front 的交互与影响)
- 提供完整节点详情(每个节点的触发条件、执行逻辑、后续分支、涉及数据、代码位置)
- 支持无限扩展(画布宽高不限,业务有多复杂流程图就撑多大)
每个操作都要说清楚:
┌────────────────────────────────────────────────┐
│ 顶部固定栏:标题 + 导航 + 图例 │
├────────────────────────────────────────────────┤
│ │
│ 流程画布(无限宽高,可滚动): │
│ ├─ 节点(圆角矩形,点击弹详情面板) │
│ ├─ 连线(SVG,不同颜色区分本端/跨端) │
│ └─ 分支(水平并排 / 树形分叉 / 回流箭头) │
│ │
└────────────────────────────────────────────────┘
#4A90E2,浅蓝背景 #E3F2FD,图标 🖥️#FF9800,浅橙背景 #FFF3E0,图标 ⚙️#9C27B0,浅紫背景 #F3E5F5,图标 💻#FFA726,琥珀背景 #FFF8E1,图标 ❓#F44336,浅红背景 #FFEBEE,图标 ⚠️<div class="flow-node" data-node-id="operate-add-dish">
<div class="node-icon">🖥️</div>
<div class="node-title">新建患者入箱</div>
<div class="node-tag">operate 端</div>
</div>
stroke-width: 2px
#4A90E2 蓝色#FF9800 橙色#9C27B0 紫色stroke-dasharray: 5,5
#4CAF50 绿色#00BCD4 青色stroke-dasharray: 3,3
#F44336 红色<marker id="arrowhead" markerWidth="8" markerHeight="6">
<polygon points="0 0, 8 3, 0 6" fill="继承连线颜色"/>
</marker>
点击任意节点,右侧滑出详情面板,必须包含以下板块:
【节点标题】新建患者入箱
【所属端】operate 操作端
【这步是什么】
医生在空舱点击,弹窗录入患者信息(夫妻姓名/病例号/周期/受精方式),
选 16 孔位放哪些胚胎,可选先平衡或直接开始培养。
【前置条件】
✓ 舱室状态 = 空舱(无培养皿)
✓ 用户已登录且有操作权限
✓ control 后台已启动、该舱硬件正常(串口/相机/电机正常)
【触发方式】
- operate 主界面(A2)点某个空舱格 → 弹 AddDishWindowView 弹窗
- 或 front 设备管理(D3)点空舱格 → 弹 AddDishWindow
【交互步骤】
1. 在 16 孔圆周上点选要放胚胎的孔位(可多选)
2. 填写表单:病例号、周期、女方/男方姓名、出生年月日、受精时间、受精方式
3. 可选:勾选"重点关注"(VIP)
4. 底部两个按钮:
- 【平衡】→ 先启动平衡流程(见分支 A)
- 【保存(开始培养)】→ 直接开始培养(见分支 B)
【后端逻辑】
1. operate 前端校验:必填项非空、孔位至少选一个、受精时间合法
2. 调接口:StartDishApi(POST /api/dish/start)
- 参数:舱号、患者信息、选中孔位列表、是否 VIP
- 后端落库:dish 表(培养皿)、embryo 表(胚胎,每个选中孔一条)
3. 发 MQTT 命令:topic `tl/command/{tlSn}`, type=StartDish
- control 后台收到 → AppData.StartDish → 舱状态改"培养中"
- 启动对焦+拍照节拍(见 C6 舱主循环)
【涉及数据】
- 数据库:dish 表插入一条(status=培养中),embryo 表插入 N 条
- 内存:HouseBin.CurrentDish 设为新 dishId,IsWorking=true
- 舱室状态:空闲 → 培养中(主界面该舱格变色+显示患者信息)
【三端联动影响】
本端动作:operate 点"开始培养"按钮
↓ 触发
后端/中间件:StartDishApi → dish 表插入 → MQTT 发 StartDish 命令
↓ 通知
control 后台:收到 MQTT → AppData.StartDish → HouseBin 状态改"培养中" → 启动对焦拍照循环
↓ 同步到
front 管理端:
- D3 设备管理首页:该舱格状态变"培养中",显示患者信息
- D7 培养记录列表:新增一条记录
↓ 反向影响
本端界面:A2 主界面该舱格变色+显示患者姓名
【后续分支】
→ 分支 A:点了"平衡"
→ 启动平衡流程(换气若干轮,duration 可配置)
→ 手动点"结束平衡"
→ 再点"开始培养"
→ 进入分支 B
→ 分支 B:点了"保存(开始培养)"
→ control 收到 StartDish
→ 进入 C6 舱主循环(温压监测 → 判断是否对焦 → 判断是否拍照)
【异常分支】
- 若该舱硬件异常(串口断/相机丢失)→ 前端提示"该舱室不可用",操作失败
- 若 control 后台未启动 → 前端提示"设备离线"
- 若正在平衡中又点"开始培养" → 校验失败,提示"请先结束平衡"
【代码位置】
- operate 前端:AddDishWindowView.xaml.cs:451 StartDish_Click
- operate 接口调用:StartDishApi (Urls.cs + ApiService)
- control 后台:AppData.cs:1102 StartDish → HouseBin.cs:614 MainThread
- 数据库表:dish、embryo、house_state
- MQTT topic:tl/command/{tlSn}
主干
↓
┌─────┴─────┐
↓ ↓
分支A 分支B
(冷冻) (鲜胚移植)
↓ ↓
[节点] [节点]
适用场景:两条独立且平行的路径(如冷冻 vs 鲜胚移植)
主干
↓
┌─────┼─────┐
↓ ↓ ↓
分支A 分支B 分支C
(移植) (冷冻) (删除)
适用场景:三条及以上分支(如胚胎去向:移植/冷冻/删除/作废)
[对焦] → [拍照]
↑ ↓
└←─[失败重试]
适用场景:失败重试、循环逻辑(如对焦失败→重新对焦)
[判断条件]
↙ ↘
[条件成立] [条件不成立]
适用场景:业务判断(如:是否首次对焦、是否到达拍照时间)
box-shadow: 0 4px 12px rgba(0,0,0,0.15)600px(不遮挡主画布)M x1,y1 L x2,y2M x1,y1 L x1,midY L x2,midY L x2,y2(适用跨模块)M x1,y1 Q cpX,cpY x2,y2(适用回流)<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>时差培养箱 - [功能名]业务流程图</title>
<style>
/* CSS 变量定义颜色 */
:root {
--operate-color: #4A90E2;
--control-color: #FF9800;
--front-color: #9C27B0;
--branch-color: #FFA726;
--error-color: #F44336;
}
/* 流程图容器:无限宽高 */
.flow-container {
position: relative;
min-width: 100vw;
min-height: 100vh;
padding: 100px;
}
</style>
</head>
<body>
<!-- 顶部固定栏 -->
<header class="top-bar">
<h1>时差培养箱 - [功能名]业务流程图</h1>
<nav><!-- 导航按钮 --></nav>
</header>
<!-- 流程画布 -->
<div class="flow-container" id="flowContainer">
<svg id="svgLines"></svg>
<!-- 节点由 JS 动态生成 -->
</div>
<!-- 详情面板 -->
<div class="detail-panel" id="detailPanel">
<!-- 动态填充 -->
</div>
<script>
// 节点数据 + 绘制逻辑
</script>
</body>
</html>
const flowData = {
nodes: [
{
id: 'operate-add-dish',
type: 'operate', // operate / control / front / branch / error
title: '新建患者入箱',
icon: '🖥️',
x: 200, // 绝对坐标
y: 100,
detail: {
description: '医生在空舱点击,弹窗录入患者信息...',
preconditions: ['舱室状态=空舱', '用户已登录'],
trigger: 'operate 主界面点空舱格',
steps: ['选孔位', '填表单', '点保存'],
backend: 'StartDishApi → dish表插入 → MQTT发StartDish',
dataChanges: ['dish表插入', 'HouseBin.CurrentDish设值'],
crossPlatform: {
from: 'operate 点按钮',
to: ['control 收到MQTT启动对焦拍照', 'front 界面显示新记录']
},
nextBranches: ['平衡流程', '直接开始培养'],
exceptions: ['硬件异常', 'control离线'],
codeLocation: ['AddDishWindowView.xaml.cs:451', 'AppData.cs:1102']
}
}
],
edges: [
{
from: 'operate-add-dish',
to: 'control-start-dish',
type: 'mqtt', // internal / api / mqtt / sync / error
label: 'MQTT StartDish'
}
]
};
端-功能-动作,如 operate-add-dish-save)[入箱] → [点击后可选:平衡 或 直接开始培养] → [开始培养]
纠正:必须画出真实分支
[入箱]
↓
┌─────┴─────┐
↓ ↓
[平衡] [直接开始培养]
↓ ↓
[结束平衡] ↓
↓ ↓
└─────┬─────┘
↓
[开始培养]
常见缺失:
纠正:严格按第三章的 10 个板块填写
所有连线都一个颜色 → 看不出哪些是本端流程、哪些是跨端调用
纠正:按第 2.3 节规范,用不同颜色 + 线型区分
.flow-container {
width: 1920px; /* ❌ 限死了 */
height: 1080px; /* ❌ 限死了 */
overflow: hidden; /* ❌ 超出部分被裁 */
}
纠正:使用 min-width / min-height + 允许滚动
.flow-container {
min-width: 100vw;
min-height: 100vh;
/* 不设 max-width / max-height */
}
时差培养箱-培养全流程详图.html(本次制作)C:/Users/AIVFO/Desktop/flow-click.html✅ 记住这三点,流程图就不会出错:
📌 每次制作前,先读这份规范,制作时对照清单逐项检查。