feat(原型设计): 增强强Agent对话工作台原型
This commit is contained in:
@@ -6,24 +6,27 @@
|
|||||||
<title>注册审核平台原型演示站</title>
|
<title>注册审核平台原型演示站</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--bg: #edf2f6;
|
--bg: #eef2f5;
|
||||||
--bg-strong: #dfe8ef;
|
--bg-strong: #d9e1e8;
|
||||||
--panel: rgba(255, 255, 255, 0.92);
|
--panel: #ffffff;
|
||||||
--panel-strong: #ffffff;
|
--panel-strong: #ffffff;
|
||||||
--ink: #122233;
|
--ink: #132535;
|
||||||
--muted: #5f7285;
|
--muted: #627588;
|
||||||
--line: #d5dee6;
|
--line: #d7e0e7;
|
||||||
--navy: #153d62;
|
--line-strong: #c4d0da;
|
||||||
--teal: #1f6b7a;
|
--navy: #173a58;
|
||||||
--accent: #d6803b;
|
--navy-strong: #112b42;
|
||||||
--danger: #b54a34;
|
--teal: #245d69;
|
||||||
--success: #2f7d57;
|
--accent: #b77a39;
|
||||||
--warning: #cb8a2f;
|
--danger: #a94731;
|
||||||
--shadow: 0 18px 40px rgba(28, 48, 73, 0.12);
|
--success: #2f6a4b;
|
||||||
--radius-xl: 28px;
|
--warning: #b8802f;
|
||||||
--radius-lg: 20px;
|
--shadow: 0 8px 18px rgba(23, 41, 61, 0.06);
|
||||||
--radius-md: 14px;
|
--shadow-strong: 0 12px 24px rgba(18, 35, 53, 0.08);
|
||||||
--radius-sm: 10px;
|
--radius-xl: 10px;
|
||||||
|
--radius-lg: 8px;
|
||||||
|
--radius-md: 6px;
|
||||||
|
--radius-sm: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -35,9 +38,7 @@
|
|||||||
font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", sans-serif;
|
font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", sans-serif;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(59, 108, 143, 0.18), transparent 30%),
|
linear-gradient(180deg, #f5f7f9 0%, #edf2f5 100%);
|
||||||
radial-gradient(circle at bottom right, rgba(215, 128, 59, 0.14), transparent 30%),
|
|
||||||
linear-gradient(180deg, #f6f9fb 0%, #edf2f6 100%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -61,19 +62,20 @@
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 24px 18px;
|
padding: 18px 14px;
|
||||||
background: linear-gradient(180deg, #163754 0%, #10283f 100%);
|
background: linear-gradient(180deg, #173754 0%, #122c43 100%);
|
||||||
color: rgba(255, 255, 255, 0.94);
|
color: rgba(255, 255, 255, 0.94);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 18px;
|
gap: 12px;
|
||||||
|
border-right: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand {
|
.brand {
|
||||||
padding: 18px;
|
padding: 16px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand h1 {
|
.brand h1 {
|
||||||
@@ -105,9 +107,9 @@
|
|||||||
|
|
||||||
.nav-btn {
|
.nav-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 14px 16px;
|
padding: 12px 14px;
|
||||||
border-radius: 14px;
|
border-radius: var(--radius-md);
|
||||||
background: rgba(255, 255, 255, 0.06);
|
background: rgba(255, 255, 255, 0.03);
|
||||||
color: white;
|
color: white;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
@@ -122,20 +124,21 @@
|
|||||||
|
|
||||||
.nav-btn.active,
|
.nav-btn.active,
|
||||||
.nav-btn:hover {
|
.nav-btn:hover {
|
||||||
background: rgba(255, 255, 255, 0.14);
|
background: rgba(255, 255, 255, 0.09);
|
||||||
border-color: rgba(255, 255, 255, 0.12);
|
border-color: rgba(255, 255, 255, 0.12);
|
||||||
transform: translateX(2px);
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-summary {
|
.sidebar-summary {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
padding: 22px 24px 30px;
|
padding: 16px 18px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar {
|
.topbar {
|
||||||
@@ -143,18 +146,18 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 18px 22px;
|
padding: 16px 18px;
|
||||||
border-radius: var(--radius-xl);
|
border-radius: var(--radius-xl);
|
||||||
background: rgba(255, 255, 255, 0.84);
|
background: #ffffff;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
border: 1px solid var(--line);
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
backdrop-filter: blur(18px);
|
margin-bottom: 16px;
|
||||||
margin-bottom: 22px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar h2 {
|
.topbar h2 {
|
||||||
margin: 0 0 6px;
|
margin: 0 0 6px;
|
||||||
font-size: 26px;
|
font-size: 22px;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-row,
|
.status-row,
|
||||||
@@ -174,19 +177,20 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 7px 12px;
|
padding: 6px 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-chip {
|
.status-chip {
|
||||||
background: #edf5ff;
|
background: #eef3f8;
|
||||||
color: var(--navy);
|
color: #264764;
|
||||||
|
border: 1px solid #d6e0ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
background: #f5f7fa;
|
background: #f6f8fa;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
@@ -209,27 +213,28 @@
|
|||||||
|
|
||||||
.primary-btn,
|
.primary-btn,
|
||||||
.secondary-btn {
|
.secondary-btn {
|
||||||
padding: 11px 16px;
|
padding: 10px 14px;
|
||||||
border-radius: 12px;
|
border-radius: var(--radius-md);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-btn {
|
.primary-btn {
|
||||||
background: linear-gradient(135deg, #1d5b8f 0%, #123c62 100%);
|
background: linear-gradient(180deg, #214b74 0%, #163754 100%);
|
||||||
color: white;
|
color: white;
|
||||||
box-shadow: 0 10px 24px rgba(21, 61, 98, 0.24);
|
box-shadow: none;
|
||||||
|
border: 1px solid #153754;
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-btn,
|
.secondary-btn,
|
||||||
.mini-btn {
|
.mini-btn {
|
||||||
background: white;
|
background: white;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line-strong);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mini-btn {
|
.mini-btn {
|
||||||
padding: 8px 10px;
|
padding: 7px 10px;
|
||||||
border-radius: 10px;
|
border-radius: var(--radius-md);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -247,16 +252,15 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1.35fr 1fr;
|
grid-template-columns: 1.35fr 1fr;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
border: 1px solid var(--line);
|
||||||
border-radius: var(--radius-xl);
|
border-radius: var(--radius-xl);
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
padding: 20px;
|
padding: 18px;
|
||||||
backdrop-filter: blur(18px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel h3,
|
.panel h3,
|
||||||
@@ -273,24 +277,24 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card,
|
.metric-card,
|
||||||
.task-card,
|
.task-card,
|
||||||
.info-card {
|
.info-card {
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
padding: 18px;
|
padding: 16px;
|
||||||
background: var(--panel-strong);
|
background: var(--panel-strong);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card strong {
|
.metric-card strong {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 30px;
|
font-size: 28px;
|
||||||
margin-top: 10px;
|
margin-top: 8px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--navy);
|
color: var(--navy-strong);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
@@ -315,7 +319,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-card {
|
.task-card {
|
||||||
@@ -325,21 +329,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.task-card.active {
|
.task-card.active {
|
||||||
border-color: rgba(21, 61, 98, 0.28);
|
border-color: #8da4b8;
|
||||||
box-shadow: 0 18px 34px rgba(21, 61, 98, 0.12);
|
box-shadow: none;
|
||||||
|
background: #fbfdff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-card.active::after {
|
.task-card.active::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
border-top: 5px solid var(--navy);
|
border-top: 3px solid var(--navy);
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-card h4 {
|
.task-card h4 {
|
||||||
margin: 0 0 8px;
|
margin: 0 0 8px;
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-card p {
|
.task-card p {
|
||||||
@@ -347,7 +352,7 @@
|
|||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-meta {
|
.task-meta {
|
||||||
@@ -397,10 +402,10 @@
|
|||||||
.issue-item,
|
.issue-item,
|
||||||
.check-item,
|
.check-item,
|
||||||
.governance-row {
|
.governance-row {
|
||||||
padding: 14px;
|
padding: 12px;
|
||||||
border-radius: 14px;
|
border-radius: var(--radius-md);
|
||||||
background: #f8fafc;
|
background: #f8fafb;
|
||||||
border: 1px solid #e1e8ee;
|
border: 1px solid #dbe4eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-node button {
|
.tree-node button {
|
||||||
@@ -471,9 +476,9 @@
|
|||||||
|
|
||||||
.evidence {
|
.evidence {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
border-radius: 16px;
|
border-radius: var(--radius-md);
|
||||||
background: linear-gradient(180deg, #f6f9fd 0%, #edf3f8 100%);
|
background: #f5f8fb;
|
||||||
border: 1px solid #dbe5ef;
|
border: 1px solid #d6e1ea;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
color: #2f4358;
|
color: #2f4358;
|
||||||
}
|
}
|
||||||
@@ -485,7 +490,7 @@
|
|||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
border-radius: 16px;
|
border-radius: var(--radius-md);
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.65;
|
line-height: 1.65;
|
||||||
@@ -515,10 +520,9 @@
|
|||||||
right: -720px;
|
right: -720px;
|
||||||
width: min(720px, 100vw);
|
width: min(720px, 100vw);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: rgba(248, 251, 253, 0.97);
|
background: #f7fafc;
|
||||||
backdrop-filter: blur(18px);
|
box-shadow: -16px 0 24px rgba(14, 29, 43, 0.12);
|
||||||
box-shadow: -24px 0 40px rgba(14, 29, 43, 0.2);
|
border-left: 1px solid var(--line);
|
||||||
border-left: 1px solid rgba(255, 255, 255, 0.7);
|
|
||||||
transition: right 0.28s ease;
|
transition: right 0.28s ease;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -557,7 +561,7 @@
|
|||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: white;
|
background: white;
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line-strong);
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@@ -584,11 +588,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message-card {
|
.message-card {
|
||||||
border-radius: 22px;
|
border-radius: var(--radius-lg);
|
||||||
background: linear-gradient(180deg, #ffffff 0%, #f7fafc 100%);
|
background: #ffffff;
|
||||||
border: 1px solid #dce5ec;
|
border: 1px solid #d6e0e7;
|
||||||
padding: 20px;
|
padding: 18px;
|
||||||
box-shadow: 0 16px 28px rgba(24, 40, 54, 0.1);
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-card .card-head {
|
.message-card .card-head {
|
||||||
@@ -615,9 +619,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 16px;
|
border-radius: var(--radius-md);
|
||||||
background: #f6fafc;
|
background: #f7fafc;
|
||||||
border: 1px dashed #bad0df;
|
border: 1px solid #cfdae3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-grid {
|
.copy-grid {
|
||||||
@@ -626,6 +630,170 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workspace-main {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.5fr 0.95fr;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-shell {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-chip {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background: #f3f6f9;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
color: var(--navy-strong);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-board {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
background: #ffffff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.user {
|
||||||
|
border-color: #cdd9e2;
|
||||||
|
background: #f7fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.agent {
|
||||||
|
border-color: #cfdae3;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.tool {
|
||||||
|
border-color: #d7dfe6;
|
||||||
|
background: #fbfcfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.system {
|
||||||
|
border-color: #d9e1e8;
|
||||||
|
background: #f6f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-head {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-bottom: 1px solid #e6edf2;
|
||||||
|
background: #f7fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.user .message-head {
|
||||||
|
background: #eef4f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.agent .message-head {
|
||||||
|
background: #f5f8fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-body {
|
||||||
|
padding: 14px;
|
||||||
|
line-height: 1.75;
|
||||||
|
color: #314659;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-body p {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-body p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-item {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border: 1px solid #dbe4eb;
|
||||||
|
background: #f8fafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-item strong {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-btn {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border: 1px solid var(--line-strong);
|
||||||
|
background: #ffffff;
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-btn.primary {
|
||||||
|
background: #173754;
|
||||||
|
border-color: #173754;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-agent-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.35fr 0.95fr;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-agent-side {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-mini-panel {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-q-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-q-item {
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background: #f8fafb;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #314659;
|
||||||
|
}
|
||||||
|
|
||||||
.list-inline {
|
.list-inline {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -672,7 +840,9 @@
|
|||||||
.two-col,
|
.two-col,
|
||||||
.tri-col,
|
.tri-col,
|
||||||
.split,
|
.split,
|
||||||
.subsplit {
|
.subsplit,
|
||||||
|
.workspace-main,
|
||||||
|
.page-agent-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,6 +1051,121 @@
|
|||||||
receipt: { id: "om_demo_message_20260603_103000", time: "2026-06-03 10:30:00" },
|
receipt: { id: "om_demo_message_20260603_103000", time: "2026-06-03 10:30:00" },
|
||||||
webLink: "http://localhost:8000/audit/1001/",
|
webLink: "http://localhost:8000/audit/1001/",
|
||||||
},
|
},
|
||||||
|
agent: {
|
||||||
|
quickPrompts: [
|
||||||
|
"检查当前资料完整性",
|
||||||
|
"抽取本批次核心字段",
|
||||||
|
"解释产品名称冲突原因",
|
||||||
|
"生成整改建议和责任人分发"
|
||||||
|
],
|
||||||
|
workspaceConversation: [
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
title: "用户指令",
|
||||||
|
meta: "10:05 · 审核任务工作台",
|
||||||
|
body: [
|
||||||
|
"请基于当前批次资料,按注册申报流程完成完整性检查、字段抽取、一致性核查,并给出风险结论。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "agent",
|
||||||
|
title: "Agent 计划",
|
||||||
|
meta: "10:05 · orchestration",
|
||||||
|
body: [
|
||||||
|
"我将按 5 个阶段执行:读取资料包目录 -> 加载法规规则包 -> 抽取统一字段池 -> 执行强一致比对 -> 汇总风险并判断是否允许导出。",
|
||||||
|
"当前建议优先关注 CH1 监管信息和说明书相关字段。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "tool",
|
||||||
|
title: "工具调用记录",
|
||||||
|
meta: "10:06 · tools",
|
||||||
|
body: [
|
||||||
|
"已调用 `scan_submission_package`、`check_nmpa_completeness`、`extract_product_fields`、`compare_field_consistency`、`build_risk_alerts`。",
|
||||||
|
"RAG 命中来源包括《体外诊断试剂注册申报资料要求及说明》与目标产品说明书切片。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
title: "结构化结论",
|
||||||
|
meta: "10:09 · result",
|
||||||
|
body: [
|
||||||
|
"完整性检查:发现 1 个缺失项、1 个错放项。",
|
||||||
|
"字段抽取:13 个目标字段中 12 个已抽取,1 个待复核。",
|
||||||
|
"一致性核查:产品名称存在冲突,疑似混档。",
|
||||||
|
"综合风险:高风险,不允许正式导出,仅允许生成草稿。"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
workspaceTrace: [
|
||||||
|
{ label: "当前任务", value: "注册申报审核闭环执行" },
|
||||||
|
{ label: "命中规则", value: "nmpa_ivd_registration_v1 / ivd_strict_consistency_v1" },
|
||||||
|
{ label: "工具链路", value: "资料扫描 -> 完整性检查 -> 字段抽取 -> 一致性 -> 风险汇总" },
|
||||||
|
{ label: "人工复核点", value: "储存条件字段 / 产品名称冲突 / CH1 缺失项确认" }
|
||||||
|
],
|
||||||
|
pagePanels: {
|
||||||
|
completeness: {
|
||||||
|
question: "为什么 CH1.11.4 会被判定为缺失?",
|
||||||
|
answer: "Agent 先读取目录汇总结果,再将 CH1 章节与法规规则包逐项匹配。规则要求 CH1.11.4 属于必交声明类资料,但当前资料包未识别到有效命中文档,因此判定为缺失。RAG 证据仅用于引用法规原文,不改变规则结论。",
|
||||||
|
trace: [
|
||||||
|
"规则命中:CH1.11.4 -> 必交项 -> 默认高风险",
|
||||||
|
"证据来源:法规要求说明 / CH1 监管信息章节",
|
||||||
|
"建议动作:补充资料后重跑完整性检查"
|
||||||
|
],
|
||||||
|
actions: ["确认缺失项", "标记疑似命中", "发起补件通知"]
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
question: "储存条件为什么是待复核,而不是直接回填?",
|
||||||
|
answer: "该字段来自申请表表格抽取,原文字段表述较模糊,和说明书标准口径未形成稳定一对一映射。Agent 将其保留在字段池中,但置信度标记为低,并要求人工确认后才能进入正式导出。",
|
||||||
|
trace: [
|
||||||
|
"抽取方式:表格抽取 + 标准化",
|
||||||
|
"字段状态:manual_review_required = true",
|
||||||
|
"影响范围:正式导出时触发阻断"
|
||||||
|
],
|
||||||
|
actions: ["采用推荐值", "驳回推荐值", "重新抽取"]
|
||||||
|
},
|
||||||
|
consistency: {
|
||||||
|
question: "产品名称冲突为什么会被上升为混档风险?",
|
||||||
|
answer: "因为当前审核范围内的说明书与申请表属于同一批次业务资料,而强一致规则要求产品名称必须完全一致。两份文档标准化后仍不一致,因此 Agent 将其识别为字段冲突,并进一步提示疑似跨产品资料混入。",
|
||||||
|
trace: [
|
||||||
|
"强一致字段:product_name",
|
||||||
|
"来源文档:目标产品说明书 / CH1.4 申请表",
|
||||||
|
"处理建议:先确认审核范围,再继续导出"
|
||||||
|
],
|
||||||
|
actions: ["确认混档风险", "排除文档后重跑", "采用说明书版本"]
|
||||||
|
},
|
||||||
|
risk: {
|
||||||
|
question: "为什么最终是不通过,而不是待复核?",
|
||||||
|
answer: "风险规则中配置了 high_risk_policy = fail。当前批次同时存在缺失必交资料和产品名称冲突两个高风险项,因此 Agent 直接给出不通过结论,而不是仅提示待复核。",
|
||||||
|
trace: [
|
||||||
|
"风险规则:ivd_registration_risk_v1",
|
||||||
|
"高风险项:缺失必交资料 / 产品名称冲突",
|
||||||
|
"下游影响:正式导出阻断 / 飞书通知责任人"
|
||||||
|
],
|
||||||
|
actions: ["确认风险结论", "生成整改任务", "推送飞书通知"]
|
||||||
|
},
|
||||||
|
word: {
|
||||||
|
question: "为什么只能生成草稿版,不能正式导出?",
|
||||||
|
answer: "Word 导出步骤会读取一致性核查和风险预警结果。当前批次存在高风险和待复核字段,因此回填拦截检查命中正式导出阻断条件,Agent 只允许生成带审阅用途的草稿版。",
|
||||||
|
trace: [
|
||||||
|
"模板:registration_application_form_v1",
|
||||||
|
"阻断原因:高风险 + 冲突字段 + 待复核字段",
|
||||||
|
"导出策略:allow_draft_when_blocked = true"
|
||||||
|
],
|
||||||
|
actions: ["生成草稿", "查看阻断详情", "整改后重试"]
|
||||||
|
},
|
||||||
|
notification: {
|
||||||
|
question: "飞书通知里为什么要同时 @ 两个责任人?",
|
||||||
|
answer: "因为责任人映射同时命中了章节缺失和风险类型冲突两类规则。CH1 缺失项对应注册申报负责人,产品名称冲突对应注册资料负责人,所以 Agent 在同一张消息卡片中同时 @ 两位责任人,并附上 Web 详情入口。",
|
||||||
|
trace: [
|
||||||
|
"责任人映射:CH1 -> 注册资料负责人",
|
||||||
|
"风险映射:missing_required_document -> 注册申报负责人",
|
||||||
|
"通知载荷:interactive_card + Web detail URL"
|
||||||
|
],
|
||||||
|
actions: ["发送通知", "切换消息模板", "查看回执日志"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
governance: [
|
governance: [
|
||||||
{
|
{
|
||||||
id: "rules",
|
id: "rules",
|
||||||
@@ -1005,6 +1290,89 @@
|
|||||||
`).join("")}</div>`;
|
`).join("")}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderAgentConversation(messages) {
|
||||||
|
return `
|
||||||
|
<div class="conversation-board">
|
||||||
|
${messages.map(message => `
|
||||||
|
<div class="message ${message.role}">
|
||||||
|
<div class="message-head">
|
||||||
|
<strong>${message.title}</strong>
|
||||||
|
<span class="tag">${message.meta}</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
${message.body.map(line => `<p>${line}</p>`).join("")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join("")}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTraceItems(items) {
|
||||||
|
return `
|
||||||
|
<div class="trace-grid">
|
||||||
|
${items.map(item => `
|
||||||
|
<div class="trace-item">
|
||||||
|
<strong>${item.label || item}</strong>
|
||||||
|
${item.value ? `<div class="muted" style="color:#5f7285;">${item.value}</div>` : ""}
|
||||||
|
</div>
|
||||||
|
`).join("")}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAgentSidePanel(key, title) {
|
||||||
|
const panel = data.agent.pagePanels[key];
|
||||||
|
if (!panel) return "";
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="page-agent-side">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="section-title">
|
||||||
|
<div>
|
||||||
|
<h3>Agent 页面追问</h3>
|
||||||
|
<p>${title}中的解释型对话与证据追溯。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="agent-mini-panel">
|
||||||
|
<div class="message user">
|
||||||
|
<div class="message-head">
|
||||||
|
<strong>追问</strong>
|
||||||
|
<span class="tag">用户</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
<p>${panel.question}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="message agent">
|
||||||
|
<div class="message-head">
|
||||||
|
<strong>Agent 解释</strong>
|
||||||
|
<span class="tag">当前页面上下文</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
<p>${panel.answer}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel">
|
||||||
|
<div class="section-title">
|
||||||
|
<div>
|
||||||
|
<h3>执行轨迹</h3>
|
||||||
|
<p>说明这个结论是怎么来的。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="agent-q-list">
|
||||||
|
${panel.trace.map(item => `<div class="agent-q-item">${item}</div>`).join("")}
|
||||||
|
</div>
|
||||||
|
<div class="review-actions">
|
||||||
|
${panel.actions.map((action, index) => `<button class="review-btn ${index === 0 ? "primary" : ""}">${action}</button>`).join("")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
function renderWorkspacePage() {
|
function renderWorkspacePage() {
|
||||||
return `
|
return `
|
||||||
<section class="page active" data-page="workspace">
|
<section class="page active" data-page="workspace">
|
||||||
@@ -1106,6 +1474,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="workspace-main">
|
||||||
|
<div class="agent-shell">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="section-title">
|
||||||
|
<div>
|
||||||
|
<h3>Agent 主对话区</h3>
|
||||||
|
<p>体现用户指令、Agent 计划、工具调用和结构化结论的多轮协作过程。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="prompt-bar">
|
||||||
|
${data.agent.quickPrompts.map(prompt => `<span class="prompt-chip">${prompt}</span>`).join("")}
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:12px;">
|
||||||
|
${renderAgentConversation(data.agent.workspaceConversation)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="page-agent-side">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="section-title">
|
||||||
|
<div>
|
||||||
|
<h3>Agent 执行轨迹</h3>
|
||||||
|
<p>把这次审核从“聊天”升级为“可追踪执行”。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderTraceItems(data.agent.workspaceTrace)}
|
||||||
|
</div>
|
||||||
|
<div class="panel">
|
||||||
|
<div class="section-title">
|
||||||
|
<div>
|
||||||
|
<h3>人工复核协同</h3>
|
||||||
|
<p>支持人机共审,而不是单向回答。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="review-actions">
|
||||||
|
<button class="review-btn primary">确认当前结论</button>
|
||||||
|
<button class="review-btn">采用说明书值</button>
|
||||||
|
<button class="review-btn">重新执行一致性核查</button>
|
||||||
|
<button class="review-btn">生成整改任务</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1243,6 +1654,8 @@
|
|||||||
return `
|
return `
|
||||||
<section class="page" data-page="completeness">
|
<section class="page" data-page="completeness">
|
||||||
${metricCards(data.completeness.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
${metricCards(data.completeness.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1334,6 +1747,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("completeness", "法规完整性检查")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1342,6 +1758,8 @@
|
|||||||
return `
|
return `
|
||||||
<section class="page" data-page="fields">
|
<section class="page" data-page="fields">
|
||||||
${metricCards(data.fields.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
${metricCards(data.fields.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
<div>
|
<div>
|
||||||
@@ -1409,6 +1827,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("fields", "字段抽取与字段池")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1417,6 +1838,8 @@
|
|||||||
return `
|
return `
|
||||||
<section class="page" data-page="consistency">
|
<section class="page" data-page="consistency">
|
||||||
${metricCards(data.consistency.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
${metricCards(data.consistency.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="two-col">
|
<div class="two-col">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1479,6 +1902,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="alert danger">说明书与申请表中的产品名称存在文本不一致,系统判定为疑似跨产品资料混入,建议先确认当前审核范围再继续回填和导出。</div>
|
<div class="alert danger">说明书与申请表中的产品名称存在文本不一致,系统判定为疑似跨产品资料混入,建议先确认当前审核范围再继续回填和导出。</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("consistency", "一致性核查")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1487,6 +1913,8 @@
|
|||||||
return `
|
return `
|
||||||
<section class="page" data-page="risk">
|
<section class="page" data-page="risk">
|
||||||
${metricCards(data.risk.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
${metricCards(data.risk.summary.map(item => ({ label: item.label, value: item.value, note: "" })))}
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="hero">
|
<div class="hero">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1549,6 +1977,9 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("risk", "风险预警")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1562,6 +1993,8 @@
|
|||||||
{ label: "阻断项", value: "3", note: "高风险 / 冲突 / 待复核" },
|
{ label: "阻断项", value: "3", note: "高风险 / 冲突 / 待复核" },
|
||||||
{ label: "导出状态", value: "草稿已生成", note: "正式版被阻断" },
|
{ label: "导出状态", value: "草稿已生成", note: "正式版被阻断" },
|
||||||
])}
|
])}
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1632,6 +2065,9 @@
|
|||||||
<button class="primary-btn">下载草稿</button>
|
<button class="primary-btn">下载草稿</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("word", "Word 回填导出")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -1639,6 +2075,8 @@
|
|||||||
function renderNotificationPage() {
|
function renderNotificationPage() {
|
||||||
return `
|
return `
|
||||||
<section class="page" data-page="notification">
|
<section class="page" data-page="notification">
|
||||||
|
<div class="page-agent-grid">
|
||||||
|
<div>
|
||||||
<div class="split">
|
<div class="split">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1695,6 +2133,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
${renderAgentSidePanel("notification", "飞书通知视图")}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user