@@ -0,0 +1,75 @@
|
||||
// server/api/images/presets.get.ts - 预设提示词列表接口:分页返回已启用的生图预设。
|
||||
import type { IPromptPresetListData } from "#shared/types/openai";
|
||||
import {
|
||||
createApiLogger,
|
||||
createSuccessResponse,
|
||||
createUpstreamErrorResponse,
|
||||
listPromptPresets,
|
||||
toSafeLogError
|
||||
} from "~~/server/utils";
|
||||
|
||||
const DEFAULT_PAGE = 1;
|
||||
const DEFAULT_PAGE_SIZE = 20;
|
||||
const MAX_PAGE_SIZE = 50;
|
||||
|
||||
/**
|
||||
* GET /api/images/presets
|
||||
*
|
||||
* 流程:
|
||||
* 1. 读取 page/size 查询参数,并限制最大 pageSize。
|
||||
* 2. 只返回已启用的预设提示词,按导入顺序展示。
|
||||
* 3. 返回前端展示和填充输入所需字段,不包含内部排查信息。
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const logger = createApiLogger("images.presets.list");
|
||||
logger.info("开始");
|
||||
|
||||
try {
|
||||
const query = getQuery(event);
|
||||
const page = normalizePositiveInt(query.page, DEFAULT_PAGE);
|
||||
const pageSize = Math.min(
|
||||
normalizePositiveInt(query.size, DEFAULT_PAGE_SIZE),
|
||||
MAX_PAGE_SIZE
|
||||
);
|
||||
|
||||
logger.info("查询参数", {
|
||||
page,
|
||||
pageSize
|
||||
});
|
||||
|
||||
const result = await listPromptPresets({
|
||||
page,
|
||||
pageSize
|
||||
});
|
||||
|
||||
logger.done("成功", {
|
||||
page,
|
||||
pageSize,
|
||||
total: result.total,
|
||||
itemCount: result.items.length
|
||||
});
|
||||
|
||||
return createSuccessResponse<IPromptPresetListData>(
|
||||
result,
|
||||
"获取预设提示词成功"
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("失败", {
|
||||
error: toSafeLogError(error)
|
||||
});
|
||||
return createUpstreamErrorResponse(error, "获取预设提示词失败");
|
||||
}
|
||||
});
|
||||
|
||||
/** 将 query 参数归一化为正整数,非法值回退到默认值 */
|
||||
const normalizePositiveInt = (
|
||||
value: unknown,
|
||||
fallbackValue: number
|
||||
): number => {
|
||||
const rawValue = Array.isArray(value) ? value[0] : value;
|
||||
const numberValue = Number.parseInt(String(rawValue ?? ""), 10);
|
||||
|
||||
return Number.isInteger(numberValue) && numberValue > 0
|
||||
? numberValue
|
||||
: fallbackValue;
|
||||
};
|
||||
@@ -10,3 +10,4 @@ export * from "./newApiTokens";
|
||||
export * from "./openai";
|
||||
export * from "./plazaPosts";
|
||||
export * from "./prisma";
|
||||
export * from "./promptPresets";
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// server/utils/promptPresets.ts - 预设提示词数据库查询:为前端提供可分页展示的预设列表。
|
||||
import type {
|
||||
IPromptPresetItem,
|
||||
IPromptPresetListData
|
||||
} from "#shared/types/openai";
|
||||
import { prisma } from "~~/server/utils/prisma";
|
||||
|
||||
export const listPromptPresets = async ({
|
||||
page,
|
||||
pageSize
|
||||
}: {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}): Promise<IPromptPresetListData> => {
|
||||
const where = {
|
||||
enabled: true
|
||||
};
|
||||
|
||||
const [total, records] = await Promise.all([
|
||||
prisma.promptPreset.count({ where }),
|
||||
prisma.promptPreset.findMany({
|
||||
where,
|
||||
orderBy: [
|
||||
{
|
||||
sortOrder: "asc"
|
||||
},
|
||||
{
|
||||
id: "asc"
|
||||
}
|
||||
],
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize
|
||||
})
|
||||
]);
|
||||
|
||||
return {
|
||||
page,
|
||||
pageSize,
|
||||
total,
|
||||
items: records.map(mapPromptPresetItem)
|
||||
};
|
||||
};
|
||||
|
||||
const mapPromptPresetItem = (record: {
|
||||
id: bigint;
|
||||
sourceId: string;
|
||||
name: string;
|
||||
promptRaw: string;
|
||||
prompt: string;
|
||||
negativePrompt: string;
|
||||
category: string;
|
||||
tags: unknown;
|
||||
aspectRatio: string;
|
||||
previewUrl: string;
|
||||
compressedPreviewUrl: string;
|
||||
sortOrder: number;
|
||||
}): IPromptPresetItem => {
|
||||
return {
|
||||
id: record.id.toString(),
|
||||
sourceId: record.sourceId,
|
||||
name: record.name,
|
||||
promptRaw: record.promptRaw,
|
||||
prompt: record.prompt,
|
||||
negativePrompt: record.negativePrompt,
|
||||
category: record.category,
|
||||
tags: Array.isArray(record.tags)
|
||||
? record.tags.filter((tag): tag is string => typeof tag === "string")
|
||||
: [],
|
||||
aspectRatio: record.aspectRatio,
|
||||
previewUrl: record.previewUrl,
|
||||
compressedPreviewUrl: record.compressedPreviewUrl,
|
||||
sortOrder: record.sortOrder
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user