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:
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 = () => {
|
||||
|
||||
@@ -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" />
|
||||
|
||||
+15
-12
@@ -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
|
||||
|
||||
+13
-1
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user