fix(department): 审批三期 (#1507)

Reviewed-on: daoyoucloud/tachybase#1507
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:
bai.zixv 2024-09-12 12:05:05 +08:00 committed by sealday
parent 7f4bfce63a
commit 5b5fa2d4ed
37 changed files with 277 additions and 69 deletions

View File

@ -66,7 +66,13 @@ const Cascade = connect((props) => {
resource
.list({
pageSize: 9999,
filter: { id: { $eq: propsValue.id } },
filter: propsValue.id
? {
id: {
$eq: propsValue.id,
},
}
: {},
sort,
tree: true,
})
@ -199,6 +205,7 @@ export const InternalCascader = observer(
(props: any) => {
const { options: collectionField } = useAssociationFieldContext();
const selectForm = useMemo(() => createForm(), []);
// @ts-ignore
const { t } = useTranslation();
const field: any = useField();
const fieldSchema = useFieldSchema();

View File

@ -9,7 +9,9 @@ import { UserMainDepartmentFieldSetting } from './settings/UserMainDepartmentFie
export class DepartmentsPlugin extends Plugin {
async afterAdd() {
// 用户和权限-部门
this.pm.add(KitMainTabDepartments);
// 用户和权限-角色和权限-部门
this.pm.add(KitRoleAuth);
}
async load() {
@ -24,3 +26,4 @@ export class DepartmentsPlugin extends Plugin {
this.app.schemaSettingsManager.add(DepartmentOwnersFieldSetting);
}
}

View File

@ -11,7 +11,12 @@ export const ProviderDepartmentIndex = ({ children }) => {
resource: 'users',
action: 'list',
params: {
appends: ['departments', 'departments.parent(recursively=true)'],
appends: [
'departments',
'departments.parent(recursively=true)',
'mainDepartment',
'mainDepartment.parent(recursively=true)',
],
filter: department
? {
'departments.id': department.id,

View File

@ -4,7 +4,10 @@ import { SchemaComponentContext, useSchemaComponentContext } from '@tachybase/cl
import { ViewDepartmentManagement } from './DepartmentManagement.view';
import { ProviderDepartmentIndex } from './DepartmentIndex.provider';
// TODO: 名称有待重新确认
/**
* TODO: 组件名称有待重新确认
* @returns
*/
export const DepartmentIndex = () => {
const context = useSchemaComponentContext();
return (

View File

@ -1,12 +1,12 @@
import React, { useContext } from 'react';
import React from 'react';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
import { useGetDepTree } from '../hooks/useGetDepTree';
import { InternalSuperiorDepartmentSelect } from './InternalSuperiorDepartmentSelect';
export const DepartmentSelect = () => {
const depTree = useGetDepTree();
const { departmentsResource } = useContext(ContextDepartments);
const { departmentsResource } = useContextDepartments();
const { service } = departmentsResource || {};
const { data } = service || {};

View File

@ -1,7 +1,7 @@
import React, { useContext, useEffect } from 'react';
import React, { useEffect } from 'react';
import { useRecord } from '@tachybase/client';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
import { useGetDepTree } from '../hooks/useGetDepTree';
import { InternalSuperiorDepartmentSelect } from './InternalSuperiorDepartmentSelect';
@ -9,7 +9,7 @@ export const SuperiorDepartmentSelect = () => {
const depTree = useGetDepTree();
const { setTreeData, getChildrenIds } = depTree;
const record = useRecord();
const { departmentsResource } = useContext(ContextDepartments);
const { departmentsResource } = useContextDepartments();
const {
service: { data },
} = departmentsResource || {};

View File

@ -20,7 +20,7 @@ interface contextType {
};
}
export const ContextDepartments = React.createContext<contextType>({
const ContextDepartments = React.createContext<contextType>({
user: {},
department: {},
});

View File

@ -6,6 +6,10 @@ import { Select } from 'antd';
import { ViewUnKnownOwerns } from './UnknownOwerns.view';
/**
* -
* @returns
*/
export const DepartmentOwnersField = () => {
const [visible, setVisible] = useState(false);
const record = useRecord();
@ -18,7 +22,7 @@ export const DepartmentOwnersField = () => {
};
const useSelectOwners = () => {
const { setVisible: setVisible } = useActionContext();
const { setVisible } = useActionContext();
return {
run() {
const fieldValue = field.value || [];

View File

@ -1,24 +1,25 @@
import React, { useContext, useState } from 'react';
import React, { useState } from 'react';
import { ActionContextProvider, RecordProvider, SchemaComponent, SchemaComponentOptions } from '@tachybase/client';
import { UserOutlined } from '@ant-design/icons';
import { Button, Divider, Row, theme } from 'antd';
import { useTranslation } from '../../../../locale';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
import { ProviderContextDepartmentsExpanded } from '../context/DepartmentsExpanded.context';
import { useGetDepTree } from '../hooks/useGetDepTree';
import { AddNewDepartment } from './AddNewDepartment.view';
import { DepartmentOwnersField } from './DepartmentOwnersField.component';
import { DepartmentsSearch } from './DepartmentsSearch.component';
import { DepartmentsTree } from './DepartmentsTree.component';
import { useCreateDepartment } from './useCreateDepartment';
import { useUpdateDepartment } from './useUpdateDepartment';
import { useCreateDepartment } from './scopes/useCreateDepartment';
import { useUpdateDepartment } from './scopes/useUpdateDepartment';
interface drawerState {
node?: object;
schema?: object;
}
// NOTE: 部门左边-部门列表部分
export const DepartmentsBlock = () => {
const { t } = useTranslation();
@ -26,10 +27,13 @@ export const DepartmentsBlock = () => {
const [visible, setVisible] = useState(false);
const [drawer, setDrawer] = useState<drawerState>({});
const { department, setDepartment } = useContext(ContextDepartments);
const { department, setDepartment } = useContextDepartments();
const { token } = theme.useToken();
const LabelComp = ({ node }) => <DepartmentsTree.Item node={node} setVisible={setVisible} setDrawer={setDrawer} />;
const value = useGetDepTree({
label: ({ node }) => <DepartmentsTree.Item node={node} setVisible={setVisible} setDrawer={setDrawer} />,
label: LabelComp,
});
const schema = drawer.schema || {};
@ -63,6 +67,7 @@ export const DepartmentsBlock = () => {
</Row>
<Divider style={{ margin: '12px 0' }} />
<DepartmentsTree />
{/* 操作浮层部分 */}
<ActionContextProvider
value={{
visible,

View File

@ -1,10 +1,10 @@
import React, { useContext, useState } from 'react';
import React, { useState } from 'react';
import { createStyles, useAPIClient, useRequest } from '@tachybase/client';
import { Button, Dropdown, Empty, Input, theme } from 'antd';
import { useTranslation } from '../../../../locale';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
const useStyles = createStyles(({ css }) => ({
searchDropdown: css`
@ -22,7 +22,7 @@ export const DepartmentsSearch = () => {
const limit = 10;
const api = useAPIClient();
const { setDepartment, setUser } = useContext(ContextDepartments);
const { setDepartment, setUser } = useContextDepartments();
const [open, setOpen] = useState(false);
const [keyword, setKeyword] = useState('');
const [users, setUsers] = useState([]);

View File

@ -1,27 +1,31 @@
import React, { useContext, useEffect } from 'react';
import React, { useEffect } from 'react';
import { css, useAPIClient, useResourceActionContext } from '@tachybase/client';
import { MoreOutlined } from '@ant-design/icons';
import { App, Dropdown, Empty, Tree } from 'antd';
import { useTranslation } from '../../../../locale';
import { schemaDepartmentEdit } from './DepartmentEdit.schema';
import { schemaDepartmentNewSub } from './DepartmentNewSub.schema';
import { ContextDepartments } from '../context/Department.context';
import { getUserListByDepartment } from '../../utils/getUserListByDepartment';
import { useContextDepartments } from '../context/Department.context';
import { useContextDepartmentsExpanded } from '../context/DepartmentsExpanded.context';
import { schemaDepartmentEdit } from './schemas/schemaDepartmentEdit';
import { schemaDepartmentNewSub } from './schemas/schemaDepartmentNewSub';
// 部门左边-部门列表
export const DepartmentsTree = () => {
const api = useAPIClient();
const { data, loading } = useResourceActionContext();
const { department, setDepartment, setUser } = useContext(ContextDepartments);
const { department, setDepartment, setUser } = useContextDepartments();
const { treeData, nodeMap, loadData, loadedKeys, setLoadedKeys, initData, expandedKeys, setExpandedKeys } =
useContextDepartmentsExpanded() as any;
const onSelect = (keys) => {
const onSelect = async (keys) => {
if (!keys.length) {
return;
}
const department = nodeMap[keys[0]];
const userList = await getUserListByDepartment(api, department.id);
setDepartment(department);
setUser(null);
};
@ -82,7 +86,7 @@ export const DepartmentsTree = () => {
);
};
DepartmentsTree.Item = ({ node, setVisible, setDrawer }) => {
const DepartmentsTreeItem = ({ node, setVisible, setDrawer }) => {
const { t } = useTranslation();
const { refreshAsync } = useResourceActionContext();
const { setLoadedKeys, expandedKeys, setExpandedKeys } = useContextDepartmentsExpanded();
@ -90,7 +94,7 @@ DepartmentsTree.Item = ({ node, setVisible, setDrawer }) => {
const API = useAPIClient();
const showModalDelete = () => {
modal.confirm({
title: t('Delete'),
title: t('Delete department'),
content: t('Are you sure you want to delete it?'),
onOk: async () => {
await API.resource('departments').destroy({ filterByTk: node.id });
@ -115,7 +119,7 @@ DepartmentsTree.Item = ({ node, setVisible, setDrawer }) => {
setVisible(true);
};
const onClick: any = ({ key, domeEvent }) => {
domeEvent.stopPropagation();
domeEvent?.stopPropagation();
switch (key) {
case 'new-sub':
setSchema(schemaDepartmentNewSub);
@ -162,3 +166,5 @@ DepartmentsTree.Item = ({ node, setVisible, setDrawer }) => {
</div>
);
};
DepartmentsTree.Item = DepartmentsTreeItem;

View File

@ -2,6 +2,9 @@ import { useEffect } from 'react';
import { useActionContext, useAPIClient, useRecord, useRequest } from '@tachybase/client';
import { uid } from '@tachybase/schema';
/**
*
*/
export const schemaDepartmentEdit = {
type: 'object',
properties: {

View File

@ -1,6 +1,9 @@
import { useActionContext, useRecord, useRequest } from '@tachybase/client';
import { uid } from '@tachybase/schema';
/**
*
*/
export const schemaDepartmentNewSub = {
type: 'object',
properties: {

View File

@ -1,7 +1,6 @@
import { useActionContext, useAPIClient, useResourceActionContext } from '@tachybase/client';
import { useField, useForm } from '@tachybase/schema';
import { useContextDepartmentsExpanded } from '../context/DepartmentsExpanded.context';
import { useContextDepartmentsExpanded } from '../../context/DepartmentsExpanded.context';
export const useCreateDepartment = () => {
const form = useForm();

View File

@ -1,8 +1,8 @@
import { useActionContext, useAPIClient, useRecord, useResourceActionContext } from '@tachybase/client';
import { useField, useForm } from '@tachybase/schema';
import { useContextDepartments } from '../context/Department.context';
import { useContextDepartmentsExpanded } from '../context/DepartmentsExpanded.context';
import { useContextDepartments } from '../../context/Department.context';
import { useContextDepartmentsExpanded } from '../../context/DepartmentsExpanded.context';
export const useUpdateDepartment = () => {
const field = useField();

View File

@ -1,12 +1,12 @@
import React, { useContext } from 'react';
import React from 'react';
import { EllipsisWithTooltip } from '@tachybase/client';
import { useField } from '@tachybase/schema';
import { getDepartmentStr } from '../../utils/getDepartmentStr';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
export const DepartmentField = () => {
const { setDepartment } = useContext(ContextDepartments);
const { setDepartment } = useContextDepartments();
const field = useField<{ value: Array<any> }>();
const fieldValues = field.value || [];

View File

@ -1,5 +1,7 @@
import { uid } from '@tachybase/schema';
import { tval } from '../../../../locale';
export const getSchemaDepartmentsUsersBlock = (department, user) => {
const schemaNotUser = user
? {}
@ -38,7 +40,7 @@ export const getSchemaDepartmentsUsersBlock = (department, user) => {
'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
'x-component-props': { style: { minWidth: 100 } },
title: '{{t("Owner")}}',
title: tval('Owner'),
properties: {
isOwner: {
type: 'boolean',
@ -105,7 +107,23 @@ export const getSchemaDepartmentsUsersBlock = (department, user) => {
'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
departments: { type: 'string', 'x-component': 'CollectionField', 'x-read-pretty': true },
departments: {
type: 'string',
'x-component': 'CollectionField',
'x-read-pretty': true,
},
},
},
mainDepartment: {
type: 'void',
'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
mainDepartment: {
type: 'string',
'x-component': 'CollectionField',
'x-read-pretty': true,
},
},
},
...tableSchemaDepartMent,

View File

@ -1,9 +1,9 @@
import React, { useContext, useEffect, useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import { SchemaComponent, useResourceActionContext } from '@tachybase/client';
import { useTranslation } from '../../../../locale';
import { useDepartmentFilterActionProps } from '../../common/scopes/useDepartmentFilterActionProps';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
import { ViewAddMembers } from './AddMembers.view';
import { DepartmentField } from './DepartmentField.component';
import { getSchemaDepartmentsUsersBlock } from './DepartmentsUsersBlock.schema';
@ -18,7 +18,7 @@ import { UserDepartmentsField } from './UserDepartmentsField.component';
// 部门右边-用户列表部分
export const ViewDepartmentsUsersBlock = () => {
const { t } = useTranslation();
const { department, user } = useContext(ContextDepartments);
const { department, user } = useContextDepartments();
const { data, setState } = useResourceActionContext();
const MemberActions = () => <ViewMemberActions department={department} />;

View File

@ -1,17 +1,19 @@
import React from 'react';
import { SchemaComponent } from '@tachybase/client';
import { useTranslation } from '../../../../locale';
import { schemaRowRemoveAction as schema } from './RowRemoveAction.schema';
import { useRemoveMemberAction } from './scopes/useRemoveMemberAction';
export const ViewRowRemoveAction = (props) => {
const { t } = useTranslation();
const { department } = props;
return department ? (
<SchemaComponent
schema={schema}
scope={{
useRemoveMemberAction: useRemoveMemberAction,
t,
useRemoveMemberAction,
}}
/>
) : null;

View File

@ -13,7 +13,7 @@ import { App, Button, Dropdown, Tag } from 'antd';
import { useTranslation } from '../../../../locale';
import { getDepartmentStr } from '../../utils/getDepartmentStr';
import { ViewUnknownUserDepartment } from './UnknownUserDepartment.view';
import { ViewUserSelectDepartment } from './UserSelectDepartment.view';
export const UserDepartmentsField = () => {
const { modal, message } = App.useApp();
@ -112,23 +112,25 @@ export const UserDepartmentsField = () => {
refresh();
};
const C = (l, u) => {
switch (l) {
const setFunc = (key, val) => {
switch (key) {
case 'setMain':
setMain(u);
setMain(val);
break;
case 'setOwner':
setOwner(u);
setOwner(val);
break;
case 'removeOwner':
removeOwner(u);
removeOwner(val);
break;
case 'remove':
showModalRemove(u);
showModalRemove(val);
}
};
const useDisabled = () => ({ disabled: (l) => field.value.some((u) => u.id === l.id) });
const useDisabled = () => ({
disabled: (target) => target && field.value.some((value) => value.id === target.id),
});
return (
<ActionContextProvider value={{ visible: visible, setVisible: setVisible }}>
<Fragment>
@ -146,10 +148,20 @@ export const UserDepartmentsField = () => {
<Dropdown
menu={{
items: [
...(val.isMain ? [] : [{ label: t('Set as main department'), key: 'setMain' }]),
{ label: t('Remove'), key: 'remove' },
...(val.isMain
? []
: [
{
key: 'setMain',
label: t('Set as main department'),
},
]),
{
key: 'remove',
label: t('Remove'),
},
],
onClick: ({ key }) => C(key, val),
onClick: ({ key }) => setFunc(key, val),
}}
>
<div style={{ float: 'right' }}>
@ -159,9 +171,9 @@ export const UserDepartmentsField = () => {
</Dropdown>
</Tag>
))}
<Button key={1} icon={<PlusOutlined />} onClick={() => setVisible(true)} />,
<Button key={1} icon={<PlusOutlined />} onClick={() => setVisible(true)} />
</Fragment>
<ViewUnknownUserDepartment user={user} useAddDepartments={useAddDepartments} useDisabled={useDisabled} />
<ViewUserSelectDepartment user={user} useAddDepartments={useAddDepartments} useDisabled={useDisabled} />
</ActionContextProvider>
);
};

View File

@ -1,12 +1,13 @@
import React from 'react';
import { SchemaComponent } from '@tachybase/client';
import { useTranslation } from '../../../../locale';
import { ViewDepartmentTable } from '../../common/DepartmentTable.view';
import { useDataSource } from './scopes/useDataSource';
import { schemaUnknownUserDepartment as schema } from './UnknownUserDepartment.schema';
import { schemaUserSelectDepartment as schema } from './UserSelectDepartment.schema';
// TODO: 有待重新命名组件
export const ViewUnknownUserDepartment = (props) => {
export const ViewUserSelectDepartment = (props) => {
const { t } = useTranslation();
const { user, useAddDepartments, useDisabled } = props;
return (
<SchemaComponent
@ -16,6 +17,7 @@ export const ViewUnknownUserDepartment = (props) => {
DepartmentTable: ViewDepartmentTable,
}}
scope={{
t,
user,
useDataSource,
useAddDepartments,

View File

@ -1,10 +1,10 @@
import { useContext, useEffect } from 'react';
import { useEffect } from 'react';
import { useResourceActionContext } from '@tachybase/client';
import { ContextDepartments } from '../../context/Department.context';
import { useContextDepartments } from '../../context/Department.context';
export const useMembersDataSource = (props) => {
const { user } = useContext(ContextDepartments);
const { user } = useContextDepartments();
const ctx = useResourceActionContext();
useEffect(() => {
if (user) {

View File

@ -1,11 +1,11 @@
import React, { useContext } from 'react';
import React from 'react';
import { CollectionProvider_deprecated, ResourceActionContext } from '@tachybase/client';
import { collectionUsers } from '../collections/users.collection';
import { ContextDepartments } from '../context/Department.context';
import { useContextDepartments } from '../context/Department.context';
export const ProviderUserResource = ({ children }) => {
const { usersResource } = useContext(ContextDepartments);
const { usersResource } = useContextDepartments();
const { service } = usersResource || {};
return (

View File

@ -0,0 +1,15 @@
export const getUserListByDepartment = async (api, departmentId: string) => {
if (!departmentId) {
return [];
}
const APIResource = api.resource('users');
const { data } = await APIResource.list({
filter: { 'departments.id': departmentId },
appends: ['departments', 'departments.parent(recursively=true)'],
});
const userList = data.data;
return userList;
};

View File

@ -4,6 +4,7 @@
"Add departments": "Add departments",
"Add members": "Add members",
"All users": "All users",
"Are you sure you want to delete it?": "Are you sure you want to delete it?",
"Are you sure you want to remove it?": "Are you sure you want to remove it?",
"Are you sure you want to remove these departments?": "Are you sure you want to remove these departments?",
"Are you sure you want to remove these members?": "Are you sure you want to remove these members?",
@ -55,6 +56,7 @@
"Roles management": "Roles management",
"Search for departments, users": "Search for departments, users",
"Search results": "Search results",
"Select Departments": "Select Departments",
"Select submit data type": "Select submit data type",
"Set as main department": "Set as main department",
"Signature input": "Signature input",

View File

@ -4,6 +4,7 @@
"Add departments": "添加部门",
"Add members": "添加成员",
"All users": "所有用户",
"Are you sure you want to delete it?": "你确定要删除吗?",
"Are you sure you want to remove it?": "你确定要移除吗?",
"Are you sure you want to remove these departments?": "你确定要移除这些部门吗?",
"Are you sure you want to remove these members?": "你确定要移除这些成员吗?",
@ -56,6 +57,7 @@
"Roles management": "角色管理",
"Search for departments, users": "搜索部门、用户",
"Search results": "搜索结果",
"Select Departments": "选择部门",
"Select actions": "选择操作",
"Select submit data type": "增量提交",
"Set as main department": "设置为主属部门",

View File

@ -8,6 +8,7 @@ import { useWorkflowAnyExecuted } from '../../../../hooks';
import { Instruction } from '../../../../nodes';
import { APPROVAL_ACTION_STATUS } from '../../constants';
import { NAMESPACE } from '../../locale';
import { ViewSkipApproval } from './approval-config/SkipApproval.view';
import { AssigneesAddition } from './approval-config/VC.AssigneesAddition';
import { AssigneesSelect } from './approval-config/VC.AssigneesSelect';
import { ContentTooltip } from './approval-config/VC.ContentTooltip';
@ -116,6 +117,64 @@ export class ApprovalInstruction extends Instruction {
},
},
},
skipArrpoval: {
type: 'array',
required: false,
title: `{{t("SkipArrpoval", { ns: "${NAMESPACE}" })}}`,
'x-decorator': 'FormItem',
'x-component': 'ArrayItems',
'x-component-props': {
className: css`
&[disabled] {
> .ant-formily-array-base-addition {
display: none;
}
> .ant-formily-array-items-item .ant-space-item:not(:nth-child(2)) {
display: none;
}
}
`,
},
items: {
type: 'void',
'x-component': 'Space',
'x-component-props': {
className: css`
width: 100%;
&.ant-space.ant-space-horizontal {
flex-wrap: nowrap;
}
> .ant-space-item:nth-child(2) {
flex-grow: 1;
}
`,
},
properties: {
sort: {
type: 'void',
'x-decorator': 'FormItem',
'x-component': 'ArrayItems.SortHandle',
},
input: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'ViewSkipApproval',
},
remove: {
type: 'void',
'x-decorator': 'FormItem',
'x-component': 'ArrayItems.Remove',
},
},
},
properties: {
add: {
type: 'void',
title: `{{t("Add Condition", { ns: "${NAMESPACE}" })}}`,
'x-component': 'AssigneesAddition',
},
},
},
negotiation: {
type: 'number',
title: `{{t("Negotiation mode", { ns: "${NAMESPACE}" })}}`,
@ -186,6 +245,7 @@ export class ApprovalInstruction extends Instruction {
NegotiationConfig,
RadioWithTooltip,
AssigneesAddition,
ViewSkipApproval,
};
isAvailable({ workflow, upstream, branchIndex }) {

View File

@ -0,0 +1,18 @@
import { FilterDynamicComponent } from '../../../../../components';
export const getSchemaSkipApproval = (params) => {
const { currentFormFields } = params;
return {
type: 'void',
properties: {
filter: {
type: 'object',
'x-component': 'Filter',
'x-component-props': {
options: currentFormFields,
dynamicComponent: FilterDynamicComponent,
},
},
},
};
};

View File

@ -0,0 +1,17 @@
import { default as React } from 'react';
import { SchemaComponent, useCollectionFilterOptions, useToken } from '@tachybase/client';
import { useField } from '@tachybase/schema';
import { getSchemaSkipApproval } from './SkipApproval.schema';
export const ViewSkipApproval = () => {
const field = useField();
const currentFormFields = useCollectionFilterOptions('users');
const { token } = useToken();
const schema = getSchemaSkipApproval({ currentFormFields });
return (
<div style={{ border: `1px dashed ${token.colorBorder}`, padding: token.paddingSM }}>
<SchemaComponent schema={schema} basePath={field.address} />
</div>
);
};

View File

@ -6,8 +6,11 @@ import { KitApprovalUsage } from './usage/plugin';
export class PluginApproval extends Plugin {
async afterAdd() {
// 审批配置
this.pm.add(KitApprovalConfiguration);
// 审批抄送
this.pm.add(KitCarbonCopy);
// 审批用户界面
this.pm.add(KitApprovalUsage);
}
async beforeLoad() {}

View File

@ -14,8 +14,8 @@ export class DataMappingInstruction extends Instruction {
fieldset = {
sourceArray: {
type: 'array',
title: tval('Data source array'),
description: tval('Data source array'),
title: tval('Data source map'),
description: tval('Data source map'),
'x-decorator': 'FormItem',
'x-component': 'ArrayTable',
items: {

View File

@ -44,6 +44,12 @@ export default class extends Instruction {
'x-content': `{{t("Allow multiple records as result", { ns: "${NAMESPACE}" })}}`,
description: `{{t("If checked, when there are multiple records in the query result, an array will be returned as the result, which can be operated on one by one using a loop node. Otherwise, only one record will be returned.", { ns: "${NAMESPACE}" })}}`,
},
isTree: {
type: 'boolean',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-content': `{{t("Allow query for tree data", { ns: "${NAMESPACE}" })}}`,
},
params: {
type: 'object',
'x-component': 'fieldset',

View File

@ -14,6 +14,7 @@
"Aggregator function": "Aggregator function",
"All pass": "All pass",
"All succeeded": "All succeeded",
"Allow query for tree data": "Allow query for tree data",
"An expression for calculation in each rows": "An expression for calculation in each rows",
"And": "And",
"Any pass": "Any pass",
@ -216,6 +217,7 @@
"Separately": "Separately",
"Sequentially": "Sequentially",
"Show Notice Detail": "Show Notice Detail",
"SkipArrpoval": "SkipArrpoval",
"Starts on": "Starts on",
"Status": "Status",
"String operation": "String operation",

View File

@ -22,6 +22,7 @@
"All pass": "全部通过",
"All succeeded": "全部成功",
"Allow multiple records as result": "允许结果是多条数据",
"Allow query for tree data": "添加查询条件为树结构表字段: tree: true",
"Allow the initiator to withdraw the approval before the approval starts.": "在审批开始之前,允许发起人撤回审批。",
"Allowed to be withdrawn": "允许撤回",
"And": "会签",
@ -273,6 +274,7 @@
"Separately": "分别处理",
"Sequentially": "顺序",
"Show Notice Detail": "显示通知详情",
"SkipArrpoval": "跳过当前审批",
"Some node meets error.": "某个节点出错。",
"Started and executing, maybe waiting for an async callback (manual, delay etc.).": "已开始执行,可能在等待异步回调(人工、延时等)。",
"Starts on": "开始于",

View File

@ -118,6 +118,7 @@ async function parseAssignees(node, processor) {
}
return [...assignees];
}
export default class ApprovalInstruction extends Instruction {
async run(node, prevJob, processor) {
const job = await processor.saveJob({

View File

@ -9,7 +9,13 @@ import { toJSON } from '../utils';
export class QueryInstruction extends Instruction {
async run(node: FlowNodeModel, input, processor: Processor) {
const { collection, multiple, params = {}, failOnEmpty = false } = node.config;
const { collection, multiple, isTree, params = {}, failOnEmpty = false } = node.config;
const otherOptions: any = {};
if (isTree) {
otherOptions.tree = true;
}
const [dataSourceName, collectionName] = parseCollectionName(collection);
@ -22,6 +28,7 @@ export class QueryInstruction extends Instruction {
sort = [],
...options
} = processor.getParsedValue(params, node.id);
const appends = options.appends
? Array.from(
options.appends.reduce((set, field) => {
@ -33,6 +40,7 @@ export class QueryInstruction extends Instruction {
: options.appends;
const result = await (multiple ? repository.find : repository.findOne).call(repository, {
...options,
...otherOptions,
...utils.pageArgsToLimitArgs(page, pageSize),
sort: sort
.filter((item) => item.field)