feat(mindspace): add achievements showcase with paginated management
Memind CI / Test, build, and release guards (push) Successful in 3m28s

Ship the M成果 page with list/delete UX, fix deletePage for incomplete page records, route /space/achievements, and add M成果 under the WeChat M空间 menu.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-12 15:21:42 +08:00
parent e9cecf8733
commit 421e204711
21 changed files with 1405 additions and 29 deletions
+2
View File
@@ -88,7 +88,9 @@ export {
getMindSpacePage,
getMindSpacePageDeletePreview,
getMindSpacePageLiveRevision,
isMindSpacePageNotFoundError,
listMindSpacePages,
listMindSpaceAchievementPages,
openMindSpaceDraftPreviewWindow,
regenerateMindSpacePageThumbnail,
rewriteMindSpacePageDownloadLinks,
+28
View File
@@ -29,6 +29,14 @@ export async function getMindSpacePageDeletePreview(
return result.data;
}
export function isMindSpacePageNotFoundError(err: unknown): boolean {
return (
err instanceof ApiError &&
err.status === 404 &&
(err.code === 'page_not_found' || err.message === '页面不存在')
);
}
export async function deleteMindSpacePage(
pageId: string,
options?: { removeFromPlaza?: boolean },
@@ -61,6 +69,26 @@ export async function listMindSpacePages(options?: {
return { items: result.data, page: result.page ?? {} };
}
export async function listMindSpaceAchievementPages(options?: {
status?: string;
limit?: number;
offset?: number;
categoryCode?: string;
includeStats?: boolean;
}): Promise<{ items: MindSpacePage[]; page: MindSpaceListPage }> {
const params = new URLSearchParams();
if (options?.status) params.set('status', options.status);
if (options?.limit != null) params.set('limit', String(options.limit));
if (options?.offset != null) params.set('offset', String(options.offset));
if (options?.categoryCode) params.set('category_code', options.categoryCode);
if (options?.includeStats) params.set('include_stats', '1');
const query = params.toString() ? `?${params.toString()}` : '';
const result = await apiFetch<{ data: MindSpacePage[]; page?: MindSpaceListPage }>(
`/mindspace/v1/pages/achievements${query}`,
);
return { items: result.data, page: result.page ?? {} };
}
export async function getMindSpacePage(pageId: string): Promise<MindSpacePage> {
const result = await apiFetch<{ data: MindSpacePage }>(
`/mindspace/v1/pages/${encodeURIComponent(pageId)}`,