|
@@ -1,9 +1,23 @@
|
|
|
import React, { CSSProperties, useEffect, useMemo, useState } from 'react';
|
|
|
import { queryUserListByRoleID, queryLeader } from '@/services/boom';
|
|
|
import { connect } from 'umi';
|
|
|
-import { CheckOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
-import { Popover, Radio, RadioChangeEvent, Spin, Steps } from 'antd';
|
|
|
+import {
|
|
|
+ CheckOutlined,
|
|
|
+ PlusOutlined,
|
|
|
+ PlusSquareOutlined,
|
|
|
+} from '@ant-design/icons';
|
|
|
+import {
|
|
|
+ Popover,
|
|
|
+ Radio,
|
|
|
+ RadioChangeEvent,
|
|
|
+ Space,
|
|
|
+ Spin,
|
|
|
+ Steps,
|
|
|
+ Timeline,
|
|
|
+ Checkbox,
|
|
|
+} from 'antd';
|
|
|
import { useModel, useRequest } from '@umijs/max';
|
|
|
+import { CheckboxValueType } from 'antd/es/checkbox/Group';
|
|
|
|
|
|
const { Step } = Steps;
|
|
|
|
|
@@ -19,6 +33,7 @@ interface AuditNode {
|
|
|
type: (typeof TYPE)[keyof typeof TYPE];
|
|
|
value: number[];
|
|
|
checkValue: [];
|
|
|
+ label: string;
|
|
|
}
|
|
|
|
|
|
const ApprovalProcess = (props: any) => {
|
|
@@ -30,7 +45,7 @@ const ApprovalProcess = (props: any) => {
|
|
|
roleList = [],
|
|
|
} = props;
|
|
|
const { userList, run } = useModel('userList');
|
|
|
- const [checkValue, setCheckValue] = useState<number[]>([]);
|
|
|
+ const [checkValue, setCheckValue] = useState<number[][]>([]);
|
|
|
|
|
|
const { auditList, ccList } = useMemo<{
|
|
|
auditList: AuditNode[];
|
|
@@ -45,6 +60,7 @@ const ApprovalProcess = (props: any) => {
|
|
|
type: item[0].type,
|
|
|
checkValue: [],
|
|
|
seq: index,
|
|
|
+ label: item[0].label,
|
|
|
value: item.map((node: any) => node.value),
|
|
|
};
|
|
|
|
|
@@ -57,7 +73,7 @@ const ApprovalProcess = (props: any) => {
|
|
|
return { auditList, ccList };
|
|
|
}, [approvalProcess]);
|
|
|
|
|
|
- const onCheckValue = (value: number, index: number) => {
|
|
|
+ const onCheckValue = (value: number[], index: number) => {
|
|
|
let values = [...checkValue];
|
|
|
values[index] = value;
|
|
|
setCheckValue(values);
|
|
@@ -76,10 +92,10 @@ const ApprovalProcess = (props: any) => {
|
|
|
fontSize: 16,
|
|
|
};
|
|
|
|
|
|
- return (
|
|
|
- <div>
|
|
|
- <div style={rowStyle}>
|
|
|
- {auditList.map((item: AuditNode, index: number) => (
|
|
|
+ const renderAudits = (list: AuditNode[]) => {
|
|
|
+ return list.map((item: AuditNode, index: number) => {
|
|
|
+ return {
|
|
|
+ children: (
|
|
|
<AuditNodeStep
|
|
|
key={`${item.type}-${item.value.join('.')}-${index}`}
|
|
|
leaderData={leaderData}
|
|
@@ -87,26 +103,18 @@ const ApprovalProcess = (props: any) => {
|
|
|
roleList={roleList}
|
|
|
userList={userList}
|
|
|
value={checkValue[item.seq]}
|
|
|
- onChange={(value: number) => onCheckValue(value, item.seq)}
|
|
|
+ onChange={(value: number[]) => onCheckValue(value, item.seq)}
|
|
|
/>
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- {ccList.length > 0 && (
|
|
|
- <div style={rowStyle}>
|
|
|
- <h3 style={{ margin: "20px 0", fontWeight: 'bold' }}>抄送人</h3>
|
|
|
- {ccList.map((item: AuditNode, index: number) => (
|
|
|
- <AuditNodeStep
|
|
|
- key={`${item.type}-${item.value.join('.')}-${index}`}
|
|
|
- leaderData={leaderData}
|
|
|
- item={item}
|
|
|
- roleList={roleList}
|
|
|
- userList={userList}
|
|
|
- value={checkValue[item.seq]}
|
|
|
- onChange={(value: number) => onCheckValue(value, item.seq)}
|
|
|
- />
|
|
|
- ))}
|
|
|
- </div>
|
|
|
- )}
|
|
|
+ ),
|
|
|
+ };
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <Timeline items={renderAudits(auditList)}></Timeline>
|
|
|
+
|
|
|
+ {ccList.length > 0 && <Timeline items={renderAudits(ccList)}></Timeline>}
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
@@ -116,8 +124,8 @@ interface AuditNodeStepProps {
|
|
|
leaderData: any;
|
|
|
roleList: any;
|
|
|
userList: any;
|
|
|
- value: number;
|
|
|
- onChange: (value: number) => void;
|
|
|
+ value: number[];
|
|
|
+ onChange: (value: number[]) => void;
|
|
|
}
|
|
|
|
|
|
const AuditNodeStep = (props: AuditNodeStepProps) => {
|
|
@@ -152,19 +160,29 @@ const AuditNodeStep = (props: AuditNodeStepProps) => {
|
|
|
setLoading(false);
|
|
|
};
|
|
|
|
|
|
- const selectedUserId = ({ target: { value } }: RadioChangeEvent) => {
|
|
|
- onChange(Number(value));
|
|
|
+ const selectedUserId = (list: CheckboxValueType[]) => {
|
|
|
+ onChange(list as number[]);
|
|
|
};
|
|
|
|
|
|
const content = (
|
|
|
<Spin spinning={loading}>
|
|
|
- <Radio.Group onChange={selectedUserId} value={value}>
|
|
|
- {selectUserList.map((item: any) => (
|
|
|
- <Radio.Button value={Number(item.user_id)}>
|
|
|
- {item.c_name}
|
|
|
- </Radio.Button>
|
|
|
- ))}
|
|
|
- </Radio.Group>
|
|
|
+ <Checkbox.Group
|
|
|
+ style={{ display: 'block' }}
|
|
|
+ onChange={selectedUserId}
|
|
|
+ value={value as any}
|
|
|
+ >
|
|
|
+ {selectUserList
|
|
|
+ .filter((item: any) => item.c_name)
|
|
|
+ .map((item: any) => (
|
|
|
+ <Checkbox
|
|
|
+ style={{ whiteSpace: 'nowrap' }}
|
|
|
+ key={item.user_id}
|
|
|
+ value={Number(item.user_id)}
|
|
|
+ >
|
|
|
+ {item.c_name}
|
|
|
+ </Checkbox>
|
|
|
+ ))}
|
|
|
+ </Checkbox.Group>
|
|
|
</Spin>
|
|
|
);
|
|
|
|
|
@@ -184,18 +202,31 @@ const AuditNodeStep = (props: AuditNodeStepProps) => {
|
|
|
);
|
|
|
}
|
|
|
if (item.type == TYPE.ROLE) {
|
|
|
- let title = '';
|
|
|
- if (value) {
|
|
|
- title = userList.find((cur: any) => cur.ID == value)?.CName;
|
|
|
- } else {
|
|
|
- const names = item.value.map((id) => {
|
|
|
- const role = roleList.find((cur: any) => cur.ID == id);
|
|
|
- return role?.Name;
|
|
|
- });
|
|
|
- title = `从${names.join('、')}选择`;
|
|
|
+ let label = item.label || '';
|
|
|
+ const names = item.value.map((id) => {
|
|
|
+ const role = roleList.find((cur: any) => cur.ID == id);
|
|
|
+ return role?.Name;
|
|
|
+ });
|
|
|
+ let title = `从${names.join('、')}选择`;
|
|
|
+ let userNames = [];
|
|
|
+ if (value?.length > 0) {
|
|
|
+ userNames = value.map(
|
|
|
+ (id: number) => userList.find((cur: any) => cur.ID == id)?.CName,
|
|
|
+ );
|
|
|
}
|
|
|
return (
|
|
|
- <div style={{ marginBottom: 20, cursor: 'pointer' }}>
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ marginBottom: 20,
|
|
|
+ cursor: 'pointer',
|
|
|
+ display: 'flex',
|
|
|
+ justifyContent: 'space-between',
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div style={{ fontSize: '18px' }}>{label}</div>
|
|
|
+ <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
|
|
|
+ </div>
|
|
|
<Popover
|
|
|
placement="bottomLeft"
|
|
|
title={'选择审批人'}
|
|
@@ -203,21 +234,40 @@ const AuditNodeStep = (props: AuditNodeStepProps) => {
|
|
|
trigger="click"
|
|
|
overlayStyle={{ width: '300px' }}
|
|
|
onOpenChange={handleOpen}
|
|
|
- style={{ marginBottom: 20 }}
|
|
|
+ style={{ marginBottom: 20, overflow: 'auto' }}
|
|
|
>
|
|
|
- <PlusOutlined style={{ marginRight: 20 }} /> {title}
|
|
|
+ <Space>
|
|
|
+ {userNames.join('、')}
|
|
|
+ <PlusSquareOutlined style={{ fontSize: '36px', color: 'gray' }} />
|
|
|
+ </Space>
|
|
|
</Popover>
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ let label = item.label || '';
|
|
|
+
|
|
|
+ let title = item.is_cc
|
|
|
+ ? `抄送${item.value.length}人`
|
|
|
+ : `${item.value.length}人审批`;
|
|
|
const names = item.value.map((id) => {
|
|
|
const user = userList.find((cur: any) => cur.ID == id);
|
|
|
return user?.CName;
|
|
|
});
|
|
|
|
|
|
return (
|
|
|
- <div style={{ marginBottom: 20 }}>
|
|
|
- <CheckOutlined style={{ marginRight: 20 }} /> {names.join('、')}
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ marginBottom: 20,
|
|
|
+ display: 'flex',
|
|
|
+ justifyContent: 'space-between',
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div style={{ fontSize: '18px' }}>{label}</div>
|
|
|
+ <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
|
|
|
+ </div>
|
|
|
+ {names.join('、')}
|
|
|
</div>
|
|
|
);
|
|
|
};
|