Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
I
integrity_risk_prevention
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
integrity_risk_prevention
Commits
c1d89af9
Commit
c1d89af9
authored
Aug 05, 2026
by
David Yang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 对齐廉洁风险详情弹窗交互
parent
6c54c130
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
81 additions
and
61 deletions
+81
-61
RiskDataWorkspace.jsx
src/pages/integrity_risk/RiskDataWorkspace.jsx
+80
-60
integrity-risk-prevention.business-flow.md
...integrity_risk/integrity-risk-prevention.business-flow.md
+1
-1
No files found.
src/pages/integrity_risk/RiskDataWorkspace.jsx
View file @
c1d89af9
...
...
@@ -40,7 +40,6 @@ import {
}
from
'@/catalyst-ui-kit/javascript/table'
;
import
{
Textarea
}
from
'@/catalyst-ui-kit/javascript/textarea'
;
import
{
UserContext
}
from
'@/wrapper/Auth'
;
import
*
as
Headless
from
'@headlessui/react'
;
import
{
ArchiveBoxArrowDownIcon
,
ArrowDownTrayIcon
,
...
...
@@ -345,9 +344,9 @@ function DynamicField({ field, value, onChange, disabled, error }) {
);
}
function
getD
rawerFieldGroups
(
field
s
,
view
)
{
function
getD
ialogColumnSections
(
column
s
,
view
)
{
const
groups
=
view
?.
settings
?.
groups
||
view
?.
groups
||
[];
if
(
!
Array
.
isArray
(
groups
)
||
groups
.
length
===
0
)
return
[];
if
(
!
Array
.
isArray
(
groups
)
||
groups
.
length
===
0
)
return
[
{
id
:
'base'
,
label
:
''
,
columns
}
];
const
groupByField
=
new
Map
();
groups
.
forEach
((
group
)
=>
{
...
...
@@ -361,21 +360,21 @@ function getDrawerFieldGroups(fields, view) {
});
const
renderedGroups
=
new
Set
();
const
rendered
Field
s
=
new
Set
();
const
rendered
Column
s
=
new
Set
();
const
sections
=
[];
fields
.
forEach
((
field
)
=>
{
const
name
=
get
FieldName
(
field
);
if
(
rendered
Field
s
.
has
(
name
))
return
;
columns
.
forEach
((
column
)
=>
{
const
name
=
get
ColumnFieldName
(
column
);
if
(
rendered
Column
s
.
has
(
name
))
return
;
const
group
=
groupByField
.
get
(
name
);
if
(
!
group
||
renderedGroups
.
has
(
group
.
id
))
{
sections
.
push
({
id
:
name
,
label
:
''
,
fields
:
[
field
]
});
rendered
Field
s
.
add
(
name
);
sections
.
push
({
id
:
column
.
field
,
label
:
''
,
columns
:
[
column
]
});
rendered
Column
s
.
add
(
name
);
return
;
}
const
group
Fields
=
fields
.
filter
((
item
)
=>
groupByField
.
get
(
get
FieldName
(
item
))?.
id
===
group
.
id
);
group
Fields
.
forEach
((
item
)
=>
renderedFields
.
add
(
get
FieldName
(
item
)));
const
group
Columns
=
columns
.
filter
((
item
)
=>
groupByField
.
get
(
getColumn
FieldName
(
item
))?.
id
===
group
.
id
);
group
Columns
.
forEach
((
item
)
=>
renderedColumns
.
add
(
getColumn
FieldName
(
item
)));
renderedGroups
.
add
(
group
.
id
);
sections
.
push
({
id
:
group
.
id
,
label
:
group
.
label
,
fields
:
groupField
s
});
sections
.
push
({
id
:
group
.
id
,
label
:
group
.
label
,
columns
:
groupColumn
s
});
});
return
sections
;
}
...
...
@@ -412,9 +411,9 @@ export function RiskRecordDialog({ open, onClose, config, subject, view, record,
},
[
subject
,
displayColumns
],
);
const
d
rawerFieldGroup
s
=
useMemo
(
()
=>
getD
rawerFieldGroups
(
field
s
,
view
),
[
field
s
,
view
],
const
d
ialogSection
s
=
useMemo
(
()
=>
getD
ialogColumnSections
(
displayColumn
s
,
view
),
[
displayColumn
s
,
view
],
);
useEffect
(()
=>
{
...
...
@@ -486,60 +485,85 @@ export function RiskRecordDialog({ open, onClose, config, subject, view, record,
);
};
const
renderDetailColumn
=
(
column
)
=>
{
const
field
=
column
.
fieldDef
;
return
(
<
Headless
.
Dialog
open=
{
open
}
onClose=
{
onClose
}
className=
"relative z-50"
>
<
Headless
.
DialogBackdrop
transition
className=
"fixed inset-0 bg-zinc-950/25 transition duration-150 data-closed:opacity-0"
/>
<
div
className=
"fixed inset-0 overflow-hidden"
>
<
div
className=
"absolute inset-0 overflow-hidden"
>
<
div
className=
"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-8 sm:pl-16"
>
<
Headless
.
DialogPanel
transition
className=
"pointer-events-auto flex h-full w-screen max-w-5xl flex-col bg-white shadow-2xl ring-1 ring-zinc-950/10 transition duration-150 data-closed:translate-x-full"
<
div
key=
{
column
.
field
}
className=
{
clsx
(
'grid gap-2 border-b border-zinc-100 pb-4 md:grid-cols-[180px_minmax(0,1fr)]'
,
[
'long_text'
,
'rich_text'
,
'textarea'
,
'json'
,
'object'
].
includes
(
getFieldType
(
field
))
&&
'md:col-span-2'
,
)
}
>
<
div
className=
"flex items-start justify-between gap-4 border-b border-zinc-200 px-5 py-4 sm:px-6"
>
<
div
>
<
Headless
.
DialogTitle
className=
"text-base font-semibold text-zinc-950"
>
{
record
?
'记录详情'
:
`新增${config.title}`
}
</
Headless
.
DialogTitle
>
<
p
className=
"mt-1 text-sm text-zinc-500"
>
{
editing
?
'业务字段将统一保存到 metadata 对象中。'
:
'查看完整字段信息。'
}
</
p
>
<
div
className=
"text-sm font-medium text-zinc-500"
>
{
getColumnLabel
(
column
,
subject
)
}
</
div
>
<
div
className=
"min-w-0 whitespace-pre-wrap break-words text-sm text-zinc-900"
>
{
formatCellValue
(
record
,
column
)
}
</
div
>
<
Button
plain
onClick=
{
onClose
}
aria
-
label=
"关闭详情"
title=
"关闭详情"
>
<
XMarkIcon
/>
</
Button
>
</
div
>
<
div
className=
"flex-1 overflow-y-auto px-5 py-5 sm:px-6"
>
{
fields
.
length
>
0
?
(
drawerFieldGroups
.
length
>
0
?
(
<
div
className=
"space-y-6"
>
{
drawerFieldGroups
.
map
((
section
)
=>
(
<
section
key=
{
section
.
id
}
className=
{
section
.
label
?
'border-t border-zinc-200 pt-5 first:border-t-0 first:pt-0'
:
''
}
>
);
};
const
renderSection
=
(
section
)
=>
(
<
section
key=
{
section
.
id
}
className=
{
section
.
label
?
'border-t border-zinc-200 pt-5 first:border-t-0 first:pt-0'
:
''
}
>
{
section
.
label
?
(
<
h3
className=
"mb-4 text-sm font-semibold text-zinc-900"
>
{
section
.
label
}
</
h3
>
)
:
null
}
{
editing
?
(
<
div
className=
"grid gap-x-6 gap-y-5 md:grid-cols-2"
>
{
section
.
fields
.
map
(
renderField
)
}
{
section
.
columns
.
map
((
column
)
=>
fields
.
find
((
field
)
=>
getFieldName
(
field
)
===
getColumnFieldName
(
column
)))
.
filter
(
Boolean
)
.
map
(
renderField
)
}
</
div
>
)
:
(
<
div
className=
"grid gap-x-6 gap-y-4 md:grid-cols-2"
>
{
section
.
columns
.
map
(
renderDetailColumn
)
}
</
div
>
)
}
</
section
>
))
}
);
const
handleClose
=
()
=>
{
if
(
!
saving
)
onClose
();
};
return
(
<
Dialog
open=
{
open
}
onClose=
{
handleClose
}
size=
"4xl"
>
<
div
className=
"flex items-start justify-between gap-4"
>
<
div
>
<
DialogTitle
>
{
record
?
'记录详情'
:
`新增${config.title}`
}
</
DialogTitle
>
<
DialogDescription
>
{
editing
?
'业务字段将统一保存到 metadata 对象中,保存成功后生效。'
:
'默认以只读方式查看记录字段;点击编辑后再修改。'
}
</
DialogDescription
>
</
div
>
)
:
(
<
div
className=
"grid gap-x-6 gap-y-5 md:grid-cols-2"
>
{
fields
.
map
(
renderField
)
}
<
button
type=
"button"
onClick=
{
handleClose
}
disabled=
{
saving
}
aria
-
label=
"关闭详情"
className=
"inline-flex size-10 shrink-0 items-center justify-center rounded-full border border-zinc-200 bg-white text-zinc-500 shadow-sm transition hover:border-zinc-300 hover:bg-zinc-50 hover:text-zinc-700 disabled:cursor-not-allowed disabled:opacity-50"
>
<
XMarkIcon
className=
"size-5"
/>
</
button
>
</
div
>
<
DialogBody
className=
"max-h-[70vh] overflow-y-auto pr-1"
>
{
displayColumns
.
length
>
0
?
(
<
div
className=
"space-y-6"
>
{
dialogSections
.
map
(
renderSection
)
}
</
div
>
)
)
:
(
<
div
className=
"rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800"
>
当前 Subject 未返回可编辑
字段,请检查线上字段配置。
当前 Subject 未返回可显示
字段,请检查线上字段配置。
</
div
>
)
}
</
div
>
<
div
className=
"flex flex-col-reverse gap-3 border-t border-zinc-200 px-5 py-4 sm:flex-row sm:justify-end sm:px-6"
>
<
Button
plain
onClick=
{
onClose
}
>
关闭
</
Button
>
</
DialogBody
>
<
DialogActions
>
<
Button
plain
onClick=
{
handleClose
}
disabled=
{
saving
}
>
关闭
</
Button
>
{
record
&&
config
.
canEdit
&&
!
editing
?
(
<
Button
color=
"blue"
onClick=
{
()
=>
setEditing
(
true
)
}
>
<
PencilSquareIcon
/>
编辑
...
...
@@ -548,7 +572,7 @@ export function RiskRecordDialog({ open, onClose, config, subject, view, record,
{
editing
?
(
<>
{
record
?
(
<
Button
outline
onClick=
{
()
=>
{
<
Button
outline
disabled=
{
saving
}
onClick=
{
()
=>
{
setMetadata
(
buildInitialMetadata
(
subject
,
record
));
setErrors
({});
setEditing
(
false
);
...
...
@@ -562,12 +586,8 @@ export function RiskRecordDialog({ open, onClose, config, subject, view, record,
</
Button
>
</>
)
:
null
}
</
div
>
</
Headless
.
DialogPanel
>
</
div
>
</
div
>
</
div
>
</
Headless
.
Dialog
>
</
DialogActions
>
</
Dialog
>
);
}
...
...
src/pages/integrity_risk/integrity-risk-prevention.business-flow.md
View file @
c1d89af9
...
...
@@ -18,7 +18,7 @@
2.
关键词可搜索标题、廉洁风险点、主要防控措施或措施描述。
3.
分类、概率、危害程度、审批状态和类别筛选只在对应字段存在
`settings.options`
时展示,筛选值不在前端硬编码。
4.
桌面端使用 Catalyst
`Table`
,表头优先按视图
`settings.columns`
生成,并兼容
`settings.groups`
的两层分组表头;若视图配置
`settings.groupCols`
,当前页记录按配置字段分块展示。移动端使用同一列配置生成可点击记录列表;两端都支持当前页勾选。
5.
点击记录打开
Headless UI 右侧详情抽屉。详情字段优先沿用当前视图列顺序和分组配置,具备编辑权限的页面可切换到编辑态
。
5.
点击记录打开
Catalyst
`Dialog`
居中详情弹窗。详情字段优先沿用当前视图列顺序和分组配置,查看态只展示配置字段值;具备编辑权限的页面可切换到编辑态,编辑控件继续按 Subject 字段类型动态生成
。
6.
新增和编辑表单根据 Subject 字段类型动态生成;业务字段统一写入
`metadata`
。
7.
删除前必须二次确认,默认执行软删除。接口异常保留当前页面状态并显示可恢复的错误提示。
...
...
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