刘光辉
119 分钟以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 = [];
    },
  };
}