Files
xiaoxia-saas/apps/web/src/api/titles.ts
T
灵应 1cff5d52fd
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Failing after 37h34m9s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 37h34m9s
fix: 标题库API兼容直接数组返回 + 素材上传弹窗闪退修复
Issue 2: getTitles() 兼容后端返回直接数组 [...] 和 {items:[...]} 两种格式
Issue 5: beforeUpload 改为同步返回 false(避免 async Promise 不稳定);
         上传失败时延迟1.5秒关闭弹窗,让用户能看到错误提示
2026-07-07 23:20:15 +08:00

131 lines
3.3 KiB
TypeScript

/**
* 标题相关 API
* Phase 1 新增:全局标题库
* 注意:后端 schema 使用 name + text 字段,前端 UI 用 content 展示
*/
import apiClient from "./client";
/** 标题条目(前端展示用) */
export interface TitleItem {
id: string;
content: string;
category?: string;
source?: string;
word_count?: number;
is_favorite?: boolean;
created_at?: string;
updated_at?: string;
}
/** 后端标题响应格式 */
interface BackendTitleResponse {
id: string;
user_id: string;
name: string;
text: string;
category: string;
description: string;
tags: string[];
usage_count: number;
is_active: boolean;
created_at: string;
updated_at: string;
}
/** 后端创建标题请求格式 */
interface BackendCreateTitleRequest {
name: string;
text: string;
category: string;
description?: string;
tags?: string[];
}
/** 后端更新标题请求格式 */
interface BackendUpdateTitleRequest {
name?: string;
text?: string;
category?: string;
description?: string;
tags?: string[];
}
/** 将后端响应映射为前端 TitleItem */
const toTitleItem = (item: BackendTitleResponse): TitleItem => ({
id: item.id,
content: item.text,
category: item.category,
word_count: item.text?.length || 0,
created_at: item.created_at,
updated_at: item.updated_at,
});
/** 创建标题请求(前端接口,保持向后兼容) */
export interface CreateTitleRequest {
content: string;
category?: string;
}
/** 获取当前用户的所有标题 */
export const getTitles = async (): Promise<TitleItem[]> => {
const response = await apiClient.get<
{ items: BackendTitleResponse[] } | BackendTitleResponse[]
>("/titles");
// 兼容两种后端返回格式:{ items: [...] } 或直接 [...]
const items = Array.isArray(response.data)
? response.data
: response.data.items || [];
return items.map(toTitleItem);
};
/** 创建标题 */
export const createTitle = async (
data: CreateTitleRequest,
): Promise<TitleItem> => {
// 后端要求 name(≤255)和 text(≤500),name 从 content 截取
const payload: BackendCreateTitleRequest = {
name: data.content.slice(0, 255),
text: data.content.slice(0, 500),
category: data.category || "default",
};
const response = await apiClient.post<BackendTitleResponse>(
"/titles",
payload,
);
return toTitleItem(response.data);
};
/** 更新标题 */
export const updateTitle = async (
titleId: string,
data: Partial<CreateTitleRequest>,
): Promise<TitleItem> => {
const payload: BackendUpdateTitleRequest = {};
if (data.content !== undefined) {
payload.name = data.content.slice(0, 255);
payload.text = data.content.slice(0, 500);
}
if (data.category !== undefined) {
payload.category = data.category;
}
// 后端用 PUT,非 PATCH
const response = await apiClient.put<BackendTitleResponse>(
`/titles/${titleId}`,
payload,
);
return toTitleItem(response.data);
};
/** 删除标题 */
export const deleteTitle = async (titleId: string): Promise<void> => {
await apiClient.delete(`/titles/${titleId}`);
};
/** 批量导入标题 */
export const batchImportTitles = async (
titles: string[],
): Promise<{ imported_count: number }> => {
const response = await apiClient.post("/titles/batch-import", { titles });
return response.data;
};