feat(mindspace): add achievements showcase with paginated management
Memind CI / Test, build, and release guards (push) Successful in 3m28s
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:
@@ -1,3 +1,5 @@
|
||||
import { listAchievementPagesForUser } from '../mindspace-page-achievement-list.mjs';
|
||||
|
||||
function assertRouter(api) {
|
||||
if (
|
||||
!api ||
|
||||
@@ -72,6 +74,7 @@ export function attachPortalMindSpacePageCoreRoutes(
|
||||
getMindSpacePageLiveEdit = () => null,
|
||||
getMindSpacePageEditSession = () => null,
|
||||
getUserAuth = () => null,
|
||||
getAuthPool = () => null,
|
||||
syncUserGeneratedPages,
|
||||
ownsAgentSession,
|
||||
ensureMindSpaceEnabled,
|
||||
@@ -161,6 +164,35 @@ export function attachPortalMindSpacePageCoreRoutes(
|
||||
}
|
||||
});
|
||||
|
||||
api.get('/mindspace/v1/pages/achievements', async (req, res) => {
|
||||
const pages = getMindSpacePages();
|
||||
if (!pages) {
|
||||
return res.status(503).json({ message: 'MindSpace 未启用' });
|
||||
}
|
||||
try {
|
||||
schedulePageListSync(req.currentUser.id);
|
||||
const result = await listAchievementPagesForUser({
|
||||
pages,
|
||||
userId: req.currentUser.id,
|
||||
query: req.query,
|
||||
pool: getAuthPool?.() ?? null,
|
||||
logger,
|
||||
});
|
||||
return res.json({
|
||||
data: result.items,
|
||||
page: {
|
||||
total: result.total,
|
||||
limit: result.limit,
|
||||
offset: result.offset,
|
||||
has_more: result.hasMore,
|
||||
next_cursor: null,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return handleMindSpaceError(res, req, error);
|
||||
}
|
||||
});
|
||||
|
||||
api.get('/mindspace/v1/pages/:pageId', async (req, res) => {
|
||||
const pages = getMindSpacePages();
|
||||
if (!pages) {
|
||||
|
||||
@@ -102,6 +102,7 @@ test('page core module preserves route inventory and order', () => {
|
||||
assert.deepEqual([...api.routes.keys()], [
|
||||
'POST /mindspace/v1/pages',
|
||||
'GET /mindspace/v1/pages',
|
||||
'GET /mindspace/v1/pages/achievements',
|
||||
'GET /mindspace/v1/pages/:pageId',
|
||||
'DELETE /mindspace/v1/pages/:pageId',
|
||||
'GET /mindspace/v1/pages/:pageId/delete-preview',
|
||||
@@ -522,3 +523,31 @@ test('page core routes preserve unavailable and mapped error responses', async (
|
||||
assert.equal(failureRes.statusCode, 418);
|
||||
assert.equal(failure.calls.routeErrors[0].error.message, 'list failed');
|
||||
});
|
||||
|
||||
test('achievements route uses listPages and enriches stats before page detail route', async () => {
|
||||
const api = createRouterRecorder();
|
||||
const setup = createDependencies({
|
||||
getMindSpacePages: () => ({
|
||||
async listPages(userId, input) {
|
||||
return {
|
||||
items: [{ id: 'page-1', title: 'Demo', viewCount: 3, clickCount: null, statsSource: 'publication' }],
|
||||
total: 1,
|
||||
limit: input.limit ?? 20,
|
||||
offset: input.offset ?? 0,
|
||||
hasMore: false,
|
||||
};
|
||||
},
|
||||
}),
|
||||
getAuthPool: () => null,
|
||||
});
|
||||
attachPortalMindSpacePageCoreRoutes(api, setup.dependencies);
|
||||
|
||||
const res = createResponseRecorder();
|
||||
await api.routes.get('GET /mindspace/v1/pages/achievements')(
|
||||
createRequest({ query: { limit: '20', offset: '0' } }),
|
||||
res,
|
||||
);
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.equal(res.body.data[0].viewCount, 3);
|
||||
assert.equal(res.body.page.total, 1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user