feat/approval-0702 (#1264)
Reviewed-on: daoyoucloud/tachybase#1264 Reviewed-by: sealday <zhanglin@daoyoucloud.com> Co-authored-by: bai.zixv <bai.zixv@foxmail.com> Co-committed-by: bai.zixv <bai.zixv@foxmail.com>
This commit is contained in:
parent
c8f99dd228
commit
0d8bbba1da
@ -13,9 +13,9 @@ import { AssigneesSelect } from './approval-config/VC.AssigneesSelect';
|
||||
import { ContentTooltip } from './approval-config/VC.ContentTooltip';
|
||||
import { NegotiationConfig } from './approval-config/VC.NegotiationConfig';
|
||||
import { SchemaConfigButtonApprover } from './approval-config/VC.SchemaConfigButtonApprover';
|
||||
import { ApprovalInstructionNode } from './ApprovalNode.component';
|
||||
import { ApproverInterfaceComponent } from './approver-interface/ApproverInterface.schema';
|
||||
import { isApprovalReturnFunc } from './utils';
|
||||
import { ApprovalInstructionNode } from './VC.ApprovalInstructionNode';
|
||||
|
||||
// 工作流节点 nodes - 人工处理->审批
|
||||
export class ApprovalInstruction extends Instruction {
|
||||
@ -42,13 +42,6 @@ export class ApprovalInstruction extends Instruction {
|
||||
];
|
||||
// 审批节点表单设置
|
||||
fieldset = {
|
||||
collection: {
|
||||
type: 'string',
|
||||
title: '{{t("Collection")}}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DataSourceCollectionCascader',
|
||||
// 'x-disabled': '{{ useWorkflowAnyExecuted() }}',
|
||||
},
|
||||
branchMode: {
|
||||
type: 'boolean',
|
||||
title: `{{t("Pass mode", { ns: "${NAMESPACE}" })}}`,
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { useActionContext } from '@tachybase/client';
|
||||
|
||||
import { ConfigButtonView } from '../../trigger/ConfigButton.view';
|
||||
import { ContextApproverConfig } from '../Pd.ContextApproverConfig';
|
||||
import { ContextApproverConfig } from '../ApproverConfig.context';
|
||||
|
||||
// 审批人操作界面->进入配置按钮
|
||||
export const SchemaConfigButtonApprover = (props) => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { gridRowColWrap, SchemaInitializer, usePlugin } from '@tachybase/client';
|
||||
import { gridRowColWrap, SchemaInitializer, useDataSourceManager, usePlugin } from '@tachybase/client';
|
||||
|
||||
import { useFlowContext } from '../../../../../FlowContext';
|
||||
import { useAvailableUpstreams, useNodeContext } from '../../../../../nodes';
|
||||
import { PluginWorkflow } from '../../../../../Plugin';
|
||||
import { useTrigger } from '../../../../../triggers';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { EditableForm } from './EditableForm.schema';
|
||||
import { approvalFormOptions, ApprovalFormType } from '../forms/Approval.options';
|
||||
import { ApproverAddBlockComponent } from './VC.ApproverAddBlock';
|
||||
import { ApproverAddBlockKit } from './VC.ApproverAddBlockKit';
|
||||
|
||||
@ -33,19 +33,6 @@ export const ApproverAddBlockInitializer = new SchemaInitializer({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'forms',
|
||||
type: 'itemGroup',
|
||||
title: '{{t("Form")}}',
|
||||
children: [
|
||||
{
|
||||
name: 'form',
|
||||
type: 'item',
|
||||
title: `{{t("Apply form", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: EditableForm,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'itemGroup',
|
||||
name: 'dataBlocks',
|
||||
@ -79,6 +66,22 @@ export const ApproverAddBlockInitializer = new SchemaInitializer({
|
||||
].filter(Boolean);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'itemGroup',
|
||||
name: 'form',
|
||||
title: '{{t("Form")}}',
|
||||
useChildren() {
|
||||
const dm = useDataSourceManager();
|
||||
const allCollections = dm.getAllCollections();
|
||||
const values = Array.from(approvalFormOptions.getValues());
|
||||
return values.map((item: ApprovalFormType) => {
|
||||
// NOTE: 这里通过赋别名,避免 eslint 检查 hooks 语法,无法提交
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { useInitializer: getInitializer } = item.config;
|
||||
return getInitializer({ allCollections });
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'others',
|
||||
type: 'itemGroup',
|
@ -8,7 +8,7 @@ import { Spin } from 'antd';
|
||||
import { DetailsBlockProvider, SimpleDesigner } from '../../../../../components';
|
||||
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
|
||||
import { flatSchemaArray } from '../../../constants';
|
||||
import { ContextApproverConfig } from '../Pd.ContextApproverConfig';
|
||||
import { ContextApproverConfig } from '../ApproverConfig.context';
|
||||
import { ActionBarProvider } from './Pd.ActionBarProvider';
|
||||
import { ApprovalActionProvider } from './Pd.ApprovalActionProvider';
|
||||
import { ContextApproverBlock } from './Pd.SchemaConfigButtonContext';
|
||||
|
@ -1,45 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
createEditFormBlockUISchema,
|
||||
createFormBlockSchema,
|
||||
parseCollectionName,
|
||||
SchemaInitializerItem,
|
||||
useRecordCollectionDataSourceItems,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
useSchemaTemplateManager,
|
||||
} from '@tachybase/client';
|
||||
import { useForm } from '@tachybase/schema';
|
||||
|
||||
import { APPROVAL_STATUS, flatSchemaArray } from '../../../constants';
|
||||
|
||||
export const EditableForm = () => {
|
||||
const { insert } = useSchemaInitializer();
|
||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||
const { values } = useForm();
|
||||
const [dataSource, collectionName] = parseCollectionName(values.collection);
|
||||
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
const items = useRecordCollectionDataSourceItems('FormItem');
|
||||
|
||||
const onClick = async ({ item }) => {
|
||||
const template = item.template ? await getTemplateSchemaByMode(item) : null;
|
||||
const formSchema = createEditFormBlockUISchema({
|
||||
dataSource: dataSource,
|
||||
collectionName: collectionName,
|
||||
templateSchema: template,
|
||||
});
|
||||
const [key] = Object.keys(formSchema.properties);
|
||||
const [targetSchema] = flatSchemaArray(
|
||||
formSchema.properties[key],
|
||||
(property) => property['x-component'] === 'ActionBar',
|
||||
);
|
||||
|
||||
targetSchema['x-decorator'] = 'ActionBarProvider';
|
||||
targetSchema['x-component-props'].style = { marginTop: '1.5em', flexWrap: 'wrap' };
|
||||
|
||||
insert(formSchema);
|
||||
};
|
||||
|
||||
return <SchemaInitializerItem {...itemConfig} onClick={onClick} items={items} />;
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
export const ApprovalActionProvider = (props) => {
|
||||
console.log('%c Line:2 🍰 props', 'font-size:18px;color:#4fff4B;background:#7f2b82', props);
|
||||
return props.children;
|
||||
};
|
||||
|
@ -0,0 +1,102 @@
|
||||
import React from 'react';
|
||||
import { CompatibleSchemaInitializer, InitializerWithSwitch, useSchemaInitializerItem } from '@tachybase/client';
|
||||
|
||||
import { JOB_STATUS } from '../../../../../constants';
|
||||
import { APPROVAL_ACTION_STATUS } from '../../../constants';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
// NOTE: 似乎没用, 但删除又报错, 先保留着
|
||||
const addActionButton_deprecated = new CompatibleSchemaInitializer({
|
||||
name: 'ApprovalAddActionButton',
|
||||
title: '{{t("Configure actions")}}',
|
||||
items: [
|
||||
{
|
||||
name: 'jobStatusResolved',
|
||||
title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
action: JOB_STATUS.RESOLVED,
|
||||
actionProps: {
|
||||
type: 'primary',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'jobStatusRejected',
|
||||
title: `{{t("Terminate the process", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
action: JOB_STATUS.REJECTED,
|
||||
actionProps: {
|
||||
danger: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'jobStatusPending',
|
||||
title: `{{t("Save temporarily", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
action: JOB_STATUS.PENDING,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const ApprovalAddActionButton = new CompatibleSchemaInitializer(
|
||||
{
|
||||
name: 'ApprovalAddActionButton',
|
||||
title: '{{t("Configure actions")}}',
|
||||
items: [
|
||||
{
|
||||
name: 'approvalStatusResolved',
|
||||
title: `{{t("Continue the process", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
statusApproval: APPROVAL_ACTION_STATUS.APPROVED,
|
||||
actionProps: {
|
||||
type: 'primary',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'approvalStatusRejected',
|
||||
title: `{{t("Terminate the process", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
statusApproval: APPROVAL_ACTION_STATUS.REJECTED,
|
||||
actionProps: {
|
||||
danger: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'approvalStatusPending',
|
||||
title: `{{t("Save temporarily", { ns: "${NAMESPACE}" })}}`,
|
||||
Component: ActionInitializer,
|
||||
statusApproval: APPROVAL_ACTION_STATUS.PENDING,
|
||||
},
|
||||
],
|
||||
},
|
||||
addActionButton_deprecated,
|
||||
);
|
||||
|
||||
function ActionInitializer() {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
const { statusApproval, actionProps, ...others } = itemConfig;
|
||||
return (
|
||||
<InitializerWithSwitch
|
||||
{...others}
|
||||
item={itemConfig}
|
||||
schema={{
|
||||
type: 'void',
|
||||
title: others.title,
|
||||
'x-decorator': 'ApprovalActionProvider',
|
||||
'x-decorator-props': {
|
||||
status: statusApproval,
|
||||
},
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
...actionProps,
|
||||
useAction: `{{ () => useSubmit({source: "updateRecord"}) }}`,
|
||||
},
|
||||
'x-designer': 'Action.Designer',
|
||||
'x-action': `${statusApproval}`,
|
||||
}}
|
||||
type="x-action"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import { SchemaInitializerItemType } from '@tachybase/client';
|
||||
import { Registry } from '@tachybase/utils/client';
|
||||
|
||||
import { JOB_STATUS } from '../../../../../constants';
|
||||
import updateFormConfig from './update';
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type FormType = {
|
||||
type: 'create' | 'update' | 'custom';
|
||||
title: string;
|
||||
actions: ValueOf<typeof JOB_STATUS>[];
|
||||
collection:
|
||||
| string
|
||||
| {
|
||||
name: string;
|
||||
fields: any[];
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
|
||||
export type ApprovalFormType = {
|
||||
title: string;
|
||||
config: {
|
||||
useInitializer: ({ allCollections }?: { allCollections: any[] }) => SchemaInitializerItemType;
|
||||
initializers?: {
|
||||
[key: string]: React.FC;
|
||||
};
|
||||
components?: {
|
||||
[key: string]: React.FC;
|
||||
};
|
||||
parseFormOptions(root: ISchema): { [key: string]: FormType };
|
||||
};
|
||||
block: {
|
||||
scope?: {
|
||||
[key: string]: () => any;
|
||||
};
|
||||
components?: {
|
||||
[key: string]: React.FC;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const approvalFormOptions = new Registry<ApprovalFormType>();
|
||||
approvalFormOptions.register('updateForm', updateFormConfig as ApprovalFormType);
|
@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
CollectionProvider_deprecated,
|
||||
createFormBlockSchema,
|
||||
Plugin,
|
||||
SchemaInitializerItem,
|
||||
SchemaInitializerItemType,
|
||||
useRecordCollectionDataSourceItems,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
useSchemaTemplateManager,
|
||||
} from '@tachybase/client';
|
||||
|
||||
import { traverseSchema } from '../../../../../utils';
|
||||
import { ApprovalAddActionButton } from './AddActionButton.setting';
|
||||
|
||||
export class KitApprovalAddActionButton extends Plugin {
|
||||
async load() {
|
||||
this.app.schemaInitializerManager.add(ApprovalAddActionButton);
|
||||
}
|
||||
}
|
||||
|
||||
function InternalFormBlockInitializer({ schema, ...others }) {
|
||||
const { insert } = useSchemaInitializer();
|
||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||
const items = useRecordCollectionDataSourceItems('FormItem') as SchemaInitializerItemType[];
|
||||
const onClick = async (item) => {
|
||||
const template = item.template ? await getTemplateSchemaByMode(item) : null;
|
||||
const result = createFormBlockSchema({
|
||||
actionInitializers: 'ApprovalAddActionButton',
|
||||
...schema,
|
||||
template,
|
||||
});
|
||||
delete result['x-acl-action-props'];
|
||||
delete result['x-acl-action'];
|
||||
const [formKey] = Object.keys(result.properties);
|
||||
//获取actionBar的schemakey
|
||||
const actionKey =
|
||||
Object.entries(result.properties[formKey].properties).find(([key, f]) => f['x-component'] === 'ActionBar')?.[0] ||
|
||||
'actions';
|
||||
result.properties[formKey].properties[actionKey]['x-decorator'] = 'ActionBarProvider';
|
||||
result.properties[formKey].properties[actionKey]['x-component-props'].style = {
|
||||
marginTop: '1.5em',
|
||||
flexWrap: 'wrap',
|
||||
};
|
||||
traverseSchema(result, (node) => {
|
||||
if (node['x-uid']) {
|
||||
delete node['x-uid'];
|
||||
}
|
||||
});
|
||||
insert(result);
|
||||
};
|
||||
|
||||
return <SchemaInitializerItem {...others} onClick={onClick} items={items} />;
|
||||
}
|
||||
|
||||
export const FormBlockFactory = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
return (
|
||||
<CollectionProvider_deprecated
|
||||
dataSource={itemConfig.schema?.dataSource}
|
||||
collection={itemConfig.schema?.collection}
|
||||
>
|
||||
<InternalFormBlockInitializer {...itemConfig} />
|
||||
</CollectionProvider_deprecated>
|
||||
);
|
||||
};
|
@ -0,0 +1,109 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useMenuSearch } from '@tachybase/client';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { FilterDynamicComponent } from '../../../../../components';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { FormBlockFactory } from './FormBlock.factory';
|
||||
|
||||
const updateFormConfig = {
|
||||
title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
|
||||
config: {
|
||||
initializers: {},
|
||||
components: {
|
||||
FilterDynamicComponent,
|
||||
},
|
||||
useInitializer: ({ allCollections }) => {
|
||||
const childItems = useMemo(() => {
|
||||
const results = allCollections.map(({ key, displayName, collections }) => ({
|
||||
key,
|
||||
name: key,
|
||||
label: displayName,
|
||||
type: 'subMenu',
|
||||
children: collections.map(({ name, title, tableName }) => ({
|
||||
name: _.camelCase(`updateRecordForm-child-${name}`),
|
||||
type: 'item',
|
||||
title: title || tableName,
|
||||
schema: {
|
||||
collection: name,
|
||||
dataSource: key,
|
||||
formType: 'update',
|
||||
},
|
||||
Component: FormBlockFactory,
|
||||
})),
|
||||
}));
|
||||
return results;
|
||||
}, [allCollections]);
|
||||
const [openMenuKeys, setOpenMenuKeys] = useState([]);
|
||||
const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys });
|
||||
return {
|
||||
name: 'updateRecordForm',
|
||||
key: 'updateRecordForm',
|
||||
type: 'subMenu',
|
||||
title: `{{t("Update record form", { ns: "${NAMESPACE}" })}}`,
|
||||
componentProps: {
|
||||
onOpenChange(keys) {
|
||||
setOpenMenuKeys(keys);
|
||||
},
|
||||
},
|
||||
children: searchedChildren,
|
||||
};
|
||||
},
|
||||
parseFormOptions: (root) => {
|
||||
const forms = {};
|
||||
const formBlocks: any[] = findSchema(
|
||||
root,
|
||||
(item) => item['x-decorator'] === 'FormBlockProvider' && item['x-decorator-props'].formType === 'update',
|
||||
);
|
||||
|
||||
formBlocks.forEach((formBlock) => {
|
||||
const [formKey] = Object.keys(formBlock.properties);
|
||||
const formSchema = formBlock.properties[formKey];
|
||||
//获取actionBar的schemakey
|
||||
const actionKey =
|
||||
Object.entries(formSchema.properties).find(([key, f]) => f['x-component'] === 'ActionBar')?.[0] || 'actions';
|
||||
forms[formKey] = {
|
||||
...formBlock['x-decorator-props'],
|
||||
type: 'update',
|
||||
title: formBlock['x-component-props']?.title || formKey,
|
||||
actions: findSchema(formSchema.properties[actionKey], (item) => item['x-component'] === 'Action').map(
|
||||
(item) => ({
|
||||
status: item['x-decorator-props'].value,
|
||||
values: item['x-action-settings']?.assignedValues?.values,
|
||||
key: item.name,
|
||||
}),
|
||||
),
|
||||
};
|
||||
});
|
||||
return forms;
|
||||
},
|
||||
},
|
||||
block: {
|
||||
scope: {},
|
||||
components: {},
|
||||
},
|
||||
};
|
||||
|
||||
// utils
|
||||
function findSchema(schema, filter, onlyLeaf = false) {
|
||||
const result = [];
|
||||
|
||||
if (!schema) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (filter(schema) && (!onlyLeaf || !schema.properties)) {
|
||||
result.push(schema);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (schema.properties) {
|
||||
Object.keys(schema.properties).forEach((key) => {
|
||||
result.push(...findSchema(schema.properties[key], filter));
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export default updateFormConfig;
|
@ -1,11 +1,16 @@
|
||||
import { Plugin } from '@tachybase/client';
|
||||
|
||||
import { PluginWorkflow } from '../../../../Plugin';
|
||||
import { ApprovalInstruction } from './Approval.node';
|
||||
import { ApproverAddBlockInitializer } from './approver-interface/ApproverAddBlock.initializer';
|
||||
import { ApproverActionConfigInitializer } from './approver-interface/Iz.ApproverActionConfig';
|
||||
import { ApproverAddBlockInitializer } from './approver-interface/Iz.ApproverAddBlock';
|
||||
import { ApprovalInstruction } from './node.ApprovalInstruction';
|
||||
import { KitApprovalAddActionButton } from './forms/FormBlock.factory';
|
||||
|
||||
export class KitApprovalInstruction extends Plugin {
|
||||
async afterAdd(): Promise<void> {
|
||||
this.pm.add(KitApprovalAddActionButton);
|
||||
}
|
||||
|
||||
async load() {
|
||||
const pluginWorkflow = this.app.pm.get(PluginWorkflow);
|
||||
pluginWorkflow.registerInstruction('approval', ApprovalInstruction);
|
||||
|
@ -5,37 +5,7 @@ import { useForm } from '@tachybase/schema';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { SchemaAddBlock } from './SchemaAddBlock.component';
|
||||
|
||||
// 发起人操作界面
|
||||
const getSchemaLauncherInterface = ({ values, dataSource, name }) => ({
|
||||
name: values.collection,
|
||||
type: 'void',
|
||||
properties: {
|
||||
drawer: {
|
||||
type: 'void',
|
||||
title: `{{t("Initiator's interface", { ns: "${NAMESPACE}" })}}`,
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
className: css`
|
||||
.ant-drawer-body {
|
||||
background: const(--tb-box-bg);
|
||||
}
|
||||
`,
|
||||
},
|
||||
properties: {
|
||||
applyForm: {
|
||||
type: 'string',
|
||||
'x-decorator': 'CollectionProvider_deprecated',
|
||||
'x-decorator-props': {
|
||||
dataSource,
|
||||
name,
|
||||
},
|
||||
'x-component': 'SchemaAddBlock',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}); // 触发器-发起人的操作界面
|
||||
|
||||
// 触发器-发起人的操作界面
|
||||
export const LauncherInterface = () => {
|
||||
const { values } = useForm();
|
||||
const [dataSource, name] = parseCollectionName(values.collection);
|
||||
@ -50,3 +20,36 @@ export const LauncherInterface = () => {
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// 发起人操作界面
|
||||
function getSchemaLauncherInterface({ values, dataSource, name }) {
|
||||
return {
|
||||
name: values.collection,
|
||||
type: 'void',
|
||||
properties: {
|
||||
drawer: {
|
||||
type: 'void',
|
||||
title: `{{t("Initiator's interface", { ns: "${NAMESPACE}" })}}`,
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
className: css`
|
||||
.ant-drawer-body {
|
||||
background: const(--tb-box-bg);
|
||||
}
|
||||
`,
|
||||
},
|
||||
properties: {
|
||||
applyForm: {
|
||||
type: 'string',
|
||||
'x-decorator': 'CollectionProvider_deprecated',
|
||||
'x-decorator-props': {
|
||||
dataSource,
|
||||
name,
|
||||
},
|
||||
'x-component': 'SchemaAddBlock',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { JOB_STATUS } from '../../constants';
|
||||
import { lang, NAMESPACE } from './locale';
|
||||
|
||||
// 审批状态
|
||||
// 审批发起的状态
|
||||
export const APPROVAL_STATUS = {
|
||||
DRAFT: 0,
|
||||
RETURNED: 1,
|
||||
@ -11,6 +11,7 @@ export const APPROVAL_STATUS = {
|
||||
REJECTED: -1,
|
||||
};
|
||||
|
||||
// 审批执行的状态
|
||||
export const APPROVAL_ACTION_STATUS = {
|
||||
ASSIGNED: null,
|
||||
PENDING: 0,
|
||||
|
@ -16,8 +16,6 @@ export function useDestroyAction() {
|
||||
return {
|
||||
async run() {
|
||||
try {
|
||||
console.log('%c Line:16 🍓 run', 'font-size:18px;color:#6ec1c2;background:#93c0a4');
|
||||
|
||||
_.set(field, ['data', 'loading'], true);
|
||||
|
||||
await apiClient.resource('approvals').destroy({
|
||||
|
@ -27,7 +27,6 @@ export function useWithdrawAction() {
|
||||
field.data.loading = false;
|
||||
refreshTable();
|
||||
} catch (v) {
|
||||
console.log('%c Line:33 🌽 v', 'font-size:18px;color:#33a5ff;background:#fca650', v);
|
||||
if (field.data) {
|
||||
field.data.loading = false;
|
||||
}
|
||||
|
@ -2,16 +2,12 @@ import React, { createContext, useContext } from 'react';
|
||||
|
||||
import { useContextApprovalExecutions } from './Pd.ApprovalExecutions';
|
||||
|
||||
export interface ApprovalAction {
|
||||
interface ApprovalAction {
|
||||
status: number | null;
|
||||
}
|
||||
|
||||
const ContextApprovalAction = createContext<Partial<ApprovalAction>>({});
|
||||
|
||||
export function useContextApprovalAction() {
|
||||
return useContext(ContextApprovalAction);
|
||||
}
|
||||
|
||||
export function ApprovalActionProvider({ children, ...props }) {
|
||||
const { status } = useContextApprovalExecutions();
|
||||
|
||||
@ -21,3 +17,8 @@ export function ApprovalActionProvider({ children, ...props }) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function useContextApprovalAction() {
|
||||
const context = useContext(ContextApprovalAction);
|
||||
return context;
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { useAPIClient } from '@tachybase/client';
|
||||
import { useAPIClient, useCollection } from '@tachybase/client';
|
||||
import { useField, useForm } from '@tachybase/schema';
|
||||
|
||||
import { useHandleRefresh } from '../../common/useHandleRefresh';
|
||||
import { useContextApprovalAction } from '../Pd.ApprovalAction';
|
||||
import { useContextApprovalExecutions } from '../Pd.ApprovalExecutions';
|
||||
|
||||
export function useSubmit() {
|
||||
export function useSubmit(props: any = {}) {
|
||||
const { refreshTable } = useHandleRefresh();
|
||||
|
||||
const field = useField();
|
||||
const api = useAPIClient();
|
||||
const form = useForm();
|
||||
const collection = useCollection();
|
||||
const approvalExecutions = useContextApprovalExecutions();
|
||||
const { status } = useContextApprovalAction();
|
||||
const { source } = props;
|
||||
const needUpdateRecord = source === 'updateRecord';
|
||||
|
||||
return {
|
||||
run: async () => {
|
||||
@ -20,14 +22,27 @@ export function useSubmit() {
|
||||
if (form.values.status) {
|
||||
return;
|
||||
}
|
||||
|
||||
await form.submit();
|
||||
field.data = field.data ?? {};
|
||||
field.data.loading = true;
|
||||
|
||||
if (needUpdateRecord) {
|
||||
const collectionName = collection.name;
|
||||
const targetId = form.values.id;
|
||||
|
||||
await api.resource(collectionName).update({
|
||||
filterByTk: targetId,
|
||||
values: form.values,
|
||||
});
|
||||
}
|
||||
|
||||
await api.resource('approvalRecords').submit({
|
||||
filterByTk: approvalExecutions.id,
|
||||
values: { ...form.values, status },
|
||||
values: {
|
||||
status,
|
||||
needUpdateRecord,
|
||||
data: form.values,
|
||||
},
|
||||
});
|
||||
|
||||
field.data.loading = false;
|
||||
|
@ -234,6 +234,7 @@ const approvalRecords = {
|
||||
async submit(context, next) {
|
||||
const repository = utils.getRepositoryFromParams(context);
|
||||
const { filterByTk, values } = context.action.params;
|
||||
const { data, status, needUpdateRecord } = values || {};
|
||||
const { currentUser } = context.state;
|
||||
if (!currentUser) {
|
||||
return context.throw(401);
|
||||
@ -254,13 +255,13 @@ const approvalRecords = {
|
||||
approvalRecord.execution.status ||
|
||||
approvalRecord.job.status ||
|
||||
approvalRecord.status !== APPROVAL_ACTION_STATUS.PENDING ||
|
||||
!(approvalRecord.node.config.actions ?? []).includes(values.status)
|
||||
(!needUpdateRecord && !(approvalRecord.node.config.actions ?? []).includes(status))
|
||||
) {
|
||||
return context.throw(400);
|
||||
}
|
||||
await approvalRecord.update({
|
||||
status: values.status,
|
||||
comment: values.comment,
|
||||
status: status,
|
||||
comment: data.comment,
|
||||
snapshot: approvalRecord.approval.data,
|
||||
summary: approvalRecord.approval.summary,
|
||||
collectionName: approvalRecord.approval.collectionName,
|
||||
|
Loading…
Reference in New Issue
Block a user