代码修改
This commit is contained in:
1 parent
559340143e
commit
e03ca7b4bd
8 files changed
+249
-85
No files matched your search
@@ -21,6 +21,7 @@ import {
|
|||||||
Grid3X3,
|
Grid3X3,
|
||||||
HelpCircle,
|
HelpCircle,
|
||||||
History,
|
History,
|
||||||
|
Layers,
|
||||||
Layout,
|
Layout,
|
||||||
Library,
|
Library,
|
||||||
List,
|
List,
|
||||||
@@ -209,10 +210,16 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
{ id: "mgmt-agents", label: "智能体管理", icon: Bot, path: "/page/strategy/agents" },
|
{ id: "mgmt-agents", label: "智能体管理", icon: Bot, path: "/page/strategy/agents" },
|
||||||
{
|
{
|
||||||
id: "mgmt-business-chain-mapping",
|
id: "mgmt-business-chain-mapping",
|
||||||
label: "业务链条管理",
|
label: "配置管理",
|
||||||
icon: Network,
|
icon: Network,
|
||||||
path: "/page/strategy/business-chain-mapping",
|
path: "/page/strategy/business-chain-mapping",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "mgmt-business-chains",
|
||||||
|
label: "业务链条配置",
|
||||||
|
icon: Layers,
|
||||||
|
path: "/page/strategy/business-chains",
|
||||||
|
},
|
||||||
{ id: "mgmt-skills", label: "技能管理", icon: Sparkles, path: "/page/strategy/skills" },
|
{ id: "mgmt-skills", label: "技能管理", icon: Sparkles, path: "/page/strategy/skills" },
|
||||||
{ id: "mgmt-memory", label: "记忆管理", icon: Brain, path: "/page/strategy/memory" },
|
{ id: "mgmt-memory", label: "记忆管理", icon: Brain, path: "/page/strategy/memory" },
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* 业务链条管理页 —— 把固定业务码(3Q/6BF/7BF/8BF)绑定到「智能体」+「业务链」。
|
* 配置管理页 —— 把固定业务码(3Q/6BF/7BF/8BF)绑定到「智能体」+「业务链」。
|
||||||
*
|
*
|
||||||
* 表格三列:业务(只读)/ 智能体 / 业务链。编辑模式下后两列为可搜索下拉:
|
* 表格三列:业务(只读)/ 智能体 / 业务链。编辑模式下后两列为可搜索下拉:
|
||||||
* - 智能体来自 `/api/agents`
|
* - 智能体来自 `/api/agents`
|
||||||
@@ -129,7 +129,7 @@ export default function BusinessChainMappingPage() {
|
|||||||
<div className="mx-auto flex min-h-full max-w-[1280px] flex-col gap-5 px-6 py-6 lg:px-8">
|
<div className="mx-auto flex min-h-full max-w-[1280px] flex-col gap-5 px-6 py-6 lg:px-8">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h1 className={`text-[26px] font-semibold tracking-[0.02em] ${isDark ? "text-slate-50" : "text-[#222222]"}`}>
|
<h1 className={`text-[26px] font-semibold tracking-[0.02em] ${isDark ? "text-slate-50" : "text-[#222222]"}`}>
|
||||||
业务链条管理
|
配置管理
|
||||||
</h1>
|
</h1>
|
||||||
<p className={`text-sm ${isDark ? "text-slate-300/80" : "text-slate-500"}`}>
|
<p className={`text-sm ${isDark ? "text-slate-300/80" : "text-slate-500"}`}>
|
||||||
为每个业务绑定智能体与业务链。多智能体会商从对应业务自动取用此处配置的业务链。业务链仅可选择「公共」链条。
|
为每个业务绑定智能体与业务链。多智能体会商从对应业务自动取用此处配置的业务链。业务链仅可选择「公共」链条。
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import { ActionAnalyzes } from "@/strategy-components/components/task-components
|
|||||||
import KnowledgeBaseResourceManagement from "@/strategy-components/components/resource-management/KnowledgeBaseResourceManagement";
|
import KnowledgeBaseResourceManagement from "@/strategy-components/components/resource-management/KnowledgeBaseResourceManagement";
|
||||||
import NetworkActorResourceManagement from "@/strategy-components/components/resource-management/NetworkActorResourceManagement";
|
import NetworkActorResourceManagement from "@/strategy-components/components/resource-management/NetworkActorResourceManagement";
|
||||||
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
|
import RoundtablePlanningPage from "@/roundtable-planning/pages/RoundtablePlanningPage";
|
||||||
|
import BusinessChainListPage from "@/roundtable-planning/pages/BusinessChainListPage";
|
||||||
|
import BusinessChainEditorPage from "@/roundtable-planning/pages/BusinessChainEditorPage";
|
||||||
import "@/roundtable-planning/styles/roundtable-planning.css";
|
import "@/roundtable-planning/styles/roundtable-planning.css";
|
||||||
import AgentChatPage from "./AgentChatPage";
|
import AgentChatPage from "./AgentChatPage";
|
||||||
import AgentsPage from "./AgentsPage";
|
import AgentsPage from "./AgentsPage";
|
||||||
@@ -174,6 +176,8 @@ export default function StrategyRoutes() {
|
|||||||
<Route path="skills/evolution" element={<SkillEvolutionPage />} />
|
<Route path="skills/evolution" element={<SkillEvolutionPage />} />
|
||||||
<Route path="memory" element={<MemoryPage />} />
|
<Route path="memory" element={<MemoryPage />} />
|
||||||
<Route path="business-chain-mapping" element={<BusinessChainMappingPage />} />
|
<Route path="business-chain-mapping" element={<BusinessChainMappingPage />} />
|
||||||
|
<Route path="business-chains" element={<BusinessChainListPage />} />
|
||||||
|
<Route path="roundtable/chains" element={<BusinessChainEditorPage />} />
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="scheduled"
|
path="scheduled"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import StudioNotebooksPage from './StudioNotebooksPage';
|
|||||||
import StudioNotebookDetailPage from './StudioNotebookDetailPage';
|
import StudioNotebookDetailPage from './StudioNotebookDetailPage';
|
||||||
import RoundtablePlanningPage from '@/roundtable-planning/pages/RoundtablePlanningPage';
|
import RoundtablePlanningPage from '@/roundtable-planning/pages/RoundtablePlanningPage';
|
||||||
import BusinessChainEditorPage from '@/roundtable-planning/pages/BusinessChainEditorPage';
|
import BusinessChainEditorPage from '@/roundtable-planning/pages/BusinessChainEditorPage';
|
||||||
|
import BusinessChainListPage from '@/roundtable-planning/pages/BusinessChainListPage';
|
||||||
import DispatchChainPreviewPage from '@/roundtable-planning/pages/DispatchChainPreviewPage';
|
import DispatchChainPreviewPage from '@/roundtable-planning/pages/DispatchChainPreviewPage';
|
||||||
import '@/roundtable-planning/styles/roundtable-planning.css';
|
import '@/roundtable-planning/styles/roundtable-planning.css';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@@ -326,6 +327,14 @@ export default function WorkspaceRoutes({
|
|||||||
</WorkspaceLayout>
|
</WorkspaceLayout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="business-chains"
|
||||||
|
element={
|
||||||
|
<WorkspaceLayout {...layoutProps}>
|
||||||
|
<BusinessChainListPage />
|
||||||
|
</WorkspaceLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
{/* Phase 7 临时预览入口:派活链路流程图弹窗(假数据自测,接通后台后可删) */}
|
{/* Phase 7 临时预览入口:派活链路流程图弹窗(假数据自测,接通后台后可删) */}
|
||||||
<Route
|
<Route
|
||||||
path="roundtable/chain-preview"
|
path="roundtable/chain-preview"
|
||||||
|
|||||||
@@ -40,11 +40,30 @@ export interface BusinessChainListDialogProps {
|
|||||||
onConfigure: (chainId?: string) => void;
|
onConfigure: (chainId?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BusinessChainListDialog({
|
export interface BusinessChainListBodyProps {
|
||||||
open,
|
/**
|
||||||
onOpenChange,
|
* 是否激活(控制何时拉取列表):弹窗里传 `open`(打开才拉),
|
||||||
|
* 独立页面里恒为 `true`。
|
||||||
|
*/
|
||||||
|
active: boolean;
|
||||||
|
/** 进入配置页。带 chainId = 打开并切到该链条;不带 = 空白新建。 */
|
||||||
|
onConfigure: (chainId?: string) => void;
|
||||||
|
/** 列表为空时的「去创建」引导文案差异(弹窗说「点下方配置」,页面说「点右上配置」)。 */
|
||||||
|
emptyHint?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务链条列表主体(筛选 tab + 滚动卡片列表)。
|
||||||
|
*
|
||||||
|
* 从 `BusinessChainListDialog` 抽出,供弹窗与独立配置页(`BusinessChainListPage`)
|
||||||
|
* 复用,保证两处的加载 / 发布 / 卡片渲染逻辑完全一致。外层负责标题栏与「配置」入口、
|
||||||
|
* 以及撑出 `flex flex-col` 高度(本组件用 `flex-1` 占满剩余空间)。
|
||||||
|
*/
|
||||||
|
export function BusinessChainListBody({
|
||||||
|
active,
|
||||||
onConfigure,
|
onConfigure,
|
||||||
}: BusinessChainListDialogProps) {
|
emptyHint,
|
||||||
|
}: BusinessChainListBodyProps) {
|
||||||
const [chains, setChains] = useState<BusinessChain[]>([]);
|
const [chains, setChains] = useState<BusinessChain[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
@@ -65,9 +84,9 @@ export function BusinessChainListDialog({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 每次打开 / 切换筛选都重新拉,保证配置页改动后回来看到的是最新列表。
|
// 每次激活 / 切换筛选都重新拉,保证配置页改动后回来看到的是最新列表。
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!active) return;
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
void (async () => {
|
void (async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -84,7 +103,7 @@ export function BusinessChainListDialog({
|
|||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
}, [open, scope]);
|
}, [active, scope]);
|
||||||
|
|
||||||
const handleTogglePublic = useCallback(
|
const handleTogglePublic = useCallback(
|
||||||
async (chain: BusinessChain) => {
|
async (chain: BusinessChain) => {
|
||||||
@@ -101,6 +120,73 @@ export function BusinessChainListDialog({
|
|||||||
[refresh, scope],
|
[refresh, scope],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* 筛选:我的 / 公共 */}
|
||||||
|
<div className="shrink-0 flex items-center gap-1 rounded-lg border border-border bg-muted/40 p-0.5 self-start">
|
||||||
|
{(["mine", "public"] as const).map((s) => (
|
||||||
|
<button
|
||||||
|
key={s}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setScope(s)}
|
||||||
|
className={cn(
|
||||||
|
"rounded-md px-3 py-1 text-xs font-medium transition",
|
||||||
|
scope === s
|
||||||
|
? "bg-primary text-primary-foreground shadow-sm"
|
||||||
|
: "text-muted-foreground hover:text-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{s === "mine" ? "我的" : "公共"}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="custom-scrollbar -mr-1 min-h-0 flex-1 overflow-y-auto py-3 pr-1">
|
||||||
|
{loading ? (
|
||||||
|
<div className="flex items-center gap-2 px-1 py-10 text-sm text-muted-foreground">
|
||||||
|
<Loader2Icon className="size-4 animate-spin" />
|
||||||
|
正在加载业务链条…
|
||||||
|
</div>
|
||||||
|
) : error ? (
|
||||||
|
<div className="rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive">
|
||||||
|
加载业务链条失败:{error}
|
||||||
|
</div>
|
||||||
|
) : chains.length === 0 ? (
|
||||||
|
<div className="flex flex-col items-center justify-center gap-3 px-6 py-12 text-center">
|
||||||
|
<LayersIcon className="size-10 text-primary/40" />
|
||||||
|
<div className="text-sm font-semibold">
|
||||||
|
{scope === "public" ? "还没有公共链条" : "还没有业务链条"}
|
||||||
|
</div>
|
||||||
|
<p className="max-w-sm text-xs leading-relaxed text-muted-foreground">
|
||||||
|
{scope === "public"
|
||||||
|
? "公共链条是其他账号(或你自己)发布出来、所有人可见的链条。去「我的」里发布一条试试。"
|
||||||
|
: emptyHint ??
|
||||||
|
"业务链条是可复用的有序智能体编排。点击下方「配置」去创建第一条链条。"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-3.5">
|
||||||
|
{chains.map((chain) => (
|
||||||
|
<ChainRow
|
||||||
|
key={chain.id}
|
||||||
|
chain={chain}
|
||||||
|
publishing={publishingId === chain.id}
|
||||||
|
onSettings={() => onConfigure(chain.id)}
|
||||||
|
onTogglePublic={() => handleTogglePublic(chain)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BusinessChainListDialog({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
onConfigure,
|
||||||
|
}: BusinessChainListDialogProps) {
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<DialogContent className="flex max-h-[85vh] flex-col gap-0 sm:max-w-2xl">
|
<DialogContent className="flex max-h-[85vh] flex-col gap-0 sm:max-w-2xl">
|
||||||
@@ -114,61 +200,7 @@ export function BusinessChainListDialog({
|
|||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
{/* 筛选:我的 / 公共 */}
|
<BusinessChainListBody active={open} onConfigure={onConfigure} />
|
||||||
<div className="shrink-0 flex items-center gap-1 rounded-lg border border-border bg-muted/40 p-0.5 self-start">
|
|
||||||
{(["mine", "public"] as const).map((s) => (
|
|
||||||
<button
|
|
||||||
key={s}
|
|
||||||
type="button"
|
|
||||||
onClick={() => setScope(s)}
|
|
||||||
className={cn(
|
|
||||||
"rounded-md px-3 py-1 text-xs font-medium transition",
|
|
||||||
scope === s
|
|
||||||
? "bg-primary text-primary-foreground shadow-sm"
|
|
||||||
: "text-muted-foreground hover:text-foreground",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{s === "mine" ? "我的" : "公共"}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="custom-scrollbar -mr-1 min-h-0 flex-1 overflow-y-auto py-3 pr-1">
|
|
||||||
{loading ? (
|
|
||||||
<div className="flex items-center gap-2 px-1 py-10 text-sm text-muted-foreground">
|
|
||||||
<Loader2Icon className="size-4 animate-spin" />
|
|
||||||
正在加载业务链条…
|
|
||||||
</div>
|
|
||||||
) : error ? (
|
|
||||||
<div className="rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive">
|
|
||||||
加载业务链条失败:{error}
|
|
||||||
</div>
|
|
||||||
) : chains.length === 0 ? (
|
|
||||||
<div className="flex flex-col items-center justify-center gap-3 px-6 py-12 text-center">
|
|
||||||
<LayersIcon className="size-10 text-primary/40" />
|
|
||||||
<div className="text-sm font-semibold">
|
|
||||||
{scope === "public" ? "还没有公共链条" : "还没有业务链条"}
|
|
||||||
</div>
|
|
||||||
<p className="max-w-sm text-xs leading-relaxed text-muted-foreground">
|
|
||||||
{scope === "public"
|
|
||||||
? "公共链条是其他账号(或你自己)发布出来、所有人可见的链条。去「我的」里发布一条试试。"
|
|
||||||
: "业务链条是可复用的有序智能体编排。点击下方「配置」去创建第一条链条。"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="space-y-3.5">
|
|
||||||
{chains.map((chain) => (
|
|
||||||
<ChainRow
|
|
||||||
key={chain.id}
|
|
||||||
chain={chain}
|
|
||||||
publishing={publishingId === chain.id}
|
|
||||||
onSettings={() => onConfigure(chain.id)}
|
|
||||||
onTogglePublic={() => handleTogglePublic(chain)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogFooter className="shrink-0 border-t pt-3 sm:justify-end">
|
<DialogFooter className="shrink-0 border-t pt-3 sm:justify-end">
|
||||||
<Button onClick={() => onConfigure()} className="gap-1.5">
|
<Button onClick={() => onConfigure()} className="gap-1.5">
|
||||||
@@ -246,22 +278,70 @@ function ChainRow({
|
|||||||
<div className="mt-1.5 line-clamp-2 text-sm text-muted-foreground">{chain.description}</div>
|
<div className="mt-1.5 line-clamp-2 text-sm text-muted-foreground">{chain.description}</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 席位名 tag(按顺序,→ 箭头连接发言次序) */}
|
{/* 席位编排:按 stage 分组——并行阶段竖向并列在虚线框里,阶段之间用 → 串联。 */}
|
||||||
<div className="mt-3.5 flex flex-wrap items-center gap-1.5">
|
<ChainSeatsFlow chain={chain} />
|
||||||
{chain.seats.map((seat, i) => (
|
</div>
|
||||||
<Fragment key={seat.agent_id}>
|
);
|
||||||
{i > 0 && <ArrowRightIcon className="size-3.5 shrink-0 text-muted-foreground/50" />}
|
}
|
||||||
<span
|
|
||||||
className={cn(
|
// ── 链条席位编排流(体现「同层并行 · 层间串行」)─────────────────────────────
|
||||||
"rounded-md border px-2 py-1 text-xs font-medium",
|
|
||||||
chainTagClasses(getAvatarTypeFor(seat.agent_id, i)),
|
function ChainSeatsFlow({ chain }: { chain: BusinessChain }) {
|
||||||
)}
|
// 名称回退表:用落库快照(seats)解析 stage 里的 agent_id。
|
||||||
>
|
const seatById = new Map(chain.seats.map((s) => [s.agent_id, s] as const));
|
||||||
{seat.name || seat.agent_id}
|
|
||||||
</span>
|
// 分层来源:带 stages(分层编排)就按 stages 渲染(过滤空阶段);否则每个席位各成
|
||||||
</Fragment>
|
// 一段、顺序串行(线性链,与旧版展示一致)。
|
||||||
))}
|
const stages =
|
||||||
</div>
|
chain.stages && chain.stages.length > 0
|
||||||
|
? chain.stages.filter((s) => s.length > 0)
|
||||||
|
: chain.seats.map((s) => [s.agent_id]);
|
||||||
|
|
||||||
|
// 跨阶段累加的全局序号 —— 决定头像配色,与编辑器 / 展平 seats 顺序对齐。
|
||||||
|
const orderById = new Map<string, number>();
|
||||||
|
let counter = 0;
|
||||||
|
for (const stageIds of stages) {
|
||||||
|
for (const id of stageIds) {
|
||||||
|
orderById.set(id, counter);
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const seatTag = (agentId: string) => {
|
||||||
|
const seat = seatById.get(agentId);
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={agentId}
|
||||||
|
className={cn(
|
||||||
|
"rounded-md border px-2 py-1 text-xs font-medium",
|
||||||
|
chainTagClasses(getAvatarTypeFor(agentId, orderById.get(agentId) ?? 0)),
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{seat?.name || agentId}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-3.5 flex flex-wrap items-center gap-1.5">
|
||||||
|
{stages.map((stageIds, stageIdx) => (
|
||||||
|
<Fragment key={stageIdx}>
|
||||||
|
{stageIdx > 0 && (
|
||||||
|
<ArrowRightIcon className="size-3.5 shrink-0 text-muted-foreground/50" />
|
||||||
|
)}
|
||||||
|
{stageIds.length > 1 ? (
|
||||||
|
// 并行阶段:席位竖向并列在虚线框里,左上角标「并行 N」。
|
||||||
|
<div className="relative flex flex-col gap-1 rounded-lg border border-dashed border-primary/40 bg-primary/[0.04] px-1.5 pb-1.5 pt-2.5">
|
||||||
|
<span className="pointer-events-none absolute -top-2 left-1.5 rounded-full bg-card px-1.5 text-[10px] font-semibold leading-tight text-primary">
|
||||||
|
并行 {stageIds.length}
|
||||||
|
</span>
|
||||||
|
{stageIds.map((id) => seatTag(id))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
seatTag(stageIds[0])
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* 业务链条配置页(独立页面版)。
|
||||||
|
*
|
||||||
|
* 把原本挂在圆桌页顶栏「业务链条」按钮上的 `BusinessChainListDialog` 弹窗内容,
|
||||||
|
* 单独画成一个全屏页面:综合管理 → 业务链条配置 入口进来即是本页。
|
||||||
|
*
|
||||||
|
* - 列表主体复用 `BusinessChainListBody`(与弹窗同一份加载 / 发布 / 卡片逻辑)。
|
||||||
|
* - 顶部「配置」按钮 = 进入编辑器空白新建;卡片「设置」= 进入编辑器并切到该链条。
|
||||||
|
*
|
||||||
|
* 路由 base 感知:用 `useRouteNavigate` 跳转,strategy / workspace 两套路由树下
|
||||||
|
* 都能落到当前 base 的编辑器(`roundtable/chains`)。
|
||||||
|
*/
|
||||||
|
import { LayersIcon, SettingsIcon } from "lucide-react";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useRouteNavigate } from "@/core/route-base";
|
||||||
|
|
||||||
|
import { BusinessChainListBody } from "@/roundtable-planning/components/BusinessChainListDialog";
|
||||||
|
|
||||||
|
export default function BusinessChainListPage() {
|
||||||
|
const navigate = useRouteNavigate();
|
||||||
|
|
||||||
|
// 进入编辑器:带 chainId = 打开并切到该链条;不带 = 空白新建。
|
||||||
|
// 路径写 workspace base,`useRouteNavigate` 会按当前路由 base 改写。
|
||||||
|
const goConfigure = (chainId?: string) => {
|
||||||
|
navigate(
|
||||||
|
chainId
|
||||||
|
? `/page/workspace/roundtable/chains?chainId=${encodeURIComponent(chainId)}`
|
||||||
|
: "/page/workspace/roundtable/chains",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-full min-h-0 flex-col bg-muted/40 text-foreground">
|
||||||
|
{/* 顶栏:标题 + 描述 + 配置入口 */}
|
||||||
|
<header className="shrink-0 border-b border-border bg-card px-6 py-4">
|
||||||
|
<div className="mx-auto flex w-full max-w-3xl items-start justify-between gap-4">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<div className="flex items-center gap-2 text-base font-bold text-foreground">
|
||||||
|
<LayersIcon className="size-5 text-primary" />
|
||||||
|
业务链条配置
|
||||||
|
</div>
|
||||||
|
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
||||||
|
可复用的有序智能体编排。点击卡片「设置」可进入编辑器修改该链条;「发布」后所有账号都能在「公共」里查看 / 选用。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button onClick={() => goConfigure()} className="shrink-0 gap-1.5">
|
||||||
|
<SettingsIcon className="size-4" />
|
||||||
|
配置
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* 列表主体(与弹窗共用 BusinessChainListBody) */}
|
||||||
|
<div className="mx-auto flex w-full min-h-0 max-w-3xl flex-1 flex-col px-6 py-4">
|
||||||
|
<BusinessChainListBody
|
||||||
|
active
|
||||||
|
onConfigure={goConfigure}
|
||||||
|
emptyHint="业务链条是可复用的有序智能体编排。点击右上角「配置」去创建第一条链条。"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
+2
-2
@@ -170,7 +170,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
|
|||||||
setShowAnalysisModal(false);
|
setShowAnalysisModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 单智能体分析:用「业务链条管理」里为本业务配置的智能体,跳转到其问答页(新会话),
|
// 单智能体分析:用「配置管理」里为本业务配置的智能体,跳转到其问答页(新会话),
|
||||||
// 把任务名称/简介作为开场消息暂存,由 AgentChatPage 读取 sessionStorage.pendingAgentMessage
|
// 把任务名称/简介作为开场消息暂存,由 AgentChatPage 读取 sessionStorage.pendingAgentMessage
|
||||||
// 自动发出并开始问答。未配置智能体则提示去配置。
|
// 自动发出并开始问答。未配置智能体则提示去配置。
|
||||||
const handleSingleAgentAnalysis = async () => {
|
const handleSingleAgentAnalysis = async () => {
|
||||||
@@ -184,7 +184,7 @@ const SentimentAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCa
|
|||||||
/* ignore → 下面按未配置处理 */
|
/* ignore → 下面按未配置处理 */
|
||||||
}
|
}
|
||||||
if (!agentId) {
|
if (!agentId) {
|
||||||
toast.error('该业务尚未在「业务链条管理」中配置单智能体');
|
toast.error('该业务尚未在「配置管理」中配置单智能体');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const text = [
|
const text = [
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
|
|||||||
setShowAnalysisModal(false);
|
setShowAnalysisModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 单智能体分析:用「业务链条管理」里为本业务配置的智能体,跳转到其问答页(新会话),
|
// 单智能体分析:用「配置管理」里为本业务配置的智能体,跳转到其问答页(新会话),
|
||||||
// 把任务名称/简介作为开场消息暂存,由 AgentChatPage 读取 sessionStorage.pendingAgentMessage
|
// 把任务名称/简介作为开场消息暂存,由 AgentChatPage 读取 sessionStorage.pendingAgentMessage
|
||||||
// 自动发出并开始问答。未配置智能体则提示去配置。
|
// 自动发出并开始问答。未配置智能体则提示去配置。
|
||||||
const handleSingleAgentAnalysis = async () => {
|
const handleSingleAgentAnalysis = async () => {
|
||||||
@@ -184,7 +184,7 @@ const TaskAnalyzes: React.FC<TaskListPageProps> = ({ title, category, subCategor
|
|||||||
/* ignore → 下面按未配置处理 */
|
/* ignore → 下面按未配置处理 */
|
||||||
}
|
}
|
||||||
if (!agentId) {
|
if (!agentId) {
|
||||||
toast.error('该业务尚未在「业务链条管理」中配置单智能体');
|
toast.error('该业务尚未在「配置管理」中配置单智能体');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const text = [
|
const text = [
|
||||||
|
|||||||
Reference in new issue
Block a user