171 lines
6.0 KiB
TypeScript
171 lines
6.0 KiB
TypeScript
import { apiRequest } from './api-request';
|
|
import type { ApiWorksheet } from './content-api';
|
|
|
|
export type AdminAction =
|
|
| 'categories.list'
|
|
| 'categories.create'
|
|
| 'categories.update'
|
|
| 'worksheets.list'
|
|
| 'worksheets.status'
|
|
| 'worksheets.batch'
|
|
| 'site.config'
|
|
| 'site.rebuild'
|
|
| 'site.timer';
|
|
interface AdminWorksheet extends ApiWorksheet {
|
|
status: 'draft' | 'active' | 'hidden';
|
|
likesDisplay: string;
|
|
downloadsDisplay: string;
|
|
likesSeed: string;
|
|
downloadsSeed: string;
|
|
}
|
|
interface AdminPage {
|
|
items: AdminWorksheet[];
|
|
total: number;
|
|
hasNext: boolean;
|
|
page: number;
|
|
pageSize: number;
|
|
}
|
|
/** 管理页迁移适配:只调用具名 REST 接口,旧页面展示字段在客户端映射,不传旧用户身份。 */
|
|
export async function managementRequest<T>(
|
|
action: AdminAction,
|
|
payload: Record<string, unknown> = {},
|
|
): Promise<{
|
|
success: boolean;
|
|
data?: T;
|
|
stats?: { total: number; active: number; draft: number; hidden: number };
|
|
message?: string;
|
|
}> {
|
|
let data: unknown;
|
|
let stats;
|
|
switch (action) {
|
|
case 'categories.list': {
|
|
const rows =
|
|
await apiRequest<Array<{ id: string }>>('/admin/categories');
|
|
data = rows.map((row) => ({ ...row, _id: row.id }));
|
|
break;
|
|
}
|
|
case 'categories.create':
|
|
data = await apiRequest('/admin/categories', {
|
|
method: 'POST',
|
|
data: payload,
|
|
});
|
|
break;
|
|
case 'categories.update': {
|
|
const { id, ...fields } = payload;
|
|
data = await apiRequest(
|
|
`/admin/categories/${encodeURIComponent(String(id))}`,
|
|
{ method: 'PUT', data: fields },
|
|
);
|
|
break;
|
|
}
|
|
case 'worksheets.list': {
|
|
const rows: AdminWorksheet[] = [];
|
|
let expected: number | undefined;
|
|
for (let page = 1; ; page++) {
|
|
const response = await apiRequest<AdminPage>(
|
|
'/admin/catalog/worksheets',
|
|
{
|
|
data: {
|
|
page,
|
|
pageSize: 100,
|
|
...(payload.category
|
|
? { categoryId: payload.category }
|
|
: {}),
|
|
...(payload.status
|
|
? { status: payload.status }
|
|
: {}),
|
|
},
|
|
},
|
|
);
|
|
if (
|
|
response.page !== page ||
|
|
response.pageSize !== 100 ||
|
|
!Array.isArray(response.items) ||
|
|
!Number.isSafeInteger(response.total) ||
|
|
(expected !== undefined && response.total !== expected) ||
|
|
response.hasNext !== page * 100 < response.total
|
|
)
|
|
throw new Error('管理目录发生变化,请重试');
|
|
expected = response.total;
|
|
rows.push(...response.items);
|
|
if (!response.hasNext) break;
|
|
}
|
|
if (
|
|
rows.length !== expected ||
|
|
new Set(rows.map((row) => row.id)).size !== rows.length
|
|
)
|
|
throw new Error('管理目录发生变化,请重试');
|
|
data = rows.map((row) => ({
|
|
...row,
|
|
_id: row.id,
|
|
likes: payload.rawStats ? row.likes : row.likesDisplay,
|
|
downloads: payload.rawStats
|
|
? row.downloads
|
|
: row.downloadsDisplay,
|
|
}));
|
|
stats = {
|
|
total: rows.length,
|
|
active: rows.filter((row) => row.status === 'active').length,
|
|
draft: rows.filter((row) => row.status === 'draft').length,
|
|
hidden: rows.filter((row) => row.status === 'hidden').length,
|
|
};
|
|
break;
|
|
}
|
|
case 'worksheets.status':
|
|
data = await apiRequest(
|
|
`/admin/worksheets/${encodeURIComponent(String(payload.id))}/status`,
|
|
{ method: 'PUT', data: { status: payload.status } },
|
|
);
|
|
break;
|
|
case 'worksheets.batch': {
|
|
const patches = (
|
|
payload.patches as Array<Record<string, unknown>>
|
|
).map(({ likes_seed, downloads_seed, ...row }) => ({
|
|
...row,
|
|
...(likes_seed === undefined ? {} : { likesSeed: likes_seed }),
|
|
...(downloads_seed === undefined
|
|
? {}
|
|
: { downloadsSeed: downloads_seed }),
|
|
}));
|
|
data = await apiRequest('/admin/worksheets/batch', {
|
|
method: 'POST',
|
|
timeout: 60000,
|
|
data: { patches, dryRun: payload.dryRun === true },
|
|
});
|
|
break;
|
|
}
|
|
case 'site.config':
|
|
data = await apiRequest('/admin/site/config');
|
|
break;
|
|
case 'site.rebuild':
|
|
data = await apiRequest('/admin/site/rebuild', {
|
|
method: 'POST',
|
|
timeout: 60000,
|
|
data: payload,
|
|
});
|
|
break;
|
|
case 'site.timer':
|
|
data = await apiRequest('/admin/site/timer', {
|
|
method: 'PUT',
|
|
data: { enabled: payload.enabled },
|
|
});
|
|
break;
|
|
default:
|
|
throw new Error('不支持的管理操作');
|
|
}
|
|
if (
|
|
[
|
|
'categories.create',
|
|
'categories.update',
|
|
'worksheets.status',
|
|
'worksheets.batch',
|
|
'site.rebuild',
|
|
].includes(action)
|
|
) {
|
|
const app = getApp<IAppOption>();
|
|
if (typeof app.refreshPageConfig === 'function')
|
|
await app.refreshPageConfig();
|
|
}
|
|
return { success: true, data: data as T, ...(stats ? { stats } : {}) };
|
|
}
|