-
+
{volcanoVideoModels.map((model, index) => (
-
+
-
模型 {index + 1}
- 排序: {(index + 1) * 10}
+
+ 模型 {index + 1}
+
+
+ 排序: {(index + 1) * 10}
+
@@ -8801,16 +10409,28 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setModelForm({ ...modelForm, modelId: e.target.value })}
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ modelId: e.target.value,
+ })
+ }
placeholder="例如: qwen-turbo"
/>
-
{modelKindHint}
+
+ {modelKindHint}
+
setModelForm({ ...modelForm, displayName: e.target.value })}
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ displayName: e.target.value,
+ })
+ }
/>
-
上传后会自动裁切并压缩为 400x400 PNG。
+
+ 上传后会自动裁切并压缩为 400x400 PNG。
+
@@ -8876,48 +10512,85 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setModelForm({ ...modelForm, sortOrder: parseInt(e.target.value) || 0 })}
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ sortOrder: parseInt(e.target.value) || 0,
+ })
+ }
/>
-
+
{/* 🆕 备用模型 ID 配置 */}
-
+
setModelForm({ ...modelForm, supportsVision: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ supportsVision: checked,
+ })
+ }
/>
-
+
setModelForm({ ...modelForm, supportsImageGen: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ supportsImageGen: checked,
+ })
+ }
/>
-
+
@@ -8925,22 +10598,39 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setModelForm({ ...modelForm, isEnabled: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ isEnabled: checked,
+ })
+ }
/>
setModelForm({ ...modelForm, isDefault: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ isDefault: checked,
+ })
+ }
/>
-
+
setModelForm({ ...modelForm, isHidden: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ isHidden: checked,
+ })
+ }
/>
@@ -8948,13 +10638,22 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setModelForm({ ...modelForm, isAgentModel: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ isAgentModel: checked,
+ })
+ }
/>
-
+
{modelForm.isAgentModel && (
-
+
@@ -8966,32 +10665,46 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
placeholder="例如: doubao-seed-2-0-code-preview-260215"
/>
- Agent 需要结构化规划/编程输出时优先使用该模型 ID,留空则使用当前 Agent 模型。
+ Agent 需要结构化规划/编程输出时优先使用该模型
+ ID,留空则使用当前 Agent 模型。
)}
setModelForm({ ...modelForm, isMultimodal: checked })}
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ isMultimodal: checked,
+ })
+ }
/>
-
+
- setModelForm({ ...modelForm, excludeFromFailover: checked })
+ setModelForm({
+ ...modelForm,
+ excludeFromFailover: checked,
+ })
}
/>
-
+
-
+
{/* 🆕 图片生成模型特性配置 */}
- {(isImageProviderForModelConfig || isVideoProviderForModelConfig) && (
+ {(isImageProviderForModelConfig ||
+ isVideoProviderForModelConfig) && (
生成配置
-
+
@@ -8999,16 +10712,23 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
type="number"
min={1}
max={10}
- value={modelForm.imageGenConfig?.maxImages || 2}
- onChange={(e) => setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- maxImages: Number.parseInt(e.target.value) || 2,
- },
- })}
+ value={
+ modelForm.imageGenConfig?.maxImages || 2
+ }
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ maxImages:
+ Number.parseInt(e.target.value) || 2,
+ },
+ })
+ }
/>
-
Gemini: 1-2, 阿里: 1-6
+
+ Gemini: 1-2, 阿里: 1-6
+
@@ -9017,20 +10737,27 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
type="number"
min={0}
step={1}
- value={modelForm.imageGenConfig?.creditCostPerImage ?? 0}
- onChange={(e) => setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- creditCostPerImage: Math.max(
- 0,
- Number.parseInt(e.target.value, 10) || 0
- ),
- },
- })}
+ value={
+ modelForm.imageGenConfig
+ ?.creditCostPerImage ?? 0
+ }
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ creditCostPerImage: Math.max(
+ 0,
+ Number.parseInt(e.target.value, 10) ||
+ 0
+ ),
+ },
+ })
+ }
/>
- 开启积分系统后,将按“单价 × 实际出图张数”扣除积分。
+ 开启积分系统后,将按“单价 ×
+ 实际出图张数”扣除积分。
@@ -9040,148 +10767,212 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
type="number"
min={0}
step={1}
- value={modelForm.imageGenConfig?.creditCostPerVideo ?? 0}
- onChange={(e) => setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- creditCostPerVideo: Math.max(
- 0,
- Number.parseInt(e.target.value, 10) || 0
- ),
- },
- })}
+ value={
+ modelForm.imageGenConfig
+ ?.creditCostPerVideo ?? 0
+ }
+ onChange={(e) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ creditCostPerVideo: Math.max(
+ 0,
+ Number.parseInt(e.target.value, 10) ||
+ 0
+ ),
+ },
+ })
+ }
/>
视频生成成功后按每条视频扣除积分。未配置时默认使用“每张图片积分”作为兼容值。
-
+
-
+
setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supportsPromptExtend: checked,
- },
- })}
+ checked={
+ modelForm.imageGenConfig
+ ?.supportsPromptExtend || false
+ }
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supportsPromptExtend: checked,
+ },
+ })
+ }
/>
-
-
-
-
- setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supportsNegativePrompt: checked,
- },
- })}
- />
-
-
-
-
- setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supportsSize: checked,
- },
- })}
- />
-
+
setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- enableLoadingPlaceholder: checked,
- },
- })}
+ checked={
+ modelForm.imageGenConfig
+ ?.supportsNegativePrompt || false
+ }
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supportsNegativePrompt: checked,
+ },
+ })
+ }
/>
-
+
+
+
+
+
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supportsSize: checked,
+ },
+ })
+ }
+ />
+
+
+
+
+
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ enableLoadingPlaceholder: checked,
+ },
+ })
+ }
+ />
+
{/* 分辨率档位开关 */}
-
分辨率档位控制
-
控制前台用户可选的分辨率档位,关闭后用户将无法选择对应分辨率
+
+ 分辨率档位控制
+
+
+ 控制前台用户可选的分辨率档位,关闭后用户将无法选择对应分辨率
+
setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supports1K: checked,
- },
- })}
+ checked={
+ modelForm.imageGenConfig?.supports1K !==
+ false
+ }
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supports1K: checked,
+ },
+ })
+ }
/>
setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supports2K: checked,
- },
- })}
+ checked={
+ modelForm.imageGenConfig?.supports2K !==
+ false
+ }
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supports2K: checked,
+ },
+ })
+ }
/>
setModelForm({
- ...modelForm,
- imageGenConfig: {
- ...modelForm.imageGenConfig,
- supports4K: checked,
- },
- })}
+ checked={
+ modelForm.imageGenConfig?.supports4K !==
+ false
+ }
+ onCheckedChange={(checked) =>
+ setModelForm({
+ ...modelForm,
+ imageGenConfig: {
+ ...modelForm.imageGenConfig,
+ supports4K: checked,
+ },
+ })
+ }
/>
@@ -9193,7 +10984,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
)}
-
+
@@ -9202,7 +10998,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{modelsData?.models?.map((model) => {
- const provider = providersData?.providers?.find((p) => p.id === model.providerId);
+ const provider = providersData?.providers?.find(
+ (p) => p.id === model.providerId
+ );
const isVideoModel = isVideoModelDescriptor({
providerType: provider?.type,
modelId: model.modelId,
@@ -9216,11 +11014,18 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
supportsImageGen: model.supportsImageGen,
});
return (
-
+
{model.avatarUrl ? (
-

+

) : (
无图
@@ -9229,64 +11034,111 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- {model.displayName}
- {model.isDefault && 默认}
- {model.isAgentModel && Agent}
- {isImageModel && 图片模型}
- {isVideoModel && 视频模型}
- {!isImageModel && !isVideoModel && 对话模型}
- {model.isMultimodal && 多模态}
- {model.isHidden && 前台隐藏}
- {(model as any).excludeFromFailover && 不参与故障迁移}
+
+ {model.displayName}
+
+ {model.isDefault && (
+
+ 默认
+
+ )}
+ {model.isAgentModel && (
+
+ Agent
+
+ )}
+ {isImageModel && (
+
+ 图片模型
+
+ )}
+ {isVideoModel && (
+
+ 视频模型
+
+ )}
+ {!isImageModel && !isVideoModel && (
+
+ 对话模型
+
+ )}
+ {model.isMultimodal && (
+
+ 多模态
+
+ )}
+ {model.isHidden && (
+
+ 前台隐藏
+
+ )}
+ {(model as any).excludeFromFailover && (
+
+ 不参与故障迁移
+
+ )}
- ID: {model.modelId} | 提供商: {provider?.name ?? "未知"}
+ ID: {model.modelId} | 提供商:{" "}
+ {provider?.name ?? "未知"}
-
@@ -9305,32 +11157,51 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
存储配置
配置 S3 兼容对象存储
-
-
+
@@ -9382,14 +11279,24 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setStorageForm({ ...storageForm, region: e.target.value })}
+ onChange={(e) =>
+ setStorageForm({
+ ...storageForm,
+ region: e.target.value,
+ })
+ }
/>
setStorageForm({ ...storageForm, publicUrl: e.target.value })}
+ onChange={(e) =>
+ setStorageForm({
+ ...storageForm,
+ publicUrl: e.target.value,
+ })
+ }
/>
>
@@ -9398,21 +11305,36 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setStorageForm({ ...storageForm, isEnabled: checked })}
+ onCheckedChange={(checked) =>
+ setStorageForm({
+ ...storageForm,
+ isEnabled: checked,
+ })
+ }
/>
setStorageForm({ ...storageForm, isDefault: checked })}
+ onCheckedChange={(checked) =>
+ setStorageForm({
+ ...storageForm,
+ isDefault: checked,
+ })
+ }
/>
- setShowStorageDialog(false)}>取消
+ setShowStorageDialog(false)}
+ >
+ 取消
+
保存
@@ -9421,40 +11343,65 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{storageData?.configs?.map((config) => (
-
+
{config.name}
- {config.isDefault && 默认}
- {!config.isEnabled && 已禁用}
+ {config.isDefault && (
+
+ 默认
+
+ )}
+ {!config.isEnabled && (
+
+ 已禁用
+
+ )}
- {config.type === "s3"
- ? (config.endpoint?.includes("aliyuncs.com") ? "阿里云 OSS" : "S3") + ` | Bucket: ${config.bucket}`
+ {config.type === "s3"
+ ? (config.endpoint?.includes("aliyuncs.com")
+ ? "阿里云 OSS"
+ : "S3") + ` | Bucket: ${config.bucket}`
: "本地存储"}
- {
- setStorageForm({
- id: config.id,
- name: config.name,
- type: config.type === "s3" && config.endpoint?.includes("aliyuncs.com") ? "aliyun-oss" : config.type as any,
- endpoint: config.endpoint || "",
- region: config.region || "",
- bucket: config.bucket || "",
- accessKeyId: "",
- secretAccessKey: "",
- publicUrl: config.publicUrl || "",
- isDefault: config.isDefault,
- isEnabled: config.isEnabled,
- });
- setEditingStorage(config.id);
- setShowStorageDialog(true);
- }}>
+ {
+ setStorageForm({
+ id: config.id,
+ name: config.name,
+ type:
+ config.type === "s3" &&
+ config.endpoint?.includes("aliyuncs.com")
+ ? "aliyun-oss"
+ : (config.type as any),
+ endpoint: config.endpoint || "",
+ region: config.region || "",
+ bucket: config.bucket || "",
+ accessKeyId: "",
+ secretAccessKey: "",
+ publicUrl: config.publicUrl || "",
+ isDefault: config.isDefault,
+ isEnabled: config.isEnabled,
+ });
+ setEditingStorage(config.id);
+ setShowStorageDialog(true);
+ }}
+ >
- handleDeleteStorage(config.id)}>
+ handleDeleteStorage(config.id)}
+ >
@@ -9468,13 +11415,16 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
存储故障迁移
- 主存储桶上传失败时,自动切换到备用 MinIO/S3/阿里云 OSS 等 S3 兼容存储桶。
+ 主存储桶上传失败时,自动切换到备用 MinIO/S3/阿里云 OSS 等 S3
+ 兼容存储桶。
-
+
建议仅在主桶不稳定时开启,避免无效重试。
@@ -9496,7 +11446,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- 仅可选择已启用的 S3 兼容配置(如阿里云 OSS、MinIO 等)作为备用桶。
+ 仅可选择已启用的 S3 兼容配置(如阿里云 OSS、MinIO
+ 等)作为备用桶。
@@ -9531,8 +11487,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
siteSettings.storageFailoverConfig.backupStorageConfigId &&
(storageData?.configs || []).some(
(config) =>
- config.id === siteSettings.storageFailoverConfig.backupStorageConfigId &&
- config.isDefault
+ config.id ===
+ siteSettings.storageFailoverConfig
+ .backupStorageConfigId && config.isDefault
) && (
备用桶不能与默认桶相同,请选择另一条存储配置。
@@ -9540,7 +11497,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
)}
- 保存故障迁移设置
+
+ 保存故障迁移设置
+
@@ -9549,15 +11508,19 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
阿里云 OSS 自动转存
- 若已配置阿里云 OSS,上传优先进入 OSS;到期后自动转存到目标默认桶并替换数据库 URL。
+ 若已配置阿里云 OSS,上传优先进入
+ OSS;到期后自动转存到目标默认桶并替换数据库 URL。
-
+
- 开启后执行“先 OSS、后迁移、再清理”的生命周期策略(不依赖 CDN)。
+ 开启后执行“先 OSS、后迁移、再清理”的生命周期策略(不依赖
+ CDN)。
-
+
关闭后新上传图片直接走当前默认存储,不再优先进入阿里云 OSS。
@@ -9585,7 +11550,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setSiteSettings((prev) => ({
...prev,
@@ -9602,7 +11569,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- {!siteSettings.ossImageMigrationConfig.preferAliyunForUploads ? (
+ {!siteSettings.ossImageMigrationConfig
+ .preferAliyunForUploads ? (
已关闭默认走阿里云 OSS,当前源桶选择不会用于新上传图片。
@@ -9645,13 +11619,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- 保存 OSS 自动转存设置
+
+ 保存 OSS 自动转存设置
+
@@ -9758,39 +11746,24 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 本地AI设置 */}
-
-
-
本地 AI 设置概览模式
-
- 默认先收起各项配置,避免打开页签时一次性展示过多参数。数据库连接信息会额外保持隐藏,需手动显示后才会回显。
-
-
-
setIsLocalAiSettingsExpanded((prev) => !prev)}
- >
- {isLocalAiSettingsExpanded ? (
-
- ) : (
-
- )}
- {isLocalAiSettingsExpanded ? "收起全部配置项" : "展开全部配置项"}
-
-
-
-
- 商品策划工具 API 配置
-
- 配置商品策划工具页面使用的淘宝 / 京东 Onebound、问大家和销量接口。保存后商品策划相关接口会优先读取这里的配置,未填写时才回退到环境变量。
-
+
+
+ 商品策划工具 API 配置
+
+ 配置商品策划工具页面使用的淘宝 / 京东
+ Onebound、问大家和销量接口。保存后商品策划相关接口会优先读取这里的配置,未填写时才回退到环境变量。
+
+
+ toggleLocalAiSection("product-planning-api")}
+ />
@@ -9803,14 +11776,19 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setSiteSettings({ ...siteSettings, productPlanningEnabled: checked })
+ setSiteSettings({
+ ...siteSettings,
+ productPlanningEnabled: checked,
+ })
}
/>
-
+
-
+
-
+
-
+
-
+
• 当前功能状态:
- {siteSettings.productPlanningEnabled ? "已启用,左侧导航和接口开放中。" : "已关闭,入口、页面和接口都会被禁用。"}
+ {siteSettings.productPlanningEnabled
+ ? "已启用,左侧导航和接口开放中。"
+ : "已关闭,入口、页面和接口都会被禁用。"}
+
+
+ •
+ 商品策划工具的评价、关键词洞察、淘宝/京东详情、问大家和销量接口都会优先使用这里的配置。
+
+
+ •
+ 若某个字段留空,系统会继续尝试读取旧环境变量,避免你切换配置期间功能直接中断。
-
• 商品策划工具的评价、关键词洞察、淘宝/京东详情、问大家和销量接口都会优先使用这里的配置。
-
• 若某个字段留空,系统会继续尝试读取旧环境变量,避免你切换配置期间功能直接中断。
@@ -9947,16 +11941,27 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- 商品策划专用 AI 模型
-
- 为商品策划工具单独绑定一套分析模型。开启后,评价分析、问大家分析、竞品图片分析和 SKU 卖点分析会优先走这里配置的 OpenAI 兼容模型,不再依赖站点默认模型。
-
+
+
+ 商品策划专用 AI 模型
+
+ 为商品策划工具单独绑定一套分析模型。开启后,评价分析、问大家分析、竞品图片分析和
+ SKU 卖点分析会优先走这里配置的 OpenAI
+ 兼容模型,不再依赖站点默认模型。
+
+
+
+ toggleLocalAiSection("product-planning-ai-model")
+ }
+ />
@@ -9979,7 +11984,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
+
-
+
- 支持填写服务根地址,例如 `http://103.118.245.6:6081`。系统会自动兼容补全 `/v1` 路径。
+ 支持填写服务根地址,例如
+ `http://103.118.245.6:6081`。系统会自动兼容补全 `/v1` 路径。
@@ -10040,7 +12050,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
placeholder={PRODUCT_PLANNING_AI_MODEL_DEFAULT_MODEL_ID}
/>
- 你的 Qwen3-VL OpenAI 兼容接口若使用默认模型名,可直接保留 `Qwen3-VL-4B-Instruct`。
+ 你的 Qwen3-VL OpenAI 兼容接口若使用默认模型名,可直接保留
+ `Qwen3-VL-4B-Instruct`。
@@ -10062,8 +12073,14 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
• 开启后,商品策划页的文本分析和图片分析都会优先使用这里配置的独立模型。
-
• 关闭后,系统会继续回退到站点默认文本/视觉模型,不会影响其他页面的模型设置。
+
+ •
+ 开启后,商品策划页的文本分析和图片分析都会优先使用这里配置的独立模型。
+
+
+ •
+ 关闭后,系统会继续回退到站点默认文本/视觉模型,不会影响其他页面的模型设置。
+
@@ -10076,16 +12093,25 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- Moonshot 官方 Kimi K2.5 配置
-
- 为 AI详情生成 单独配置 Moonshot 官方 Kimi K2.5 模型。保存后会自动绑定到“AI详情生成 - Agent专用模型”。
-
+
+
+
+ Moonshot 官方 Kimi K2.5 配置
+
+
+ 为 AI详情生成 单独配置 Moonshot 官方 Kimi K2.5
+ 模型。保存后会自动绑定到“AI详情生成 - Agent专用模型”。
+
+
+ toggleLocalAiSection("moonshot-detail-agent")}
+ />
@@ -10117,13 +12143,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
placeholder={DETAIL_AGENT_LOCAL_MOONSHOT_BASE_URL}
/>
- 根据 Moonshot 官方文档,OpenAI 兼容接口地址为 `{DETAIL_AGENT_LOCAL_MOONSHOT_BASE_URL}`
+ 根据 Moonshot 官方文档,OpenAI 兼容接口地址为 `
+ {DETAIL_AGENT_LOCAL_MOONSHOT_BASE_URL}`
@@ -10180,7 +12211,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- 关闭后仍会保留记录,但不会被 AI详情生成 选作专用 Agent 模型。
+ 关闭后仍会保留记录,但不会被 AI详情生成 选作专用 Agent
+ 模型。
@@ -10200,8 +12232,14 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
• 专用于 AI详情生成 的分镜规划与排版复审,不影响普通 Agent 对话。
-
• 系统会按多模态 Agent 模型写入:支持视觉、支持结构化规划、支持协议复审。
+
+ • 专用于 AI详情生成 的分镜规划与排版复审,不影响普通 Agent
+ 对话。
+
+
+ • 系统会按多模态 Agent
+ 模型写入:支持视觉、支持结构化规划、支持协议复审。
+
• 保存成功后会自动写入“AI详情生成 - Agent专用模型”。
@@ -10215,16 +12253,23 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- Tripo3D API 配置
-
- 配置无限画布 3D 生成功能使用的 Tripo3D 接口,保存后写入数据库 AI 提供商配置。
-
+
+
+ Tripo3D API 配置
+
+ 配置无限画布 3D 生成功能使用的 Tripo3D 接口,保存后写入数据库
+ AI 提供商配置。
+
+
+ toggleLocalAiSection("tripo3d")}
+ />
@@ -10244,7 +12289,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="tripo3dBaseUrl"
value={tripo3dConfig.baseUrl}
onChange={(e) =>
- setTripo3dConfig({ ...tripo3dConfig, baseUrl: e.target.value })
+ setTripo3dConfig({
+ ...tripo3dConfig,
+ baseUrl: e.target.value,
+ })
}
placeholder={getProviderDefaultBaseUrl("tripo-3d")}
/>
@@ -10261,10 +12309,15 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
type="password"
value={tripo3dConfig.apiKey}
onChange={(e) =>
- setTripo3dConfig({ ...tripo3dConfig, apiKey: e.target.value })
+ setTripo3dConfig({
+ ...tripo3dConfig,
+ apiKey: e.target.value,
+ })
}
placeholder={
- tripo3dConfig.providerId ? "留空则不修改当前 Key" : "请输入 Tripo3D API Key"
+ tripo3dConfig.providerId
+ ? "留空则不修改当前 Key"
+ : "请输入 Tripo3D API Key"
}
/>
@@ -10294,16 +12347,23 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- World Labs API 配置
-
- 配置无限画布 3D 世界模式使用的 World Labs 接口,保存后写入数据库 AI 提供商配置。
-
+
+
+ World Labs API 配置
+
+ 配置无限画布 3D 世界模式使用的 World Labs
+ 接口,保存后写入数据库 AI 提供商配置。
+
+
+ toggleLocalAiSection("worldlabs3d")}
+ />
@@ -10339,7 +12399,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- 抠图API配置
-
- 配置背景移除API,用于画图标注功能中的抠图处理。支持自部署RMBG、PhotoRoom和AOS云服务。
-
+
+
+ 抠图API配置
+
+ 配置背景移除API,用于画图标注功能中的抠图处理。支持自部署RMBG、PhotoRoom和AOS云服务。
+
+
+ toggleLocalAiSection("rmbg")}
+ />
{/* 服务提供商选择 */}
@@ -10406,49 +12473,85 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setRmbgConfig({ ...rmbgConfig, provider: "rmbg" })}
+ onClick={() =>
+ setRmbgConfig({ ...rmbgConfig, provider: "rmbg" })
+ }
>
-
- {rmbgConfig.provider === "rmbg" &&
}
+
+ {rmbgConfig.provider === "rmbg" && (
+
+ )}
-
RMBG-2.0 (自部署)
+
+ RMBG-2.0 (自部署)
+
setRmbgConfig({ ...rmbgConfig, provider: "photoroom" })}
+ onClick={() =>
+ setRmbgConfig({ ...rmbgConfig, provider: "photoroom" })
+ }
>
-
- {rmbgConfig.provider === "photoroom" &&
}
+
+ {rmbgConfig.provider === "photoroom" && (
+
+ )}
-
PhotoRoom (云服务)
+
+ PhotoRoom (云服务)
+
setRmbgConfig({ ...rmbgConfig, provider: "aoscdn" })}
+ onClick={() =>
+ setRmbgConfig({ ...rmbgConfig, provider: "aoscdn" })
+ }
>
-
- {rmbgConfig.provider === "aoscdn" &&
}
+
+ {rmbgConfig.provider === "aoscdn" && (
+
+ )}
-
AOS Segmentation
+
+ AOS Segmentation
+
@@ -10459,13 +12562,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* RMBG 配置 */}
{rmbgConfig.provider === "rmbg" && (
<>
-
RMBG-2.0 配置
+
+ RMBG-2.0 配置
+
setRmbgConfig({ ...rmbgConfig, apiUrl: e.target.value })}
+ onChange={(e) =>
+ setRmbgConfig({ ...rmbgConfig, apiUrl: e.target.value })
+ }
placeholder="http://156.225.27.52:8000"
/>
@@ -10478,12 +12585,16 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="rmbgApiKey"
type="password"
value={rmbgConfig.apiKey}
- onChange={(e) => setRmbgConfig({ ...rmbgConfig, apiKey: e.target.value })}
+ onChange={(e) =>
+ setRmbgConfig({ ...rmbgConfig, apiKey: e.target.value })
+ }
placeholder="如果API需要密钥,请在此输入"
/>
-
RMBG-2.0 说明
+
+ RMBG-2.0 说明
+
• 需要自行部署RMBG-2.0服务
• 系统会自动调用 /rmbg/base64 接口进行抠图处理
@@ -10496,14 +12607,21 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* PhotoRoom 配置 */}
{rmbgConfig.provider === "photoroom" && (
<>
-
PhotoRoom 配置
+
+ PhotoRoom 配置
+
-
PhotoRoom 说明
+
+ PhotoRoom 说明
+
• 使用 PhotoRoom 云服务进行高清抠图
• 支持 HD 高清背景移除,效果更好
@@ -10525,14 +12645,21 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* AOS 配置 */}
{rmbgConfig.provider === "aoscdn" && (
<>
-
AOS Segmentation 配置
+
+ AOS Segmentation 配置
+
setRmbgConfig({ ...rmbgConfig, aosApiKey: e.target.value })}
+ onChange={(e) =>
+ setRmbgConfig({
+ ...rmbgConfig,
+ aosApiKey: e.target.value,
+ })
+ }
placeholder="输入 AOS X-API-KEY"
/>
@@ -10541,7 +12668,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setRmbgConfig({ ...rmbgConfig, aosApiBaseUrl: e.target.value })}
+ onChange={(e) =>
+ setRmbgConfig({
+ ...rmbgConfig,
+ aosApiBaseUrl: e.target.value,
+ })
+ }
placeholder="https://techsz.aoscdn.com"
/>
@@ -10553,8 +12685,13 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
AOS 说明
+
+ AOS 说明
+
• 使用异步任务模式(1秒轮询,最多30秒)
-
• 接口返回链接有效期1小时,系统会自动转存到你的存储桶
+
+ • 接口返回链接有效期1小时,系统会自动转存到你的存储桶
+
• 官方限制:图片最大20MB,分辨率最大4096x4096
@@ -10622,16 +12765,22 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 变清晰API配置 */}
-
- 变清晰API配置
-
- 配置图片变清晰API,用于画图标注功能中的图片增强处理。支持主API和备用API切换。
-
+
+
+ 变清晰API配置
+
+ 配置图片变清晰API,用于画图标注功能中的图片增强处理。支持主API和备用API切换。
+
+
+ toggleLocalAiSection("enhance")}
+ />
{/* API切换开关 */}
@@ -10645,7 +12794,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setEnhanceConfig({ ...enhanceConfig, useBackupApi: checked })}
+ onCheckedChange={(checked) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ useBackupApi: checked,
+ })
+ }
/>
{enhanceConfig.useBackupApi ? "已开启" : "已关闭"}
@@ -10657,13 +12811,20 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{!enhanceConfig.useBackupApi && (
<>
- 主API配置 (第三方云服务)
+
+ 主API配置 (第三方云服务)
+
setEnhanceConfig({ ...enhanceConfig, apiUrl: e.target.value })}
+ onChange={(e) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ apiUrl: e.target.value,
+ })
+ }
placeholder="https://techsz.aoscdn.com"
/>
@@ -10676,7 +12837,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="enhanceApiKey"
type="password"
value={enhanceConfig.apiKey}
- onChange={(e) => setEnhanceConfig({ ...enhanceConfig, apiKey: e.target.value })}
+ onChange={(e) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ apiKey: e.target.value,
+ })
+ }
placeholder="请输入API密钥"
/>
@@ -10687,7 +12853,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
主API文档说明
+
+ 主API文档说明
+
-
• API地址应指向服务根地址,例如: https://techsz.aoscdn.com
-
• 系统会自动调用 /api/tasks/visual/scale 接口进行变清晰处理
+
+ • API地址应指向服务根地址,例如:
+ https://techsz.aoscdn.com
+
+
+ • 系统会自动调用 /api/tasks/visual/scale
+ 接口进行变清晰处理
+
• 支持的图片格式:JPG, JPEG, PNG, BMP, WEBP, TIFF等
-
• 图片大小:不超过50MB,不限制分辨率(建议按业务需求控制尺寸)
+
+ •
+ 图片大小:不超过50MB,不限制分辨率(建议按业务需求控制尺寸)
+
• 返回的链接有效期为1小时,系统会自动下载并存储到S3
@@ -10738,13 +12922,20 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{enhanceConfig.useBackupApi && (
<>
-
备用API配置 (Real-ESRGAN 本地模型)
+
+ 备用API配置 (Real-ESRGAN 本地模型)
+
setEnhanceConfig({ ...enhanceConfig, backupApiUrl: e.target.value })}
+ onChange={(e) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ backupApiUrl: e.target.value,
+ })
+ }
placeholder="http://156.225.27.52:5233"
/>
@@ -10757,7 +12948,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="backupApiKey"
type="password"
value={enhanceConfig.backupApiKey}
- onChange={(e) => setEnhanceConfig({ ...enhanceConfig, backupApiKey: e.target.value })}
+ onChange={(e) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ backupApiKey: e.target.value,
+ })
+ }
placeholder="请输入Real-ESRGAN API密钥"
/>
@@ -10769,7 +12965,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setEnhanceConfig({ ...enhanceConfig, backupScale: value })}
+ onValueChange={(value) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ backupScale: value,
+ })
+ }
>
@@ -10788,16 +12989,29 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setEnhanceConfig({ ...enhanceConfig, backupModel: value })}
+ onValueChange={(value) =>
+ setEnhanceConfig({
+ ...enhanceConfig,
+ backupModel: value,
+ })
+ }
>
- RealESRGAN x2plus (2倍)
- RealESRGAN x4plus (推荐)
- RealESRGAN x8plus (8倍)
- 动漫视频模型 (4倍)
+
+ RealESRGAN x2plus (2倍)
+
+
+ RealESRGAN x4plus (推荐)
+
+
+ RealESRGAN x8plus (8倍)
+
+
+ 动漫视频模型 (4倍)
+
@@ -10806,7 +13020,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
Real-ESRGAN API说明
+
+ Real-ESRGAN API说明
+
• 基于Real-ESRGAN深度学习模型,图像超分辨率效果更好
• 使用URL方式上传图片,处理后自动保存到S3存储
@@ -10826,30 +13042,41 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
- 图像增强 Pro 配置
-
- 配置 Krea Topaz Generative,用于无限画布中的“图像增强 Pro”能力。
-
+
+
+ 图像增强 Pro 配置
+
+ 配置 Krea Topaz Generative,用于无限画布中的“图像增强
+ Pro”能力。
+
+
+ toggleLocalAiSection("enhance-pro")}
+ />
- 关闭后无限画布仍保留普通“高清增强”,但不再开放 Krea Topaz Generative 参数面板。
+ 关闭后无限画布仍保留普通“高清增强”,但不再开放 Krea Topaz
+ Generative 参数面板。
- setEnhanceProConfig((prev) => ({ ...prev, enabled: checked }))
+ setEnhanceProConfig((prev) => ({
+ ...prev,
+ enabled: checked,
+ }))
}
/>
@@ -10933,7 +13160,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
+
@@ -10969,7 +13198,7 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
...preset,
batchSize: Math.min(
Math.max(1, preset.batchSize || 1),
- nextMaxBatchSize,
+ nextMaxBatchSize
),
})),
}));
@@ -10998,7 +13227,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setEnhanceProConfig((prev) => ({
...prev,
- maxOutputEdge: Number.parseInt(e.target.value, 10) || 4096,
+ maxOutputEdge:
+ Number.parseInt(e.target.value, 10) || 4096,
}))
}
/>
@@ -11010,7 +13240,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- 开启后用户可在画布里选择 1-4 张候选结果,系统会按数量生成多个新节点。
+ 开启后用户可在画布里选择 1-4
+ 张候选结果,系统会按数量生成多个新节点。
- 控制是否在画布对话框中展示 creativity、texture、denoise 等高级调节项。
+ 控制是否在画布对话框中展示 creativity、texture、denoise
+ 等高级调节项。
- 管理员可以预设一组适合不同场景的默认参数,画布用户打开“图像增强 Pro”时可直接选择。
+ 管理员可以预设一组适合不同场景的默认参数,画布用户打开“图像增强
+ Pro”时可直接选择。
@@ -11075,7 +13308,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setEnhanceProPresetEditorMode(value as "simple" | "advanced")
+ setEnhanceProPresetEditorMode(
+ value as "simple" | "advanced"
+ )
}
className="space-y-4"
>
@@ -11106,7 +13341,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
key={preset.id}
draggable={enhanceProConfig.presets.length > 1}
onDragStart={(event) =>
- handleEnhanceProPresetDragStart(event, preset.id)
+ handleEnhanceProPresetDragStart(
+ event,
+ preset.id
+ )
}
onDragEnd={handleEnhanceProPresetDragEnd}
onDragOver={(event) => event.preventDefault()}
@@ -11130,12 +13368,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setSelectedEnhanceProPresetId(preset.id)
}
>
-
-
+
+
{preset.name || `预设 ${index + 1}`}
{preset.isDefault ? (
-
+
默认
) : null}
@@ -11152,7 +13390,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
variant="ghost"
size="icon"
onClick={() =>
- handleMoveEnhanceProPreset(index, index - 1)
+ handleMoveEnhanceProPreset(
+ index,
+ index - 1
+ )
}
disabled={index === 0}
>
@@ -11163,7 +13404,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
variant="ghost"
size="icon"
onClick={() =>
- handleMoveEnhanceProPreset(index, index + 1)
+ handleMoveEnhanceProPreset(
+ index,
+ index + 1
+ )
}
disabled={
index ===
@@ -11186,7 +13430,7 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{selectedEnhanceProPreset ? (
renderEnhanceProPresetEditor(
selectedEnhanceProPreset,
- selectedEnhanceProPresetIndex,
+ selectedEnhanceProPresetIndex
)
) : (
@@ -11203,7 +13447,7 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{enhanceProConfig.presets.map((preset, index) =>
- renderEnhanceProPresetEditor(preset, index, true),
+ renderEnhanceProPresetEditor(preset, index, true)
)}
@@ -11211,12 +13455,22 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
Krea Topaz Generative 说明
+
+ Krea Topaz Generative 说明
+
-
• 使用异步 Job 模式,服务端会自动短轮询并在完成后转存到你的存储桶。
-
• 无限画布将向用户开放 width / height / model / prompt / subject detection / face enhancement / upscaling 等参数。
+
+ • 使用异步 Job
+ 模式,服务端会自动短轮询并在完成后转存到你的存储桶。
+
+
+ • 无限画布将向用户开放 width / height / model / prompt /
+ subject detection / face enhancement / upscaling 等参数。
+
• 如果启用多候选结果,用户一次可回收多张增强图到画布。
-
• 建议控制最大输出长边与候选图数量,避免时延和成本过高。
+
+ • 建议控制最大输出长边与候选图数量,避免时延和成本过高。
+
@@ -11228,16 +13482,22 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 图像拓展API配置 */}
-
- 图像拓展API配置
-
- 配置阿里云Dashscope图像拓展API,用于画图标注功能中的图像智能扩展处理
-
+
+
+ 图像拓展API配置
+
+ 配置阿里云Dashscope图像拓展API,用于画图标注功能中的图像智能扩展处理
+
+
+ toggleLocalAiSection("extend")}
+ />
@@ -11246,11 +13506,14 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="extendApiKey"
type="password"
value={extendConfig.apiKey}
- onChange={(e) => setExtendConfig({ ...extendConfig, apiKey: e.target.value })}
+ onChange={(e) =>
+ setExtendConfig({ ...extendConfig, apiKey: e.target.value })
+ }
placeholder="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
/>
- 请输入阿里云Dashscope API密钥,例如: sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ 请输入阿里云Dashscope API密钥,例如:
+ sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@@ -11263,7 +13526,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
min="1.0"
max="2.0"
value={extendConfig.xScale}
- onChange={(e) => setExtendConfig({ ...extendConfig, xScale: e.target.value })}
+ onChange={(e) =>
+ setExtendConfig({
+ ...extendConfig,
+ xScale: e.target.value,
+ })
+ }
placeholder="1.5"
/>
@@ -11279,7 +13547,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
min="1.0"
max="2.0"
value={extendConfig.yScale}
- onChange={(e) => setExtendConfig({ ...extendConfig, yScale: e.target.value })}
+ onChange={(e) =>
+ setExtendConfig({
+ ...extendConfig,
+ yScale: e.target.value,
+ })
+ }
placeholder="1.5"
/>
@@ -11288,10 +13561,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
API文档说明
+
+ API文档说明
+
-
• 使用阿里云Dashscope图像拓展API(image-out-painting模型)
-
• API端点: https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/out-painting
+
+ • 使用阿里云Dashscope图像拓展API(image-out-painting模型)
+
+
+ • API端点:
+ https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/out-painting
+
• 支持的图片格式:JPG, PNG, WebP等常见格式
• 最大图片大小:4MB
• 处理时间:约5-15秒/张
@@ -11306,22 +13586,36 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 去水印API配置 */}
-
-
-
- 去水印API配置
-
-
- 配置PicWish去水印API,用于自动去除图片中的水印
-
+
+
+
+
+ 去水印API配置
+
+
+ 配置PicWish去水印API,用于自动去除图片中的水印
+
+
+ toggleLocalAiSection("watermark-remove")}
+ />
@@ -11330,7 +13624,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="watermarkRemoveApiKey"
type="password"
value={watermarkRemoveConfig.apiKey}
- onChange={(e) => setWatermarkRemoveConfig({ ...watermarkRemoveConfig, apiKey: e.target.value })}
+ onChange={(e) =>
+ setWatermarkRemoveConfig({
+ ...watermarkRemoveConfig,
+ apiKey: e.target.value,
+ })
+ }
placeholder="输入PicWish API密钥"
/>
@@ -11338,7 +13637,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
PicWish API 说明
+
+ PicWish API 说明
+
• 使用 PicWish 云服务进行智能去水印
• 支持各种类型的水印去除(文字、图片水印)
@@ -11354,19 +13655,26 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 角度编辑API配置 */}
-
-
-
- 角度编辑API配置
-
-
- 配置 fal.ai 多角度图像编辑 API,用于对同一图像生成不同视角的变体
-
+
+
+
+
+ 角度编辑API配置
+
+
+ 配置 fal.ai 多角度图像编辑
+ API,用于对同一图像生成不同视角的变体
+
+
+ toggleLocalAiSection("angle-edit")}
+ />
{/* 启用开关 */}
@@ -11380,16 +13688,21 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setAngleEditConfig({ ...angleEditConfig, enabled: checked })}
+ onCheckedChange={(checked) =>
+ setAngleEditConfig({
+ ...angleEditConfig,
+ enabled: checked,
+ })
+ }
/>
{angleEditConfig.enabled ? "已开启" : "已关闭"}
-
+
-
+
{/* API Key */}
-
+
-
+
{/* LoRA 强度 */}
-
+
-
+
{/* 高级设置 */}
-
+
@@ -11455,7 +13778,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="inferenceSteps"
type="number"
value={angleEditConfig.inferenceSteps}
- onChange={(e) => setAngleEditConfig({ ...angleEditConfig, inferenceSteps: Number.parseInt(e.target.value) || 28 })}
+ onChange={(e) =>
+ setAngleEditConfig({
+ ...angleEditConfig,
+ inferenceSteps: Number.parseInt(e.target.value) || 28,
+ })
+ }
min={10}
max={50}
disabled={!angleEditConfig.enabled}
@@ -11467,7 +13795,13 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="guidanceScale"
type="number"
value={angleEditConfig.guidanceScale}
- onChange={(e) => setAngleEditConfig({ ...angleEditConfig, guidanceScale: Number.parseFloat(e.target.value) || 4.5 })}
+ onChange={(e) =>
+ setAngleEditConfig({
+ ...angleEditConfig,
+ guidanceScale:
+ Number.parseFloat(e.target.value) || 4.5,
+ })
+ }
min={1}
max={10}
step={0.5}
@@ -11475,7 +13809,7 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
/>
-
+
@@ -11483,7 +13817,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="maxImageSize"
type="number"
value={angleEditConfig.maxImageSize}
- onChange={(e) => setAngleEditConfig({ ...angleEditConfig, maxImageSize: Number.parseInt(e.target.value) || 10 })}
+ onChange={(e) =>
+ setAngleEditConfig({
+ ...angleEditConfig,
+ maxImageSize: Number.parseInt(e.target.value) || 10,
+ })
+ }
min={1}
max={50}
disabled={!angleEditConfig.enabled}
@@ -11495,7 +13834,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="timeout"
type="number"
value={angleEditConfig.timeout}
- onChange={(e) => setAngleEditConfig({ ...angleEditConfig, timeout: Number.parseInt(e.target.value) || 120 })}
+ onChange={(e) =>
+ setAngleEditConfig({
+ ...angleEditConfig,
+ timeout: Number.parseInt(e.target.value) || 120,
+ })
+ }
min={30}
max={300}
disabled={!angleEditConfig.enabled}
@@ -11503,9 +13847,11 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
+
-
功能说明
+
+ 功能说明
+
• 使用 Qwen-Image-Edit-2511-Multiple-Angles-LoRA 模型
• 支持 96 种相机姿态(4 仰角 × 8 方位角 × 3 距离)
@@ -11514,7 +13860,7 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
• 费用:约 $0.02-0.05/张(fal.ai 按量计费)
-
+
保存配置
@@ -11522,19 +13868,26 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
-
-
- 图层拆分API配置
-
-
- 配置 Replicate 上的 Qwen-Image-Layered 模型,用于将单张图片拆分为多个可编辑图层并回写到无限画布。
-
+
+
+
+
+ 图层拆分API配置
+
+
+ 配置 Replicate 上的 Qwen-Image-Layered
+ 模型,用于将单张图片拆分为多个可编辑图层并回写到无限画布。
+
+
+ toggleLocalAiSection("layer-split")}
+ />
@@ -11548,7 +13901,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setLayerSplitConfig({ ...layerSplitConfig, enabled: checked })
+ setLayerSplitConfig({
+ ...layerSplitConfig,
+ enabled: checked,
+ })
}
/>
@@ -11561,14 +13917,18 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setLayerSplitConfig({ ...layerSplitConfig, replicateApiToken: e.target.value })
+ setLayerSplitConfig({
+ ...layerSplitConfig,
+ replicateApiToken: e.target.value,
+ })
}
placeholder="r8_xxxxxxxxxxxxx"
disabled={!layerSplitConfig.enabled}
@@ -11581,7 +13941,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="layerSplitReplicateModel"
value={layerSplitConfig.replicateModel}
onChange={(e) =>
- setLayerSplitConfig({ ...layerSplitConfig, replicateModel: e.target.value })
+ setLayerSplitConfig({
+ ...layerSplitConfig,
+ replicateModel: e.target.value,
+ })
}
placeholder="qwen/qwen-image-layered"
disabled={!layerSplitConfig.enabled}
@@ -11600,7 +13963,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setLayerSplitConfig({
...layerSplitConfig,
- layers: Math.max(2, Math.min(12, Number(e.target.value) || 4)),
+ layers: Math.max(
+ 2,
+ Math.min(12, Number(e.target.value) || 4)
+ ),
})
}
disabled={!layerSplitConfig.enabled}
@@ -11618,7 +13984,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setLayerSplitConfig({
...layerSplitConfig,
- resolution: Math.max(256, Math.min(1536, Number(e.target.value) || 640)),
+ resolution: Math.max(
+ 256,
+ Math.min(1536, Number(e.target.value) || 640)
+ ),
})
}
disabled={!layerSplitConfig.enabled}
@@ -11636,7 +14005,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setLayerSplitConfig({
...layerSplitConfig,
- trueCfgScale: Math.max(1, Math.min(12, Number(e.target.value) || 4)),
+ trueCfgScale: Math.max(
+ 1,
+ Math.min(12, Number(e.target.value) || 4)
+ ),
})
}
disabled={!layerSplitConfig.enabled}
@@ -11653,7 +14025,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setLayerSplitConfig({
...layerSplitConfig,
- numInferenceSteps: Math.max(1, Math.min(80, Number(e.target.value) || 30)),
+ numInferenceSteps: Math.max(
+ 1,
+ Math.min(80, Number(e.target.value) || 30)
+ ),
})
}
disabled={!layerSplitConfig.enabled}
@@ -11665,12 +14040,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
保持前景/背景透明边缘更稳定
+
+ 保持前景/背景透明边缘更稳定
+
- setLayerSplitConfig({ ...layerSplitConfig, cfgNormalize: checked })
+ setLayerSplitConfig({
+ ...layerSplitConfig,
+ cfgNormalize: checked,
+ })
}
disabled={!layerSplitConfig.enabled}
/>
@@ -11679,12 +14059,17 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
使用英文提示增强兼容性
+
+ 使用英文提示增强兼容性
+
- setLayerSplitConfig({ ...layerSplitConfig, useEnPrompt: checked })
+ setLayerSplitConfig({
+ ...layerSplitConfig,
+ useEnPrompt: checked,
+ })
}
disabled={!layerSplitConfig.enabled}
/>
@@ -11702,7 +14087,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setLayerSplitConfig({
...layerSplitConfig,
- timeoutMs: Math.max(30000, Math.min(900000, Number(e.target.value) || 300000)),
+ timeoutMs: Math.max(
+ 30000,
+ Math.min(900000, Number(e.target.value) || 300000)
+ ),
})
}
disabled={!layerSplitConfig.enabled}
@@ -11711,13 +14099,18 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
+
-
Qwen-Image-Layered 说明
+
+ Qwen-Image-Layered 说明
+
• 用途:将单张图片拆成多个独立图层(RGBA layer)
• 平台:Replicate 托管推理,无需自建 GPU 服务器
• 默认模型:qwen/qwen-image-layered
-
• 使用后会将每个图层转存到你的存储桶,并在无限画布中新增图片节点
+
+ •
+ 使用后会将每个图层转存到你的存储桶,并在无限画布中新增图片节点
+
@@ -11741,19 +14139,26 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
-
-
- 第三方 SQL Server 数据库连接
-
-
- 配置后可供后续业务功能直接访问外部 SQL Server 数据库。当前仅提供配置保存与连通性测试。
-
+
+
+
+
+ 第三方 SQL Server 数据库连接
+
+
+ 配置后可供后续业务功能直接访问外部 SQL Server
+ 数据库。当前仅提供配置保存与连通性测试。
+
+
+ toggleLocalAiSection("third-party-sqlserver")}
+ />
@@ -11767,7 +14172,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setThirdPartySqlServerConfig((prev) => ({ ...prev, enabled: checked }))
+ setThirdPartySqlServerConfig((prev) => ({
+ ...prev,
+ enabled: checked,
+ }))
}
/>
@@ -11778,7 +14186,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
数据库连接信息默认隐藏
+
+ 数据库连接信息默认隐藏
+
{hasThirdPartySqlServerConfiguredValue
? "已保存的主机地址、数据库、账号和密码不会默认显示,只有主动点击后才会回显并允许编辑。"
@@ -11797,7 +14207,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
) : (
)}
- {isThirdPartySqlServerFieldsVisible ? "隐藏连接信息" : "显示并编辑连接信息"}
+ {isThirdPartySqlServerFieldsVisible
+ ? "隐藏连接信息"
+ : "显示并编辑连接信息"}
@@ -11829,7 +14241,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setThirdPartySqlServerConfig((prev) => ({
...prev,
- port: Math.max(1, Math.min(65535, Number(e.target.value) || 1433)),
+ port: Math.max(
+ 1,
+ Math.min(65535, Number(e.target.value) || 1433)
+ ),
}))
}
placeholder="1433"
@@ -11886,7 +14301,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
+
-
+
setThirdPartySqlServerConfig((prev) => ({
...prev,
@@ -11975,11 +14396,18 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
• 当前支持 SQL Server 标准 TCP 连接。
• 配置会保存到系统设置,供后续外部数据查询/同步功能复用。
-
• 测试连接会尝试建立连接并执行基础查询,不会修改外部数据库数据。
+
+ •
+ 测试连接会尝试建立连接并执行基础查询,不会修改外部数据库数据。
+
-
+
{isTestingThirdPartySqlServer ? (
) : (
@@ -11996,19 +14424,27 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 实时画布API配置 */}
-
-
-
- 实时画布配置
-
-
- 配置实时画布功能的供应商、模型与 API Key。当前已接入 BFL / Replicate / FAL 供应商;FAL 的 WebSocket 真流式实时属于第二阶段,不是这次上线内容。
-
+
+
+
+
+ 实时画布配置
+
+
+ 配置实时画布功能的供应商、模型与 API Key。当前已接入 BFL /
+ Replicate / FAL 供应商;FAL 的 WebSocket
+ 真流式实时属于第二阶段,不是这次上线内容。
+
+
+ toggleLocalAiSection("realtime-canvas")}
+ />
@@ -12022,7 +14458,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, enabled: checked })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ enabled: checked,
+ })
}
/>
@@ -12036,7 +14475,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, providerType: value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ providerType: value,
+ })
}
>
@@ -12045,7 +14487,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
BFL / 兼容接口
Replicate
- FAL(WebSocket 真流式实时为二阶段)
+
+ FAL(WebSocket 真流式实时为二阶段)
+
@@ -12054,7 +14498,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
<>
- 当前 FAL 接入的是“供应商能力接入阶段”,会通过现有 `/api/realtime/generate` 服务端链路调用 FAL。
- 前端直连 FAL WebSocket 的“真流式实时”属于第二阶段,当前尚未启用。
+ 当前 FAL 接入的是“供应商能力接入阶段”,会通过现有
+ `/api/realtime/generate` 服务端链路调用 FAL。 前端直连 FAL
+ WebSocket 的“真流式实时”属于第二阶段,当前尚未启用。
@@ -12160,7 +14606,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
type="password"
value={realtimeCanvasConfig.bflApiKey}
onChange={(e) =>
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, bflApiKey: e.target.value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ bflApiKey: e.target.value,
+ })
}
placeholder="bfl_xxxxxxxxxxxxx"
disabled={!realtimeCanvasConfig.enabled}
@@ -12173,7 +14622,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="realtimeBflBaseUrl"
value={realtimeCanvasConfig.bflBaseUrl}
onChange={(e) =>
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, bflBaseUrl: e.target.value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ bflBaseUrl: e.target.value,
+ })
}
placeholder={DEFAULT_BFL_BASE_URL}
disabled={!realtimeCanvasConfig.enabled}
@@ -12188,7 +14640,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
id="realtimeBflModel"
value={realtimeCanvasConfig.bflModel}
onChange={(e) =>
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, bflModel: e.target.value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ bflModel: e.target.value,
+ })
}
placeholder={DEFAULT_BFL_REALTIME_MODEL}
disabled={!realtimeCanvasConfig.enabled}
@@ -12208,7 +14663,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, fallbackEnabled: checked })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ fallbackEnabled: checked,
+ })
}
disabled={!realtimeCanvasConfig.enabled}
/>
@@ -12219,7 +14677,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, fallbackProviderType: value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ fallbackProviderType: value,
+ })
}
>
@@ -12228,7 +14689,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
BFL / 兼容接口
Replicate
- FAL(WebSocket 真流式实时为二阶段)
+
+ FAL(WebSocket 真流式实时为二阶段)
+
@@ -12236,7 +14699,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{realtimeCanvasConfig.fallbackProviderType === "replicate" ? (
<>
-
+
-
+
>
) : realtimeCanvasConfig.fallbackProviderType === "fal" ? (
<>
- 备用 FAL 目前同样走现有服务端生成链路,不是前端直连 WebSocket 真流式实时。
+ 备用 FAL 目前同样走现有服务端生成链路,不是前端直连
+ WebSocket 真流式实时。
-
+
-
+
-
+
>
) : (
<>
-
+
-
+
-
+
>
@@ -12385,7 +14889,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onValueChange={(
value: "strict-structure" | "balanced" | "stylize"
) =>
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, renderMode: value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ renderMode: value,
+ })
}
>
@@ -12400,7 +14907,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- 推荐:BFL 实时草图模型使用 `flux-2-klein-4b`;FAL 需填写支持图像编辑输入的模型 ID。
+ 推荐:BFL 实时草图模型使用 `flux-2-klein-4b`;FAL
+ 需填写支持图像编辑输入的模型 ID。
@@ -12414,7 +14922,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setRealtimeCanvasConfig({
...realtimeCanvasConfig,
- throttleInterval: Number.parseInt(e.target.value, 10) || 100,
+ throttleInterval:
+ Number.parseInt(e.target.value, 10) || 100,
})
}
/>
@@ -12447,7 +14956,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setRealtimeCanvasConfig({
...realtimeCanvasConfig,
- maxInputResolution: Number.parseInt(e.target.value, 10) || 1024,
+ maxInputResolution:
+ Number.parseInt(e.target.value, 10) || 1024,
})
}
/>
@@ -12482,7 +14992,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setRealtimeCanvasConfig({
...realtimeCanvasConfig,
- previewMegapixels: Number.parseFloat(e.target.value) || 0.4,
+ previewMegapixels:
+ Number.parseFloat(e.target.value) || 0.4,
})
}
/>
@@ -12498,7 +15009,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setRealtimeCanvasConfig({
...realtimeCanvasConfig,
- detailMegapixels: Number.parseFloat(e.target.value) || 1,
+ detailMegapixels:
+ Number.parseFloat(e.target.value) || 1,
})
}
/>
@@ -12514,7 +15026,8 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
onChange={(e) =>
setRealtimeCanvasConfig({
...realtimeCanvasConfig,
- outputJpegQuality: Number.parseInt(e.target.value, 10) || 62,
+ outputJpegQuality:
+ Number.parseInt(e.target.value, 10) || 62,
})
}
/>
@@ -12577,7 +15090,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setRealtimeCanvasConfig({ ...realtimeCanvasConfig, imageSize: value })
+ setRealtimeCanvasConfig({
+ ...realtimeCanvasConfig,
+ imageSize: value,
+ })
}
>
@@ -12599,19 +15115,25 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
{/* 批量处理配置 */}
-
-
-
- 批量处理配置
-
-
- 配置批量处理功能的默认提示词和参数。批量处理可将产品图批量融合到多个场景中。
-
+
+
+
+
+ 批量处理配置
+
+
+ 配置批量处理功能的默认提示词和参数。批量处理可将产品图批量融合到多个场景中。
+
+
+ toggleLocalAiSection("batch-process")}
+ />
{/* 功能开关 */}
@@ -12625,7 +15147,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setSceneFusionConfig({ ...sceneFusionConfig, enabled: checked })}
+ onCheckedChange={(checked) =>
+ setSceneFusionConfig({
+ ...sceneFusionConfig,
+ enabled: checked,
+ })
+ }
/>
{sceneFusionConfig.enabled ? "已开启" : "已关闭"}
@@ -12644,7 +15171,10 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
- setSceneFusionConfig({ ...sceneFusionConfig, preRmbgEnabled: checked })
+ setSceneFusionConfig({
+ ...sceneFusionConfig,
+ preRmbgEnabled: checked,
+ })
}
disabled={!sceneFusionConfig.enabled}
/>
@@ -12660,7 +15190,12 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
生成模式:多样性模式(固定)
+
+ 生成模式:多样性模式(固定)
+
系统会在所有可用生图模型中轮换分配任务,并在单模型失败时自动迁移到其他模型。
@@ -12704,31 +15244,43 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
setSceneFusionConfig({ ...sceneFusionConfig, modelId: value === "auto" ? "" : value })}
+ onValueChange={(value) =>
+ setSceneFusionConfig({
+ ...sceneFusionConfig,
+ modelId: value === "auto" ? "" : value,
+ })
+ }
disabled={!sceneFusionConfig.enabled}
>
- 不指定首选(完全随机轮换)
+
+ 不指定首选(完全随机轮换)
+
{(modelsData?.models || [])
.filter((m: AiModel) => {
- const provider = (providersData?.providers || []).find((p: AiProvider) => p.id === m.providerId);
+ const provider = (providersData?.providers || []).find(
+ (p: AiProvider) => p.id === m.providerId
+ );
return Boolean(provider && m.supportsImageGen);
})
.map((m: AiModel) => {
- const provider = (providersData?.providers || []).find((p: AiProvider) => p.id === m.providerId);
+ const provider = (providersData?.providers || []).find(
+ (p: AiProvider) => p.id === m.providerId
+ );
return (
{m.displayName} ({provider?.name || provider?.type})
);
- })
- }
+ })}
{/* 如果没有找到生图模型,显示提示 */}
{(modelsData?.models || []).filter((m: AiModel) => {
- const provider = (providersData?.providers || []).find((p: AiProvider) => p.id === m.providerId);
+ const provider = (providersData?.providers || []).find(
+ (p: AiProvider) => p.id === m.providerId
+ );
return Boolean(provider && m.supportsImageGen);
}).length === 0 && (
@@ -12743,7 +15295,9 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
-
功能说明
+
+ 功能说明
+
• 用户上传1张产品图和多张场景参考图
• 系统自动将产品图融合到每个场景中
@@ -12751,18 +15305,20 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
• 生成的图片会自动保存到用户相册
-
+
保存配置
-
{/* 批量设置出图限额对话框 */}
-
)}
@@ -12838,21 +15398,31 @@ const [realtimeCanvasConfig, setRealtimeCanvasConfig] = useState({
即将执行:
{batchLimitType === "all" && "将为所有用户设置出图限额"}
- {batchLimitType === "department" && batchLimitDepartment && `将为部门「${batchLimitDepartment}」的用户设置出图限额`}
- {batchLimitType === "department" && !batchLimitDepartment && "请先选择部门"}
- {batchLimitType === "no_department" && "将为所有无部门用户设置出图限额"}
+ {batchLimitType === "department" &&
+ batchLimitDepartment &&
+ `将为部门「${batchLimitDepartment}」的用户设置出图限额`}
+ {batchLimitType === "department" &&
+ !batchLimitDepartment &&
+ "请先选择部门"}
+ {batchLimitType === "no_department" &&
+ "将为所有无部门用户设置出图限额"}
{" → "}
{batchLimitValue ? `${batchLimitValue} 张/月` : "无限制"}
- setShowBatchLimitDialog(false)}>
+ setShowBatchLimitDialog(false)}
+ >
取消
-
确认设置