feat(client): add offline digital employee overview

This commit is contained in:
baiyanyun
2026-06-04 19:42:37 +08:00
parent 44fe160880
commit 2c3f2c8c54
35 changed files with 2902 additions and 7 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "@qiming-ai/qimingclaw",
"version": "0.9.7",
"description": "启明数字员工",
"description": "飞天数字员工",
"main": "dist/main/main.js",
"author": "Qiming Team",
"license": "MIT",
@@ -128,7 +128,7 @@
},
"build": {
"appId": "com.qiming.qimingclaw",
"productName": "启明数字员工",
"productName": "飞天数字员工",
"afterSign": "scripts/build/after-sign.js",
"electronLanguages": [
"en",
@@ -297,8 +297,8 @@
"hardenedRuntime": true,
"extendInfo": {
"CFBundleIdentifier": "com.qiming.agent",
"CFBundleName": "启明数字员工",
"CFBundleDisplayName": "启明数字员工",
"CFBundleName": "飞天数字员工",
"CFBundleDisplayName": "飞天数字员工",
"NSDesktopFolderUsageDescription": "需要访问桌面文件夹以支持文件操作",
"NSDocumentsFolderUsageDescription": "需要访问文档文件夹以支持文件操作",
"NSDownloadsFolderUsageDescription": "需要访问下载文件夹以支持文件操作"

View File

@@ -0,0 +1 @@
function t(n,e,i,s){if(typeof e=="function"?n!==e||!s:!e.has(n))throw new TypeError("Cannot read private member from an object whose class did not declare it");return i==="m"?s:i==="a"?s.call(n):s?s.value:e.get(n)}function c(n,e,i,s,_){if(typeof e=="function"?n!==e||!0:!e.has(n))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(n,i),i}var a,r,o,l,u;const d="__TAURI_TO_IPC_KEY__";function w(n,e=!1){return window.__TAURI_INTERNALS__.transformCallback(n,e)}class g{constructor(e){a.set(this,void 0),r.set(this,0),o.set(this,[]),l.set(this,void 0),c(this,a,e||(()=>{})),this.id=w(i=>{const s=i.index;if("end"in i){s==t(this,r,"f")?this.cleanupCallback():c(this,l,s);return}const _=i.message;if(s==t(this,r,"f")){for(t(this,a,"f").call(this,_),c(this,r,t(this,r,"f")+1);t(this,r,"f")in t(this,o,"f");){const p=t(this,o,"f")[t(this,r,"f")];t(this,a,"f").call(this,p),delete t(this,o,"f")[t(this,r,"f")],c(this,r,t(this,r,"f")+1)}t(this,r,"f")===t(this,l,"f")&&this.cleanupCallback()}else t(this,o,"f")[s]=_})}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(e){c(this,a,e)}get onmessage(){return t(this,a,"f")}[(a=new WeakMap,r=new WeakMap,o=new WeakMap,l=new WeakMap,d)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[d]()}}class f{constructor(e,i,s){this.plugin=e,this.event=i,this.channelId=s}async unregister(){return h(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function m(n,e,i){const s=new g(i);try{return await h(`plugin:${n}|register_listener`,{event:e,handler:s}),new f(n,e,s.id)}catch{return await h(`plugin:${n}|registerListener`,{event:e,handler:s}),new f(n,e,s.id)}}async function I(n){return h(`plugin:${n}|check_permissions`)}async function C(n){return h(`plugin:${n}|request_permissions`)}async function h(n,e={},i){return window.__TAURI_INTERNALS__.invoke(n,e,i)}function T(n,e="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(n,e)}class k{get rid(){return t(this,u,"f")}constructor(e){u.set(this,void 0),c(this,u,e)}async close(){return h("plugin:resources|close",{rid:this.rid})}}u=new WeakMap;function E(){return!!(globalThis||window).isTauri}export{g as Channel,f as PluginListener,k as Resource,d as SERIALIZE_TO_IPC_FN,m as addPluginListener,I as checkPermissions,T as convertFileSrc,h as invoke,E as isTauri,C as requestPermissions,w as transformCallback};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
# Digital Employee Static Assets
This directory is owned by the React digital employee frontend.
- `avatars/` keeps the original digital employee character images used by the home page `Avatar3D` stage.
- Do not place the legacy Vue standalone application bundle here.
- If an avatar file is renamed, update `src/pages/digital/CommandDeck.tsx` in the same change.

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="dark" />
<link rel="icon" type="image/png" href="/sgrobot-digital/logo.png" />
<title>sgRobot</title>
<script>
window.__TAURI__ = window.__TAURI__ || {};
</script>
<script type="module" crossorigin src="/sgrobot-digital/assets/index-DwDxQhF4.js"></script>
<link rel="stylesheet" crossorigin href="/sgrobot-digital/assets/index-BTJFqpbJ.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

@@ -0,0 +1,660 @@
<!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>

View File

@@ -0,0 +1,650 @@
<!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-text-gray { color: #5f7082; }
.theme-red { color: #d92d20; }
/* 连接线箭头样式辅助 */
.arrow-right-solid {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 8px solid #0d2758;
}
.arrow-down-solid {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 8px solid #0d2758;
}
/* 用于核心闭环的虚线箭头 */
.dashed-arrow-line {
background-image: linear-gradient(to right, #d92d20 50%, transparent 50%);
background-size: 10px 2px;
background-repeat: repeat-x;
}
.arrow-right-red {
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 6px solid #d92d20;
}
.arrow-left-red {
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-right: 6px solid #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-\[9px\] { font-size: 0.82rem !important; }
.text-\[10px\] { font-size: 0.92rem !important; }
.text-\[11px\] { font-size: 1.02rem !important; }
.text-\[13px\] { font-size: 1.14rem !important; }
/* 放大后给各层卡片更多高度,避免文字贴边 */
.min-h-\[60px\] { min-height: 86px !important; }
.min-h-\[65px\] { min-height: 92px !important; }
.min-h-\[70px\] { min-height: 104px !important; }
[data-tip] {
cursor: help;
}
.term-list {
display: flex;
flex-wrap: wrap;
gap: 5px 6px;
margin-top: 5px;
}
.term {
display: inline-flex;
align-items: center;
border: 1px solid #c8d7e8;
border-radius: 999px;
background: #f8fbff;
padding: 2px 8px;
color: #5f7082;
font-size: 0.86rem;
line-height: 1.35;
white-space: nowrap;
}
#sg-tooltip {
position: fixed;
z-index: 9999;
max-width: 520px;
padding: 10px 12px;
border-radius: 6px;
background: #0d2758;
color: white;
font-size: 0.95rem;
line-height: 1.45;
white-space: pre-line;
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);
}
</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="theme-dark-blue text-white rounded px-4 py-2 font-bold shadow-sm" data-tip="查看 sgRobot 的目标态业务架构总览。">业务架构总览</a>
<a href="flows.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>
<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>
<div class="max-w-[1780px] mx-auto mb-6">
<div class="flex items-center mb-2">
<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-cube 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">
围绕<span class="font-bold">业务入口</span><span class="font-bold">任务治理</span><span class="font-bold">自动执行</span><span class="theme-red font-bold">运营看板</span>四条主线,把目标接收、计划拆解、执行过程、人工决策、经验沉淀和后台服务统一纳入可管理的业务闭环。
</div>
</div>
<div class="max-w-[1780px] mx-auto relative">
<!-- 顶层用户 -->
<div class="flex justify-center mb-[-12px] relative z-10">
<div class="bg-white border-2 theme-border-blue rounded-full px-10 py-2 flex items-center gap-3 shadow-sm" data-tip="系统的外部参与者。用户提交目标,运维关注健康与风险,审批人处理治理节点,外部业务系统可通过系统接口或业务事件触发任务。">
<i class="fa-solid fa-user-group text-blue-600 text-lg"></i>
<span class="font-bold theme-text-dark-blue text-base">
<span data-tip="用户是目标和需求的主要提出者,可以发起任务、补充输入和接受结果。">用户</span> /
<span data-tip="运维关注系统健康、服务状态、告警、失败恢复和上线风险。">运维</span> /
<span data-tip="审批人负责处理高风险动作、外部副作用、权限边界和人工治理节点。">审批人</span> /
<span data-tip="外部业务系统通过系统接口、消息或业务事件触发 sgRobot 工作流。">外部业务系统</span>
</span>
</div>
</div>
<div class="flex justify-center mb-2 text-blue-600 text-lg">
<i class="fa-solid fa-arrow-down"></i>
</div>
<!-- 主结构外框 -->
<div class="border-2 theme-border-blue rounded-lg p-3 pt-6 flex flex-col gap-2 relative bg-white">
<div class="absolute right-[-10px] top-[15%] bottom-[15%] w-[20px] border-r-2 border-t-2 border-b-2 theme-border-blue rounded-r-lg z-0 opacity-50 hidden lg:block"></div>
<!-- Plane 1: 业务入口与协同 -->
<div class="flex items-stretch border theme-border-blue rounded bg-white relative z-10">
<div class="w-12 md:w-40 theme-dark-blue text-white flex flex-col items-center justify-center p-2 rounded-l flex-shrink-0" data-tip="业务入口与协同负责把人的需求、系统事件和业务审批统一接入,并把任务进展反馈给相关人员。">
<div class="bg-white/20 px-2 py-1 rounded text-xs mb-1 font-mono">1</div>
<span class="font-bold hidden md:block text-center leading-tight">业务入口与协同</span>
<span class="font-bold md:hidden text-center writing-vertical-lr text-xs">入口协同</span>
</div>
<div class="flex-1 theme-light-blue-bg p-3 grid grid-cols-1 md:grid-cols-2 gap-4 rounded-r">
<div class="bg-white border theme-border-blue rounded p-2 flex items-center gap-3 shadow-sm min-h-[60px] w-full" data-tip="业务需求入口把人工提交、接口调用、计划任务和事件触发统一登记为可跟踪的业务目标或处理请求。">
<i class="fa-solid fa-arrow-right-to-bracket text-2xl theme-text-dark-blue ml-2"></i>
<div>
<div class="font-bold theme-text-dark-blue text-sm">业务需求入口</div>
<div class="term-list">
<span class="term" data-tip="人工提交是用户在控制台或对话入口主动发起的目标。">人工提交</span>
<span class="term" data-tip="系统接口让外部业务系统以结构化请求提交目标、状态或审批动作。">系统接口</span>
<span class="term" data-tip="计划任务是按时间、周期或排程触发的目标入口。">计划任务</span>
<span class="term" data-tip="事件触发来自邮件、系统通知、消息、文件变化或内部业务事件。">事件触发</span>
</div>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 flex items-center gap-3 shadow-sm min-h-[60px] w-full" data-tip="协同工作台让用户、运维和审批人查看进度、处理审批、回放过程和验收成果。">
<i class="fa-solid fa-desktop text-2xl theme-text-dark-blue ml-2"></i>
<div>
<div class="font-bold theme-text-dark-blue text-sm">协同工作台</div>
<div class="term-list">
<span class="term" data-tip="查看用于读取目标、计划、任务、执行记录、服务状态和经验记忆。">查看</span>
<span class="term" data-tip="操作是用户对任务、服务、参数和视图发起的显式动作。">操作</span>
<span class="term" data-tip="审批用于确认高风险动作、外部副作用或权限敏感步骤。">审批</span>
<span class="term" data-tip="回放按事件时间线复原过程,用于诊断、复盘和追责。">回放</span>
<span class="term" data-tip="成果浏览用于查看报告、截图、文件、日志快照和结构化结果。">成果浏览</span>
</div>
</div>
</div>
</div>
</div>
<!-- Plane 2: 任务治理与风控 -->
<div class="flex items-stretch border theme-border-blue rounded bg-white relative z-10">
<div class="w-12 md:w-40 theme-dark-blue text-white flex flex-col items-center justify-center p-2 rounded-l flex-shrink-0" data-tip="任务治理与风控负责把业务目标拆成计划和任务,并统一管理审批、风险、暂停、恢复、重试和服务占用规则。">
<i class="fa-solid fa-sliders text-xl mb-1"></i>
<span class="font-bold hidden md:block text-center leading-tight">任务治理与风控</span>
<span class="font-bold md:hidden text-center writing-vertical-lr text-xs mt-2">任务风控</span>
</div>
<div class="flex-1 theme-light-blue-bg p-3 grid grid-cols-1 md:grid-cols-4 gap-3 rounded-r">
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[70px]" data-tip="目标与计划管理把原始目标转成可审查、可冻结、可重规划的计划结构。">
<div class="flex items-center gap-2 mb-1">
<i class="fa-solid fa-bullseye theme-text-dark-blue text-lg"></i>
<span class="font-bold theme-text-dark-blue text-[13px]">目标计划管理</span>
</div>
<div class="term-list">
<span class="term" data-tip="业务目标是用户或外部系统想达成的结果,也是后续计划拆解的源头。">业务目标</span>
<span class="term" data-tip="执行计划描述成功标准、风险、依赖和执行步骤。">执行计划</span>
<span class="term" data-tip="计划步骤是计划中的单个动作,用于生成可调度的工作任务。">计划步骤</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[70px]" data-tip="任务执行管理负责从步骤生成任务,并管理执行尝试、失败恢复、服务占用和最终状态。">
<div class="flex items-center gap-2 mb-1">
<i class="fa-solid fa-list-ul theme-text-dark-blue text-lg"></i>
<span class="font-bold theme-text-dark-blue text-[13px]">任务执行管理</span>
</div>
<div class="term-list">
<span class="term" data-tip="工作任务是可调度的工作单元,绑定能力、输入、依赖和优先级。">工作任务</span>
<span class="term" data-tip="执行记录代表一次任务执行尝试,重试会产生新的执行记录。">执行记录</span>
<span class="term" data-tip="自动重试是失败或中断后的再执行策略,受预算和风险约束。">自动重试</span>
<span class="term" data-tip="恢复点是长任务的过程锚点,用于失败后恢复和问题诊断。">恢复点</span>
<span class="term" data-tip="超时管控防止任务无限运行,超时后进入恢复或人工介入路径。">超时管控</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[70px]" data-tip="人工治理把人的介入变成可记录、可回放、可追责的业务操作,而不是后台直接改结果。">
<div class="flex items-center gap-2 mb-1">
<i class="fa-solid fa-user-check theme-text-dark-blue text-lg"></i>
<span class="font-bold theme-text-dark-blue text-[13px]">人工治理</span>
</div>
<div class="term-list">
<span class="term" data-tip="审批通过允许高风险步骤、外部副作用或权限敏感动作继续执行。">审批通过</span>
<span class="term" data-tip="暂停让人检查任务状态、参数、风险或依赖。">暂停</span>
<span class="term" data-tip="恢复从暂停点继续执行,通常需要保留上下文和服务占用状态。">恢复</span>
<span class="term" data-tip="取消终止任务或计划,并释放相关服务占用。">取消</span>
<span class="term" data-tip="人工接管把自动执行转交给人工或指定操作者处理。">人工接管</span>
<span class="term" data-tip="重新规划在现有目标下重新生成或修改执行路径。">重新规划</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[70px]" data-tip="风险与规则规定经验记忆怎么用、后台服务怎么占用、哪些动作必须审批、哪些状态必须进入看板。">
<div class="flex items-center gap-2 mb-1">
<i class="fa-solid fa-shield-halved theme-text-dark-blue text-lg"></i>
<span class="font-bold theme-text-dark-blue text-[13px]">风险与规则</span>
</div>
<div class="term-list">
<span class="term" data-tip="记忆规则规定经验何时召回、写入、遗忘、替代或标记冲突。">记忆规则</span>
<span class="term" data-tip="服务占用记录任务对后台服务的使用关系,防止误停和资源泄漏。">服务占用</span>
<span class="term" data-tip="风险等级表示动作、任务、服务或记忆使用的风险级别和审批要求。">风险等级</span>
<span class="term" data-tip="健康状态汇总任务、服务、通道和看板等关键组件是否正常。">健康状态</span>
</div>
</div>
</div>
</div>
<!-- Plane 3: 自动执行与能力 -->
<div class="flex items-stretch border theme-border-blue rounded bg-white relative z-10">
<div class="w-12 md:w-40 theme-dark-blue text-white flex flex-col items-center justify-center p-2 rounded-l flex-shrink-0" data-tip="自动执行与能力负责真正完成业务动作,包括脚本、流程、智能辅助、外部系统适配和按需后台服务。">
<i class="fa-solid fa-gears text-xl mb-1"></i>
<span class="font-bold hidden md:block text-center leading-tight">自动执行与能力</span>
<span class="font-bold md:hidden text-center writing-vertical-lr text-xs mt-2">自动执行</span>
</div>
<div class="flex-1 theme-light-blue-bg p-3 grid grid-cols-1 md:grid-cols-7 gap-3 rounded-r">
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="能力目录管理可治理自动化能力的登记、版本、使用约定、策略和健康。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-box mr-1"></i>能力目录</div>
<div class="term-list">
<span class="term" data-tip="能力登记把脚本、流程、智能辅助或外部适配纳入统一目录。">能力登记</span>
<span class="term" data-tip="版本管理用于区分能力说明、实现和兼容边界。">版本管理</span>
<span class="term" data-tip="使用约定说明输入、输出、成果和过程记录要求。">使用约定</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="调度中枢负责检查前置条件、匹配自动化能力、安排执行顺序并处理失败恢复。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-sitemap mr-1"></i>调度中枢</div>
<div class="term-list">
<span class="term" data-tip="前置检查判断任务、服务、记忆、成果和审批之间的依赖是否满足。">前置检查</span>
<span class="term" data-tip="能力匹配根据使用约定、风险、可用性和上下文选择合适能力。">能力匹配</span>
<span class="term" data-tip="失败恢复处理回滚、替代路径、重试和人工兜底。">失败恢复</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="自动脚本适合规则清楚、结果稳定、可重试、可审计的任务。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-code mr-1"></i>自动脚本</div>
<div class="term-list"><span class="term" data-tip="确定性任务适合明确输入输出,结果更容易测试和审计。">确定性任务</span></div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="流程编排承载组合能力和子流程,把多步骤操作纳入统一治理。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-diagram-project mr-1"></i>流程编排</div>
<div class="term-list">
<span class="term" data-tip="组合能力把多个原子能力组合为一个可治理流程。">组合能力</span>
<span class="term" data-tip="子流程是在一个任务内部继续拆分的执行片段。">子流程</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="智能辅助用于规划、选择、解释和修复建议,但任务状态仍由治理流程统一管理。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-brain mr-1"></i>智能辅助</div>
<div class="term-list">
<span class="term" data-tip="规划用于把目标拆成可审查的计划和步骤。">规划</span>
<span class="term" data-tip="修复建议用于失败诊断、替代能力和补偿路径建议。">修复建议</span>
<span class="term" data-tip="解释用于说明计划、风险、失败原因和人工介入建议。">解释</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="外部系统适配把网页、设备和机器人能力接入统一业务流程,避免各自独立运行、难以管理。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-robot mr-1"></i>外部系统适配</div>
<div class="term-list">
<span class="term" data-tip="网页操作用于网页、控制台和浏览器自动化能力。">网页操作</span>
<span class="term" data-tip="设备接入用于连接硬件、串口、设备接口或外设能力。">设备接入</span>
<span class="term" data-tip="机器人控制用于机器人本体能力,如感知、运动和语音。">机器人控制</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[60px]" data-tip="按需后台服务负责邮件读取、监听器、浏览器环境、配套后台程序和外部服务进程的启动、占用、健康、日志和空闲回收。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-server mr-1"></i>按需后台服务</div>
<div class="term-list">
<span class="term" data-tip="服务定义描述后台服务如何启动、停止、授权、检查健康和对外提供能力。">服务定义</span>
<span class="term" data-tip="运行实例是服务的一次实际运行,记录访问地址、进程和状态。">运行实例</span>
<span class="term" data-tip="占用关系表示某个任务正在依赖服务实例,决定服务是否能回收。">占用关系</span>
</div>
</div>
</div>
</div>
<!-- Plane 4: 运营记录与看板 -->
<div class="flex items-stretch border theme-border-blue rounded bg-white relative z-10">
<div class="w-12 md:w-40 theme-dark-blue text-white flex flex-col items-center justify-center p-2 rounded-l flex-shrink-0" data-tip="运营记录与看板沉淀业务过程、成果、经验和服务状态,让管理者能看进度、看风险、看结果、看责任。">
<i class="fa-solid fa-database text-xl mb-1"></i>
<span class="font-bold hidden md:block text-center leading-tight">运营记录与看板</span>
<span class="font-bold md:hidden text-center writing-vertical-lr text-xs mt-2">运营看板</span>
</div>
<div class="flex-1 theme-light-blue-bg p-3 grid grid-cols-1 md:grid-cols-7 gap-3 rounded-r">
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="业务状态台账保存计划、任务、执行记录和审批记录的当前状态,是进度和责任判断的依据。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-lock mr-1"></i>业务状态台账</div>
<div class="term-list">
<span class="term" data-tip="执行计划状态表示计划处于草稿、审核、激活、阻塞、完成或取消等阶段。">执行计划</span>
<span class="term" data-tip="工作任务状态表示任务是否待处理、排队、执行中、暂停、失败或完成。">工作任务</span>
<span class="term" data-tip="执行记录状态表示一次执行尝试的生命周期和健康信息。">执行记录</span>
<span class="term" data-tip="审批记录状态表示审批请求是否待处理、已通过、已拒绝、已过期或已取消。">审批记录</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="过程日志记录所有关键变化,是审计、回放、看板生成和问题追踪的基础。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-regular fa-file-lines mr-1"></i>过程日志</div>
<div class="term-list"><span class="term" data-tip="关键过程记录是已经发生的业务变化,如任务开始、执行失败、服务启动或经验更新。">关键过程记录</span></div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="成果资料库存放执行生成的文件、报告、截图和结构化数据结果。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-folder-open mr-1"></i>成果资料库</div>
<div class="term-list">
<span class="term" data-tip="文件是执行生成或引用的本地或远端文件产物。">文件</span>
<span class="term" data-tip="报告是面向人或验收的总结性产物。">报告</span>
<span class="term" data-tip="截图用于证明界面、网页、浏览器或视觉状态。">截图</span>
<span class="term" data-tip="数据结果是可被系统继续读取的结构化数据、表格、记录或索引。">数据结果</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="经验与记忆库存放可复用知识,不代表当前任务状态,必须受来源、置信度、保留和遗忘规则约束。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-brain mr-1"></i>经验与记忆库</div>
<div class="term-list">
<span class="term" data-tip="项目事实是相对稳定、可引用的信息,但仍应有来源和置信度。">项目事实</span>
<span class="term" data-tip="使用偏好记录用户、项目或团队的长期选择倾向。">使用偏好</span>
<span class="term" data-tip="关键决策记录已经确定的架构、流程、策略或边界选择。">关键决策</span>
<span class="term" data-tip="处理经验记录过去执行中的成功路径、失败模式和修复方法。">处理经验</span>
<span class="term" data-tip="观察摘要从邮件、消息、工单、服务日志或运行结果中提炼可复用结论。">观察摘要</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="运营看板面向管理、查询和协同,由状态、过程日志、成果、经验记忆和服务健康汇总生成。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-chart-column mr-1"></i>运营看板</div>
<div class="term-list">
<span class="term" data-tip="任务看板展示任务状态、阻塞、风险和下一步动作。">任务看板</span>
<span class="term" data-tip="审批队列集中展示等待人工处理的治理节点。">审批队列</span>
<span class="term" data-tip="记忆索引让用户查看、修正、替代或遗忘长期记忆。">记忆索引</span>
<span class="term" data-tip="服务健康展示服务实例、占用关系、重启和最近错误。">服务健康</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="全程追踪按时间顺序展示计划、任务、执行、审批、服务和经验记忆变化。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-clock-rotate-left mr-1"></i>全程追踪</div>
<div class="term-list">
<span class="term" data-tip="过程回放按时间顺序复原业务过程和人工操作。">过程回放</span>
<span class="term" data-tip="诊断用于定位失败原因、依赖问题、服务退化或策略阻塞。">诊断</span>
<span class="term" data-tip="追责用于确认谁在什么时候通过什么操作改变了什么状态。">追责</span>
</div>
</div>
<div class="bg-white border theme-border-blue rounded p-2 shadow-sm min-h-[65px]" data-tip="运营指标用于验收、运营和持续改进,衡量服务时效、成功率、响应耗时和人工介入率。">
<div class="font-bold theme-text-dark-blue text-[13px]"><i class="fa-solid fa-chart-simple mr-1"></i>运营指标</div>
<div class="term-list">
<span class="term" data-tip="服务时效衡量任务、服务或工作流的服务水平和完成时限。">服务时效</span>
<span class="term" data-tip="成功率衡量任务、能力、服务或计划执行成功的比例。">成功率</span>
<span class="term" data-tip="响应耗时衡量目标接入、任务排队、执行、看板生成和审批等待时间。">响应耗时</span>
<span class="term" data-tip="人工介入率衡量有多少任务需要审批、暂停、接管或人工修复。">人工介入率</span>
</div>
</div>
</div>
</div>
</div> <!-- End of Main Architecture Container -->
<!-- 核心闭环 -->
<div class="mt-4 border border-blue-200 rounded flex overflow-hidden shadow-sm">
<div class="w-16 md:w-24 theme-dark-blue text-white flex flex-col items-center justify-center p-2 flex-shrink-0" data-tip="核心闭环展示一次业务目标从接入、计划、执行、沉淀、看板到人工决策的完整路径。">
<i class="fa-solid fa-rotate text-xl mb-1"></i>
<span class="font-bold text-center text-xs md:text-sm">核心闭环</span>
</div>
<div class="flex-1 bg-white p-4 relative overflow-x-auto">
<div class="flex items-center justify-between min-w-[1260px] mb-4 mt-2 px-4">
<div class="flex items-center gap-1 font-bold theme-text-dark-blue" data-tip="业务目标是用户或外部系统想达成的结果,进入系统后会先转成可治理的执行计划。"><i class="fa-solid fa-bullseye mr-1"></i>业务目标</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue" data-tip="执行计划描述为什么做、做成什么、如何拆,并支持人工审查、冻结和重新规划。"><i class="fa-regular fa-file-lines mr-1"></i>执行计划</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue" data-tip="工作任务是由计划步骤拆出来的可调度工作单元,负责绑定能力、输入、优先级和依赖。"><i class="fa-solid fa-list-ul mr-1"></i>工作任务</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue" data-tip="能力匹配为当前任务选择正式自动化能力或业务流程,必须满足版本、策略、权限和输入输出约定。"><i class="fa-solid fa-link mr-1"></i>能力匹配</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue" data-tip="执行前准备需要召回的经验记忆、需要启动或占用的后台服务,例如邮件读取、浏览器环境或外部服务进程。"><i class="fa-solid fa-server mr-1"></i>经验与服务准备</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue" data-tip="执行记录代表任务的一次执行尝试,记录执行人、服务占用、运行状态、恢复点和最终状态。"><i class="fa-regular fa-circle-play mr-1"></i>执行记录</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 font-bold theme-text-dark-blue" data-tip="自动执行阶段由脚本、流程、智能辅助或外部系统适配真正调用资源,并持续回写过程记录和状态。"><i class="fa-solid fa-gear mr-1"></i>自动执行</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 border border-blue-200 px-2 py-1 rounded theme-text-dark-blue bg-gray-50" data-tip="执行结果沉淀为业务状态、过程日志、成果资料和可复用经验,后续看板和审计都从这里生成。"><i class="fa-solid fa-database mr-1"></i>过程记录与成果沉淀</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 font-bold theme-text-dark-blue" data-tip="运营看板面向管理和查询,包括任务看板、全程追踪、审批队列、记忆索引和服务健康。"><i class="fa-solid fa-chart-column mr-1"></i>运营看板</div>
<i class="fa-solid fa-arrow-right text-blue-300 text-sm"></i>
<div class="flex items-center gap-1 font-bold theme-red border border-red-200 px-2 py-1 rounded" data-tip="人工决策允许审批、暂停、恢复、取消、接管和重新规划,并把每次干预记录下来。"><i class="fa-regular fa-user mr-1"></i>人工决策</div>
</div>
<!-- 底部虚线回环 -->
<div class="relative mt-6 min-w-[1260px] h-4">
<div class="absolute w-[80%] left-[10%] border-t border-dashed border-red-500 top-1/2"></div>
<div class="absolute left-[10%] top-1/2 -mt-1"><div class="arrow-left-red"></div></div>
<div class="absolute w-full flex justify-center -top-3">
<span class="bg-white px-2 text-xs font-bold theme-red" data-tip="人工决策会回到计划或任务层,改变后续执行路径,而不是直接绕过业务流程。">审批 / 暂停 / 恢复 / 取消 / 人工接管 / 重新规划</span>
</div>
<!-- 垂直连接线 -->
<div class="absolute left-[10%] bottom-1/2 h-4 border-l border-dashed border-red-500"></div>
<div class="absolute right-[10%] bottom-1/2 h-6 border-r border-dashed border-red-500"></div>
</div>
</div>
</div>
</div>
<script>
const tooltip = document.createElement("div");
tooltip.id = "sg-tooltip";
document.body.appendChild(tooltip);
let activeTipTarget = null;
const exampleRules = [
{ keys: ["汇报专用静态网站"], example: "双击 report-site/index.html 打开后,可在业务架构总览和业务流程图之间切换。" },
{ keys: ["业务架构总览"], example: "汇报开场先用这一页讲清楚 sgRobot 的四个业务分区。" },
{ keys: ["业务流程图"], example: "讲邮件触发流程时,可以切到流程页看它经过哪些架构模块。" },
{ keys: ["外部参与者"], example: "业务人员提交目标,运维看服务状态,审批人处理高风险动作。" },
{ keys: ["用户是目标"], example: "用户提出“把今天收到的客户邮件整理成日报”。" },
{ keys: ["运维关注"], example: "运维发现邮件读取服务连续失败后,查看健康状态并重启服务。" },
{ keys: ["审批人负责"], example: "系统要自动发送外部邮件前,审批人确认内容和收件人。" },
{ keys: ["外部业务系统"], example: "工单系统产生新工单后,通过系统接口触发 sgRobot 处理。" },
{ keys: ["业务入口与协同"], example: "用户提交巡检需求,外部系统推送消息,审批人在工作台确认风险动作。" },
{ keys: ["业务需求入口"], example: "每天 9 点的巡检计划、人工提交的日报需求、邮件到达事件都先进入这里。" },
{ keys: ["人工提交"], example: "负责人在工作台提交“生成本周设备巡检报告”。" },
{ keys: ["系统接口"], example: "CRM 系统把新客户资料同步过来,请求自动补全客户画像。" },
{ keys: ["计划任务"], example: "每个工作日 18 点自动汇总当天处理结果。" },
{ keys: ["事件触发"], example: "指定邮箱收到带附件的邮件后,自动触发读取和归档流程。" },
{ keys: ["协同工作台"], example: "审批人打开工作台查看待审批队列,运维查看失败任务。" },
{ keys: ["查看"], example: "查看某个任务当前是排队中、执行中还是等待审批。" },
{ keys: ["操作"], example: "用户手动暂停一个执行中的网页采集任务。" },
{ keys: ["审批"], example: "自动发送客户邮件前,需要审批人确认内容。" },
{ keys: ["回放"], example: "复盘昨天失败的巡检任务,查看它在哪一步超时。" },
{ keys: ["成果浏览"], example: "打开自动生成的报告、截图和数据表进行验收。" },
{ keys: ["任务治理与风控"], example: "把“处理客户邮件”拆成读取、分类、回复、归档,并在发信前要求审批。" },
{ keys: ["目标计划管理"], example: "把“生成月度巡检报告”拆成采集数据、生成报告、提交验收。" },
{ keys: ["业务目标"], example: "目标可以是“完成今日邮件分类并输出异常清单”。" },
{ keys: ["执行计划"], example: "计划中写明先读取邮件,再分类,再生成日报,最后等待验收。" },
{ keys: ["计划步骤"], example: "“登录系统下载报表”就是计划里的一个步骤。" },
{ keys: ["任务执行管理"], example: "同一计划下的多个采集任务可以排队、重试、暂停或取消。" },
{ keys: ["工作任务"], example: "“读取 inbox 中未处理邮件”是一项可调度工作任务。" },
{ keys: ["执行记录"], example: "第一次读取邮件失败后,第二次重试会形成新的执行记录。" },
{ keys: ["自动重试"], example: "网页临时超时后,系统在 3 分钟后自动再试一次。" },
{ keys: ["恢复点"], example: "长流程已经完成数据下载,失败后从报告生成环节继续。" },
{ keys: ["超时管控"], example: "浏览器操作超过 10 分钟未完成,就转入失败恢复或人工介入。" },
{ keys: ["人工治理"], example: "任务可以被审批、暂停、恢复、取消、接管或重新规划。" },
{ keys: ["审批通过"], example: "审批人确认发信内容无误后,允许流程继续发送。" },
{ keys: ["暂停"], example: "发现输入资料不完整时,先暂停任务等待补充。" },
{ keys: ["恢复"], example: "资料补齐后,从暂停点继续执行,不必从头开始。" },
{ keys: ["取消"], example: "业务目标已经撤销,取消计划并释放后台服务。" },
{ keys: ["人工接管"], example: "网页验证码无法自动处理时,转给人工完成后再继续。" },
{ keys: ["重新规划"], example: "原接口不可用,改走网页下载报表的替代路径。" },
{ keys: ["风险与规则"], example: "涉及外部发信、删除文件、控制设备的动作必须进入审批。" },
{ keys: ["记忆规则"], example: "用户偏好可以长期保留,但临时验证码不允许写入记忆。" },
{ keys: ["服务占用"], example: "某个任务正在使用邮件读取服务时,系统不会把该服务提前回收。" },
{ keys: ["风险等级"], example: "读取邮件是低风险,批量发信是高风险,需要审批。" },
{ keys: ["健康状态"], example: "邮件服务正常、浏览器环境异常、任务队列积压都能被展示出来。" },
{ keys: ["自动执行与能力"], example: "系统调用脚本、流程、智能辅助和外部系统适配来完成真实业务动作。" },
{ keys: ["能力目录"], example: "“读取邮件”“生成报告”“网页下载报表”都登记成可复用能力。" },
{ keys: ["能力登记"], example: "新增一个“登录后台下载销售报表”的自动化能力。" },
{ keys: ["版本管理"], example: "报表下载流程改版后,保留 v1 和 v2避免影响旧任务。" },
{ keys: ["使用约定"], example: "规定输入必须包含日期范围,输出必须包含报告文件和数据结果。" },
{ keys: ["调度中枢"], example: "先检查账号和服务是否可用,再安排读取邮件、分类和生成报告。" },
{ keys: ["前置检查"], example: "执行前确认邮箱权限、浏览器环境、审批状态都满足条件。" },
{ keys: ["能力匹配"], example: "同样是取报表,优先走接口,接口失败再走网页自动化。" },
{ keys: ["失败恢复"], example: "下载失败后先重试,仍失败则换备用路径或转人工处理。" },
{ keys: ["自动脚本"], example: "每天固定导出报表、清洗数据、生成 CSV 文件。" },
{ keys: ["确定性任务"], example: "把固定格式表格转换成统一字段就是确定性任务。" },
{ keys: ["流程编排"], example: "把邮件读取、附件解析、报告生成、审批发送组合成一条流程。" },
{ keys: ["组合能力"], example: "“客户邮件处理”由读取、分类、回复草稿、归档四个能力组合。" },
{ keys: ["子流程"], example: "报告生成任务内部再拆成取数、制图、写摘要三个子流程。" },
{ keys: ["智能辅助"], example: "根据失败日志判断可能原因,并给出下一步处理建议。" },
{ keys: ["规划用于"], example: "把“做一份巡检报告”拆成采集、分析、生成、验收。" },
{ keys: ["修复建议"], example: "系统提示“登录页结构变化,建议改用备用选择器或人工接管”。" },
{ keys: ["解释用于"], example: "向审批人说明为什么这一步被判定为高风险。" },
{ keys: ["外部系统适配"], example: "同一业务流程可以同时操作网页后台、设备接口和机器人。" },
{ keys: ["网页操作"], example: "自动登录后台,下载当天订单报表。" },
{ keys: ["设备接入"], example: "读取设备状态或通过设备接口下发巡检命令。" },
{ keys: ["机器人控制"], example: "让机器人执行移动、拍照、语音播报等动作。" },
{ keys: ["按需后台服务"], example: "只有处理邮件任务时才启动邮件读取服务,空闲后自动回收。" },
{ keys: ["服务定义"], example: "定义邮件读取服务如何启动、检查健康、停止和授权。" },
{ keys: ["运行实例"], example: "当前启动了一个邮件读取实例,状态为运行中。" },
{ keys: ["占用关系"], example: "任务 A 正在使用浏览器环境,因此该环境不能被其他任务关闭。" },
{ keys: ["运营记录与看板"], example: "领导可以看到任务进度、风险节点、成果报告和人工介入情况。" },
{ keys: ["业务状态台账"], example: "某计划已激活,三个任务成功,一个任务等待审批。" },
{ keys: ["执行计划状态"], example: "计划当前处于“等待审批”或“执行中”。" },
{ keys: ["工作任务状态"], example: "任务当前是排队中、执行中、暂停、失败或完成。" },
{ keys: ["执行记录状态"], example: "第 2 次执行成功,第 1 次执行因网页超时失败。" },
{ keys: ["审批记录状态"], example: "发信审批已通过,删除文件审批被拒绝。" },
{ keys: ["过程日志"], example: "记录任务开始、服务启动、审批通过、执行失败等关键变化。" },
{ keys: ["关键过程记录"], example: "“09:03 邮件读取服务启动”“09:05 附件解析失败”。" },
{ keys: ["成果资料库"], example: "保存巡检报告、页面截图、附件解析结果和导出的表格。" },
{ keys: ["文件是"], example: "保存下载的 Excel、PDF 报告或邮件附件。" },
{ keys: ["报告是"], example: "自动生成日报、巡检报告或异常汇总。" },
{ keys: ["截图用于"], example: "保留网页提交成功页面,作为验收证据。" },
{ keys: ["数据结果"], example: "把邮件分类结果保存成结构化表格,供后续统计。" },
{ keys: ["经验与记忆库"], example: "记录某项目常用账号、报告格式偏好、失败处理经验。" },
{ keys: ["项目事实"], example: "某系统的报表入口固定在“运营中心 / 日报”菜单下。" },
{ keys: ["使用偏好"], example: "用户偏好报告用中文摘要,并保留原始数据表。" },
{ keys: ["关键决策"], example: "决定所有外部发信必须先进入人工审批。" },
{ keys: ["处理经验"], example: "某网页下载失败时,先刷新登录态再重试。" },
{ keys: ["观察摘要"], example: "最近三次失败都集中在同一个外部系统登录环节。" },
{ keys: ["运营看板"], example: "展示今日任务成功率、待审批数量、失败任务和服务健康。" },
{ keys: ["任务看板"], example: "看到哪些任务已完成、哪些阻塞、哪些需要人工介入。" },
{ keys: ["审批队列"], example: "所有等待确认的发信、删除、设备控制动作集中展示。" },
{ keys: ["记忆索引"], example: "查看并修正“用户偏好报告格式”的长期记忆。" },
{ keys: ["服务健康"], example: "邮件读取服务正常,浏览器环境重启 1 次,设备连接异常。" },
{ keys: ["全程追踪"], example: "按时间线查看一次任务从提交到验收的完整过程。" },
{ keys: ["过程回放"], example: "复盘某次失败,看到它在附件解析步骤出错。" },
{ keys: ["诊断"], example: "定位失败原因是账号过期、网页变化还是服务不可用。" },
{ keys: ["追责"], example: "确认是谁在什么时间批准了批量发信动作。" },
{ keys: ["运营指标"], example: "每周统计成功率、平均耗时和人工介入率。" },
{ keys: ["服务时效"], example: "巡检报告要求 30 分钟内完成并提交。" },
{ keys: ["成功率"], example: "本周邮件处理任务 100 次,成功 96 次。" },
{ keys: ["响应耗时"], example: "从邮件到达到生成处理结果平均耗时 2 分钟。" },
{ keys: ["人工介入率"], example: "本月 12% 的任务因审批或异常需要人工介入。" },
{ keys: ["核心闭环"], example: "一封客户邮件进入系统后,生成任务、自动处理、沉淀成果,再进入看板和复盘。" },
{ keys: ["经验与服务准备"], example: "执行前先读取用户偏好,并启动邮件读取或浏览器服务。" },
{ keys: ["过程记录与成果沉淀"], example: "任务完成后保存报告、截图、日志和可复用处理经验。" },
{ keys: ["人工决策"], example: "审批人确认批量发信、暂停异常任务或要求重新规划。" },
{ keys: ["审批 / 暂停"], example: "审批不通过时,流程回到计划层重新规划。" },
];
function normalizeText(value) {
return (value || "").replace(/\s+/g, " ").trim();
}
function tooltipExample(target) {
const label = normalizeText(target.textContent);
const base = normalizeText(target.dataset.tip);
const haystack = `${label} ${base}`;
const rule = exampleRules.find((item) => item.keys.every((key) => haystack.includes(key)));
if (rule) return rule.example;
return "领导查看该节点时,可以把它对应到一次人工交办、邮件触发、定时巡检或高风险审批中的具体动作。";
}
function tooltipText(target) {
const text = normalizeText(target.dataset.tip);
if (!text) return "";
if (text.includes("例:")) return text;
return `${text}\n例:${tooltipExample(target)}`;
}
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 = tooltipText(target);
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", tooltipText(element));
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>

View File

@@ -0,0 +1,626 @@
<!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-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; }
.panel {
border: 1px solid #aec3db;
border-radius: 8px;
background: white;
box-shadow: 0 8px 20px rgba(13, 39, 88, 0.08);
overflow: hidden;
}
.panel-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 16px 10px 16px;
border-bottom: 1px solid #d8e4f2;
}
.panel-title {
display: flex;
align-items: center;
gap: 10px;
color: #0d2758;
font-weight: 900;
font-size: 1.3rem;
line-height: 1.25;
}
.panel-tag {
border: 1px solid #c8d7e8;
border-radius: 999px;
padding: 3px 10px;
color: #5f7082;
background: #f8fbff;
font-weight: 800;
white-space: nowrap;
font-size: 0.92rem;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
padding: 14px;
background: #f0f6fc;
}
.summary-card {
border: 1px solid #aec3db;
border-radius: 8px;
background: white;
padding: 12px;
color: #0d2758;
}
.summary-card strong {
display: block;
font-size: 1.5rem;
line-height: 1;
margin-bottom: 6px;
}
.summary-card span {
display: block;
color: #5f7082;
font-weight: 800;
line-height: 1.32;
}
.task-table-wrap {
overflow-x: auto;
background: #f0f6fc;
}
.task-table {
width: 100%;
min-width: 1320px;
border-collapse: collapse;
color: #0d2758;
}
.task-table th {
background: #0d2758;
color: white;
text-align: left;
padding: 11px 12px;
font-weight: 900;
border-right: 1px solid #375078;
white-space: nowrap;
}
.task-table td {
background: white;
padding: 11px 12px;
border-right: 1px solid #d8e4f2;
border-bottom: 1px solid #d8e4f2;
vertical-align: top;
font-weight: 760;
line-height: 1.38;
}
.task-table tr:nth-child(even) td {
background: #f8fbff;
}
.task-name {
font-weight: 900;
color: #0d2758;
}
.date-pill {
display: inline-flex;
align-items: center;
border-radius: 999px;
background: #0d2758;
color: white;
padding: 4px 10px;
font-weight: 900;
white-space: nowrap;
}
.owner-pill {
display: inline-flex;
align-items: center;
border-radius: 999px;
border: 1px solid #c8d7e8;
background: white;
color: #0d2758;
padding: 4px 10px;
font-weight: 900;
white-space: nowrap;
}
.boundary-ok {
color: #0d2758;
}
.boundary-no {
color: #9f1239;
}
.interface-map-wrap {
overflow-x: auto;
background: #f0f6fc;
padding: 14px;
}
.interface-map {
min-width: 1320px;
width: 100%;
height: auto;
display: block;
border: 1px solid #d8e4f2;
border-radius: 8px;
background: white;
}
.map-note {
padding: 10px 14px 14px 14px;
background: #f0f6fc;
color: #5f7082;
font-weight: 800;
line-height: 1.4;
}
.timeline {
display: grid;
grid-template-columns: repeat(6, minmax(160px, 1fr));
gap: 10px;
padding: 14px;
background: #f0f6fc;
overflow-x: auto;
}
.time-card {
min-width: 170px;
border: 1px solid #aec3db;
border-radius: 8px;
background: white;
padding: 12px;
color: #0d2758;
}
.time-date {
display: inline-flex;
background: #0d2758;
color: white;
border-radius: 999px;
padding: 4px 10px;
font-weight: 900;
margin-bottom: 8px;
}
.time-title {
font-weight: 900;
line-height: 1.25;
margin-bottom: 5px;
}
.time-text {
color: #5f7082;
font-weight: 760;
line-height: 1.35;
}
#sg-tooltip {
position: fixed;
z-index: 9999;
max-width: 460px;
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) {
.summary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.timeline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
.summary-grid { grid-template-columns: 1fr; }
.timeline { grid-template-columns: 1fr; }
.panel-head { align-items: flex-start; flex-direction: column; }
}
</style>
</head>
<body class="bg-white p-4 md:p-8 min-h-screen text-sm select-none">
<div class="max-w-[1780px] mx-auto mb-4 border border-amber-300 bg-amber-50 text-amber-900 rounded-lg px-4 py-3 shadow-sm">
<div class="font-black text-base">历史汇报版</div>
<div class="text-sm leading-relaxed mt-1">
本页面保留为早期 10 任务包汇报视图,不再作为团队分工和接口冻结源头。当前分工、接口 owner、状态、Mock 和验收证据以
<code>plan/2026-04-26-architecture-team-handoff/</code>
及其中的 <code>interfaces/interface-freeze-register.md</code> 为准。
</div>
</div>
<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="返回业务架构总览。">业务架构总览</a>
<a href="flows.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>
<a href="roadmap.html" class="theme-dark-blue text-white rounded px-4 py-2 font-bold shadow-sm" 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-list-check 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>。各模块只按公共接口交付不互相改代码5 月 31 日统一验收。
</div>
</header>
<main class="max-w-[1780px] mx-auto flex flex-col gap-5">
<section class="panel" data-tip="这四个数字是领导快速判断范围用的。">
<div class="panel-head">
<div class="panel-title"><i class="fa-solid fa-circle-info"></i><span>一页结论</span></div>
<span class="panel-tag" data-tip="如需具体人名,直接把负责人角色替换为姓名即可。">负责人先按角色占位</span>
</div>
<div class="summary-grid">
<div class="summary-card" data-tip="共 10 个任务包;公共接口只做口径冻结,核心控制另行实现,避免一个负责人背所有责任。"><strong>10 个</strong><span>任务包</span></div>
<div class="summary-card" data-tip="只设一个最终日期2026 年 5 月 31 日完成上线验收。"><strong>5/31</strong><span>上线验收收口</span></div>
<div class="summary-card" data-tip="模块之间只通过公共接口、测试样例和交付物对接。"><strong>互不改代码</strong><span>只按接口交付</span></div>
<div class="summary-card" data-tip="测试和发布有否决权,没证据就不能算完成。"><strong>有证据</strong><span>才算完成</span></div>
</div>
</section>
<section class="panel" data-tip="这是核心表。领导看这一张表就能知道谁负责什么、哪天完成、边界在哪里。">
<div class="panel-head">
<div class="panel-title"><i class="fa-solid fa-table"></i><span>任务分工总表</span></div>
<span class="panel-tag" data-tip="完成日期是建议倒排,可根据真实人员情况微调。">按完成日期倒排</span>
</div>
<div class="task-table-wrap">
<table class="task-table">
<thead>
<tr>
<th>任务</th>
<th>负责人</th>
<th>完成日期</th>
<th>交付物</th>
<th>边界:只负责</th>
<th>边界:不负责</th>
</tr>
</thead>
<tbody>
<tr data-tip="公共接口不要求 4 月 30 日全部实现只要求各负责人把字段、调用方向、Mock 数据和验收口径确认下来。">
<td><span class="task-name">公共接口口径冻结</span></td>
<td><span class="owner-pill">总负责人 + 各模块负责人</span></td>
<td><span class="date-pill">4/30</span></td>
<td>接口目录、字段草案、Mock 数据、对接方向、验收口径</td>
<td class="boundary-ok">只冻结模块之间怎么对接,以及每个模块交付什么数据</td>
<td class="boundary-no">不要求一次性完成所有后端实现;不替各模块写内部代码</td>
</tr>
<tr data-tip="核心后端只负责把主链路跑起来,不再同时承担所有适配模块的接口设计责任。">
<td><span class="task-name">核心控制主链路</span></td>
<td><span class="owner-pill">核心后端负责人</span></td>
<td><span class="date-pill">5/08</span></td>
<td>计划、任务、执行记录、审批、服务占用、能力目录最小实现</td>
<td class="boundary-ok">核心状态推进、公共接口实现、主链路冒烟</td>
<td class="boundary-no">不写 UI不写浏览器、硬件、本地服务实现</td>
</tr>
<tr data-tip="解决新增 Skill 时自动写控制脚本的问题。">
<td><span class="task-name">Skill 编写助手</span></td>
<td><span class="owner-pill">Skill 工具负责人</span></td>
<td><span class="date-pill">5/08</span></td>
<td>控制脚本生成器、模板、校验器、3 个示例 Skill</td>
<td class="boundary-ok">自动生成新 Skill 的控制脚本和校验规则</td>
<td class="boundary-no">不做浏览器、硬件、本地服务底层适配</td>
</tr>
<tr data-tip="把已有自动化脚本批量纳入 Skill 体系。">
<td><span class="task-name">自动化脚本批量转 Skill</span></td>
<td><span class="owner-pill">脚本迁移负责人</span></td>
<td><span class="date-pill">5/12</span></td>
<td>转换工具、迁移清单、已转换 Skill 包、回归报告</td>
<td class="boundary-ok">旧脚本包装、补输入输出、补日志、登记能力目录</td>
<td class="boundary-no">不重写业务逻辑;不改适配器底层能力</td>
</tr>
<tr data-tip="浏览器适配独立成包,不和 UI 混在一起。">
<td><span class="task-name">浏览器适配</span></td>
<td><span class="owner-pill">浏览器适配负责人</span></td>
<td><span class="date-pill">5/12</span></td>
<td>浏览器适配器、示例 Skill、截图证据、失败说明</td>
<td class="boundary-ok">打开页面、点击、输入、下载、截图、会话和错误回写</td>
<td class="boundary-no">不决定业务审批;不做 UI 页面;不写硬件接口</td>
</tr>
<tr data-tip="子程序和本地服务单独管理,避免主程序和后台服务绑死。">
<td><span class="task-name">本地服务与子程序管理</span></td>
<td><span class="owner-pill">本地服务负责人</span></td>
<td><span class="date-pill">5/14</span></td>
<td>服务管理器、服务清单、健康数据、运维命令</td>
<td class="boundary-ok">邮件读取、监听器、后台进程启动停止、健康、日志、回收</td>
<td class="boundary-no">不定义业务流程;不直接修改任务结果</td>
</tr>
<tr data-tip="硬件适配要有安全边界,不能绕过人工治理。">
<td><span class="task-name">硬件与机器人适配</span></td>
<td><span class="owner-pill">硬件适配负责人</span></td>
<td><span class="date-pill">5/14</span></td>
<td>硬件适配器、模拟测试、状态回写、安全风险清单</td>
<td class="boundary-ok">设备连接、状态读取、基础动作、机器人控制、异常停止</td>
<td class="boundary-no">不绕过审批执行高风险动作;不负责浏览器自动化</td>
</tr>
<tr data-tip="UI 只做操作台,不能自己发明另一套后端状态。">
<td><span class="task-name">UI 操作台</span></td>
<td><span class="owner-pill">前端负责人</span></td>
<td><span class="date-pill">5/18</span></td>
<td>任务看板、审批队列、服务健康、成果浏览、过程回放</td>
<td class="boundary-ok">用户操作入口和可视化验收页面</td>
<td class="boundary-no">不绕过后端改状态;不自建任务模型</td>
</tr>
<tr data-tip="编译打包独立负责 Windows、信创、ARM不和业务开发绑在一起。">
<td><span class="task-name">浏览器编译与平台打包</span></td>
<td><span class="owner-pill">构建发布负责人</span></td>
<td><span class="date-pill">5/22</span></td>
<td>Windows / 信创 / ARM 构建产物、依赖清单、安装说明</td>
<td class="boundary-ok">平台构建、依赖整理、打包、失败归因</td>
<td class="boundary-no">不改业务逻辑;不写 Skill不做 UI 功能</td>
</tr>
<tr data-tip="测试发布负责最终收口和上线判断。">
<td><span class="task-name">测试验收与发布收口</span></td>
<td><span class="owner-pill">测试发布负责人</span></td>
<td><span class="date-pill">5/31</span></td>
<td>测试报告、上线风险、已知问题、发布包、回滚方案</td>
<td class="boundary-ok">模块测试、端到端测试、兼容验证、发布门禁</td>
<td class="boundary-no">不替功能模块补实现,但可判定是否阻断上线</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="panel" data-tip="这张图只表达接口关系:每个负责人都通过中间的公共接口对接,模块之间不互相改代码。">
<div class="panel-head">
<div class="panel-title"><i class="fa-solid fa-diagram-project"></i><span>分工接口关系图</span></div>
<span class="panel-tag" data-tip="线上的文字就是这个负责人和核心接口之间的交付接口。">看线上的接口名</span>
</div>
<div class="interface-map-wrap">
<svg class="interface-map" viewBox="0 0 1500 720" role="img" aria-label="sgRobot 五月底上线分工接口关系图">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#6f8faf"></path>
</marker>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#0d2758" flood-opacity="0.12"></feDropShadow>
</filter>
</defs>
<rect x="40" y="30" width="1420" height="660" rx="10" fill="#f8fbff" stroke="#d8e4f2"></rect>
<rect x="555" y="64" width="390" height="92" rx="10" fill="#0d2758" filter="url(#shadow)"></rect>
<text x="750" y="102" text-anchor="middle" fill="#ffffff" font-size="25" font-weight="900">核心控制主链路</text>
<text x="750" y="132" text-anchor="middle" fill="#dbeafe" font-size="18" font-weight="800">核心后端负责人5/08 实现</text>
<rect x="565" y="285" width="370" height="118" rx="10" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="750" y="325" text-anchor="middle" fill="#0d2758" font-size="24" font-weight="900">公共接口合同</text>
<text x="750" y="356" text-anchor="middle" fill="#5f7082" font-size="17" font-weight="800">总负责人 + 各模块负责人共同确认4/30</text>
<text x="750" y="383" text-anchor="middle" fill="#d92d20" font-size="17" font-weight="900">核心后端只实现主链路,不替各模块兜底</text>
<line x1="750" y1="156" x2="750" y2="285" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<text x="766" y="226" fill="#5f7082" font-size="16" font-weight="800">核心接口实现</text>
<rect x="75" y="75" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="220" y="106" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">Skill 编写助手</text>
<text x="220" y="131" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">Skill 工具负责人</text>
<line x1="365" y1="111" x2="565" y2="302" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="376" y="178" width="172" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="462" y="200" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">Skill 生成合同</text>
<rect x="75" y="185" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="220" y="216" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">脚本批量转 Skill</text>
<text x="220" y="241" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">脚本迁移负责人</text>
<line x1="365" y1="221" x2="565" y2="327" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="386" y="253" width="160" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="466" y="275" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">Skill 包接口</text>
<rect x="75" y="295" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="220" y="326" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">浏览器适配</text>
<text x="220" y="351" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">浏览器适配负责人</text>
<line x1="365" y1="331" x2="565" y2="344" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="384" y="333" width="158" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="463" y="355" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">浏览器接口</text>
<rect x="75" y="405" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="220" y="436" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">本地服务管理</text>
<text x="220" y="461" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">本地服务负责人</text>
<line x1="365" y1="441" x2="565" y2="366" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="392" y="397" width="146" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="465" y="419" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">服务合同</text>
<rect x="75" y="515" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="220" y="546" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">硬件与机器人适配</text>
<text x="220" y="571" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">硬件适配负责人</text>
<line x1="365" y1="551" x2="565" y2="388" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="382" y="474" width="168" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="466" y="496" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">硬件适配接口</text>
<rect x="1135" y="120" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="1280" y="151" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">UI 操作台</text>
<text x="1280" y="176" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">前端负责人</text>
<line x1="1135" y1="156" x2="935" y2="310" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="960" y="220" width="152" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="1036" y="242" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">UI 数据接口</text>
<rect x="1135" y="285" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="1280" y="316" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">浏览器编译与打包</text>
<text x="1280" y="341" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">构建发布负责人</text>
<line x1="1135" y1="321" x2="935" y2="344" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="954" y="311" width="170" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="1039" y="333" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">构建产物接口</text>
<rect x="1135" y="450" width="290" height="72" rx="8" fill="#ffffff" stroke="#aec3db" stroke-width="2" filter="url(#shadow)"></rect>
<text x="1280" y="481" text-anchor="middle" fill="#0d2758" font-size="20" font-weight="900">测试验收与发布</text>
<text x="1280" y="506" text-anchor="middle" fill="#5f7082" font-size="16" font-weight="800">测试发布负责人</text>
<line x1="1135" y1="486" x2="935" y2="378" stroke="#6f8faf" stroke-width="3" marker-end="url(#arrow)"></line>
<rect x="958" y="412" width="158" height="32" rx="16" fill="#ffffff" stroke="#c8d7e8"></rect>
<text x="1037" y="434" text-anchor="middle" fill="#0d2758" font-size="15" font-weight="900">验收门禁</text>
<rect x="520" y="560" width="460" height="76" rx="10" fill="#fff7f7" stroke="#fecaca" stroke-width="2"></rect>
<text x="750" y="592" text-anchor="middle" fill="#9f1239" font-size="21" font-weight="900">规则:负责人之间不直接改对方模块</text>
<text x="750" y="620" text-anchor="middle" fill="#9f1239" font-size="17" font-weight="800">所有协作都落到接口合同、交付包、测试报告</text>
</svg>
</div>
<div class="map-note" data-tip="这句话是给领导看的解释口径。">
读图方式:每个白框是一个负责人,线上的文字是他交给核心控制或从核心控制读取的接口。除测试发布外,其他负责人不直接验收别人内部实现,只按接口和交付物对接。
</div>
</section>
<section class="panel" data-tip="把里程碑压缩到几个关键日期,领导只需要知道每个日期要看到什么。">
<div class="panel-head">
<div class="panel-title"><i class="fa-solid fa-calendar-days"></i><span>简版里程碑</span></div>
<span class="panel-tag" data-tip="不再画复杂甘特图,只保留关键日期。">哪个任务哪天完成</span>
</div>
<div class="timeline">
<div class="time-card" data-tip="这里只冻结口径,不要求完成全部实现。目标是让各模块能并行开工。">
<span class="time-date">4/30</span>
<div class="time-title">公共接口口径冻结</div>
<div class="time-text">接口目录、字段草案、Mock 数据、对接方向确认。</div>
</div>
<div class="time-card" data-tip="核心后端在这个日期前交付主链路最小实现,不再背所有适配模块的实现。">
<span class="time-date">5/08</span>
<div class="time-title">核心主链路完成</div>
<div class="time-text">计划、任务、执行记录、审批、服务占用可冒烟。</div>
</div>
<div class="time-card" data-tip="这一阶段拿到 Skill 生产、脚本迁移和浏览器适配首批能力。">
<span class="time-date">5/12</span>
<div class="time-title">Skill 与浏览器首批完成</div>
<div class="time-text">Skill 编写助手、脚本转 Skill、浏览器适配可用。</div>
</div>
<div class="time-card" data-tip="本地服务和硬件适配要给出可调用版本。">
<span class="time-date">5/14</span>
<div class="time-title">服务与硬件完成</div>
<div class="time-text">本地服务管理、硬件与机器人适配完成首版验收。</div>
</div>
<div class="time-card" data-tip="UI 在 5 月 18 日前必须从粗略页面变成可操作台。">
<span class="time-date">5/18</span>
<div class="time-title">UI 操作台完成</div>
<div class="time-text">任务、审批、服务、成果、回放都能操作或查看。</div>
</div>
<div class="time-card" data-tip="五月底只做验收和发布,不再扩功能。">
<span class="time-date">5/31</span>
<div class="time-title">上线验收完成</div>
<div class="time-text">发布包、测试报告、回滚方案、演示材料齐备。</div>
</div>
</div>
</section>
</main>
<script>
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>

View File

@@ -0,0 +1,176 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>白领一天业务测试页</title>
<style>
body {
margin: 0;
font-family: "Microsoft YaHei", Arial, sans-serif;
color: #1f2937;
background: #f6f8fb;
}
header {
padding: 20px 28px;
background: #0f766e;
color: white;
}
main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 16px;
padding: 20px;
}
section {
min-height: 180px;
padding: 16px;
border: 1px solid #d8dee8;
border-radius: 8px;
background: white;
}
h1,
h2 {
margin: 0 0 12px;
}
label,
input,
select,
textarea,
button {
display: block;
width: 100%;
box-sizing: border-box;
margin: 8px 0;
font-size: 14px;
}
input,
select,
textarea {
padding: 8px;
border: 1px solid #cbd5e1;
border-radius: 6px;
}
button {
padding: 9px 12px;
border: 0;
border-radius: 6px;
color: white;
background: #2563eb;
cursor: pointer;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
th,
td {
padding: 8px;
border-bottom: 1px solid #e5e7eb;
text-align: left;
}
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 999px;
background: #e0f2fe;
color: #0369a1;
}
.result {
min-height: 22px;
color: #166534;
font-weight: 600;
}
</style>
</head>
<body>
<header>
<h1>白领一天业务测试页</h1>
<p>用于验证数字员工通过 sgBrowser 完成网页采集、填写、比对和下载确认。</p>
</header>
<main>
<section id="company-contact">
<h2>供应商联系人</h2>
<p data-field="company">白银智维科技有限公司</p>
<p data-field="contact">联系人:李敏</p>
<p data-field="phone">电话0931-6201888</p>
<p data-field="email">邮箱limin@example.local</p>
</section>
<section id="industry-news">
<h2>行业动态</h2>
<ol>
<li data-score="96">内网终端安全巡检纳入月度闭环</li>
<li data-score="88">营销系统工单响应时限压缩至 2 小时</li>
<li data-score="81">国产化办公终端批量适配完成</li>
</ol>
</section>
<section id="customer-form">
<h2>客户回访登记</h2>
<label>客户名称<input id="customer-name" /></label>
<label>联系电话<input id="customer-phone" /></label>
<label>回访结论<select id="visit-result"><option>请选择</option><option>已解决</option><option>需跟进</option></select></label>
<textarea id="visit-note" rows="3" placeholder="回访备注"></textarea>
<button id="prepare-form" type="button">检查表单</button>
<p id="form-status" class="result"></p>
</section>
<section id="product-compare">
<h2>设备方案比对</h2>
<table>
<thead>
<tr><th>方案</th><th>价格</th><th>交付天数</th><th>风险</th></tr>
</thead>
<tbody>
<tr><td>基础巡检包</td><td>68000</td><td>12</td><td></td></tr>
<tr><td>增强巡检包</td><td>82000</td><td>9</td><td></td></tr>
<tr><td>全量管控包</td><td>98000</td><td>7</td><td></td></tr>
</tbody>
</table>
</section>
<section id="todo-login">
<h2>待办系统</h2>
<label>用户名<input id="login-user" /></label>
<label>口令<input id="login-pass" type="password" /></label>
<button id="login-button" type="button">登录</button>
<ul id="todo-list">
<li><span class="badge">紧急</span> 完成安全巡检日报</li>
<li><span class="badge">普通</span> 核对客户回访清单</li>
<li><span class="badge">普通</span> 整理明日会议材料</li>
</ul>
<p id="login-status" class="result"></p>
</section>
<section id="customer-list">
<h2>客户清单</h2>
<table>
<tbody>
<tr><td>兰州新区供电服务站</td><td>待回访</td><td>王磊</td></tr>
<tr><td>白银银光营业厅</td><td>已完成</td><td>张琴</td></tr>
<tr><td>景泰调度中心</td><td>需协同</td><td>马宁</td></tr>
</tbody>
</table>
</section>
<section id="download-center">
<h2>资料下载</h2>
<p>最新资料2026 年 5 月内网终端巡检模板</p>
<a id="latest-download" href="daily-template-202605.xlsx" download>下载巡检模板</a>
</section>
</main>
<script>
document.getElementById("prepare-form").addEventListener("click", function () {
const name = document.getElementById("customer-name").value.trim();
const result = document.getElementById("visit-result").value;
document.getElementById("form-status").textContent =
name && result !== "请选择" ? "表单已检查,等待人工确认提交" : "表单信息不完整";
});
document.getElementById("login-button").addEventListener("click", function () {
document.getElementById("login-status").textContent = "已读取待办,不执行真实登录";
});
</script>
</body>
</html>

View File

@@ -28,6 +28,7 @@ import {
ArrowLeftOutlined,
ReloadOutlined,
ApiOutlined,
AppstoreOutlined,
} from "@ant-design/icons";
import {
setupService,
@@ -57,6 +58,7 @@ import AboutPage from "./components/pages/AboutPage";
import LogViewer from "./components/pages/LogViewer";
import PermissionsPage from "./components/pages/PermissionsPage";
import SessionsPage from "./components/pages/SessionsPage";
import OverviewPage from "./components/pages/OverviewPage";
import MCPSettings from "./components/settings/MCPSettings";
import type { WebviewHeaderActions } from "./components/pages/SessionsPage";
import { createLogger } from "./services/utils/rendererLog";
@@ -104,6 +106,7 @@ export function useI18nLang(): I18nContextValue {
// Tab 类型定义(对齐 Tauri 客户端)
type TabKey =
| "client"
| "overview"
| "sessions"
| "mcp"
| "settings"
@@ -1054,6 +1057,11 @@ function App() {
icon: <DashboardOutlined />,
label: t("Claw.Menu.client"),
},
{
key: "overview",
icon: <AppstoreOutlined />,
label: t("Claw.Menu.overview"),
},
{
key: "sessions",
icon: <TeamOutlined />,
@@ -1353,6 +1361,7 @@ function App() {
onLoginStarted={handleLoginStarted}
/>
)}
{activeTab === "overview" && <OverviewPage />}
{activeTab === "sessions" && (
<SessionsPage
autoOpen={sessionsAutoOpen}

View File

@@ -0,0 +1,161 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { Alert, Button, Input, message } from "antd";
import { ReloadOutlined, SaveOutlined } from "@ant-design/icons";
import { APP_DISPLAY_NAME } from "@shared/constants";
import { t } from "../../services/core/i18n";
import styles from "../../styles/components/OverviewPage.module.css";
const OVERVIEW_URL_SETTING_KEY = "overview.digital_employee_url";
const DEFAULT_OVERVIEW_URL = "sgrobot-digital/index.html#/digital";
function normalizeOverviewUrl(value: string): string {
const trimmed = value.trim();
if (!trimmed) return DEFAULT_OVERVIEW_URL;
const url = new URL(trimmed, window.location.href);
const legacySgRobotEndpoint =
(url.hostname === "localhost" && url.port === "5173") ||
(url.hostname === "127.0.0.1" && url.port === "42617");
if (legacySgRobotEndpoint && url.pathname === "/_app/digital") {
return DEFAULT_OVERVIEW_URL;
}
if (!["http:", "https:", "file:"].includes(url.protocol)) {
throw new Error("Unsupported protocol");
}
return trimmed;
}
function OverviewPage() {
const webviewRef = useRef<HTMLElement | null>(null);
const [url, setUrl] = useState(DEFAULT_OVERVIEW_URL);
const [draftUrl, setDraftUrl] = useState(DEFAULT_OVERVIEW_URL);
const [error, setError] = useState<string | null>(null);
const [userAgent, setUserAgent] = useState<string | undefined>();
useEffect(() => {
window.electronAPI?.app
.getVersion()
.then((version) => {
setUserAgent(navigator.userAgent + ` ${APP_DISPLAY_NAME}/${version}`);
})
.catch(() => {});
}, []);
useEffect(() => {
let mounted = true;
window.electronAPI?.settings
.get(OVERVIEW_URL_SETTING_KEY)
.then((saved) => {
if (!mounted || typeof saved !== "string" || !saved.trim()) return;
const normalized = normalizeOverviewUrl(saved);
setUrl(normalized);
setDraftUrl(normalized);
})
.catch(() => {});
return () => {
mounted = false;
};
}, []);
useEffect(() => {
const el = webviewRef.current as any;
if (!el) return;
const handleStartLoading = () => setError(null);
const handleFailLoad = (e: any) => {
if (e.errorCode && e.errorCode !== -3) {
setError(
t(
"Claw.Overview.loadFailed",
e.errorDescription || t("Claw.EmbeddedWebview.unknownError"),
String(e.errorCode),
),
);
}
};
el.addEventListener("did-start-loading", handleStartLoading);
el.addEventListener("did-fail-load", handleFailLoad);
return () => {
el.removeEventListener("did-start-loading", handleStartLoading);
el.removeEventListener("did-fail-load", handleFailLoad);
};
}, [url]);
const canSave = useMemo(() => draftUrl.trim() !== url, [draftUrl, url]);
const webviewUrl = useMemo(
() => new URL(url, window.location.href).toString(),
[url],
);
const handleReload = useCallback(() => {
setError(null);
(webviewRef.current as any)?.reload?.();
}, []);
const handleSave = useCallback(async () => {
try {
const normalized = normalizeOverviewUrl(draftUrl);
await window.electronAPI?.settings.set(
OVERVIEW_URL_SETTING_KEY,
normalized,
);
setUrl(normalized);
setDraftUrl(normalized);
setError(null);
message.success(t("Claw.Overview.urlSaved"));
} catch {
message.error(t("Claw.Overview.invalidUrl"));
}
}, [draftUrl]);
return (
<div className={styles.container}>
<div className={styles.toolbar}>
<span className={styles.title}>{t("Claw.Overview.title")}</span>
<Input
size="small"
className={styles.urlInput}
value={draftUrl}
onChange={(e) => setDraftUrl(e.target.value)}
onPressEnter={handleSave}
/>
<Button
size="small"
icon={<SaveOutlined />}
onClick={handleSave}
disabled={!canSave}
>
{t("Claw.Common.save")}
</Button>
<Button size="small" icon={<ReloadOutlined />} onClick={handleReload}>
{t("Claw.Common.refresh")}
</Button>
</div>
{error && (
<Alert
message={error}
type="error"
showIcon
closable
onClose={() => setError(null)}
className={styles.error}
/>
)}
<webview
ref={webviewRef as any}
src={webviewUrl}
useragent={userAgent}
className={styles.webview}
allowpopups={"true" as any}
/>
</div>
);
}
export default OverviewPage;

View File

@@ -6,7 +6,7 @@
<link rel="icon" type="image/png" href="/icon.png" />
<!-- 与 @shared/constants APP_DISPLAY_NAME 保持一致 -->
<title>启明</title>
<title>飞天</title>
</head>
<body>
<div id="root"></div>

View File

@@ -0,0 +1,42 @@
.container {
display: flex;
flex: 1;
min-height: 0;
height: 100%;
flex-direction: column;
background: var(--color-bg-layout);
}
.toolbar {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid var(--color-border);
background: var(--color-bg-container);
flex-shrink: 0;
}
.title {
flex: 0 0 auto;
font-size: 13px;
font-weight: 600;
color: var(--color-text);
}
.urlInput {
flex: 1;
min-width: 180px;
}
.error {
margin: 8px 12px 0;
flex-shrink: 0;
}
.webview {
flex: 1;
width: 100%;
min-height: 0;
border: none;
}

View File

@@ -49,7 +49,7 @@ import {
describe("Constants", () => {
describe("App Identity", () => {
it("should have consistent app name", () => {
expect(APP_DISPLAY_NAME).toBe("启明数字员工");
expect(APP_DISPLAY_NAME).toBe("飞天数字员工");
expect(APP_NAME_IDENTIFIER).toBe("qimingclaw");
});

View File

@@ -10,7 +10,7 @@ import type { AgentEngineType } from "@shared/types/electron";
// ==================== 应用名称 ====================
/** 应用对外显示名称(窗口标题、关于、安装包名称等),与 package.json build.productName 保持一致 */
export const APP_DISPLAY_NAME = "启明数字员工";
export const APP_DISPLAY_NAME = "飞天数字员工";
/** 应用技术标识(进程名、目录名等,小写字母),与 appId 等保持一致 */
export const APP_NAME_IDENTIFIER = "qimingclaw";

View File

@@ -164,6 +164,7 @@
"Claw.Agent.Status.stopped": "Stopped",
"Claw.Agent.Status.error": "Error",
"Claw.Menu.client": "Client",
"Claw.Menu.overview": "Overview",
"Claw.Menu.session": "Session",
"Claw.Menu.mcp": "MCP",
"Claw.Menu.settings": "Settings",
@@ -254,6 +255,10 @@
"Claw.EmbeddedWebview.back": "Back",
"Claw.EmbeddedWebview.refresh": "Refresh",
"Claw.EmbeddedWebview.unknownError": "Unknown error",
"Claw.Overview.title": "Digital Employee Overview",
"Claw.Overview.loadFailed": "Digital employee page failed to load: {0} ({1})",
"Claw.Overview.urlSaved": "Overview URL saved",
"Claw.Overview.invalidUrl": "Enter a valid http/https URL",
"Claw.AgentRunner.configSaved": "Config saved",
"Claw.AgentRunner.stopped": "Agent Runner stopped",
"Claw.AgentRunner.started": "Agent Runner started",

View File

@@ -164,6 +164,7 @@
"Claw.Agent.Status.stopped": "已停止",
"Claw.Agent.Status.error": "错误",
"Claw.Menu.client": "客户端",
"Claw.Menu.overview": "概览",
"Claw.Menu.session": "会话",
"Claw.Menu.mcp": "MCP",
"Claw.Menu.settings": "设置",
@@ -254,6 +255,10 @@
"Claw.EmbeddedWebview.back": "返回",
"Claw.EmbeddedWebview.refresh": "刷新",
"Claw.EmbeddedWebview.unknownError": "未知错误",
"Claw.Overview.title": "数字员工概览",
"Claw.Overview.loadFailed": "数字员工页面加载失败: {0} ({1})",
"Claw.Overview.urlSaved": "概览地址已保存",
"Claw.Overview.invalidUrl": "请输入有效的 http/https 地址",
"Claw.AgentRunner.configSaved": "配置已保存",
"Claw.AgentRunner.stopped": "Agent Runner 已停止",
"Claw.AgentRunner.started": "Agent Runner 已启动",

View File

@@ -164,6 +164,7 @@
"Claw.Agent.Status.stopped": "已停止",
"Claw.Agent.Status.error": "錯誤",
"Claw.Menu.client": "客戶端",
"Claw.Menu.overview": "概覽",
"Claw.Menu.session": "工作階段",
"Claw.Menu.mcp": "MCP",
"Claw.Menu.settings": "設定",
@@ -254,6 +255,10 @@
"Claw.EmbeddedWebview.back": "返回",
"Claw.EmbeddedWebview.refresh": "重新整理",
"Claw.EmbeddedWebview.unknownError": "未知錯誤",
"Claw.Overview.title": "數字員工概覽",
"Claw.Overview.loadFailed": "數字員工頁面載入失敗: {0} ({1})",
"Claw.Overview.urlSaved": "概覽位址已儲存",
"Claw.Overview.invalidUrl": "請輸入有效的 http/https 位址",
"Claw.AgentRunner.configSaved": "配置已儲存",
"Claw.AgentRunner.stopped": "Agent Runner 已停止",
"Claw.AgentRunner.started": "Agent Runner 已啟動",

View File

@@ -164,6 +164,7 @@
"Claw.Agent.Status.stopped": "已停止",
"Claw.Agent.Status.error": "錯誤",
"Claw.Menu.client": "客戶端",
"Claw.Menu.overview": "概覽",
"Claw.Menu.session": "工作階段",
"Claw.Menu.mcp": "MCP",
"Claw.Menu.settings": "設定",
@@ -254,6 +255,10 @@
"Claw.EmbeddedWebview.back": "返回",
"Claw.EmbeddedWebview.refresh": "重新整理",
"Claw.EmbeddedWebview.unknownError": "未知錯誤",
"Claw.Overview.title": "數字員工概覽",
"Claw.Overview.loadFailed": "數字員工頁面載入失敗: {0} ({1})",
"Claw.Overview.urlSaved": "概覽位址已儲存",
"Claw.Overview.invalidUrl": "請輸入有效的 http/https 位址",
"Claw.AgentRunner.configSaved": "配置已儲存",
"Claw.AgentRunner.stopped": "Agent Runner 已停止",
"Claw.AgentRunner.started": "Agent Runner 已啟動",