Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
oa_process_monitor
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
David Yang
oa_process_monitor
Commits
e7319334
Commit
e7319334
authored
Sep 03, 2026
by
Andy-bubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: open process instance details as page
parent
c8685ec9
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
10 additions
and
29 deletions
+10
-29
ProcessInstanceDetailContent.jsx
src/components/ProcessInstanceDetailContent.jsx
+1
-1
ProcessDetail.jsx
src/pages/process_monitor/ProcessDetail.jsx
+1
-2
ProcessTemplateList.jsx
src/pages/process_monitor/ProcessTemplateList.jsx
+7
-25
process-monitor.business-flow.md
src/pages/process_monitor/process-monitor.business-flow.md
+1
-1
No files found.
src/components/ProcessInstanceDetailContent.jsx
View file @
e7319334
...
...
@@ -58,5 +58,5 @@ export default function ProcessInstanceDetailContent({ data, loading = false, wi
{
details
.
map
((
field
,
index
)
=>
<
DetailField
key=
{
`${field.label}-${index}`
}
label=
{
field
.
label
||
`字段 ${index + 1}`
}
fullWidth=
{
field
?.
type
===
'file'
||
String
(
field
?.
value
||
''
).
length
>
80
}
>
{
resolveDetailValue
(
field
,
fieldMap
,
lookups
)
}
</
DetailField
>)
}
</
div
>;
return
withSurface
?
<
Surface
className=
"px-5 py-5 sm:px-6 sm:py-6"
variant=
"secondary"
>
{
fieldGrid
}
</
Surface
>
:
fieldGrid
;
return
withSurface
?
<
Surface
className=
"
rounded-2xl
px-5 py-5 sm:px-6 sm:py-6"
variant=
"secondary"
>
{
fieldGrid
}
</
Surface
>
:
fieldGrid
;
}
src/pages/process_monitor/ProcessDetail.jsx
View file @
e7319334
...
...
@@ -2,7 +2,6 @@ import {
loadProcessInstanceDetail
,
}
from
'@/pages/process_monitor/processMonitorService'
;
import
ProcessInstanceDetailContent
from
'@/components/ProcessInstanceDetailContent'
;
import
{
TitleInfo
}
from
'@/components/XinyuanUi'
;
import
{
Alert
}
from
'@heroui/react'
;
import
{
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useParams
}
from
'umi'
;
...
...
@@ -27,7 +26,7 @@ export default function ProcessDetailPage() {
return
(
<
div
className=
"rc-page-stack"
>
{
errorMessage
?
<
Alert
status=
"danger"
><
Alert
.
Indicator
/><
Alert
.
Content
><
Alert
.
Title
>
详情加载失败
</
Alert
.
Title
><
Alert
.
Description
>
{
errorMessage
}
</
Alert
.
Description
></
Alert
.
Content
></
Alert
>
:
null
}
<
div
className=
"rc-list-action-bar"
><
div
className=
"flex items-center gap-1.5"
><
h2
>
流程实例信息
</
h2
><
TitleInfo
label=
"流程实例信息"
content=
"展示该实例的流程信息和动态表单字段,附件保留独立下载入口。"
/></
div
></
div
>
<
div
className=
"rc-list-action-bar"
><
h2
>
流程实例信息
</
h2
></
div
>
<
ProcessInstanceDetailContent
data=
{
detailData
}
loading=
{
loading
}
withSurface
/>
</
div
>
...
...
src/pages/process_monitor/ProcessTemplateList.jsx
View file @
e7319334
import
{
Close
,
DataStore
,
Delete
,
Eye
,
FieldTime
,
FileText
,
Filter
,
FolderOpen
,
Search
}
from
'@/components/AppIcons'
;
import
ProcessInstanceDetailContent
from
'@/components/ProcessInstanceDetailContent'
;
import
{
TableActionButton
,
TableActionGroup
}
from
'@/components/TableActionButton'
;
import
{
TitleInfo
}
from
'@/components/XinyuanUi'
;
import
XinyuanAutocomplete
from
'@/components/XinyuanAutocomplete'
;
...
...
@@ -15,13 +14,12 @@ import {
findDetailField
,
formatDateTime
,
loadTemplateMonitorPage
,
loadProcessInstanceDetail
,
normalizeDisplayFieldDefinitions
,
queryProcessInstances
,
updateTemplateDisplayFields
,
}
from
'@/pages/process_monitor/processMonitorService'
;
import
{
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useParams
,
useSearchParams
}
from
'umi'
;
import
{
use
Navigate
,
use
Params
,
useSearchParams
}
from
'umi'
;
const
PAGE_SIZE
=
20
;
const
PAGE_SIZE_OPTIONS
=
[
20
,
50
,
100
];
...
...
@@ -96,6 +94,7 @@ function PagePagination({ page, pageSize, total, onPageChange, onPageSizeChange
export
default
function
ProcessTemplateListPage
()
{
const
{
processId
}
=
useParams
();
const
navigate
=
useNavigate
();
const
[
searchParams
]
=
useSearchParams
();
const
tabName
=
searchParams
.
get
(
'tab'
)
||
''
;
const
[
loading
,
setLoading
]
=
useState
(
true
);
...
...
@@ -114,10 +113,6 @@ export default function ProcessTemplateListPage() {
const
[
fieldDialogOpen
,
setFieldDialogOpen
]
=
useState
(
false
);
const
[
fieldDrafts
,
setFieldDrafts
]
=
useState
([]);
const
[
fieldSaving
,
setFieldSaving
]
=
useState
(
false
);
const
[
detailDialogOpen
,
setDetailDialogOpen
]
=
useState
(
false
);
const
[
detailLoading
,
setDetailLoading
]
=
useState
(
false
);
const
[
detailError
,
setDetailError
]
=
useState
(
''
);
const
[
detailRecord
,
setDetailRecord
]
=
useState
(
null
);
const
loadTemplateMeta
=
async
()
=>
{
const
result
=
await
loadTemplateMonitorPage
(
processId
);
...
...
@@ -139,24 +134,12 @@ export default function ProcessTemplateListPage() {
const
instanceColumns
=
useMemo
(()
=>
[
{
id
:
'title'
,
header
:
'表单名称'
,
isRowHeader
:
true
,
width
:
'1fr'
,
minWidth
:
220
,
allowsResizing
:
false
,
pinned
:
'start'
,
cell
:
(
record
)
=>
<
span
className=
"pm-data-grid-primary"
>
{
record
.
title
}
</
span
>
},
...
fieldsDefinition
.
map
((
field
)
=>
({
id
:
`
${
field
.
display_name
}
-
${
field
.
type
}
`
,
header
:
field
.
display_name
,
width
:
220
,
minWidth
:
180
,
allowsResizing
:
false
,
cell
:
(
record
)
=>
<
span
className=
"pm-data-grid-text"
>
{
renderFieldValue
(
field
,
record
,
lookups
)
}
</
span
>
})),
{
id
:
'actions'
,
header
:
'操作'
,
width
:
80
,
minWidth
:
80
,
maxWidth
:
80
,
allowsResizing
:
false
,
align
:
'start'
,
pinned
:
'end'
,
cell
:
(
record
)
=>
<
TableActionGroup
><
TableActionButton
icon=
{
Eye
}
label=
"查看"
onPress=
{
()
=>
openDetailDialog
(
record
)
}
/></
TableActionGroup
>
},
],
[
fieldsDefinition
,
lookups
]);
const
openDetailDialog
=
async
(
record
)
=>
{
{
id
:
'actions'
,
header
:
'操作'
,
width
:
80
,
minWidth
:
80
,
maxWidth
:
80
,
allowsResizing
:
false
,
align
:
'start'
,
pinned
:
'end'
,
cell
:
(
record
)
=>
<
TableActionGroup
><
TableActionButton
icon=
{
Eye
}
label=
"查看"
onPress=
{
()
=>
{
if
(
!
record
?.
_id
)
return
;
setDetailDialogOpen
(
true
);
setDetailLoading
(
true
);
setDetailError
(
''
);
setDetailRecord
(
null
);
try
{
const
detail
=
await
loadProcessInstanceDetail
(
record
.
_id
);
setDetailRecord
(
detail
);
}
catch
(
error
)
{
setDetailError
(
error
?.
message
||
'加载流程详情失败'
);
}
finally
{
setDetailLoading
(
false
);
}
};
const
tabQuery
=
tabName
?
`?tab=${encodeURIComponent(tabName)}`
:
''
;
navigate
(
`/process_monitor/${processId}/${record._id}${tabQuery}`
);
}
}
/></
TableActionGroup
>
},
],
[
fieldsDefinition
,
lookups
,
navigate
,
processId
,
tabName
]);
const
openFieldDialog
=
()
=>
{
const
normalizedFields
=
normalizeDisplayFieldDefinitions
(
fieldsDefinition
);
...
...
@@ -197,7 +180,6 @@ export default function ProcessTemplateListPage() {
<
div
className=
"grid gap-3"
>
{
fieldDrafts
.
map
((
field
,
index
)
=>
<
div
key=
{
field
.
_key
}
className=
"grid gap-3 sm:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_2rem] sm:items-end"
><
div
className=
"grid gap-1.5"
><
Label
>
字段名
</
Label
><
Input
aria
-
label=
{
`字段 ${index + 1} 名称`
}
fullWidth
variant=
"secondary"
value=
{
field
.
display_name
}
onChange=
{
(
event
)
=>
setFieldDrafts
((
current
)
=>
current
.
map
((
item
,
itemIndex
)
=>
itemIndex
===
index
?
{
...
item
,
display_name
:
event
.
target
.
value
}
:
item
))
}
placeholder=
"请输入字段名"
/></
div
><
div
className=
"grid gap-1.5"
><
Label
>
字段类型
</
Label
><
XinyuanAutocomplete
aria
-
label=
{
`字段 ${index + 1} 类型`
}
options=
{
FIELD_TYPE_OPTIONS
}
placeholder=
"请选择"
selectedKey=
{
field
.
type
}
onSelectionChange=
{
(
key
)
=>
setFieldDrafts
((
current
)
=>
current
.
map
((
item
,
itemIndex
)
=>
itemIndex
===
index
?
{
...
item
,
type
:
String
(
key
||
''
)
}
:
item
))
}
/></
div
><
Tooltip
delay=
{
0
}
><
Button
isIconOnly
aria
-
label=
{
`删除字段 ${index + 1}`
}
size=
"sm"
variant=
"danger-soft"
onPress=
{
()
=>
setFieldDrafts
((
current
)
=>
current
.
filter
((
_
,
itemIndex
)
=>
itemIndex
!==
index
))
}
><
Delete
size=
{
16
}
/></
Button
><
Tooltip
.
Content
>
删除字段
</
Tooltip
.
Content
></
Tooltip
></
div
>)
}{
!
fieldDrafts
.
length
?
<
div
className=
"py-6 text-center text-sm text-muted"
>
暂未添加显示字段
</
div
>
:
null
}
<
Button
fullWidth
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
setFieldDrafts
((
current
)
=>
[...
current
,
createFieldDraft
()])
}
>
添加字段
</
Button
></
div
>
</
Modal
.
Body
><
Modal
.
Footer
><
Button
isDisabled=
{
fieldSaving
}
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
setFieldDialogOpen
(
false
)
}
>
取消
</
Button
><
Button
isPending=
{
fieldSaving
}
size=
"sm"
variant=
"primary"
onPress=
{
saveFieldDefinitions
}
>
保存字段
</
Button
></
Modal
.
Footer
></
Modal
.
Dialog
></
Modal
.
Container
></
Modal
.
Backdrop
></
Modal
.
Root
>
<
Modal
.
Root
><
Modal
.
Trigger
aria
-
hidden=
"true"
className=
"sr-only"
tabIndex=
{
-
1
}
/><
Modal
.
Backdrop
isOpen=
{
detailDialogOpen
}
onOpenChange=
{
setDetailDialogOpen
}
variant=
"blur"
><
Modal
.
Container
placement=
"center"
scroll=
"inside"
size=
"lg"
><
Modal
.
Dialog
aria
-
label=
"流程实例详情"
className=
"p-7 sm:max-w-[68rem]"
><
Modal
.
CloseTrigger
aria
-
label=
"关闭"
><
Close
size=
{
16
}
/></
Modal
.
CloseTrigger
><
Modal
.
Header
><
Modal
.
Heading
>
流程实例详情
</
Modal
.
Heading
></
Modal
.
Header
><
Modal
.
Body
>
{
detailError
?
<
Alert
status=
"danger"
><
Alert
.
Indicator
/><
Alert
.
Content
><
Alert
.
Title
>
详情加载失败
</
Alert
.
Title
><
Alert
.
Description
>
{
detailError
}
</
Alert
.
Description
></
Alert
.
Content
></
Alert
>
:
null
}
<
ProcessInstanceDetailContent
data=
{
detailRecord
}
loading=
{
detailLoading
}
/></
Modal
.
Body
><
Modal
.
Footer
><
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
setDetailDialogOpen
(
false
)
}
>
关闭
</
Button
></
Modal
.
Footer
></
Modal
.
Dialog
></
Modal
.
Container
></
Modal
.
Backdrop
></
Modal
.
Root
>
</
div
>
);
}
src/pages/process_monitor/process-monitor.business-flow.md
View file @
e7319334
...
...
@@ -133,7 +133,7 @@ Shell 中的应用切换入口继续读取当前登录用户可访问应用,
列表交互:
-
使用 HeroUI Pro DataGrid 生成动态列并承载选择状态
-
表单名称列仅展示文本,通过操作列的“查看”图标
在当前列表页打开单条流程实例详情 Modal;详情路由仍保留用于直接访问和兼容既有链接
-
表单名称列仅展示文本,通过操作列的“查看”图标
进入
`/process_monitor/:processId/:application`
独立流程实例详情页;顶部 Navbar 面包屑显示“流程监控 / 实例列表 / 流程详情”,前级节点可点击返回
-
Pagination 保留原有页码语义和
`page`
/
`page_size`
请求参数,条数选择器支持 20/50/100 条,宽度为 128px
-
有选中记录时由 HeroUI Pro ActionBar 承载批量附件下载;空数据使用 HeroUI Pro EmptyState
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment