chore(ui): sync latest manual canvas and settings updates
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-02-22 16:38:54 +08:00
parent c6c6c3f7bb
commit 9c4e51d3fd
5 changed files with 141 additions and 76 deletions

View File

@ -2316,7 +2316,11 @@ export function AdminSettingsClient() {
{/* 用户管理 */} {/* 用户管理 */}
<TabsContent value="users" className="mt-6"> <TabsContent value="users" className="mt-6">
<Card> <Card>
<CardContent className="pt-6"> <CardHeader>
<CardTitle className="text-xl">用户管理</CardTitle>
<CardDescription>管理所有注册用户及其权限与积分</CardDescription>
</CardHeader>
<CardContent>
{/* 搜索框和同步按钮 */} {/* 搜索框和同步按钮 */}
<div className="mb-4 flex flex-col sm:flex-row gap-3 sm:items-center sm:justify-between"> <div className="mb-4 flex flex-col sm:flex-row gap-3 sm:items-center sm:justify-between">
<Input <Input
@ -2750,7 +2754,7 @@ export function AdminSettingsClient() {
{/* 图片详情弹窗 */} {/* 图片详情弹窗 */}
<Dialog open={!!selectedImage} onOpenChange={(open) => !open && setSelectedImage(null)}> <Dialog open={!!selectedImage} onOpenChange={(open) => !open && setSelectedImage(null)}>
<DialogContent className="max-w-2xl"> <DialogContent className="max-w-3xl max-h-[85vh] overflow-y-auto">
<DialogHeader> <DialogHeader>
<DialogTitle className="flex items-center gap-2"> <DialogTitle className="flex items-center gap-2">
{selectedImage?.recordType === "video" ? "视频详情" : "图片详情"} {selectedImage?.recordType === "video" ? "视频详情" : "图片详情"}
@ -2801,7 +2805,13 @@ export function AdminSettingsClient() {
</div> </div>
<div> <div>
<Label className="text-muted-foreground">模型</Label> <Label className="text-muted-foreground">模型</Label>
<p>{selectedImage.modelId || "未知"}</p> <p>
{analyticsData?.modelDetailStats?.find(
(s) => s.modelId === selectedImage.modelId
)?.modelName ||
selectedImage.modelId ||
"未知"}
</p>
</div> </div>
{selectedImage.recordType !== "video" ? ( {selectedImage.recordType !== "video" ? (
<div> <div>
@ -3382,7 +3392,11 @@ export function AdminSettingsClient() {
{/* 网站设置 */} {/* 网站设置 */}
<TabsContent value="site" className="mt-6"> <TabsContent value="site" className="mt-6">
<Card> <Card>
<CardContent className="space-y-6 pt-6"> <CardHeader>
<CardTitle className="text-xl">网站基本设置</CardTitle>
<CardDescription>配置网站名称、LOGO、功能开关等</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="siteName">网站名称</Label> <Label htmlFor="siteName">网站名称</Label>
<Input <Input
@ -5427,7 +5441,11 @@ export function AdminSettingsClient() {
<TabsContent value="questions" className="mt-6"> <TabsContent value="questions" className="mt-6">
<Card> <Card>
<CardContent className="space-y-4 pt-6"> <CardHeader>
<CardTitle className="text-xl">快捷短语</CardTitle>
<CardDescription>配置聊天输入框下方的预设快捷提问</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{questions.map((q, index) => ( {questions.map((q, index) => (
<div key={index} className="flex gap-2"> <div key={index} className="flex gap-2">
<Input <Input
@ -5458,7 +5476,11 @@ export function AdminSettingsClient() {
{/* 认证设置 */} {/* 认证设置 */}
<TabsContent value="auth" className="mt-6"> <TabsContent value="auth" className="mt-6">
<Card> <Card>
<CardContent className="space-y-6 pt-6"> <CardHeader>
<CardTitle className="text-xl">登录认证</CardTitle>
<CardDescription>配置开放注册、钉钉登录与Google登录</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="space-y-0.5"> <div className="space-y-0.5">
<Label>开放注册</Label> <Label>开放注册</Label>
@ -5673,7 +5695,11 @@ export function AdminSettingsClient() {
{/* 系统通知设置 */} {/* 系统通知设置 */}
<TabsContent value="notification" className="mt-6"> <TabsContent value="notification" className="mt-6">
<Card> <Card>
<CardContent className="space-y-6 pt-6"> <CardHeader>
<CardTitle className="text-xl">系统通知</CardTitle>
<CardDescription>发布全站公告通知,用户进入系统时可见</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Switch <Switch
id="notification-enabled" id="notification-enabled"
@ -6525,49 +6551,63 @@ export function AdminSettingsClient() {
{/* 抠图API配置 */} {/* 抠图API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle>抠图API配置</CardTitle> <CardTitle className="text-xl">抠图API配置</CardTitle>
<CardDescription> <CardDescription>
配置背景移除API,用于画图标注功能中的抠图处理。支持自部署RMBG、PhotoRoom和AOS云服务。 配置背景移除API,用于画图标注功能中的抠图处理。支持自部署RMBG、PhotoRoom和AOS云服务。
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-6 pt-6"> <CardContent className="space-y-6 pt-6">
{/* 服务提供商选择 */} {/* 服务提供商选择 */}
<div className="space-y-2"> <div className="space-y-3">
<Label>抠图服务提供商</Label> <Label>抠图服务提供商</Label>
<div className="flex gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<label className="flex items-center gap-2 cursor-pointer"> <div
<input className={`relative flex cursor-pointer items-center gap-3 rounded-lg border p-4 transition-all hover:bg-accent ${
type="radio" rmbgConfig.provider === "rmbg" ? "border-primary bg-accent ring-1 ring-primary" : ""
name="rmbgProvider" }`}
value="rmbg" onClick={() => setRmbgConfig({ ...rmbgConfig, provider: "rmbg" })}
checked={rmbgConfig.provider === "rmbg"} >
onChange={() => setRmbgConfig({ ...rmbgConfig, provider: "rmbg" })} <div className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-full border border-primary ${
className="w-4 h-4" rmbgConfig.provider === "rmbg" ? "bg-primary text-primary-foreground" : "bg-transparent"
/> }`}>
<span className="text-sm">RMBG-2.0 (自部署)</span> {rmbgConfig.provider === "rmbg" && <Check className="h-3 w-3" />}
</label> </div>
<label className="flex items-center gap-2 cursor-pointer"> <div className="space-y-1">
<input <p className="text-sm font-medium leading-none">RMBG-2.0 (自部署)</p>
type="radio" </div>
name="rmbgProvider" </div>
value="photoroom"
checked={rmbgConfig.provider === "photoroom"} <div
onChange={() => setRmbgConfig({ ...rmbgConfig, provider: "photoroom" })} className={`relative flex cursor-pointer items-center gap-3 rounded-lg border p-4 transition-all hover:bg-accent ${
className="w-4 h-4" rmbgConfig.provider === "photoroom" ? "border-primary bg-accent ring-1 ring-primary" : ""
/> }`}
<span className="text-sm">PhotoRoom (云服务)</span> onClick={() => setRmbgConfig({ ...rmbgConfig, provider: "photoroom" })}
</label> >
<label className="flex items-center gap-2 cursor-pointer"> <div className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-full border border-primary ${
<input rmbgConfig.provider === "photoroom" ? "bg-primary text-primary-foreground" : "bg-transparent"
type="radio" }`}>
name="rmbgProvider" {rmbgConfig.provider === "photoroom" && <Check className="h-3 w-3" />}
value="aoscdn" </div>
checked={rmbgConfig.provider === "aoscdn"} <div className="space-y-1">
onChange={() => setRmbgConfig({ ...rmbgConfig, provider: "aoscdn" })} <p className="text-sm font-medium leading-none">PhotoRoom (云服务)</p>
className="w-4 h-4" </div>
/> </div>
<span className="text-sm">AOS Segmentation (云服务)</span>
</label> <div
className={`relative flex cursor-pointer items-center gap-3 rounded-lg border p-4 transition-all hover:bg-accent ${
rmbgConfig.provider === "aoscdn" ? "border-primary bg-accent ring-1 ring-primary" : ""
}`}
onClick={() => setRmbgConfig({ ...rmbgConfig, provider: "aoscdn" })}
>
<div className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-full border border-primary ${
rmbgConfig.provider === "aoscdn" ? "bg-primary text-primary-foreground" : "bg-transparent"
}`}>
{rmbgConfig.provider === "aoscdn" && <Check className="h-3 w-3" />}
</div>
<div className="space-y-1">
<p className="text-sm font-medium leading-none">AOS Segmentation</p>
</div>
</div>
</div> </div>
</div> </div>
@ -6710,10 +6750,15 @@ export function AdminSettingsClient() {
关闭时保持原图尺寸,开启时按主体区域裁剪。 关闭时保持原图尺寸,开启时按主体区域裁剪。
</div> </div>
</div> </div>
<Switch <div className="flex items-center gap-2">
checked={rmbgConfig.aosCrop} <Switch
onCheckedChange={(checked) => setRmbgConfig({ ...rmbgConfig, aosCrop: checked })} checked={rmbgConfig.aosCrop}
/> onCheckedChange={(checked) => setRmbgConfig({ ...rmbgConfig, aosCrop: checked })}
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{rmbgConfig.aosCrop ? "已开启" : "已关闭"}
</span>
</div>
</div> </div>
<div className="rounded-lg border border-indigo-200 bg-indigo-50 p-4 space-y-2"> <div className="rounded-lg border border-indigo-200 bg-indigo-50 p-4 space-y-2">
<div className="text-sm font-medium text-indigo-900">AOS 说明</div> <div className="text-sm font-medium text-indigo-900">AOS 说明</div>
@ -6735,7 +6780,7 @@ export function AdminSettingsClient() {
{/* 变清晰API配置 */} {/* 变清晰API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle>变清晰API配置</CardTitle> <CardTitle className="text-xl">变清晰API配置</CardTitle>
<CardDescription> <CardDescription>
配置图片变清晰API,用于画图标注功能中的图片增强处理。支持主API和备用API切换。 配置图片变清晰API,用于画图标注功能中的图片增强处理。支持主API和备用API切换。
</CardDescription> </CardDescription>
@ -6749,10 +6794,15 @@ export function AdminSettingsClient() {
启用后将使用Real-ESRGAN本地模型进行图片增强,效果更好 启用后将使用Real-ESRGAN本地模型进行图片增强,效果更好
</div> </div>
</div> </div>
<Switch <div className="flex items-center gap-2">
checked={enhanceConfig.useBackupApi} <Switch
onCheckedChange={(checked) => setEnhanceConfig({ ...enhanceConfig, useBackupApi: checked })} checked={enhanceConfig.useBackupApi}
/> onCheckedChange={(checked) => setEnhanceConfig({ ...enhanceConfig, useBackupApi: checked })}
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{enhanceConfig.useBackupApi ? "已开启" : "已关闭"}
</span>
</div>
</div> </div>
{/* 主API配置 */} {/* 主API配置 */}
@ -6930,7 +6980,7 @@ export function AdminSettingsClient() {
{/* 图像拓展API配置 */} {/* 图像拓展API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle>图像拓展API配置</CardTitle> <CardTitle className="text-xl">图像拓展API配置</CardTitle>
<CardDescription> <CardDescription>
配置阿里云Dashscope图像拓展API,用于画图标注功能中的图像智能扩展处理 配置阿里云Dashscope图像拓展API,用于画图标注功能中的图像智能扩展处理
</CardDescription> </CardDescription>
@ -7003,7 +7053,7 @@ export function AdminSettingsClient() {
{/* 去水印API配置 */} {/* 去水印API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2 text-xl">
<svg className="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> <svg className="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" /> <path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />
<line x1="4" y1="4" x2="20" y2="20" /> <line x1="4" y1="4" x2="20" y2="20" />
@ -7046,7 +7096,7 @@ export function AdminSettingsClient() {
{/* 角度编辑API配置 */} {/* 角度编辑API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2 text-xl">
<Move3D className="h-5 w-5" /> <Move3D className="h-5 w-5" />
角度编辑API配置 角度编辑API配置
</CardTitle> </CardTitle>
@ -7063,10 +7113,15 @@ export function AdminSettingsClient() {
开启后用户可在图片编辑器中使用角度编辑功能 开启后用户可在图片编辑器中使用角度编辑功能
</div> </div>
</div> </div>
<Switch <div className="flex items-center gap-2">
checked={angleEditConfig.enabled} <Switch
onCheckedChange={(checked) => setAngleEditConfig({ ...angleEditConfig, enabled: checked })} checked={angleEditConfig.enabled}
/> onCheckedChange={(checked) => setAngleEditConfig({ ...angleEditConfig, enabled: checked })}
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{angleEditConfig.enabled ? "已开启" : "已关闭"}
</span>
</div>
</div> </div>
<Separator /> <Separator />
@ -7205,7 +7260,7 @@ export function AdminSettingsClient() {
{/* 实时画布API配置 */} {/* 实时画布API配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2 text-xl">
<Paintbrush className="h-5 w-5" /> <Paintbrush className="h-5 w-5" />
实时画布配置 实时画布配置
</CardTitle> </CardTitle>
@ -7221,12 +7276,17 @@ export function AdminSettingsClient() {
关闭后前端“实时画布”入口仍可显示,但会提示服务未启用。 关闭后前端“实时画布”入口仍可显示,但会提示服务未启用。
</div> </div>
</div> </div>
<Switch <div className="flex items-center gap-2">
checked={realtimeCanvasConfig.enabled} <Switch
onCheckedChange={(checked) => checked={realtimeCanvasConfig.enabled}
setRealtimeCanvasConfig({ ...realtimeCanvasConfig, enabled: checked }) onCheckedChange={(checked) =>
} setRealtimeCanvasConfig({ ...realtimeCanvasConfig, enabled: checked })
/> }
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{realtimeCanvasConfig.enabled ? "已开启" : "已关闭"}
</span>
</div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@ -7391,7 +7451,7 @@ export function AdminSettingsClient() {
{/* 详情替换配置 */} {/* 详情替换配置 */}
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2 text-xl">
<Sparkles className="h-5 w-5" /> <Sparkles className="h-5 w-5" />
详情替换配置 详情替换配置
</CardTitle> </CardTitle>
@ -7408,10 +7468,15 @@ export function AdminSettingsClient() {
开启后用户可在图片编辑器中使用详情替换功能 开启后用户可在图片编辑器中使用详情替换功能
</div> </div>
</div> </div>
<Switch <div className="flex items-center gap-2">
checked={sceneFusionConfig.enabled} <Switch
onCheckedChange={(checked) => setSceneFusionConfig({ ...sceneFusionConfig, enabled: checked })} checked={sceneFusionConfig.enabled}
/> onCheckedChange={(checked) => setSceneFusionConfig({ ...sceneFusionConfig, enabled: checked })}
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{sceneFusionConfig.enabled ? "已开启" : "已关闭"}
</span>
</div>
</div> </div>
{/* 默认提示词 */} {/* 默认提示词 */}

View File

@ -5397,7 +5397,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
}, [activeSessionTitle, projectTitle]); }, [activeSessionTitle, projectTitle]);
return ( return (
<div className="relative flex h-full min-h-0 flex-col bg-background/50 backdrop-blur-sm"> <div className="relative flex h-full min-h-0 flex-col bg-background">
{/* 全局遮罩提示 - 当处于画布选图模式时显示 */} {/* 全局遮罩提示 - 当处于画布选图模式时显示 */}
{detailSlotPickerIndex !== null && ( {detailSlotPickerIndex !== null && (
<div className="absolute inset-0 z-50 flex flex-col items-center justify-center bg-background/80 backdrop-blur-sm animate-in fade-in duration-200"> <div className="absolute inset-0 z-50 flex flex-col items-center justify-center bg-background/80 backdrop-blur-sm animate-in fade-in duration-200">
@ -6052,7 +6052,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
)} )}
{/* 底部输入区域 - 混合输入(图片标签+文字可自由混合) */} {/* 底部输入区域 - 混合输入(图片标签+文字可自由混合) */}
<div className="p-4 bg-background/80 backdrop-blur-md border-t"> <div className="p-4 bg-background border-t">
<div <div
className="relative flex flex-col bg-card rounded-3xl border transition-all duration-200 focus-within:border-primary/50 focus-within:bg-background" className="relative flex flex-col bg-card rounded-3xl border transition-all duration-200 focus-within:border-primary/50 focus-within:bg-background"
data-canvas-chat-input-anchor="true" data-canvas-chat-input-anchor="true"

View File

@ -99,7 +99,7 @@ export function CanvasFileList({ open, onOpenChange, currentId }: CanvasFileList
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md max-h-[80vh] flex flex-col p-0 gap-0 overflow-hidden bg-background/90 backdrop-blur-md"> <DialogContent className="max-w-md max-h-[80vh] flex flex-col p-0 gap-0 overflow-hidden bg-background">
<DialogHeader className="p-4 border-b"> <DialogHeader className="p-4 border-b">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<DialogTitle>已生成文件列表</DialogTitle> <DialogTitle>已生成文件列表</DialogTitle>

View File

@ -956,7 +956,7 @@ export function RealtimeCanvasDialog({
</DialogHeader> </DialogHeader>
{/* Top Header - Minimal */} {/* Top Header - Minimal */}
<div className="absolute left-0 right-0 top-0 z-50 flex h-14 items-center justify-start px-6 bg-gradient-to-b from-black/20 to-transparent pointer-events-none"> <div className="absolute left-0 right-0 top-0 z-50 flex h-14 items-center justify-start px-6 bg-gradient-to-b from-black/20 to-transparent pointer-events-none">
<div className="pointer-events-auto flex items-center gap-3 rounded-full bg-background/80 backdrop-blur-md px-4 py-1.5 border border-border/50 shadow-sm"> <div className="pointer-events-auto flex items-center gap-3 rounded-full bg-background px-4 py-1.5 border border-border/50 shadow-sm">
<span className="font-semibold text-sm">Realtime Canvas</span> <span className="font-semibold text-sm">Realtime Canvas</span>
<div className="h-4 w-[1px] bg-border" /> <div className="h-4 w-[1px] bg-border" />
<span className={cn("flex items-center gap-1.5 text-xs font-medium", statusBadge.className, "bg-transparent p-0")}> <span className={cn("flex items-center gap-1.5 text-xs font-medium", statusBadge.className, "bg-transparent p-0")}>

View File

@ -45,7 +45,7 @@ const DialogContent = forwardRef<
{...props} {...props}
> >
{children} {children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> <DialogPrimitive.Close className="absolute right-4 top-4 z-[100] rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<X className="h-4 w-4" /> <X className="h-4 w-4" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</DialogPrimitive.Close> </DialogPrimitive.Close>