release: prepare 0629001 portal updates

This commit is contained in:
john
2026-06-29 22:20:04 +08:00
parent 18ea4f82fd
commit a40e340a41
84 changed files with 17516 additions and 2475 deletions
+36 -15
View File
@@ -600,7 +600,7 @@ export async function listMindSpaceAssets(
export async function uploadMindSpaceAsset(
categoryId: string,
file: File,
options: { maxImageBytes?: number } = {},
options: { maxImageBytes?: number; onProgress?: (progress: number) => void } = {},
): Promise<MindSpaceAsset> {
const maxImageBytes = options.maxImageBytes ?? CHAT_IMAGE_UPLOAD_MAX_INPUT_BYTES;
if (file.type.startsWith('image/') && file.size > maxImageBytes) {
@@ -621,20 +621,7 @@ export async function uploadMindSpaceAsset(
});
try {
const contentResponse = await fetch(created.data.uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/octet-stream' },
body: file,
});
if (!contentResponse.ok) {
const body = (await contentResponse.json().catch(() => null)) as {
error?: { message?: string };
} | null;
throw new ApiError(
contentResponse.status,
body?.error?.message ?? '文件内容上传失败',
);
}
await uploadFileContent(created.data.uploadUrl, file, options.onProgress);
const completed = await apiFetch<{ data: MindSpaceAsset }>(
`/mindspace/v1/uploads/${created.data.id}/complete`,
{ method: 'POST', body: JSON.stringify({}) },
@@ -648,6 +635,40 @@ export async function uploadMindSpaceAsset(
}
}
function uploadFileContent(
url: string,
file: File,
onProgress?: (progress: number) => void,
): Promise<void> {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('PUT', url);
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.upload.onprogress = (event) => {
if (!event.lengthComputable || !onProgress) return;
onProgress(Math.min(0.99, Math.max(0, event.loaded / event.total)));
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
onProgress?.(1);
resolve();
return;
}
let message = '文件内容上传失败';
try {
const body = JSON.parse(xhr.responseText || '{}') as { error?: { message?: string } };
message = body?.error?.message ?? message;
} catch {
// Keep the generic upload error when the response is not JSON.
}
reject(new ApiError(xhr.status, message));
};
xhr.onerror = () => reject(new ApiError(0, '文件内容上传失败'));
xhr.onabort = () => reject(new ApiError(0, '文件上传已取消'));
xhr.send(file);
});
}
export async function deleteMindSpaceAsset(assetId: string): Promise<void> {
await apiFetch(`/mindspace/v1/assets/${assetId}`, { method: 'DELETE' });
}