feat: enhance operations dashboard and reporting controls

This commit is contained in:
hectorzhao
2026-09-04 16:26:22 +08:00
parent bc18c7ff12
commit 48d0363920
23 changed files with 544 additions and 49 deletions
+17
View File
@@ -140,6 +140,23 @@ describe('request tenant and error boundaries', () => {
await expect(requestBlob('/client/file-fail')).rejects.toThrow('文件不存在');
});
it('marks string-body blob requests as JSON so download endpoints receive their payload', async () => {
let receivedContentType = '';
let receivedBody: unknown;
server.use(
http.post('http://localhost/api/admin/report-export', async ({ request: incoming }) => {
receivedContentType = incoming.headers.get('content-type') ?? '';
receivedBody = await incoming.json();
return new HttpResponse('xlsx-data', { status: 200 });
}),
);
await expect(
(await requestBlob('/admin/report-export', { method: 'POST', body: JSON.stringify({ reportType: 'signature' }) })).text(),
).resolves.toBe('xlsx-data');
expect(receivedContentType).toContain('application/json');
expect(receivedBody).toEqual({ reportType: 'signature' });
});
it('retries blob downloads after recent authentication and supports admin tenant selection', async () => {
writeSession({
portal: 'admin',
+3
View File
@@ -114,6 +114,9 @@ export async function request<T>(path: string, options: RequestOptions = {}): Pr
export async function requestBlob(path: string, options: RequestOptions = {}): Promise<Blob> {
const headers = new Headers(options.headers);
if (typeof options.body === 'string' && !headers.has('Content-Type')) {
headers.set('Content-Type', 'application/json');
}
const portal = requestPortal(path);
const session = portal ? readSession(portal) : null;
if (session && hasRecentUserActivity()) headers.set('x-session-activity', 'user');