feat: 优化图片资源删除管理,生图任务列表管理

This commit is contained in:
2026-08-30 14:50:33 +08:00
parent 4ee667142b
commit 957289f717
46 changed files with 4180 additions and 524 deletions
+76 -11
View File
@@ -5,6 +5,7 @@
*/
import { api } from './api';
import apiClient from './api';
import type { AxiosRequestConfig } from 'axios';
/** 套图类型白名单(与服务端 prompts/common.py 对齐) */
export const SUITE_TYPE_OPTIONS = [
@@ -42,11 +43,11 @@ export const DEFAULT_PLAN: PlanItem[] = SUITE_TYPE_OPTIONS.slice(0, 7).map((t) =
/** 视觉风格(默认提示词可在页面上改写,随生成请求覆盖后端模板) */
export const STYLE_SET_OPTIONS = [
{ value: 1, label: '北欧极简', prompt: '北欧极简风:浅灰或米白背景,柔和漫射光,低饱和色调,画面留白充足,构图克制干净' },
{ value: 2, label: '清新明亮', prompt: '清新明亮风:明亮的白色到浅蓝渐变背景,高调光线,色彩明快通透,整体轻盈干净' },
{ value: 3, label: '高级感深色', prompt: '高级质感风:深灰或炭黑背景,戏剧性侧光打光,突出商品材质与光泽,沉稳高级' },
{ value: 4, label: '暖调生活', prompt: '温暖生活风:暖米色背景,暖色灯光氛围,温馨的家居质感,亲和力强' },
{ value: 5, label: '纯净棚拍', prompt: '标准电商棚拍:纯色浅背景,均匀的正面柔光,无杂物干扰,商品居中突出' },
{ value: 1, label: '北欧极简', prompt: 'Nordic minimalism: light gray or warm off-white background, soft diffused light, low-saturation palette, generous negative space, restrained and clean composition' },
{ value: 2, label: '清新明亮', prompt: 'Fresh and bright: white-to-pale-blue gradient background, high-key lighting, clear luminous colors, airy and uncluttered composition' },
{ value: 3, label: '高级感深色', prompt: 'Premium dark aesthetic: deep gray or charcoal background, dramatic side lighting, emphasize material texture and sheen, refined and restrained mood' },
{ value: 4, label: '暖调生活', prompt: 'Warm lifestyle: warm beige background, cozy warm lighting, inviting home-living texture, approachable and natural atmosphere' },
{ value: 5, label: '纯净棚拍', prompt: 'Clean e-commerce studio: plain light background, even frontal softbox lighting, no distracting props, product centered and prominent' },
] as const;
/** 试算页固定目标平台 Ozon:俄文文案 · 3:4 图片 */
@@ -115,6 +116,7 @@ export interface SuiteGeneratePayload {
}
export interface SuiteImageInfo {
item_id: string;
type_id: string;
name: string;
url: string;
@@ -124,13 +126,20 @@ export interface SuiteImageInfo {
export interface SuiteInfo {
id: string;
status: 'pending' | 'running' | 'done' | 'partial' | 'failed';
status: 'queued' | 'pending' | 'running' | 'done' | 'partial' | 'failed' | 'cancelled';
kind?: 'image_suite' | 'image_edit' | string;
style_set: number;
platform: string;
lang: string;
ratio: string;
provider?: string;
total?: number;
completed?: number;
failed?: number;
cancel_requested?: boolean;
created_at?: string | null;
started_at?: string | null;
completed_at?: string | null;
images: SuiteImageInfo[];
error?: string | null;
}
@@ -146,8 +155,26 @@ export function generateSuite(payload: SuiteGeneratePayload) {
}
/** ★ 查询套图任务状态(轮询用) */
export function getSuite(suiteId: string) {
return api.get<SuiteInfo>(`/suites/${suiteId}`);
export function getSuite(suiteId: string, config?: AxiosRequestConfig) {
return api.get<SuiteInfo>(`/suites/${suiteId}`, config);
}
/** 当前商品的后台图片任务,用于刷新页面后恢复进度。 */
export function listProductSuites(productId: string, activeOnly = false, config?: AxiosRequestConfig) {
return api.get<SuiteInfo[]>(`/products/${productId}/suites`, { ...config, params: { active_only: activeOnly } });
}
export function cancelSuite(suiteId: string) {
return api.post<SuiteInfo>(`/suites/${suiteId}/cancel`);
}
export function retrySuite(suiteId: string) {
return api.post<SuiteInfo>(`/suites/${suiteId}/retry`);
}
/** 重试任务中单个失败图片;批量水印可据此只补偿失败项。 */
export function retrySuiteItem(suiteId: string, itemId: string) {
return api.post<SuiteInfo>(`/suites/${suiteId}/items/${itemId}/retry`);
}
/** ★ 下载生成结果 ZIP(blob) */
@@ -159,16 +186,18 @@ export async function downloadSuiteZip(suiteId: string): Promise<Blob> {
export interface ImageEditSinglePayload {
product_id?: string;
image_url: string;
prompt: string;
prompt?: string;
model: string;
append?: boolean;
/** 插入锚点:新素材排在该素材之后(方便与原图对比) */
after_asset_id?: string;
/** 单张生成完成后由服务端合成水印;关闭时不传。 */
watermark?: WatermarkPayload;
}
/** ★ 单张 AI 生图(采集图/生成图上的「AI生图」入口) */
/** ★ 提交单张 AI 生图任务;通过 getSuite(suite_id) 查询进度。 */
export function imageEditSingle(payload: ImageEditSinglePayload) {
return api.post<{ url: string; asset_id: string | null }>('/suite/image-edit', payload);
return api.post<{ suite_id: string }>('/suite/image-edit', payload);
}
/** 删除一条素材(DB 记录 + 本地文件),用于删除已生成的图片 */
@@ -176,6 +205,36 @@ export function deleteAsset(assetId: string) {
return api.delete<{ deleted: boolean }>(`/assets/${assetId}`);
}
export interface ApplyWatermarkPayload {
asset_ids: string[];
watermark: WatermarkPayload;
}
export interface ApplyWatermarkResponse {
job_id: string;
total: number;
}
export interface RemoveWatermarkResponse {
updated_ids: string[];
failed: Array<{ asset_id: string; error: string }>;
}
/** 将水印任务加入后台队列;Worker 始终从保留的原图重做,避免重复叠加。 */
export function applyWatermarkToAssets(payload: ApplyWatermarkPayload) {
return api.post<ApplyWatermarkResponse>('/assets/watermark', payload);
}
/** 取消已选图片的水印,服务端切回保留的无水印原图。 */
export function removeWatermarkFromAssets(assetIds: string[]) {
return api.post<RemoveWatermarkResponse>('/assets/watermark/remove', { asset_ids: assetIds });
}
/** 当前商品的批量水印任务,用于刷新页面后恢复进度。 */
export function listProductWatermarkJobs(productId: string, activeOnly = false, config?: AxiosRequestConfig) {
return api.get<SuiteInfo[]>(`/products/${productId}/watermark-jobs`, { ...config, params: { active_only: activeOnly } });
}
export interface ExportImagesPayload {
title: string;
images: Array<{ url: string; groupName: string; variantName?: string | null; key: string }>;
@@ -187,6 +246,12 @@ export async function exportImages(payload: ExportImagesPayload): Promise<Blob>
return res.data as Blob;
}
/** 单张图片下载:服务端代理源站图片,避免防盗链与跨域导致浏览器无法保存。 */
export async function exportImage(payload: ExportImagesPayload['images'][number]): Promise<Blob> {
const res = await apiClient.post('/export/image', payload, { responseType: 'blob' });
return res.data as Blob;
}
/** 上传补充参考图到商品素材(已有接口:POST /api/materials/bytes) */
export async function uploadProductAsset(
productId: string,