fix: 审批, 自动刷新机制和撤回后更改子表格关联字段 (#1260)

Reviewed-on: daoyoucloud/tachybase#1260
Co-authored-by: bai.zixv <bai.zixv@foxmail.com>
Co-committed-by: bai.zixv <bai.zixv@foxmail.com>
This commit is contained in:
bai.zixv 2024-07-02 17:54:18 +08:00 committed by sealday
parent a15f5aedf0
commit ef2e2c9beb
9 changed files with 108 additions and 34 deletions

View File

@ -0,0 +1,19 @@
import { useActionContext, useAPIClient, useTableBlockContext } from '@tachybase/client';
// NOTE: 用于处理关闭弹窗, 和刷新外边显示的表格
export function useHandleRefresh(delay = 500) {
const { service } = useTableBlockContext();
const { setVisible, setSubmitted } = useActionContext() as any;
const refreshTable = () => {
setVisible(false);
setSubmitted?.(true);
setTimeout(() => {
service.refresh();
}, delay);
};
return {
refreshTable,
};
}

View File

@ -22,11 +22,24 @@ export const ViewActionLaunch = ({ popoverComponent = 'Action.Drawer', popoverCo
drawer: {
type: 'void',
'x-component': popoverComponent,
'x-component-props': { className: 'nb-action-popup', ...popoverComponentProps },
'x-component-props': {
className: 'nb-action-popup',
...popoverComponentProps,
},
properties: {
content: Object.assign({ type: 'void' }, record.approvalId ? {} : { 'x-decorator': 'RecordDecorator' }, {
content: Object.assign(
{
type: 'void',
},
record.approvalId
? {}
: {
'x-decorator': 'RecordDecorator',
},
{
'x-component': 'ViewActionContent',
}),
},
),
},
},
},

View File

@ -58,8 +58,6 @@ export const ViewActionLaunchContent = () => {
) as any;
// @ts-ignore
const approvalData = data?.data;
const { approval, execution, ...approvalValue } = approvalData || {};
const { workflow } = approval || {};
if (loading) {
return <Spin />;
@ -69,6 +67,9 @@ export const ViewActionLaunchContent = () => {
return <Result status="error" title="Loading failed" />;
}
const { approval, execution, ...approvalValue } = approvalData || {};
const { workflow } = approval || {};
return (
<FlowContextProvider
value={{

View File

@ -1,27 +1,30 @@
import { useActionContext, useAPIClient } from '@tachybase/client';
import { useAPIClient } from '@tachybase/client';
import { useField } from '@tachybase/schema';
import _ from 'lodash';
import { useApproval } from '../../../approval-common/ApprovalData.provider';
import { useHandleRefresh } from '../../common/useHandleRefresh';
export function useDestroyAction() {
const { refreshTable } = useHandleRefresh();
const field = useField();
const { setVisible, setSubmitted } = useActionContext() as any;
const approval = useApproval();
const apiClient = useAPIClient();
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({
filterByTk: approval.id,
});
setSubmitted(true);
setVisible(false);
refreshTable();
} catch (err) {
_.set(field, ['data', 'loading'], false);
}

View File

@ -1,40 +1,43 @@
import { useActionContext, useAPIClient } from '@tachybase/client';
import { useAPIClient } from '@tachybase/client';
import { useField, useForm } from '@tachybase/schema';
import _ from 'lodash';
import { useFlowContext } from '../../../../../../FlowContext';
import { useApproval } from '../../../approval-common/ApprovalData.provider';
import { useHandleRefresh } from '../../common/useHandleRefresh';
import { useContextApprovalStatus } from '../Pd.ApplyActionStatus';
export function useSubmit() {
const from = useForm();
const { refreshTable } = useHandleRefresh();
const apiClient = useAPIClient();
const form = useForm();
const field = useField();
const { setVisible, setSubmitted } = useActionContext() as any;
const { id } = useApproval();
const { workflow } = useFlowContext();
const contextApprovalStatus = useContextApprovalStatus();
const apiClient = useAPIClient();
return {
async run() {
try {
from.submit();
form.submit();
_.set(field, ['data', 'loading'], true);
apiClient.resource('approvals').update({
filterByTk: id,
values: {
collectionName: workflow.config.collection,
data: from.values,
data: form.values,
status: contextApprovalStatus,
schemaFormId: workflow.config.applyForm,
},
});
setSubmitted(true);
setVisible(false);
from.reset();
form.reset();
_.set(field, ['data', 'loading'], false);
refreshTable();
} catch (m) {
_.set(field, ['data', 'loading'], false);
}

View File

@ -1,30 +1,33 @@
import { useActionContext, useAPIClient } from '@tachybase/client';
import { useActionContext, useAPIClient, useTableBlockContext } from '@tachybase/client';
import { useField } from '@tachybase/schema';
import { useApproval } from '../../../approval-common/ApprovalData.provider';
import { useHandleRefresh } from '../../common/useHandleRefresh';
// 撤回
export function useWithdrawAction() {
const { refreshTable } = useHandleRefresh(100);
const field = useField();
const { setVisible, setSubmitted } = useActionContext() as any;
const approval = useApproval();
const api = useAPIClient();
return {
async run() {
try {
field.data = field.data ?? {};
field.data.loading = true;
await api.resource('approvals').withdraw({
filterByTk: approval.id,
});
setVisible(false);
setSubmitted(true);
// setSubmitted(true);
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;
}

View File

@ -1,36 +1,39 @@
import { useActionContext, useAPIClient, useRefreshActionProps } from '@tachybase/client';
import { useAPIClient } 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() {
const { refreshTable } = useHandleRefresh();
const field = useField();
const api = useAPIClient();
const form = useForm();
const approvalExecutions = useContextApprovalExecutions();
const { status } = useContextApprovalAction();
const { setVisible, setSubmitted } = useActionContext() as any;
// TODO: 自动更新外层block, 提升交互体验
// const { onClick: refreshAction } = useRefreshActionProps();
return {
run: async () => {
try {
if (form.values.status) {
return;
}
await form.submit();
field.data = field.data ?? {};
field.data.loading = true;
setVisible(false);
await api.resource('approvalRecords').submit({
filterByTk: approvalExecutions.id,
values: { ...form.values, status },
});
field.data.loading = false;
await form.reset();
// refreshAction?.();
setSubmitted?.(true);
refreshTable();
} catch (error) {
console.error(error);
field.data && (field.data.loading = false);

View File

@ -4,6 +4,7 @@ import { parseCollectionName } from '@tachybase/data-source-manager';
import { EXECUTION_STATUS, JOB_STATUS, PluginWorkflow } from '../..';
import { APPROVAL_ACTION_STATUS, APPROVAL_STATUS } from './constants';
import { getSummary } from './tools';
import { getAssociationName, jsonParse } from './utils';
const workflows = {
async listApprovalFlows(context, next) {
@ -71,13 +72,27 @@ const approvals = {
return actions.create(context, next);
},
async update(context, next) {
const { collectionName, data, status } = context.action.params.values ?? {};
const { collectionName, data, status, schemaFormId } = context.action.params.values ?? {};
const [dataSourceName, cName] = parseCollectionName(collectionName);
const dataSource = context.app.dataSourceManager.dataSources.get(dataSourceName);
const collection = dataSource.collectionManager.getCollection(cName);
/** 以下为,处理子表单子表格等关联字段的更新逻辑 */
const schemaOfForm = await context.db.getRepository('uiSchemas').getJsonSchema(schemaFormId);
const itemsOfSchema = await jsonParse(`**["x-component-props".mode]`, schemaOfForm);
const fieldAssociationName = itemsOfSchema
.filter((item) => {
return ['Nester', 'SubTable', 'PopoverNester'].includes(item?.['x-component-props']?.mode);
})
.map((item) => getAssociationName(item['x-collection-field']));
const updateAssociationValues = [...new Set(fieldAssociationName)];
/** 以上为,处理子表单子表格等关联字段的更新逻辑 */
const [target] = await collection.repository.update({
filterByTk: data[collection.filterTargetKey],
values: data,
updateAssociationValues,
});
context.action.mergeParams({
values: {

View File

@ -0,0 +1,14 @@
import jsonata from 'jsonata';
export function getAssociationName(str) {
const lastIndex = str.lastIndexOf('.');
if (lastIndex !== -1) {
return str.substring(lastIndex + 1);
}
return str;
}
export function jsonParse(expression, scope) {
const result = jsonata(expression).evaluate(scope);
return result;
}