feat(ai-image): AI生图开发
This commit is contained in:
@@ -6,7 +6,9 @@ import {
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
Res,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiBearerAuth,
|
||||
@@ -19,6 +21,11 @@ import {
|
||||
createMediaAccessUrlRequestSchema,
|
||||
createMediaUploadIntentRequestSchema,
|
||||
importProductImageRequestSchema,
|
||||
createAspectRatioDerivativeRequestSchema,
|
||||
createWatermarkDerivativeRequestSchema,
|
||||
createMediaAiEditRequestSchema,
|
||||
listProductImageTasksQuerySchema,
|
||||
type CreateMediaAccessUrlRequest,
|
||||
type Workspace,
|
||||
} from '@atlas/contracts';
|
||||
import { z } from 'zod';
|
||||
@@ -26,6 +33,11 @@ import { ApiError } from '../common/api-error.js';
|
||||
import type { AuthenticatedRequest } from '../auth/auth.guard.js';
|
||||
import { CurrentWorkspace } from '../workspace/current-workspace.decorator.js';
|
||||
import { MediaService } from './media.service.js';
|
||||
import { AspectRatioDerivativeService } from './aspect-ratio-derivative.service.js';
|
||||
import { WatermarkDerivativeService } from './watermark-derivative.service.js';
|
||||
import { MediaAiEditService } from './media-ai-edit.service.js';
|
||||
import { ProductImageTaskService } from './product-image-task.service.js';
|
||||
import { ProductImageDerivativeHistoryService } from './product-image-derivative-history.service.js';
|
||||
|
||||
@ApiTags('Media')
|
||||
@ApiBearerAuth('access-token')
|
||||
@@ -33,8 +45,132 @@ import { MediaService } from './media.service.js';
|
||||
export class MediaController {
|
||||
public constructor(
|
||||
@Inject(MediaService) private readonly media: MediaService,
|
||||
@Inject(AspectRatioDerivativeService) private readonly derivatives: AspectRatioDerivativeService,
|
||||
@Inject(WatermarkDerivativeService) private readonly watermarkDerivatives: WatermarkDerivativeService,
|
||||
@Inject(MediaAiEditService) private readonly aiEdits: MediaAiEditService,
|
||||
@Inject(ProductImageTaskService) private readonly productImageTasks: ProductImageTaskService,
|
||||
@Inject(ProductImageDerivativeHistoryService) private readonly derivativeHistory: ProductImageDerivativeHistoryService,
|
||||
) {}
|
||||
|
||||
@Get('products/:productId/image-derivatives')
|
||||
public async listProductImageDerivatives(
|
||||
@Param('productId') productId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return { data: await this.derivativeHistory.list(workspace.id, uuid('product_id', productId)) };
|
||||
}
|
||||
|
||||
@Get('products/:productId/image-tasks')
|
||||
public async listProductImageTasks(
|
||||
@Param('productId') productId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
@Query() query: unknown,
|
||||
) {
|
||||
return this.productImageTasks.list(workspace.id, uuid('product_id', productId),
|
||||
parse(listProductImageTasksQuerySchema, query));
|
||||
}
|
||||
|
||||
@Post('media-assets/:assetId/ai-edits')
|
||||
public async createAiEdit(
|
||||
@Param('assetId') assetId: string,
|
||||
@Body() body: unknown,
|
||||
@Headers('idempotency-key') key: string | undefined,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
@Res({ passthrough: true }) response: { status: (code: number) => void },
|
||||
) {
|
||||
const result = await this.aiEdits.create(
|
||||
workspace.id, request.auth.userId, uuid('asset_id', assetId),
|
||||
idempotencyKey(key), parse(createMediaAiEditRequestSchema, body),
|
||||
);
|
||||
response.status(result.status);
|
||||
return result.body;
|
||||
}
|
||||
|
||||
@Get('media-ai-edits/:editId')
|
||||
public async aiEdit(
|
||||
@Param('editId') editId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return { data: await this.aiEdits.read(workspace.id, uuid('edit_id', editId)) };
|
||||
}
|
||||
|
||||
@Get('media-ai-edits')
|
||||
public async listAiEdits(
|
||||
@Query('product_id') productId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return { data: await this.aiEdits.list(workspace.id, uuid('product_id', productId)) };
|
||||
}
|
||||
|
||||
@Post('media-ai-edits/:editId/cancel')
|
||||
public async cancelAiEdit(
|
||||
@Param('editId') editId: string,
|
||||
@Headers('idempotency-key') key: string | undefined,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return (await this.aiEdits.cancel(
|
||||
workspace.id, request.auth.userId, uuid('edit_id', editId), idempotencyKey(key),
|
||||
)).body;
|
||||
}
|
||||
|
||||
@Post('media-assets/:assetId/watermark-derivatives')
|
||||
public async createWatermarkDerivative(
|
||||
@Param('assetId') assetId: string,
|
||||
@Body() body: unknown,
|
||||
@Headers('idempotency-key') key: string | undefined,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
@Res({ passthrough: true }) response: { status: (code: number) => void },
|
||||
) {
|
||||
const result = await this.watermarkDerivatives.create(
|
||||
workspace.id,
|
||||
request.auth.userId,
|
||||
uuid('asset_id', assetId),
|
||||
idempotencyKey(key),
|
||||
parse(createWatermarkDerivativeRequestSchema, body),
|
||||
);
|
||||
response.status(result.status);
|
||||
return result.body;
|
||||
}
|
||||
|
||||
@Get('media-watermark-derivatives/:derivativeId')
|
||||
public async watermarkDerivative(
|
||||
@Param('derivativeId') derivativeId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return { data: await this.watermarkDerivatives.read(workspace.id, uuid('derivative_id', derivativeId)) };
|
||||
}
|
||||
|
||||
@Post('media-assets/:assetId/aspect-ratio-derivatives')
|
||||
public async createAspectRatioDerivative(
|
||||
@Param('assetId') assetId: string,
|
||||
@Body() body: unknown,
|
||||
@Headers('idempotency-key') key: string | undefined,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
@Res({ passthrough: true }) response: { status: (code: number) => void },
|
||||
) {
|
||||
const result = await this.derivatives.create(
|
||||
workspace.id,
|
||||
request.auth.userId,
|
||||
uuid('asset_id', assetId),
|
||||
idempotencyKey(key),
|
||||
parse(createAspectRatioDerivativeRequestSchema, body),
|
||||
);
|
||||
response.status(result.status);
|
||||
return result.body;
|
||||
}
|
||||
|
||||
@Get('media-derivatives/:derivativeId')
|
||||
public async aspectRatioDerivative(
|
||||
@Param('derivativeId') derivativeId: string,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return { data: await this.derivatives.read(workspace.id, uuid('derivative_id', derivativeId)) };
|
||||
}
|
||||
|
||||
@Get('media-assets/product-uploads')
|
||||
@ApiOkResponse({ description: '最近上传的商品图片及短时预览地址' })
|
||||
public async productUploads(@CurrentWorkspace() workspace: Workspace) {
|
||||
@@ -102,17 +238,18 @@ export class MediaController {
|
||||
}
|
||||
|
||||
@Post('media-assets/:assetId/access-urls')
|
||||
@ApiOkResponse({ description: '已签发短时预览 URL' })
|
||||
@ApiOkResponse({ description: '已签发短时预览或下载 URL' })
|
||||
public async accessUrl(
|
||||
@Param('assetId') assetId: string,
|
||||
@Body() body: unknown,
|
||||
@CurrentWorkspace() workspace: Workspace,
|
||||
) {
|
||||
parse(createMediaAccessUrlRequestSchema, body);
|
||||
const input = parse(createMediaAccessUrlRequestSchema, body) as CreateMediaAccessUrlRequest;
|
||||
return {
|
||||
data: await this.media.accessUrl(
|
||||
workspace.id,
|
||||
uuid('asset_id', assetId),
|
||||
input.purpose,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user