feat: 完善图像工作区与创作工具体验
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
inman committed 2026-08-16 14:08:27 +08:00
1 parent bfcb88cfef
commit 26b52d76e3
92 files changed
+16678 -2975

No files matched your search

+94
View File
@@ -0,0 +1,94 @@
import { AppError } from '@/lib/error-model';
import { hostApiFetch } from '@/lib/host-api';
import {
IMAGE_PROMPT_MUSEUM_API_PATH,
type PromptMuseumEntry,
type PromptMuseumListQuery,
type PromptMuseumPage,
} from '../../shared/image-prompt-museum';
type PromptMuseumEnvelope<T> = {
success?: boolean;
status?: number;
code?: string;
error?: string;
data?: T;
};
export class PromptMuseumApiError extends Error {
readonly status: number;
readonly code: string;
constructor(status: number, code: string, message: string) {
super(message);
this.name = 'PromptMuseumApiError';
this.status = status;
this.code = code;
}
}
function errorStatus(error: unknown): number {
if (error instanceof AppError && typeof error.details?.status === 'number') {
return error.details.status;
}
return 502;
}
function errorCode(error: unknown, status: number): string {
if (error instanceof AppError && typeof error.details?.backendCode === 'string') {
return error.details.backendCode;
}
if (status === 401) return 'PROMPT_MUSEUM_AUTH_REQUIRED';
if (status === 404) return 'PROMPT_MUSEUM_NOT_FOUND';
return 'PROMPT_MUSEUM_REQUEST_FAILED';
}
function createQuery(query: PromptMuseumListQuery): string {
const params = new URLSearchParams();
const values: Array<[string, string | undefined]> = [
['q', query.q],
['use_case', query.useCase],
['style', query.style],
['subject', query.subject],
['language', query.language],
['model', query.model],
['cursor', query.cursor],
['limit', query.limit === undefined ? undefined : String(query.limit)],
];
for (const [key, value] of values) {
if (value?.trim()) params.set(key, value.trim());
}
const encoded = params.toString();
return encoded ? `?${encoded}` : '';
}
async function requestData<T>(path: string): Promise<T> {
let response: PromptMuseumEnvelope<T>;
try {
response = await hostApiFetch<PromptMuseumEnvelope<T>>(path);
} catch (error) {
const status = errorStatus(error);
throw new PromptMuseumApiError(
status,
errorCode(error, status),
error instanceof Error ? error.message : '提示词博物馆请求失败',
);
}
if (!response.success || response.data === undefined) {
throw new PromptMuseumApiError(
response.status ?? 502,
response.code ?? 'PROMPT_MUSEUM_REQUEST_FAILED',
response.error ?? '提示词博物馆请求失败',
);
}
return response.data;
}
export async function fetchPromptMuseumPage(query: PromptMuseumListQuery = {}): Promise<PromptMuseumPage> {
return await requestData(`${IMAGE_PROMPT_MUSEUM_API_PATH}${createQuery(query)}`);
}
export async function fetchPromptMuseumEntry(entryId: string): Promise<PromptMuseumEntry> {
return await requestData(`${IMAGE_PROMPT_MUSEUM_API_PATH}/${encodeURIComponent(entryId)}`);
}