feat(mindspace): add per-user OA cloud drive with fds-style file manager

Expose authenticated /api/mindspace/v1/oa/drive APIs over each user's oa/ workspace and wire a MindSpace entry at /space/oa/drive.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-10 18:55:46 +08:00
parent d07815d317
commit 6d5eb15b1b
22 changed files with 3833 additions and 9 deletions
@@ -0,0 +1,59 @@
function assertRouter(api) {
if (
!api
|| typeof api.use !== 'function'
) {
throw new Error(
'attachPortalMindSpaceOaDriveRoutes requires an Express-compatible router',
);
}
}
function isOaDrivePath(req) {
return req.path === '/mindspace/v1/oa/drive'
|| req.path.startsWith('/mindspace/v1/oa/drive/');
}
function needsRawBody(req) {
if (req.method === 'PATCH') return true;
if (req.method === 'POST' && req.path === '/mindspace/v1/oa/drive/upload') return true;
return false;
}
export function attachPortalMindSpaceOaDriveRoutes(
api,
{
getOaDriveService = () => null,
ensureMindSpaceEnabled = () => false,
rawUploadBody = (_req, _res, next) => next(),
handleMindSpaceError = (_res, _req, error) => {
throw error;
},
} = {},
) {
assertRouter(api);
api.use(async (req, res, next) => {
if (!isOaDrivePath(req)) return next();
if (!ensureMindSpaceEnabled(res, req, { upload: true })) return;
const service = getOaDriveService();
if (!service) {
return res.status(503).json({ error: { code: 'feature_disabled', message: 'OA 网盘未启用' } });
}
const run = async () => {
try {
await service.handlers.handle(req, res);
} catch (error) {
handleMindSpaceError(res, req, error);
}
};
if (needsRawBody(req)) {
return rawUploadBody(req, res, () => {
void run();
});
}
return run();
});
}