feat: approval, resubmit approval (#1270)
Reviewed-on: daoyoucloud/tachybase#1270 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
81a622e77d
commit
86cc441465
@ -6,7 +6,7 @@ import { uid } from '@tachybase/utils/client';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
import { DetailsBlockProvider, SimpleDesigner } from '../../../../../components';
|
||||
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
|
||||
import { FormBlockProvider } from '../../../common/FormBlock.provider';
|
||||
import { flatSchemaArray } from '../../../constants';
|
||||
import { ContextApproverConfig } from '../ApproverConfig.context';
|
||||
import { ActionBarProvider } from './Pd.ActionBarProvider';
|
||||
|
@ -11,7 +11,7 @@ import { useForm } from '@tachybase/schema';
|
||||
import { uid } from '@tachybase/utils/client';
|
||||
|
||||
import { useFlowContext } from '../../../../../FlowContext';
|
||||
import { CollectionApprovalTodos } from '../../../common/Cn.ApprovalTodos';
|
||||
import { CollectionApprovalTodos } from '../../../common/ApprovalTodos.collection';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { SchemaAddBlock } from '../../trigger/launcher-interface/SchemaAddBlock.component';
|
||||
import { ApproverBlock } from './ApproverBlock.view';
|
||||
|
@ -1,4 +1,3 @@
|
||||
export const ApprovalActionProvider = (props) => {
|
||||
console.log('%c Line:2 🍰 props', 'font-size:18px;color:#4fff4B;background:#7f2b82', props);
|
||||
return props.children;
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import { ActionInitializer, useSchemaInitializerItem } from '@tachybase/client';
|
||||
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
|
||||
// 区块-配置操作
|
||||
export const LauncherActionConfigComponent = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
@ -29,3 +31,29 @@ export const LauncherActionConfigComponent = () => {
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// setup-action-resubmit
|
||||
export const LauncherActionConfigReSubmit = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
const { action, actionProps = {}, ...restItemConfig } = itemConfig;
|
||||
return (
|
||||
<ActionInitializer
|
||||
{...restItemConfig}
|
||||
schema={{
|
||||
type: 'void',
|
||||
title: restItemConfig.title,
|
||||
'x-decorator': 'ProviderActionResubmit',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
confirm: {
|
||||
title: `{{t('resubmit', { ns: "${NAMESPACE}" })}}`,
|
||||
content: `{{t('Are you sure you want to resubmit it?', { ns: "${NAMESPACE}" })}}`,
|
||||
},
|
||||
useAction: '{{ useActionResubmit }}',
|
||||
},
|
||||
'x-designer': 'Action.Designer',
|
||||
'x-action': `reSubmit`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -2,11 +2,11 @@ import { SchemaInitializer } from '@tachybase/client';
|
||||
|
||||
import { APPROVAL_STATUS } from '../../../constants';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { LauncherActionConfigComponent } from './LauncherActionConfig.component';
|
||||
import { LauncherActionConfigComponent, LauncherActionConfigReSubmit } from './LauncherActionConfig.component';
|
||||
|
||||
// 区块-配置操作
|
||||
export const LauncherActionConfigInitializer = new SchemaInitializer({
|
||||
name: 'ApprovalApplyAddActionButton',
|
||||
name: 'LauncherActionConfigInitializer',
|
||||
title: '{{t("Configure actions")}}',
|
||||
items: [
|
||||
{
|
||||
@ -25,5 +25,12 @@ export const LauncherActionConfigInitializer = new SchemaInitializer({
|
||||
Component: LauncherActionConfigComponent,
|
||||
action: APPROVAL_STATUS.DRAFT,
|
||||
},
|
||||
{
|
||||
name: 'reSubmit',
|
||||
type: 'item',
|
||||
title: `{{t("resubmit", { ns: "${NAMESPACE}" })}}`,
|
||||
action: APPROVAL_STATUS.RESUBMIT,
|
||||
Component: LauncherActionConfigReSubmit,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -27,15 +27,21 @@ export const LauncherAddBlockButtonComponent = () => {
|
||||
['x-acl-action']: deleteB,
|
||||
...formSchema
|
||||
} = createFormBlockSchema({
|
||||
actionInitializers: 'ApprovalApplyAddActionButton',
|
||||
actionInitializers: 'LauncherActionConfigInitializer',
|
||||
actions: {
|
||||
submit: {
|
||||
type: 'void',
|
||||
title: '{{t("Submit")}}',
|
||||
'x-decorator': 'ApplyActionStatusProvider',
|
||||
'x-decorator-props': { value: APPROVAL_STATUS.SUBMITTED },
|
||||
'x-decorator-props': {
|
||||
value: APPROVAL_STATUS.SUBMITTED,
|
||||
},
|
||||
'x-component': 'Action',
|
||||
'x-component-props': { type: 'primary', htmlType: 'submit', useAction: '{{ useSubmit }}' },
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
htmlType: 'submit',
|
||||
useAction: '{{ useSubmit }}',
|
||||
},
|
||||
'x-designer': 'Action.Designer',
|
||||
'x-designer-props': {},
|
||||
'x-action': `${APPROVAL_STATUS.SUBMITTED}`,
|
||||
|
@ -53,11 +53,13 @@ export const SchemaAddBlock = ({ value, onChange }) => {
|
||||
ActionBarProvider,
|
||||
ApplyActionStatusProvider,
|
||||
WithdrawActionProvider,
|
||||
ProviderActionResubmit,
|
||||
}}
|
||||
scope={{
|
||||
useSubmit,
|
||||
useWithdrawAction,
|
||||
useFormBlockProps,
|
||||
useActionResubmit,
|
||||
}}
|
||||
// @ts-ignore ugly
|
||||
schema={data}
|
||||
@ -80,6 +82,13 @@ function ApplyActionStatusProvider(props) {
|
||||
function WithdrawActionProvider(props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function useActionResubmit() {
|
||||
return { run() {} };
|
||||
}
|
||||
function ProviderActionResubmit(props) {
|
||||
return props.children;
|
||||
}
|
||||
// TODO:
|
||||
const E = (f, o, p) =>
|
||||
// eslint-disable-next-line promise/param-names
|
||||
|
@ -8,6 +8,7 @@ export const APPROVAL_STATUS = {
|
||||
SUBMITTED: 2,
|
||||
PROCESSING: 3,
|
||||
APPROVED: 4,
|
||||
RESUBMIT: 5,
|
||||
REJECTED: -1,
|
||||
};
|
||||
|
||||
@ -37,17 +38,43 @@ export const approvalStatusConfigObj = approvalStatusOptions.reduce(
|
||||
{},
|
||||
);
|
||||
export const ApprovalStatusEnums = [
|
||||
{ value: APPROVAL_STATUS.DRAFT, label: `{{t("Draft", { ns: "${NAMESPACE}" })}}`, editable: true },
|
||||
{
|
||||
value: APPROVAL_STATUS.DRAFT,
|
||||
label: `{{t("Draft", { ns: "${NAMESPACE}" })}}`,
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
value: APPROVAL_STATUS.RETURNED,
|
||||
label: `{{t("Returned", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'purple',
|
||||
editable: true,
|
||||
},
|
||||
{ value: APPROVAL_STATUS.SUBMITTED, label: `{{t("Submitted", { ns: "${NAMESPACE}" })}}`, color: 'cyan' },
|
||||
{ value: APPROVAL_STATUS.PROCESSING, label: `{{t("Processing", { ns: "${NAMESPACE}" })}}`, color: 'gold' },
|
||||
{ value: APPROVAL_STATUS.APPROVED, label: `{{t("Approved", { ns: "${NAMESPACE}" })}}`, color: 'green' },
|
||||
{ value: APPROVAL_STATUS.REJECTED, label: `{{t("Rejected", { ns: "${NAMESPACE}" })}}`, color: 'red' },
|
||||
{
|
||||
value: APPROVAL_STATUS.SUBMITTED,
|
||||
label: `{{t("Submitted", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'cyan',
|
||||
},
|
||||
{
|
||||
value: APPROVAL_STATUS.PROCESSING,
|
||||
label: `{{t("Processing", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'gold',
|
||||
},
|
||||
{
|
||||
value: APPROVAL_STATUS.APPROVED,
|
||||
label: `{{t("Approved", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
value: APPROVAL_STATUS.RESUBMIT,
|
||||
label: `{{t("reSubmit", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'blue',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
value: APPROVAL_STATUS.REJECTED,
|
||||
label: `{{t("Rejected", { ns: "${NAMESPACE}" })}}`,
|
||||
color: 'red',
|
||||
},
|
||||
];
|
||||
export const ApprovalStatusEnumDict = ApprovalStatusEnums.reduce((e, t) => Object.assign(e, { [t.value]: t }), {});
|
||||
export const JobStatusEnums = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { ExtendCollectionsProvider, TableBlockProvider, useRecord } from '@tachybase/client';
|
||||
|
||||
import { CollectionApprovalTodos } from '../../common/Cn.ApprovalTodos';
|
||||
import { CollectionApprovalTodos } from '../../common/ApprovalTodos.collection';
|
||||
import { CollectionApprovals } from '../approval-common/Approvals.collection';
|
||||
import { CollectionFlowNodes } from '../approval-common/FlowNodes.collection';
|
||||
import { CollectionWorkflows } from '../approval-common/Workflows.collection';
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { useCurrentUserContext } from '@tachybase/client';
|
||||
|
||||
import { useFlowContext } from '../../../../../FlowContext';
|
||||
import { APPROVAL_STATUS } from '../../../constants';
|
||||
import { useApproval } from '../../approval-common/ApprovalData.provider';
|
||||
|
||||
export function ProviderActionResubmit(props) {
|
||||
const { data } = useCurrentUserContext();
|
||||
const { status, createdById } = useApproval();
|
||||
const { workflow } = useFlowContext();
|
||||
|
||||
const isSameId = data.data.id === createdById;
|
||||
// const isEnabledWithdraw = workflow.enabled && workflow.config.withdrawable;
|
||||
// const isNotDraft = status !== APPROVAL_STATUS.DRAFT;
|
||||
|
||||
if (isSameId) {
|
||||
return props.children;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
@ -11,7 +11,12 @@ export function ActionBarProvider(props) {
|
||||
|
||||
const isSameId = data.data.id === createdById;
|
||||
const isSameExcutionId = latestExecutionId === approvalExecution.id;
|
||||
const isExcutionDid = [APPROVAL_STATUS.DRAFT, APPROVAL_STATUS.RETURNED, APPROVAL_STATUS.SUBMITTED].includes(status);
|
||||
const isExcutionDid = [
|
||||
APPROVAL_STATUS.DRAFT,
|
||||
APPROVAL_STATUS.RETURNED,
|
||||
APPROVAL_STATUS.SUBMITTED,
|
||||
APPROVAL_STATUS.RESUBMIT,
|
||||
].includes(status);
|
||||
|
||||
if (!isSameId || !isSameExcutionId || !isExcutionDid) {
|
||||
return null;
|
||||
|
@ -18,7 +18,7 @@ export function ApplyActionStatusProvider(props) {
|
||||
const { data } = useCurrentUserContext();
|
||||
const isSameId = data.data.id === createdById;
|
||||
const isEnbled = workflow.enabled;
|
||||
const isStatusDid = [APPROVAL_STATUS.DRAFT, APPROVAL_STATUS.RETURNED].includes(status);
|
||||
const isStatusDid = [APPROVAL_STATUS.RESUBMIT, APPROVAL_STATUS.DRAFT, APPROVAL_STATUS.RETURNED].includes(status);
|
||||
|
||||
if (isSameId && isEnbled && isStatusDid) {
|
||||
return <ContextApprovalStatus.Provider value={value}>{children}</ContextApprovalStatus.Provider>;
|
||||
|
@ -12,13 +12,16 @@ import { useForm } from '@tachybase/schema';
|
||||
import { Result, Spin } from 'antd';
|
||||
|
||||
import { DetailsBlockProvider } from '../../../../../components';
|
||||
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
|
||||
import { FormBlockProvider } from '../../../common/FormBlock.provider';
|
||||
import { APPROVAL_STATUS } from '../../../constants';
|
||||
import { NAMESPACE } from '../../../locale';
|
||||
import { ApprovalContext } from '../../approval-common/ApprovalData.provider';
|
||||
import { ContextWithActionEnabled } from '../../approval-common/WithActionEnabled.provider';
|
||||
import { ContextApprovalExecution } from '../common/ApprovalExecution.provider';
|
||||
import { FlowContextProvider } from '../common/FlowContext.provider';
|
||||
import { SchemaComponentContextProvider } from '../common/SchemaComponent.provider';
|
||||
import { ProviderActionResubmit } from './ActionResubmit.provider';
|
||||
import { useActionResubmit } from './hooks/useActionResubmit';
|
||||
import { useDestroyAction } from './hooks/useDestroyAction';
|
||||
import { useFormBlockProps } from './hooks/useFormBlockProps';
|
||||
import { useSubmit } from './hooks/useSubmit';
|
||||
@ -59,6 +62,8 @@ export const ViewActionLaunchContent = () => {
|
||||
// @ts-ignore
|
||||
const approvalData = data?.data;
|
||||
|
||||
const needHideProcess = actionEnabled || approvalData?.status !== APPROVAL_STATUS.RESUBMIT;
|
||||
|
||||
if (loading) {
|
||||
return <Spin />;
|
||||
}
|
||||
@ -90,6 +95,7 @@ export const ViewActionLaunchContent = () => {
|
||||
ApplyActionStatusProvider,
|
||||
WithdrawActionProvider,
|
||||
DetailsBlockProvider,
|
||||
ProviderActionResubmit,
|
||||
}}
|
||||
scope={{
|
||||
useForm,
|
||||
@ -98,6 +104,7 @@ export const ViewActionLaunchContent = () => {
|
||||
useDetailsBlockProps: useFormBlockContext,
|
||||
useWithdrawAction,
|
||||
useDestroyAction,
|
||||
useActionResubmit,
|
||||
}}
|
||||
schema={{
|
||||
name: `view-${approval == null ? void 0 : approval.id}`,
|
||||
@ -116,7 +123,9 @@ export const ViewActionLaunchContent = () => {
|
||||
detail: {
|
||||
type: 'void',
|
||||
'x-decorator': 'SchemaComponentContextProvider',
|
||||
'x-decorator-props': { designable: false },
|
||||
'x-decorator-props': {
|
||||
designable: true,
|
||||
},
|
||||
'x-component': 'RemoteSchemaComponent',
|
||||
'x-component-props': {
|
||||
uid: workflow?.config.applyForm,
|
||||
@ -126,7 +135,7 @@ export const ViewActionLaunchContent = () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
actionEnabled
|
||||
needHideProcess
|
||||
? {}
|
||||
: {
|
||||
process: {
|
||||
|
@ -0,0 +1,59 @@
|
||||
import { useAPIClient } from '@tachybase/client';
|
||||
import { useFlowContext } from '@tachybase/plugin-workflow/client';
|
||||
import { useField } from '@tachybase/schema';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { APPROVAL_STATUS } from '../../../../constants';
|
||||
import { useApproval } from '../../../approval-common/ApprovalData.provider';
|
||||
import { useHandleRefresh } from '../../common/useHandleRefresh';
|
||||
|
||||
// 重新发起
|
||||
export function useActionResubmit() {
|
||||
const { refreshTable } = useHandleRefresh();
|
||||
|
||||
const field = useField();
|
||||
const approval = useApproval();
|
||||
const api = useAPIClient();
|
||||
|
||||
const { workflow } = useFlowContext();
|
||||
|
||||
return {
|
||||
async run() {
|
||||
try {
|
||||
field.data = field.data ?? {};
|
||||
|
||||
field.data.loading = true;
|
||||
|
||||
const appendsConfigs = [...workflow.config.appends];
|
||||
const summaryConfigs = [...workflow.config.summary];
|
||||
const appends = _.intersection(appendsConfigs, summaryConfigs);
|
||||
|
||||
const { data: approvalData } = await api.resource('approvals').get({
|
||||
filterByTk: approval.id,
|
||||
});
|
||||
|
||||
const { collectionName, data, workflowId } = approvalData.data;
|
||||
|
||||
const newData = _.omit(data, ['id', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy']);
|
||||
|
||||
await api.resource('approvals').reSubmit({
|
||||
values: {
|
||||
collectionName: collectionName,
|
||||
data: newData,
|
||||
status: APPROVAL_STATUS.RESUBMIT,
|
||||
workflowId: workflowId,
|
||||
collectionAppends: appends,
|
||||
},
|
||||
});
|
||||
|
||||
field.data.loading = false;
|
||||
refreshTable();
|
||||
} catch (v) {
|
||||
if (field.data) {
|
||||
field.data.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
@ -13,7 +13,7 @@ import _ from 'lodash';
|
||||
|
||||
import { DetailsBlockProvider } from '../../../../../components';
|
||||
import { ExecutionContextProvider } from '../../../../../ExecutionContextProvider';
|
||||
import { FormBlockProvider } from '../../../common/Pd.FormBlock';
|
||||
import { FormBlockProvider } from '../../../common/FormBlock.provider';
|
||||
import { NAMESPACE, useTranslation } from '../../../locale';
|
||||
import { ApprovalContext } from '../../approval-common/ApprovalData.provider';
|
||||
import { ContextWithActionEnabled } from '../../approval-common/WithActionEnabled.provider';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useCollectionManager, useCollectionRecordData, useCompile } from '@tachybase/client';
|
||||
import { dayjs } from '@tachybase/utils/client';
|
||||
|
||||
import useStyles from './style';
|
||||
|
||||
@ -13,12 +14,19 @@ export const ApprovalsSummary = (props) => {
|
||||
const { collectionName } = record;
|
||||
const results = Object.entries(value).map(([key, objValue]) => {
|
||||
const field = cm.getCollectionField(`${collectionName}.${key}`);
|
||||
const realValue = Object.prototype.toString.call(objValue) === '[object Object]' ? objValue?.['name'] : objValue;
|
||||
// 如果是UTC时间字符串, 则转换为本地时区时间
|
||||
if (isUTCString(realValue)) {
|
||||
return {
|
||||
label: compile(field?.uiSchema?.title || key),
|
||||
value: Object.prototype.toString.call(objValue) === '[object Object]' ? objValue?.['name'] : objValue,
|
||||
value: convertUTCToLocal(realValue),
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: compile(field?.uiSchema?.title || key),
|
||||
value: realValue,
|
||||
};
|
||||
});
|
||||
|
||||
// 展示结果要展示一个数组对象, 是 label 和 value 的形式
|
||||
// label 放中文, value 放值
|
||||
return (
|
||||
@ -32,3 +40,19 @@ export const ApprovalsSummary = (props) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// TODO: 将下边的函数转移至 core 库中
|
||||
// 定义正则表达式, 检测形如 2024-07-04T04:46:27.166Z 的UTC时间字符串
|
||||
const utcRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
||||
|
||||
// 测试函数
|
||||
function isUTCString(str = '') {
|
||||
return utcRegex.test(str);
|
||||
}
|
||||
|
||||
// 将UTC时间字符串转换为本地时区时间
|
||||
function convertUTCToLocal(utcString) {
|
||||
// 使用dayjs解析UTC时间,并转换为本地时区时间
|
||||
const localDate = dayjs.utc(utcString).local().format('YYYY-MM-DD HH:mm:ss');
|
||||
return localDate;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
useRecord,
|
||||
} from '@tachybase/client';
|
||||
|
||||
import { CollectionApprovalTodos } from '../../common/Cn.ApprovalTodos';
|
||||
import { CollectionApprovalTodos } from '../../common/ApprovalTodos.collection';
|
||||
import { CollectionApprovals } from '../approval-common/Approvals.collection';
|
||||
import { CollectionFlowNodes } from '../approval-common/FlowNodes.collection';
|
||||
import { CollectionWorkflows } from '../approval-common/Workflows.collection';
|
||||
|
@ -275,5 +275,6 @@
|
||||
"Workflow": "Workflow",
|
||||
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" only support \"application/json\", and no need to specify",
|
||||
"concat": "concat",
|
||||
"ms": "ms"
|
||||
"ms": "ms",
|
||||
"reSubmit": "reSubmit"
|
||||
}
|
||||
|
@ -355,5 +355,6 @@
|
||||
"Workflow": "工作流",
|
||||
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" 请求头仅支持 \"application/json\",无需填写",
|
||||
"concat": "连接",
|
||||
"ms": "毫秒"
|
||||
"ms": "毫秒",
|
||||
"reSubmit": "重新提交"
|
||||
}
|
||||
|
@ -38,7 +38,9 @@ export default class ApprovalTrigger extends Trigger {
|
||||
},
|
||||
transaction,
|
||||
});
|
||||
if (!workflow || !approval.changed('status') || approval.status !== APPROVAL_STATUS.SUBMITTED) {
|
||||
const isChangedStatus = approval.changed('status');
|
||||
const isAllowStatusList = [APPROVAL_STATUS.SUBMITTED, APPROVAL_STATUS.RESUBMIT].includes(approval.status);
|
||||
if (!workflow || !isChangedStatus || !isAllowStatusList) {
|
||||
return;
|
||||
}
|
||||
const [dataSourceName, collectionName] = parseCollectionName(approval.collectionName);
|
||||
|
@ -2,6 +2,7 @@ import actions, { utils } from '@tachybase/actions';
|
||||
import { parseCollectionName } from '@tachybase/data-source-manager';
|
||||
|
||||
import { EXECUTION_STATUS, JOB_STATUS, PluginWorkflow } from '../..';
|
||||
import { appends } from '../../../client/schemas/collection';
|
||||
import { APPROVAL_ACTION_STATUS, APPROVAL_STATUS } from './constants';
|
||||
import { getSummary } from './tools';
|
||||
import { getAssociationName, jsonParse } from './utils';
|
||||
@ -84,7 +85,7 @@ const approvals = {
|
||||
/** 以下为,处理子表单子表格等关联字段的更新逻辑 */
|
||||
const schemaOfForm = await context.db.getRepository('uiSchemas').getJsonSchema(schemaFormId);
|
||||
const itemsOfSchema = await jsonParse(`**["x-component-props".mode]`, schemaOfForm);
|
||||
const fieldAssociationName = itemsOfSchema
|
||||
const fieldAssociationName = (itemsOfSchema || [])
|
||||
.filter((item) => {
|
||||
return ['Nester', 'SubTable', 'PopoverNester'].includes(item?.['x-component-props']?.mode);
|
||||
})
|
||||
@ -113,6 +114,61 @@ const approvals = {
|
||||
});
|
||||
return actions.update(context, next);
|
||||
},
|
||||
|
||||
// NOTE: 和 create 逻辑雷同, 但是 因为原本的 create 并非纯操作, 因此拷贝一份以便方便改动
|
||||
async reSubmit(context, next) {
|
||||
const { status, collectionName, data, workflowId, collectionAppends } = context.action.params.values ?? {};
|
||||
const [dataSourceName, cName] = parseCollectionName(collectionName);
|
||||
const dataSource = context.app.dataSourceManager.dataSources.get(dataSourceName);
|
||||
if (!dataSource) {
|
||||
return context.throw(400, `Data source "${dataSourceName}" not found`);
|
||||
}
|
||||
const collection = dataSource.collectionManager.getCollection(cName);
|
||||
if (!collection) {
|
||||
return context.throw(400, `Collection "${cName}" not found`);
|
||||
}
|
||||
const workflow = await context.db.getRepository('workflows').findOne({
|
||||
filterByTk: workflowId,
|
||||
});
|
||||
if (!workflow?.enabled) {
|
||||
return context.throw(400, 'Current workflow not found or disabled, please refresh and try again');
|
||||
}
|
||||
const { repository, model } = collection;
|
||||
const values = await repository.create({
|
||||
values: {
|
||||
...data,
|
||||
createdBy: context.state.currentUser.id,
|
||||
updatedBy: context.state.currentUser.id,
|
||||
},
|
||||
context,
|
||||
});
|
||||
const instance = values.get();
|
||||
|
||||
// NOTE: 这里需要取出关联字段, 用于摘要的构造;
|
||||
// 有点奇怪的方式, 但是没想到更好的处理方式, 也许应该改造摘要的构造方式, 存储关联字段的id, 在前端请求具体数据.
|
||||
const valuesWithAppends = await repository.findOne({
|
||||
filterByTk: values.id,
|
||||
appends: [...collectionAppends],
|
||||
});
|
||||
const summary = getSummary({
|
||||
summaryConfig: workflow.config.summary,
|
||||
data: valuesWithAppends,
|
||||
});
|
||||
Object.keys(model.associations).forEach((key) => {
|
||||
delete instance[key];
|
||||
});
|
||||
context.action.mergeParams({
|
||||
values: {
|
||||
collectionName,
|
||||
data: instance,
|
||||
dataKey: values[collection.filterTargetKey],
|
||||
workflowKey: workflow.key,
|
||||
applicantRoleName: context.state.currentRole,
|
||||
summary,
|
||||
},
|
||||
});
|
||||
return actions.create(context, next);
|
||||
},
|
||||
async destroy(context, next) {
|
||||
const {
|
||||
filterByTk,
|
||||
|
@ -4,6 +4,7 @@ export const APPROVAL_STATUS = {
|
||||
SUBMITTED: 2,
|
||||
PROCESSING: 3,
|
||||
APPROVED: 4,
|
||||
RESUBMIT: 5,
|
||||
REJECTED: -1,
|
||||
};
|
||||
export const APPROVAL_ACTION_STATUS = {
|
||||
|
@ -10,9 +10,10 @@ export function getSummary(params: ParamsType): object {
|
||||
|
||||
const result = summaryConfig.reduce((summary, key) => {
|
||||
const value = _.get(data, key);
|
||||
const realValue = Object.prototype.toString.call(value) === '[object Object]' ? value?.['name'] : value;
|
||||
return {
|
||||
...summary,
|
||||
[key]: value,
|
||||
[key]: realValue,
|
||||
};
|
||||
}, {});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user