Files
qiming/qimingclaw/crates/agent-electron-client/public/sgrobot-digital/report/flows.html

661 lines
36 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sgRobot 业务流程与架构模块映射</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.theme-dark-blue { background-color: #0d2758; }
.theme-text-dark-blue { color: #0d2758; }
.theme-light-blue-bg { background-color: #f0f6fc; }
.theme-border-blue { border-color: #aec3db; }
.theme-red { color: #d92d20; }
body {
font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", "Source Han Sans SC", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 18px;
}
.text-xs { font-size: 0.92rem !important; }
.text-sm { font-size: 1.08rem !important; }
.text-base { font-size: 1.24rem !important; }
.text-lg { font-size: 1.4rem !important; }
.text-xl { font-size: 1.62rem !important; }
.text-3xl { font-size: 2.75rem !important; }
.text-\[13px\] { font-size: 1.14rem !important; }
[data-tip] {
cursor: help;
}
.module-map {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
}
.module-card {
border: 1px solid #aec3db;
border-radius: 8px;
background: white;
box-shadow: 0 6px 16px rgba(13, 39, 88, 0.07);
overflow: hidden;
}
.module-title {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
color: white;
background: #0d2758;
font-weight: 800;
line-height: 1.25;
}
.module-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 10px;
background: #f0f6fc;
}
.module-pill {
border: 1px solid #c8d7e8;
border-radius: 999px;
padding: 3px 9px;
background: white;
color: #0d2758;
font-size: 0.9rem;
font-weight: 700;
white-space: nowrap;
}
.flow-card {
border: 1px solid #aec3db;
border-radius: 8px;
background: white;
box-shadow: 0 8px 20px rgba(13, 39, 88, 0.08);
overflow: hidden;
}
.flow-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 16px 10px 16px;
border-bottom: 1px solid #d8e4f2;
}
.flow-title {
display: flex;
align-items: center;
gap: 10px;
color: #0d2758;
font-weight: 800;
font-size: 1.22rem;
line-height: 1.25;
}
.flow-tag {
border: 1px solid #c8d7e8;
border-radius: 999px;
padding: 3px 10px;
color: #5f7082;
background: #f8fbff;
font-weight: 700;
white-space: nowrap;
font-size: 0.92rem;
}
.flow-note {
padding: 9px 16px;
background: #f8fbff;
color: #5f7082;
border-bottom: 1px solid #d8e4f2;
font-weight: 700;
line-height: 1.45;
}
.swimlane-grid {
display: flex;
flex-direction: column;
gap: 0;
overflow-x: auto;
}
.lane {
min-width: 1080px;
display: grid;
grid-template-columns: 220px minmax(0, 1fr);
border-bottom: 1px solid #d8e4f2;
background: #f0f6fc;
}
.lane:last-child {
border-bottom: none;
}
.lane-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-height: 54px;
padding: 10px 12px;
background: #0d2758;
color: white;
font-weight: 800;
line-height: 1.25;
}
.lane-body {
display: flex;
flex-direction: row;
align-items: stretch;
gap: 10px;
min-height: 118px;
padding: 12px;
}
.module-node {
min-width: 180px;
flex: 1 1 0;
border: 1px solid #c8d7e8;
border-left: 5px solid #0d2758;
border-radius: 7px;
background: white;
color: #0d2758;
padding: 9px 10px 10px 10px;
box-shadow: 0 2px 8px rgba(13, 39, 88, 0.06);
}
.module-node.risk {
border-left-color: #d92d20;
}
.module-node.memory {
border-left-color: #7a5af8;
}
.module-node.service {
border-left-color: #00856f;
}
.node-top {
display: flex;
align-items: center;
gap: 7px;
margin-bottom: 7px;
}
.node-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
border-radius: 999px;
color: white;
background: #0d2758;
font-weight: 800;
font-size: 0.8rem;
flex: 0 0 auto;
}
.module-node.risk .node-number {
background: #d92d20;
}
.module-node.memory .node-number {
background: #7a5af8;
}
.module-node.service .node-number {
background: #00856f;
}
.node-module {
display: inline-flex;
align-items: center;
max-width: 100%;
border: 1px solid #c8d7e8;
border-radius: 999px;
background: #f8fbff;
padding: 2px 8px;
color: #5f7082;
font-size: 0.82rem;
font-weight: 800;
line-height: 1.35;
}
.node-title {
display: block;
font-weight: 900;
line-height: 1.25;
margin-bottom: 4px;
}
.node-desc {
display: block;
color: #5f7082;
font-size: 0.9rem;
line-height: 1.35;
}
.legend {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 7px;
border: 1px solid #c8d7e8;
border-radius: 999px;
background: white;
color: #0d2758;
padding: 5px 11px;
font-weight: 700;
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 999px;
background: #0d2758;
flex: 0 0 auto;
}
.legend-dot.risk {
background: #d92d20;
}
.legend-dot.memory {
background: #7a5af8;
}
.legend-dot.service {
background: #00856f;
}
#sg-tooltip {
position: fixed;
z-index: 9999;
max-width: 440px;
padding: 10px 12px;
border-radius: 6px;
background: #0d2758;
color: white;
font-size: 0.95rem;
line-height: 1.45;
box-shadow: 0 12px 32px rgba(13, 39, 88, 0.22);
pointer-events: none;
opacity: 0;
transform: translateY(4px);
transition: opacity 0.12s ease, transform 0.12s ease;
}
#sg-tooltip.is-visible {
opacity: 1;
transform: translateY(0);
}
@media (max-width: 1100px) {
.module-map {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 720px) {
.module-map {
grid-template-columns: 1fr;
}
.flow-head {
align-items: flex-start;
flex-direction: column;
}
.lane {
min-width: 0;
display: block;
}
.lane-body {
flex-direction: column;
}
.module-node {
min-width: 0;
}
}
</style>
</head>
<body class="bg-white p-4 md:p-8 min-h-screen text-sm select-none">
<nav class="max-w-[1780px] mx-auto mb-5 flex flex-wrap items-center justify-between gap-3 border border-blue-200 rounded-lg px-4 py-3 shadow-sm bg-white">
<div class="flex items-center gap-2 theme-text-dark-blue font-bold text-base" data-tip="汇报专用静态网站,可直接双击 index.html 打开,不需要启动本地服务。">
<i class="fa-solid fa-display"></i>
<span>sgRobot 汇报静态网站</span>
</div>
<div class="flex items-center gap-2">
<a href="index.html" class="border theme-border-blue theme-text-dark-blue rounded px-4 py-2 font-bold bg-white hover:bg-blue-50" data-tip="返回 sgRobot 的目标态业务架构总览。">业务架构总览</a>
<a href="flows.html" class="theme-dark-blue text-white rounded px-4 py-2 font-bold shadow-sm" data-tip="当前页面展示业务流程如何落到架构模块。">业务流程图</a>
<a href="roadmap.html" class="border theme-border-blue theme-text-dark-blue rounded px-4 py-2 font-bold bg-white hover:bg-blue-50" data-tip="查看五月底上线倒排的里程碑、分工边界和验收口径。">里程碑与分工</a>
</div>
</nav>
<header class="max-w-[1780px] mx-auto mb-6">
<div class="flex items-center mb-2" data-tip="本页展示业务流程与架构模块的对应关系,不再只画孤立步骤。">
<div class="w-10 h-10 theme-dark-blue text-white flex items-center justify-center rounded shadow-sm mr-3">
<i class="fa-solid fa-route text-xl"></i>
</div>
<div>
<h1 class="text-3xl font-bold theme-text-dark-blue tracking-wide">sgRobot <span class="font-bold">业务流程与架构模块映射</span></h1>
</div>
</div>
<div class="ml-14 text-[13px] font-medium text-gray-700 leading-relaxed" data-tip="每条流程按架构图的上下分层来摆放,节点上的小标签标明它落到哪个具体模块。">
读图方式:每张流程图按<span class="font-bold">四个架构分区</span>自上而下展开,节点编号表示业务先后顺序,节点标签表示承接该动作的<span class="theme-red font-bold">具体架构模块</span>
</div>
</header>
<main class="max-w-[1780px] mx-auto flex flex-col gap-5">
<section class="border-2 theme-border-blue rounded-lg p-4 bg-white shadow-sm" data-tip="这里先把架构图中的四个分区和模块列出来,后续每个流程节点都会引用这些模块。">
<div class="flex flex-wrap items-center justify-between gap-3 mb-4">
<div class="font-bold theme-text-dark-blue text-lg flex items-center gap-2">
<i class="fa-solid fa-layer-group"></i>
<span>架构模块对照</span>
</div>
<div class="legend">
<span class="legend-item" data-tip="蓝色节点表示常规业务动作。"><span class="legend-dot"></span>常规动作</span>
<span class="legend-item" data-tip="红色节点表示需要人工判断、风险确认或异常处置。"><span class="legend-dot risk"></span>风险决策</span>
<span class="legend-item" data-tip="绿色节点表示按需后台服务、设备连接或外部系统协作。"><span class="legend-dot service"></span>服务协作</span>
<span class="legend-item" data-tip="紫色节点表示结果、经验、规则或过程记录沉淀。"><span class="legend-dot memory"></span>记录沉淀</span>
</div>
</div>
<div class="module-map">
<div class="module-card" data-tip="业务入口与协同负责把人的需求、系统事件和审批动作接进系统。">
<div class="module-title"><i class="fa-solid fa-right-to-bracket"></i><span>业务入口与协同</span></div>
<div class="module-list">
<span class="module-pill" data-tip="接收人工提交、系统接口、计划任务和事件触发。">业务需求入口</span>
<span class="module-pill" data-tip="让用户、运维和审批人查看、操作、审批、回放和验收成果。">协同工作台</span>
</div>
</div>
<div class="module-card" data-tip="任务治理与风控负责计划拆解、任务执行管理、人工治理和风险规则。">
<div class="module-title"><i class="fa-solid fa-shield-halved"></i><span>任务治理与风控</span></div>
<div class="module-list">
<span class="module-pill" data-tip="把业务目标拆成执行计划和计划步骤。">目标计划管理</span>
<span class="module-pill" data-tip="管理工作任务、执行记录、重试、恢复点和超时。">任务执行管理</span>
<span class="module-pill" data-tip="承接审批、暂停、恢复、取消、人工接管和重新规划。">人工治理</span>
<span class="module-pill" data-tip="管理记忆规则、服务占用、风险等级和健康状态。">风险与规则</span>
</div>
</div>
<div class="module-card" data-tip="自动执行与能力负责真正完成业务动作,并管理外部系统、设备和后台服务。">
<div class="module-title"><i class="fa-solid fa-gears"></i><span>自动执行与能力</span></div>
<div class="module-list">
<span class="module-pill" data-tip="登记可被调度使用的自动化能力。">能力目录</span>
<span class="module-pill" data-tip="检查前置条件、匹配能力、安排顺序和失败恢复。">调度中枢</span>
<span class="module-pill" data-tip="执行规则清楚、结果稳定、可重复的任务。">自动脚本</span>
<span class="module-pill" data-tip="把多步骤工作组织成可治理流程。">流程编排</span>
<span class="module-pill" data-tip="辅助规划、解释、诊断和修复建议。">智能辅助</span>
<span class="module-pill" data-tip="对接网页、业务系统、设备和机器人。">外部系统适配</span>
<span class="module-pill" data-tip="按需启动和回收邮件读取、监听器、浏览器环境等后台服务。">按需后台服务</span>
</div>
</div>
<div class="module-card" data-tip="运营记录与看板沉淀过程、成果、经验和指标,让管理者看到进度、风险和结果。">
<div class="module-title"><i class="fa-solid fa-chart-column"></i><span>运营记录与看板</span></div>
<div class="module-list">
<span class="module-pill" data-tip="保存计划、任务、执行和审批的当前状态。">业务状态台账</span>
<span class="module-pill" data-tip="记录关键过程变化,用于回放、审计和问题追踪。">过程日志</span>
<span class="module-pill" data-tip="保存文件、报告、截图和数据结果。">成果资料库</span>
<span class="module-pill" data-tip="沉淀项目事实、偏好、关键决策、处理经验和观察摘要。">经验与记忆库</span>
<span class="module-pill" data-tip="展示任务看板、审批队列、记忆索引和服务健康。">运营看板</span>
<span class="module-pill" data-tip="按时间顺序展示过程回放、诊断和追责。">全程追踪</span>
<span class="module-pill" data-tip="统计服务时效、成功率、响应耗时和人工介入率。">运营指标</span>
</div>
</div>
</div>
</section>
<div id="flow-root" class="flex flex-col gap-5"></div>
</main>
<script>
const lanes = [
{ key: "entry", icon: "fa-right-to-bracket", name: "业务入口与协同", tip: "对应架构图第一分区:业务需求入口和协同工作台。" },
{ key: "governance", icon: "fa-shield-halved", name: "任务治理与风控", tip: "对应架构图第二分区:目标计划管理、任务执行管理、人工治理、风险与规则。" },
{ key: "execution", icon: "fa-gears", name: "自动执行与能力", tip: "对应架构图第三分区:能力目录、调度中枢、自动脚本、流程编排、智能辅助、外部系统适配、按需后台服务。" },
{ key: "records", icon: "fa-chart-column", name: "运营记录与看板", tip: "对应架构图第四分区:业务状态台账、过程日志、成果资料库、经验与记忆库、运营看板、全程追踪、运营指标。" },
];
const flows = [
{
title: "人工交办任务处理",
icon: "fa-user-pen",
tag: "用户主动发起",
tip: "用户主动提交目标后,流程依次经过需求入口、计划治理、自动执行、成果验收和经验沉淀。",
nodes: [
{ lane: "entry", step: 1, module: "协同工作台", title: "接收交办", desc: "目标、材料、期望结果", tip: "用户在协同工作台提交业务目标、背景材料和验收要求。" },
{ lane: "entry", step: 2, module: "业务需求入口", title: "登记目标", desc: "形成可追踪入口", tip: "业务需求入口把原始需求登记成可追踪的业务目标。" },
{ lane: "governance", step: 3, module: "目标计划管理", title: "拆解计划", desc: "步骤、依赖、验收标准", tip: "目标计划管理把业务目标拆成执行计划、计划步骤、依赖和验收标准。" },
{ lane: "governance", step: 4, module: "任务执行管理", title: "生成任务", desc: "排队、优先级、恢复点", tip: "任务执行管理把计划步骤转成工作任务,并设置优先级、重试和恢复点。" },
{ lane: "execution", step: 5, module: "调度中枢", title: "匹配能力", desc: "脚本、流程、智能辅助", tip: "调度中枢为工作任务选择合适能力,并检查前置条件。" },
{ lane: "execution", step: 6, module: "自动脚本 / 流程编排", title: "执行任务", desc: "自动处理并持续回写", tip: "自动执行模块完成实际业务动作,并持续回写过程状态和中间成果。" },
{ lane: "governance", step: 7, module: "人工治理", title: "成果验收", desc: "确认、退回、接管", type: "risk", tip: "人工治理负责成果确认、退回重做、暂停或人工接管。" },
{ lane: "records", step: 8, module: "成果资料库 / 运营看板", title: "成果呈现", desc: "报告、截图、任务看板", type: "memory", tip: "成果资料库保存交付物,运营看板展示任务状态和验收结果。" },
{ lane: "records", step: 9, module: "经验与记忆库", title: "经验沉淀", desc: "偏好、决策、处理经验", type: "memory", tip: "经验与记忆库沉淀用户偏好、关键决策和处理经验,供后续任务复用。" },
],
},
{
title: "邮件与消息触发处理",
icon: "fa-envelope-open-text",
tag: "事件自动触发",
tip: "邮件、消息或业务通知到达后,按需服务先把事件读入,再由治理模块判断是否生成任务。",
nodes: [
{ lane: "execution", step: 1, module: "按需后台服务", title: "启动读取服务", desc: "邮件、监听器、消息", type: "service", tip: "按需后台服务在需要时启动邮件读取或消息监听,不要求所有服务随主程序常驻。" },
{ lane: "entry", step: 2, module: "业务需求入口", title: "接收事件", desc: "通知、邮件、业务提醒", tip: "业务需求入口把读取到的消息统一登记为事件或待判断请求。" },
{ lane: "governance", step: 3, module: "风险与规则", title: "分类判断", desc: "优先级、风险、是否自动处理", type: "risk", tip: "风险与规则判断消息类别、优先级、影响范围,以及是否需要人工确认。" },
{ lane: "governance", step: 4, module: "目标计划管理", title: "生成目标或任务", desc: "纳入统一治理", tip: "符合条件的消息会被转成业务目标、执行计划或工作任务。" },
{ lane: "execution", step: 5, module: "调度中枢 / 自动脚本", title: "自动处理", desc: "回复、归档、提取、触发后续流程", tip: "调度中枢选择处理能力,自动完成回复、归档、数据提取或后续流程触发。" },
{ lane: "governance", step: 6, module: "人工治理", title: "异常转人工", desc: "审批、补充、接管", type: "risk", tip: "遇到权限、金额、外部影响或识别不确定时,进入人工审批或人工接管。" },
{ lane: "records", step: 7, module: "过程日志 / 运营看板", title: "记录处理结果", desc: "结果、风险、处理人", type: "memory", tip: "过程日志记录处理过程,运营看板展示处理结果、风险状态和责任人。" },
{ lane: "records", step: 8, module: "经验与记忆库", title: "更新规则经验", desc: "分类经验、处理偏好", type: "memory", tip: "消息分类、人工判断和处理偏好沉淀为后续自动判断依据。" },
],
},
{
title: "定时巡检与报告",
icon: "fa-calendar-check",
tag: "周期运营任务",
tip: "周期巡检从计划任务入口进入,经过巡检计划、外部采集、报告生成和运营指标沉淀。",
nodes: [
{ lane: "entry", step: 1, module: "业务需求入口", title: "排程触发", desc: "日常、周报、月报", tip: "业务需求入口接收计划任务触发,启动周期巡检流程。" },
{ lane: "governance", step: 2, module: "目标计划管理", title: "生成巡检计划", desc: "对象、范围、标准", tip: "目标计划管理根据巡检对象、范围、责任人和验收标准生成计划。" },
{ lane: "governance", step: 3, module: "任务执行管理", title: "安排巡检任务", desc: "批次、优先级、超时", tip: "任务执行管理把巡检计划拆成工作任务,并配置批次、优先级和超时管控。" },
{ lane: "execution", step: 4, module: "外部系统适配", title: "连接巡检对象", desc: "系统、网页、设备", type: "service", tip: "外部系统适配连接业务系统、网页、设备或机器人,准备采集信息。" },
{ lane: "execution", step: 5, module: "自动脚本 / 智能辅助", title: "采集并生成报告", desc: "指标、截图、结论", tip: "自动脚本采集数据,智能辅助整理结论、异常和建议。" },
{ lane: "records", step: 6, module: "成果资料库", title: "归档报告证据", desc: "报告、截图、数据结果", type: "memory", tip: "成果资料库保存巡检报告、截图和数据结果,支撑验收和复盘。" },
{ lane: "records", step: 7, module: "运营指标", title: "更新运营指标", desc: "趋势、成功率、耗时", type: "memory", tip: "运营指标沉淀巡检趋势、执行成功率、响应耗时和服务时效。" },
{ lane: "governance", step: 8, module: "人工治理", title: "异常升级", desc: "告警、确认、复盘", type: "risk", tip: "发现异常、超时或失败率升高时,转人工确认、升级和复盘。" },
],
},
{
title: "高风险动作审批",
icon: "fa-shield-halved",
tag: "人控关键节点",
tip: "高风险动作通过风险规则识别,在执行前转入人工治理,并在全程追踪中留痕。",
nodes: [
{ lane: "governance", step: 1, module: "风险与规则", title: "识别风险动作", desc: "权限、影响、不可逆", type: "risk", tip: "风险与规则识别删除、发布、付款、发信、改配置、控制设备等高风险动作。" },
{ lane: "governance", step: 2, module: "任务执行管理", title: "暂停在风险点", desc: "停止继续执行", type: "risk", tip: "任务执行管理把流程暂停在风险节点,避免未经确认继续执行。" },
{ lane: "entry", step: 3, module: "协同工作台", title: "呈现审批材料", desc: "原因、影响、建议", type: "risk", tip: "协同工作台向审批人展示目标、原因、影响范围、可选方案和建议动作。" },
{ lane: "governance", step: 4, module: "人工治理", title: "审批决策", desc: "通过、拒绝、接管、重规划", type: "risk", tip: "人工治理承接审批通过、拒绝、补充材料、人工接管或重新规划。" },
{ lane: "execution", step: 5, module: "调度中枢", title: "执行分支", desc: "继续、取消、转人工", tip: "调度中枢根据审批结论继续执行、取消任务或转人工处理。" },
{ lane: "records", step: 6, module: "全程追踪", title: "审批留痕", desc: "谁、何时、为何", type: "memory", tip: "全程追踪记录审批人、审批时间、审批理由和最终结果。" },
{ lane: "records", step: 7, module: "经验与记忆库", title: "沉淀审批边界", desc: "规则、案例、判断依据", type: "memory", tip: "审批案例会沉淀为后续风险判断、审批边界和培训材料。" },
],
},
{
title: "外部系统与设备协作",
icon: "fa-plug-circle-bolt",
tag: "跨系统协作",
tip: "跨系统任务通过服务准备、外部适配、状态回写和成果归档,把网页、设备和机器人纳入统一治理。",
nodes: [
{ lane: "entry", step: 1, module: "业务需求入口", title: "协作请求进入", desc: "业务系统、人、计划任务", tip: "业务需求入口接收需要外部系统、设备或机器人参与的协作请求。" },
{ lane: "governance", step: 2, module: "风险与规则", title: "检查权限与服务占用", desc: "账号、设备、占用关系", type: "risk", tip: "风险与规则检查权限、账号、设备状态和后台服务占用关系。" },
{ lane: "execution", step: 3, module: "按需后台服务", title: "准备运行环境", desc: "浏览器环境、连接、服务实例", type: "service", tip: "按需后台服务准备浏览器环境、设备连接或外部服务实例。" },
{ lane: "execution", step: 4, module: "外部系统适配", title: "执行外部动作", desc: "网页、设备、机器人", type: "service", tip: "外部系统适配执行网页操作、设备控制或机器人动作。" },
{ lane: "records", step: 5, module: "业务状态台账", title: "状态回写", desc: "进度、异常、服务健康", type: "memory", tip: "业务状态台账记录进度、异常和服务健康,供治理流程继续判断。" },
{ lane: "governance", step: 6, module: "任务执行管理", title: "异常恢复", desc: "重试、替代、接管", type: "risk", tip: "外部系统不可用、设备异常或页面变化时,任务执行管理负责重试、替代路径或人工接管。" },
{ lane: "records", step: 7, module: "成果资料库 / 全程追踪", title: "成果归档", desc: "证据、状态、经验", type: "memory", tip: "最终成果、截图证据、设备状态和处理过程统一归档。" },
],
},
{
title: "失败恢复与复盘改进",
icon: "fa-screwdriver-wrench",
tag: "持续改进闭环",
tip: "失败不是只停在报错,而是由记录层提供证据,治理层决策恢复路径,执行层重试,最后沉淀规则。",
nodes: [
{ lane: "records", step: 1, module: "过程日志", title: "发现失败事实", desc: "失败、超时、不达标", type: "risk", tip: "过程日志记录任务失败、超时、外部异常或成果不达标。" },
{ lane: "records", step: 2, module: "全程追踪", title: "汇总证据", desc: "过程、截图、状态", type: "memory", tip: "全程追踪汇总过程记录、截图、服务状态和最近变更。" },
{ lane: "execution", step: 3, module: "智能辅助", title: "自动诊断", desc: "原因、影响、建议", tip: "智能辅助根据证据给出可能原因、影响范围和修复建议。" },
{ lane: "governance", step: 4, module: "任务执行管理", title: "选择恢复路径", desc: "重试、替代、回退", type: "risk", tip: "任务执行管理根据风险和预算选择自动重试、替代能力或回退路径。" },
{ lane: "execution", step: 5, module: "调度中枢", title: "执行恢复方案", desc: "重新调度、替代执行", tip: "调度中枢安排重试、替代能力或补偿步骤。" },
{ lane: "governance", step: 6, module: "人工治理", title: "人工介入", desc: "补充、确认、接管", type: "risk", tip: "自动恢复仍不可靠或风险较高时,人工治理负责补充信息、确认方案或接管执行。" },
{ lane: "records", step: 7, module: "经验与记忆库", title: "复盘沉淀", desc: "原因、方法、预防", type: "memory", tip: "处理完成后沉淀失败原因、修复方法、适用条件和预防建议。" },
{ lane: "governance", step: 8, module: "风险与规则", title: "优化规则", desc: "减少重复失败", type: "memory", tip: "复盘结果转化为规则、能力说明、巡检项或审批边界优化。" },
],
},
];
function escapeHtml(value) {
return String(value)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function renderNode(node) {
const type = node.type ? ` ${escapeHtml(node.type)}` : "";
return `
<div class="module-node${type}" data-tip="${escapeHtml(node.tip)}">
<div class="node-top">
<span class="node-number">${escapeHtml(node.step)}</span>
<span class="node-module">${escapeHtml(node.module)}</span>
</div>
<span class="node-title">${escapeHtml(node.title)}</span>
<span class="node-desc">${escapeHtml(node.desc)}</span>
</div>
`;
}
function renderFlow(flow) {
const lanesHtml = lanes.map((lane) => {
const nodes = flow.nodes
.filter((node) => node.lane === lane.key)
.sort((a, b) => a.step - b.step)
.map(renderNode)
.join("");
return `
<div class="lane" data-tip="${escapeHtml(lane.tip)}">
<div class="lane-head">
<span><i class="fa-solid ${escapeHtml(lane.icon)} mr-1"></i>${escapeHtml(lane.name)}</span>
</div>
<div class="lane-body">${nodes}</div>
</div>
`;
}).join("");
return `
<section class="flow-card" data-tip="${escapeHtml(flow.tip)}">
<div class="flow-head">
<div class="flow-title">
<i class="fa-solid ${escapeHtml(flow.icon)}"></i>
<span>${escapeHtml(flow.title)}</span>
</div>
<span class="flow-tag" data-tip="${escapeHtml(flow.tip)}">${escapeHtml(flow.tag)}</span>
</div>
<div class="flow-note" data-tip="节点按数字读,四层顺序与架构图一致;有些流程会在治理、执行和记录之间回流。">
节点按数字读;每一层就是架构图中的一个分区,节点标签就是承接该步骤的具体模块。
</div>
<div class="swimlane-grid">${lanesHtml}</div>
</section>
`;
}
document.getElementById("flow-root").innerHTML = flows.map(renderFlow).join("");
const tooltip = document.createElement("div");
tooltip.id = "sg-tooltip";
document.body.appendChild(tooltip);
let activeTipTarget = null;
function positionTooltip(event) {
const margin = 14;
const offset = 16;
const rect = tooltip.getBoundingClientRect();
let left = event.clientX + offset;
let top = event.clientY + offset;
if (left + rect.width + margin > window.innerWidth) {
left = Math.max(margin, event.clientX - rect.width - offset);
}
if (top + rect.height + margin > window.innerHeight) {
top = Math.max(margin, event.clientY - rect.height - offset);
}
tooltip.style.left = `${left}px`;
tooltip.style.top = `${top}px`;
}
function showTooltip(target, event) {
const text = target.dataset.tip;
if (!text) return;
activeTipTarget = target;
tooltip.textContent = text;
tooltip.classList.add("is-visible");
positionTooltip(event);
}
function hideTooltip() {
activeTipTarget = null;
tooltip.classList.remove("is-visible");
}
document.addEventListener("pointerover", (event) => {
const target = event.target.closest("[data-tip]");
if (target) showTooltip(target, event);
});
document.addEventListener("pointermove", (event) => {
if (activeTipTarget) positionTooltip(event);
});
document.addEventListener("pointerout", (event) => {
if (!activeTipTarget) return;
const next = event.relatedTarget;
if (!next || !activeTipTarget.contains(next)) hideTooltip();
});
document.querySelectorAll("[data-tip]").forEach((element) => {
element.setAttribute("tabindex", "0");
element.setAttribute("aria-label", element.dataset.tip);
element.addEventListener("focus", (event) => {
const rect = event.currentTarget.getBoundingClientRect();
showTooltip(event.currentTarget, {
clientX: rect.left + rect.width / 2,
clientY: rect.top + rect.height / 2,
});
});
element.addEventListener("blur", hideTooltip);
});
</script>
</body>
</html>