import type { UploadEditParticipant } from './uploadEditContext';
|
|
import type { UploadEditContext, UploadEditDraft } from '#/api/onlineDev/uploadEdit';
|
|
/** Scoped to one mounted native form; batches requests, never caches permission decisions. */
|
export function createUploadEditCoordinator(load: (contexts: UploadEditContext[]) => Promise<{ data: UploadEditDraft[] }>) {
|
let disposed = false;
|
let scheduled = false;
|
let queue: { context: UploadEditContext; reject: (reason: unknown) => void; resolve: (value: { data: UploadEditDraft }) => void }[] = [];
|
async function flush() {
|
scheduled = false;
|
const pending = queue;
|
queue = [];
|
// A form can change record while earlier work is in flight. Never mix records in a batch.
|
const groups = new Map<string, typeof pending>();
|
for (const item of pending) {
|
const c = item.context;
|
const key = JSON.stringify([c.modelId, c.recordId, c.taskId, c.menuId]);
|
if (!groups.has(key)) groups.set(key, []);
|
groups.get(key)!.push(item);
|
}
|
await Promise.all(
|
[...groups.values()].map(async (group) => {
|
try {
|
if (disposed) throw new Error('表单已关闭');
|
const response = await load(group.map((item) => item.context));
|
if (disposed || response.data.length !== group.length) throw new Error('共享附件状态不完整,请重试');
|
group.forEach((item, i) => item.resolve({ data: response.data[i]! }));
|
} catch (error) {
|
group.forEach((item) => item.reject(error));
|
}
|
}),
|
);
|
}
|
return {
|
loadShared(context: UploadEditContext): Promise<{ data: UploadEditDraft }> {
|
if (disposed) return Promise.reject(new Error('表单已关闭'));
|
return new Promise((resolve, reject) => {
|
queue.push({ context: { ...context }, resolve, reject });
|
if (!scheduled) {
|
scheduled = true;
|
queueMicrotask(() => void flush());
|
}
|
});
|
},
|
async prepare(participants: Iterable<UploadEditParticipant>) {
|
const items = [...participants];
|
await Promise.all(items.map((item) => item.settle?.()));
|
return Promise.all(items.map((item) => item.prepare()));
|
},
|
async refresh(participants: Iterable<UploadEditParticipant>) {
|
await Promise.allSettled([...participants].map((item) => item.refresh?.()));
|
},
|
dispose() {
|
disposed = true;
|
queue.forEach((item) => item.reject(new Error('表单已关闭')));
|
queue = [];
|
},
|
};
|
}
|