Skip to content

Commit e4cfb0c

Browse files
xlorneclaude
andcommitted
fix: 修复审批流程记录展示问题
- 修复Ant Design Timeline组件API兼容性问题,使用items属性替代子组件 - 利用history字段正确区分历史节点和未执行节点状态 - 优化UI样式:添加边框、修复关闭按钮显示、使用Ant Design图标 - 侧边栏标题改为"审批流程记录" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 715ad9e commit e4cfb0c

7 files changed

Lines changed: 168 additions & 119 deletions

File tree

flow-engine-framework/src/main/java/com/codingapi/flow/pojo/response/ProcessNode.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
@Data
1717
@NoArgsConstructor
1818
public class ProcessNode {
19+
20+
public final static int STATE_HISTORY = -1;
21+
public final static int STATE_CURRENT = 0;
22+
public final static int STATE_NEXT = 1;
23+
1924
/**
2025
* 节点名称
2126
*/
@@ -30,23 +35,30 @@ public class ProcessNode {
3035
private String nodeType;
3136

3237
/**
33-
* 是否历史记录
38+
* 记录状态
39+
* -1 为历史状态
40+
* 0 为当前状态
41+
* 1 为后续状态
3442
*/
35-
private boolean history;
43+
private int state;
3644

3745
/**
3846
* 节点审批人
3947
*/
4048
private List<FlowOperatorBody> operators;
4149

4250

51+
public boolean isHistory(){
52+
return this.state == STATE_HISTORY;
53+
}
54+
4355
public ProcessNode(FlowRecord flowRecord, Workflow workflow) {
4456
this.nodeId = flowRecord.getNodeId();
4557
IFlowNode flowNode = workflow.getFlowNode(this.nodeId);
4658
this.nodeName = flowNode.getName();
4759
this.nodeType = flowNode.getType();
4860
this.operators = new ArrayList<>();
49-
this.history = true;
61+
this.state = STATE_HISTORY;
5062
this.operators.add(new FlowOperatorBody(flowRecord));
5163
}
5264

@@ -56,7 +68,16 @@ public ProcessNode(IFlowNode flowNode, List<IFlowOperator> operators) {
5668
this.nodeName = flowNode.getName();
5769
this.nodeType = flowNode.getType();
5870
this.operators = operators.stream().map(FlowOperatorBody::new).toList();
59-
this.history = false;
71+
this.state = STATE_NEXT;
72+
}
73+
74+
75+
public boolean isFlowNode(IFlowNode currentNode) {
76+
return this.nodeId.equals(currentNode.getId());
77+
}
78+
79+
public void setCurrentState() {
80+
this.state = STATE_CURRENT;
6081
}
6182

6283

flow-engine-framework/src/main/java/com/codingapi/flow/service/impl/FlowProcessNodeService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ private void fetchNextNode(FlowSession flowSession, List<IFlowNode> nexNodes) {
122122
operators = operatorManager.getOperators();
123123
}
124124
ProcessNode processNode = new ProcessNode(flowNode,operators);
125+
if(processNode.isFlowNode(this.currentNode)){
126+
processNode.setCurrentState();
127+
}
125128
this.nodeList.add(processNode);
126129
List<IFlowNode> nextNodes = workflow.nextNodes(flowNode);
127130
this.fetchNextNode(flowSession.updateSession(flowNode), nextNodes);

frontend/packages/flow-design/src/components/flow-approval/components/flow-node-history.tsx

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React from "react";
22
import {useApprovalContext} from "@/components/flow-approval/hooks/use-approval-context";
33
import {ProcessNode} from "@/components/flow-approval/typings";
4-
import {Timeline, Tag, Badge, Empty, Typography, Space} from "antd";
5-
import {CheckCircleFilled, ClockCircleOutlined, LoadingOutlined} from "@ant-design/icons";
4+
import {Timeline, Tag, Empty, Typography} from "antd";
5+
import {CheckCircleFilled, ClockCircleOutlined, LoadingOutlined, SyncOutlined} from "@ant-design/icons";
66

7-
const {Text, Paragraph} = Typography;
7+
const {Text} = Typography;
88

99
export interface FlowNodeHistoryAction{
1010
refresh:()=>void;
@@ -16,9 +16,13 @@ interface FlowNodeHistoryProps{
1616

1717
// 获取节点状态
1818
const getNodeStatus = (node: ProcessNode): 'completed' | 'current' | 'pending' => {
19-
if (node.operators && node.operators.length > 0) {
19+
if (node.state===-1) {
2020
return 'completed';
2121
}
22+
// 非历史节点,检查是否有审批人
23+
if (node.state === 0) {
24+
return 'current';
25+
}
2226
return 'pending';
2327
};
2428

@@ -28,72 +32,24 @@ const getStatusConfig = (status: 'completed' | 'current' | 'pending') => {
2832
case 'completed':
2933
return {
3034
color: 'success',
31-
label: '通过',
35+
label: '已通过',
3236
icon: <CheckCircleFilled style={{color: '#52c41a', fontSize: 16}}/>
3337
};
3438
case 'current':
3539
return {
36-
color: 'error',
40+
color: 'processing',
3741
label: '待审批',
38-
icon: <LoadingOutlined style={{color: '#ff4d4f', fontSize: 16}}/>
42+
icon: <SyncOutlined spin style={{color: '#1890ff', fontSize: 16}}/>
3943
};
4044
case 'pending':
4145
return {
4246
color: 'default',
43-
label: '待处理',
47+
label: '未执行',
4448
icon: <ClockCircleOutlined style={{color: '#d9d9d9', fontSize: 16}}/>
4549
};
4650
}
4751
};
4852

49-
// 单个审批节点项组件
50-
const ApprovalNodeItem: React.FC<{node: ProcessNode}> = ({node}) => {
51-
const status = getNodeStatus(node);
52-
const firstOperator = node.operators?.[0];
53-
const statusConfig = getStatusConfig(status);
54-
55-
return (
56-
<Timeline.Item dot={statusConfig.icon}>
57-
<Space direction="vertical" size={8} style={{width: '100%'}}>
58-
<Space size={12}>
59-
<Text strong>{node.nodeName}</Text>
60-
<Tag color={statusConfig.color}>{statusConfig.label}</Tag>
61-
</Space>
62-
63-
{firstOperator && (
64-
<Text type="secondary">审批人: {firstOperator.flowOperator.name}</Text>
65-
)}
66-
67-
{firstOperator?.approveTime && (
68-
<Text type="secondary" style={{fontSize: 12}}>
69-
{new Date(firstOperator.approveTime).toLocaleString('zh-CN', {
70-
year: 'numeric',
71-
month: '2-digit',
72-
day: '2-digit',
73-
hour: '2-digit',
74-
minute: '2-digit',
75-
})}
76-
</Text>
77-
)}
78-
79-
{firstOperator?.advice && (
80-
<div style={{marginTop: 4}}>
81-
<Text type="secondary">审批意见</Text>
82-
<div style={{
83-
padding: 12,
84-
backgroundColor: '#fafafa',
85-
borderRadius: 4,
86-
marginTop: 6
87-
}}>
88-
<Text>{firstOperator.advice}</Text>
89-
</div>
90-
</div>
91-
)}
92-
</Space>
93-
</Timeline.Item>
94-
);
95-
};
96-
9753
export const FlowNodeHistory: React.FC<FlowNodeHistoryProps> = (props) => {
9854
const {context} = useApprovalContext();
9955
const [processNodes, setProcessNodes] = React.useState<ProcessNode[]>([]);
@@ -119,13 +75,56 @@ export const FlowNodeHistory: React.FC<FlowNodeHistoryProps> = (props) => {
11975
return (
12076
<>
12177
{processNodes.length > 0 ? (
122-
<Timeline>
123-
{processNodes.map(node => (
124-
<ApprovalNodeItem key={node.nodeId} node={node}/>
125-
))}
126-
</Timeline>
78+
<Timeline items={processNodes.map(node => ({
79+
icon: getStatusConfig(getNodeStatus(node)).icon,
80+
content: (
81+
<div style={{display: 'flex', flexDirection: 'column', gap: 4, width: '100%'}}>
82+
<div style={{display: 'flex', alignItems: 'center', gap: 8}}>
83+
<Text strong style={{fontSize: 14}}>{node.nodeName}</Text>
84+
<Tag color={getStatusConfig(getNodeStatus(node)).color} style={{margin: 0}}>
85+
{getStatusConfig(getNodeStatus(node)).label}
86+
</Tag>
87+
</div>
88+
{node.state===-1 && node.operators?.[0] && (
89+
<>
90+
<Text type="secondary" style={{fontSize: 12}}>
91+
审批人: {node.operators[0].flowOperator.name}
92+
</Text>
93+
{node.operators[0].approveTime > 0 && (
94+
<Text type="secondary" style={{fontSize: 12}}>
95+
{new Date(node.operators[0].approveTime).toLocaleString('zh-CN', {
96+
year: 'numeric',
97+
month: '2-digit',
98+
day: '2-digit',
99+
hour: '2-digit',
100+
minute: '2-digit',
101+
})}
102+
</Text>
103+
)}
104+
{node.operators[0].advice && (
105+
<div style={{
106+
padding: 8,
107+
backgroundColor: '#fafafa',
108+
borderRadius: 4,
109+
marginTop: 4
110+
}}>
111+
<Text type="secondary" style={{fontSize: 12}}>
112+
{node.operators[0].advice}
113+
</Text>
114+
</div>
115+
)}
116+
</>
117+
)}
118+
{node.state!==-1 && node.operators?.[0] && (
119+
<Text type="secondary" style={{fontSize: 12}}>
120+
待审批人: {node.operators[0].flowOperator.name}
121+
</Text>
122+
)}
123+
</div>
124+
)
125+
}))} />
127126
) : (
128-
<Empty description="暂无审批历史记录" />
127+
<Empty description="暂无审批流程记录" />
129128
)}
130129
</>
131130
)

frontend/packages/flow-design/src/components/flow-approval/index.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ import {ApprovalLayout} from "@/components/flow-approval/layout";
66

77
interface ApprovalPanelProps {
88
workflowCode?: string;
9-
recordId?:string;
9+
recordId?: string;
1010
onClose?: () => void;
1111
}
1212

1313
export const ApprovalPanel: React.FC<ApprovalPanelProps> = (props) => {
1414

15-
const [content,dispatch] = React.useState<FlowContent|undefined>(undefined);
15+
const [content, dispatch] = React.useState<FlowContent | undefined>(undefined);
1616

17-
React.useEffect(()=>{
18-
const id = props.recordId || props.workflowCode || '';
19-
detail(id).then(res=>{
20-
if(res.success){
17+
React.useEffect(() => {
18+
const id = props.recordId || props.workflowCode || '';
19+
detail(id).then(res => {
20+
if (res.success) {
2121
dispatch(res.data);
2222
}
2323
});
24-
},[]);
24+
}, []);
2525

2626
return (
27-
<>
27+
<div>
2828
{content && <ApprovalLayout content={content} onClose={props.onClose}/>}
29-
</>
29+
</div>
3030
)
3131
}
3232

@@ -41,6 +41,12 @@ export const ApprovalPanelDrawer: React.FC<ApprovalPanelDrawerProps> = (props) =
4141
<Drawer
4242
open={props.open}
4343
onClose={props.onClose}
44+
styles={{
45+
body: {
46+
padding: 0,
47+
margin: 0,
48+
}
49+
}}
4450
>
4551
<ApprovalPanel
4652
{...props}

frontend/packages/flow-design/src/components/flow-approval/layout/body.tsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ApprovalLayoutHeight,
1010
} from "@/components/flow-approval/typings";
1111
import {Layout, Card, Button, Typography, Flex} from "antd";
12+
import {LeftOutlined, RightOutlined} from "@ant-design/icons";
1213

1314
const {Sider, Content} = Layout;
1415
const {Title} = Typography;
@@ -24,14 +25,19 @@ export const Body = () => {
2425
return (
2526
<Layout style={{
2627
padding: `${ApprovalContentPaddingV}px ${ApprovalContentPaddingH}px`,
27-
backgroundColor: '#fff',
28+
backgroundColor: '#f5f5f5',
29+
width: '100%',
2830
height: `calc(100vh - ${ApprovalLayoutHeight}px)`,
2931
}}>
30-
<Content style={{overflow: 'auto'}}>
32+
<Content
33+
style={{
34+
overflow: 'auto',
35+
width: '100%',
36+
}}>
3137
<Card
3238
title={<Title level={4} style={{margin: 0}}>流程表单</Title>}
33-
bordered={true}
34-
style={{height: '100%'}}
39+
style={{height: '100%', borderRadius: 8}}
40+
styles={{body: {padding: 24}}}
3541
>
3642
<FormViewComponent
3743
onValuesChange={handleValuesChange}
@@ -47,23 +53,30 @@ export const Body = () => {
4753
onCollapse={setCollapsed}
4854
trigger={null}
4955
style={{
56+
marginLeft: "8px",
5057
backgroundColor: '#fff',
51-
borderLeft: '1px solid #f0f0f0',
58+
borderRadius: 8,
59+
overflow: 'hidden',
5260
}}
5361
>
5462
{!collapsed && (
5563
<Flex vertical style={{height: '100%'}}>
5664
<Flex
5765
justify="space-between"
5866
align="center"
59-
style={{padding: '16px 24px', borderBottom: '1px solid #f0f0f0'}}
67+
style={{
68+
padding: '16px 24px',
69+
borderBottom: '1px solid #f0f0f0',
70+
backgroundColor: '#fafafa'
71+
}}
6072
>
61-
<Title level={5} style={{margin: 0}}>审批节点历史记录</Title>
73+
<Title level={5} style={{margin: 0, fontSize: 15}}>流程记录</Title>
6274
<Button
6375
type="text"
6476
size="small"
65-
icon={<span></span>}
77+
icon={<LeftOutlined style={{fontSize: 12}}/>}
6678
onClick={() => setCollapsed(true)}
79+
style={{color: '#8c8c8c'}}
6780
/>
6881
</Flex>
6982
<div style={{padding: 16, flex: 1, overflow: 'auto'}}>
@@ -77,22 +90,24 @@ export const Body = () => {
7790
align="center"
7891
justify="center"
7992
gap={16}
80-
style={{height: '100%', padding: '12px 8px'}}
93+
style={{height: '100%', padding: '12px 8px', backgroundColor: '#fafafa'}}
8194
>
8295
<Button
8396
type="text"
8497
size="small"
85-
icon={<span></span>}
98+
icon={<RightOutlined style={{fontSize: 12}}/>}
8699
onClick={() => setCollapsed(false)}
100+
style={{color: '#8c8c8c'}}
87101
/>
88102
<div style={{
89103
writingMode: 'vertical-rl',
90104
textOrientation: 'mixed',
91105
letterSpacing: 4,
92106
fontSize: 14,
93-
fontWeight: 600,
107+
fontWeight: 500,
108+
color: '#595959',
94109
}}>
95-
审批历史
110+
流程记录
96111
</div>
97112
</Flex>
98113
)}

0 commit comments

Comments
 (0)