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);
|
});
|
}
|