Compare commits
No commits in common. "e27e6392e00f5dc2e8d813a60d285df7b0324f5c" and "d65e592956ff9bef529bdf1feb3eb28aa57bf128" have entirely different histories.
e27e6392e0
...
d65e592956
@ -7,115 +7,70 @@
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
<title>RPA工作站 · 高保真交互原型</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary:#ff5000; --rpa-primary:#ff5000; --rpa-primary-hover:#e64500; --rpa-primary-soft:#fff3e8;
|
||||
--rpa-tech-blue:#ff8a00; --rpa-tech-blue-hover:#ff9d2e; --rpa-nav-bg:#373942; --rpa-nav-panel:#2b2d34;
|
||||
--rpa-nav-border:#383a45; --rpa-hosting-bg:#0a091e; --rpa-bg:#f7f8fa; --rpa-surface:#ffffff;
|
||||
--rpa-surface-subtle:#f3f4f6; --rpa-border:#e6e6e6; --rpa-border-strong:#cbd5e1; --rpa-text:#333333;
|
||||
--rpa-heading:#1f2937; --rpa-muted:#666666; --rpa-subtle:#7c7c7c; --rpa-inverse:#e5e9ee;
|
||||
--rpa-inverse-muted:#a3a3a3; --rpa-success:#4ab933; --rpa-success-bg:#edffe9; --rpa-success-border:#dcf9d6;
|
||||
--rpa-info:#28a3ef; --rpa-info-bg:#eef8ff; --rpa-warning:#f59e0b; --rpa-warning-bg:#fffbeb;
|
||||
--rpa-danger:#d44044; --rpa-danger-bg:#fff2f2; --rpa-danger-border:#ffe3e0;
|
||||
--rpa-shadow-card:0 1px 2px rgba(15,23,42,.06); --rpa-shadow-float:0 8px 24px rgba(15,23,42,.14);
|
||||
--rpa-shadow-blocking:0 24px 60px rgba(0,0,0,.35); --rpa-font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;
|
||||
}
|
||||
:root { --primary:#4f46e5; }
|
||||
* { box-sizing: border-box; }
|
||||
body { overflow: hidden; color: var(--rpa-text); }
|
||||
body { overflow: hidden; }
|
||||
.scrollbar-thin::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||
.scrollbar-thin::-webkit-scrollbar-thumb { background: var(--rpa-border-strong); border-radius: 999px; }
|
||||
.focus-ring:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--rpa-primary); }
|
||||
.rpa-card { border:1px solid var(--rpa-border); background:var(--rpa-surface); border-radius:1rem; box-shadow:var(--rpa-shadow-card); }
|
||||
.rpa-panel { border:1px solid var(--rpa-border); background:var(--rpa-surface); border-radius:1rem; box-shadow:var(--rpa-shadow-card); }
|
||||
.rpa-table { overflow:hidden; border:1px solid var(--rpa-border); background:var(--rpa-surface); border-radius:1rem; box-shadow:var(--rpa-shadow-card); }
|
||||
.rpa-table thead { background:var(--rpa-surface-subtle); color:var(--rpa-muted); }
|
||||
.rpa-table tbody { color:var(--rpa-text); }
|
||||
.rpa-table tbody tr { border-top:1px solid var(--rpa-border); }
|
||||
.rpa-table tbody tr:hover { background:#f8fafc; }
|
||||
.rpa-scrim { background:rgba(10,9,30,.55); }
|
||||
.rpa-hosting-scrim { background:rgba(10,9,30,.85); }
|
||||
.rpa-primary-btn { background:var(--rpa-primary); color:#fff; box-shadow:0 8px 20px rgba(255,80,0,.22); }
|
||||
.rpa-primary-btn:hover { background:var(--rpa-primary-hover); }
|
||||
.rpa-secondary-btn { border:1px solid var(--rpa-border); background:var(--rpa-surface); color:var(--rpa-text); }
|
||||
.rpa-secondary-btn:hover { background:var(--rpa-surface-subtle); }
|
||||
.rpa-danger-btn { background:var(--rpa-danger); color:#fff; box-shadow:0 8px 20px rgba(212,64,68,.22); }
|
||||
.rpa-danger-btn:hover { filter:brightness(.95); }
|
||||
.rpa-link-btn { color:var(--rpa-primary); }
|
||||
.rpa-link-btn:hover { color:var(--rpa-primary-hover); }
|
||||
.rpa-chip { display:inline-flex; align-items:center; gap:.375rem; border-radius:999px; padding:.25rem .625rem; font-size:.75rem; line-height:1rem; font-weight:500; border:1px solid transparent; }
|
||||
.rpa-chip-primary { background:var(--rpa-primary-soft); color:var(--rpa-primary-hover); border-color:#ffd8bf; }
|
||||
.rpa-chip-success { background:var(--rpa-success-bg); color:#2f8a20; border-color:var(--rpa-success-border); }
|
||||
.rpa-chip-info { background:var(--rpa-info-bg); color:#0f7fbd; border-color:#d6efff; }
|
||||
.rpa-chip-warning { background:var(--rpa-warning-bg); color:#b45309; border-color:#fde68a; }
|
||||
.rpa-chip-danger { background:var(--rpa-danger-bg); color:var(--rpa-danger); border-color:var(--rpa-danger-border); }
|
||||
.rpa-chip-neutral { background:var(--rpa-surface-subtle); color:var(--rpa-muted); border-color:var(--rpa-border); }
|
||||
.rpa-nav-item { color:var(--rpa-inverse-muted); }
|
||||
.rpa-nav-item:hover { background:rgba(255,255,255,.08); color:var(--rpa-inverse); }
|
||||
.rpa-nav-item:hover i { color:var(--rpa-tech-blue); }
|
||||
.rpa-nav-item-active { background:var(--rpa-primary); color:#fff; box-shadow:0 8px 20px rgba(255,80,0,.25); }
|
||||
.rpa-nav-item-active i { color:#fff; }
|
||||
.rpa-nav-status { background:var(--rpa-nav-panel); border:1px solid var(--rpa-nav-border); color:var(--rpa-inverse-muted); }
|
||||
.rpa-code { font-family:var(--rpa-font-mono); background:var(--rpa-surface-subtle); color:var(--rpa-heading); border:1px solid var(--rpa-border); border-radius:.75rem; }
|
||||
.rpa-progress { background:linear-gradient(90deg, var(--rpa-primary), var(--rpa-tech-blue)); }
|
||||
.rpa-control, [data-app-root] input, [data-app-root] select, [data-app-root] textarea { border-color:var(--rpa-border-strong); }
|
||||
[data-app-root] input:focus-visible, [data-app-root] select:focus-visible, [data-app-root] textarea:focus-visible { outline:none; box-shadow:0 0 0 2px var(--rpa-primary); }
|
||||
.scrollbar-thin::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 999px; }
|
||||
.focus-ring:focus-visible { outline: none; box-shadow: 0 0 0 2px #6366f1; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen p-6" style="background:linear-gradient(180deg, #fff3e8 0%, #f7f8fa 45%, #ffffff 100%); color:var(--rpa-text);">
|
||||
<body class="min-h-screen bg-gradient-to-b from-indigo-50 to-slate-100 p-6 text-slate-950">
|
||||
<main class="mx-auto flex h-[calc(100vh-48px)] max-w-[1240px] flex-col items-center gap-4 overflow-hidden">
|
||||
<header class="flex w-[1180px] shrink-0 items-center justify-between gap-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="grid h-10 w-10 place-items-center rounded-2xl text-white shadow-lg" style="background:var(--rpa-primary); box-shadow:0 10px 24px rgba(255,80,0,.25)">
|
||||
<div class="grid h-10 w-10 place-items-center rounded-2xl bg-[var(--primary)] text-white shadow-lg shadow-indigo-500/25">
|
||||
<i data-lucide="workflow" class="h-5 w-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="m-0 text-xl font-semibold" style="color:var(--rpa-heading)">RPA工作站 原型</h1>
|
||||
<p class="m-0 text-sm" style="color:var(--rpa-muted)">本地优先 AI + RPA 视觉标注与托管执行平台</p>
|
||||
<h1 class="m-0 text-xl font-semibold text-slate-950">RPA工作站 原型</h1>
|
||||
<p class="m-0 text-sm text-slate-600">本地优先 AI + RPA 视觉标注与托管执行平台</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex rounded-full border bg-white p-1 shadow-sm" style="border-color:var(--rpa-border)" aria-label="端切换">
|
||||
<button type="button" data-platform-tab="windows" class="focus-ring h-10 rounded-full px-5 text-sm font-medium text-white" style="background:var(--rpa-primary)">Windows 端</button>
|
||||
<button type="button" data-platform-tab="mac" class="focus-ring h-10 rounded-full px-5 text-sm font-medium" style="color:var(--rpa-muted)">Mac 端</button>
|
||||
<div class="flex rounded-full border border-slate-200 bg-white p-1 shadow-sm" aria-label="端切换">
|
||||
<button type="button" data-platform-tab="windows" class="focus-ring h-10 rounded-full bg-[var(--primary)] px-5 text-sm font-medium text-white">Windows 端</button>
|
||||
<button type="button" data-platform-tab="mac" class="focus-ring h-10 rounded-full px-5 text-sm font-medium text-slate-600">Mac 端</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="min-h-0 shrink-0" data-platform-panel="windows">
|
||||
<div class="flex h-[760px] w-[1180px] flex-col overflow-hidden border border-slate-300 bg-white shadow-2xl">
|
||||
<div class="flex h-10 shrink-0 items-center border-b border-slate-200 bg-white pl-3">
|
||||
<div class="flex flex-1 items-center gap-2 text-sm font-medium text-[var(--rpa-text)]">
|
||||
<span class="grid h-5 w-5 place-items-center rounded bg-[var(--rpa-primary)] text-white"><i data-lucide="workflow" class="h-3.5 w-3.5"></i></span>
|
||||
<div class="flex flex-1 items-center gap-2 text-sm font-medium text-slate-700">
|
||||
<span class="grid h-5 w-5 place-items-center rounded bg-[var(--primary)] text-white"><i data-lucide="workflow" class="h-3.5 w-3.5"></i></span>
|
||||
<span>RPA工作站</span>
|
||||
</div>
|
||||
<button class="grid h-10 w-12 place-items-center hover:text-[var(--rpa-tech-blue)]" aria-label="最小化">—</button>
|
||||
<button class="grid h-10 w-12 place-items-center hover:text-[var(--rpa-tech-blue)]" aria-label="最大化">□</button>
|
||||
<button class="grid h-10 w-12 place-items-center text-[var(--rpa-muted)] hover:bg-red-500 hover:text-white" aria-label="关闭">×</button>
|
||||
<button class="grid h-10 w-12 place-items-center text-slate-600 hover:bg-slate-100" aria-label="最小化">—</button>
|
||||
<button class="grid h-10 w-12 place-items-center text-slate-600 hover:bg-slate-100" aria-label="最大化">□</button>
|
||||
<button class="grid h-10 w-12 place-items-center text-slate-600 hover:bg-red-500 hover:text-white" aria-label="关闭">×</button>
|
||||
</div>
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden" style="background:var(--rpa-bg)" data-app-root data-platform="windows"></div>
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden bg-slate-50" data-app-root data-platform="windows"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="hidden min-h-0 shrink-0" data-platform-panel="mac">
|
||||
<div class="flex h-[760px] w-[1180px] flex-col overflow-hidden rounded-[1.75rem] bg-white shadow-2xl shadow-slate-900/20 ring-1 ring-slate-200">
|
||||
<div class="flex h-11 shrink-0 items-center border-b border-slate-200 px-4" style="background:var(--rpa-bg)">
|
||||
<div class="flex h-11 shrink-0 items-center border-b border-slate-200 bg-slate-50/95 px-4">
|
||||
<div class="flex gap-2">
|
||||
<span class="h-3 w-3 rounded-full bg-red-500"></span>
|
||||
<span class="h-3 w-3 rounded-full bg-yellow-400"></span>
|
||||
<span class="h-3 w-3 rounded-full bg-green-500"></span>
|
||||
</div>
|
||||
<div class="flex-1 text-center text-sm font-medium text-[var(--rpa-muted)]">RPA工作站</div>
|
||||
<div class="flex-1 text-center text-sm font-medium text-slate-600">RPA工作站</div>
|
||||
<div class="w-16"></div>
|
||||
</div>
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden" style="background:var(--rpa-bg)" data-app-root data-platform="mac"></div>
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden bg-slate-50" data-app-root data-platform="mac"></div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<div class="hidden" aria-hidden="true" data-page="工作台" data-page-secondary="自动化任务">PRD coverage marker: 名称、类型、索引状态、引用次数、更新时间、权限模式;时间、员工、应用、知识库、任务状态。</div>
|
||||
|
||||
<template id="app-template">
|
||||
<div class="flex h-full overflow-hidden" style="background:var(--rpa-bg); color:var(--rpa-text);">
|
||||
<aside class="flex w-[92px] shrink-0 flex-col items-center gap-2 border-r p-3" style="background:var(--rpa-nav-bg); border-color:var(--rpa-nav-border); color:var(--rpa-inverse-muted);" data-nav></aside>
|
||||
<div class="flex h-full overflow-hidden bg-slate-50 text-slate-950">
|
||||
<aside class="flex w-[92px] shrink-0 flex-col items-center gap-2 border-r border-slate-200 bg-slate-950 p-3 text-slate-300" data-nav></aside>
|
||||
<section class="relative flex min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<header class="flex h-20 shrink-0 items-center justify-between border-b px-6" style="border-color:var(--rpa-border); background:var(--rpa-surface);" data-header></header>
|
||||
<main class="min-h-0 flex-1 overflow-y-auto p-6 scrollbar-thin" style="background:var(--rpa-bg);" data-content></main>
|
||||
<header class="flex h-20 shrink-0 items-center justify-between border-b border-slate-200 bg-white px-6" data-header></header>
|
||||
<main class="min-h-0 flex-1 overflow-y-auto p-6 scrollbar-thin" data-content></main>
|
||||
<div class="pointer-events-none absolute right-5 top-24 z-50 space-y-2" data-toasts></div>
|
||||
<div class="absolute inset-0 z-40 hidden" data-overlay-layer></div>
|
||||
</section>
|
||||
@ -164,8 +119,8 @@ const prototypeState = {
|
||||
};
|
||||
|
||||
function clsBadge(kind){
|
||||
const map = {ready:'rpa-chip rpa-chip-success', succeeded:'rpa-chip rpa-chip-success', indexing:'rpa-chip rpa-chip-warning', waiting_user:'rpa-chip rpa-chip-warning', pending:'rpa-chip rpa-chip-info', queued:'rpa-chip rpa-chip-info', failed:'rpa-chip rpa-chip-danger', running:'rpa-chip rpa-chip-primary', idle:'rpa-chip rpa-chip-neutral', canceled:'rpa-chip rpa-chip-neutral'};
|
||||
return map[kind] || map.idle;
|
||||
const map = {ready:'bg-emerald-50 text-emerald-700 ring-emerald-200', indexing:'bg-amber-50 text-amber-700 ring-amber-200', pending:'bg-blue-50 text-blue-700 ring-blue-200', failed:'bg-red-50 text-red-700 ring-red-200', running:'bg-indigo-50 text-indigo-700 ring-indigo-200', idle:'bg-slate-100 text-slate-700 ring-slate-200', waiting_user:'bg-orange-50 text-orange-700 ring-orange-200', succeeded:'bg-emerald-50 text-emerald-700 ring-emerald-200', canceled:'bg-slate-100 text-slate-700 ring-slate-200', queued:'bg-blue-50 text-blue-700 ring-blue-200'};
|
||||
return 'inline-flex items-center rounded-full px-2.5 py-1 text-xs font-medium ring-1 ' + (map[kind] || map.idle);
|
||||
}
|
||||
function icon(name, c='h-4 w-4'){ return `<i data-lucide="${name}" class="${c}"></i>`; }
|
||||
function toast(text, type='success'){ prototypeState.toast.push({text,type,id:Date.now()}); setTimeout(()=>{ prototypeState.toast.shift(); renderAll(); }, 2400); renderAll(); }
|
||||
@ -178,17 +133,16 @@ function init(){
|
||||
function renderRoot(root){
|
||||
root.dataset.appRoot = '';
|
||||
const nav = root.querySelector('[data-nav]');
|
||||
const hosting = prototypeState.rpaHosting;
|
||||
nav.innerHTML = `<div class="flex h-full w-full flex-col"><div class="flex flex-1 flex-col items-center gap-2">${pages.map(([p,ic]) => { const active = prototypeState.page===p; return `<button type="button" data-page="${p}" aria-label="${p}" aria-current="${active?'page':'false'}" class="focus-ring group flex min-h-[56px] w-full flex-col items-center justify-center gap-1 rounded-2xl text-[11px] transition ${active?'rpa-nav-item-active':'rpa-nav-item'}"><span>${icon(ic,'h-5 w-5')}</span><span>${p}</span></button>`; }).join('')}</div><div class="rpa-nav-status mt-2 flex w-full flex-col items-center rounded-2xl px-2 py-2 text-[10px] leading-4"><span class="mb-1" style="color:${hosting?'var(--rpa-warning)':'var(--rpa-success)'}">${icon('circle-dot','h-3.5 w-3.5')}</span><span>${hosting?'托管中':'本地在线'}</span></div></div>`;
|
||||
nav.innerHTML = `<div class="flex h-full w-full flex-col"><div class="flex flex-1 flex-col items-center gap-2">${pages.map(([p,ic]) => { const active = prototypeState.page===p; return `<button type="button" data-page="${p}" aria-label="${p}" aria-current="${active?'page':'false'}" class="focus-ring group flex min-h-[56px] w-full flex-col items-center justify-center gap-1 rounded-2xl text-[11px] transition ${active?'bg-indigo-500 text-white shadow-lg shadow-indigo-500/25':'text-slate-400 hover:bg-white/10 hover:text-indigo-100'}"><span class="${active?'text-white':'text-slate-400 group-hover:text-indigo-200'}">${icon(ic,'h-5 w-5')}</span><span>${p}</span></button>`; }).join('')}</div><div class="mt-2 flex w-full flex-col items-center rounded-2xl bg-slate-900/90 px-2 py-2 text-[10px] leading-4 text-slate-400 ring-1 ring-white/5"><span class="mb-1 text-emerald-400">${icon('circle-dot','h-3.5 w-3.5')}</span><span>本地在线</span></div></div>`;
|
||||
const header = root.querySelector('[data-header]');
|
||||
header.innerHTML = `<div><h2 class="text-xl font-semibold" style="color:var(--rpa-heading)">${prototypeState.page}</h2><p class="mt-1 text-sm" style="color:var(--rpa-muted)">${pageSummaries[prototypeState.page]}</p></div><div class="flex flex-wrap justify-end gap-2">${chip('模型 在线','activity','emerald')}${chip(prototypeState.rpaHosting?'RPA 托管中':'RPA 空闲','radio','indigo')}${chip('本地模式','hard-drive','slate')}${chip('试用 14天','badge-check','amber')}</div>`;
|
||||
header.innerHTML = `<div><h2 class="text-xl font-semibold">${prototypeState.page}</h2><p class="mt-1 text-sm text-slate-500">${pageSummaries[prototypeState.page]}</p></div><div class="flex flex-wrap justify-end gap-2">${chip('模型 在线','activity','emerald')}${chip(prototypeState.rpaHosting?'RPA 托管中':'RPA 空闲','radio','indigo')}${chip('本地模式','hard-drive','slate')}${chip('试用 14天','badge-check','amber')}</div>`;
|
||||
root.querySelector('[data-content]').innerHTML = renderPage();
|
||||
root.querySelector('[data-toasts]').innerHTML = prototypeState.toast.map(t => `<div class="pointer-events-auto flex min-w-[280px] items-start gap-2 rounded-xl border px-4 py-3 text-sm shadow-xl" style="background:${t.type==='error'?'var(--rpa-danger-bg)':'var(--rpa-success-bg)'}; border-color:${t.type==='error'?'var(--rpa-danger-border)':'var(--rpa-success-border)'}; color:${t.type==='error'?'var(--rpa-danger)':'var(--rpa-text)'}">${icon(t.type==='error'?'circle-alert':'circle-check','mt-0.5 h-4 w-4 shrink-0')}<span>${t.text}</span></div>`).join('');
|
||||
root.querySelector('[data-toasts]').innerHTML = prototypeState.toast.map(t => `<div class="pointer-events-auto flex min-w-[280px] items-start gap-2 rounded-xl border bg-white px-4 py-3 text-sm shadow-xl ${t.type==='error'?'border-red-200 text-red-700':'border-emerald-200 text-slate-700'}">${icon(t.type==='error'?'circle-alert':'circle-check','mt-0.5 h-4 w-4 shrink-0')}<span>${t.text}</span></div>`).join('');
|
||||
renderOverlay(root);
|
||||
}
|
||||
function chip(text, ic, tone){ const map={emerald:'rpa-chip-success', indigo:'rpa-chip-primary', slate:'rpa-chip-neutral', amber:'rpa-chip-warning'}; return `<span class="rpa-chip ${map[tone] || 'rpa-chip-neutral'}">${icon(ic)}${text}</span>`; }
|
||||
function card(title, body, footer=''){ return `<article class="rpa-card p-5"><h3 class="mb-4 flex items-center gap-2 font-semibold" style="color:var(--rpa-heading)"><span style="color:var(--rpa-primary)">${body.icon||''}</span>${title}</h3>${body.html||body}${footer}</article>`; }
|
||||
function actionBtn(label, attrs='', primary=false){ return `<button type="button" ${attrs} class="focus-ring inline-flex h-10 items-center justify-center gap-2 rounded-xl ${primary?'rpa-primary-btn':'rpa-secondary-btn'} px-4 text-sm font-medium">${label}</button>`; }
|
||||
function chip(text, ic, tone){ return `<span class="inline-flex h-8 items-center gap-1.5 rounded-full bg-${tone==='slate'?'slate':'white'}-${tone==='slate'?'100':'50'} px-3 text-xs font-medium text-${tone}-700 ring-1 ring-${tone}-200">${icon(ic)}${text}</span>`; }
|
||||
function card(title, body, footer=''){ return `<article class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><h3 class="mb-4 flex items-center gap-2 font-semibold text-slate-900">${body.icon||''}${title}</h3>${body.html||body}${footer}</article>`; }
|
||||
function actionBtn(label, attrs='', primary=false){ return `<button type="button" ${attrs} class="focus-ring inline-flex h-10 items-center justify-center gap-2 rounded-xl ${primary?'bg-[var(--primary)] text-white shadow-lg shadow-indigo-500/20':'border border-slate-200 bg-white text-slate-700 hover:bg-slate-50'} px-4 text-sm font-medium">${label}</button>`; }
|
||||
|
||||
function renderPage(){
|
||||
if (prototypeState.page==='工作台') return dashboardPage();
|
||||
@ -201,36 +155,36 @@ function renderPage(){
|
||||
function dashboardPage(){
|
||||
return `<div class="space-y-6">
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
${card('环境状态',{icon:icon('shield-check'),html:`<div class="space-y-3 text-sm"><div class="flex justify-between"><span>权限</span><b>3/4</b></div><div class="flex justify-between"><span>模型连通</span><span class="text-[var(--rpa-success)]">通过</span></div><div class="flex justify-between"><span>本地 GPU</span><span>中档</span></div><div class="flex justify-between"><span>存储</span><span class="text-[var(--rpa-success)]">可用</span></div>${actionBtn('查看首次配置','data-modal-open="config"')}</div>`})}
|
||||
${card('环境状态',{icon:icon('shield-check'),html:`<div class="space-y-3 text-sm"><div class="flex justify-between"><span>权限</span><b>3/4</b></div><div class="flex justify-between"><span>模型连通</span><span class="text-emerald-600">通过</span></div><div class="flex justify-between"><span>本地 GPU</span><span>中档</span></div><div class="flex justify-between"><span>存储</span><span class="text-emerald-600">可用</span></div>${actionBtn('查看首次配置','data-modal-open="config"')}</div>`})}
|
||||
${card('资产状态',{icon:icon('boxes'),html:`<div class="grid grid-cols-2 gap-3 text-sm"><b>知识库 3</b><b>就绪索引 2</b><b>AI 员工 2</b><b>标注应用 1</b></div>`})}
|
||||
${card('执行状态',{icon:icon('activity'),html:`<div class="space-y-3 text-sm"><div class="flex justify-between"><span>运行中</span><b>0</b></div><div class="flex justify-between"><span>失败任务</span><b class="text-[var(--rpa-danger)]">1</b></div><div class="flex justify-between"><span>最近托管</span><span class="text-[var(--rpa-success)]">成功</span></div><div class="flex justify-between"><span>RPA</span><span>${prototypeState.rpaHosting?'托管中':'空闲'}</span></div></div>`})}
|
||||
${card('执行状态',{icon:icon('activity'),html:`<div class="space-y-3 text-sm"><div class="flex justify-between"><span>运行中</span><b>0</b></div><div class="flex justify-between"><span>失败任务</span><b class="text-red-600">1</b></div><div class="flex justify-between"><span>最近托管</span><span class="text-emerald-600">成功</span></div><div class="flex justify-between"><span>RPA</span><span>${prototypeState.rpaHosting?'托管中':'空闲'}</span></div></div>`})}
|
||||
</div>
|
||||
<section class="rpa-panel p-5"><h3 class="mb-4 font-semibold">快速入口</h3><div class="flex flex-wrap gap-3">
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><h3 class="mb-4 font-semibold">快速入口</h3><div class="flex flex-wrap gap-3">
|
||||
${actionBtn(icon('database')+'创建知识库','data-modal-open="knowledge"',true)}
|
||||
${actionBtn(icon('bot')+'创建 AI 员工','data-modal-open="agent"',true)}
|
||||
${actionBtn(icon('scan-line')+'进入标注模式 Ctrl+E','data-overlay-open="annotation"')}
|
||||
${actionBtn(icon('play')+'启动自动化任务','data-modal-open="hosting-confirm"')}
|
||||
${actionBtn(icon('package-check')+'导出诊断包','data-action="diagnostic"')}
|
||||
</div></section>
|
||||
<section class="rpa-panel p-5"><h3 class="mb-4 font-semibold">核心闭环</h3><div class="flex items-center gap-2 text-sm text-[var(--rpa-muted)]">${['首次配置','知识库','AI 员工','标注应用','自动化任务','托管执行','审计复盘'].map((s,i)=>`<div class="flex items-center gap-2"><span class="grid h-8 w-8 place-items-center rounded-full font-semibold" style="background:var(--rpa-primary-soft); color:var(--rpa-primary)">${i+1}</span><span>${s}</span></div>${i<6?'<div class="h-px w-8 bg-slate-200"></div>':''}`).join('')}</div></section>
|
||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><h3 class="mb-4 font-semibold">核心闭环</h3><div class="flex items-center gap-2 text-sm text-slate-600">${['首次配置','知识库','AI 员工','标注应用','自动化任务','托管执行','审计复盘'].map((s,i)=>`<div class="flex items-center gap-2"><span class="grid h-8 w-8 place-items-center rounded-full bg-indigo-50 font-semibold text-indigo-700">${i+1}</span><span>${s}</span></div>${i<6?'<div class="h-px w-8 bg-slate-200"></div>':''}`).join('')}</div></section>
|
||||
</div>`;
|
||||
}
|
||||
function kbPage(){
|
||||
return `<div class="space-y-5"><div class="flex items-center gap-3 rpa-panel p-4"><div class="relative flex-1">${icon('search','absolute left-3 top-3 h-4 w-4 text-slate-400')}<input class="focus-ring h-10 w-full rounded-xl border border-slate-200 pl-9 text-sm" placeholder="搜索制度、流程、操作说明"></div>${actionBtn('来源','')}${actionBtn('类型','')}${actionBtn('按更新时间','')}${actionBtn(icon('upload')+'上传/创建知识库','data-modal-open="knowledge"',true)}</div>${table(['名称','类型','索引状态','引用次数','更新时间','权限模式'], prototypeState.kbs.map((k,i)=>[`<div><b>${k.name}</b><p class="text-xs text-[var(--rpa-muted)]">${k.description}${k.error?` · ${k.error} ${actionBtn('重试',`data-action="retry-kb" data-index="${i}"`)}`:''}</p></div>`,k.type,`<span class="${clsBadge(k.status)}">${k.status}</span>`,k.refs,k.updated,`<button data-action="permission" data-index="${i}" class="${clsBadge('idle')}">${k.permission}</button>`]))}</div>`;
|
||||
return `<div class="space-y-5"><div class="flex items-center gap-3 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm"><div class="relative flex-1">${icon('search','absolute left-3 top-3 h-4 w-4 text-slate-400')}<input class="focus-ring h-10 w-full rounded-xl border border-slate-200 pl-9 text-sm" placeholder="搜索制度、流程、操作说明"></div>${actionBtn('来源','')}${actionBtn('类型','')}${actionBtn('按更新时间','')}${actionBtn(icon('upload')+'上传/创建知识库','data-modal-open="knowledge"',true)}</div>${table(['名称','类型','索引状态','引用次数','更新时间','权限模式'], prototypeState.kbs.map((k,i)=>[`<div><b>${k.name}</b><p class="text-xs text-slate-500">${k.description}${k.error?` · ${k.error} ${actionBtn('重试',`data-action="retry-kb" data-index="${i}"`)}`:''}</p></div>`,k.type,`<span class="${clsBadge(k.status)}">${k.status}</span>`,k.refs,k.updated,`<button data-action="permission" data-index="${i}" class="${clsBadge('idle')}">${k.permission}</button>`]))}</div>`;
|
||||
}
|
||||
function agentPage(){
|
||||
return `<div class="space-y-5"><div class="flex justify-between rpa-panel p-4"><div><h3 class="font-semibold">AI 员工</h3><p class="text-sm text-[var(--rpa-muted)]">启动任务前必须展示知识库、应用和停止方式。</p></div>${actionBtn(icon('plus')+'创建 AI 员工','data-modal-open="agent"',true)}</div>${table(['名称','角色','状态','可访问知识库','可操作标注应用','最近执行时间','操作'], prototypeState.agents.map((a,i)=>[a.name,a.role,`<span class="${clsBadge(a.status)}">${a.status}</span>`,a.kb,a.apps,a.last,actionBtn('启动任务',`data-modal-open="agent-confirm" data-index="${i}"`)]))}</div>`;
|
||||
return `<div class="space-y-5"><div class="flex justify-between rounded-2xl border border-slate-200 bg-white p-4 shadow-sm"><div><h3 class="font-semibold">AI 员工</h3><p class="text-sm text-slate-500">启动任务前必须展示知识库、应用和停止方式。</p></div>${actionBtn(icon('plus')+'创建 AI 员工','data-modal-open="agent"',true)}</div>${table(['名称','角色','状态','可访问知识库','可操作标注应用','最近执行时间','操作'], prototypeState.agents.map((a,i)=>[a.name,a.role,`<span class="${clsBadge(a.status)}">${a.status}</span>`,a.kb,a.apps,a.last,actionBtn('启动任务',`data-modal-open="agent-confirm" data-index="${i}"`)]))}</div>`;
|
||||
}
|
||||
function annotationPage(){
|
||||
const tab = prototypeState.activeAppTab;
|
||||
const tabHtml = ['概览','窗口','节点','流程'].map(t=>`<button type="button" data-tab="${t}" class="focus-ring h-10 rounded-xl px-4 text-sm font-medium ${tab===t?'rpa-primary-btn':'hover:text-[var(--rpa-tech-blue)]'}">${t}</button>`).join('');
|
||||
const tabHtml = ['概览','窗口','节点','流程'].map(t=>`<button type="button" data-tab="${t}" class="focus-ring h-10 rounded-xl px-4 text-sm font-medium ${tab===t?'bg-indigo-600 text-white':'text-slate-600 hover:bg-slate-100'}">${t}</button>`).join('');
|
||||
let panel = tab==='节点' ? table(['节点名','node_type','bounds','allowed_actions','confidence'], prototypeState.nodes.map(n=>[n.name,n.type,n.bounds,n.actions,n.confidence])) : tab==='窗口' ? `<div class="grid grid-cols-2 gap-4 text-sm"><div class="rounded-xl border p-4"><b>主窗口</b><p>1180×760 · 已标注</p></div><div class="rounded-xl border p-4"><b>审批弹窗</b><p>520×360 · 已标注</p></div></div>` : tab==='流程' ? `<ol class="space-y-3 text-sm"><li>1. 读取制度规则</li><li>2. 填写金额输入框</li><li>3. 点击提交按钮前暂停确认</li></ol>` : `<div class="grid grid-cols-4 gap-4 text-sm"><div class="rounded-xl border p-4"><b>窗口数</b><p>2</p></div><div class="rounded-xl border p-4"><b>节点数</b><p>${prototypeState.nodes.length}</p></div><div class="rounded-xl border p-4"><b>流程数</b><p>3</p></div><div class="rounded-xl border p-4"><b>最近更新</b><p>今天 09:20</p></div></div>`;
|
||||
return `<div class="space-y-5"><div class="rpa-panel p-5"><div class="flex items-center justify-between"><div><h3 class="font-semibold">企业报销系统</h3><p class="text-sm text-[var(--rpa-muted)]">窗口数 2、节点数 ${prototypeState.nodes.length}、流程数 3、最近更新 今天</p></div>${actionBtn(icon('scan-line')+'进入标注模式 Ctrl+E','data-overlay-open="annotation"',true)}</div></div><section class="rpa-panel p-5"><div class="mb-5 flex gap-2">${tabHtml}</div>${panel}</section></div>`;
|
||||
return `<div class="space-y-5"><div class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><div class="flex items-center justify-between"><div><h3 class="font-semibold">企业报销系统</h3><p class="text-sm text-slate-500">窗口数 2、节点数 ${prototypeState.nodes.length}、流程数 3、最近更新 今天</p></div>${actionBtn(icon('scan-line')+'进入标注模式 Ctrl+E','data-overlay-open="annotation"',true)}</div></div><section class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><div class="mb-5 flex gap-2">${tabHtml}</div>${panel}</section></div>`;
|
||||
}
|
||||
function tasksPage(){
|
||||
const rows = prototypeState.tasks.map((t,i)=>[t.name,t.type,`<span class="${clsBadge(t.status)}">${t.status}</span>`,t.employee,t.app,t.updated,t.error?`<div class="text-[var(--rpa-danger)]">${t.error}<br><code class="text-xs">${t.code}</code><br>${actionBtn('重试',`data-action="retry-task" data-index="${i}"`)}</div>`:actionBtn('查看','')]);
|
||||
const rows = prototypeState.tasks.map((t,i)=>[t.name,t.type,`<span class="${clsBadge(t.status)}">${t.status}</span>`,t.employee,t.app,t.updated,t.error?`<div class="text-red-700">${t.error}<br><code class="text-xs">${t.code}</code><br>${actionBtn('重试',`data-action="retry-task" data-index="${i}"`)}</div>`:actionBtn('查看','')]);
|
||||
let audits = prototypeState.audits.filter(a=>(!prototypeState.auditFilters.employee||a.employee===prototypeState.auditFilters.employee)&&(!prototypeState.auditFilters.status||a.status===prototypeState.auditFilters.status));
|
||||
return `<div class="space-y-5"><div class="flex items-center justify-between rpa-panel p-4"><div><h3 class="font-semibold">自动化任务</h3><p class="text-sm text-[var(--rpa-muted)]">状态只使用 queued | running | succeeded | failed | canceled。</p></div>${actionBtn(icon('play')+'启动托管演示','data-modal-open="hosting-confirm"',true)}</div><div class="grid grid-cols-3 gap-4">${['运行中任务','历史任务','失败任务'].map((s,i)=>`<div class="rpa-panel p-4"><h3 class="font-semibold">${s}</h3><p class="mt-2 text-2xl font-semibold">${i===0?prototypeState.tasks.filter(t=>t.status==='running').length:i===1?prototypeState.tasks.filter(t=>t.status==='succeeded').length:prototypeState.tasks.filter(t=>t.status==='failed').length}</p></div>`).join('')}</div>${table(['任务名','类型','状态','员工','目标应用','更新时间','操作'], rows)}<section class="rpa-panel p-5"><button type="button" data-action="toggle-audit" class="flex h-10 w-full items-center justify-between font-semibold">审计日志 ${icon(prototypeState.auditOpen?'chevron-up':'chevron-down')}</button><div class="${prototypeState.auditOpen?'':'hidden'} mt-4 space-y-4"><div class="grid grid-cols-5 gap-3 text-sm"><select data-filter="time" class="h-10 rounded-xl border px-3"><option>时间</option></select><select data-filter="employee" class="h-10 rounded-xl border px-3"><option value="">员工</option><option>报销审核员</option><option>系统</option></select><select data-filter="app" class="h-10 rounded-xl border px-3"><option>应用</option></select><select data-filter="kb" class="h-10 rounded-xl border px-3"><option>知识库</option></select><select data-filter="status" class="h-10 rounded-xl border px-3"><option value="">任务状态</option><option>running</option><option>succeeded</option><option>failed</option><option>canceled</option></select></div>${table(['时间','员工','应用','知识库','状态','记录'], audits.map(a=>[a.time,a.employee,a.app,a.kb,`<span class="${clsBadge(a.status)}">${a.status}</span>`,a.text]))}</div></section></div>`;
|
||||
return `<div class="space-y-5"><div class="flex items-center justify-between rounded-2xl border border-slate-200 bg-white p-4 shadow-sm"><div><h3 class="font-semibold">自动化任务</h3><p class="text-sm text-slate-500">状态只使用 queued | running | succeeded | failed | canceled。</p></div>${actionBtn(icon('play')+'启动托管演示','data-modal-open="hosting-confirm"',true)}</div><div class="grid grid-cols-3 gap-4">${['运行中任务','历史任务','失败任务'].map((s,i)=>`<div class="rounded-2xl border bg-white p-4 shadow-sm"><h3 class="font-semibold">${s}</h3><p class="mt-2 text-2xl font-semibold">${i===0?prototypeState.tasks.filter(t=>t.status==='running').length:i===1?prototypeState.tasks.filter(t=>t.status==='succeeded').length:prototypeState.tasks.filter(t=>t.status==='failed').length}</p></div>`).join('')}</div>${table(['任务名','类型','状态','员工','目标应用','更新时间','操作'], rows)}<section class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><button type="button" data-action="toggle-audit" class="flex h-10 w-full items-center justify-between font-semibold">审计日志 ${icon(prototypeState.auditOpen?'chevron-up':'chevron-down')}</button><div class="${prototypeState.auditOpen?'':'hidden'} mt-4 space-y-4"><div class="grid grid-cols-5 gap-3 text-sm"><select data-filter="time" class="h-10 rounded-xl border px-3"><option>时间</option></select><select data-filter="employee" class="h-10 rounded-xl border px-3"><option value="">员工</option><option>报销审核员</option><option>系统</option></select><select data-filter="app" class="h-10 rounded-xl border px-3"><option>应用</option></select><select data-filter="kb" class="h-10 rounded-xl border px-3"><option>知识库</option></select><select data-filter="status" class="h-10 rounded-xl border px-3"><option value="">任务状态</option><option>running</option><option>succeeded</option><option>failed</option><option>canceled</option></select></div>${table(['时间','员工','应用','知识库','状态','记录'], audits.map(a=>[a.time,a.employee,a.app,a.kb,`<span class="${clsBadge(a.status)}">${a.status}</span>`,a.text]))}</div></section></div>`;
|
||||
}
|
||||
function settingsPage(){
|
||||
const groups = [
|
||||
@ -240,9 +194,9 @@ function settingsPage(){
|
||||
['诊断与日志',`${actionBtn('导出诊断包','data-action="diagnostic-full"')} ${actionBtn('查看本地日志目录','data-action="log-dir"')} ${actionBtn('复制环境信息','data-action="copy-env"')}`],
|
||||
['数据备份与恢复','导出配置、导出知识库元数据、恢复 SQLite 与索引文件'], ['许可证管理','trial · 14 天试用 · 最多 3 个知识库 / 2 个 AI 员工 / 1 个标注应用 / 每日 20 次托管任务']
|
||||
];
|
||||
return `<div class="grid grid-cols-2 gap-4 pb-8">${groups.map(g=>`<section class="rpa-panel p-5"><h3 class="mb-3 font-semibold">${g[0]}</h3><div class="text-sm leading-7 text-[var(--rpa-muted)]">${g[1]}</div></section>`).join('')}</div>`;
|
||||
return `<div class="grid grid-cols-2 gap-4 pb-8">${groups.map(g=>`<section class="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm"><h3 class="mb-3 font-semibold">${g[0]}</h3><div class="text-sm leading-7 text-slate-600">${g[1]}</div></section>`).join('')}</div>`;
|
||||
}
|
||||
function table(headers, rows){ return `<div class="rpa-table"><table class="w-full text-left text-sm"><thead class="text-xs"><tr>${headers.map(h=>`<th class="px-4 py-3 font-medium">${h}</th>`).join('')}</tr></thead><tbody>${rows.map(r=>`<tr class="align-top">${r.map(c=>`<td class="px-4 py-3">${c}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`; }
|
||||
function table(headers, rows){ return `<div class="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm"><table class="w-full text-left text-sm"><thead class="bg-slate-50 text-xs text-slate-500"><tr>${headers.map(h=>`<th class="px-4 py-3 font-medium">${h}</th>`).join('')}</tr></thead><tbody class="divide-y divide-slate-100">${rows.map(r=>`<tr class="align-top hover:bg-slate-50">${r.map(c=>`<td class="px-4 py-3">${c}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`; }
|
||||
|
||||
function renderOverlay(root){
|
||||
const layer = root.querySelector('[data-overlay-layer]');
|
||||
@ -253,34 +207,34 @@ function renderOverlay(root){
|
||||
if (prototypeState.modal) { layer.innerHTML = modalHtml(prototypeState.modal); return; }
|
||||
layer.innerHTML = '';
|
||||
}
|
||||
function modalFrame(title, body, wide=false){ return `<div class="rpa-scrim flex h-full items-center justify-center p-8"><div class="max-h-full ${wide?'w-[760px]':'w-[560px]'} overflow-y-auto rounded-2xl border p-6" style="background:var(--rpa-surface); border-color:var(--rpa-border); box-shadow:var(--rpa-shadow-blocking)"><div class="mb-5 flex items-center justify-between"><h3 class="text-lg font-semibold" style="color:var(--rpa-heading)">${title}</h3><button data-modal-close class="focus-ring grid h-9 w-9 place-items-center rounded-xl hover:bg-slate-100">${icon('x')}</button></div>${body}</div></div>`; }
|
||||
function modalFrame(title, body, wide=false){ return `<div class="flex h-full items-center justify-center bg-slate-950/40 p-8"><div class="max-h-full ${wide?'w-[760px]':'w-[560px]'} overflow-y-auto rounded-2xl bg-white p-6 shadow-2xl"><div class="mb-5 flex items-center justify-between"><h3 class="text-lg font-semibold">${title}</h3><button data-modal-close class="focus-ring grid h-9 w-9 place-items-center rounded-xl hover:bg-slate-100">${icon('x')}</button></div>${body}</div></div>`; }
|
||||
function modalHtml(type){
|
||||
if(type==='config') return configModal();
|
||||
if(type==='knowledge') return modalFrame('上传/创建知识库', `<form data-form="knowledge" class="space-y-4"><input name="name" required class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="名称"><textarea name="description" class="focus-ring w-full rounded-xl border p-3" placeholder="描述"></textarea><select name="type" class="focus-ring h-10 w-full rounded-xl border px-3"><option value="document">document</option><option value="image">image</option><option value="video">video</option><option value="folder">folder</option><option value="url">url</option></select><select name="permission" class="focus-ring h-10 w-full rounded-xl border px-3"><option value="private">private</option><option value="selected_agents">selected_agents</option><option value="workspace">workspace</option></select><button class="focus-ring h-10 rounded-xl rpa-primary-btn px-4">提交</button></form>`);
|
||||
if(type==='agent') return modalFrame('创建/编辑 AI 员工', `<form data-form="agent" class="space-y-4"><input name="role" required class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="角色描述"><textarea name="prompt" class="focus-ring w-full rounded-xl border p-3" placeholder="系统提示词"></textarea><input class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="模型配置:本地模型"><input class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="知识库权限:财务报销制度"><input class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="可操作应用权限:企业报销系统"><button class="focus-ring h-10 rounded-xl rpa-primary-btn px-4">提交</button></form>`);
|
||||
if(type==='knowledge') return modalFrame('上传/创建知识库', `<form data-form="knowledge" class="space-y-4"><input name="name" required class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="名称"><textarea name="description" class="focus-ring w-full rounded-xl border p-3" placeholder="描述"></textarea><select name="type" class="h-10 w-full rounded-xl border px-3"><option value="document">document</option><option value="image">image</option><option value="video">video</option><option value="folder">folder</option><option value="url">url</option></select><select name="permission" class="h-10 w-full rounded-xl border px-3"><option value="private">private</option><option value="selected_agents">selected_agents</option><option value="workspace">workspace</option></select><button class="h-10 rounded-xl bg-indigo-600 px-4 text-white">提交</button></form>`);
|
||||
if(type==='agent') return modalFrame('创建/编辑 AI 员工', `<form data-form="agent" class="space-y-4"><input name="role" required class="focus-ring h-10 w-full rounded-xl border px-3" placeholder="角色描述"><textarea name="prompt" class="focus-ring w-full rounded-xl border p-3" placeholder="系统提示词"></textarea><input class="h-10 w-full rounded-xl border px-3" placeholder="模型配置:本地模型"><input class="h-10 w-full rounded-xl border px-3" placeholder="知识库权限:财务报销制度"><input class="h-10 w-full rounded-xl border px-3" placeholder="可操作应用权限:企业报销系统"><button class="h-10 rounded-xl bg-indigo-600 px-4 text-white">提交</button></form>`);
|
||||
if(type==='permission') return modalFrame('权限模式', `<div class="space-y-3">${['private','selected_agents','workspace'].map(p=>`<button data-action="save-permission" data-value="${p}" class="focus-ring flex h-10 w-full items-center rounded-xl border px-3 text-sm hover:bg-slate-50">${p}</button>`).join('')}</div>`);
|
||||
if(type==='agent-confirm' || type==='hosting-confirm') return modalFrame('启动前确认', `<div class="space-y-4 text-sm"><div class="rounded-xl p-4" style="background:var(--rpa-primary-soft)"><b>AI 员工</b><p>报销审核员</p></div><div class="rounded-xl p-4" style="background:var(--rpa-surface-subtle)"><b>将访问的知识库</b><p>财务报销制度</p></div><div class="rounded-xl p-4" style="background:var(--rpa-surface-subtle)"><b>将控制的应用</b><p>企业报销系统</p></div><div class="rounded-xl p-4" style="background:var(--rpa-surface-subtle)"><b>预计动作范围</b><p>读取报销规则、填写金额、点击提交前暂停确认</p></div><div class="rounded-xl p-4" style="background:var(--rpa-surface-subtle)"><b>停止方式</b><p>ESC 或遮罩上的停止托管按钮</p></div><div class="flex justify-end gap-3">${actionBtn('取消','data-modal-close')}${actionBtn('确认启动托管','data-action="start-hosting"',true)}</div></div>`);
|
||||
if(type==='agent-confirm' || type==='hosting-confirm') return modalFrame('启动前确认', `<div class="space-y-4 text-sm"><div class="rounded-xl bg-indigo-50 p-4"><b>AI 员工</b><p>报销审核员</p></div><div class="rounded-xl bg-slate-50 p-4"><b>将访问的知识库</b><p>财务报销制度</p></div><div class="rounded-xl bg-slate-50 p-4"><b>将控制的应用</b><p>企业报销系统</p></div><div class="rounded-xl bg-slate-50 p-4"><b>预计动作范围</b><p>读取报销规则、填写金额、点击提交前暂停确认</p></div><div class="rounded-xl bg-slate-50 p-4"><b>停止方式</b><p>ESC 或遮罩上的停止托管按钮</p></div><div class="flex justify-end gap-3">${actionBtn('取消','data-modal-close')}${actionBtn('确认启动托管','data-action="start-hosting"',true)}</div></div>`);
|
||||
return '';
|
||||
}
|
||||
function configModal(){
|
||||
const steps=['权限检查','模型配置','性能评估','存储位置','安全说明']; const s=prototypeState.configStep;
|
||||
const status=['通过','通过','通过','通过','需手动处理'];
|
||||
return modalFrame('首次配置与环境检查', `<div class="flex gap-5"><aside class="w-40 space-y-2">${steps.map((x,i)=>`<button data-action="config-step" data-index="${i}" class="focus-ring h-10 w-full rounded-xl text-left text-sm ${s===i?'rpa-primary-btn px-3':'px-3 hover:bg-slate-100'}">${x}</button>`).join('')}</aside><div class="flex-1 space-y-4 text-sm"><p style="color:var(--rpa-muted)">状态枚举:未检查 | 检查中 | 通过 | 失败 | 需手动处理</p>${s===0?`<div class="space-y-2">${['屏幕录制','辅助功能/自动化控制','文件访问','网络访问'].map((x,i)=>`<div class="flex justify-between rounded-xl border p-3"><span>${x}</span><span class="${clsBadge(i===1?status[4]:'ready')}">${i===1?status[4]:'通过'}</span></div>`).join('')}</div><div class="rounded-xl p-4" style="background:var(--rpa-warning-bg); color:#92400e">原因:辅助功能权限需手动授权;恢复:打开系统设置或重新检测。</div><div class="flex gap-2">${actionBtn('打开系统设置','data-action="open-settings"')}${actionBtn('重新检测','data-action="recheck-permission"',true)}${actionBtn('跳过并以后配置','data-modal-close')}</div>`:`<div class="rounded-xl border p-4"><b>${steps[s]}</b><p class="mt-2">当前状态:通过。本页用于演示 ${steps[s]} 配置检查。</p></div>`}</div></div>`, true);
|
||||
return modalFrame('首次配置与环境检查', `<div class="flex gap-5"><aside class="w-40 space-y-2">${steps.map((x,i)=>`<button data-action="config-step" data-index="${i}" class="h-10 w-full rounded-xl text-left text-sm ${s===i?'bg-indigo-600 px-3 text-white':'px-3 hover:bg-slate-100'}">${x}</button>`).join('')}</aside><div class="flex-1 space-y-4 text-sm"><p class="text-slate-500">状态枚举:未检查 | 检查中 | 通过 | 失败 | 需手动处理</p>${s===0?`<div class="space-y-2">${['屏幕录制','辅助功能/自动化控制','文件访问','网络访问'].map((x,i)=>`<div class="flex justify-between rounded-xl border p-3"><span>${x}</span><span class="${clsBadge(i===1?status[4]:'ready')}">${i===1?status[4]:'通过'}</span></div>`).join('')}</div><div class="rounded-xl bg-amber-50 p-4 text-amber-800">原因:辅助功能权限需手动授权;恢复:打开系统设置或重新检测。</div><div class="flex gap-2">${actionBtn('打开系统设置','data-action="open-settings"')}${actionBtn('重新检测','data-action="recheck-permission"',true)}${actionBtn('跳过并以后配置','data-modal-close')}</div>`:`<div class="rounded-xl border p-4"><b>${steps[s]}</b><p class="mt-2">当前状态:通过。本页用于演示 ${steps[s]} 配置检查。</p></div>`}</div></div>`, true);
|
||||
}
|
||||
function annotationOverlay(){
|
||||
const b=prototypeState.draftBounds;
|
||||
return `<div class="rpa-hosting-scrim relative h-full p-8 text-white"><div class="mx-auto flex h-full max-w-4xl flex-col gap-4"><div class="flex items-center justify-between"><div><h3 class="text-lg font-semibold">Ctrl+E 标注模式</h3><p class="text-sm text-slate-300">选择当前标注应用 → 框选窗口/节点 → 命名节点 → 保存</p></div>${actionBtn('退出','data-overlay-close')}</div><div class="grid grid-cols-[1fr_280px] gap-4 min-h-0 flex-1"><div class="relative overflow-hidden rounded-2xl bg-slate-200 p-5 text-slate-900"><div class="h-full rounded-xl bg-white p-5 shadow-inner"><div class="mb-4 flex h-10 items-center gap-2 rounded bg-slate-100 px-3"><b>企业报销系统</b><span class="text-sm" style="color:var(--rpa-muted)">模拟桌面截图</span></div><div class="grid grid-cols-3 gap-4"><div class="h-80 rounded bg-slate-100"></div><div class="col-span-2 h-80 rounded bg-slate-50 p-4"><input class="mb-4 h-10 w-52 rounded border px-3" value="1280.00"><button class="absolute rounded rpa-primary-btn px-4 py-2" style="left:520px;top:430px">提交</button></div></div></div><div data-drag-box class="absolute cursor-move rounded-lg border-2" style="left:${b.x}px;top:${b.y}px;width:${b.width}px;height:${b.height}px; border-color:var(--rpa-primary); background:rgba(255,80,0,.16)"></div></div><form data-form="node" class="space-y-4 rounded-2xl bg-white p-5 text-slate-900"><label class="block text-sm font-medium">当前标注应用<select class="focus-ring mt-2 h-10 w-full rounded-xl border px-3"><option>企业报销系统</option></select></label><label class="block text-sm font-medium">节点名<input name="name" required class="focus-ring mt-2 h-10 w-full rounded-xl border px-3" placeholder="测试提交按钮"></label><p class="rpa-code p-3 text-xs">当前 bounds:{ x: ${b.x}, y: ${b.y}, width: ${b.width}, height: ${b.height} }</p><button class="focus-ring h-10 w-full rounded-xl rpa-primary-btn">保存</button><button type="button" data-action="annotation-fail" class="h-9 text-sm rpa-link-btn" style="color:var(--rpa-danger)">模拟保存失败</button><button type="button" data-action="annotation-retry" class="hidden h-9 text-sm rpa-link-btn">重试保存</button><p data-annotation-error class="hidden rounded-xl p-3 text-sm" style="background:var(--rpa-danger-bg); color:var(--rpa-danger)">保存失败:窗口句柄已变化,可保留草稿并重试。原因:窗口句柄已变化;恢复:保留草稿并重试保存。</p></form></div></div></div>`;
|
||||
return `<div class="relative h-full bg-slate-950/85 p-8 text-white"><div class="mx-auto flex h-full max-w-4xl flex-col gap-4"><div class="flex items-center justify-between"><div><h3 class="text-lg font-semibold">Ctrl+E 标注模式</h3><p class="text-sm text-slate-300">选择当前标注应用 → 框选窗口/节点 → 命名节点 → 保存</p></div>${actionBtn('退出','data-overlay-close')}</div><div class="grid grid-cols-[1fr_280px] gap-4 min-h-0 flex-1"><div class="relative overflow-hidden rounded-2xl bg-slate-200 p-5 text-slate-900"><div class="h-full rounded-xl bg-white p-5 shadow-inner"><div class="mb-4 flex h-10 items-center gap-2 rounded bg-slate-100 px-3"><b>企业报销系统</b><span class="text-sm text-slate-500">模拟桌面截图</span></div><div class="grid grid-cols-3 gap-4"><div class="h-80 rounded bg-slate-100"></div><div class="col-span-2 h-80 rounded bg-slate-50 p-4"><input class="mb-4 h-10 w-52 rounded border px-3" value="1280.00"><button class="absolute rounded bg-indigo-600 px-4 py-2 text-white" style="left:520px;top:430px">提交</button></div></div></div><div data-drag-box class="absolute cursor-move rounded-lg border-2 border-indigo-500 bg-indigo-500/20" style="left:${b.x}px;top:${b.y}px;width:${b.width}px;height:${b.height}px"></div></div><form data-form="node" class="space-y-4 rounded-2xl bg-white p-5 text-slate-900"><label class="block text-sm font-medium">当前标注应用<select class="mt-2 h-10 w-full rounded-xl border px-3"><option>企业报销系统</option></select></label><label class="block text-sm font-medium">节点名<input name="name" required class="mt-2 h-10 w-full rounded-xl border px-3" placeholder="测试提交按钮"></label><p class="rounded-xl bg-slate-50 p-3 text-xs">当前 bounds:{ x: ${b.x}, y: ${b.y}, width: ${b.width}, height: ${b.height} }</p><button class="h-10 w-full rounded-xl bg-indigo-600 text-white">保存</button><button type="button" data-action="annotation-fail" class="h-9 text-sm text-red-600">模拟保存失败</button><button type="button" data-action="annotation-retry" class="hidden h-9 text-sm text-indigo-600">重试保存</button><p data-annotation-error class="hidden rounded-xl bg-red-50 p-3 text-sm text-red-700">保存失败:窗口句柄已变化,可保留草稿并重试。原因:窗口句柄已变化;恢复:保留草稿并重试保存。</p></form></div></div></div>`;
|
||||
}
|
||||
function hostingOverlay(){
|
||||
const actions=['读取报销规则','填写金额输入框','定位提交按钮','提交报销单'];
|
||||
const current=actions[Math.min(prototypeState.hostingStep, actions.length-1)];
|
||||
return `<div class="flex h-full items-center justify-center p-8 text-white" style="background:rgba(10,9,30,.90)"><div class="w-[760px] rounded-3xl border p-6" style="background:var(--rpa-nav-panel); border-color:rgba(255,255,255,.10); box-shadow:var(--rpa-shadow-blocking)"><div class="flex items-center justify-between"><div><h3 class="text-xl font-semibold">RPA 托管执行中</h3><p class="text-sm text-slate-300">ESC 紧急停止始终可用</p></div><button data-action="stop-hosting" class="h-11 rounded-xl rpa-danger-btn px-5 font-semibold">停止托管</button></div><div class="mt-5 rounded-2xl p-4" style="background:#111827"><p class="text-sm text-slate-400">当前动作</p><p class="mt-1 text-lg font-semibold">${current}</p><div class="mt-4 h-3 rounded-full bg-slate-800"><div class="rpa-progress h-3 rounded-full" style="width:${(prototypeState.hostingStep+1)*25}%"></div></div></div><div class="mt-5 max-h-48 overflow-y-auto rounded-2xl p-4 text-sm text-slate-300" style="background:#080b14; font-family:var(--rpa-font-mono)">${prototypeState.hostingLogs.map(l=>`<p>${l}</p>`).join('') || '<p>等待下一步动作。</p>'}</div><div class="mt-5 flex justify-end gap-3">${actionBtn('下一步动作','data-action="next-hosting"',true)}</div></div></div>`;
|
||||
return `<div class="flex h-full items-center justify-center bg-slate-950/90 p-8 text-white"><div class="w-[760px] rounded-3xl border border-white/10 bg-slate-900 p-6 shadow-2xl"><div class="flex items-center justify-between"><div><h3 class="text-xl font-semibold">RPA 托管执行中</h3><p class="text-sm text-slate-300">ESC 紧急停止始终可用</p></div><button data-action="stop-hosting" class="h-11 rounded-xl bg-red-600 px-5 font-semibold text-white">停止托管</button></div><div class="mt-5 rounded-2xl bg-slate-950 p-4"><p class="text-sm text-slate-400">当前动作</p><p class="mt-1 text-lg font-semibold">${current}</p><div class="mt-4 h-3 rounded-full bg-slate-800"><div class="h-3 rounded-full bg-indigo-500" style="width:${(prototypeState.hostingStep+1)*25}%"></div></div></div><div class="mt-5 max-h-48 overflow-y-auto rounded-2xl bg-slate-950 p-4 text-sm text-slate-300">${prototypeState.hostingLogs.map(l=>`<p>${l}</p>`).join('') || '<p>等待下一步动作。</p>'}</div><div class="mt-5 flex justify-end gap-3">${actionBtn('下一步动作','data-action="next-hosting"',true)}</div></div></div>`;
|
||||
}
|
||||
function highRiskOverlay(){ return `<div class="rpa-scrim flex h-full items-center justify-center p-8"><div class="w-[520px] rounded-2xl border p-6" style="background:var(--rpa-surface); border-color:var(--rpa-danger-border); box-shadow:var(--rpa-shadow-blocking)"><h3 class="text-lg font-semibold" style="color:var(--rpa-danger)">高风险动作:提交</h3><p class="mt-3 text-sm" style="color:var(--rpa-muted)">确认后将向业务系统提交单据。</p><div class="mt-5 flex justify-end gap-3">${actionBtn('取消并等待人工','data-action="cancel-high-risk"')}<button type="button" data-action="confirm-high-risk" class="focus-ring inline-flex h-10 items-center justify-center rounded-xl rpa-danger-btn px-4 text-sm font-medium">确认提交</button></div></div></div>`; }
|
||||
function highRiskOverlay(){ return `<div class="flex h-full items-center justify-center bg-slate-950/70 p-8"><div class="w-[520px] rounded-2xl bg-white p-6 shadow-2xl"><h3 class="text-lg font-semibold text-red-700">高风险动作:提交</h3><p class="mt-3 text-sm text-slate-600">确认后将向业务系统提交单据。</p><div class="mt-5 flex justify-end gap-3">${actionBtn('取消并等待人工','data-action="cancel-high-risk"')}${actionBtn('确认提交','data-action="confirm-high-risk"',true)}</div></div></div>`; }
|
||||
|
||||
document.addEventListener('click', event => {
|
||||
const platformTab = event.target.closest('[data-platform-tab]');
|
||||
if(platformTab){ const target=platformTab.dataset.platformTab; prototypeState.activePlatform=target; document.querySelectorAll('[data-platform-panel]').forEach(p=>p.classList.toggle('hidden',p.dataset.platformPanel!==target)); document.querySelectorAll('[data-platform-tab]').forEach(b=>{b.className='focus-ring h-10 rounded-full px-5 text-sm font-medium text-[var(--rpa-muted)]';}); platformTab.className='focus-ring h-10 rounded-full bg-[var(--rpa-primary)] px-5 text-sm font-medium text-white'; return; }
|
||||
if(platformTab){ const target=platformTab.dataset.platformTab; prototypeState.activePlatform=target; document.querySelectorAll('[data-platform-panel]').forEach(p=>p.classList.toggle('hidden',p.dataset.platformPanel!==target)); document.querySelectorAll('[data-platform-tab]').forEach(b=>{b.className='focus-ring h-10 rounded-full px-5 text-sm font-medium text-slate-600';}); platformTab.className='focus-ring h-10 rounded-full bg-[var(--primary)] px-5 text-sm font-medium text-white'; return; }
|
||||
const page = event.target.closest('[data-page]'); if(page){ prototypeState.page=page.dataset.page; renderAll(); return; }
|
||||
const tab = event.target.closest('[data-tab]'); if(tab){ prototypeState.activeAppTab=tab.dataset.tab; renderAll(); return; }
|
||||
const open = event.target.closest('[data-modal-open]'); if(open){ prototypeState.modal=open.dataset.modalOpen; renderAll(); return; }
|
||||
|
||||
@ -1,321 +0,0 @@
|
||||
# RPA工作站风格主题
|
||||
|
||||
## 1. 主题来源
|
||||
- 产品依据:`PRD.md`。
|
||||
- 风格依据:`taobao-open-style-card.md`。
|
||||
- 生成日期:2026-06-26。
|
||||
- 主题目标:把淘宝开放平台的“深色技术导航 + 白底业务入口 + 蓝色交互高亮”转译为 RPA 工作站的“本地优先、可审计、可托管、专业工具型桌面产品”视觉系统。
|
||||
|
||||
## 2. 一句话主题定位
|
||||
深色技术控制台骨架 + 靛蓝/技术蓝高亮 + 白底高密度业务面板,表达本地 AI + RPA 的可信托管、显式授权、审计可追溯和桌面工具效率。
|
||||
|
||||
## 3. 设计原则
|
||||
1. **专业克制**:遵循 PRD 的“专业、克制、工具型、低饱和科技感”,避免消费营销感和高饱和橙色。
|
||||
2. **安全优先**:托管、权限、高风险动作使用更高对比度的阻断层和语义色,不用纯装饰动效稀释风险。
|
||||
3. **本地可信**:以深 Slate 导航和低亮蓝色状态表达“本地运行、可控、稳定”。
|
||||
4. **高信息密度**:知识库、AI 员工、任务、审计日志以表格、状态 chip、紧凑卡片呈现。
|
||||
5. **显式授权**:所有权限、托管、AI 员工操作范围都要有清晰边界、标题、说明和取消路径。
|
||||
6. **桌面优先**:主窗口固定左侧导航 + 右侧内容,壳内滚动,适配 Windows/Mac 桌面壳。
|
||||
|
||||
## 4. 风格关键词
|
||||
- **本地技术控制台**:沿用淘宝开放平台 `#373942` 深色技术导航,但转为桌面左侧窄栏。
|
||||
- **靛蓝 AI 感**:PRD 指定蓝紫/靛蓝主色,覆盖主按钮、激活导航、托管进度、关键动作。
|
||||
- **技术蓝辅助**:继承淘宝开放平台 `#5eb5fe` 作为链接、图标 hover、信息型高亮。
|
||||
- **白底数据面板**:工作台、知识库、AI 员工、自动化任务保留白底卡片与细分割线,提升可读性。
|
||||
- **低圆角工具感**:比当前原型的超大圆角更收敛;桌面壳保留平台特征,业务组件使用 8–14px 圆角。
|
||||
- **审计可追溯**:日志、权限、任务状态使用表格化、时间线化、可筛选的视觉模式。
|
||||
|
||||
## 5. 配色系统
|
||||
|
||||
### 5.1 核心色
|
||||
| Token | Hex | 用途 | 来源/理由 |
|
||||
|---|---:|---|---|
|
||||
| `--rpa-primary` | `#4f46e5` | 主按钮、激活状态、关键流程 | PRD 指定蓝紫/靛蓝方向 |
|
||||
| `--rpa-primary-hover` | `#4338ca` | 主按钮 hover/pressed | 靛蓝加深,适合桌面工具 |
|
||||
| `--rpa-primary-soft` | `#eef2ff` | 主色浅底、选中卡片背景 | 保持低饱和科技感 |
|
||||
| `--rpa-tech-blue` | `#5eb5fe` | 链接、图标 hover、信息强调 | 淘宝开放平台交互蓝 |
|
||||
| `--rpa-tech-blue-hover` | `#6cb5f4` | 次级链接 hover | 淘宝开放平台 hover 蓝 |
|
||||
| `--rpa-nav-bg` | `#373942` | 左侧导航背景、托管深色面板 | 淘宝开放平台技术导航 |
|
||||
| `--rpa-nav-panel` | `#2b2d34` | 导航 hover/active 深色底 | 淘宝开放平台菜单面板 |
|
||||
| `--rpa-hosting-bg` | `#0a091e` | RPA 托管遮罩核心面板 | 淘宝开放平台 Hero 深底 |
|
||||
|
||||
### 5.2 中性色
|
||||
| Token | Hex | 用途 |
|
||||
|---|---:|---|
|
||||
| `--rpa-bg` | `#f7f8fa` | 应用内容区背景 |
|
||||
| `--rpa-surface` | `#ffffff` | 卡片、表格、模态主体 |
|
||||
| `--rpa-surface-subtle` | `#f3f4f6` | 次级分组、输入背景 |
|
||||
| `--rpa-border` | `#e6e6e6` | 表格线、卡片边框、公告分割 |
|
||||
| `--rpa-border-strong` | `#cbd5e1` | 输入框、可交互边框 |
|
||||
| `--rpa-text` | `#333333` | 主文本 |
|
||||
| `--rpa-heading` | `#1f2937` | 标题、页面 Header |
|
||||
| `--rpa-muted` | `#666666` | 描述、公告、表格次级文本 |
|
||||
| `--rpa-subtle` | `#7c7c7c` | 弱提示、空状态补充 |
|
||||
| `--rpa-inverse` | `#e5e9ee` | 深色导航文字 |
|
||||
| `--rpa-inverse-muted` | `#a3a3a3` | 深色导航次级文字 |
|
||||
|
||||
### 5.3 语义色
|
||||
| Token | Hex | 场景 |
|
||||
|---|---:|---|
|
||||
| `--rpa-success` | `#4ab933` | ready、模型在线、检测通过 |
|
||||
| `--rpa-success-bg` | `#edffe9` | 成功 toast / 成功 chip 背景 |
|
||||
| `--rpa-info` | `#28a3ef` | indexing、处理中、普通信息 |
|
||||
| `--rpa-info-bg` | `#eef8ff` | 信息提示浅底 |
|
||||
| `--rpa-warning` | `#f59e0b` | waiting_user、需手动处理、高风险前置提醒 |
|
||||
| `--rpa-warning-bg` | `#fffbeb` | 警告浅底 |
|
||||
| `--rpa-danger` | `#d44044` | failed、停止托管、高风险取消 |
|
||||
| `--rpa-danger-bg` | `#fff2f2` | 错误与阻断提示背景 |
|
||||
| `--rpa-danger-border` | `#ffe3e0` | 错误边框 |
|
||||
|
||||
## 6. CSS 主题 Tokens
|
||||
```css
|
||||
:root {
|
||||
color-scheme: light;
|
||||
|
||||
--rpa-primary: #4f46e5;
|
||||
--rpa-primary-hover: #4338ca;
|
||||
--rpa-primary-soft: #eef2ff;
|
||||
--rpa-tech-blue: #5eb5fe;
|
||||
--rpa-tech-blue-hover: #6cb5f4;
|
||||
|
||||
--rpa-nav-bg: #373942;
|
||||
--rpa-nav-panel: #2b2d34;
|
||||
--rpa-nav-border: #383a45;
|
||||
--rpa-hosting-bg: #0a091e;
|
||||
|
||||
--rpa-bg: #f7f8fa;
|
||||
--rpa-surface: #ffffff;
|
||||
--rpa-surface-subtle: #f3f4f6;
|
||||
--rpa-border: #e6e6e6;
|
||||
--rpa-border-strong: #cbd5e1;
|
||||
|
||||
--rpa-text: #333333;
|
||||
--rpa-heading: #1f2937;
|
||||
--rpa-muted: #666666;
|
||||
--rpa-subtle: #7c7c7c;
|
||||
--rpa-inverse: #e5e9ee;
|
||||
--rpa-inverse-muted: #a3a3a3;
|
||||
|
||||
--rpa-success: #4ab933;
|
||||
--rpa-success-bg: #edffe9;
|
||||
--rpa-success-border: #dcf9d6;
|
||||
--rpa-info: #28a3ef;
|
||||
--rpa-info-bg: #eef8ff;
|
||||
--rpa-warning: #f59e0b;
|
||||
--rpa-warning-bg: #fffbeb;
|
||||
--rpa-danger: #d44044;
|
||||
--rpa-danger-bg: #fff2f2;
|
||||
--rpa-danger-border: #ffe3e0;
|
||||
|
||||
--rpa-font-sans: Inter, Arial, "Helvetica Neue", Helvetica, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
--rpa-font-mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
|
||||
|
||||
--rpa-text-xs: 12px;
|
||||
--rpa-text-sm: 14px;
|
||||
--rpa-text-md: 16px;
|
||||
--rpa-text-lg: 18px;
|
||||
--rpa-text-xl: 20px;
|
||||
--rpa-text-2xl: 24px;
|
||||
--rpa-text-3xl: 32px;
|
||||
|
||||
--rpa-space-1: 4px;
|
||||
--rpa-space-2: 8px;
|
||||
--rpa-space-3: 12px;
|
||||
--rpa-space-4: 16px;
|
||||
--rpa-space-6: 24px;
|
||||
--rpa-space-8: 32px;
|
||||
--rpa-space-12: 48px;
|
||||
|
||||
--rpa-radius-xs: 4px;
|
||||
--rpa-radius-sm: 8px;
|
||||
--rpa-radius-md: 12px;
|
||||
--rpa-radius-lg: 16px;
|
||||
--rpa-radius-shell: 28px;
|
||||
|
||||
--rpa-shadow-card: 0 1px 2px rgba(15, 23, 42, 0.06);
|
||||
--rpa-shadow-float: 0 8px 24px rgba(15, 23, 42, 0.14);
|
||||
--rpa-shadow-menu: 1px 1px 5px rgba(0, 0, 0, 0.45);
|
||||
--rpa-shadow-blocking: 0 24px 60px rgba(0, 0, 0, 0.35);
|
||||
|
||||
--rpa-sidebar-width: 92px;
|
||||
--rpa-header-height: 80px;
|
||||
--rpa-control-height: 40px;
|
||||
--rpa-hit-target: 32px;
|
||||
--rpa-transition-fast: 0.18s ease-out;
|
||||
--rpa-transition-normal: 0.28s ease-in-out;
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 字体与字号规则
|
||||
| 层级 | Size | Weight | Line-height | 用途 |
|
||||
|---|---:|---:|---:|---|
|
||||
| Display | 32px | 700 | 1.2 | 销售演示标题、核心闭环页标题 |
|
||||
| Page Title | 24px | 650 | 1.25 | 页面 Header 标题 |
|
||||
| Section Title | 20px | 600 | 1.35 | 卡片组、表格区标题 |
|
||||
| Card Title | 16px | 600 | 1.45 | 状态卡、设置分组 |
|
||||
| Body | 14px | 400 | 1.6 | 表格、说明、表单正文 |
|
||||
| Dense Label | 12px | 500 | 1.4 | chip、状态、表格辅助信息 |
|
||||
| Log / Code | 12–13px | 400/500 | 1.6 | 托管日志、错误码、bounds、API Key 脱敏字段 |
|
||||
|
||||
规则:不继承淘宝开放平台 `12px` 全局正文;RPA 工作站按 PRD 字号阶梯提升正文可读性,12px 只用于辅助标签。
|
||||
|
||||
## 8. 布局系统
|
||||
|
||||
### 主窗口
|
||||
- Shell:Windows/Mac 外壳固定,壳内业务区域 `flex flex-col overflow-hidden`。
|
||||
- 左侧导航:`92px`,深色 `--rpa-nav-bg`,符合 PRD `80–100px`。
|
||||
- Header:`80px`,白底,左侧标题/摘要,右侧状态 chip。
|
||||
- 内容区:`min-h-0 flex-1 overflow-y-auto`,背景 `--rpa-bg`。
|
||||
|
||||
### 页面布局
|
||||
- 工作台:3 张状态卡 + 快速入口 + 核心闭环步骤条。
|
||||
- 知识库 / AI 员工 / 自动化任务:工具栏 + 表格 + 详情/弹窗。
|
||||
- 标注应用:应用概览卡 + 四 Tab + 节点表格。
|
||||
- 设置:双列分组卡,诊断/备份/许可证保持可扫描。
|
||||
|
||||
### 密度
|
||||
- 页面外边距:24px。
|
||||
- 卡片间距:16px 或 24px。
|
||||
- 表格行高:48–56px。
|
||||
- 控件高度:普通 40px,紧凑 chip 28–32px。
|
||||
|
||||
## 9. 组件主题规则
|
||||
|
||||
### 左侧导航
|
||||
- 背景:`--rpa-nav-bg`。
|
||||
- 默认文字/icon:`--rpa-inverse-muted`。
|
||||
- hover:背景 `rgba(255,255,255,.08)`,icon `--rpa-tech-blue`。
|
||||
- active:背景 `--rpa-primary`,文字白色,阴影 `0 8px 20px rgba(79,70,229,.25)`。
|
||||
- 底部状态:深色面 `--rpa-nav-panel`,在线点 `--rpa-success`,托管中改为 `--rpa-warning`。
|
||||
|
||||
### Header 状态 Chip
|
||||
- 模型在线:success。
|
||||
- RPA 空闲:neutral。
|
||||
- RPA 托管中:warning 或 primary breathing dot。
|
||||
- 本地模式:info。
|
||||
- 试用 14天:warning soft。
|
||||
|
||||
### Card
|
||||
- 背景:`--rpa-surface`。
|
||||
- 边框:`1px solid --rpa-border`。
|
||||
- 圆角:12–16px。
|
||||
- 阴影:`--rpa-shadow-card`,hover 可略微上浮但不改变布局。
|
||||
- 标题:16px/600,icon 使用 `--rpa-primary` 或页面语义色。
|
||||
|
||||
### Table
|
||||
- 表头:`--rpa-surface-subtle`,12px/500,文字 `--rpa-muted`。
|
||||
- 行分割:`--rpa-border`。
|
||||
- hover:`#f8fafc`。
|
||||
- 状态列必须用 chip + 文本,不只靠颜色。
|
||||
- 错误码使用 mono 字体和浅红底。
|
||||
|
||||
### Button
|
||||
- Primary:`--rpa-primary`,hover `--rpa-primary-hover`,高度 40px,圆角 10–12px。
|
||||
- Secondary:白底 + `--rpa-border-strong`,hover `--rpa-surface-subtle`。
|
||||
- Danger:`--rpa-danger`,仅用于停止托管、高风险取消、失败重试危险动作。
|
||||
- Link:`--rpa-tech-blue`,hover `--rpa-tech-blue-hover`。
|
||||
|
||||
### Modal / Blocking Overlay
|
||||
- 必须限制在 shell 内容区内。
|
||||
- Scrim:`rgba(10,9,30,.55)`,取自 Hero 深色。
|
||||
- 主体:白底,16px 圆角,`--rpa-shadow-blocking`。
|
||||
- 阻断操作必须有取消路径。
|
||||
- 高风险确认标题使用 danger,说明包含“原因 + 后果 + 恢复/取消方式”。
|
||||
|
||||
### RPA 托管遮罩
|
||||
- 背景:`--rpa-hosting-bg` + 90% opacity。
|
||||
- 面板:深色 `#111827` 或 `--rpa-nav-panel`。
|
||||
- 进度:`--rpa-primary` 到 `--rpa-tech-blue` 渐变。
|
||||
- 日志:mono 字体,深色日志区,时间戳弱化,当前动作高亮。
|
||||
- 停止按钮:danger 实心,视觉优先级高于“下一步动作”。
|
||||
|
||||
### 标注遮罩
|
||||
- Scrim:深色半透明,主窗口“退后”。
|
||||
- 框选矩形:边框 `--rpa-primary`,填充 `rgba(79,70,229,.16)`。
|
||||
- 当前 bounds:mono 字体,浅色信息底。
|
||||
- 保存失败:danger soft,必须显示原因和恢复动作。
|
||||
|
||||
### Toast / Notification
|
||||
- 成功:复用淘宝开放平台 success `#edffe9 / #4ab933`。
|
||||
- 错误:复用 `#fff2f2 / #d44044`。
|
||||
- 位置:壳内右上角,不能挂到 body。
|
||||
- 动效:opacity + translateY,180–240ms。
|
||||
|
||||
## 10. 页面级主题映射
|
||||
|
||||
| 页面 | 主视觉重点 | 推荐主色 | 组件重点 |
|
||||
|---|---|---|---|
|
||||
| 工作台 | 环境、资产、执行三态 | Primary + success/info/warning | 状态卡、快速入口、闭环步骤条 |
|
||||
| 首次配置 | 检查与恢复 | Info + warning | 步骤侧栏、权限列表、恢复动作区 |
|
||||
| 知识库 | 可索引、可授权、可审计 | Tech blue | 表格、权限 badge、索引状态 |
|
||||
| AI 员工 | 角色与授权边界 | Primary | 员工表格、启动确认、权限说明 |
|
||||
| 标注应用 | 视觉节点与框选 | Primary + tech blue | Tab、节点表、标注遮罩 |
|
||||
| 自动化任务 | 状态机、托管、安全 | Hosting dark + danger | 任务表、托管遮罩、审计日志 |
|
||||
| 设置 | 本地配置与诊断 | Neutral + info | 分组卡、表单、诊断按钮 |
|
||||
|
||||
## 11. 状态色映射
|
||||
|
||||
### 知识库索引状态
|
||||
- `pending`:info soft。
|
||||
- `indexing`:warning soft + spinner。
|
||||
- `ready`:success soft。
|
||||
- `failed`:danger soft + 错误原因 + 重试按钮。
|
||||
|
||||
### AI 员工状态
|
||||
- `idle`:neutral。
|
||||
- `running`:primary。
|
||||
- `waiting_user`:warning。
|
||||
- `failed`:danger。
|
||||
- `disabled`:muted。
|
||||
|
||||
### 自动化任务状态
|
||||
- `queued`:info。
|
||||
- `running`:primary。
|
||||
- `succeeded`:success。
|
||||
- `failed`:danger。
|
||||
- `canceled`:neutral + 审计说明。
|
||||
|
||||
### 许可证状态
|
||||
- `trial`:warning soft。
|
||||
- `active`:success。
|
||||
- `expired`:danger。
|
||||
- `offline_grace`:warning。
|
||||
- `invalid`:danger strong。
|
||||
|
||||
## 12. 图标规则
|
||||
- 使用 Lucide 或同一套 SVG 图标,禁止 emoji。
|
||||
- 导航 icon:20px,stroke 2px。
|
||||
- 状态 chip icon:14–16px。
|
||||
- 卡片标题 icon:16–20px。
|
||||
- 危险/阻断 icon 不只靠颜色,必须搭配文字。
|
||||
|
||||
## 13. 动效规则
|
||||
- 普通 hover:180–220ms。
|
||||
- Tab/导航切换:180ms,颜色/背景过渡即可。
|
||||
- Modal:fade + scale 0.98→1,220ms。
|
||||
- 托管日志追加:新日志淡入 180ms,不自动大幅滚动抢焦点。
|
||||
- 异步超过 300ms:按钮 loading 或 spinner。
|
||||
- 避免淘宝旧式大面积 3D 翻转;RPA 工具应保持稳定可控。
|
||||
|
||||
## 14. 可访问性与安全交互
|
||||
- 点击区域至少 32px,关键按钮至少 40px。
|
||||
- focus-visible 使用 `2px --rpa-primary` ring。
|
||||
- 错误信息必须同时说明原因和恢复动作。
|
||||
- 高风险动作必须二次确认。
|
||||
- ESC 始终停止托管;UI 上持续展示“ESC 紧急停止始终可用”。
|
||||
- 模态/遮罩必须有取消路径。
|
||||
- 颜色不作为唯一状态表达:状态 chip 必须包含文本。
|
||||
|
||||
## 15. 应用到当前 HTML 原型的建议
|
||||
1. 将左侧导航背景从纯 `slate-950` 调整为 `#373942`,hover/底部状态使用 `#2b2d34`。
|
||||
2. 保留 PRD 主色 `#4f46e5` 作为 active 和主按钮;把普通 hover icon 改为 `#5eb5fe`。
|
||||
3. 内容卡片边框统一为 `#e6e6e6`,背景保持白色,减少重阴影。
|
||||
4. 托管遮罩底色改为 `#0a091e`,日志面板使用深 Slate,停止按钮使用 `#d44044`。
|
||||
5. 表格、审计日志、错误码使用更紧凑的 14px/12px 层级,增强工具感。
|
||||
6. 首次配置、权限、托管确认等阻断弹窗使用更强 scrim 和明确的原因/恢复文案。
|
||||
|
||||
## 16. 不采用项
|
||||
- 不采用淘宝/阿里 Logo、橙色品牌识别、原始 banner 图、iconfont 字形。
|
||||
- 不采用 12px 全局正文;RPA 工作站正文以 14px 起步。
|
||||
- 不采用大面积营销 Hero;RPA 主界面以任务状态和可操作数据为核心。
|
||||
- 不采用无边界入口卡片作为主结构;桌面工具需要卡片/表格边界清晰。
|
||||
@ -1,174 +0,0 @@
|
||||
# 淘宝开放平台风格采集卡
|
||||
|
||||
## 1. 采集信息
|
||||
- 来源:`https://open.taobao.com/index.htm`;辅助参考:`https://developer.alibaba.com/en/index.htm`、淘宝开放平台 Color 颜色文档。
|
||||
- 采集日期:2026-06-26。
|
||||
- 视口/页面:首页 HTML、首页公开 CSS、导航/公告/业务入口/能力模块/文档颜色规范。
|
||||
- 可信度:中。`open.taobao.com/index.htm` 当前页面为 Rax 应用壳,静态 HTML 只暴露资源入口;本文件的精确色值主要来自公开 CSS 与文档页源码,布局与组件来自可读取首页结构。
|
||||
|
||||
## 2. 一句话风格定位
|
||||
深色技术导航 + 白底业务入口 + 蓝色交互高亮的 B2B 开放平台风格,强调开发者可信、信息密度和平台能力展示。
|
||||
|
||||
## 3. 风格关键词
|
||||
- 开发者平台感:顶部深色导航 `#373942`,二级菜单 `#2b2d34`,适合承载控制台、文档、解决方案等技术入口。
|
||||
- 蓝色高亮交互:链接 hover、菜单标题、查看更多使用 `#5eb5fe` / `#6cb5f4`,形成“技术服务”而非电商促销的视觉语气。
|
||||
- 白底轻量内容:业务卡片、公告、能力模块主要使用白底、灰字、细分割线,信息密度高但克制。
|
||||
- 图片型 Hero:首屏轮播使用 1920 宽大图,外层深背景 `#0a091e`,品牌视觉主要交给 banner 图承担。
|
||||
- 低圆角、轻阴影:组件多为直角或小圆角,通知/菜单使用 2–4px 圆角,阴影只在浮层中使用。
|
||||
|
||||
## 4. 配色系统
|
||||
| Token | Hex/RGB | 用途 | 观察证据 |
|
||||
|---|---:|---|---|
|
||||
| color-nav-bg | `#373942` | 顶部/侧边深色导航背景 | `.openplatform-nav { background:#373942 }` |
|
||||
| color-nav-panel | `#2b2d34` | hover 状态、二级菜单背景、激活导航 | `.top-openplatform-nav ul li.active/hover` 与 `.sub-nav` |
|
||||
| color-hero-bg | `#0a091e` | 首页轮播深色承托背景 | `.slide { background-color:#0a091e }` |
|
||||
| color-primary | `#5eb5fe` | 菜单标题、链接 hover、阅读更多 | `.sub-nav dl dt`、`.page-tips a.read-more` |
|
||||
| color-primary-hover | `#6cb5f4` | 顶部菜单项 hover | `.open-nav-menu > li > a:hover` |
|
||||
| color-tech-blue | `#28a3ef` | 技术能力模块数字/步骤高亮 | `.cols-3 .grid .step-1` |
|
||||
| color-text-main | `#333333` | 主要正文/图标 | `.cols-1 i`、`.bottom-item` |
|
||||
| color-text-heading | `#444444` | 业务入口标题 | `.cols-1 h4` |
|
||||
| color-text-muted | `#666666` | 公告、段落、弱信息 | `.page-tips a`、`.cols-1 p` |
|
||||
| color-text-subtle | `#7c7c7c` | 次级说明文本 | `.cols-3 p` |
|
||||
| color-nav-text | `#e5e9ee` | 深色导航主文字/Logo | `.logo-container h1 a`、`.top-openplatform-nav a` |
|
||||
| color-nav-muted | `#a3a3a3` | 二级菜单普通链接 | `.sub-nav dl dd a` |
|
||||
| color-border | `#e6e6e6` | 公告底线、表格分割线 | `.page-tips`、`.table-bordered` |
|
||||
| color-nav-border | `#383a45` | 深色菜单内部分割线 | `.sub-nav dl dd` |
|
||||
| color-success-bg | `#edffe9` | 成功通知背景 | `.open-success` |
|
||||
| color-success | `#4ab933` | 成功通知文字 | `.open-success` |
|
||||
| color-error-bg | `#fff2f2` | 错误通知背景 | `.open-alert` |
|
||||
| color-error-border | `#ffe3e0` | 错误通知边框 | `.open-alert` |
|
||||
| color-danger | `#d44044` | 通知红点 hover / 强提醒 | `.notify-container.has-message:hover` |
|
||||
|
||||
## 5. 字体与字号
|
||||
| 层级 | Font | Size | Weight | Line-height | 说明 |
|
||||
|---|---|---:|---:|---:|---|
|
||||
| Body | 系统 sans-serif / Bootstrap 默认 | `12px` | 400 | 默认 | 首页 CSS 明确 `body{font-size:12px}`,偏传统门户密度。 |
|
||||
| Nav | 系统 sans-serif | `14px` | 400 | `64px` | 顶部导航高 64,文字垂直居中。 |
|
||||
| Logo | iconfont + sans-serif | `18px` | 400 | `64px` | Logo 文案不加粗,依靠图标与深色背景建立品牌识别。 |
|
||||
| Section H3 | 系统 sans-serif | `22px` | 400/默认 | 默认 | 模块标题使用较大字号但非粗重风格。 |
|
||||
| Business H4 | 系统 sans-serif | `20px` | 400/默认 | 默认 | 四列业务入口标题。 |
|
||||
| Paragraph | 系统 sans-serif | `12–14px` | 400 | `1.8–2` | 段落行高较松,缓解小字号带来的拥挤。 |
|
||||
| Iconfont | Alibaba iconfont | `16–105px` | normal | 1 | 大图标用于业务入口和能力模块。 |
|
||||
|
||||
## 6. 布局与间距
|
||||
- 页面宽度:核心容器 `max-width:1170px`,文档页内容 `990px`。
|
||||
- 顶部导航:高度 `64px`,深色通栏,Logo 左置,主导航横排,登录/搜索右置。
|
||||
- 首页 Hero:全宽轮播,图片 1800–1920px 级别,背景深色兜底。
|
||||
- 公告条:Hero 下方 `15px` 上下外边距,底部 `1px #e6e6e6` 分割线。
|
||||
- 业务入口:四列栅格 `.col-md-3`,容器左右内边距 `45px`,每项图标/图片 + 标题 + 描述。
|
||||
- Section spacing:模块常用 `margin-top:20–80px`、`margin-bottom:40–60px`。
|
||||
- 信息密度:导航和表格偏紧凑,营销/能力模块留白较多。
|
||||
|
||||
## 7. 组件拆解
|
||||
|
||||
### Nav
|
||||
- 尺寸:高 `64px`,主导航项左右 padding `20px`。
|
||||
- 背景:默认 `#373942`,hover/active `#2b2d34`。
|
||||
- 文本:默认 `#e5e9ee`,菜单子项 `#a3a3a3`,标题/hover `#5eb5fe`。
|
||||
- 下拉:深色大面板,顶部贴合导航,padding `25px 20px 20px`,内部按 `dl/dt/dd` 分组。
|
||||
- 动效:hover 展开,opacity 0.3s;箭头旋转 180 度,0.5s。
|
||||
- 可复用规则:适合控制台型产品的顶栏或左侧导航;导航背景不要纯黑,使用带蓝灰倾向的深 Slate。
|
||||
|
||||
### Button / CTA
|
||||
- 首页强 CTA 不突出;更多使用链接、图片卡片、`btn-knowmore`。
|
||||
- `btn-knowmore`:高 `44px`,透明蓝背景 `rgba(80,133,177,0.8)`,边框 `#3199f4`,hover 背景 `rgba(49,153,244,0.8)`。
|
||||
- 可复用规则:主按钮可使用蓝色描边/半透明填充,不要大面积淘宝橙;橙色只适合品牌点缀或营销态。
|
||||
|
||||
### Card / Business Entry
|
||||
- 结构:图标/图片在上,`h4` 标题,`p` 描述。
|
||||
- 背景:白底或透明,无明显卡片边框。
|
||||
- Hover:整项文字/图标变蓝 `#5eb5fe`。
|
||||
- 尺寸:图形资源约 `135px × 85px`;标题 `20px`。
|
||||
- 可复用规则:入口卡片应轻边界、重图标,避免厚重阴影。
|
||||
|
||||
### Announcement Bar
|
||||
- 结构:公告图标 + 多条横向链接 + “查看更多”。
|
||||
- 颜色:普通链接 `#666`,查看更多 `#5eb5fe`。
|
||||
- 行为:文本单行截断,宽度约 `16em`,适合密集公告。
|
||||
|
||||
### Tech Grid
|
||||
- 形态:蜂窝/网格图形背景,hover 翻转 `rotateY(180deg)`。
|
||||
- 高亮:数字/步骤用 `#28a3ef`,hover 后白字。
|
||||
- 动效:transform 0.3s ease-in-out。
|
||||
- 可复用规则:可用于“能力矩阵”“流程步骤”“开放能力”展示。
|
||||
|
||||
### Notification
|
||||
- 浮层:高 `46px`,顶部 fixed,阴影 `0 2px 5px rgba(0,0,0,.26)`,圆角 `2px`。
|
||||
- 成功:`#edffe9` 背景、`#dcf9d6` 边框、`#4ab933` 文本。
|
||||
- 错误:`#fff2f2` 背景、`#ffe3e0` 边框、red 文本。
|
||||
|
||||
## 8. 圆角、边框、阴影、质感
|
||||
- Radius scale:`2px` 用于通知,`3px` 用于选中胶囊,`4px` 用于下拉菜单;整体偏低圆角。
|
||||
- Border:浅色分割线 `#e6e6e6`;深色菜单分割线 `#383a45`。
|
||||
- Shadow:只在通知和下拉菜单中使用;菜单阴影 `1px 1px 5px rgba(0,0,0,.75)`,通知阴影 `0 2px 5px rgba(0,0,0,.26)`。
|
||||
- Texture:部分模块使用背景图纹理,不是纯色卡片风格;复用时建议用极淡网格/渐变替代老旧纹理图。
|
||||
|
||||
## 9. 动效与交互
|
||||
- 顶部下拉:hover 展开,opacity 0.3s ease-in-out。
|
||||
- 箭头旋转:0.5s。
|
||||
- 搜索框:border-color 0.3s,input width 0.3s。
|
||||
- 技术网格:hover 翻转,transform 0.3s ease-in-out。
|
||||
- 云环境卡片:hover 后内容上移/淡入,all 0.3s。
|
||||
- 复用建议:保留 0.2–0.3s 的快速反馈;避免大面积 3D 翻转,可改为轻微 translate/opacity 以现代化。
|
||||
|
||||
## 10. 可复用主题 Tokens
|
||||
```css
|
||||
:root {
|
||||
--tbop-bg: #ffffff;
|
||||
--tbop-bg-muted: #f7f8fa;
|
||||
--tbop-nav-bg: #373942;
|
||||
--tbop-nav-panel: #2b2d34;
|
||||
--tbop-hero-bg: #0a091e;
|
||||
|
||||
--tbop-primary: #5eb5fe;
|
||||
--tbop-primary-hover: #6cb5f4;
|
||||
--tbop-tech-blue: #28a3ef;
|
||||
--tbop-link: #5eb5fe;
|
||||
|
||||
--tbop-text: #333333;
|
||||
--tbop-text-heading: #444444;
|
||||
--tbop-text-muted: #666666;
|
||||
--tbop-text-subtle: #7c7c7c;
|
||||
--tbop-text-inverse: #e5e9ee;
|
||||
--tbop-text-inverse-muted: #a3a3a3;
|
||||
|
||||
--tbop-border: #e6e6e6;
|
||||
--tbop-border-dark: #383a45;
|
||||
|
||||
--tbop-success: #4ab933;
|
||||
--tbop-success-bg: #edffe9;
|
||||
--tbop-success-border: #dcf9d6;
|
||||
--tbop-error: #d44044;
|
||||
--tbop-error-bg: #fff2f2;
|
||||
--tbop-error-border: #ffe3e0;
|
||||
|
||||
--tbop-font-sans: Arial, "Helvetica Neue", Helvetica, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
--tbop-font-size-xs: 12px;
|
||||
--tbop-font-size-sm: 14px;
|
||||
--tbop-font-size-md: 20px;
|
||||
--tbop-font-size-lg: 22px;
|
||||
|
||||
--tbop-radius-xs: 2px;
|
||||
--tbop-radius-sm: 3px;
|
||||
--tbop-radius-md: 4px;
|
||||
|
||||
--tbop-shadow-menu: 1px 1px 5px rgba(0, 0, 0, 0.75);
|
||||
--tbop-shadow-notify: 0 2px 5px rgba(0, 0, 0, 0.26);
|
||||
|
||||
--tbop-nav-height: 64px;
|
||||
--tbop-container: 1170px;
|
||||
--tbop-doc-container: 990px;
|
||||
--tbop-transition-fast: 0.2s ease-in-out;
|
||||
--tbop-transition-normal: 0.3s ease-in-out;
|
||||
}
|
||||
```
|
||||
|
||||
## 11. 适合用于 / 不适合用于
|
||||
- 适合:开放平台、开发者门户、插件市场、企业 SaaS 控制台、API 文档中心、技术生态官网。
|
||||
- 不适合:强消费转化型落地页、年轻化社交产品、移动端优先 C 端 App、需要大量圆角/玻璃拟态的现代品牌页面。
|
||||
|
||||
## 12. 复刻注意事项
|
||||
- 保留:深色技术导航、蓝色交互高亮、白底四列能力入口、公告条、能力矩阵、低圆角与轻阴影。
|
||||
- 避免:直接复制淘宝/阿里 Logo、banner 原图、iconfont 字形、具体文案和品牌名称。
|
||||
- 现代化变体:保持 `#373942 + #5eb5fe` 的骨架,把小字号从 12px 提升到 14px,把老式图片纹理替换为浅蓝渐变/网格背景,把 3D 翻转改为轻微浮起与淡入。
|
||||
- 用于当前 RPA 工作站原型时:可将左侧导航改成 `#373942` 深 Slate,激活/hover 用 `#2b2d34`,图标高亮用 `#5eb5fe`,内容区继续保持白底与 `#e6e6e6` 分割线。
|
||||
Loading…
x
Reference in New Issue
Block a user