整理后端模块清单

This commit is contained in:
2026-04-20 23:07:43 +08:00
parent 39c7f0735f
commit adc57ba49b
11 changed files with 4777 additions and 21 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@ import { PNG } from 'pngjs';
import { removeBackgroundFromRgba } from '../../../../packages/shared/src/assets/chromaKey.js';
import { parseApiErrorMessage } from '../../../../packages/shared/src/http.js';
import type { AppConfig } from '../../config.js';
import { routeMeta } from '../../middleware/routeMeta.js';
import {
buildArkCharacterAnimationPrompt,
buildFallbackModerationSafeAnimationPrompt,
@@ -30,14 +31,18 @@ import {
import type { UpstreamLlmClient } from '../../services/llmClient.js';
const CHARACTER_WORKFLOW_CACHE_PATH = '/api/assets/character-workflow-cache';
const CHARACTER_WORKFLOW_CACHE_DETAIL_PATH =
'/api/assets/character-workflow-cache/:characterId';
const CHARACTER_VISUAL_GENERATE_PATH = '/api/assets/character-visual/generate';
const CHARACTER_VISUAL_PUBLISH_PATH = '/api/assets/character-visual/publish';
const CHARACTER_VISUAL_JOBS_PATH = '/api/assets/character-visual/jobs/';
const CHARACTER_VISUAL_JOB_DETAIL_PATH =
'/api/assets/character-visual/jobs/:taskId';
const CHARACTER_ANIMATION_GENERATE_PATH =
'/api/assets/character-animation/generate';
const CHARACTER_ANIMATION_PUBLISH_PATH =
'/api/assets/character-animation/publish';
const CHARACTER_ANIMATION_JOBS_PATH = '/api/assets/character-animation/jobs/';
const CHARACTER_ANIMATION_JOB_DETAIL_PATH =
'/api/assets/character-animation/jobs/:taskId';
const CHARACTER_ANIMATION_IMPORT_VIDEO_PATH =
'/api/assets/character-animation/import-video';
const CHARACTER_ANIMATION_TEMPLATES_PATH =
@@ -2990,29 +2995,37 @@ export function createCharacterAssetRoutes(
next();
});
router.use(
router.post(
CHARACTER_WORKFLOW_CACHE_PATH,
routeMeta({ operation: 'assets.character.workflowCache.save' }),
toExpressHandler((request, response) => {
if (request.method === 'GET') {
return handleGetCharacterWorkflowCache(config, request, response);
}
return handleSaveCharacterWorkflowCache(config, request, response);
}),
);
router.use(
router.get(
CHARACTER_WORKFLOW_CACHE_DETAIL_PATH,
routeMeta({ operation: 'assets.character.workflowCache.get' }),
toExpressHandler((request, response) =>
handleGetCharacterWorkflowCache(config, request, response),
),
);
router.post(
CHARACTER_VISUAL_GENERATE_PATH,
routeMeta({ operation: 'assets.character.visual.generate' }),
toExpressHandler((request, response) =>
handleGenerateCharacterVisuals(config, request, response),
),
);
router.use(
router.post(
CHARACTER_VISUAL_PUBLISH_PATH,
routeMeta({ operation: 'assets.character.visual.publish' }),
toExpressHandler((request, response) =>
handlePublishCharacterVisual(config, request, response),
),
);
router.use(
CHARACTER_VISUAL_JOBS_PATH,
router.get(
CHARACTER_VISUAL_JOB_DETAIL_PATH,
routeMeta({ operation: 'assets.character.visual.job.get' }),
toExpressHandler((request, response) =>
handleReadCharacterJobStatus(
config.projectRoot,
@@ -3022,20 +3035,23 @@ export function createCharacterAssetRoutes(
),
),
);
router.use(
router.post(
CHARACTER_ANIMATION_GENERATE_PATH,
routeMeta({ operation: 'assets.character.animation.generate' }),
toExpressHandler((request, response) =>
handleGenerateCharacterAnimation(config, request, response),
),
);
router.use(
router.post(
CHARACTER_ANIMATION_PUBLISH_PATH,
routeMeta({ operation: 'assets.character.animation.publish' }),
toExpressHandler((request, response) =>
handlePublishCharacterAnimation(config, request, response),
),
);
router.use(
CHARACTER_ANIMATION_JOBS_PATH,
router.get(
CHARACTER_ANIMATION_JOB_DETAIL_PATH,
routeMeta({ operation: 'assets.character.animation.job.get' }),
toExpressHandler((request, response) =>
handleReadCharacterJobStatus(
config.projectRoot,
@@ -3045,8 +3061,9 @@ export function createCharacterAssetRoutes(
),
),
);
router.use(
router.post(
CHARACTER_ANIMATION_IMPORT_VIDEO_PATH,
routeMeta({ operation: 'assets.character.animation.importVideo' }),
toExpressHandler((request, response) =>
handleImportCharacterAnimationVideo(
config.projectRoot,
@@ -3055,8 +3072,9 @@ export function createCharacterAssetRoutes(
),
),
);
router.use(
router.get(
CHARACTER_ANIMATION_TEMPLATES_PATH,
routeMeta({ operation: 'assets.character.animation.templates.list' }),
toExpressHandler((request, response) =>
handleListAnimationTemplates(config, request, response),
),

View File

@@ -9,6 +9,7 @@ import path from 'node:path';
import { Router, type NextFunction, type Request, type Response } from 'express';
import type { AppConfig } from '../../config.js';
import { routeMeta } from '../../middleware/routeMeta.js';
const QWEN_SPRITE_MASTER_GENERATE_PATH = '/api/assets/qwen-sprite/master';
const QWEN_SPRITE_SHEET_GENERATE_PATH = '/api/assets/qwen-sprite/sheet';
@@ -878,26 +879,30 @@ export function createQwenSpriteRoutes(config: AppConfig) {
next();
});
router.use(
router.post(
QWEN_SPRITE_MASTER_GENERATE_PATH,
routeMeta({ operation: 'assets.qwenSprite.master.generate' }),
toExpressHandler((request, response) =>
handleGenerateMaster(config, request, response),
),
);
router.use(
router.post(
QWEN_SPRITE_SHEET_GENERATE_PATH,
routeMeta({ operation: 'assets.qwenSprite.sheet.generate' }),
toExpressHandler((request, response) =>
handleGenerateSheet(config, request, response),
),
);
router.use(
router.post(
QWEN_SPRITE_FRAME_REPAIR_PATH,
routeMeta({ operation: 'assets.qwenSprite.frameRepair.generate' }),
toExpressHandler((request, response) =>
handleRepairFrame(config, request, response),
),
);
router.use(
router.post(
QWEN_SPRITE_SAVE_PATH,
routeMeta({ operation: 'assets.qwenSprite.asset.save' }),
toExpressHandler((request, response) =>
handleSaveAsset(config.projectRoot, request, response),
),

View File

@@ -6,6 +6,7 @@ import { Router } from 'express';
import type { AppConfig } from '../../config.js';
import { badRequest, notFound } from '../../errors.js';
import { asyncHandler } from '../../http.js';
import { routeMeta } from '../../middleware/routeMeta.js';
const EDITOR_JSON_RESOURCE_FILES = {
'item-overrides': 'src/data/itemOverrides.json',
@@ -102,6 +103,7 @@ export function createEditorRoutes(config: AppConfig) {
router.get(
'/api/editor/catalog/items',
routeMeta({ operation: 'editor.catalog.items.list' }),
asyncHandler(async (_request, response) => {
response.json({
assetPaths: await collectPngAssetPaths(
@@ -113,6 +115,7 @@ export function createEditorRoutes(config: AppConfig) {
router.get(
'/api/editor/json/:resourceId',
routeMeta({ operation: 'editor.resource.read' }),
asyncHandler(async (request, response) => {
const filePath = resolveEditorJsonFile(config, request.params.resourceId);
response.json(await readEditorJsonFile(filePath));
@@ -121,6 +124,7 @@ export function createEditorRoutes(config: AppConfig) {
router.post(
'/api/editor/json/:resourceId',
routeMeta({ operation: 'editor.resource.write' }),
asyncHandler(async (request, response) => {
if (!isEditorJsonPayload(request.body)) {
throw badRequest('编辑器保存请求必须是 JSON 对象。');