刘光辉
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
61
62
63
64
65
import type { InjectionKey } from 'vue';
 
import type { FileAccess, FileAction } from './fileAccess';
 
import { computed, inject } from 'vue';
 
export interface FilePermissionView {
  enabled: boolean;
  taskId: string;
  formId: string;
  status: 'error' | 'loading' | 'ready';
  revision?: string;
  fields?: Record<string, FileAccess>;
}
 
export const filePermissionFormKey: InjectionKey<() => { modelId: string; readOnly?: boolean; view?: FilePermissionView }> = Symbol('file-permission-form');
export const workflowFileSubmitPendingKey: InjectionKey<() => boolean> = Symbol('workflow-file-submit-pending');
 
function applyReadOnlyLimit(access: FileAccess | undefined, readOnly: boolean): FileAccess | undefined {
  if (!readOnly || access === undefined || access.status !== 'ready') return access;
  return {
    ...access,
    actions: {
      ADD: false,
      DOWNLOAD: access.actions?.DOWNLOAD === true,
      EDIT: false,
      REVIEW: false,
      REMOVE: false,
      REPLACE: false,
      VIEW: access.actions?.VIEW === true,
    },
  };
}
 
/** 服务端明确返回旧实例才沿用旧行为;受控实例缺字段或跨表单响应都关闭动作。 */
export function fieldFileAccess(view: FilePermissionView | undefined, modelId: string, field: string, parent?: string): FileAccess | undefined {
  if (view === undefined || view === null) return undefined;
  if (!modelId || view.formId !== modelId || !view.taskId) return { status: 'error' };
  if (view.enabled === false && view.status === 'ready') return undefined;
  if (view.enabled !== true || view.status !== 'ready' || !view.revision) return { status: view.status === 'loading' ? 'loading' : 'error' };
  return view.fields?.[parent ? `${parent}-${field}` : field] ?? { status: 'error' };
}
 
export function useFilePermissionAccess(props: { editField: string; editParentField?: string; fileAccess?: FileAccess }) {
  const form = inject(filePermissionFormKey, undefined);
  return computed(() => {
    const context = form?.();
    const inherited = context ? fieldFileAccess(context.view, context.modelId, props.editField, props.editParentField) : undefined;
    // 表单运行态始终是上限,不能被控件上的旧配置覆盖。
    let resolved = inherited;
    if (inherited === undefined) resolved = props.fileAccess;
    else if (props.fileAccess !== undefined && inherited.status === 'ready') {
      resolved =
        props.fileAccess.status === 'ready'
          ? ({
              ...inherited,
              actions: Object.fromEntries(
                Object.entries(inherited.actions ?? {}).map(([key, value]) => [key, value === true && props.fileAccess?.actions?.[key as FileAction] === true]),
              ),
            } as FileAccess)
          : props.fileAccess;
    }
    return applyReadOnlyLimit(resolved, context?.readOnly === true);
  });
}