feat: improve approval (#820)

Co-authored-by: bai.zixv <bai.zixv@foxmail.com>
Reviewed-on: daoyoucloud/tachybase#820
This commit is contained in:
sealday 2024-04-24 11:58:14 +08:00
parent a30a214ac0
commit e9c4ade676
20 changed files with 60 additions and 161 deletions

View File

@ -4,7 +4,7 @@ import { APPROVAL_ACTION_STATUS } from '../../../constants';
import { ApprovalActionConfigComponent } from './VC.ApprovalActionConfig'; import { ApprovalActionConfigComponent } from './VC.ApprovalActionConfig';
export const ApproverActionConfigInitializer = new SchemaInitializer({ export const ApproverActionConfigInitializer = new SchemaInitializer({
name: 'ApprovalProcessAddActionButton', name: 'ApproverActionConfigInitializer',
title: '{{t("Configure actions")}}', title: '{{t("Configure actions")}}',
items: [ items: [
{ {

View File

@ -10,7 +10,7 @@ import { ApproverAddBlockComponent } from './VC.ApproverAddBlock';
import { ApproverAddBlockKit } from './VC.ApproverAddBlockKit'; import { ApproverAddBlockKit } from './VC.ApproverAddBlockKit';
export const ApproverAddBlockInitializer = new SchemaInitializer({ export const ApproverAddBlockInitializer = new SchemaInitializer({
name: 'ApprovalProcessAddBlockButton', name: 'ApproverAddBlockInitializer',
wrap: gridRowColWrap, wrap: gridRowColWrap,
title: "{{t('Add block')}}", title: "{{t('Add block')}}",
items: [ items: [

View File

@ -9,7 +9,7 @@ import { flatSchemaArray } from '../../../constants';
export const ApproverAddBlockKit = () => { export const ApproverAddBlockKit = () => {
const itemConfig = useSchemaInitializerItem(); const itemConfig = useSchemaInitializerItem();
const formSchema = createFormBlockSchema({ const formSchema = createFormBlockSchema({
actionInitializers: 'ApprovalProcessAddActionButton', actionInitializers: 'ApproverActionConfigInitializer',
actions: { actions: {
approve: { approve: {
type: 'void', type: 'void',

View File

@ -54,7 +54,7 @@ export const ApproverBlock = ({ value: srcID, onChange }) => {
name: id, name: id,
'x-uid': id, 'x-uid': id,
'x-component': 'Grid', 'x-component': 'Grid',
'x-initializer': 'ApprovalProcessAddBlockButton', 'x-initializer': 'ApproverAddBlockInitializer',
properties: {}, properties: {},
}; };

View File

@ -10,11 +10,8 @@ export default class PluginKitApprovalTrigger extends Plugin {
async load() { async load() {
const workflowPlugin = this.app.pm.get(PluginWorkflow); const workflowPlugin = this.app.pm.get(PluginWorkflow);
workflowPlugin.registerTrigger('approval', ApprovalTrigger); workflowPlugin.registerTrigger('approval', ApprovalTrigger);
// workflowPlugin.registerInstruction('approval', ApprovalInstruction);
this.app.schemaInitializerManager.add(LauncherActionConfigInitializer); this.app.schemaInitializerManager.add(LauncherActionConfigInitializer);
this.app.schemaInitializerManager.add(LauncherAddBlockButtonIntializer); this.app.schemaInitializerManager.add(LauncherAddBlockButtonIntializer);
// this.app.schemaInitializerManager.add(ApproverActionConfigInitializer);
// this.app.schemaInitializerManager.add(ApproverAddBlockInitializer);
} }
} }

View File

@ -3,7 +3,6 @@ import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem }
import { uid } from '@nocobase/utils/client'; import { uid } from '@nocobase/utils/client';
import React from 'react'; import React from 'react';
import { NAMESPACE } from '../../locale'; import { NAMESPACE } from '../../locale';
import { PathNameMap_ApprovalBlock } from './map';
// 创建区块-审批(发起/待办) // 创建区块-审批(发起/待办)
export const ApprovalBlockComponent = () => { export const ApprovalBlockComponent = () => {
@ -54,7 +53,7 @@ export const ApprovalBlockComponent = () => {
name: id, name: id,
'x-uid': id, 'x-uid': id,
'x-component': 'CardItem', 'x-component': 'CardItem',
'x-decorator': PathNameMap_ApprovalBlock.Decorator, 'x-decorator': 'ApprovalBlock.Decorator',
'x-decorator-props': { 'x-decorator-props': {
collection: item.collection, collection: item.collection,
action: 'listCentralized', action: 'listCentralized',

View File

@ -1,5 +1,3 @@
// import { PathNameMap_ApprovalBlock } from '../map';
import { ApprovalBlock } from '../map';
import { NAMESPACE } from '../../../locale'; import { NAMESPACE } from '../../../locale';
import { css } from '@nocobase/client'; import { css } from '@nocobase/client';
@ -66,7 +64,6 @@ export const SchemaApprovalBlockLaunch = {
title: '{{t("Actions")}}', title: '{{t("Actions")}}',
properties: { properties: {
action: { action: {
// 'x-component': PathNameMap_ApprovalBlock.ViewActionLaunch,
'x-component': 'ApprovalBlock.ViewActionLaunch', 'x-component': 'ApprovalBlock.ViewActionLaunch',
}, },
}, },

View File

@ -24,7 +24,6 @@ import { ActionBarProvider } from './Pd.ActionBar';
import { WithdrawActionProvider } from './Pd.WithdrawAction'; import { WithdrawActionProvider } from './Pd.WithdrawAction';
import { SchemaComponentContextProvider } from '../common/Pd.SchemaComponent'; import { SchemaComponentContextProvider } from '../common/Pd.SchemaComponent';
import { ApplyActionStatusProvider } from './Pd.ApplyActionStatus'; import { ApplyActionStatusProvider } from './Pd.ApplyActionStatus';
import { ApprovalCommon } from '../../approval-common/map';
import { FlowContextProvider } from '../common/Pd.FlowContext'; import { FlowContextProvider } from '../common/Pd.FlowContext';
export const ViewActionLaunchContent = () => { export const ViewActionLaunchContent = () => {
@ -136,7 +135,7 @@ export const ViewActionLaunchContent = () => {
process: { process: {
type: 'void', type: 'void',
'x-decorator': 'CardItem', 'x-decorator': 'CardItem',
'x-component': ApprovalCommon.PathNameMap.ViewComponent.ApprovalProcess, 'x-component': 'ApprovalCommon.ViewComponent.ApprovalProcess',
}, },
}, },
}, },

View File

@ -1,31 +0,0 @@
import { ViewActionTodos } from './todos/VC.ViewActionTodos';
import { ApprovalBlockComponent } from './VC.ApprovalBlock';
import { ApprovalBlockTodos } from './todos/VC.ApprovalBlockTodos';
import { ViewActionLaunch } from './launch/VC.ViewActionLaunch';
import { ApprovalBlockDecorator } from './Dt.ApprovalBlock';
import { ApprovalBlockLaunch } from './launch/VC.ApprovalBlockLaunch';
// 区块-审批
export const ApprovalBlock = () => null;
export const PathNameMap_ApprovalBlock = {
Decorator: 'ApprovalBlock.Decorator',
BlockInitializer: 'ApprovalBlock.BlockInitializer',
Launch: 'ApprovalBlock.Launch',
Todos: 'ApprovalBlock.Todos',
ViewActionLaunch: 'ApprovalBlock.ViewActionLaunch',
ViewActionTodos: 'ApprovalBlock.ViewActionTodos',
};
ApprovalBlock.Decorator = ApprovalBlockDecorator;
ApprovalBlock.BlockInitializer = ApprovalBlockComponent;
ApprovalBlock.Launch = ApprovalBlockLaunch;
ApprovalBlock.Todos = ApprovalBlockTodos;
ApprovalBlock.ViewActionLaunch = ViewActionLaunch;
ApprovalBlock.ViewActionTodos = ViewActionTodos;

View File

@ -5,7 +5,6 @@ import {
FormBlockContext, FormBlockContext,
FormV2, FormV2,
RecordProvider, RecordProvider,
SchemaComponent,
useAPIClient, useAPIClient,
useAssociationNames, useAssociationNames,
useCurrentUserContext, useCurrentUserContext,
@ -23,36 +22,40 @@ export function ApprovalFormBlockDecorator(props) {
const omitApproval = _.omit(approvalExecutions, ['approval', 'job', 'node', 'snapshot']); const omitApproval = _.omit(approvalExecutions, ['approval', 'job', 'node', 'snapshot']);
const { execution, workflow } = useFlowContext(); const { execution, workflow } = useFlowContext();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const field = useField(); const field = useField();
const ref = useRef(null); const formBlockRef = useRef(null);
const { getAssociationAppends } = useAssociationNames(); const { getAssociationAppends } = useAssociationNames();
const { appends, updateAssociationValues } = getAssociationAppends(); const { appends, updateAssociationValues } = getAssociationAppends();
const { data } = useCurrentUserContext(); const { data } = useCurrentUserContext();
const { findComponent } = useDesignable(); const { findComponent } = useDesignable();
const component = findComponent(field.component?.[0]) || Fragment; const ContainerFormComp = findComponent(field.component?.[0]) || Fragment;
const form = useMemo(() => { const form = useMemo(() => {
return createForm({ return createForm({
initialValues: omitApproval, initialValues: omitApproval,
pattern: pattern:
!workflow.enabled || execution.status || job.status || omitApproval.status == null !workflow?.enabled || execution?.status || job?.status || omitApproval?.status == null
? 'disabled' ? 'disabled'
: omitApproval.status || data.data?.id !== omitApproval.userId : omitApproval.status || data.data?.id !== omitApproval.userId
? 'readPretty' ? 'readPretty'
: 'editable', : 'editable',
}); });
}, [data.data?.id, omitApproval.status, workflow.enabled]); }, [data.data?.id, omitApproval?.status, workflow?.enabled]);
const params = useMemo(() => ({ appends: appends, ...props.params }), [appends, props.params]); const params = useMemo(() => ({ appends: appends, ...props.params }), [appends, props.params]);
const result = useMemo(() => ({ loading: false, data: { data: omitApproval } }), [omitApproval]); const result = useMemo(() => ({ loading: false, data: { data: omitApproval } }), [omitApproval]);
const collectionApi = useAPIClient().resource(props.collection); const collectionApi = useAPIClient().resource(props.collection);
const blockRequestContext = useContext(BlockRequestContext_deprecated); const blockRequestContext = useContext(BlockRequestContext_deprecated);
const request = useMemo(
const formValue = useMemo(
() => ({ () => ({
params: params, params: params,
form: form, form: form,
field: field, field: field,
service: result, service: result,
updateAssociationValues: updateAssociationValues, updateAssociationValues: updateAssociationValues,
formBlockRef: ref, formBlockRef: formBlockRef,
}), }),
[field, form, params, result, updateAssociationValues], [field, form, params, result, updateAssociationValues],
); );
@ -76,13 +79,13 @@ export function ApprovalFormBlockDecorator(props) {
__parent: blockRequestContext, __parent: blockRequestContext,
}} }}
> >
<FormBlockContext.Provider value={request}> <FormBlockContext.Provider value={formValue}>
<SchemaComponent component={component} {...field.componentProps}> <ContainerFormComp {...field.componentProps}>
<FormV2.Templates key={1} style={{ marginBottom: 18 }} form={form} /> <FormV2.Templates key={1} style={{ marginBottom: 18 }} form={form} />
<div key={2} ref={ref}> <div key={2} ref={formBlockRef}>
<RecursionField schema={fieldSchema} onlyRenderProperties={true} /> <RecursionField schema={fieldSchema} onlyRenderProperties={true} />
</div> </div>
</SchemaComponent> </ContainerFormComp>
</FormBlockContext.Provider> </FormBlockContext.Provider>
</BlockRequestContext_deprecated.Provider> </BlockRequestContext_deprecated.Provider>
</FormActiveFieldsProvider> </FormActiveFieldsProvider>

View File

@ -13,11 +13,11 @@ export function useContextApprovalAction() {
} }
export function ApprovalActionProvider({ children, ...props }) { export function ApprovalActionProvider({ children, ...props }) {
const context = useContextApprovalExecutions(); const { status } = useContextApprovalExecutions();
if (context && context.status !== props.status) {
return null;
}
if (!status || status === props.status) {
return <ContextApprovalAction.Provider value={props}>{children}</ContextApprovalAction.Provider>; return <ContextApprovalAction.Provider value={props}>{children}</ContextApprovalAction.Provider>;
} }
return null;
}

View File

@ -1,4 +1,3 @@
// @ts-nocheck
import { import {
RemoteSchemaComponent, RemoteSchemaComponent,
SchemaComponent, SchemaComponent,
@ -11,26 +10,26 @@ import { DetailsBlockProvider, ExecutionContextProvider } from '@nocobase/plugin
import { Result, Spin } from 'antd'; import { Result, Spin } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
import { NAMESPACE, useTranslation } from '../../../locale';
import { ApprovalContext } from '../../approval-common/Pd.ApprovalData';
import { ContextWithActionEnabled } from '../../approval-common/Pd.WithActionEnabled'; import { ContextWithActionEnabled } from '../../approval-common/Pd.WithActionEnabled';
import { ContextApprovalExecution } from '../common/Pd.ApprovalExecution'; import { ContextApprovalExecution } from '../common/Pd.ApprovalExecution';
import { ContextApprovalExecutions } from './Pd.ApprovalExecutions';
import { NAMESPACE, useTranslation } from '../../../locale';
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
import { ApprovalContext } from '../../approval-common/Pd.ApprovalData';
import { ApprovalCommon } from '../../approval-common/map';
import { SchemaComponentContextProvider } from '../common/Pd.SchemaComponent'; import { SchemaComponentContextProvider } from '../common/Pd.SchemaComponent';
import { useApprovalDetailBlockProps } from './hooks/useApprovalDetailBlockProps';
import { useApprovalFormBlockProps } from './hooks/useApprovalFormBlockProps';
import { useSubmit } from './hooks/useSubmit';
import { ApprovalFormBlockDecorator } from './Dt.ApprovalFormBlock'; import { ApprovalFormBlockDecorator } from './Dt.ApprovalFormBlock';
import { ActionBarProvider } from './Pd.ActionBarProvider'; import { ActionBarProvider } from './Pd.ActionBarProvider';
import { ApprovalActionProvider } from './Pd.ApprovalAction'; import { ApprovalActionProvider } from './Pd.ApprovalAction';
import { ContextApprovalExecutions } from './Pd.ApprovalExecutions';
import { useApprovalDetailBlockProps } from './hooks/useApprovalDetailBlockProps';
import { useApprovalFormBlockProps } from './hooks/useApprovalFormBlockProps';
import { useSubmit } from './hooks/useSubmit';
// 审批-待办-查看: 内容 // 审批-待办-查看: 内容
export const ViewActionTodosContent = () => { export const ViewActionTodosContent = () => {
const { id } = useRecord(); const { id } = useRecord();
const { t } = useTranslation(); const { t } = useTranslation();
const { actionEnabled } = useContext(ContextWithActionEnabled); const { actionEnabled } = useContext(ContextWithActionEnabled);
const { loading, data } = useRequest( const { loading, data: data }: any = useRequest(
{ {
resource: 'approvalRecords', resource: 'approvalRecords',
action: 'get', action: 'get',
@ -68,15 +67,19 @@ export const ViewActionTodosContent = () => {
}, },
{ refreshDeps: [id] }, { refreshDeps: [id] },
); );
if (loading) return <Spin />; if (loading) return <Spin />;
if (!(data != null && data.data))
if (data == null || !data.data) {
return <Result status="error" title={t('Submission may be withdrawn, please try refresh the list.')} />; return <Result status="error" title={t('Submission may be withdrawn, please try refresh the list.')} />;
}
const items = data.data; const items = data.data;
const { approvalExecution, node, approval, workflow } = items; const { approvalExecution, node, approval, workflow, execution } = items;
const { nodes } = workflow; const { nodes } = workflow;
const omitWorkflow = _.omit(workflow, ['nodes']); const omitWorkflow = _.omit(workflow, ['nodes']);
const { execution } = items; node?.config.applyDetail;
// return null;
return ( return (
<ExecutionContextProvider workflow={omitWorkflow} nodes={nodes} execution={execution}> <ExecutionContextProvider workflow={omitWorkflow} nodes={nodes} execution={execution}>
<ApprovalContext.Provider value={approval}> <ApprovalContext.Provider value={approval}>
@ -84,9 +87,9 @@ export const ViewActionTodosContent = () => {
<ContextApprovalExecutions.Provider value={data.data}> <ContextApprovalExecutions.Provider value={data.data}>
<SchemaComponent <SchemaComponent
components={{ components={{
SchemaComponentProvider: SchemaComponentProvider, SchemaComponentProvider,
RemoteSchemaComponent: RemoteSchemaComponent, RemoteSchemaComponent,
SchemaComponentContextProvider: SchemaComponentContextProvider, SchemaComponentContextProvider,
FormBlockProvider, FormBlockProvider,
ActionBarProvider, ActionBarProvider,
ApprovalActionProvider, ApprovalActionProvider,
@ -113,7 +116,9 @@ export const ViewActionTodosContent = () => {
detail: { detail: {
type: 'void', type: 'void',
'x-decorator': 'SchemaComponentContextProvider', 'x-decorator': 'SchemaComponentContextProvider',
'x-decorator-props': { designable: false }, 'x-decorator-props': {
designable: false,
},
'x-component': 'RemoteSchemaComponent', 'x-component': 'RemoteSchemaComponent',
'x-component-props': { 'x-component-props': {
uid: node?.config.applyDetail, uid: node?.config.applyDetail,
@ -134,7 +139,7 @@ export const ViewActionTodosContent = () => {
history: { history: {
type: 'void', type: 'void',
'x-decorator': 'CardItem', 'x-decorator': 'CardItem',
'x-component': ApprovalCommon.ViewComponent.ApprovalProcess, 'x-component': 'ApprovalCommon.ViewComponent.ApprovalProcess',
}, },
}, },
}, },

View File

@ -1,12 +1,15 @@
import { Plugin } from '@nocobase/client'; import { Plugin } from '@nocobase/client';
import { ApprovalCommon } from './map'; import { ApprovalDataProvider } from './Pd.ApprovalData';
import { ApprovalProcess } from './VC.ApprovalProcess';
export default class PluginKitApprovalCommon extends Plugin { export default class PluginKitApprovalCommon extends Plugin {
async afterAdd() {} async afterAdd() {}
async beforeLoad() {} async beforeLoad() {}
async load() { async load() {
this.app.addComponents({ this.app.addComponents({
ApprovalCommon, // ApprovalCommon,
'ApprovalCommon.Provider.ApprovalDataProvider': ApprovalDataProvider,
'ApprovalCommon.ViewComponent.ApprovalProcess': ApprovalProcess,
}); });
} }
} }

View File

@ -1,26 +0,0 @@
import { ApprovalDataProvider } from './Pd.ApprovalData';
import { ApprovalProcess } from './VC.ApprovalProcess';
// 通用,审批
export const ApprovalCommon = () => null;
ApprovalCommon.PathNameMap = {
Provider: {
ApprovalDataProvider: 'ApprovalCommon.Provider.ApprovalDataProvider',
},
ViewComponent: {
ApprovalProcess: 'ApprovalCommon.ViewComponent.ApprovalProcess',
},
};
ApprovalCommon.Decorator = null;
ApprovalCommon.Provider = {
ApprovalDataProvider,
};
ApprovalCommon.BlockInitializer = null;
ApprovalCommon.ViewComponent = {
ApprovalProcess,
};

View File

@ -2,7 +2,6 @@ import { AuditOutlined } from '@ant-design/icons';
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '@nocobase/client'; import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '@nocobase/client';
import { uid } from '@nocobase/utils/client'; import { uid } from '@nocobase/utils/client';
import React from 'react'; import React from 'react';
import { ApprovalRecordBlock } from './map';
// 初始化器,创建区块-相关审批 // 初始化器,创建区块-相关审批
export function RecordApprovalsInitializer() { export function RecordApprovalsInitializer() {
@ -18,13 +17,13 @@ export function RecordApprovalsInitializer() {
type: 'void', type: 'void',
name: id, name: id,
'x-uid': id, 'x-uid': id,
'x-decorator': ApprovalRecordBlock.PathNameMap.Decorator, 'x-decorator': 'ApprovalRecordBlock.Decorator',
'x-component': 'CardItem', 'x-component': 'CardItem',
'x-designer': 'List.Designer', 'x-designer': 'List.Designer',
properties: { properties: {
block: { block: {
type: 'void', type: 'void',
'x-component': ApprovalRecordBlock.PathNameMap.ViewComponent, 'x-component': 'ApprovalRecordBlock.ViewComponent',
}, },
}, },
}); });

View File

@ -1,5 +1,4 @@
import { NAMESPACE } from '../../locale'; import { NAMESPACE } from '../../locale';
import { ApprovalCommon } from '../approval-common/map';
export const SchemaRecordApprovals = { export const SchemaRecordApprovals = {
type: 'void', type: 'void',
@ -86,9 +85,8 @@ export const SchemaRecordApprovals = {
}, },
processRow: { processRow: {
type: 'void', type: 'void',
// 'x-decorator': 'ApprovalBlock.ApprovalDataProvider', 'x-decorator': 'ApprovalCommon.Provider.ApprovalDataProvider',
'x-decorator': ApprovalCommon.PathNameMap.Provider.ApprovalDataProvider, 'x-component': 'ApprovalCommon.ViewComponent.ApprovalProcess',
'x-component': ApprovalCommon.PathNameMap.ViewComponent.ApprovalProcess,
'x-component-props': { 'x-component-props': {
actionEnabled: true, actionEnabled: true,
}, },

View File

@ -1,44 +0,0 @@
import { RecordApprovalsDecorator } from './Dt.RecordApprovals';
import { RecordApprovalsInitializer } from './Iz.RecordApprovals';
import { RecordApprovals } from './VC.RecordApprovals';
// 区块-相关审批
export const ApprovalRecordBlock = () => null;
// Think: 这里其实可以从框架层面定义, 现在是取名字,
// 可以改为, name和component的对象.让开发体验更友好.
// 目前只是适应框架现在的定义,这样处理
// 名称映射,声明而不是生成,提供ts较好的路径提示信息,便于修改,以及避免遍历计算带来的性能损耗
ApprovalRecordBlock.PathNameMap = {
Decorator: 'ApprovalRecordBlock.Decorator',
BlockInitializer: 'ApprovalRecordBlock.BlockInitializer',
ViewComponent: 'ApprovalRecordBlock.ViewComponent',
};
ApprovalRecordBlock.Decorator = RecordApprovalsDecorator;
ApprovalRecordBlock.BlockInitializer = RecordApprovalsInitializer;
ApprovalRecordBlock.ViewComponent = RecordApprovals;
// ApprovalRecordBlock.PathNameMap = getPathNameMap(ApprovalRecordBlock);
// 改为如下形式, 需要改addComponent的机制, 以及加载组件的机制
// 以下代码为 demo
// export const ApprovalRecordBlock1 = {
// Decorator: {
// name: 'ApprovalRecordBlock.Decorator',
// component: RecordApprovalsDecorator,
// },
// Provider: {
// name: '',
// component: null,
// },
// BlockInitializer: {
// name: 'ApprovalRecordBlock.BlockInitializer',
// component: RecordApprovalsInitializer,
// },
// ViewComponent: {
// name: 'ApprovalRecordBlock.ViewComponent',
// component: RecordApprovals,
// },
// };

View File

@ -2,7 +2,7 @@ import { defineCollection } from '@nocobase/database';
export default defineCollection({ export default defineCollection({
namespace: 'workflow.approvalExecutions', namespace: 'workflow.approvalExecutions',
duplicator: 'required', dumpRules: 'required',
name: 'approvalExecutions', name: 'approvalExecutions',
fields: [ fields: [
{ {

View File

@ -1,7 +1,7 @@
import { defineCollection } from '@nocobase/database'; import { defineCollection } from '@nocobase/database';
export default defineCollection({ export default defineCollection({
namespace: 'workflow.approvalRecords', namespace: 'workflow.approvalRecords',
duplicator: 'required', dumpRules: 'required',
name: 'approvalRecords', name: 'approvalRecords',
fields: [ fields: [
{ {

View File

@ -1,7 +1,7 @@
import { defineCollection } from '@nocobase/database'; import { defineCollection } from '@nocobase/database';
export default defineCollection({ export default defineCollection({
namespace: 'workflow.approvals', namespace: 'workflow.approvals',
duplicator: 'required', dumpRules: 'required',
name: 'approvals', name: 'approvals',
createdBy: true, createdBy: true,
updatedBy: true, updatedBy: true,