feat(theme): 浅蓝色主题适配 —— COH任务三子页 + 应用中心子页

- ThemeContext: 新增 data-theme="lightblue" 属性管理,支持红/蓝双浅色主题
- strategy-data.css: 新增 [data-theme="lightblue"] 变量覆盖块(与浅红默认共存)
- SentimentAnalyzes / TaskAnalyzes / ActionAnalyzes / KanbanColumn / TaskCard / ActionColumn:
  isDark ? dark : isLightBlue ? blue : red 三路适配
- LightAppListPage: 应用列表页品牌色(标题点、徽章、搜索 focus、计数、进入按钮)浅蓝适配
- LightAppNoteQAPage: 问答发送按钮浅蓝适配
- light-app-management.css: 新增 [data-theme="lightblue"] CSS 覆盖块(主按钮、保存、开关、输入 focus 等)
- light-app-pages.css: 浅蓝模式页面底色轻染 #F9FCFF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
董宏凯andClaude Sonnet 4.6 committed 2026-06-15 18:16:06 +08:00
1 parent 1ad8da5ef2
commit b1b2540dc0
16 files changed
+292 -64

No files matched your search

@@ -227,11 +227,18 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
if (theme === 'dark') {
root.setAttribute('theme-mode', 'dark');
root.classList.add('dark');
root.removeAttribute('data-theme');
return;
}
root.removeAttribute('theme-mode');
root.classList.remove('dark');
if (theme === 'lightblue') {
root.setAttribute('data-theme', 'lightblue');
} else {
root.removeAttribute('data-theme');
}
}, [theme]);
const toggleTheme = () => {
+16 -11
View File
@@ -34,6 +34,7 @@ import { toast } from "sonner";
import { Pagination } from "@/components/ui/pagination";
import { cn } from "@/lib/utils";
import { useTheme } from "@/contexts/ThemeContext";
import { useLightApps, type LightApp } from "@/strategy-components/api/light-apps";
import { buildLightAppUrl } from "@/strategy-components/lib/light-app";
@@ -67,6 +68,8 @@ export default function LightAppListPage() {
const [search, setSearch] = useState("");
const [page, setPage] = useState(1);
const [copiedId, setCopiedId] = useState<string | null>(null);
const { theme } = useTheme();
const isLightBlue = theme === 'lightblue';
const { data: apps = [], isLoading } = useLightApps({
appType: "window_open",
@@ -115,13 +118,13 @@ export default function LightAppListPage() {
<div className="space-y-1">
<div className="flex items-center gap-2.5">
<span className="relative flex size-3">
<span className="absolute inline-flex size-full animate-ping rounded-full bg-[#CF1322] opacity-75 dark:bg-[#1677FF]" />
<span className="relative inline-flex size-3 rounded-full bg-[#CF1322] dark:bg-[#1677FF]" />
<span className={cn("absolute inline-flex size-full animate-ping rounded-full opacity-75", isLightBlue ? "bg-[#0062D9]" : "bg-[#CF1322]", "dark:bg-[#1677FF]")} />
<span className={cn("relative inline-flex size-3 rounded-full", isLightBlue ? "bg-[#0062D9]" : "bg-[#CF1322]", "dark:bg-[#1677FF]")} />
</span>
<h1 className="text-2xl font-bold tracking-tight text-zinc-900 dark:text-[#E8EDF5]">
应用列表
</h1>
<span className="rounded-[5px] border border-[#CF1322]/15 bg-[#FFF1F0] px-2 py-0.5 font-mono text-xs font-medium text-[#CF1322] dark:border-[#1677FF]/30 dark:bg-[#1677FF]/15 dark:text-[#4096FF]">
<span className={cn("rounded-[5px] border px-2 py-0.5 font-mono text-xs font-medium dark:border-[#1677FF]/30 dark:bg-[#1677FF]/15 dark:text-[#4096FF]", isLightBlue ? "border-[#0062D9]/15 bg-[#EAF4FF] text-[#0062D9]" : "border-[#CF1322]/15 bg-[#FFF1F0] text-[#CF1322]")}>
导航工作台
</span>
</div>
@@ -139,7 +142,7 @@ export default function LightAppListPage() {
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="键入应用名称、目标地址、或描述,实时过滤检索…"
className="w-full rounded-[5px] border border-zinc-200 bg-zinc-50/50 py-3 pl-10 pr-10 text-sm transition focus:border-[#CF1322]/60 focus:bg-white focus:outline-none focus:ring-2 focus:ring-[#CF1322]/20 dark:border-[#1A2F5A] dark:bg-[#0C1836] dark:text-[#C5CFE0] dark:placeholder-[#4A6491] dark:focus:border-[#1677FF]/60 dark:focus:bg-[#122347] dark:focus:ring-[#1677FF]/25"
className={cn("w-full rounded-[5px] border border-zinc-200 bg-zinc-50/50 py-3 pl-10 pr-10 text-sm transition focus:bg-white focus:outline-none focus:ring-2 dark:border-[#1A2F5A] dark:bg-[#0C1836] dark:text-[#C5CFE0] dark:placeholder-[#4A6491] dark:focus:border-[#1677FF]/60 dark:focus:bg-[#122347] dark:focus:ring-[#1677FF]/25", isLightBlue ? "focus:border-[#0062D9]/60 focus:ring-[#0062D9]/20" : "focus:border-[#CF1322]/60 focus:ring-[#CF1322]/20")}
/>
{search && (
<button
@@ -158,13 +161,13 @@ export default function LightAppListPage() {
<div className="-mt-2 flex items-center justify-between">
<div className="text-xs font-medium text-zinc-500 dark:text-[#6E88B0]">
检索到最终结果:{" "}
<span className="font-bold text-[#CF1322] dark:text-[#4096FF]">{apps.length}</span> 个关联应用
<span className={cn("font-bold dark:text-[#4096FF]", isLightBlue ? "text-[#0062D9]" : "text-[#CF1322]")}>{apps.length}</span> 个关联应用
</div>
{search && (
<button
type="button"
onClick={() => setSearch("")}
className="text-xs font-medium text-[#CF1322] underline hover:text-[#A8071A] dark:text-[#4096FF] dark:hover:text-[#1677FF]"
className={cn("text-xs font-medium underline dark:text-[#4096FF] dark:hover:text-[#1677FF]", isLightBlue ? "text-[#0062D9] hover:text-[#0056C6]" : "text-[#CF1322] hover:text-[#A8071A]")}
>
重置过滤条件
</button>
@@ -235,8 +238,10 @@ function AppCard({
onCopy: () => void;
onOpen: () => void;
}) {
const { theme } = useTheme();
const isLightBlue = theme === 'lightblue';
const Icon = ICON_POOL[hashIndex(app.appId, ICON_POOL.length)];
const theme = THEME_POOL[hashIndex(app.appId, THEME_POOL.length)];
const cardTheme = THEME_POOL[hashIndex(app.appId, THEME_POOL.length)];
const parsedUrl = buildLightAppUrl(app);
const hasParams = (app.routeParams ?? []).some((p) => p.key) && parsedUrl !== app.url;
@@ -246,12 +251,12 @@ function AppCard({
{/* 上:图标 + 标题 + 描述 */}
<div>
<div className="mb-3.5 flex items-start gap-4">
<div className={cn("rounded-[5px] p-3 shadow-sm", theme.iconBg)}>
<div className={cn("rounded-[5px] p-3 shadow-sm", cardTheme.iconBg)}>
<Icon className="size-5.5" />
</div>
</div>
<h4 className="mb-2 line-clamp-1 text-base font-bold leading-snug text-zinc-900 transition-colors group-hover:text-[#CF1322] dark:text-[#E8EDF5] dark:group-hover:text-[#4096FF]">
<h4 className={cn("mb-2 line-clamp-1 text-base font-bold leading-snug text-zinc-900 transition-colors dark:text-[#E8EDF5] dark:group-hover:text-[#4096FF]", isLightBlue ? "group-hover:text-[#0062D9]" : "group-hover:text-[#CF1322]")}>
{app.name}
</h4>
@@ -265,7 +270,7 @@ function AppCard({
<div className="mb-4 rounded-[5px] bg-zinc-50/70 p-3 dark:bg-[#0C1836]">
<div className="mb-1 flex items-center justify-between text-[10px] font-semibold text-zinc-400 dark:text-[#6E88B0]">
<span>拼接后目标路由终端:</span>
<span className="text-[9px] font-bold uppercase tracking-wider text-[#CF1322] dark:text-[#4096FF]">
<span className={cn("text-[9px] font-bold uppercase tracking-wider dark:text-[#4096FF]", isLightBlue ? "text-[#0062D9]" : "text-[#CF1322]")}>
自动拼接已激活参
</span>
</div>
@@ -307,7 +312,7 @@ function AppCard({
<button
type="button"
onClick={onOpen}
className="flex items-center justify-center gap-1.5 rounded-[5px] bg-[#CF1322] px-3 py-2 text-xs font-semibold text-white shadow-[0_1px_3px_rgba(207,19,34,0.2)] transition hover:bg-[#A8071A] active:scale-[0.98] dark:bg-[#1677FF] dark:shadow-none dark:hover:bg-[#0958D9]"
className={cn("flex items-center justify-center gap-1.5 rounded-[5px] px-3 py-2 text-xs font-semibold text-white transition active:scale-[0.98] dark:bg-[#1677FF] dark:shadow-none dark:hover:bg-[#0958D9]", isLightBlue ? "bg-[#0062D9] shadow-[0_1px_3px_rgba(0,98,217,0.2)] hover:bg-[#0079FE]" : "bg-[#CF1322] shadow-[0_1px_3px_rgba(207,19,34,0.2)] hover:bg-[#A8071A]")}
>
<span>进入应用</span>
<ArrowUpRight className="size-3.5" />
@@ -9,6 +9,7 @@ import { cn } from "@/lib/utils";
export default function LightAppNoteQAPage() {
const { theme } = useTheme();
const isDark = theme === "dark";
const isLightBlue = theme === 'lightblue';
const [question, setQuestion] = useState("");
const handleSubmit = () => {
@@ -111,7 +112,9 @@ export default function LightAppNoteQAPage() {
"flex h-7 w-7 shrink-0 items-center justify-center rounded-full transition-colors",
isDark
? "bg-sky-500 text-white hover:bg-sky-400"
: "bg-[#F5222D] text-white hover:bg-[#CF1322]",
: isLightBlue
? "bg-[#0062D9] text-white hover:bg-[#0079FE]"
: "bg-[#F5222D] text-white hover:bg-[#CF1322]",
)}
aria-label="发送"
>
@@ -568,3 +568,108 @@
background: rgba(22, 119, 255, 0.08);
color: var(--color-link);
}
/* ══════════════════════════════════════════════════════════════════════
浅蓝主题覆盖([data-theme="lightblue"])
══════════════════════════════════════════════════════════════════════ */
/* ── 注册应用按钮 ─────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-primary-btn {
background-color: #0062D9;
box-shadow: 0 2px 6px rgba(0, 98, 217, 0.2);
}
[data-theme="lightblue"] .light-app-management-page .lam-primary-btn:hover {
background-color: #0079FE;
}
[data-theme="lightblue"] .light-app-management-page .lam-primary-btn:active {
background-color: #0056C6;
}
/* ── 搜索框 focus ────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-search-input:focus {
border-color: rgba(0, 98, 217, 0.4);
box-shadow: 0 0 0 4px rgba(0, 98, 217, 0.1);
}
/* ── 视图切换激活态 ──────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-view-toggle-btn.is-active {
color: #0062D9;
}
/* ── 结果计数 ───────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-count strong {
color: #0062D9;
}
/* ── 表格行名 hover ──────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-table tr:hover .lam-row-name {
color: #0062D9;
}
/* ── 参数弹窗 ───────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-param-popover-close {
color: #0062D9;
}
[data-theme="lightblue"] .light-app-management-page .lam-param-key {
color: #0062D9;
}
/* ── 卡片标题 hover ──────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-card:hover .lam-card-title {
color: #0062D9;
}
/* ── 弹窗图标 / 关闭按钮 ─────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-dialog-icon {
background-color: #EAF4FF;
color: #0062D9;
}
[data-theme="lightblue"] .light-app-management-page .lam-dialog-close:hover {
color: #0062D9;
}
/* ── 添加路由参数按钮 hover ───────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-add-param-btn:hover {
border-color: #0062D9;
color: #0062D9;
}
/* ── 表单输入框 focus ────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-input:focus,
[data-theme="lightblue"] .light-app-management-page .lam-dialog input[type="text"]:focus {
border-color: #0062D9;
box-shadow: 0 0 0 1px #0062D9;
}
[data-theme="lightblue"] .light-app-management-page .lam-dialog [data-slot="input"]:focus-visible,
[data-theme="lightblue"] .light-app-management-page .lam-dialog textarea:focus-visible {
border-color: #0062D9;
box-shadow: 0 0 0 2px rgba(0, 98, 217, 0.16);
}
/* ── TDesign Select focus / hover ────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .t-select:hover .t-input,
[data-theme="lightblue"] .light-app-management-page .t-select:hover .t-input__wrap {
border-color: rgba(0, 98, 217, 0.5);
}
[data-theme="lightblue"] .light-app-management-page .t-select.t-is-focused .t-input,
[data-theme="lightblue"] .light-app-management-page .t-select.t-is-focused .t-input__wrap {
border-color: #0062D9;
box-shadow: 0 0 0 2px rgba(0, 98, 217, 0.16);
}
/* ── 启用开关 ───────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-switch-on {
background-color: #0062D9;
}
/* ── 保存按钮 ───────────────────────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page .lam-dialog-save {
background-color: #0062D9;
box-shadow: 0 2px 8px rgba(0, 98, 217, 0.2);
}
[data-theme="lightblue"] .light-app-management-page .lam-dialog-save:hover {
background-color: #0079FE;
}
[data-theme="lightblue"] .light-app-management-page .lam-dialog-save:active {
background-color: #0056C6;
}
@@ -1,6 +1,12 @@
@import "../../docs/ui规范-深蓝/tokens.css";
/** 轻应用中心列表 / 管理页 —— 深色模式共用页面底图(与 workspace 深蓝主题一致) */
/* ── 浅蓝主题:页面底色轻微蓝染 ──────────────────────────────────────── */
[data-theme="lightblue"] .light-app-management-page,
[data-theme="lightblue"] .light-app-list-page {
background-color: #F9FCFF;
}
.dark .light-app-management-page,
.dark .light-app-list-page {
background-color: var(--color-bg-page);
@@ -475,9 +475,12 @@ export async function streamMultiAgent(
let frameSeq = 0;
const debugLabel = `[stream:${req.agentType}:${req.agentName}]`;
// Stream 帧日志(frame# / delta)仅 opt-in 开启。默认关闭,避免 Step 2 流式期间
// 刷屏(含 wujie 嵌入时子应用 devtools);需要排查 SSE 时在控制台执行:
// `window.__MULTI_AGENT_DEBUG__ = true`
const debugEnabled =
typeof window !== "undefined" &&
(window as unknown as { __MULTI_AGENT_DEBUG__?: boolean }).__MULTI_AGENT_DEBUG__ !== false;
(window as unknown as { __MULTI_AGENT_DEBUG__?: boolean }).__MULTI_AGENT_DEBUG__ === true;
const result: StreamMultiAgentResult = {
dispatched: [],
@@ -194,6 +194,14 @@ export default function RoundtablePlanningPage() {
const prefillClearedRef = useRef(false);
// 共识达成后只向父页面(无界)回传一次交付结果。
const consensusEmittedRef = useRef(false);
/** 上一帧 hasConsensus,用于识别 false→true 的 live 过渡(回显不算)。 */
const prevHasConsensusRef = useRef(false);
const markRestoredConsensusAsEmitted = useCallback((hasConsensus: boolean) => {
prevHasConsensusRef.current = hasConsensus;
if (hasConsensus && inWujieEmbed) {
consensusEmittedRef.current = true;
}
}, [inWujieEmbed]);
// 带 taskId 时,先按任务回显最新草稿再决定是否 autoStart。用 state 而非 ref:
// 解析完成需触发重渲染让 C2 effect 重跑(否则 intentThreadId 先就绪会错过 autoStart)。
// 无 taskId 时初始即「已解析」,autoStart 照常。
@@ -510,8 +518,9 @@ export default function RoundtablePlanningPage() {
setDagExecMode(run.dagExecMode ?? "fast");
setStep3Report(run.step3 ?? null);
step2.hydrateFromDraft(run as unknown as Step2Snapshot);
markRestoredConsensusAsEmitted(Boolean(run.hasConsensus));
},
[step2],
[markRestoredConsensusAsEmitted, step2],
);
const handleSelectStep2Run = useCallback(
@@ -571,6 +580,7 @@ export default function RoundtablePlanningPage() {
setOrchestrationPlan(snapshot.orchestrationPlan ?? null);
setDagExecMode(snapshot.dagExecMode ?? "fast");
step2.hydrateFromDraft(snapshot as unknown as Step2Snapshot);
markRestoredConsensusAsEmitted(Boolean(snapshot.hasConsensus));
},
cancelAllStreams: () => {
step2.abortAllInFlight();
@@ -736,6 +746,7 @@ export default function RoundtablePlanningPage() {
drafts.loadedFromDraftRef.current = false;
// 新一轮研讨 → 允许共识达成后再次向父页面回传。
consensusEmittedRef.current = false;
prevHasConsensusRef.current = false;
// result.mode 决定 Step 2 编排:recommend = 总控自由派活;chain = 按链条顺序派活;
// dag = 分层并行(来源链条带 stages,携带 result.plan)。
setOrchestrationMode(result.mode);
@@ -888,11 +899,17 @@ export default function RoundtablePlanningPage() {
triggerToast("⚙️ 系统管理面板拉取中(暂不开放外部审计)");
}, [buildWujieConsensusPayload, emitConsensusToParent, inWujieEmbed, triggerToast]);
// C4(无界回传):第二步达成共识后,把总控结论 + 各智能体交付一次性广播给父页面。
// 用 ref 防重(共识态会多次触发渲染);非无界环境静默跳过。
// C4(无界回传):第二步**本次 live 研讨** newly 达成共识时,把总控结论 + 各智能体交付广播给父页面。
// 草稿/任务回显(抽屉重开)已在 hydrate 时 markRestoredConsensusAsEmitted,不再重复 emit。
useEffect(() => {
if (!step2.hasConsensus || consensusEmittedRef.current) return;
const prev = prevHasConsensusRef.current;
const now = step2.hasConsensus;
prevHasConsensusRef.current = now;
if (!now || prev) return;
if (consensusEmittedRef.current) return;
if (!inWujieEmbed) return;
consensusEmittedRef.current = true;
emitConsensusToParent();
}, [step2.hasConsensus, inWujieEmbed, emitConsensusToParent]);
@@ -1095,6 +1112,7 @@ export default function RoundtablePlanningPage() {
drafts.setCurrentDraftId(null);
// 重置后新一轮共识仍需回传父页面。
consensusEmittedRef.current = false;
prevHasConsensusRef.current = false;
setCurrentStep(1);
// 同步触发 Step 1 init,而不是依赖 useEffect —— 已经在 Step 1 时
// currentStep 不变,useEffect 不会 re-fire。
@@ -1329,7 +1347,7 @@ export default function RoundtablePlanningPage() {
)}
{/* HEADER */}
<header className="flex shrink-0 items-center justify-between gap-4 border-b border-slate-100 bg-white px-6 py-3 shadow-[0_1px_3px_rgba(0,0,0,0.02)] dark:border-border dark:bg-card dark:shadow-none">
<header className="relative z-[2000] flex shrink-0 items-center justify-between gap-4 border-b border-slate-100 bg-white px-6 py-3 shadow-[0_1px_3px_rgba(0,0,0,0.02)] dark:border-border dark:bg-card dark:shadow-none">
<StepNavigation
currentStep={currentStep}
intentReady={step1.intentReady}
@@ -1385,6 +1403,7 @@ export default function RoundtablePlanningPage() {
<HistoryDropdown
innerRef={drafts.historyDropdownRef}
isDark={isDark}
isOpen={drafts.isHistoryOpen}
setIsOpen={drafts.setIsHistoryOpen}
drafts={drafts.drafts}
@@ -1423,7 +1442,7 @@ export default function RoundtablePlanningPage() {
sidebarExpanded={step2SidebarExpanded}
setSidebarExpanded={setStep2SidebarExpanded}
/>
<main className="flex-1 overflow-hidden p-4 flex gap-4 min-h-0">
<main className="relative z-0 flex-1 overflow-hidden p-4 flex gap-4 min-h-0">
{/* LEFT SIDEBAR */}
<LeftSidebar
currentStep={currentStep}
@@ -1709,6 +1728,7 @@ function StepButton({
interface HistoryDropdownProps {
innerRef: React.MutableRefObject<HTMLDivElement | null>;
isDark: boolean;
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
drafts: ReturnType<typeof useDraftPersistence>["drafts"];
@@ -1730,6 +1750,7 @@ interface HistoryDropdownProps {
function HistoryDropdown(props: HistoryDropdownProps) {
const {
innerRef,
isDark,
isOpen,
setIsOpen,
drafts,
@@ -1745,6 +1766,8 @@ function HistoryDropdown(props: HistoryDropdownProps) {
onCommitRename,
onCancelRename,
} = props;
const panelBg = isDark ? "#122347" : "#ffffff";
const currentBg = isDark ? "#1a2f5a" : "#ecfdf5";
return (
<div className="relative" ref={innerRef}>
@@ -1768,8 +1791,28 @@ function HistoryDropdown(props: HistoryDropdownProps) {
</button>
{isOpen && (
<div className="absolute right-0 top-full mt-2 w-[360px] max-h-[60vh] overflow-y-auto bg-white border border-slate-200 rounded-2xl shadow-xl z-50 dark:bg-[#0d1d3b] dark:border-border">
<div className="px-4 py-3 border-b border-slate-100 flex items-center justify-between sticky top-0 bg-white z-10 dark:bg-[#0d1d3b] dark:border-border">
<div
className="rt-history-dropdown-panel absolute right-0 top-full mt-2 w-[360px] max-h-[60vh] overflow-y-auto border border-slate-200 rounded-2xl shadow-xl z-[1000] dark:border-border"
style={{
background: panelBg,
backgroundColor: panelBg,
backgroundImage: "none",
opacity: 1,
backdropFilter: "none",
WebkitBackdropFilter: "none",
}}
>
<div
className="rt-history-dropdown-header px-4 py-3 border-b border-slate-100 flex items-center justify-between sticky top-0 z-10 dark:border-border"
style={{
background: panelBg,
backgroundColor: panelBg,
backgroundImage: "none",
opacity: 1,
backdropFilter: "none",
WebkitBackdropFilter: "none",
}}
>
<span className="text-xs font-black text-slate-800 tracking-wide dark:text-foreground">历史草稿</span>
<span className="text-[10px] font-mono text-slate-400">{drafts.length} 条</span>
</div>
@@ -1788,7 +1831,11 @@ function HistoryDropdown(props: HistoryDropdownProps) {
const openOrLoad = () =>
isActiveJob && d.jobId ? onOpenJob(d.jobId) : onLoad(d.id);
return (
<li key={d.id} className={`px-3 py-2.5 ${isCurrent ? "bg-emerald-50/40" : ""}`}>
<li
key={d.id}
className="px-3 py-2.5"
style={isCurrent ? { backgroundColor: currentBg } : undefined}
>
<div className="flex items-start gap-2">
<div className="flex-1 min-w-0">
{isRenaming ? (
@@ -110,10 +110,13 @@
--rt-primary-hover: var(--primary);
--rt-primary-soft: var(--accent);
color: var(--foreground);
/* 整页背景换深蓝主题底图(仅深色;浅色保持红白主题不受影响)。
* background-image 叠在 background-color 上 —— 底色作为图加载前/未覆盖区域的回落;
* cover 铺满、fixed 固定不随内容滚动(大屏背板观感,与应用渲染大屏一致)。
* url() 里的 SVG 由 Vite 当独立资源输出(非内联),浏览器缓存。 */
}
/* 整页背景换深蓝主题底图(仅页面根 .roundtable-planning;浅色不受影响)。
* background-image 叠在 background-color 上 —— 底色作为图加载前/未覆盖区域的回落;
* cover 铺满、fixed 固定不随内容滚动(大屏背板观感,与应用渲染大屏一致)。
* url() 里的 SVG 由 Vite 当独立资源输出(非内联),浏览器缓存。 */
.dark .roundtable-planning {
background-color: var(--background);
background-image: url("../../assets/img/layout-bg-theme-dark-blue.svg");
background-size: cover;
@@ -122,6 +125,19 @@
background-attachment: fixed;
}
/* Portal 弹窗(RecommendAgentsDialog 等挂 .roundtable-planning--dark 但不在页面根内):
* 不透明实底、无底图 —— 对齐 §21 Modal 容器色 ZS-004-08。 */
.roundtable-planning--dark:not(.roundtable-planning) {
--background: #122347;
--card: #0c1836;
--popover: #122347;
--muted: #0f1c3d;
--secondary: #1a2f5a;
--accent: #1a2f5a;
background-color: var(--background);
background-image: none;
}
.dark .roundtable-planning ::-webkit-scrollbar-thumb,
.roundtable-planning--dark ::-webkit-scrollbar-thumb {
background: color-mix(in oklch, var(--primary) 45%, var(--border));
@@ -388,7 +404,7 @@
/* 顶栏 */
.dark .roundtable-planning > header,
.roundtable-planning--dark > header {
background-color: var(--card) !important;
background-color: #122347 !important;
border-color: var(--border) !important;
box-shadow: none !important;
}
@@ -407,6 +423,16 @@
color: var(--foreground) !important;
}
/* 历史记录下拉面板:深色下改为不透明实底(避免 token 半透明透出底图)。 */
:is(.dark .roundtable-planning, .roundtable-planning--dark) .rt-history-dropdown-panel {
background-color: #122347 !important;
background-image: none !important;
}
:is(.dark .roundtable-planning, .roundtable-planning--dark) .rt-history-dropdown-header {
background-color: #122347 !important;
}
/* =============================================================================
* 派活链路流程图连接线(DispatchChainModal)。
*
@@ -294,7 +294,7 @@ const Header = ({ collapsed }: HeaderProps) => {
open={notificationOpen}
onOpenChange={setNotificationOpen}
/>
<header className="strategy-app-header theme-transition relative flex h-16 items-center justify-between px-4">
<header className="strategy-app-header theme-transition relative z-[2101] flex h-16 items-center justify-between px-4">
{showTopNav ? (
<>
{/* 左分区(flex-1):菜单靠右贴近中间基座 */}
@@ -23,7 +23,8 @@ export const ActionAnalyzes: React.FC<ActionAnalyzesProps> = ({ title, category,
const isDark = theme === 'dark';
// 主题颜色变量
const cardBg = isDark ? 'bg-slate-800/30' : 'bg-white';
const cardBorder = isDark ? 'border-blue-800/30' : 'border-red-100';
const isLightBlue = theme === 'lightblue';
const cardBorder = isDark ? 'border-blue-800/30' : isLightBlue ? 'border-[#D4E9FF]' : 'border-red-100';
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
const textSecondary = isDark ? 'text-slate-400' : 'text-gray-600';
const textMuted = isDark ? 'text-slate-500' : 'text-gray-400';
@@ -137,7 +138,7 @@ export const ActionAnalyzes: React.FC<ActionAnalyzesProps> = ({ title, category,
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onKeyDown={(e) => handleKeyDown(e)}
className={`w-full pl-10 pr-4 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-red-500/20 transition-colors ${inputBg} ${cardBorder} ${textPrimary} placeholder:${textMuted}`}
className={`w-full pl-10 pr-4 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 ${isLightBlue ? 'focus:ring-[#0062D9]/20' : 'focus:ring-red-500/20'} transition-colors ${inputBg} ${cardBorder} ${textPrimary} placeholder:${textMuted}`}
/>
</div>
{/* 任务列表 */}
@@ -27,7 +27,8 @@ export const ActionColumn: React.FC<ActionColumnProps> = ({ title, category, sub
const isDark = theme === 'dark';
// 主题颜色变量
const cardBg = isDark ? 'bg-slate-800/30' : 'bg-white';
const cardBorder = isDark ? 'border-blue-800/30' : 'border-red-100';
const isLightBlue = theme === 'lightblue';
const cardBorder = isDark ? 'border-blue-800/30' : isLightBlue ? 'border-[#D4E9FF]' : 'border-red-100';
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
const textSecondary = isDark ? 'text-slate-400' : 'text-gray-600';
const textMuted = isDark ? 'text-slate-500' : 'text-gray-400';
@@ -28,6 +28,7 @@ export const KanbanColumn: React.FC<KanbanColumnProps> = ({
}) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
const isLightBlue = theme === 'lightblue';
const [pageNum, setPageNum] = useState(1);
const handlePageChange = async (value: number) => {
@@ -37,7 +38,9 @@ export const KanbanColumn: React.FC<KanbanColumnProps> = ({
const columnClass = isDark
? 'border border-[rgba(67,89,124,0.46)] bg-[linear-gradient(180deg,rgba(18,36,67,0.96),rgba(12,28,54,0.96))] shadow-[0_18px_40px_rgba(3,10,22,0.18)]'
: 'border border-[#E8E8E8] bg-[linear-gradient(180deg,#FFFFFF_0%,#FFF9F9_100%)] shadow-[0_2px_8px_rgba(34,34,34,0.08)]';
: isLightBlue
? 'border border-[#E8E8E8] bg-[linear-gradient(180deg,#FFFFFF_0%,#F4F9FF_100%)] shadow-[0_2px_8px_rgba(34,34,34,0.08)]'
: 'border border-[#E8E8E8] bg-[linear-gradient(180deg,#FFFFFF_0%,#FFF9F9_100%)] shadow-[0_2px_8px_rgba(34,34,34,0.08)]';
return (
<section className={`flex h-full flex-col rounded p-4 ${columnClass}`}>
@@ -54,7 +57,7 @@ export const KanbanColumn: React.FC<KanbanColumnProps> = ({
</h2>
<span
className={`inline-flex rounded-sm px-2 py-0.5 text-xs ${
isDark ? 'bg-[rgba(77,141,255,0.14)] text-[#9CCBFF]' : 'bg-[#FFF1F0] text-[#CF1322]'
isDark ? 'bg-[rgba(77,141,255,0.14)] text-[#9CCBFF]' : isLightBlue ? 'bg-[#EAF4FF] text-[#0062D9]' : 'bg-[#FFF1F0] text-[#CF1322]'
}`}
>
{count}
@@ -86,7 +89,7 @@ export const KanbanColumn: React.FC<KanbanColumnProps> = ({
className={`flex h-full min-h-[220px] flex-col items-center justify-center rounded border border-dashed ${
isDark
? 'border-[rgba(87,111,149,0.42)] bg-[rgba(12,24,44,0.46)] text-slate-400'
: 'border-[#F3C4C8] bg-[#FFF7F7] text-[#A6A6A6]'
: isLightBlue ? 'border-[#AAD2FF] bg-[#F4F9FF] text-[#A6A6A6]' : 'border-[#F3C4C8] bg-[#FFF7F7] text-[#A6A6A6]'
}`}
>
<FileText className="h-8 w-8 opacity-70" />
@@ -33,6 +33,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
const { theme } = useTheme();
const navigate = useNavigate();
const isDark = theme === 'dark';
const isLightBlue = theme === 'lightblue';
const [searchQuery, setSearchQuery] = useState('');
const [showAnalysisModal, setShowAnalysisModal] = useState(false);
@@ -222,7 +223,9 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
const shellClass = isDark
? 'strategy-data h-full overflow-y-auto'
: 'strategy-data h-full overflow-y-auto bg-[linear-gradient(180deg,#FFFDFD_0%,#FFF7F7_46%,#FAFAFA_100%)]';
: isLightBlue
? 'strategy-data h-full overflow-y-auto bg-[linear-gradient(180deg,#F9FCFF_0%,#F4F9FF_46%,#FAFAFA_100%)]'
: 'strategy-data h-full overflow-y-auto bg-[linear-gradient(180deg,#FFFDFD_0%,#FFF7F7_46%,#FAFAFA_100%)]';
const toolbarClass = isDark
? 'border border-[rgba(43,143,254,0.55)] bg-[rgba(3,38,80,0.82)] text-white shadow-[0_16px_36px_rgba(3,10,22,0.2)]'
@@ -238,8 +241,8 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
const metrics = [
{ label: '全部任务', value: unanalyzedTotal + runningTotal + completedTotal, icon: Layers, fg: '#222222', chipBg: '#F5F5F5', chipFg: '#7F7F7F' },
{ label: '未分析', value: unanalyzedTotal, icon: Inbox, fg: '#F5222D', chipBg: '#FEEDED', chipFg: '#F5222D' },
{ label: '分析中', value: runningTotal, icon: Loader, fg: '#1677FF', chipBg: '#EAF4FF', chipFg: '#1677FF' },
{ label: '未分析', value: unanalyzedTotal, icon: Inbox, fg: isLightBlue ? '#0062D9' : '#F5222D', chipBg: isLightBlue ? '#EAF4FF' : '#FEEDED', chipFg: isLightBlue ? '#0062D9' : '#F5222D' },
{ label: '分析中', value: runningTotal, icon: Loader, fg: isLightBlue ? '#0079FE' : '#1677FF', chipBg: isLightBlue ? '#F4F9FF' : '#EAF4FF', chipFg: isLightBlue ? '#0079FE' : '#1677FF' },
{ label: '已完成', value: completedTotal, icon: CircleCheck, fg: '#52C41A', chipBg: '#EEFCF7', chipFg: '#189D72' },
];
@@ -250,11 +253,11 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<div className="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
<div className="space-y-2.5">
<div className="flex items-center gap-1.5 text-xs">
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(108,161,255,0.24)] bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : 'border-[#FFD6D6] bg-[#FFF1F0] text-[#CF1322]'}`}>
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(108,161,255,0.24)] bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : isLightBlue ? 'border-[#AAD2FF] bg-[#EAF4FF] text-[#0062D9]' : 'border-[#FFD6D6] bg-[#FFF1F0] text-[#CF1322]'}`}>
{category}
</span>
<ArrowRight className={`h-3 w-3 ${isDark ? 'text-slate-500' : 'text-[#A6A6A6]'}`} />
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(103,232,165,0.2)] bg-[rgba(34,197,94,0.14)] text-[#89E8B8]' : 'border-[#FFE2B8] bg-[#FFF6E8] text-[#D46B08]'}`}>
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(103,232,165,0.2)] bg-[rgba(34,197,94,0.14)] text-[#89E8B8]' : isLightBlue ? 'border-[#C1EBFB] bg-[#EFFAFE] text-[#2F9ACC]' : 'border-[#FFE2B8] bg-[#FFF6E8] text-[#D46B08]'}`}>
{subCategory}
</span>
</div>
@@ -293,7 +296,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<button
type="button"
className={`inline-flex items-center gap-2 rounded-sm px-4 py-2 text-sm ${isDark ? 'bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : 'bg-[#F5222D] text-white hover:bg-[#CF1322]'}`}
className={`inline-flex items-center gap-2 rounded-sm px-4 py-2 text-sm ${isDark ? 'bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : isLightBlue ? 'bg-[#0062D9] text-white hover:bg-[#0079FE]' : 'bg-[#F5222D] text-white hover:bg-[#CF1322]'}`}
>
<Plus className="h-4 w-4" />
新建任务
@@ -336,7 +339,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<KanbanColumn
title="未分析"
count={unanalyzedTotal}
color={isDark ? 'bg-[#7CC9FF]' : 'bg-[#F5222D]'}
color={isDark ? 'bg-[#7CC9FF]' : isLightBlue ? 'bg-[#0062D9]' : 'bg-[#F5222D]'}
tasks={unanalyzedList}
taskType="unanalyzed"
taskDataType="sentiment"
@@ -396,7 +399,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<button
type="button"
onClick={() => setShowAnalysisModal(false)}
className={`rounded-sm p-2 ${isDark ? 'hover:bg-[rgba(21,42,72,0.9)]' : 'hover:bg-[#FFF1F0]'}`}
className={`rounded-sm p-2 ${isDark ? 'hover:bg-[rgba(21,42,72,0.9)]' : isLightBlue ? 'hover:bg-[#EAF4FF]' : 'hover:bg-[#FFF1F0]'}`}
>
<X className="h-4 w-4" />
</button>
@@ -406,7 +409,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<button
type="button"
onClick={handleOpenTaskDetail}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(110,168,255,0.46)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(110,168,255,0.46)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div>
<div className="font-medium">查看任务详情</div>
@@ -420,10 +423,10 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<button
type="button"
onClick={handleOpenConsultation}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(103,232,165,0.42)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(103,232,165,0.42)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div className="flex items-start gap-3">
<Users className={`mt-0.5 h-5 w-5 ${isDark ? 'text-[#89E8B8]' : 'text-[#CF1322]'}`} />
<Users className={`mt-0.5 h-5 w-5 ${isDark ? 'text-[#89E8B8]' : isLightBlue ? 'text-[#0062D9]' : 'text-[#CF1322]'}`} />
<div>
<div className="font-medium">多智能体会商</div>
<div className={`mt-1 text-sm ${isDark ? 'text-slate-300' : 'text-[#575757]'}`}>
@@ -437,7 +440,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
<button
type="button"
onClick={handleSingleAgentAnalysis}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(167,139,250,0.46)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`flex w-full items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(67,89,124,0.46)] bg-[rgba(15,33,60,0.92)] hover:border-[rgba(167,139,250,0.46)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div className="flex items-start gap-3">
<Bot className={`mt-0.5 h-5 w-5 ${isDark ? 'text-[#C4B5FD]' : 'text-[#7C3AED]'}`} />
@@ -33,6 +33,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
const { theme } = useTheme();
const navigate = useNavigate();
const isDark = theme === 'dark';
const isLightBlue = theme === 'lightblue';
const [searchQuery, setSearchQuery] = useState('');
const [showAnalysisModal, setShowAnalysisModal] = useState(false);
@@ -222,7 +223,9 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
const shellClass = isDark
? 'strategy-data h-full overflow-y-auto text-slate-100'
: 'strategy-data h-full overflow-y-auto bg-[radial-gradient(circle_at_top_left,rgba(245,34,45,0.08),transparent_26%),linear-gradient(180deg,#fffdfd_0%,#fff7f7_42%,#fafafa_100%)] text-[#222222]';
: isLightBlue
? 'strategy-data h-full overflow-y-auto bg-[radial-gradient(circle_at_top_left,rgba(0,98,217,0.06),transparent_26%),linear-gradient(180deg,#F9FCFF_0%,#F4F9FF_42%,#FAFAFA_100%)] text-[#222222]'
: 'strategy-data h-full overflow-y-auto bg-[radial-gradient(circle_at_top_left,rgba(245,34,45,0.08),transparent_26%),linear-gradient(180deg,#fffdfd_0%,#fff7f7_42%,#fafafa_100%)] text-[#222222]';
const toolbarClass = isDark
? 'border border-[rgba(43,143,254,0.55)] bg-[rgba(3,38,80,0.82)] text-slate-100 shadow-[0_16px_36px_rgba(3,10,22,0.2)]'
@@ -242,8 +245,8 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
const metrics = [
{ label: '全部任务', value: unanalyzedTotal + runningTotal + completedTotal, icon: Layers, fg: '#222222', chipBg: '#F5F5F5', chipFg: '#7F7F7F' },
{ label: '未分析', value: unanalyzedTotal, icon: Inbox, fg: '#F5222D', chipBg: '#FEEDED', chipFg: '#F5222D' },
{ label: '分析中', value: runningTotal, icon: Loader, fg: '#1677FF', chipBg: '#EAF4FF', chipFg: '#1677FF' },
{ label: '未分析', value: unanalyzedTotal, icon: Inbox, fg: isLightBlue ? '#0062D9' : '#F5222D', chipBg: isLightBlue ? '#EAF4FF' : '#FEEDED', chipFg: isLightBlue ? '#0062D9' : '#F5222D' },
{ label: '分析中', value: runningTotal, icon: Loader, fg: isLightBlue ? '#0079FE' : '#1677FF', chipBg: isLightBlue ? '#F4F9FF' : '#EAF4FF', chipFg: isLightBlue ? '#0079FE' : '#1677FF' },
{ label: '已完成', value: completedTotal, icon: CircleCheck, fg: '#52C41A', chipBg: '#EEFCF7', chipFg: '#189D72' },
];
@@ -254,11 +257,11 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
<h1 className={`text-[24px] font-semibold leading-8 ${isDark ? 'text-slate-50' : 'text-[#222222]'}`}>{title}</h1>
<div className="flex items-center gap-1.5 text-xs">
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(108,161,255,0.24)] bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : 'border-[#FFD6D6] bg-[#FFF1F0] text-[#CF1322]'}`}>
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(108,161,255,0.24)] bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : isLightBlue ? 'border-[#AAD2FF] bg-[#EAF4FF] text-[#0062D9]' : 'border-[#FFD6D6] bg-[#FFF1F0] text-[#CF1322]'}`}>
{category}
</span>
<ArrowRight className={`h-3 w-3 ${isDark ? 'text-slate-500' : 'text-[#A6A6A6]'}`} />
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(103,232,165,0.2)] bg-[rgba(34,197,94,0.14)] text-[#89E8B8]' : 'border-[#FFE2B8] bg-[#FFF6E8] text-[#D46B08]'}`}>
<span className={`rounded-sm border px-2 py-0.5 font-medium ${isDark ? 'border-[rgba(103,232,165,0.2)] bg-[rgba(34,197,94,0.14)] text-[#89E8B8]' : isLightBlue ? 'border-[#C1EBFB] bg-[#EFFAFE] text-[#2F9ACC]' : 'border-[#FFE2B8] bg-[#FFF6E8] text-[#D46B08]'}`}>
{subCategory}
</span>
</div>
@@ -290,7 +293,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
/>
<button
type="button"
className={`inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-sm px-4 py-2 text-sm ${isDark ? 'bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : 'bg-[#F5222D] text-white hover:bg-[#CF1322]'}`}
className={`inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-sm px-4 py-2 text-sm ${isDark ? 'bg-[rgba(77,141,255,0.16)] text-[#9CCBFF]' : isLightBlue ? 'bg-[#0062D9] text-white hover:bg-[#0079FE]' : 'bg-[#F5222D] text-white hover:bg-[#CF1322]'}`}
>
<Plus className="h-4 w-4" />
新建任务
@@ -332,7 +335,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<KanbanColumn
title="未分析"
count={unanalyzedTotal}
color={isDark ? 'bg-[#7CC9FF]' : 'bg-[#F5222D]'}
color={isDark ? 'bg-[#7CC9FF]' : isLightBlue ? 'bg-[#0062D9]' : 'bg-[#F5222D]'}
tasks={unanalyzedList}
taskType="unanalyzed"
pageIndexSearch={pageIndexChange}
@@ -389,7 +392,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<button
type="button"
onClick={() => setShowAnalysisModal(false)}
className={`rounded-sm p-2 transition ${isDark ? 'hover:bg-[rgba(15,41,74,0.88)]' : 'hover:bg-[#FFF1F0]'}`}
className={`rounded-sm p-2 transition ${isDark ? 'hover:bg-[rgba(15,41,74,0.88)]' : isLightBlue ? 'hover:bg-[#EAF4FF]' : 'hover:bg-[#FFF1F0]'}`}
>
<X className="h-4 w-4" />
</button>
@@ -399,7 +402,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<button
type="button"
onClick={handleOpenTaskDetail}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(96,165,250,0.48)] hover:bg-[rgba(12,38,69,0.96)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(96,165,250,0.48)] hover:bg-[rgba(12,38,69,0.96)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div className="flex items-center gap-4">
<div
@@ -421,12 +424,12 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<button
type="button"
onClick={handleOpenConsultation}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(45,212,191,0.48)] hover:bg-[rgba(10,42,58,0.96)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(45,212,191,0.48)] hover:bg-[rgba(10,42,58,0.96)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div className="flex items-center gap-4">
<div
className={`flex h-10 w-10 items-center justify-center rounded-sm ${isDark ? 'bg-[linear-gradient(180deg,#14B8A6,#22C55E)] text-white' : ''}`}
style={isDark ? undefined : { backgroundColor: '#FEEDED', color: '#CF1322' }}
style={isDark ? undefined : isLightBlue ? { backgroundColor: '#EAF4FF', color: '#0062D9' } : { backgroundColor: '#FEEDED', color: '#CF1322' }}
>
<Users className="h-5 w-5" />
</div>
@@ -443,7 +446,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
<button
type="button"
onClick={handleSingleAgentAnalysis}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(167,139,250,0.48)] hover:bg-[rgba(28,24,58,0.96)]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
className={`group flex items-center justify-between rounded border px-5 py-4 text-left transition ${isDark ? 'border-[rgba(110,136,176,0.24)] bg-[rgba(10,30,54,0.9)] hover:border-[rgba(167,139,250,0.48)] hover:bg-[rgba(28,24,58,0.96)]' : isLightBlue ? 'border-[#E8E8E8] bg-[#F4F9FF] hover:border-[#80BCFF]' : 'border-[#E8E8E8] bg-[#FFF9F9] hover:border-[#F6B0B4]'}`}
>
<div className="flex items-center gap-4">
<div
@@ -55,6 +55,7 @@ export const TaskCard: React.FC<TaskCardProps> = ({
const { setStartConfig } = useChatContext();
const navigate = useNavigate();
const isDark = theme === 'dark';
const isLightBlue = theme === 'lightblue';
const typeConfig = getTaskTypeConfig(task.taskType);
const TypeIcon = typeConfig.icon;
@@ -118,11 +119,13 @@ export const TaskCard: React.FC<TaskCardProps> = ({
const panelClass = isDark
? 'border border-[rgba(67,89,124,0.46)] bg-[rgba(19,39,72,0.9)] shadow-[0_14px_34px_rgba(3,10,22,0.2)] hover:border-[rgba(110,168,255,0.52)]'
: 'border border-[#E8E8E8] bg-white shadow-[0_2px_8px_rgba(34,34,34,0.08)] hover:border-[#F6B0B4] hover:shadow-[0_4px_16px_rgba(34,34,34,0.12)]';
: isLightBlue
? 'border border-[#E8E8E8] bg-white shadow-[0_2px_8px_rgba(34,34,34,0.08)] hover:border-[#80BCFF] hover:shadow-[0_4px_16px_rgba(34,34,34,0.12)]'
: 'border border-[#E8E8E8] bg-white shadow-[0_2px_8px_rgba(34,34,34,0.08)] hover:border-[#F6B0B4] hover:shadow-[0_4px_16px_rgba(34,34,34,0.12)]';
const typeBadgeClass = isDark
? 'bg-[rgba(77,141,255,0.14)] text-[#A9D2FF] border border-[rgba(108,161,255,0.24)]'
: 'bg-[#FFF1F0] text-[#CF1322] border border-[#FFD6D6]';
: isLightBlue ? 'bg-[#EAF4FF] text-[#0062D9] border border-[#AAD2FF]' : 'bg-[#FFF1F0] text-[#CF1322] border border-[#FFD6D6]';
const levelClass = isDark
? 'text-slate-400'
@@ -139,15 +142,15 @@ export const TaskCard: React.FC<TaskCardProps> = ({
: 'bg-[#EAF4FF] text-[#1677FF] border border-[#CDE2FF]'
: isDark
? 'bg-[rgba(96,165,250,0.12)] text-[#8FD1FF] border border-[rgba(143,209,255,0.2)]'
: 'bg-[#FFF1F0] text-[#F5222D] border border-[#FFD6D6]';
: isLightBlue ? 'bg-[#EAF4FF] text-[#0062D9] border border-[#AAD2FF]' : 'bg-[#FFF1F0] text-[#F5222D] border border-[#FFD6D6]';
const actionClass = isCompleted
? isDark
? 'bg-[rgba(12,48,82,0.95)] text-white hover:bg-[rgba(15,60,104,0.98)]'
: 'bg-[#FFF1F0] text-[#CF1322] hover:bg-[#FFE4E6]'
: isLightBlue ? 'bg-[#EAF4FF] text-[#0062D9] hover:bg-[#D4E9FF]' : 'bg-[#FFF1F0] text-[#CF1322] hover:bg-[#FFE4E6]'
: isDark
? 'bg-[linear-gradient(90deg,#1677FF,#22A8F0)] text-white hover:brightness-110'
: 'bg-[linear-gradient(90deg,#F5222D,#FF6B73)] text-white hover:brightness-105';
: isLightBlue ? 'bg-[linear-gradient(90deg,#0062D9,#2B8FFE)] text-white hover:brightness-105' : 'bg-[linear-gradient(90deg,#F5222D,#FF6B73)] text-white hover:brightness-105';
return (
<article
@@ -5,7 +5,7 @@
* Used by TaskAnalyzes, SentimentAnalyzes, ActionAnalyzes and related children.
*/
/* ── CSS variables (light) ─────────────────────────────────────────────── */
/* ── CSS variables (light - red) ─────────────────────────────────────── */
.strategy-data {
--color-main: #cf1322;
--td-brand-color: #ce2d39;
@@ -20,6 +20,18 @@
--input-border: 0 76% 89%;
}
/* ── CSS variables (light - blue) ────────────────────────────────────── */
[data-theme="lightblue"] .strategy-data {
--color-main: #0062D9;
--td-brand-color: #0062D9;
--bg-color: #EAF4FF;
--card-border: #80BCFF;
--card-hover: 211 100% 96%;
--border-color: 211 100% 92%;
--input-border: 211 100% 92%;
}
/* ── CSS variables (dark) ────────────────────────────────────────────── */
.dark .strategy-data {
--color-main: var(--color-primary);