chore: rename agent UI to stylized
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-11 19:48:45 +08:00
parent fe5d571190
commit 8757f76b1f
39 changed files with 183 additions and 177 deletions

View File

@ -308,7 +308,7 @@ const ROLE_LABELS: Record<User["role"], string> = {
guest: "访客用户",
regular: "普通用户",
admin: "管理员",
agent_admin: "智能体管理员",
agent_admin: "风格化管理员",
};
type ToolConfig = {
@ -5931,7 +5931,7 @@ export function AdminSettingsClient() {
<SelectItem value="regular">普通</SelectItem>
<SelectItem value="admin">管理员</SelectItem>
<SelectItem value="agent_admin">
智能体管理员
风格化管理员
</SelectItem>
</SelectContent>
</Select>
@ -9119,9 +9119,9 @@ export function AdminSettingsClient() {
<>
<div className="flex items-center justify-between rounded-lg border p-3">
<div className="space-y-0.5">
<Label htmlFor="agentEnabled">智能体功能</Label>
<Label htmlFor="agentEnabled">风格化功能</Label>
<div className="text-xs text-muted-foreground">
开启后,首页侧边栏显示“智能体”入口,用户可进入独立的智能体工作台;关闭后隐藏该入口。
开启后,首页侧边栏显示“风格化”入口,用户可进入独立的风格化工作台;关闭后隐藏该入口。
</div>
</div>
<Switch
@ -9143,7 +9143,7 @@ export function AdminSettingsClient() {
</Label>
<div className="text-xs text-muted-foreground">
控制无限画布右侧对话框中的 Agent模式
入口,与上面的智能体工作台入口独立。
入口,与上面的风格化工作台入口独立。
</div>
</div>
<Switch
@ -9161,9 +9161,9 @@ export function AdminSettingsClient() {
{siteSettings.agentEnabled && (
<div className="rounded-lg border p-4 space-y-4">
<div>
<div className="font-medium">智能体工作流配置</div>
<div className="font-medium">风格化工作流配置</div>
<div className="text-xs text-muted-foreground mt-1">
智能体页面的功能按钮名称、Prompt
风格化页面的功能按钮名称、Prompt
片段和预览图已迁移到独立子页面,避免网站设置页过于臃肿。原先重复的分类和二级类型配置已不再在这里维护。
</div>
</div>
@ -9171,7 +9171,7 @@ export function AdminSettingsClient() {
<div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
<div className="space-y-1">
<div className="text-sm font-medium">
独立维护智能体功能卡片
独立维护风格化功能卡片
</div>
<div className="text-xs text-muted-foreground">
建议在独立页面中维护每个环节的按钮名称、预览图上传、说明文案和
@ -9181,7 +9181,7 @@ export function AdminSettingsClient() {
<div className="flex flex-wrap gap-2">
<Button asChild>
<Link href="/settings/agent-workflow">
前往智能体工作流配置
前往风格化工作流配置
</Link>
</Button>
<Button asChild variant="outline">

View File

@ -2055,7 +2055,7 @@ export function AgentWorkflowSettingsClient({
throw new Error(message);
}
toast.success("智能体工作流配置已保存");
toast.success("风格化工作流配置已保存");
await mutate();
} catch (error) {
toast.error(error instanceof Error ? error.message : "保存失败");
@ -3056,9 +3056,9 @@ export function AgentWorkflowSettingsClient({
<Sparkles className="h-5 w-5 text-white" />
</div>
<div>
<h1 className="text-xl font-semibold tracking-tight">智能体工作流配置</h1>
<h1 className="text-xl font-semibold tracking-tight">风格化工作流配置</h1>
<p className="text-sm text-muted-foreground">
配置智能体页面的视频海报、素材搜索、品牌模特及工作流步骤
配置风格化页面的视频海报、素材搜索、品牌模特及工作流步骤
</p>
</div>
</div>

View File

@ -13,7 +13,7 @@ export default async function AgentWorkflowPsdTemplatesPage() {
return (
<PsdTemplatesSettingsClient
backHref="/settings/agent-workflow"
backLabel="返回智能体工作流配置"
backLabel="返回风格化工作流配置"
/>
);
}

View File

@ -1146,7 +1146,7 @@ export function PsdTemplatesSettingsClient({
<div>
<h1 className="text-xl font-semibold tracking-tight">PSD 模板配置</h1>
<p className="text-sm text-muted-foreground">
上传 PSD 模板、管理字体库、配置图片和文字槽位,并在智能体结果区直接套版导出
上传 PSD 模板、管理字体库、配置图片和文字槽位,并在风格化结果区直接套版导出
</p>
</div>
</div>

View File

@ -2917,8 +2917,8 @@ function normalizeAgentSupplementPrompt(text: string, presetName?: string | null
if (!normalized) return "";
const escapedPresetName = String(presetName || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const genericPattern = escapedPresetName
? new RegExp(`^请按「${escapedPresetName}」智能体配置顺序处理这\\d+张图片。?$`)
: /^请按「.+」智能体配置顺序处理这\d+张图片。?$/;
? new RegExp(`^请按「${escapedPresetName}」风格化配置顺序处理这\\d+张图片。?$`)
: /^请按「.+」风格化配置顺序处理这\d+张图片。?$/;
if (genericPattern.test(normalized)) {
return "";
}
@ -6848,15 +6848,15 @@ export async function POST(request: Request) {
return NextResponse.json(
{
code: "not_found:chat",
message: "智能体不存在或无权使用",
message: "风格化不存在或无权使用",
},
{ status: 404 },
);
}
if (selectedAgentPreset.type === "text") {
// 生文智能体走常规多模态对话链路:
// - 模型已由前端切到智能体预设模型
// 生文风格化走常规多模态对话链路:
// - 模型已由前端切到风格化预设模型
// - 提示词通过 hiddenPrompt 注入
// - 图片输入沿用普通多模态附件
} else {
@ -6898,7 +6898,7 @@ export async function POST(request: Request) {
return NextResponse.json(
{
code: "bad_request:api",
message: "当前智能体未配置可执行槽位",
message: "当前风格化未配置可执行槽位",
},
{ status: 400 },
);
@ -6935,7 +6935,7 @@ export async function POST(request: Request) {
return NextResponse.json(
{
code: "bad_request:api",
message: `当前智能体需要上传 ${requiredUploadCount} 张图片`,
message: `当前风格化需要上传 ${requiredUploadCount} 张图片`,
},
{ status: 400 },
);
@ -6946,7 +6946,7 @@ export async function POST(request: Request) {
return NextResponse.json(
{
code: "bad_request:api",
message: "当前智能体未配置默认模型",
message: "当前风格化未配置默认模型",
},
{ status: 400 },
);

View File

@ -40,7 +40,7 @@ export async function GET(request: NextRequest) {
);
}
return NextResponse.json(
{ success: false, error: "获取智能体分类失败" },
{ success: false, error: "获取风格化分类失败" },
{ status: 500 }
);
}
@ -74,7 +74,7 @@ export async function POST(request: NextRequest) {
);
}
return NextResponse.json(
{ success: false, error: "创建智能体分类失败" },
{ success: false, error: "创建风格化分类失败" },
{ status: 500 }
);
}

View File

@ -40,7 +40,7 @@ export async function POST(
);
}
return NextResponse.json(
{ success: false, error: "复制智能体失败" },
{ success: false, error: "复制风格化失败" },
{ status: 500 }
);
}

View File

@ -72,7 +72,7 @@ export async function GET(
});
if (!preset) {
return NextResponse.json({ success: false, error: "智能体不存在" }, { status: 404 });
return NextResponse.json({ success: false, error: "风格化不存在" }, { status: 404 });
}
return NextResponse.json({ success: true, data: preset });
@ -81,7 +81,7 @@ export async function GET(
return error.toResponse();
}
return NextResponse.json(
{ success: false, error: "获取智能体失败" },
{ success: false, error: "获取风格化失败" },
{ status: 500 }
);
}
@ -106,7 +106,7 @@ export async function PUT(
});
if (!existingPreset) {
return NextResponse.json({ success: false, error: "智能体不存在" }, { status: 404 });
return NextResponse.json({ success: false, error: "风格化不存在" }, { status: 404 });
}
const canManagePublicPreset =
isAgentWorkflowAdminType(session.user.type) && existingPreset.visibility === "public";
@ -164,7 +164,7 @@ export async function PUT(
);
}
return NextResponse.json(
{ success: false, error: "更新智能体失败" },
{ success: false, error: "更新风格化失败" },
{ status: 500 }
);
}
@ -187,7 +187,7 @@ export async function DELETE(
});
if (!existingPreset) {
return NextResponse.json({ success: false, error: "智能体不存在" }, { status: 404 });
return NextResponse.json({ success: false, error: "风格化不存在" }, { status: 404 });
}
const canManagePublicPreset =
isAgentWorkflowAdminType(session.user.type) && existingPreset.visibility === "public";
@ -201,7 +201,7 @@ export async function DELETE(
});
if (!deleted) {
return NextResponse.json({ success: false, error: "智能体不存在" }, { status: 404 });
return NextResponse.json({ success: false, error: "风格化不存在" }, { status: 404 });
}
return NextResponse.json({ success: true, data: deleted });
@ -210,7 +210,7 @@ export async function DELETE(
return error.toResponse();
}
return NextResponse.json(
{ success: false, error: "删除智能体失败" },
{ success: false, error: "删除风格化失败" },
{ status: 500 }
);
}

View File

@ -130,7 +130,7 @@ export async function GET(request: NextRequest) {
);
}
return NextResponse.json(
{ success: false, error: "获取智能体列表失败" },
{ success: false, error: "获取风格化列表失败" },
{ status: 500 }
);
}
@ -190,7 +190,7 @@ export async function POST(request: NextRequest) {
);
}
return NextResponse.json(
{ success: false, error: "创建智能体失败" },
{ success: false, error: "创建风格化失败" },
{ status: 500 }
);
}

View File

@ -1042,7 +1042,7 @@ const updateSchema = z.object({
.optional(),
});
// PUT /api/site-settings - 更新网站设置(管理员 / 智能体管理员)
// PUT /api/site-settings - 更新网站设置(管理员 / 风格化管理员)
export async function PUT(request: NextRequest) {
try {
const session = await auth();

View File

@ -2268,7 +2268,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
.getState()
.setProject(
id,
requestedAgentMode ? "智能体工作台" : defaultCanvasTitle
requestedAgentMode ? "风格化工作台" : defaultCanvasTitle
);
setWorkflowHydrationSource("empty");
if (!requestedAgentMode) {
@ -7823,7 +7823,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
<div className="-translate-x-1/2 absolute top-4 left-1/2 z-20">
<div className="inline-flex items-center gap-2 rounded-full border border-amber-200 bg-amber-50 px-4 py-2 text-amber-800 text-sm shadow-sm dark:border-amber-900/60 dark:bg-amber-950/80 dark:text-amber-200">
<AlertCircle className="h-4 w-4" />
<span>智能体功能未开启,请联系管理员在系统设置中开启。</span>
<span>风格化功能未开启,请联系管理员在系统设置中开启。</span>
</div>
</div>
) : null;
@ -8003,7 +8003,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
先选择一个生图项目
</h1>
<p className="mt-4 text-sm text-white/55 leading-7 md:text-base">
打开历史项目可以继续沿用之前的生图结果、模式和工作流。只有在你明确点击新建项目时,系统才会创建一个全新的智能体项目。
打开历史项目可以继续沿用之前的生图结果、模式和工作流。只有在你明确点击新建项目时,系统才会创建一个全新的风格化项目。
</p>
</div>
@ -8018,7 +8018,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
<span className="font-medium text-sm">打开历史项目</span>
</div>
<div className="mt-3 text-sm text-white/55 leading-6">
从项目列表里继续昨天或今天的智能体项目,避免生成结果分散在多个空项目中。
从项目列表里继续昨天或今天的风格化项目,避免生成结果分散在多个空项目中。
</div>
</button>
@ -8127,7 +8127,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
syncGeneratedResultsToCanvas={false}
topNavRightSlot={agentProjectNavSlot}
workflowContext={workflowContext}
// 嵌入的智能体选择面板
// 嵌入的风格化选择面板
workflowPromptOptimizationEnabled={appearanceRecognitionEnabled}
workflowStylePanel={
<AgentWorkflowPanelDarkV2
@ -9000,7 +9000,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
<Wand2 className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="top">智能体模式</TooltipContent>
<TooltipContent side="top">风格化模式</TooltipContent>
</Tooltip>
) : null}

View File

@ -23,7 +23,7 @@ const NAV_ITEMS = [
},
{
key: "agent" as const,
label: "智能体",
label: "风格化",
icon: Wand2,
onClick: () => window.location.assign("/canvas?mode=agent"),
},

View File

@ -42,7 +42,7 @@ export function AgentExecutionSnapshotDialog({
<DialogHeader>
<DialogTitle>执行快照</DialogTitle>
<DialogDescription>
查看本次智能体执行时使用的素材图、槽位提示词、参考图与模型。
查看本次风格化执行时使用的素材图、槽位提示词、参考图与模型。
</DialogDescription>
</DialogHeader>
@ -59,7 +59,7 @@ export function AgentExecutionSnapshotDialog({
<div className="space-y-5">
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
<div className="rounded-xl border p-3">
<div className="text-xs text-muted-foreground">智能体</div>
<div className="text-xs text-muted-foreground">风格化</div>
<div className="mt-1 font-medium">{snapshot.presetName}</div>
<div className="mt-1 text-sm text-muted-foreground">
类型:{snapshot.presetType === "video" ? "视频" : "生图"}

View File

@ -578,7 +578,7 @@ export function AgentGenerationWorkspaceDark({
<p className="mt-2 text-sm text-white/30">
{selectedAgentPresetId
? "配置图片槽位后点击开始生成"
: "从左侧选择或创建一个智能体"}
: "从左侧选择或创建一个风格化"}
</p>
</motion.div>
)}

View File

@ -2727,14 +2727,14 @@ export function AgentGenerationWorkspaceDarkV2({
? selectedModelId
: selectedAgentPreset?.defaultModelId || selectedModelId;
if (!resolvedModelId) {
toast.error("当前智能体未配置模型");
toast.error("当前风格化未配置模型");
return;
}
if (
resolvedModelId !== "auto" &&
!selectableModels.some((model) => model.id === resolvedModelId)
) {
toast.error("当前智能体绑定的模型不存在或已停用,请重新编辑智能体模型配置");
toast.error("当前风格化绑定的模型不存在或已停用,请重新编辑风格化模型配置");
return;
}
const parts: Array<{ type: "text"; text: string } | { type: "file"; mediaType: string; name: string; url: string; assetId?: string }> = [];
@ -6104,7 +6104,7 @@ export function AgentGenerationWorkspaceDarkV2({
<DialogHeader>
<DialogTitle>PSD 模板暂时无法打开</DialogTitle>
<DialogDescription>
已拦截本次客户端异常,避免整个智能体工作台被一起打断。
已拦截本次客户端异常,避免整个风格化工作台被一起打断。
</DialogDescription>
</DialogHeader>
<div className="space-y-3 text-sm leading-6 text-white/72">

View File

@ -18,13 +18,13 @@ interface AgentPanelHeaderProps {
}
export function AgentPanelHeader({
title = "智能体",
title = "风格化",
description = "选择模式后,工作台会自动加载对应槽位和生成能力",
searchValue,
onSearchChange,
searchPlaceholder = "搜索智能体...",
searchPlaceholder = "搜索风格化...",
onCreateClick,
createLabel = "新建智能体",
createLabel = "新建风格化",
className,
}: AgentPanelHeaderProps) {
return (

View File

@ -112,7 +112,7 @@ export function AgentPresetCard({
event.stopPropagation();
onFork(preset);
}}
title="另存为我的智能体"
title="另存为我的风格化"
>
<Copy className="h-4 w-4" />
</button>

View File

@ -193,7 +193,7 @@ export function AgentPresetCardNew({
event.stopPropagation();
onFork(preset);
}}
title="另存为我的智能体"
title="另存为我的风格化"
>
<Copy className="h-3.5 w-3.5" />
</motion.button>

View File

@ -130,7 +130,7 @@ export function AgentPresetDialog({
onOpenChange,
initialPreset,
onSaved,
entityLabel = "智能体",
entityLabel = "风格化",
theme = "light",
}: AgentPresetDialogProps) {
const { data: modelsData } = useSWR<{
@ -1010,7 +1010,7 @@ export function AgentPresetDialog({
</div>
) : (
<div className={cn("rounded-lg border border-dashed px-4 py-6 text-sm", isDark ? "border-white/10 bg-black/20 text-white/55" : "text-muted-foreground")}>
还没有配置任何生图分类,请先到“智能体工作流配置 - 生图分类”中新增顶部分类页和三级分类树。
还没有配置任何生图分类,请先到“风格化工作流配置 - 生图分类”中新增顶部分类页和三级分类树。
</div>
)}
</div>

View File

@ -30,11 +30,11 @@ export function AgentPresetPanel({
onSelectPreset,
embedded = false,
layout = "fill",
title = "智能体",
title = "风格化",
description = "选择模式后,工作台会自动加载对应槽位和生成能力",
searchPlaceholder = "搜索智能体",
publicTitle = "公共智能体",
privateTitle = "我的智能体",
searchPlaceholder = "搜索风格化",
publicTitle = "公共风格化",
privateTitle = "我的风格化",
}: AgentPresetPanelProps) {
const [keyword, setKeyword] = useState("");
const [showCreateDialog, setShowCreateDialog] = useState(false);
@ -47,7 +47,7 @@ export function AgentPresetPanel({
sort: "latest",
});
if (!result.success || !result.data) {
throw new Error(result.error || "获取智能体失败");
throw new Error(result.error || "获取风格化失败");
}
return result.data;
}
@ -81,26 +81,26 @@ export function AgentPresetPanel({
const handleForkPreset = async (preset: AgentPreset) => {
const result = await agentService.forkPreset(preset.id, `${preset.name}(副本)`);
if (!result.success || !result.data) {
toast.error(result.error || "复制智能体失败");
toast.error(result.error || "复制风格化失败");
return;
}
toast.success("已另存为我的智能体");
toast.success("已另存为我的风格化");
await mutate();
onSelectPreset(result.data.id);
};
const handleDeletePreset = async (preset: AgentPreset) => {
if (!window.confirm(`确定删除智能体「${preset.name}」吗?`)) {
if (!window.confirm(`确定删除风格化「${preset.name}」吗?`)) {
return;
}
const result = await agentService.deletePreset(preset.id);
if (!result.success) {
toast.error(result.error || "删除智能体失败");
toast.error(result.error || "删除风格化失败");
return;
}
toast.success("智能体已删除");
toast.success("风格化已删除");
if (selectedPresetId === preset.id) {
onSelectPreset(null);
}
@ -164,7 +164,7 @@ export function AgentPresetPanel({
</div>
) : (
<div className="rounded-xl border border-dashed p-4 text-sm text-muted-foreground">
暂无公共智能体
暂无公共风格化
</div>
)}
</section>
@ -186,7 +186,7 @@ export function AgentPresetPanel({
</div>
) : (
<div className="rounded-xl border border-dashed p-4 text-sm text-muted-foreground">
还没有私有智能体,先新建一个吧
还没有私有风格化,先新建一个吧
</div>
)}
</section>
@ -216,7 +216,7 @@ export function AgentPresetPanel({
</div>
) : (
<div className="rounded-xl border border-dashed p-4 text-sm text-muted-foreground">
暂无公共智能体
暂无公共风格化
</div>
)}
</section>
@ -238,7 +238,7 @@ export function AgentPresetPanel({
</div>
) : (
<div className="rounded-xl border border-dashed p-4 text-sm text-muted-foreground">
还没有私有智能体,先新建一个吧
还没有私有风格化,先新建一个吧
</div>
)}
</section>

View File

@ -27,11 +27,11 @@ interface AgentPresetPanelDarkProps {
export function AgentPresetPanelDark({
selectedPresetId,
onSelectPreset,
title = "智能体",
title = "风格化",
description = "选择生图模式开始创作",
searchPlaceholder = "搜索智能体...",
publicTitle = "公共智能体",
privateTitle = "我的智能体",
searchPlaceholder = "搜索风格化...",
publicTitle = "公共风格化",
privateTitle = "我的风格化",
}: AgentPresetPanelDarkProps) {
const [keyword, setKeyword] = useState("");
const [showCreateDialog, setShowCreateDialog] = useState(false);
@ -45,7 +45,7 @@ export function AgentPresetPanelDark({
sort: "latest",
});
if (!result.success || !result.data) {
throw new Error(result.error || "获取智能体失败");
throw new Error(result.error || "获取风格化失败");
}
return result.data;
}
@ -74,24 +74,24 @@ export function AgentPresetPanelDark({
const handleForkPreset = async (preset: AgentPreset) => {
const result = await agentService.forkPreset(preset.id, `${preset.name}(副本)`);
if (!result.success || !result.data) {
toast.error(result.error || "复制智能体失败");
toast.error(result.error || "复制风格化失败");
return;
}
toast.success("已另存为我的智能体");
toast.success("已另存为我的风格化");
await mutate();
onSelectPreset(result.data.id);
};
const handleDeletePreset = async (preset: AgentPreset) => {
if (!window.confirm(`确定删除智能体「${preset.name}」吗?`)) {
if (!window.confirm(`确定删除风格化「${preset.name}」吗?`)) {
return;
}
const result = await agentService.deletePreset(preset.id);
if (!result.success) {
toast.error(result.error || "删除智能体失败");
toast.error(result.error || "删除风格化失败");
return;
}
toast.success("智能体已删除");
toast.success("风格化已删除");
if (selectedPresetId === preset.id) {
onSelectPreset(null);
}
@ -145,7 +145,7 @@ export function AgentPresetPanelDark({
)}
>
<Plus className="h-4 w-4" />
新建智能体
新建风格化
</Button>
</div>
</div>
@ -155,7 +155,7 @@ export function AgentPresetPanelDark({
<main className="mx-auto max-w-[1800px] px-8 py-8">
<ScrollArea className="h-[calc(100vh-120px)]">
<div className="space-y-10 pb-20">
{/* 公共智能体区域 */}
{/* 公共风格化区域 */}
<section>
<motion.div
className="mb-6 flex items-center gap-3"
@ -194,11 +194,11 @@ export function AgentPresetPanelDark({
</AnimatePresence>
</div>
) : (
<EmptyState message="暂无公共智能体" />
<EmptyState message="暂无公共风格化" />
)}
</section>
{/* 私有智能体区域 */}
{/* 私有风格化区域 */}
<section>
<motion.div
className="mb-6 flex items-center gap-3"
@ -232,7 +232,7 @@ export function AgentPresetPanelDark({
</AnimatePresence>
</div>
) : (
<EmptyState message="还没有私有智能体,点击右上角新建一个吧" />
<EmptyState message="还没有私有风格化,点击右上角新建一个吧" />
)}
</section>
</div>

View File

@ -49,7 +49,7 @@ export function AgentPresetPanelDarkV2({
onSelectPreset,
onCreateClick,
embedded = false,
embeddedEntityLabel = "智能体",
embeddedEntityLabel = "风格化",
}: AgentPresetPanelDarkV2Props) {
const { data: session } = useSession();
const [activeTab, setActiveTab] = useState<string>(AGENT_PRESET_LIBRARY_ALL_MODES_ID);
@ -75,7 +75,7 @@ export function AgentPresetPanelDarkV2({
sort: "latest",
});
if (!result.success || !result.data) {
throw new Error(result.error || "获取智能体失败");
throw new Error(result.error || "获取风格化失败");
}
return result.data;
}
@ -235,24 +235,24 @@ export function AgentPresetPanelDarkV2({
const handleForkPreset = async (preset: AgentPreset) => {
const result = await agentService.forkPreset(preset.id, `${preset.name}(副本)`);
if (!result.success || !result.data) {
toast.error(result.error || "复制智能体失败");
toast.error(result.error || "复制风格化失败");
return;
}
toast.success("已另存为我的智能体");
toast.success("已另存为我的风格化");
await mutate();
onSelectPreset(result.data.id);
};
const handleDeletePreset = async (preset: AgentPreset) => {
if (!window.confirm(`确定删除智能体「${preset.name}」吗?`)) {
if (!window.confirm(`确定删除风格化「${preset.name}」吗?`)) {
return;
}
const result = await agentService.deletePreset(preset.id);
if (!result.success) {
toast.error(result.error || "删除智能体失败");
toast.error(result.error || "删除风格化失败");
return;
}
toast.success("智能体已删除");
toast.success("风格化已删除");
if (selectedPresetId === preset.id) {
onSelectPreset(null);
}
@ -499,7 +499,7 @@ export function AgentPresetPanelDarkV2({
</div>
</section>
{/* 智能体卡片网格区域 */}
{/* 风格化卡片网格区域 */}
<section className="pb-20">
<div id="agent-preset-grid" className="mx-auto max-w-[1480px] px-6 lg:px-8 xl:px-10">
{/* 搜索栏 */}

View File

@ -31,11 +31,11 @@ export function AgentPresetPanelNew({
onSelectPreset,
embedded = false,
layout = "fill",
title = "智能体",
title = "风格化",
description = "选择模式后,工作台会自动加载对应槽位和生成能力",
searchPlaceholder = "搜索智能体...",
publicTitle = "公共智能体",
privateTitle = "我的智能体",
searchPlaceholder = "搜索风格化...",
publicTitle = "公共风格化",
privateTitle = "我的风格化",
}: AgentPresetPanelNewProps) {
const [keyword, setKeyword] = useState("");
const [showCreateDialog, setShowCreateDialog] = useState(false);
@ -49,7 +49,7 @@ export function AgentPresetPanelNew({
sort: "latest",
});
if (!result.success || !result.data) {
throw new Error(result.error || "获取智能体失败");
throw new Error(result.error || "获取风格化失败");
}
return result.data;
}
@ -78,24 +78,24 @@ export function AgentPresetPanelNew({
const handleForkPreset = async (preset: AgentPreset) => {
const result = await agentService.forkPreset(preset.id, `${preset.name}(副本)`);
if (!result.success || !result.data) {
toast.error(result.error || "复制智能体失败");
toast.error(result.error || "复制风格化失败");
return;
}
toast.success("已另存为我的智能体");
toast.success("已另存为我的风格化");
await mutate();
onSelectPreset(result.data.id);
};
const handleDeletePreset = async (preset: AgentPreset) => {
if (!window.confirm(`确定删除智能体「${preset.name}」吗?`)) {
if (!window.confirm(`确定删除风格化「${preset.name}」吗?`)) {
return;
}
const result = await agentService.deletePreset(preset.id);
if (!result.success) {
toast.error(result.error || "删除智能体失败");
toast.error(result.error || "删除风格化失败");
return;
}
toast.success("智能体已删除");
toast.success("风格化已删除");
if (selectedPresetId === preset.id) {
onSelectPreset(null);
}
@ -126,7 +126,7 @@ export function AgentPresetPanelNew({
const content = (
<div className="space-y-6 p-5">
{/* 公共智能体区域 */}
{/* 公共风格化区域 */}
<section className="space-y-3">
<AgentSectionHeader
title={publicTitle}
@ -154,11 +154,11 @@ export function AgentPresetPanelNew({
</AnimatePresence>
</div>
) : (
renderEmptyState("暂无公共智能体")
renderEmptyState("暂无公共风格化")
)}
</section>
{/* 私有智能体区域 */}
{/* 私有风格化区域 */}
<section className="space-y-3">
<AgentSectionHeader
title={privateTitle}
@ -183,7 +183,7 @@ export function AgentPresetPanelNew({
</AnimatePresence>
</div>
) : (
renderEmptyState("还没有私有智能体,点击右上角新建一个吧")
renderEmptyState("还没有私有风格化,点击右上角新建一个吧")
)}
</section>
</div>

View File

@ -2659,7 +2659,7 @@ export function AgentPsdTemplateEditorDialog({
) : (
<Sparkles className="mr-2 h-4 w-4" />
)}
应用并导出
{renderedResultUrl ? "重新编辑应用导出" : "应用并导出"}
</Button>
)}
<div className="h-4 w-[1px] bg-white/10" />

View File

@ -209,7 +209,7 @@ export function AgentWorkflowPanel({
<div>
<div className="flex items-center gap-2 text-sm font-semibold">
<Sparkles className="h-4 w-4 text-amber-500" />
智能体工作流
风格化工作流
</div>
<div className="mt-1 text-xs text-muted-foreground">
先完成工作流设定,下一步再进入生图模式执行。

View File

@ -292,7 +292,7 @@ export function AgentWorkflowPanelDark({
<Sparkles className="h-5 w-5 text-white" />
</div>
<div>
<h1 className="text-xl font-bold text-white">智能体工作流</h1>
<h1 className="text-xl font-bold text-white">风格化工作流</h1>
<p className="text-xs text-white/40">配置工作流参数后进入生图模式</p>
</div>
</div>

View File

@ -314,7 +314,7 @@ export function AgentWorkflowPanelNew({
<Sparkles className="h-4 w-4" />
</div>
<h2 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
智能体工作流
风格化工作流
</h2>
</motion.div>
<motion.p

View File

@ -668,6 +668,9 @@ export function AgentPsdTemplateExportPreview({
});
const [imageSize, setImageSize] = useState<ImageSize | null>(null);
const [annotations, setAnnotations] = useState<DimensionAnnotation[]>([]);
const [defaultAnnotationColor, setDefaultAnnotationColor] = useState(
DEFAULT_DIMENSION_COLOR
);
const [selectedAnnotationId, setSelectedAnnotationId] = useState<string>("");
const [isDrawMode, setIsDrawMode] = useState(false);
const [isDownloading, setIsDownloading] = useState(false);
@ -845,7 +848,7 @@ export function AgentPsdTemplateExportPreview({
x2: startPoint.x,
y2: startPoint.y,
label: "",
color: DEFAULT_DIMENSION_COLOR,
color: defaultAnnotationColor,
glow: false,
},
]);
@ -897,6 +900,7 @@ export function AgentPsdTemplateExportPreview({
},
[
attachPointerSession,
defaultAnnotationColor,
enableDimensionAnnotations,
getCoordinateSpace,
isDrawMode,
@ -1487,7 +1491,8 @@ export function AgentPsdTemplateExportPreview({
: "border-white/10 hover:border-white/30"
)}
key={normalizedColor}
onClick={() =>
onClick={() => {
setDefaultAnnotationColor(normalizedColor);
setAnnotations((current) =>
current.map((annotation) =>
annotation.id === selectedAnnotation.id
@ -1497,8 +1502,8 @@ export function AgentPsdTemplateExportPreview({
}
: annotation
)
)
}
);
}}
style={{ backgroundColor: normalizedColor }}
type="button"
/>
@ -1512,6 +1517,7 @@ export function AgentPsdTemplateExportPreview({
const nextColor = normalizeDimensionColor(
event.target.value
);
setDefaultAnnotationColor(nextColor);
setAnnotations((current) =>
current.map((annotation) =>
annotation.id === selectedAnnotation.id

View File

@ -1,4 +1,4 @@
// 智能体深色主题 V2 组件统一导出
// 风格化深色主题 V2 组件统一导出
export { AgentPresetCardDark } from "./AgentPresetCardDark";
export { AgentPresetPanelDarkV2 } from "./AgentPresetPanelDarkV2";
export { AgentGenerationWorkspaceDarkV2 } from "./AgentGenerationWorkspaceDarkV2";

View File

@ -1,4 +1,4 @@
// 智能体深色主题组件统一导出
// 风格化深色主题组件统一导出
export { AgentPresetCardDark } from "./AgentPresetCardDark";
export { AgentPresetPanelDark } from "./AgentPresetPanelDark";
export { AgentWorkflowPanelDark } from "./AgentWorkflowPanelDark";

View File

@ -1,4 +1,4 @@
// 智能体新UI组件统一导出
// 风格化新UI组件统一导出
export { AgentPresetCardNew } from "./AgentPresetCardNew";
export { AgentPresetPanelNew } from "./AgentPresetPanelNew";
export { AgentWorkflowPanelNew } from "./AgentWorkflowPanelNew";

View File

@ -3584,15 +3584,15 @@ export function CanvasChatPanel({
setAttachments(next);
toast.success(
slotCount === 1
? "已添加到智能体图片槽位"
: `已添加到智能体槽位(${inserted}/${slotCount})`
? "已添加到风格化图片槽位"
: `已添加到风格化槽位(${inserted}/${slotCount})`
);
} else if (toAdd.length > 0) {
toast.info("智能体图片槽位已满,请先替换或移除");
toast.info("风格化图片槽位已满,请先替换或移除");
}
if (toAdd.length - inserted > 0) {
toast.info(`还有 ${toAdd.length - inserted} 张未添加,可继续替换智能体图片槽位`);
toast.info(`还有 ${toAdd.length - inserted} 张未添加,可继续替换风格化图片槽位`);
}
setTimeout(() => {
@ -5699,7 +5699,7 @@ export function CanvasChatPanel({
(slotIndex: number) => {
const preferredNode = selectedImageNodes[slotIndex] || selectedImageNodes[0];
const attachment = preferredNode
? getCanvasNodeAttachment(preferredNode, `智能体图片 ${slotIndex + 1}`)
? getCanvasNodeAttachment(preferredNode, `风格化图片 ${slotIndex + 1}`)
: null;
if (!attachment) return false;
@ -7873,7 +7873,7 @@ export function CanvasChatPanel({
}
if (effectiveAttachments.length < agentRequiredUploadCount) {
toast.error("当前智能体需要上传 3 张图片:产品图1、产品图2、模特图");
toast.error("当前风格化需要上传 3 张图片:产品图1、产品图2、模特图");
return;
}
}
@ -7957,7 +7957,7 @@ export function CanvasChatPanel({
const effectiveComposerMode = activeComposerModeRef.current || activeComposerMode;
const effectiveAgentEntryMode = agentEntryModeRef.current || agentEntryMode;
if (!textContent && hasAgentUploadSlots && selectedAgentPreset) {
textContent = `请按「${selectedAgentPreset.name}」智能体配置顺序处理产品图1、产品图2和模特图。`;
textContent = `请按「${selectedAgentPreset.name}」风格化配置顺序处理产品图1、产品图2和模特图。`;
}
if (!textContent && selectedSkillTag) {
textContent = `请按「${selectedSkillTag.name}」标签的要求处理。`;
@ -7987,7 +7987,7 @@ export function CanvasChatPanel({
const title = String(slot.title || slot.uploadLabel || `模板${index + 1}`).trim();
const promptText = String(slot.promptTemplate || "").trim();
if (!promptText) return "";
return `【智能体:${selectedAgentPreset.name}|${title}】\n${promptText}`;
return `【风格化:${selectedAgentPreset.name}|${title}】\n${promptText}`;
})
.filter(Boolean)
.join("\n\n");
@ -8271,12 +8271,12 @@ export function CanvasChatPanel({
if (handledCount > 0) {
toast.success(
handledCount === 1
? "已粘贴图片到智能体槽位"
: `已粘贴 ${handledCount} 张图片到智能体槽位`
? "已粘贴图片到风格化槽位"
: `已粘贴 ${handledCount} 张图片到风格化槽位`
);
}
if (handledCount < files.length) {
toast.info("智能体图片槽位已满,剩余图片未添加");
toast.info("风格化图片槽位已满,剩余图片未添加");
}
void maybeAutoSetCanvasTitle(firstImageUrl);
return;
@ -8411,12 +8411,12 @@ export function CanvasChatPanel({
if (handledCount > 0) {
toast.success(
handledCount === 1
? "图片已添加到智能体槽位"
: `已添加 ${handledCount} 张图片到智能体槽位`
? "图片已添加到风格化槽位"
: `已添加 ${handledCount} 张图片到风格化槽位`
);
}
if (handledCount < files.length) {
toast.info("智能体需要的图片槽位已满,剩余图片未添加");
toast.info("风格化需要的图片槽位已满,剩余图片未添加");
}
void maybeAutoSetCanvasTitle(firstImageUrl);
@ -11087,7 +11087,7 @@ export function CanvasChatPanel({
})}
</div>
<div className="mt-1.5 text-[11px] text-muted-foreground">
智能体需要上传 3 张图片:产品图1、产品图2、模特图;已选主 SKU / 搭配 SKU 的素材图会优先进入前两个产品槽位,模特图继续手动上传或替换。
风格化需要上传 3 张图片:产品图1、产品图2、模特图;已选主 SKU / 搭配 SKU 的素材图会优先进入前两个产品槽位,模特图继续手动上传或替换。
</div>
</div>
)}

View File

@ -1574,12 +1574,12 @@ export function LovartHome({
type="button"
className="flex h-10 w-10 items-center justify-center rounded-full hover:bg-black/5"
onClick={() => router.push("/canvas?mode=agent")}
title="智能体"
title="风格化"
>
<Wand2 className="h-[18px] w-[18px]" />
</button>
</TooltipTrigger>
<TooltipContent side="right">智能体</TooltipContent>
<TooltipContent side="right">风格化</TooltipContent>
</Tooltip>
) : null}
<Tooltip>

View File

@ -174,8 +174,8 @@ export function TopNavbar({
if (trimmed === "图片编辑") {
return "编辑";
}
if (trimmed === "智能体") {
return "智能";
if (trimmed === "风格化") {
return "风格";
}
if (trimmed === "视频画布") {
return "视频";
@ -588,18 +588,18 @@ export function TopNavbar({
<span className={navLabelClass}>{getShortLabel("图片编辑")}</span>
</Button>
{/* 智能体模式 */}
{/* 风格化模式 */}
{agentEnabled && (
<button
className={navItemBaseClass}
onClick={() => {
window.location.href = "/canvas?mode=agent";
}}
title="智能体"
title="风格化"
type="button"
>
<Wand2 className="h-5 w-5" />
<span className={navLabelClass}>{getShortLabel("智能体")}</span>
<span className={navLabelClass}>{getShortLabel("风格化")}</span>
</button>
)}
@ -644,7 +644,7 @@ export function TopNavbar({
</a>
</div>
{/* 系统设置(管理员 / 智能体管理员可见)*/}
{/* 系统设置(管理员 / 风格化管理员可见)*/}
{(isAdmin || settingsHref) && (
<div className="pb-4">
<a

View File

@ -64,7 +64,7 @@ export const AGENT_DETAIL_GENERATION_MODE_OPTIONS: Array<{
{
value: "classic",
label: "经典详情",
description: "整页直接生图,适合当前智能体页快速生成。",
description: "整页直接生图,适合当前风格化页快速生成。",
},
{
value: "agent_layout",

View File

@ -16,7 +16,7 @@ export const AGENT_WORKFLOW_BRAND_IMPORT_ACCEPT = ".xlsx,.xls,.csv";
const BRAND_SHEET_NAME = "品牌树模板";
const INSTRUCTION_SHEET_NAME = "填写说明";
const TEMPLATE_FILE_NAME = "智能体品牌树导入模板";
const TEMPLATE_FILE_NAME = "风格化品牌树导入模板";
const STATIC_HEADER_ALIASES = {
brandName: ["品牌", "品牌名称", "brand", "brandname"],

View File

@ -1960,7 +1960,7 @@ async function validateAgentDefaultModel(params: {
if (!isVideoModel) {
throw new ChatSDKError(
"bad_request:database",
"视频智能体只能选择视频模型"
"视频风格化只能选择视频模型"
);
}
return model;
@ -1974,7 +1974,7 @@ async function validateAgentDefaultModel(params: {
if (isVideoModel || !isMultimodal) {
throw new ChatSDKError(
"bad_request:database",
"生文智能体只能选择带多模态标签的模型"
"生文风格化只能选择带多模态标签的模型"
);
}
return model;
@ -1983,7 +1983,7 @@ async function validateAgentDefaultModel(params: {
if (isVideoModel || !model.supportsImageGen) {
throw new ChatSDKError(
"bad_request:database",
"生图智能体只能选择支持生图的模型"
"生图风格化只能选择支持生图的模型"
);
}
@ -2295,10 +2295,10 @@ async function validateAgentPresetSlots(params: {
}) {
const slots = Array.isArray(params.slots) ? params.slots : [];
if (slots.length === 0) {
throw new ChatSDKError("bad_request:database", "智能体至少需要配置 1 个槽位");
throw new ChatSDKError("bad_request:database", "风格化至少需要配置 1 个槽位");
}
if (slots.length > 20) {
throw new ChatSDKError("bad_request:database", "智能体槽位数量不能超过 20");
throw new ChatSDKError("bad_request:database", "风格化槽位数量不能超过 20");
}
const allAssetIds = Array.from(

View File

@ -382,7 +382,7 @@ export const siteSettings = pgTable("SiteSettings", {
productPlanningEnabled: boolean("productPlanningEnabled").notNull().default(true), // 是否显示并启用商品策划工具
// 无限画布设置
canvasEnabled: boolean("canvasEnabled").notNull().default(true), // 是否启用无限画布功能
agentEnabled: boolean("agentEnabled").notNull().default(true), // 是否启用智能体功能
agentEnabled: boolean("agentEnabled").notNull().default(true), // 是否启用风格化功能
realtimeCanvasEnabled: boolean("realtimeCanvasEnabled").notNull().default(true), // 是否显示实时画布入口
canvasDefaultModelId: varchar("canvasDefaultModelId", { length: 128 }), // 画布默认选择的模型ID(null表示智能自动)
canvasAutoModeDefaultModelId: varchar("canvasAutoModeDefaultModelId", { length: 128 }), // 智能自动模式下实际使用的默认生图模型ID
@ -504,7 +504,7 @@ export const generatedImage = pgTable("GeneratedImage", {
export type GeneratedImage = InferSelectModel<typeof generatedImage>;
// 智能体分类表
// 风格化分类表
export const agentPresetCategory = pgTable("AgentPresetCategory", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
name: varchar("name", { length: 64 }).notNull(),
@ -521,7 +521,7 @@ export const agentPresetCategory = pgTable("AgentPresetCategory", {
export type AgentPresetCategory = InferSelectModel<typeof agentPresetCategory>;
// 智能体表
// 风格化表
export const agentPreset = pgTable("AgentPreset", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
ownerUserId: uuid("ownerUserId")
@ -574,7 +574,7 @@ export const agentPreset = pgTable("AgentPreset", {
export type AgentPreset = InferSelectModel<typeof agentPreset>;
// 智能体槽位表(每个槽位=一套提示词 + 一组参考图 + 一张用户上传图)
// 风格化槽位表(每个槽位=一套提示词 + 一组参考图 + 一张用户上传图)
export const agentPresetSlot = pgTable("AgentPresetSlot", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
presetId: uuid("presetId")
@ -1086,7 +1086,7 @@ export const assetMemorySnapshot = pgTable("AssetMemorySnapshot", {
export type AssetMemorySnapshot = InferSelectModel<typeof assetMemorySnapshot>;
// 智能体参考图绑定表
// 风格化参考图绑定表
export const agentPresetReferenceAsset = pgTable("AgentPresetReferenceAsset", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
presetId: uuid("presetId")
@ -1104,7 +1104,7 @@ export const agentPresetReferenceAsset = pgTable("AgentPresetReferenceAsset", {
export type AgentPresetReferenceAsset = InferSelectModel<typeof agentPresetReferenceAsset>;
// 智能体执行快照表
// 风格化执行快照表
export const agentPresetExecutionSnapshot = pgTable("AgentPresetExecutionSnapshot", {
id: uuid("id").primaryKey().notNull().defaultRandom(),
presetId: uuid("presetId")

View File

@ -29,11 +29,11 @@ export const agentCategoryService = {
});
const data = await parseJsonSafely<ApiResponse<AgentCategory[]>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "获取智能体分类失败" };
return { success: false, error: data?.error || "获取风格化分类失败" };
}
return data || { success: false, error: "获取智能体分类失败" };
return data || { success: false, error: "获取风格化分类失败" };
} catch (_error) {
return { success: false, error: "获取智能体分类失败" };
return { success: false, error: "获取风格化分类失败" };
}
},
@ -46,11 +46,11 @@ export const agentCategoryService = {
});
const data = await parseJsonSafely<ApiResponse<AgentCategory>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "创建智能体分类失败" };
return { success: false, error: data?.error || "创建风格化分类失败" };
}
return data || { success: false, error: "创建智能体分类失败" };
return data || { success: false, error: "创建风格化分类失败" };
} catch (_error) {
return { success: false, error: "创建智能体分类失败" };
return { success: false, error: "创建风格化分类失败" };
}
},
};
@ -76,11 +76,11 @@ export const agentService = {
});
const data = await parseJsonSafely<ApiResponse<AgentPresetListResponse>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "获取智能体列表失败" };
return { success: false, error: data?.error || "获取风格化列表失败" };
}
return data || { success: false, error: "获取智能体列表失败" };
return data || { success: false, error: "获取风格化列表失败" };
} catch (_error) {
return { success: false, error: "获取智能体列表失败" };
return { success: false, error: "获取风格化列表失败" };
}
},
@ -89,11 +89,11 @@ export const agentService = {
const response = await fetch(`/api/agents/${id}`, { cache: "no-store" });
const data = await parseJsonSafely<ApiResponse<AgentPreset>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "获取智能体失败" };
return { success: false, error: data?.error || "获取风格化失败" };
}
return data || { success: false, error: "获取智能体失败" };
return data || { success: false, error: "获取风格化失败" };
} catch (_error) {
return { success: false, error: "获取智能体失败" };
return { success: false, error: "获取风格化失败" };
}
},
@ -106,11 +106,11 @@ export const agentService = {
});
const data = await parseJsonSafely<ApiResponse<AgentPreset>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "创建智能体失败" };
return { success: false, error: data?.error || "创建风格化失败" };
}
return data || { success: false, error: "创建智能体失败" };
return data || { success: false, error: "创建风格化失败" };
} catch (_error) {
return { success: false, error: "创建智能体失败" };
return { success: false, error: "创建风格化失败" };
}
},
@ -123,11 +123,11 @@ export const agentService = {
});
const data = await parseJsonSafely<ApiResponse<AgentPreset>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "更新智能体失败" };
return { success: false, error: data?.error || "更新风格化失败" };
}
return data || { success: false, error: "更新智能体失败" };
return data || { success: false, error: "更新风格化失败" };
} catch (_error) {
return { success: false, error: "更新智能体失败" };
return { success: false, error: "更新风格化失败" };
}
},
@ -138,11 +138,11 @@ export const agentService = {
});
const data = await parseJsonSafely<ApiResponse<AgentPreset>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "删除智能体失败" };
return { success: false, error: data?.error || "删除风格化失败" };
}
return data || { success: false, error: "删除智能体失败" };
return data || { success: false, error: "删除风格化失败" };
} catch (_error) {
return { success: false, error: "删除智能体失败" };
return { success: false, error: "删除风格化失败" };
}
},
@ -155,11 +155,11 @@ export const agentService = {
});
const data = await parseJsonSafely<ApiResponse<AgentPreset>>(response);
if (!response.ok) {
return { success: false, error: data?.error || "复制智能体失败" };
return { success: false, error: data?.error || "复制风格化失败" };
}
return data || { success: false, error: "复制智能体失败" };
return data || { success: false, error: "复制风格化失败" };
} catch (_error) {
return { success: false, error: "复制智能体失败" };
return { success: false, error: "复制风格化失败" };
}
},
};