代码泰囧

This commit is contained in:
fengxiangdebaozi committed 2026-07-23 16:27:35 +08:00
1 parent 21722b9f5a
commit f32de510fe
7 files changed
+178 -25

No files matched your search

@@ -500,12 +500,12 @@ export function PositionBuiltinAgentChat({
return (
<ThreadContext.Provider value={threadContextValue}>
<div className="flex min-h-0 flex-1 flex-col">
<header className="flex min-h-12 shrink-0 items-center gap-2 border-b border-slate-100 px-4 py-2 dark:border-[#2b8ffe]/20">
<span className="flex size-7 items-center justify-center rounded-lg bg-primary/10 text-primary">
<div className="position-roundtable-agent-analysis-page position-roundtable-builtin-chat flex min-h-0 flex-1 flex-col">
<header className="position-roundtable-agent-header flex min-h-12 shrink-0 items-center gap-2 border-b border-slate-100 px-4 py-2 dark:border-[#2b8ffe]/20">
<span className="position-roundtable-agent-avatar flex size-7 items-center justify-center rounded-lg bg-primary/10 text-primary">
{canWrite ? <Icon className="size-4" /> : <LockKeyhole className="size-3.5" />}
</span>
<div className="min-w-0 flex-1">
<div className="position-roundtable-agent-title min-w-0 flex-1">
<h2 className="truncate text-sm font-extrabold text-slate-900 dark:text-[#e8edf5]">
{agentDisplayName}
</h2>
@@ -536,7 +536,7 @@ export function PositionBuiltinAgentChat({
</header>
{persistedArtifacts.length > 0 && (
<section className="shrink-0 border-b border-slate-100 bg-slate-50/70 px-4 py-2.5 dark:border-[#2b8ffe]/20 dark:bg-[#032650]/50">
<section className="position-roundtable-agent-artifacts shrink-0 border-b border-slate-100 bg-slate-50/70 px-4 py-2.5 dark:border-[#2b8ffe]/20 dark:bg-[#032650]/50">
<div className="mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-[#c5cfe0]">
<FileText className="size-3.5 text-primary" />
阶段产物
@@ -572,7 +572,7 @@ export function PositionBuiltinAgentChat({
{boundThreadId ? (
<MessageList
className="min-h-0 flex-1"
className="position-roundtable-agent-message-list min-h-0 flex-1"
threadId={boundThreadId}
thread={thread}
paddingBottom={24}
@@ -613,7 +613,7 @@ export function PositionBuiltinAgentChat({
</div>
)}
<div className="shrink-0 border-t border-slate-100 px-4 py-3 dark:border-[#2b8ffe]/20">
<div className="position-roundtable-agent-composer-bar shrink-0 border-t border-slate-100 px-4 py-3 dark:border-[#2b8ffe]/20">
<PositionAgentInput
className="w-full"
isNewThread={!boundThreadId}
@@ -71,10 +71,10 @@ export function PositionIntentInput({
const fileInputRef = useRef<HTMLInputElement>(null);
return (
<div className="position-roundtable-intent-input shrink-0 border-t border-slate-200 bg-[#f7faff] px-4 py-3 dark:border-[#2b8ffe]/35 dark:bg-[#071a38]">
<div className="relative overflow-hidden rounded-[4px] border border-slate-300 bg-white shadow-[0_2px_10px_rgba(15,23,42,0.08)] transition-all focus-within:border-primary focus-within:ring-2 focus-within:ring-[var(--brand-200)]/45 dark:border-[#2b8ffe]/55 dark:bg-[#0d2855] dark:shadow-none dark:focus-within:border-[#56baff] dark:focus-within:ring-[#2b8ffe]/25">
<div className="position-roundtable-intent-input position-roundtable-intent-composer shrink-0 border-t border-slate-200 bg-[#f7faff] px-4 py-3 dark:border-[#2b8ffe]/35 dark:bg-[#071a38]">
<div className="position-roundtable-intent-composer-frame relative overflow-hidden rounded-[4px] border border-slate-300 bg-white shadow-[0_2px_10px_rgba(15,23,42,0.08)] transition-all focus-within:border-primary focus-within:ring-2 focus-within:ring-[var(--brand-200)]/45 dark:border-[#2b8ffe]/55 dark:bg-[#0d2855] dark:shadow-none dark:focus-within:border-[#56baff] dark:focus-within:ring-[#2b8ffe]/25">
{attachedFiles.length > 0 && (
<div className="mx-3 mb-2 flex flex-wrap gap-1.5 border-b border-slate-100 pb-2 pt-2.5 dark:border-[#2b8ffe]/25">
<div className="position-roundtable-intent-attachments mx-3 mb-2 flex flex-wrap gap-1.5 border-b border-slate-100 pb-2 pt-2.5 dark:border-[#2b8ffe]/25">
{attachedFiles.map((file, index) => (
<span
key={`${file.name}-${file.size}-${index}`}
@@ -113,7 +113,7 @@ export function PositionIntentInput({
? "也可在此输入自定义回答(Enter 发送 / Shift+Enter 换行)"
: "请输入补充信息 / 回答问题 / 继续澄清(Enter 发送 / Shift+Enter 换行)"
}
className="min-h-[74px] w-full max-h-80 bg-transparent px-3 py-2.5 text-sm font-normal leading-relaxed text-slate-700 placeholder:text-slate-400 focus:outline-none dark:text-[#e7f0ff] dark:placeholder:text-[#7e9bc5]"
className="position-roundtable-intent-textarea min-h-[74px] w-full max-h-80 bg-transparent px-3 py-2.5 text-sm font-normal leading-relaxed text-slate-700 placeholder:text-slate-400 focus:outline-none dark:text-[#e7f0ff] dark:placeholder:text-[#7e9bc5]"
maxHeight={320}
maxLength={500}
/>
@@ -154,7 +154,7 @@ export function PositionIntentInput({
Parent pages can still hide optional actions by their stable ids
without changing this component's layout or global input styles.
*/}
<div className="flex flex-wrap items-center gap-3 border-t border-slate-100 bg-white px-3 py-2.5 dark:border-[#2b8ffe]/25 dark:bg-[#0b234c]">
<div className="position-roundtable-intent-toolbar flex flex-wrap items-center gap-3 border-t border-slate-100 bg-white px-3 py-2.5 dark:border-[#2b8ffe]/25 dark:bg-[#0b234c]">
<div className="flex shrink-0 items-center">
<input
ref={fileInputRef}
@@ -171,15 +171,15 @@ export function PositionIntentInput({
onClick={() => fileInputRef.current?.click()}
title="上传参考文件"
aria-label="上传参考文件"
className="flex size-10 items-center justify-center rounded-[4px] border border-slate-200 bg-white text-slate-500 transition hover:border-primary/45 hover:text-primary dark:border-[#2b8ffe]/35 dark:bg-[#102f63] dark:text-[#b9d3f7] dark:hover:bg-[#1a417b] dark:hover:text-[#73c8ff]"
className="position-roundtable-intent-upload-btn flex size-10 items-center justify-center rounded-[4px] border border-slate-200 bg-white text-slate-500 transition hover:border-primary/45 hover:text-primary dark:border-[#2b8ffe]/35 dark:bg-[#102f63] dark:text-[#b9d3f7] dark:hover:bg-[#1a417b] dark:hover:text-[#73c8ff]"
>
<Paperclip className="size-4" />
</button>
</div>
<div className="ml-auto flex min-w-0 flex-wrap items-center justify-end gap-1.5">
<div className="position-roundtable-intent-actions ml-auto flex min-w-0 flex-wrap items-center justify-end gap-1.5">
{modelOptions.length > 0 && (
<div
className="flex h-10 shrink-0 items-center gap-1.5 rounded-[4px] border border-slate-200 bg-white pl-2 text-xs font-bold text-slate-700 shadow-sm dark:border-[#2b8ffe]/35 dark:bg-[#102f63] dark:text-[#b9d3f7]"
className="position-roundtable-intent-model-switch flex h-10 shrink-0 items-center gap-1.5 rounded-[4px] border border-slate-200 bg-white pl-2 text-xs font-bold text-slate-700 shadow-sm dark:border-[#2b8ffe]/35 dark:bg-[#102f63] dark:text-[#b9d3f7]"
title="切换意图理解模型"
>
<Sparkles className="size-3.5 shrink-0 text-primary dark:text-[#73c8ff]" />
@@ -200,7 +200,7 @@ export function PositionIntentInput({
type="button"
onClick={onSend}
disabled={!canSend}
className="flex h-10 shrink-0 items-center gap-1.5 rounded-[4px] bg-primary px-3 text-xs font-bold text-white shadow-[0_2px_8px_rgba(245,34,45,0.15)] transition-all active:scale-[0.98] hover:bg-[var(--brand-900)] disabled:cursor-not-allowed disabled:bg-slate-300 dark:bg-[#1478e8] dark:hover:bg-[#2995ff] dark:disabled:bg-[#28476f]"
className="position-roundtable-intent-send-btn flex h-10 shrink-0 items-center gap-1.5 rounded-[4px] bg-primary px-3 text-xs font-bold text-white shadow-[0_2px_8px_rgba(245,34,45,0.15)] transition-all active:scale-[0.98] hover:bg-[var(--brand-900)] disabled:cursor-not-allowed disabled:bg-slate-300 dark:bg-[#1478e8] dark:hover:bg-[#2995ff] dark:disabled:bg-[#28476f]"
>
{isSending ? <Loader2 className="size-3 animate-spin" /> : <Send className="size-3" />}
{isSending ? "发送中" : "发送"}
@@ -570,12 +570,12 @@ export function PositionNodeChat({
return (
<ThreadContext.Provider value={threadContextValue}>
<div className="flex min-h-0 flex-1 flex-col">
<header className="flex min-h-12 shrink-0 items-center gap-2 border-b border-slate-100 px-4 py-2 dark:border-[#2b8ffe]/20">
<span className="flex size-7 items-center justify-center rounded-lg bg-primary/10 text-primary">
<div className="position-roundtable-agent-analysis-page position-roundtable-node-chat flex min-h-0 flex-1 flex-col">
<header className="position-roundtable-agent-header flex min-h-12 shrink-0 items-center gap-2 border-b border-slate-100 px-4 py-2 dark:border-[#2b8ffe]/20">
<span className="position-roundtable-agent-avatar flex size-7 items-center justify-center rounded-lg bg-primary/10 text-primary">
{node.status === "locked" ? <LockKeyhole className="size-3.5" /> : <Bot className="size-4" />}
</span>
<div className="min-w-0 flex-1">
<div className="position-roundtable-agent-title min-w-0 flex-1">
<h2 className="truncate text-sm font-extrabold text-slate-900 dark:text-[#e8edf5]">
{agentDisplayName}
</h2>
@@ -644,7 +644,7 @@ export function PositionNodeChat({
</header>
{nodeArtifacts.length > 0 && (
<section className="shrink-0 border-b border-slate-100 bg-slate-50/70 px-4 py-2.5 dark:border-[#2b8ffe]/20 dark:bg-[#032650]/50">
<section className="position-roundtable-agent-artifacts shrink-0 border-b border-slate-100 bg-slate-50/70 px-4 py-2.5 dark:border-[#2b8ffe]/20 dark:bg-[#032650]/50">
<div className="mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-[#c5cfe0]">
<FileText className="size-3.5 text-primary" />
节点产物
@@ -680,7 +680,7 @@ export function PositionNodeChat({
{boundThreadId ? (
<MessageList
className="min-h-0 flex-1"
className="position-roundtable-agent-message-list min-h-0 flex-1"
threadId={boundThreadId}
thread={thread}
paddingBottom={24}
@@ -713,7 +713,7 @@ export function PositionNodeChat({
</div>
)}
<div className="shrink-0 border-t border-slate-100 px-4 py-3 dark:border-[#2b8ffe]/20">
<div className="position-roundtable-agent-composer-bar shrink-0 border-t border-slate-100 px-4 py-3 dark:border-[#2b8ffe]/20">
<PositionAgentInput
className="w-full"
isNewThread={!boundThreadId}
@@ -75,6 +75,8 @@ import { listChains } from "@/roundtable-planning/api/chains";
import { Step1Panel } from "@/roundtable-planning/components/Step1Panel";
import { PositionIntentInput } from "@/position-roundtable/components/PositionIntentInput";
import { PositionNodeChat } from "@/position-roundtable/components/PositionNodeChat";
import "@/position-roundtable/styles/intent-understanding.css";
import "@/position-roundtable/styles/agent-analysis.css";
import { getAvatar } from "@/roundtable-planning/components/Avatars";
import { useStep1Intent, type InteractiveMessage } from "@/roundtable-planning/hooks/useStep1Intent";
import type { IntentSummary } from "@/roundtable-planning/api/intent";
@@ -1520,7 +1522,7 @@ export default function PositionRoundtablePage({
[closeSandbox, searchParamsString, setSearchParams],
);
const renderIntentChatPanel = (chainStarted: boolean) => (
<div className="contents">
<div className="position-roundtable-intent-page contents">
{intent.intentInitError && (
<div className="flex shrink-0 items-center justify-between gap-3 border-b border-amber-200 bg-amber-50 px-4 py-2 text-xs text-amber-800 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200">
<span className="line-clamp-2">对话初始化失败:{intent.intentInitError}</span>
@@ -1532,6 +1534,7 @@ export default function PositionRoundtablePage({
{/* Step1Panel retains intent state; only the composer is replaced so this
workspace can evolve its visual language without changing other Step 1 pages. */}
<Step1Panel
rootClassName="position-roundtable-intent-panel"
headerLeftSlot={
<div className="flex min-w-0 items-center gap-2">
<MessageSquareText className="size-4 text-primary" />
@@ -0,0 +1,76 @@
/*
* 岗位会商 - 其他岗位智能体分析页面专属样式
*
* 覆盖范围:
* - 普通业务链节点:PositionNodeChat
* - 内置收口节点:PositionBuiltinAgentChat(方案总结 / 行动规划)
*
* 后续如果要调岗位智能体聊天页、产物条、输入区,优先改这个文件。
*/
.position-roundtable-agent-analysis-page {
--prt-agent-panel-bg: #ffffff;
--prt-agent-header-bg: #ffffff;
--prt-agent-header-border: rgb(241 245 249);
--prt-agent-artifact-bg: rgba(248, 250, 252, 0.72);
--prt-agent-composer-bg: #ffffff;
--prt-agent-border: rgb(241 245 249);
--prt-agent-title-color: rgb(15 23 42);
--prt-agent-muted-color: rgb(100 116 139);
--prt-agent-avatar-bg: rgba(245, 34, 45, 0.1);
--prt-agent-avatar-color: var(--primary);
}
.dark .position-roundtable-agent-analysis-page {
--prt-agent-panel-bg: rgba(3, 38, 80, 0.62);
--prt-agent-header-bg: rgba(3, 38, 80, 0.74);
--prt-agent-header-border: rgba(43, 143, 254, 0.2);
--prt-agent-artifact-bg: rgba(3, 38, 80, 0.5);
--prt-agent-composer-bg: rgba(3, 38, 80, 0.64);
--prt-agent-border: rgba(43, 143, 254, 0.2);
--prt-agent-title-color: #e8edf5;
--prt-agent-muted-color: #8aa0c4;
--prt-agent-avatar-bg: rgba(43, 143, 254, 0.16);
--prt-agent-avatar-color: #73c8ff;
}
.position-roundtable-agent-analysis-page {
background: var(--prt-agent-panel-bg);
}
.position-roundtable-agent-header {
border-color: var(--prt-agent-header-border);
background: var(--prt-agent-header-bg);
}
.position-roundtable-agent-avatar {
background: var(--prt-agent-avatar-bg);
color: var(--prt-agent-avatar-color);
}
.position-roundtable-agent-title h2 {
color: var(--prt-agent-title-color);
}
.position-roundtable-agent-title p {
color: var(--prt-agent-muted-color);
}
.position-roundtable-agent-artifacts {
border-color: var(--prt-agent-border);
background: var(--prt-agent-artifact-bg);
}
.position-roundtable-agent-message-list {
background: var(--prt-agent-panel-bg);
}
.position-roundtable-agent-composer-bar {
border-color: var(--prt-agent-border);
background: var(--prt-agent-composer-bg);
}
.position-roundtable-agent-input {
--prt-agent-input-radius: 14px;
}
@@ -0,0 +1,72 @@
/*
* 岗位会商 - 意图理解页面专属样式
*
* 这个文件只服务 `PositionRoundtablePage` 里的意图理解区域。
* 后续手写样式优先改这里,尽量不要再往 globals.css 或组件 className 里堆。
*/
.position-roundtable-intent-page {
--prt-intent-panel-bg: #ffffff;
--prt-intent-panel-border: rgb(226 232 240);
--prt-intent-composer-bg: #f7faff;
--prt-intent-composer-frame-bg: #ffffff;
--prt-intent-composer-border: rgb(203 213 225);
--prt-intent-toolbar-bg: #ffffff;
--prt-intent-text-color: rgb(51 65 85);
--prt-intent-muted-color: rgb(100 116 139);
--prt-intent-radius: 4px;
}
.dark .position-roundtable-intent-page {
--prt-intent-panel-bg: rgba(3, 38, 80, 0.72);
--prt-intent-panel-border: rgba(43, 143, 254, 0.28);
--prt-intent-composer-bg: #071a38;
--prt-intent-composer-frame-bg: #0d2855;
--prt-intent-composer-border: rgba(43, 143, 254, 0.55);
--prt-intent-toolbar-bg: #0b234c;
--prt-intent-text-color: #e7f0ff;
--prt-intent-muted-color: #8aa0c4;
}
.position-roundtable-intent-panel {
background: var(--prt-intent-panel-bg);
}
.position-roundtable-intent-panel > div:first-child {
border-color: var(--prt-intent-panel-border);
}
.position-roundtable-intent-panel > div:nth-child(2) > div:first-child {
background: var(--prt-intent-panel-bg);
}
.position-roundtable-intent-composer {
background: var(--prt-intent-composer-bg);
}
.position-roundtable-intent-composer-frame {
border-color: var(--prt-intent-composer-border);
border-radius: var(--prt-intent-radius);
background: var(--prt-intent-composer-frame-bg);
}
.position-roundtable-intent-textarea {
color: var(--prt-intent-text-color);
}
.position-roundtable-intent-toolbar {
background: var(--prt-intent-toolbar-bg);
}
.position-roundtable-intent-attachments {
color: var(--prt-intent-muted-color);
}
.position-roundtable-intent-actions {
row-gap: 6px;
}
.position-roundtable-intent-model-switch {
border-radius: var(--prt-intent-radius);
}
@@ -95,6 +95,7 @@ export interface Step1InputAreaProps {
}
export interface Step1PanelProps {
rootClassName?: string;
// ─── State ────────────────────────────────────────────────────
/**
* 头部左侧自定义内容(深链 taskId 模式:用「策划流程」小图取代默认标题)。
@@ -141,6 +142,7 @@ export function Step1Panel(props: Step1PanelProps) {
const {
headerLeftSlot,
headerRightSlot,
rootClassName,
interactiveMessages,
intentThreadId,
intentReady,
@@ -210,7 +212,7 @@ export function Step1Panel(props: Step1PanelProps) {
const headerDzRef = useDesensitizeSubtree<HTMLDivElement>();
return (
<div className="flex-1 flex flex-col min-h-0">
<div className={`flex-1 flex flex-col min-h-0 ${rootClassName ?? ""}`}>
{/* Dialogue Header */}
<div ref={headerDzRef} className="shrink-0 px-6 py-4.5 border-b border-slate-100 flex items-center justify-between gap-3 bg-slate-50/50">
{headerLeftSlot ?? (