Commit 89a3b72c by luoqi

style(web): 卡片边框 slate-200 → slate-100 发丝线 — 降噪去"框感"(只动边框色)

现代清爽审美的常见做法:保留 1px 边框但压到极低对比(~6%),靠 bg 明度差+阴影分区。
全局 21 处 border-slate-200 统一软化为 slate-100,结构/阴影/间距/标签/文字一律不动。

web tsc 0。仅本地,未部署。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
parent d66dc855
...@@ -69,7 +69,7 @@ function EntryResolver() { ...@@ -69,7 +69,7 @@ function EntryResolver() {
// ③ 空工作台:左栏可用(调筛选自己找人),右侧整体空态 // ③ 空工作台:左栏可用(调筛选自己找人),右侧整体空态
return ( return (
<div className="flex h-screen flex-col overflow-hidden bg-slate-50"> <div className="flex h-screen flex-col overflow-hidden bg-slate-50">
<header className="flex h-12 flex-none items-center gap-2 border-b border-slate-200 bg-white px-4"> <header className="flex h-12 flex-none items-center gap-2 border-b border-slate-100 bg-white px-4">
<span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white"> <span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white">
PAC PAC
</span> </span>
...@@ -89,7 +89,7 @@ function EntryResolver() { ...@@ -89,7 +89,7 @@ function EntryResolver() {
<button <button
type="button" type="button"
onClick={() => window.location.reload()} onClick={() => window.location.reload()}
className="inline-flex items-center gap-1.5 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-[12.5px] text-slate-600 hover:bg-slate-50" className="inline-flex items-center gap-1.5 rounded-md border border-slate-100 bg-white px-3 py-1.5 text-[12.5px] text-slate-600 hover:bg-slate-50"
> >
<RefreshCw className="h-3.5 w-3.5" /> <RefreshCw className="h-3.5 w-3.5" />
刷新 刷新
......
...@@ -85,7 +85,7 @@ function resultSummary(result: unknown): string { ...@@ -85,7 +85,7 @@ function resultSummary(result: unknown): string {
function ToolCallView({ step }: { step: ToolStep }) { function ToolCallView({ step }: { step: ToolStep }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
return ( return (
<div className="overflow-hidden rounded-lg border border-slate-200 bg-slate-50/70"> <div className="overflow-hidden rounded-lg border border-slate-100 bg-slate-50/70">
<button <button
type="button" type="button"
onClick={() => setOpen((o) => !o)} onClick={() => setOpen((o) => !o)}
...@@ -96,7 +96,7 @@ function ToolCallView({ step }: { step: ToolStep }) { ...@@ -96,7 +96,7 @@ function ToolCallView({ step }: { step: ToolStep }) {
/> />
<Wrench className="h-3.5 w-3.5 flex-none text-slate-400" /> <Wrench className="h-3.5 w-3.5 flex-none text-slate-400" />
<span className="flex-none text-[12px] text-slate-500">调用工具</span> <span className="flex-none text-[12px] text-slate-500">调用工具</span>
<code className="flex-none rounded border border-slate-200 bg-white px-1.5 py-0.5 font-mono text-[11.5px] text-slate-700"> <code className="flex-none rounded border border-slate-100 bg-white px-1.5 py-0.5 font-mono text-[11.5px] text-slate-700">
{step.tool} {step.tool}
</code> </code>
<span className="ml-1 truncate text-[11px] text-slate-400"> <span className="ml-1 truncate text-[11px] text-slate-400">
...@@ -113,7 +113,7 @@ function ToolCallView({ step }: { step: ToolStep }) { ...@@ -113,7 +113,7 @@ function ToolCallView({ step }: { step: ToolStep }) {
</span> </span>
</button> </button>
{open && ( {open && (
<div className="space-y-2 border-t border-slate-200/70 px-3 pb-3 pt-1"> <div className="space-y-2 border-t border-slate-100/70 px-3 pb-3 pt-1">
<CodeBlock label="入参" code={pretty(step.args) || '{}'} /> <CodeBlock label="入参" code={pretty(step.args) || '{}'} />
{step.result !== undefined && <CodeBlock label="返回" code={pretty(step.result)} muted />} {step.result !== undefined && <CodeBlock label="返回" code={pretty(step.result)} muted />}
</div> </div>
...@@ -130,7 +130,7 @@ function CodeBlock({ label, code, muted }: { label: string; code: string; muted? ...@@ -130,7 +130,7 @@ function CodeBlock({ label, code, muted }: { label: string; code: string; muted?
</div> </div>
<pre <pre
className={cn( className={cn(
'overflow-x-auto rounded-md border border-slate-200 bg-white px-3 py-2 text-[11.5px] leading-relaxed text-slate-600', 'overflow-x-auto rounded-md border border-slate-100 bg-white px-3 py-2 text-[11.5px] leading-relaxed text-slate-600',
muted && 'max-h-44 overflow-y-auto', muted && 'max-h-44 overflow-y-auto',
)} )}
> >
...@@ -160,7 +160,7 @@ function Markdown({ text }: { text: string }) { ...@@ -160,7 +160,7 @@ function Markdown({ text }: { text: string }) {
{children} {children}
</a> </a>
), ),
hr: () => <hr className="my-3 border-slate-200" />, hr: () => <hr className="my-3 border-slate-100" />,
blockquote: ({ children }) => ( blockquote: ({ children }) => (
<blockquote className="my-2 border-l-2 border-teal-300 bg-teal-50/40 py-1 pl-3 text-slate-600"> <blockquote className="my-2 border-l-2 border-teal-300 bg-teal-50/40 py-1 pl-3 text-slate-600">
{children} {children}
...@@ -175,7 +175,7 @@ function Markdown({ text }: { text: string }) { ...@@ -175,7 +175,7 @@ function Markdown({ text }: { text: string }) {
</code> </code>
), ),
pre: ({ children }) => ( pre: ({ children }) => (
<pre className="my-2 overflow-x-auto rounded-md border border-slate-200 bg-slate-50 p-3 text-[12px]"> <pre className="my-2 overflow-x-auto rounded-md border border-slate-100 bg-slate-50 p-3 text-[12px]">
{children} {children}
</pre> </pre>
), ),
...@@ -186,9 +186,9 @@ function Markdown({ text }: { text: string }) { ...@@ -186,9 +186,9 @@ function Markdown({ text }: { text: string }) {
), ),
thead: ({ children }) => <thead className="bg-slate-50">{children}</thead>, thead: ({ children }) => <thead className="bg-slate-50">{children}</thead>,
th: ({ children }) => ( th: ({ children }) => (
<th className="border border-slate-200 px-2 py-1 text-left font-medium text-slate-600">{children}</th> <th className="border border-slate-100 px-2 py-1 text-left font-medium text-slate-600">{children}</th>
), ),
td: ({ children }) => <td className="border border-slate-200 px-2 py-1 text-slate-700">{children}</td>, td: ({ children }) => <td className="border border-slate-100 px-2 py-1 text-slate-700">{children}</td>,
}} }}
> >
{text} {text}
...@@ -335,7 +335,7 @@ function ArtifactView({ artifact }: { artifact: Artifact }) { ...@@ -335,7 +335,7 @@ function ArtifactView({ artifact }: { artifact: Artifact }) {
}; };
return ( return (
<div className="overflow-hidden rounded-lg border border-slate-200 bg-white shadow-sm"> <div className="overflow-hidden rounded-lg border border-slate-100 bg-white shadow-sm">
<div className="flex items-center gap-1.5 border-b border-slate-100 bg-slate-50/60 px-3 py-1.5"> <div className="flex items-center gap-1.5 border-b border-slate-100 bg-slate-50/60 px-3 py-1.5">
<LayoutTemplate className="h-3.5 w-3.5 text-teal-600" /> <LayoutTemplate className="h-3.5 w-3.5 text-teal-600" />
<span className="text-[11.5px] font-medium text-slate-500">{artifact.title || '可视化卡片'}</span> <span className="text-[11.5px] font-medium text-slate-500">{artifact.title || '可视化卡片'}</span>
...@@ -358,7 +358,7 @@ function ArtifactView({ artifact }: { artifact: Artifact }) { ...@@ -358,7 +358,7 @@ function ArtifactView({ artifact }: { artifact: Artifact }) {
createPortal( createPortal(
<div className="fixed inset-0 z-[70] flex items-center justify-center p-4"> <div className="fixed inset-0 z-[70] flex items-center justify-center p-4">
<div className="absolute inset-0 bg-black/40" onClick={() => setExpanded(false)} /> <div className="absolute inset-0 bg-black/40" onClick={() => setExpanded(false)} />
<div className="relative z-10 flex h-[min(86vh,920px)] w-[min(980px,94vw)] flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-2xl"> <div className="relative z-10 flex h-[min(86vh,920px)] w-[min(980px,94vw)] flex-col overflow-hidden rounded-xl border border-slate-100 bg-white shadow-2xl">
<div className="flex flex-none items-center gap-1.5 border-b border-slate-100 bg-slate-50/60 px-3 py-2"> <div className="flex flex-none items-center gap-1.5 border-b border-slate-100 bg-slate-50/60 px-3 py-2">
<LayoutTemplate className="h-4 w-4 text-teal-600" /> <LayoutTemplate className="h-4 w-4 text-teal-600" />
<span className="text-[12.5px] font-medium text-slate-600">{artifact.title || '可视化卡片'}</span> <span className="text-[12.5px] font-medium text-slate-600">{artifact.title || '可视化卡片'}</span>
...@@ -457,14 +457,14 @@ function ModelSelect({ ...@@ -457,14 +457,14 @@ function ModelSelect({
type="button" type="button"
disabled={disabled} disabled={disabled}
onClick={() => setOpen((o) => !o)} onClick={() => setOpen((o) => !o)}
className="inline-flex items-center gap-1.5 rounded-md border border-slate-200 bg-white px-2.5 py-1.5 text-[12.5px] text-slate-700 transition-colors hover:bg-slate-50 disabled:opacity-50" className="inline-flex items-center gap-1.5 rounded-md border border-slate-100 bg-white px-2.5 py-1.5 text-[12.5px] text-slate-700 transition-colors hover:bg-slate-50 disabled:opacity-50"
> >
<span className="h-1.5 w-1.5 rounded-full bg-emerald-500" /> <span className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
{label} {label}
<ChevronDown className={cn('h-3.5 w-3.5 text-slate-400 transition-transform', open && 'rotate-180')} /> <ChevronDown className={cn('h-3.5 w-3.5 text-slate-400 transition-transform', open && 'rotate-180')} />
</button> </button>
{open && ( {open && (
<div className="absolute right-0 z-50 mt-1 w-40 rounded-lg border border-slate-200 bg-white py-1 shadow-lg"> <div className="absolute right-0 z-50 mt-1 w-40 rounded-lg border border-slate-100 bg-white py-1 shadow-lg">
{MODELS.map((m) => ( {MODELS.map((m) => (
<button <button
key={m.value} key={m.value}
...@@ -630,7 +630,7 @@ export function AssistantChat({ ...@@ -630,7 +630,7 @@ export function AssistantChat({
return ( return (
<div className={cn('flex flex-col bg-slate-50', isWidget ? 'h-full' : 'h-[100dvh]')}> <div className={cn('flex flex-col bg-slate-50', isWidget ? 'h-full' : 'h-[100dvh]')}>
{/* Header */} {/* Header */}
<header className="flex-none border-b border-slate-200 bg-white/90 backdrop-blur"> <header className="flex-none border-b border-slate-100 bg-white/90 backdrop-blur">
<div <div
className={cn( className={cn(
'mx-auto flex items-center gap-2.5', 'mx-auto flex items-center gap-2.5',
...@@ -681,7 +681,7 @@ export function AssistantChat({ ...@@ -681,7 +681,7 @@ export function AssistantChat({
key={ex} key={ex}
type="button" type="button"
onClick={() => fire(ex)} onClick={() => fire(ex)}
className="rounded-full border border-slate-200 bg-white px-3 py-1.5 text-[11.5px] text-slate-600 transition-colors hover:border-teal-300 hover:bg-teal-50/50 hover:text-teal-700" className="rounded-full border border-slate-100 bg-white px-3 py-1.5 text-[11.5px] text-slate-600 transition-colors hover:border-teal-300 hover:bg-teal-50/50 hover:text-teal-700"
> >
{ex} {ex}
</button> </button>
...@@ -701,9 +701,9 @@ export function AssistantChat({ ...@@ -701,9 +701,9 @@ export function AssistantChat({
</div> </div>
{/* Composer */} {/* Composer */}
<div className="flex-none border-t border-slate-200 bg-white"> <div className="flex-none border-t border-slate-100 bg-white">
<div className="mx-auto max-w-3xl px-4 py-3"> <div className="mx-auto max-w-3xl px-4 py-3">
<div className="flex items-end gap-2 rounded-xl border border-slate-200 bg-white px-3 py-2 transition-all focus-within:border-teal-300 focus-within:ring-2 focus-within:ring-teal-200"> <div className="flex items-end gap-2 rounded-xl border border-slate-100 bg-white px-3 py-2 transition-all focus-within:border-teal-300 focus-within:ring-2 focus-within:ring-teal-200">
<textarea <textarea
ref={taRef} ref={taRef}
rows={1} rows={1}
......
...@@ -53,7 +53,7 @@ export function AssistantWidget() { ...@@ -53,7 +53,7 @@ export function AssistantWidget() {
<div <div
style={winPos ? { left: winPos.x, top: winPos.y } : undefined} style={winPos ? { left: winPos.x, top: winPos.y } : undefined}
className={cn( className={cn(
'fixed z-[60] flex flex-col overflow-hidden rounded-xl border border-slate-200 shadow-2xl', 'fixed z-[60] flex flex-col overflow-hidden rounded-xl border border-slate-100 shadow-2xl',
!winPos && 'bottom-4 right-4', !winPos && 'bottom-4 right-4',
'h-[620px] max-h-[78vh] w-[400px] max-w-[calc(100vw-2rem)]', 'h-[620px] max-h-[78vh] w-[400px] max-w-[calc(100vw-2rem)]',
'transition-[opacity,transform] duration-150', 'transition-[opacity,transform] duration-150',
......
...@@ -141,7 +141,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -141,7 +141,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
'flex flex-col items-start gap-0.5 rounded-md border px-2.5 py-1.5 text-left transition-all', 'flex flex-col items-start gap-0.5 rounded-md border px-2.5 py-1.5 text-left transition-all',
role === r.key role === r.key
? 'border-teal-400 bg-teal-50/60 ring-1 ring-teal-200' ? 'border-teal-400 bg-teal-50/60 ring-1 ring-teal-200'
: 'border-slate-200 hover:border-teal-300', : 'border-slate-100 hover:border-teal-300',
)} )}
> >
<span className="text-[12.5px] font-semibold text-slate-800">{r.nameZh}</span> <span className="text-[12.5px] font-semibold text-slate-800">{r.nameZh}</span>
...@@ -152,7 +152,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -152,7 +152,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
</div> </div>
{/* ② 选客服 */} {/* ② 选客服 */}
<div className="rounded-lg border border-slate-200 p-3"> <div className="rounded-lg border border-slate-100 p-3">
<div className="mb-2 flex items-center justify-between"> <div className="mb-2 flex items-center justify-between">
<div className="text-[12px] font-medium text-slate-600"> <div className="text-[12px] font-medium text-slate-600">
② 选客服 — 以其真实身份 + 上面的「{roleNameZh(role)}」权限登录 ② 选客服 — 以其真实身份 + 上面的「{roleNameZh(role)}」权限登录
...@@ -174,7 +174,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -174,7 +174,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
'rounded-full border px-2.5 py-0.5 text-[11px] transition-colors', 'rounded-full border px-2.5 py-0.5 text-[11px] transition-colors',
tenantFilter === t.k tenantFilter === t.k
? 'border-teal-400 bg-teal-50 text-teal-700' ? 'border-teal-400 bg-teal-50 text-teal-700'
: 'border-slate-200 text-slate-500 hover:border-teal-300', : 'border-slate-100 text-slate-500 hover:border-teal-300',
)} )}
> >
{t.n} {t.n}
...@@ -184,7 +184,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -184,7 +184,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
value={query} value={query}
onChange={(e) => setQuery(e.target.value)} onChange={(e) => setQuery(e.target.value)}
placeholder="搜客服姓名…" placeholder="搜客服姓名…"
className="ml-auto w-40 rounded-md border border-slate-200 px-2.5 py-1 text-[12px] outline-none focus:border-teal-400" className="ml-auto w-40 rounded-md border border-slate-100 px-2.5 py-1 text-[12px] outline-none focus:border-teal-400"
/> />
</div> </div>
...@@ -204,7 +204,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -204,7 +204,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
'flex w-full items-center justify-between gap-2 rounded-md border px-2.5 py-1.5 text-left transition-all', 'flex w-full items-center justify-between gap-2 rounded-md border px-2.5 py-1.5 text-left transition-all',
loading loading
? 'border-teal-400 ring-2 ring-teal-200' ? 'border-teal-400 ring-2 ring-teal-200'
: 'border-slate-200 hover:border-teal-400 hover:bg-teal-50/40', : 'border-slate-100 hover:border-teal-400 hover:bg-teal-50/40',
busy && !loading && 'opacity-50', busy && !loading && 'opacity-50',
)} )}
> >
...@@ -251,7 +251,7 @@ export function MockLoginDialog({ open }: { open: boolean }) { ...@@ -251,7 +251,7 @@ export function MockLoginDialog({ open }: { open: boolean }) {
'group flex flex-col items-start gap-1 rounded-md border bg-white px-3 py-2 text-left transition-all', 'group flex flex-col items-start gap-1 rounded-md border bg-white px-3 py-2 text-left transition-all',
loading loading
? 'border-teal-400 ring-2 ring-teal-200' ? 'border-teal-400 ring-2 ring-teal-200'
: 'border-slate-200 hover:border-teal-400 hover:bg-teal-50/40', : 'border-slate-100 hover:border-teal-400 hover:bg-teal-50/40',
busy && !loading && 'opacity-50', busy && !loading && 'opacity-50',
)} )}
> >
......
...@@ -275,7 +275,7 @@ function TargetTimelineRow({ chain }: { chain: Chain }) { ...@@ -275,7 +275,7 @@ function TargetTimelineRow({ chain }: { chain: Chain }) {
function HistoryStrip({ chains }: { chains: Chain[] }) { function HistoryStrip({ chains }: { chains: Chain[] }) {
return ( return (
<div className="rounded-lg border border-slate-200 bg-slate-50/60 px-3 py-2"> <div className="rounded-lg border border-slate-100 bg-slate-50/60 px-3 py-2">
<div className="flex items-center justify-between mb-1.5"> <div className="flex items-center justify-between mb-1.5">
<div className="flex items-center gap-1.5 text-[11px] text-slate-500"> <div className="flex items-center gap-1.5 text-[11px] text-slate-500">
<svg viewBox="0 0 24 24" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2"> <svg viewBox="0 0 24 24" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2">
...@@ -298,7 +298,7 @@ function HistoryChainCard({ chain }: { chain: Chain }) { ...@@ -298,7 +298,7 @@ function HistoryChainCard({ chain }: { chain: Chain }) {
const lastNode = chain.nodes[4]; const lastNode = chain.nodes[4];
const currNode = chain.nodes[chain.currentStage - 1]; const currNode = chain.nodes[chain.currentStage - 1];
return ( return (
<div className="bg-white rounded border border-slate-200 px-2.5 py-1.5 flex items-center gap-2"> <div className="bg-white rounded border border-slate-100 px-2.5 py-1.5 flex items-center gap-2">
<span <span
className={cn( className={cn(
'flex-none w-5 h-5 rounded-full flex items-center justify-center text-[10px] font-bold', 'flex-none w-5 h-5 rounded-full flex items-center justify-center text-[10px] font-bold',
...@@ -460,7 +460,7 @@ const TONE_WRAP: Record<ChainTone, string> = { ...@@ -460,7 +460,7 @@ const TONE_WRAP: Record<ChainTone, string> = {
amber: 'bg-amber-50/40 border-amber-200/70', amber: 'bg-amber-50/40 border-amber-200/70',
sky: 'bg-sky-50/40 border-sky-200/70', sky: 'bg-sky-50/40 border-sky-200/70',
emerald: 'bg-emerald-50/40 border-emerald-200/70', emerald: 'bg-emerald-50/40 border-emerald-200/70',
slate: 'bg-slate-50/40 border-slate-200/70', slate: 'bg-slate-50/40 border-slate-100/70',
}; };
const TONE_DOT: Record<ChainTone, string> = { const TONE_DOT: Record<ChainTone, string> = {
rose: 'bg-rose-500 text-white', rose: 'bg-rose-500 text-white',
...@@ -495,7 +495,7 @@ export function ChainDetailView({ chains }: { chains: Chain[] }) { ...@@ -495,7 +495,7 @@ export function ChainDetailView({ chains }: { chains: Chain[] }) {
)} )}
{/* 下半:全部列表(点击切换上面的明细)*/} {/* 下半:全部列表(点击切换上面的明细)*/}
<div className="pt-3 border-t border-slate-200"> <div className="pt-3 border-t border-slate-100">
<div className="text-[11px] text-slate-500 mb-2"> <div className="text-[11px] text-slate-500 mb-2">
全部 {chains.length} 条治疗链 全部 {chains.length} 条治疗链
</div> </div>
...@@ -548,7 +548,7 @@ function ChainListItem({ ...@@ -548,7 +548,7 @@ function ChainListItem({
'text-left rounded-md border px-2.5 py-2 transition', 'text-left rounded-md border px-2.5 py-2 transition',
active active
? activeRing[v.tone] ? activeRing[v.tone]
: 'border-slate-200 bg-white hover:bg-slate-50', : 'border-slate-100 bg-white hover:bg-slate-50',
)} )}
> >
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
......
...@@ -107,7 +107,7 @@ export function Drawer({ ...@@ -107,7 +107,7 @@ export function Drawer({
const T = tone(f.tone); const T = tone(f.tone);
const { tag, text } = cleanPersonaValue(f.value); const { tag, text } = cleanPersonaValue(f.value);
return ( return (
<div key={f.key} className="relative rounded-md border border-slate-200 p-3"> <div key={f.key} className="relative rounded-md border border-slate-100 p-3">
{/* 右上角 ? hover 看算法说明 */} {/* 右上角 ? hover 看算法说明 */}
<PersonaFeatureHover featureKey={f.key}> <PersonaFeatureHover featureKey={f.key}>
<span <span
...@@ -141,7 +141,7 @@ export function Drawer({ ...@@ -141,7 +141,7 @@ export function Drawer({
<div className="fixed inset-0 z-40 flex" onClick={onClose}> <div className="fixed inset-0 z-40 flex" onClick={onClose}>
<div className="flex-1 bg-slate-900/30" /> <div className="flex-1 bg-slate-900/30" />
<aside <aside
className={cn('max-w-[92vw] bg-white shadow-2xl border-l border-slate-200 flex flex-col', width)} className={cn('max-w-[92vw] bg-white shadow-2xl border-l border-slate-100 flex flex-col', width)}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<header className="px-5 py-3.5 border-b border-slate-100 flex items-center justify-between flex-none"> <header className="px-5 py-3.5 border-b border-slate-100 flex items-center justify-between flex-none">
...@@ -243,7 +243,7 @@ function ImageFactsView({ facts }: { facts: AdaptedFact[] }) { ...@@ -243,7 +243,7 @@ function ImageFactsView({ facts }: { facts: AdaptedFact[] }) {
: ((c.tooth_position as string | undefined) ?? null); : ((c.tooth_position as string | undefined) ?? null);
const encId = c.encounter_external_id as string | undefined; const encId = c.encounter_external_id as string | undefined;
return ( return (
<div key={f.id} className="rounded-md border border-slate-200 p-3"> <div key={f.id} className="rounded-md border border-slate-100 p-3">
<div className="flex items-center justify-between mb-1.5"> <div className="flex items-center justify-between mb-1.5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Chip tone="violet" size="xs"> <Chip tone="violet" size="xs">
...@@ -285,7 +285,7 @@ function ImageFactsView({ facts }: { facts: AdaptedFact[] }) { ...@@ -285,7 +285,7 @@ function ImageFactsView({ facts }: { facts: AdaptedFact[] }) {
function CBCTImageView() { function CBCTImageView() {
return ( return (
<div className="space-y-3"> <div className="space-y-3">
<div className="aspect-[4/3] rounded-lg border border-slate-200 bg-slate-900 relative overflow-hidden"> <div className="aspect-[4/3] rounded-lg border border-slate-100 bg-slate-900 relative overflow-hidden">
<div <div
className="absolute inset-0" className="absolute inset-0"
style={{ backgroundImage: 'radial-gradient(circle at 50% 60%, #475569 0%, #0f172a 50%, #000 100%)' }} style={{ backgroundImage: 'radial-gradient(circle at 50% 60%, #475569 0%, #0f172a 50%, #000 100%)' }}
......
...@@ -69,7 +69,7 @@ export function EmrSoapView({ facts }: { facts: AdaptedFact[] }) { ...@@ -69,7 +69,7 @@ export function EmrSoapView({ facts }: { facts: AdaptedFact[] }) {
<button <button
onClick={prev} onClick={prev}
aria-label="上一次接诊" aria-label="上一次接诊"
className="inline-flex items-center justify-center w-7 h-7 rounded-md border border-slate-200 bg-white hover:bg-slate-50 hover:border-slate-300 text-slate-600 transition-colors" className="inline-flex items-center justify-center w-7 h-7 rounded-md border border-slate-100 bg-white hover:bg-slate-50 hover:border-slate-300 text-slate-600 transition-colors"
> >
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-3.5 h-3.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-3.5 h-3.5">
<path d="M15 18l-6-6 6-6" strokeLinecap="round" strokeLinejoin="round" /> <path d="M15 18l-6-6 6-6" strokeLinecap="round" strokeLinejoin="round" />
...@@ -107,7 +107,7 @@ export function EmrSoapView({ facts }: { facts: AdaptedFact[] }) { ...@@ -107,7 +107,7 @@ export function EmrSoapView({ facts }: { facts: AdaptedFact[] }) {
<button <button
onClick={next} onClick={next}
aria-label="下一次接诊" aria-label="下一次接诊"
className="inline-flex items-center justify-center w-7 h-7 rounded-md border border-slate-200 bg-white hover:bg-slate-50 hover:border-slate-300 text-slate-600 transition-colors" className="inline-flex items-center justify-center w-7 h-7 rounded-md border border-slate-100 bg-white hover:bg-slate-50 hover:border-slate-300 text-slate-600 transition-colors"
> >
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-3.5 h-3.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-3.5 h-3.5">
<path d="M9 18l6-6-6-6" strokeLinecap="round" strokeLinejoin="round" /> <path d="M9 18l6-6-6-6" strokeLinecap="round" strokeLinejoin="round" />
...@@ -181,9 +181,9 @@ function EmrSection({ ...@@ -181,9 +181,9 @@ function EmrSection({
const doctorAdvice = (c.doctor_advice as string | undefined) ?? ''; const doctorAdvice = (c.doctor_advice as string | undefined) ?? '';
return ( return (
<section className="rounded-lg border border-slate-200 bg-white overflow-hidden"> <section className="rounded-lg border border-slate-100 bg-white overflow-hidden">
{/* 头:日期 + 医生 + 第几次 */} {/* 头:日期 + 医生 + 第几次 */}
<header className="px-3 py-2 bg-slate-50 border-b border-slate-200 flex items-center justify-between flex-wrap gap-2"> <header className="px-3 py-2 bg-slate-50 border-b border-slate-100 flex items-center justify-between flex-wrap gap-2">
<div className="flex items-center gap-2 min-w-0"> <div className="flex items-center gap-2 min-w-0">
<span className="text-[12.5px] font-semibold text-slate-900 tabular-nums">{date}</span> <span className="text-[12.5px] font-semibold text-slate-900 tabular-nums">{date}</span>
<span className="text-[11px] text-slate-500">·</span> <span className="text-[11px] text-slate-500">·</span>
......
...@@ -119,7 +119,7 @@ export function FactsTimeline({ facts }: { facts: AdaptedFact[] }) { ...@@ -119,7 +119,7 @@ export function FactsTimeline({ facts }: { facts: AdaptedFact[] }) {
'rounded-md border px-2 py-0.5 text-[11px] focus:outline-none focus:ring-1 focus:ring-sky-300', 'rounded-md border px-2 py-0.5 text-[11px] focus:outline-none focus:ring-1 focus:ring-sky-300',
toothFilter toothFilter
? 'border-sky-200 bg-sky-50 text-sky-700 font-medium' ? 'border-sky-200 bg-sky-50 text-sky-700 font-medium'
: 'border-slate-200 bg-white text-slate-600', : 'border-slate-100 bg-white text-slate-600',
)} )}
> >
<option value="">全部牙位</option> <option value="">全部牙位</option>
...@@ -205,7 +205,7 @@ function StatsSummary({ facts }: { facts: AdaptedFact[] }) { ...@@ -205,7 +205,7 @@ function StatsSummary({ facts }: { facts: AdaptedFact[] }) {
t ? new Date(t).toLocaleDateString('zh-CN').replace(/\//g, '.') : '—'; t ? new Date(t).toLocaleDateString('zh-CN').replace(/\//g, '.') : '—';
return ( return (
<div className="rounded-lg border border-slate-200 bg-slate-50/60 p-2.5"> <div className="rounded-lg border border-slate-100 bg-slate-50/60 p-2.5">
<div className="grid grid-cols-4 gap-3"> <div className="grid grid-cols-4 gap-3">
<StatBlock label="累计净消费"> <StatBlock label="累计净消费">
<div className="text-[13px] font-semibold text-slate-900 tabular-nums"> <div className="text-[13px] font-semibold text-slate-900 tabular-nums">
...@@ -344,7 +344,7 @@ function computeEffectiveTone(fact: AdaptedFact, meta: FactMeta): string { ...@@ -344,7 +344,7 @@ function computeEffectiveTone(fact: AdaptedFact, meta: FactMeta): string {
} }
// 状态 badge 统一样式(slate)— W4 末降噪:语义色集中在时间轴 icon dot,badge 不重复表达 // 状态 badge 统一样式(slate)— W4 末降噪:语义色集中在时间轴 icon dot,badge 不重复表达
const STATUS_BADGE = 'px-1.5 py-px rounded border text-[10.5px] bg-slate-50 text-slate-600 border-slate-200'; const STATUS_BADGE = 'px-1.5 py-px rounded border text-[10.5px] bg-slate-50 text-slate-600 border-slate-100';
// 右列数据 — 按 fact 类型挑最关键的 1-2 行 // 右列数据 — 按 fact 类型挑最关键的 1-2 行
interface RightLine { text: string; className?: string } interface RightLine { text: string; className?: string }
...@@ -439,7 +439,7 @@ function FilterChip({ ...@@ -439,7 +439,7 @@ function FilterChip({
'inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-[11px] border transition-colors', 'inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-[11px] border transition-colors',
active active
? 'bg-sky-50 text-sky-700 border-sky-200 font-medium' ? 'bg-sky-50 text-sky-700 border-sky-200 font-medium'
: 'bg-white text-slate-500 border-slate-200 hover:bg-slate-50', : 'bg-white text-slate-500 border-slate-100 hover:bg-slate-50',
)} )}
> >
<span>{label}</span> <span>{label}</span>
......
...@@ -125,7 +125,7 @@ export function OutcomeForm({ ...@@ -125,7 +125,7 @@ export function OutcomeForm({
return ( return (
<div className="flex flex-col gap-2.5 h-full min-h-0"> <div className="flex flex-col gap-2.5 h-full min-h-0">
{isTerminal && ( {isTerminal && (
<div className="flex-none rounded bg-slate-100 border border-slate-200 px-2.5 py-1.5 text-[11px] text-slate-500 leading-snug"> <div className="flex-none rounded bg-slate-100 border border-slate-100 px-2.5 py-1.5 text-[11px] text-slate-500 leading-snug">
本任务已{plan.status === 'abandoned' ? '放弃' : plan.status === 'superseded' ? '被新版本替代' : '结案'},不可再提交执行;如需重新跟进,等召回重新生成。 本任务已{plan.status === 'abandoned' ? '放弃' : plan.status === 'superseded' ? '被新版本替代' : '结案'},不可再提交执行;如需重新跟进,等召回重新生成。
</div> </div>
)} )}
...@@ -145,7 +145,7 @@ export function OutcomeForm({ ...@@ -145,7 +145,7 @@ export function OutcomeForm({
'px-2 py-1.5 rounded text-[11.5px] border transition-colors inline-flex items-center justify-center gap-1.5', 'px-2 py-1.5 rounded text-[11.5px] border transition-colors inline-flex items-center justify-center gap-1.5',
selected selected
? `${T.bg} ${T.text} border-current font-medium ring-1 ring-current/30` ? `${T.bg} ${T.text} border-current font-medium ring-1 ring-current/30`
: 'bg-white text-slate-700 border-slate-200 hover:border-slate-300 hover:bg-slate-50', : 'bg-white text-slate-700 border-slate-100 hover:border-slate-300 hover:bg-slate-50',
)} )}
> >
<svg <svg
...@@ -186,7 +186,7 @@ export function OutcomeForm({ ...@@ -186,7 +186,7 @@ export function OutcomeForm({
'px-2 py-1 rounded text-left text-[11px] border transition-colors flex items-center gap-1.5', 'px-2 py-1 rounded text-left text-[11px] border transition-colors flex items-center gap-1.5',
selected selected
? `${T.bg} ${T.text} border-current font-medium ring-1 ring-current/30` ? `${T.bg} ${T.text} border-current font-medium ring-1 ring-current/30`
: 'bg-white text-slate-700 border-slate-200 hover:border-slate-300 hover:bg-slate-50', : 'bg-white text-slate-700 border-slate-100 hover:border-slate-300 hover:bg-slate-50',
)} )}
> >
<span className={cn('flex-none w-1.5 h-1.5 rounded-full', selected ? T.dot : 'bg-slate-300')} /> <span className={cn('flex-none w-1.5 h-1.5 rounded-full', selected ? T.dot : 'bg-slate-300')} />
...@@ -267,7 +267,7 @@ export function OutcomeForm({ ...@@ -267,7 +267,7 @@ export function OutcomeForm({
value={notes} value={notes}
onChange={(e) => setNotes(e.target.value)} onChange={(e) => setNotes(e.target.value)}
placeholder="患者反馈、关键点、需告知医生的信息……" placeholder="患者反馈、关键点、需告知医生的信息……"
className="flex-1 min-h-[60px] px-2.5 py-1.5 rounded border border-slate-200 bg-white text-[12.5px] resize-none focus:outline-none focus:ring-2 focus:ring-teal-200 focus:border-teal-300" className="flex-1 min-h-[60px] px-2.5 py-1.5 rounded border border-slate-100 bg-white text-[12.5px] resize-none focus:outline-none focus:ring-2 focus:ring-teal-200 focus:border-teal-300"
/> />
</div> </div>
......
...@@ -30,7 +30,7 @@ export function PersonaFeatureHover({ ...@@ -30,7 +30,7 @@ export function PersonaFeatureHover({
<HoverCardTrigger asChild>{children}</HoverCardTrigger> <HoverCardTrigger asChild>{children}</HoverCardTrigger>
<HoverCardContent align="end" sideOffset={6} className="w-80 p-3 text-[11.5px]"> <HoverCardContent align="end" sideOffset={6} className="w-80 p-3 text-[11.5px]">
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-baseline justify-between border-b border-slate-200 pb-1.5"> <div className="flex items-baseline justify-between border-b border-slate-100 pb-1.5">
<span className="text-[13px] font-semibold text-slate-900">{meta?.title ?? featureKey}</span> <span className="text-[13px] font-semibold text-slate-900">{meta?.title ?? featureKey}</span>
{meta?.subtitle && <span className="text-[10.5px] text-slate-500">{meta.subtitle}</span>} {meta?.subtitle && <span className="text-[10.5px] text-slate-500">{meta.subtitle}</span>}
</div> </div>
......
...@@ -347,7 +347,7 @@ export function PlanDetailApp({ ...@@ -347,7 +347,7 @@ export function PlanDetailApp({
} }
centerPane={ centerPane={
<main className="relative min-h-0 flex flex-col h-full"> <main className="relative min-h-0 flex flex-col h-full">
<section className="bg-white rounded-lg border border-slate-200 shadow-sm flex flex-col min-h-0 flex-1 overflow-hidden"> <section className="bg-white rounded-lg border border-slate-100 shadow-sm flex flex-col min-h-0 flex-1 overflow-hidden">
{/* 窄屏 flex-wrap 自然换行,gap-y 给行间距 */} {/* 窄屏 flex-wrap 自然换行,gap-y 给行间距 */}
<header className="flex-none px-3 sm:px-4 py-2.5 border-b border-slate-100 flex flex-wrap items-center justify-between gap-x-2 gap-y-2"> <header className="flex-none px-3 sm:px-4 py-2.5 border-b border-slate-100 flex flex-wrap items-center justify-between gap-x-2 gap-y-2">
<div className="min-w-0"> <div className="min-w-0">
...@@ -458,7 +458,7 @@ export function PlanDetailApp({ ...@@ -458,7 +458,7 @@ export function PlanDetailApp({
} }
rightPane={ rightPane={
<aside className="min-h-0 flex flex-col gap-2.5 overflow-hidden h-full"> <aside className="min-h-0 flex flex-col gap-2.5 overflow-hidden h-full">
<section className="bg-white rounded-lg border border-slate-200 shadow-sm flex flex-col min-h-0 flex-1 overflow-hidden"> <section className="bg-white rounded-lg border border-slate-100 shadow-sm flex flex-col min-h-0 flex-1 overflow-hidden">
<header className="flex-none px-4 py-2.5 border-b border-slate-100 flex items-center justify-between gap-2"> <header className="flex-none px-4 py-2.5 border-b border-slate-100 flex items-center justify-between gap-2">
<div> <div>
<h2 className="text-[14px] font-semibold text-slate-900 leading-tight">通话结果</h2> <h2 className="text-[14px] font-semibold text-slate-900 leading-tight">通话结果</h2>
...@@ -615,7 +615,7 @@ function RecallFeedbackControl({ ...@@ -615,7 +615,7 @@ function RecallFeedbackControl({
return ( return (
<> <>
<div <div
className="hidden sm:flex flex-none items-center gap-0.5 rounded-md border border-slate-200 px-1 py-0.5" className="hidden sm:flex flex-none items-center gap-0.5 rounded-md border border-slate-100 px-1 py-0.5"
title="召回反馈:这条召回准不准?" title="召回反馈:这条召回准不准?"
> >
<span className="hidden lg:inline px-1 text-[10.5px] text-slate-400">召回反馈</span> <span className="hidden lg:inline px-1 text-[10.5px] text-slate-400">召回反馈</span>
...@@ -665,7 +665,7 @@ function RecallFeedbackControl({ ...@@ -665,7 +665,7 @@ function RecallFeedbackControl({
type="button" type="button"
title={f.hint} title={f.hint}
onClick={() => quickInsert(f.labelZh)} onClick={() => quickInsert(f.labelZh)}
className="px-2 py-1 rounded-full text-[12px] border border-slate-200 bg-white text-slate-600 hover:border-rose-300 hover:bg-rose-50 hover:text-rose-700 transition-colors" className="px-2 py-1 rounded-full text-[12px] border border-slate-100 bg-white text-slate-600 hover:border-rose-300 hover:bg-rose-50 hover:text-rose-700 transition-colors"
> >
{f.labelZh} {f.labelZh}
</button> </button>
...@@ -676,14 +676,14 @@ function RecallFeedbackControl({ ...@@ -676,14 +676,14 @@ function RecallFeedbackControl({
onChange={(e) => setNote(e.target.value)} onChange={(e) => setNote(e.target.value)}
placeholder="补充说明(选填)…" placeholder="补充说明(选填)…"
rows={3} rows={3}
className="w-full px-2.5 py-2 rounded border border-slate-200 bg-white text-[13px] resize-none focus:outline-none focus:ring-2 focus:ring-rose-200 focus:border-rose-300" className="w-full px-2.5 py-2 rounded border border-slate-100 bg-white text-[13px] resize-none focus:outline-none focus:ring-2 focus:ring-rose-200 focus:border-rose-300"
/> />
</div> </div>
<DialogFooter> <DialogFooter>
<button <button
type="button" type="button"
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
className="px-3 py-1.5 rounded-md border border-slate-200 text-[13px] text-slate-600 hover:bg-slate-50" className="px-3 py-1.5 rounded-md border border-slate-100 text-[13px] text-slate-600 hover:bg-slate-50"
> >
取消 取消
</button> </button>
...@@ -757,7 +757,7 @@ function TopBar({ ...@@ -757,7 +757,7 @@ function TopBar({
}; };
return ( return (
<header className="flex flex-none items-center justify-between gap-2 border-b border-slate-200 bg-white px-3 py-2 sm:px-5 sm:py-3 sm:gap-3"> <header className="flex flex-none items-center justify-between gap-2 border-b border-slate-100 bg-white px-3 py-2 sm:px-5 sm:py-3 sm:gap-3">
<div className="flex min-w-0 items-center gap-2 sm:gap-3"> <div className="flex min-w-0 items-center gap-2 sm:gap-3">
<div className="inline-flex flex-none items-center gap-2"> <div className="inline-flex flex-none items-center gap-2">
<span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white"> <span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white">
...@@ -811,8 +811,8 @@ function TopBar({ ...@@ -811,8 +811,8 @@ function TopBar({
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-md border px-2 sm:px-2.5 py-1 text-[11.5px] font-medium transition-colors', 'inline-flex items-center gap-1.5 rounded-md border px-2 sm:px-2.5 py-1 text-[11.5px] font-medium transition-colors',
refreshing refreshing
? 'cursor-not-allowed border-slate-200 bg-slate-50 text-slate-400' ? 'cursor-not-allowed border-slate-100 bg-slate-50 text-slate-400'
: 'border-slate-200 bg-white text-slate-700 hover:border-teal-300 hover:bg-teal-50 hover:text-teal-700', : 'border-slate-100 bg-white text-slate-700 hover:border-teal-300 hover:bg-teal-50 hover:text-teal-700',
)} )}
> >
<RefreshCw className={cn('h-3.5 w-3.5', refreshing && 'animate-spin')} /> <RefreshCw className={cn('h-3.5 w-3.5', refreshing && 'animate-spin')} />
...@@ -1001,7 +1001,7 @@ function IdentityCard({ ...@@ -1001,7 +1001,7 @@ function IdentityCard({
setTimeout(() => setCopied(false), 1500); setTimeout(() => setCopied(false), 1500);
}; };
return ( return (
<section className="bg-white rounded-lg border border-slate-200 shadow-sm flex-none"> <section className="bg-white rounded-lg border border-slate-100 shadow-sm flex-none">
<div className="p-3 flex items-start gap-2.5"> <div className="p-3 flex items-start gap-2.5">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
...@@ -1739,10 +1739,10 @@ function RegenBtn({ ...@@ -1739,10 +1739,10 @@ function RegenBtn({
'inline-flex items-center gap-0.5 px-1.5 py-0.5 text-[10.5px] border-r transition-colors', 'inline-flex items-center gap-0.5 px-1.5 py-0.5 text-[10.5px] border-r transition-colors',
streaming streaming
? 'text-slate-300 border-slate-100 cursor-not-allowed' ? 'text-slate-300 border-slate-100 cursor-not-allowed'
: 'text-slate-500 border-slate-200 hover:text-teal-700 hover:bg-teal-50', : 'text-slate-500 border-slate-100 hover:text-teal-700 hover:bg-teal-50',
); );
return ( return (
<div className="inline-flex flex-none items-stretch rounded border border-slate-200 overflow-hidden"> <div className="inline-flex flex-none items-stretch rounded border border-slate-100 overflow-hidden">
{/* 档位选择(只选,不触发) */} {/* 档位选择(只选,不触发) */}
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild disabled={streaming}> <DropdownMenuTrigger asChild disabled={streaming}>
......
...@@ -91,11 +91,11 @@ export type OracleVerdict = { ...@@ -91,11 +91,11 @@ export type OracleVerdict = {
const VERDICT_META: Record<OracleVerdictKind, { zh: string; tone: string }> = { const VERDICT_META: Record<OracleVerdictKind, { zh: string; tone: string }> = {
recall: { zh: '应召回', tone: 'bg-emerald-50 text-emerald-700 border-emerald-200' }, recall: { zh: '应召回', tone: 'bg-emerald-50 text-emerald-700 border-emerald-200' },
resolved: { zh: '已治疗', tone: 'bg-slate-100 text-slate-500 border-slate-200' }, resolved: { zh: '已治疗', tone: 'bg-slate-100 text-slate-500 border-slate-100' },
superseded: { zh: '被取代', tone: 'bg-slate-100 text-slate-400 border-slate-200' }, superseded: { zh: '被取代', tone: 'bg-slate-100 text-slate-400 border-slate-100' },
cooldown: { zh: '考虑期', tone: 'bg-amber-50 text-amber-700 border-amber-200' }, cooldown: { zh: '考虑期', tone: 'bg-amber-50 text-amber-700 border-amber-200' },
ineligible: { zh: '非修复', tone: 'bg-slate-100 text-slate-400 border-slate-200' }, ineligible: { zh: '非修复', tone: 'bg-slate-100 text-slate-400 border-slate-100' },
suppressed: { zh: '被压制', tone: 'bg-slate-100 text-slate-500 border-slate-200' }, suppressed: { zh: '被压制', tone: 'bg-slate-100 text-slate-500 border-slate-100' },
}; };
export function verdictMeta(kind: OracleVerdictKind) { export function verdictMeta(kind: OracleVerdictKind) {
......
...@@ -32,7 +32,7 @@ export function ScriptDeepProcess({ steps }: { steps: DeepStep[] }) { ...@@ -32,7 +32,7 @@ export function ScriptDeepProcess({ steps }: { steps: DeepStep[] }) {
const runningStep = steps.find((s) => s.status === 'running')?.step ?? null; const runningStep = steps.find((s) => s.status === 'running')?.step ?? null;
return ( return (
<div className="mb-3 rounded-lg border border-slate-200 bg-slate-50 p-2.5"> <div className="mb-3 rounded-lg border border-slate-100 bg-slate-50 p-2.5">
<ol className="space-y-1.5"> <ol className="space-y-1.5">
{steps.map((s) => { {steps.map((s) => {
const hasDetail = stepHasDetail(s); const hasDetail = stepHasDetail(s);
......
...@@ -21,7 +21,7 @@ export function ScriptMarkdown({ sections, streaming = false }: { sections: Scri ...@@ -21,7 +21,7 @@ export function ScriptMarkdown({ sections, streaming = false }: { sections: Scri
{sections.map((sec, idx) => { {sections.map((sec, idx) => {
const isOpen = !collapsed[sec.id]; const isOpen = !collapsed[sec.id];
return ( return (
<div key={sec.id} className="rounded-md border border-slate-200 bg-white overflow-hidden"> <div key={sec.id} className="rounded-md border border-slate-100 bg-white overflow-hidden">
<button <button
onClick={() => setCollapsed({ ...collapsed, [sec.id]: !collapsed[sec.id] })} onClick={() => setCollapsed({ ...collapsed, [sec.id]: !collapsed[sec.id] })}
className="w-full flex items-center justify-between gap-2 px-3 py-2 text-left hover:bg-slate-50" className="w-full flex items-center justify-between gap-2 px-3 py-2 text-left hover:bg-slate-50"
...@@ -63,7 +63,7 @@ export function ScriptStepCards({ sections, streaming = false }: { sections: Scr ...@@ -63,7 +63,7 @@ export function ScriptStepCards({ sections, streaming = false }: { sections: Scr
return ( return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{sections.map((sec, i) => ( {sections.map((sec, i) => (
<div key={sec.id} className="rounded-md border border-slate-200 bg-white p-3 flex flex-col"> <div key={sec.id} className="rounded-md border border-slate-100 bg-white p-3 flex flex-col">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="w-6 h-6 rounded-full bg-teal-600 text-white text-[11px] font-semibold flex items-center justify-center"> <span className="w-6 h-6 rounded-full bg-teal-600 text-white text-[11px] font-semibold flex items-center justify-center">
...@@ -93,7 +93,7 @@ export function ScriptCopilot({ sections, streaming = false }: { sections: Scrip ...@@ -93,7 +93,7 @@ export function ScriptCopilot({ sections, streaming = false }: { sections: Scrip
return ( return (
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{/* 进度条 */} {/* 进度条 */}
<div className="flex items-center gap-1.5 rounded-md bg-slate-50 border border-slate-200 p-1.5"> <div className="flex items-center gap-1.5 rounded-md bg-slate-50 border border-slate-100 p-1.5">
{sections.map((s, i) => ( {sections.map((s, i) => (
<button <button
key={s.id} key={s.id}
......
...@@ -141,7 +141,7 @@ export function SidebarCard({ ...@@ -141,7 +141,7 @@ export function SidebarCard({
return ( return (
<section <section
className={cn( className={cn(
'bg-white rounded-lg border border-slate-200 shadow-sm flex flex-col min-h-0 flex-none', 'bg-white rounded-lg border border-slate-100 shadow-sm flex flex-col min-h-0 flex-none',
className, className,
)} )}
> >
......
...@@ -99,7 +99,7 @@ export function TaskDrawer({ currentPlanId }: { currentPlanId: string }) { ...@@ -99,7 +99,7 @@ export function TaskDrawer({ currentPlanId }: { currentPlanId: string }) {
<aside <aside
className={cn( className={cn(
'fixed left-0 top-0 bottom-0 w-[320px] bg-white border-r border-slate-200 shadow-xl z-50', 'fixed left-0 top-0 bottom-0 w-[320px] bg-white border-r border-slate-100 shadow-xl z-50',
'transition-transform duration-200 ease-out flex flex-col', 'transition-transform duration-200 ease-out flex flex-col',
open ? 'translate-x-0' : '-translate-x-full', open ? 'translate-x-0' : '-translate-x-full',
)} )}
...@@ -152,7 +152,7 @@ export function TaskDrawer({ currentPlanId }: { currentPlanId: string }) { ...@@ -152,7 +152,7 @@ export function TaskDrawer({ currentPlanId }: { currentPlanId: string }) {
placeholder="搜索 姓名 / 手机 / ID(已加载项)" placeholder="搜索 姓名 / 手机 / ID(已加载项)"
value={search} value={search}
onChange={(e) => setSearch(e.target.value)} onChange={(e) => setSearch(e.target.value)}
className="w-full pl-7 pr-2.5 py-1.5 rounded-md border border-slate-200 bg-slate-50 text-[12px] text-slate-800 focus:outline-none focus:ring-2 focus:ring-teal-200 focus:border-teal-300 focus:bg-white transition-all" className="w-full pl-7 pr-2.5 py-1.5 rounded-md border border-slate-100 bg-slate-50 text-[12px] text-slate-800 focus:outline-none focus:ring-2 focus:ring-teal-200 focus:border-teal-300 focus:bg-white transition-all"
/> />
</div> </div>
<div className="grid grid-cols-3 gap-1"> <div className="grid grid-cols-3 gap-1">
...@@ -223,7 +223,7 @@ function KpiMini({ ...@@ -223,7 +223,7 @@ function KpiMini({
}) { }) {
const T = KPI_TONE[tone] ?? ''; const T = KPI_TONE[tone] ?? '';
return ( return (
<div className="flex items-center gap-2 rounded-lg border border-slate-200 bg-white px-2 py-1.5"> <div className="flex items-center gap-2 rounded-lg border border-slate-100 bg-white px-2 py-1.5">
<span className={cn('inline-flex h-7 w-7 flex-none items-center justify-center rounded-lg ring-1 ring-inset', T)}> <span className={cn('inline-flex h-7 w-7 flex-none items-center justify-center rounded-lg ring-1 ring-inset', T)}>
{icon} {icon}
</span> </span>
...@@ -256,7 +256,7 @@ function TaskRow({ ...@@ -256,7 +256,7 @@ function TaskRow({
'w-full text-left rounded-md border px-2.5 py-2 transition-colors', 'w-full text-left rounded-md border px-2.5 py-2 transition-colors',
active active
? 'border-teal-400 bg-teal-50/60 ring-1 ring-teal-100' ? 'border-teal-400 bg-teal-50/60 ring-1 ring-teal-100'
: 'border-slate-200 bg-white hover:border-slate-300 hover:bg-slate-50', : 'border-slate-100 bg-white hover:border-slate-300 hover:bg-slate-50',
done && 'opacity-70', done && 'opacity-70',
)} )}
> >
......
...@@ -81,7 +81,7 @@ export function ToothTimeline({ facts }: { facts: AdaptedFact[] }) { ...@@ -81,7 +81,7 @@ export function ToothTimeline({ facts }: { facts: AdaptedFact[] }) {
); );
const isWhole = k.startsWith('全口'); const isWhole = k.startsWith('全口');
return ( return (
<div key={k} className="rounded-lg border border-slate-200 overflow-hidden"> <div key={k} className="rounded-lg border border-slate-100 overflow-hidden">
<div <div
className={cn( className={cn(
'flex items-center gap-2 px-2.5 py-1.5 text-[12px] font-semibold border-b border-slate-100', 'flex items-center gap-2 px-2.5 py-1.5 text-[12px] font-semibold border-b border-slate-100',
......
...@@ -112,7 +112,7 @@ export function PatientPickerRail({ ...@@ -112,7 +112,7 @@ export function PatientPickerRail({
}); });
return ( return (
<aside className="flex h-full w-[300px] flex-none flex-col border-r border-slate-200 bg-white"> <aside className="flex h-full w-[300px] flex-none flex-col border-r border-slate-100 bg-white">
{/* view tabs */} {/* view tabs */}
<div className="flex flex-none gap-1 border-b border-slate-100 px-2 pt-2"> <div className="flex flex-none gap-1 border-b border-slate-100 px-2 pt-2">
{VIEW_TABS.filter((t) => t.v !== 'all' || canViewAll).map((t) => ( {VIEW_TABS.filter((t) => t.v !== 'all' || canViewAll).map((t) => (
...@@ -144,14 +144,14 @@ export function PatientPickerRail({ ...@@ -144,14 +144,14 @@ export function PatientPickerRail({
value={search} value={search}
onChange={(e) => setSearch(e.target.value)} onChange={(e) => setSearch(e.target.value)}
placeholder="姓名 / 手机 / 患者号" placeholder="姓名 / 手机 / 患者号"
className="h-7 w-full rounded-md border border-slate-200 bg-slate-50 pl-7 pr-2 text-[12px] outline-none placeholder:text-slate-400 focus:border-teal-300 focus:bg-white" className="h-7 w-full rounded-md border border-slate-100 bg-slate-50 pl-7 pr-2 text-[12px] outline-none placeholder:text-slate-400 focus:border-teal-300 focus:bg-white"
/> />
</div> </div>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<select <select
value={sort} value={sort}
onChange={(e) => setSort(e.target.value as PickerFilters['sort'])} onChange={(e) => setSort(e.target.value as PickerFilters['sort'])}
className="h-6.5 rounded-md border border-slate-200 bg-white px-1.5 py-0.5 text-[11px] text-slate-600" className="h-6.5 rounded-md border border-slate-100 bg-white px-1.5 py-0.5 text-[11px] text-slate-600"
> >
<option value="priority_desc">优先级 高→低</option> <option value="priority_desc">优先级 高→低</option>
<option value="priority_asc">优先级 低→高</option> <option value="priority_asc">优先级 低→高</option>
...@@ -165,7 +165,7 @@ export function PatientPickerRail({ ...@@ -165,7 +165,7 @@ export function PatientPickerRail({
'inline-flex h-6 items-center gap-1 rounded-md border px-1.5 text-[11px] transition-colors', 'inline-flex h-6 items-center gap-1 rounded-md border px-1.5 text-[11px] transition-colors',
realPhoneOnly realPhoneOnly
? 'border-teal-300 bg-teal-50 font-medium text-teal-700' ? 'border-teal-300 bg-teal-50 font-medium text-teal-700'
: 'border-slate-200 bg-white text-slate-500 hover:bg-slate-50', : 'border-slate-100 bg-white text-slate-500 hover:bg-slate-50',
)} )}
> >
<PhoneCall className="h-3 w-3" /> <PhoneCall className="h-3 w-3" />
...@@ -260,7 +260,7 @@ function PersonaTagFilter({ ...@@ -260,7 +260,7 @@ function PersonaTagFilter({
'inline-flex h-6 items-center gap-1 rounded-md border px-1.5 text-[11px] transition-colors', 'inline-flex h-6 items-center gap-1 rounded-md border px-1.5 text-[11px] transition-colors',
selected.size > 0 selected.size > 0
? 'border-teal-300 bg-teal-50 font-medium text-teal-700' ? 'border-teal-300 bg-teal-50 font-medium text-teal-700'
: 'border-slate-200 bg-white text-slate-500 hover:bg-slate-50', : 'border-slate-100 bg-white text-slate-500 hover:bg-slate-50',
)} )}
> >
<Filter className="h-3 w-3" /> <Filter className="h-3 w-3" />
...@@ -295,7 +295,7 @@ function PersonaTagFilter({ ...@@ -295,7 +295,7 @@ function PersonaTagFilter({
'rounded-full border px-2 py-0.5 text-[11px] transition-colors', 'rounded-full border px-2 py-0.5 text-[11px] transition-colors',
on on
? 'border-teal-300 bg-teal-50 font-medium text-teal-700' ? 'border-teal-300 bg-teal-50 font-medium text-teal-700'
: 'border-slate-200 bg-white text-slate-600 hover:border-teal-200 hover:bg-teal-50/40', : 'border-slate-100 bg-white text-slate-600 hover:border-teal-200 hover:bg-teal-50/40',
)} )}
> >
{o.zh} {o.zh}
...@@ -337,7 +337,7 @@ function RailClinicFilter({ ...@@ -337,7 +337,7 @@ function RailClinicFilter({
'inline-flex h-6 w-full items-center justify-between rounded-md border px-1.5 text-[11px] transition-colors', 'inline-flex h-6 w-full items-center justify-between rounded-md border px-1.5 text-[11px] transition-colors',
selected.length selected.length
? 'border-teal-300 bg-teal-50 font-medium text-teal-700' ? 'border-teal-300 bg-teal-50 font-medium text-teal-700'
: 'border-slate-200 bg-white text-slate-500 hover:bg-slate-50', : 'border-slate-100 bg-white text-slate-500 hover:bg-slate-50',
)} )}
> >
<span className="truncate"> <span className="truncate">
......
...@@ -240,7 +240,7 @@ export function PlansListApp() { ...@@ -240,7 +240,7 @@ export function PlansListApp() {
<div className="flex h-full min-h-screen flex-col bg-slate-50"> <div className="flex h-full min-h-screen flex-col bg-slate-50">
<PageHeader user={user} mineAssigned={counts.mineAssigned} poolHi={counts.pool} onRefresh={refreshAll} /> <PageHeader user={user} mineAssigned={counts.mineAssigned} poolHi={counts.pool} onRefresh={refreshAll} />
<div className="grid flex-none grid-cols-2 gap-3 border-b border-slate-200 bg-slate-50 px-5 py-3 md:grid-cols-4"> <div className="grid flex-none grid-cols-2 gap-3 border-b border-slate-100 bg-slate-50 px-5 py-3 md:grid-cols-4">
<KpiCard tone="amber" icon={<ListChecks className="h-4 w-4" />} label="我的进行中" value={counts.mineAssigned} sub={`共 ${counts.mine} 个工单`} /> <KpiCard tone="amber" icon={<ListChecks className="h-4 w-4" />} label="我的进行中" value={counts.mineAssigned} sub={`共 ${counts.mine} 个工单`} />
<KpiCard tone="rose" icon={<Flame className="h-4 w-4" />} label="召回池余量" value={counts.pool} sub="池中待领取" /> <KpiCard tone="rose" icon={<Flame className="h-4 w-4" />} label="召回池余量" value={counts.pool} sub="池中待领取" />
<KpiCard tone="emerald" icon={<ListChecks className="h-4 w-4" />} label="我完成" value={counts.mineCompleted} sub={successRateText(counts)} /> <KpiCard tone="emerald" icon={<ListChecks className="h-4 w-4" />} label="我完成" value={counts.mineCompleted} sub={successRateText(counts)} />
...@@ -354,7 +354,7 @@ function PageHeader({ ...@@ -354,7 +354,7 @@ function PageHeader({
}) { }) {
const greeting = mineAssigned > 0 ? `今天好,还有 ${mineAssigned} 个待打` : poolHi > 0 ? `池中还有 ${poolHi} 个待领取` : '今天好'; const greeting = mineAssigned > 0 ? `今天好,还有 ${mineAssigned} 个待打` : poolHi > 0 ? `池中还有 ${poolHi} 个待领取` : '今天好';
return ( return (
<header className="flex flex-none items-center justify-between gap-3 border-b border-slate-200 bg-white px-5 py-3"> <header className="flex flex-none items-center justify-between gap-3 border-b border-slate-100 bg-white px-5 py-3">
<div className="flex min-w-0 items-center gap-3"> <div className="flex min-w-0 items-center gap-3">
<div className="inline-flex items-center gap-2"> <div className="inline-flex items-center gap-2">
<span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white">PAC</span> <span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-teal-600 text-[12px] font-bold text-white">PAC</span>
...@@ -421,7 +421,7 @@ function KpiCard({ ...@@ -421,7 +421,7 @@ function KpiCard({
}) { }) {
const T = TONE_BG[tone] ?? ''; const T = TONE_BG[tone] ?? '';
return ( return (
<div className="flex items-center gap-3 rounded-lg border border-slate-200 bg-white px-3 py-2.5"> <div className="flex items-center gap-3 rounded-lg border border-slate-100 bg-white px-3 py-2.5">
<span className={cn('inline-flex h-9 w-9 flex-none items-center justify-center rounded-lg ring-1 ring-inset', T)}> <span className={cn('inline-flex h-9 w-9 flex-none items-center justify-center rounded-lg ring-1 ring-inset', T)}>
{icon} {icon}
</span> </span>
...@@ -462,7 +462,7 @@ function ViewTabs({ ...@@ -462,7 +462,7 @@ function ViewTabs({
{ v: 'all', label: '全部', hint: '全状态', gated: !canViewAll }, { v: 'all', label: '全部', hint: '全状态', gated: !canViewAll },
]; ];
return ( return (
<div className="border-b border-slate-200"> <div className="border-b border-slate-100">
<div className="flex items-center px-3"> <div className="flex items-center px-3">
{tabs.map((t) => { {tabs.map((t) => {
const active = current === t.v; const active = current === t.v;
...@@ -532,7 +532,7 @@ function ClinicFilter({ ...@@ -532,7 +532,7 @@ function ClinicFilter({
return ( return (
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<button className="inline-flex h-8 items-center gap-1.5 rounded-md border border-slate-200 bg-white px-3 text-xs hover:border-slate-300"> <button className="inline-flex h-8 items-center gap-1.5 rounded-md border border-slate-100 bg-white px-3 text-xs hover:border-slate-300">
<span className={cn(selected.length ? 'font-medium text-slate-900' : 'text-slate-600')}>{label}</span> <span className={cn(selected.length ? 'font-medium text-slate-900' : 'text-slate-600')}>{label}</span>
<ChevronDown className="h-3.5 w-3.5 text-slate-400" /> <ChevronDown className="h-3.5 w-3.5 text-slate-400" />
</button> </button>
...@@ -613,7 +613,7 @@ function FilterBar({ ...@@ -613,7 +613,7 @@ function FilterBar({
{ value: 'abandoned', label: '已放弃' }, { value: 'abandoned', label: '已放弃' },
]; ];
return ( return (
<div className="flex flex-none flex-wrap items-center gap-2 border-b border-slate-200 bg-white px-5 py-2.5"> <div className="flex flex-none flex-wrap items-center gap-2 border-b border-slate-100 bg-white px-5 py-2.5">
<div className="relative"> <div className="relative">
<Search className="absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-slate-400" /> <Search className="absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-slate-400" />
<Input <Input
...@@ -654,7 +654,7 @@ function FilterBar({ ...@@ -654,7 +654,7 @@ function FilterBar({
'inline-flex h-8 items-center gap-1 rounded-md border px-2.5 text-xs transition-colors', 'inline-flex h-8 items-center gap-1 rounded-md border px-2.5 text-xs transition-colors',
realPhoneOnly realPhoneOnly
? 'border-teal-300 bg-teal-50 font-medium text-teal-700' ? 'border-teal-300 bg-teal-50 font-medium text-teal-700'
: 'border-slate-200 bg-white text-slate-600 hover:bg-slate-50', : 'border-slate-100 bg-white text-slate-600 hover:bg-slate-50',
)} )}
> >
<PhoneCall className="h-3.5 w-3.5" /> <PhoneCall className="h-3.5 w-3.5" />
...@@ -763,7 +763,7 @@ function PatientPlanCard({ ...@@ -763,7 +763,7 @@ function PatientPlanCard({
<article <article
className={cn( className={cn(
'group relative flex flex-col rounded-lg border bg-white transition-all', 'group relative flex flex-col rounded-lg border bg-white transition-all',
selected ? 'border-teal-400 ring-2 ring-teal-100' : 'border-slate-200 hover:border-slate-300 hover:shadow-sm', selected ? 'border-teal-400 ring-2 ring-teal-100' : 'border-slate-100 hover:border-slate-300 hover:shadow-sm',
isClosed && 'opacity-75', isClosed && 'opacity-75',
)} )}
> >
...@@ -903,7 +903,7 @@ function PatientPlanCard({ ...@@ -903,7 +903,7 @@ function PatientPlanCard({
{!isPool && !(isMine && p.status === 'assigned') && ( {!isPool && !(isMine && p.status === 'assigned') && (
<Link <Link
href={`/plans/${p.id}`} href={`/plans/${p.id}`}
className="rounded-md border border-slate-200 px-2.5 py-1 text-[12px] text-slate-700 hover:bg-slate-50" className="rounded-md border border-slate-100 px-2.5 py-1 text-[12px] text-slate-700 hover:bg-slate-50"
> >
详情 → 详情 →
</Link> </Link>
...@@ -972,7 +972,7 @@ function Pagination({ ...@@ -972,7 +972,7 @@ function Pagination({
}) { }) {
const totalPages = Math.max(1, Math.ceil(total / pageSize)); const totalPages = Math.max(1, Math.ceil(total / pageSize));
return ( return (
<div className="flex flex-none items-center justify-between border-t border-slate-200 bg-white px-5 py-2.5 text-[11.5px] text-slate-500"> <div className="flex flex-none items-center justify-between border-t border-slate-100 bg-white px-5 py-2.5 text-[11.5px] text-slate-500">
<div> <div>
<b className="nums font-semibold text-slate-800">{total}</b> 条 · 第 <b className="nums">{page}</b>/<span className="nums">{totalPages}</span> <b className="nums font-semibold text-slate-800">{total}</b> 条 · 第 <b className="nums">{page}</b>/<span className="nums">{totalPages}</span>
</div> </div>
......
...@@ -111,7 +111,7 @@ function PriorityBreakdownTable({ ...@@ -111,7 +111,7 @@ function PriorityBreakdownTable({
function Header({ disp }: { disp: string }) { function Header({ disp }: { disp: string }) {
return ( return (
<div className="flex items-baseline justify-between border-b border-slate-200 pb-1.5"> <div className="flex items-baseline justify-between border-b border-slate-100 pb-1.5">
<span className="text-[13px] font-semibold text-slate-900">优先级 {disp} / 10</span> <span className="text-[13px] font-semibold text-slate-900">优先级 {disp} / 10</span>
<span className="text-[10.5px] text-slate-500">急迫 × 价值 × 意愿</span> <span className="text-[10.5px] text-slate-500">急迫 × 价值 × 意愿</span>
</div> </div>
......
...@@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef< ...@@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef<
align={align} align={align}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
'z-50 w-auto rounded-md border border-slate-200 bg-white p-2 shadow-md outline-none', 'z-50 w-auto rounded-md border border-slate-100 bg-white p-2 shadow-md outline-none',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className, className,
)} )}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment