Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
law_reference_new
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
law_reference_new
Commits
86bbaf04
Commit
86bbaf04
authored
Sep 30, 2026
by
drigle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: use modal confirmations and adjust filter tree defaults
parent
a288b353
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
67 additions
and
25 deletions
+67
-25
ConfiguredSpecialViews.jsx
src/pages/ConfiguredSpecialViews.jsx
+13
-3
LawRecordPage.jsx
src/pages/LawRecordPage.jsx
+52
-6
LawSubjectPage.jsx
src/pages/LawSubjectPage.jsx
+2
-16
law-reference.business-flow.md
src/pages/law-reference.business-flow.md
+0
-0
No files found.
src/pages/ConfiguredSpecialViews.jsx
View file @
86bbaf04
...
@@ -34,13 +34,23 @@ function useSubjectRecords(subjectName, groupName) {
...
@@ -34,13 +34,23 @@ function useSubjectRecords(subjectName, groupName) {
function
ProcessListView
({
subjectName
,
config
})
{
function
ProcessListView
({
subjectName
,
config
})
{
const
groupSubject
=
config
?.
group_subject
||
'process_flow_group'
;
const
groupSubject
=
config
?.
group_subject
||
'process_flow_group'
;
const
[
groups
,
setGroups
]
=
useState
([]);
const
[
active
,
setActive
]
=
useState
(
''
);
const
[
modal
,
setModal
]
=
useState
(
false
);
const
[
draft
,
setDraft
]
=
useState
({});
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
error
,
setError
]
=
useState
(
''
);
const
[
groups
,
setGroups
]
=
useState
([]);
const
[
active
,
setActive
]
=
useState
(
''
);
const
[
modal
,
setModal
]
=
useState
(
false
);
const
[
draft
,
setDraft
]
=
useState
({});
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
deleting
,
setDeleting
]
=
useState
(
false
);
const
[
deleteTarget
,
setDeleteTarget
]
=
useState
(
null
);
const
[
deleteError
,
setDeleteError
]
=
useState
(
''
);
const
[
error
,
setError
]
=
useState
(
''
);
const
{
group
,
items
,
loading
,
error
:
groupError
,
reload
}
=
useSubjectRecords
(
subjectName
,
active
);
const
{
group
,
items
,
loading
,
error
:
groupError
,
reload
}
=
useSubjectRecords
(
subjectName
,
active
);
const
loadGroups
=
async
()
=>
{
try
{
const
result
=
await
loadRecords
(
groupSubject
,
0
,
100
);
const
next
=
result
?.
records
||
[];
setGroups
(
next
);
setActive
((
current
)
=>
current
||
next
[
0
]?.
name
||
''
);
}
catch
(
requestError
)
{
setError
(
requestError
?.
message
||
'流程分组加载失败'
);
}
};
const
loadGroups
=
async
()
=>
{
try
{
const
result
=
await
loadRecords
(
groupSubject
,
0
,
100
);
const
next
=
result
?.
records
||
[];
setGroups
(
next
);
setActive
((
current
)
=>
current
||
next
[
0
]?.
name
||
''
);
}
catch
(
requestError
)
{
setError
(
requestError
?.
message
||
'流程分组加载失败'
);
}
};
useEffect
(()
=>
{
loadGroups
();
},
[
groupSubject
]);
useEffect
(()
=>
{
loadGroups
();
},
[
groupSubject
]);
const
save
=
async
()
=>
{
setSaving
(
true
);
setError
(
''
);
try
{
if
(
draft
.
group_name
!==
undefined
)
await
createRecord
({
subject
:
groupSubject
,
title
:
draft
.
group_name
,
metadata
:
{
group_name
:
draft
.
group_name
,
process_list
:
[]
}
});
else
if
(
draft
.
editName
)
await
updateRecord
(
draft
.
editName
,
{
title
:
draft
.
title
,
metadata
:
{
remark
:
draft
.
remark
,
source
:
draft
.
source
||
null
}
});
else
{
const
created
=
await
createRecord
({
subject
:
subjectName
,
title
:
draft
.
title
,
metadata
:
{
remark
:
draft
.
remark
,
source
:
draft
.
source
||
null
}
});
await
updateRecord
(
group
.
name
,
{
metadata
:
{
...
group
.
metadata
,
process_list
:
[...(
group
.
metadata
?.
process_list
||
[]).
map
(
valueOf
),
created
.
_id
]
}
});
}
setModal
(
false
);
setDraft
({});
await
loadGroups
();
await
reload
();
}
catch
(
requestError
)
{
setError
(
requestError
?.
message
||
'保存失败'
);
}
finally
{
setSaving
(
false
);
}
};
const
save
=
async
()
=>
{
setSaving
(
true
);
setError
(
''
);
try
{
if
(
draft
.
group_name
!==
undefined
)
await
createRecord
({
subject
:
groupSubject
,
title
:
draft
.
group_name
,
metadata
:
{
group_name
:
draft
.
group_name
,
process_list
:
[]
}
});
else
if
(
draft
.
editName
)
await
updateRecord
(
draft
.
editName
,
{
title
:
draft
.
title
,
metadata
:
{
remark
:
draft
.
remark
,
source
:
draft
.
source
||
null
}
});
else
{
const
created
=
await
createRecord
({
subject
:
subjectName
,
title
:
draft
.
title
,
metadata
:
{
remark
:
draft
.
remark
,
source
:
draft
.
source
||
null
}
});
await
updateRecord
(
group
.
name
,
{
metadata
:
{
...
group
.
metadata
,
process_list
:
[...(
group
.
metadata
?.
process_list
||
[]).
map
(
valueOf
),
created
.
_id
]
}
});
}
setModal
(
false
);
setDraft
({});
await
loadGroups
();
await
reload
();
}
catch
(
requestError
)
{
setError
(
requestError
?.
message
||
'保存失败'
);
}
finally
{
setSaving
(
false
);
}
};
const
deleteProcess
=
async
(
item
)
=>
{
if
(
!
group
||
!
window
.
confirm
(
'确定删除该流程吗?'
))
return
;
await
removeRecord
(
item
.
name
||
item
.
_id
);
await
updateRecord
(
group
.
name
,
{
metadata
:
{
...
group
.
metadata
,
process_list
:
(
group
.
metadata
?.
process_list
||
[]).
map
(
valueOf
).
filter
((
id
)
=>
id
!==
(
item
.
_id
||
item
.
name
))
}
});
await
reload
();
};
const
confirmDeleteProcess
=
async
()
=>
{
return
<
div
className=
"rc-page-stack"
><
h2
className=
"mb-4 text-xl font-semibold"
>
流程管理
</
h2
>
{
error
||
groupError
?
<
Alert
status=
"danger"
><
Alert
.
Content
><
Alert
.
Description
>
{
error
||
groupError
}
</
Alert
.
Description
></
Alert
.
Content
></
Alert
>
:
null
}
<
GroupTabs
groups=
{
groups
}
active=
{
active
}
onChange=
{
setActive
}
onCreate=
{
()
=>
{
setDraft
({
group_name
:
''
});
setModal
(
true
);
}
}
label=
"流程分组"
/><
Card
><
Card
.
Header
><
Card
.
Title
className=
"mr-auto"
>
{
group
?.
title
||
'请选择流程分组'
}
</
Card
.
Title
>
{
group
?
<
Button
variant=
"primary"
onPress=
{
()
=>
{
setDraft
({});
setModal
(
true
);
}
}
>
新增流程
</
Button
>
:
null
}
</
Card
.
Header
><
Card
.
Content
>
{
loading
?
<
div
className=
"flex min-h-32 items-center justify-center"
><
Spinner
/></
div
>
:
!
items
.
length
?
<
div
className=
"py-16 text-center text-sm text-muted"
>
暂无流程
</
div
>
:
<
ol
className=
"space-y-3"
>
{
items
.
map
((
item
,
index
)
=>
<
li
className=
"flex items-center gap-3 rounded-lg border border-default p-3"
key=
{
item
.
name
||
item
.
_id
}
><
span
className=
"grid h-8 w-8 place-items-center rounded-full bg-accent/10 text-sm font-semibold text-accent"
>
{
index
+
1
}
</
span
><
div
className=
"min-w-0 flex-1"
><
div
className=
"truncate font-medium"
>
{
item
.
title
||
item
.
name
}
</
div
><
div
className=
"text-sm text-muted"
>
{
item
.
metadata
?.
remark
||
'暂无说明'
}
</
div
></
div
><
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
{
setDraft
({
...
item
.
metadata
,
title
:
item
.
title
,
editName
:
item
.
name
});
setModal
(
true
);
}
}
>
编辑
</
Button
><
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
history
.
push
(
`/${subjectName}/${item.name || item._id}`
)
}
>
查看
</
Button
><
Button
size=
"sm"
variant=
"danger"
onPress=
{
()
=>
deleteProcess
(
item
)
}
>
删除
</
Button
></
li
>)
}
</
ol
>
}
</
Card
.
Content
></
Card
><
XinyuanModal
isOpen=
{
modal
}
onOpenChange=
{
setModal
}
title=
{
draft
.
group_name
!==
undefined
?
'新建流程分组'
:
draft
.
editName
?
'编辑流程'
:
'新建流程'
}
footer=
{
<><
Button
variant=
"secondary"
onPress=
{
()
=>
setModal
(
false
)
}
>
取消
</
Button
><
Button
variant=
"primary"
isPending=
{
saving
}
onPress=
{
save
}
>
保存
</
Button
></>
}
><
div
className=
"grid gap-4"
>
{
draft
.
group_name
!==
undefined
?
<
Input
label=
"分组名称"
value=
{
draft
.
group_name
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
group_name
:
event
.
target
.
value
})
}
/>
:
<><
Input
label=
"流程名称"
value=
{
draft
.
title
||
''
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
title
:
event
.
target
.
value
})
}
/><
TextArea
label=
"流程说明"
value=
{
draft
.
remark
||
''
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
remark
:
event
.
target
.
value
})
}
/></>
}
</
div
></
XinyuanModal
></
div
>;
if
(
!
group
||
!
deleteTarget
)
return
;
setDeleting
(
true
);
setDeleteError
(
''
);
try
{
await
removeRecord
(
deleteTarget
.
name
||
deleteTarget
.
_id
);
await
updateRecord
(
group
.
name
,
{
metadata
:
{
...
group
.
metadata
,
process_list
:
(
group
.
metadata
?.
process_list
||
[]).
map
(
valueOf
).
filter
((
id
)
=>
id
!==
(
deleteTarget
.
_id
||
deleteTarget
.
name
))
}
});
setDeleteTarget
(
null
);
await
reload
();
}
catch
(
requestError
)
{
setDeleteError
(
requestError
?.
message
||
'删除失败'
);
}
finally
{
setDeleting
(
false
);
}
};
return
<
div
className=
"rc-page-stack"
><
h2
className=
"mb-4 text-xl font-semibold"
>
流程管理
</
h2
>
{
error
||
groupError
?
<
Alert
status=
"danger"
><
Alert
.
Content
><
Alert
.
Description
>
{
error
||
groupError
}
</
Alert
.
Description
></
Alert
.
Content
></
Alert
>
:
null
}
<
GroupTabs
groups=
{
groups
}
active=
{
active
}
onChange=
{
setActive
}
onCreate=
{
()
=>
{
setDraft
({
group_name
:
''
});
setModal
(
true
);
}
}
label=
"流程分组"
/><
Card
><
Card
.
Header
><
Card
.
Title
className=
"mr-auto"
>
{
group
?.
title
||
'请选择流程分组'
}
</
Card
.
Title
>
{
group
?
<
Button
variant=
"primary"
onPress=
{
()
=>
{
setDraft
({});
setModal
(
true
);
}
}
>
新增流程
</
Button
>
:
null
}
</
Card
.
Header
><
Card
.
Content
>
{
loading
?
<
div
className=
"flex min-h-32 items-center justify-center"
><
Spinner
/></
div
>
:
!
items
.
length
?
<
div
className=
"py-16 text-center text-sm text-muted"
>
暂无流程
</
div
>
:
<
ol
className=
"space-y-3"
>
{
items
.
map
((
item
,
index
)
=>
<
li
className=
"flex items-center gap-3 rounded-lg border border-default p-3"
key=
{
item
.
name
||
item
.
_id
}
><
span
className=
"grid h-8 w-8 place-items-center rounded-full bg-accent/10 text-sm font-semibold text-accent"
>
{
index
+
1
}
</
span
><
div
className=
"min-w-0 flex-1"
><
div
className=
"truncate font-medium"
>
{
item
.
title
||
item
.
name
}
</
div
><
div
className=
"text-sm text-muted"
>
{
item
.
metadata
?.
remark
||
'暂无说明'
}
</
div
></
div
><
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
{
setDraft
({
...
item
.
metadata
,
title
:
item
.
title
,
editName
:
item
.
name
});
setModal
(
true
);
}
}
>
编辑
</
Button
><
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
history
.
push
(
`/${subjectName}/${item.name || item._id}`
)
}
>
查看
</
Button
><
Button
size=
"sm"
variant=
"danger"
onPress=
{
()
=>
{
setDeleteError
(
''
);
setDeleteTarget
(
item
);
}
}
>
删除
</
Button
></
li
>)
}
</
ol
>
}
</
Card
.
Content
></
Card
><
XinyuanModal
isOpen=
{
Boolean
(
deleteTarget
)
}
onOpenChange=
{
(
open
)
=>
{
if
(
!
open
&&
!
deleting
)
setDeleteTarget
(
null
);
}
}
title=
"删除流程"
footer=
{
<><
Button
variant=
"secondary"
isDisabled=
{
deleting
}
onPress=
{
()
=>
setDeleteTarget
(
null
)
}
>
取消
</
Button
><
Button
variant=
"danger"
isPending=
{
deleting
}
onPress=
{
confirmDeleteProcess
}
>
确认删除
</
Button
></>
}
><
p
>
确定删除“
{
titleOf
(
deleteTarget
)
}
”吗?
</
p
>
{
deleteError
?
<
p
className=
"mt-3 text-danger"
role=
"alert"
>
{
deleteError
}
</
p
>
:
null
}
</
XinyuanModal
><
XinyuanModal
isOpen=
{
modal
}
onOpenChange=
{
setModal
}
title=
{
draft
.
group_name
!==
undefined
?
'新建流程分组'
:
draft
.
editName
?
'编辑流程'
:
'新建流程'
}
footer=
{
<><
Button
variant=
"secondary"
onPress=
{
()
=>
setModal
(
false
)
}
>
取消
</
Button
><
Button
variant=
"primary"
isPending=
{
saving
}
onPress=
{
save
}
>
保存
</
Button
></>
}
><
div
className=
"grid gap-4"
>
{
draft
.
group_name
!==
undefined
?
<
Input
label=
"分组名称"
value=
{
draft
.
group_name
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
group_name
:
event
.
target
.
value
})
}
/>
:
<><
Input
label=
"流程名称"
value=
{
draft
.
title
||
''
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
title
:
event
.
target
.
value
})
}
/><
TextArea
label=
"流程说明"
value=
{
draft
.
remark
||
''
}
onChange=
{
(
event
)
=>
setDraft
({
...
draft
,
remark
:
event
.
target
.
value
})
}
/></>
}
</
div
></
XinyuanModal
></
div
>;
}
}
export
default
function
ConfiguredSpecialViews
({
view
,
subjectName
,
config
})
{
export
default
function
ConfiguredSpecialViews
({
view
,
subjectName
,
config
})
{
...
...
src/pages/LawRecordPage.jsx
View file @
86bbaf04
...
@@ -202,6 +202,9 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
...
@@ -202,6 +202,9 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
const
value
=
record
?.
metadata
?.[
field
];
const
value
=
record
?.
metadata
?.[
field
];
const
attachments
=
Array
.
isArray
(
value
)
?
value
:
value
?
[
value
]
:
[];
const
attachments
=
Array
.
isArray
(
value
)
?
value
:
value
?
[
value
]
:
[];
const
[
uploading
,
setUploading
]
=
useState
(
false
);
const
[
uploading
,
setUploading
]
=
useState
(
false
);
const
[
removing
,
setRemoving
]
=
useState
(
false
);
const
[
removeTarget
,
setRemoveTarget
]
=
useState
(
null
);
const
[
removeError
,
setRemoveError
]
=
useState
(
''
);
const
uploadFiles
=
async
(
files
)
=>
{
const
uploadFiles
=
async
(
files
)
=>
{
if
(
!
field
||
!
files
?.
length
)
return
;
if
(
!
field
||
!
files
?.
length
)
return
;
...
@@ -217,10 +220,19 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
...
@@ -217,10 +220,19 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
}
}
};
};
const
removeAttachment
=
async
(
attachment
)
=>
{
const
confirmRemoveAttachment
=
async
()
=>
{
if
(
!
field
||
!
window
.
confirm
(
'确定移除这个附件吗?'
))
return
;
if
(
!
field
||
!
removeTarget
)
return
;
const
key
=
attachment
?.
_id
||
attachment
?.
url
||
attachment
?.
name
||
attachment
?.
title
;
const
key
=
removeTarget
?.
_id
||
removeTarget
?.
url
||
removeTarget
?.
name
||
removeTarget
?.
title
;
setRemoving
(
true
);
setRemoveError
(
''
);
try
{
await
onPatchMetadata
(
field
,
attachments
.
filter
((
item
)
=>
(
item
?.
_id
||
item
?.
url
||
item
?.
name
||
item
?.
title
)
!==
key
));
await
onPatchMetadata
(
field
,
attachments
.
filter
((
item
)
=>
(
item
?.
_id
||
item
?.
url
||
item
?.
name
||
item
?.
title
)
!==
key
));
setRemoveTarget
(
null
);
}
catch
(
error
)
{
setRemoveError
(
error
?.
message
||
'附件移除失败'
);
}
finally
{
setRemoving
(
false
);
}
};
};
return
(
return
(
...
@@ -235,7 +247,7 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
...
@@ -235,7 +247,7 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
<
a
href=
{
item
?.
url
||
'#'
}
rel=
"noreferrer"
target=
"_blank"
>
<
a
href=
{
item
?.
url
||
'#'
}
rel=
"noreferrer"
target=
"_blank"
>
{
item
?.
title
||
item
?.
name
||
`附件 ${index + 1}`
}
{
item
?.
title
||
item
?.
name
||
`附件 ${index + 1}`
}
</
a
>
</
a
>
<
Button
isIconOnly
aria
-
label=
"移除附件"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
removeAttachment
(
item
)
}
>
<
Button
isIconOnly
aria
-
label=
"移除附件"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
{
setRemoveError
(
''
);
setRemoveTarget
(
item
);
}
}
>
<
Close
size=
{
14
}
/>
<
Close
size=
{
14
}
/>
</
Button
>
</
Button
>
</
div
>
</
div
>
...
@@ -251,6 +263,21 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
...
@@ -251,6 +263,21 @@ function AttachmentPanel({ config, record, onPatchMetadata, setError }) {
onFilesChange=
{
uploadFiles
}
onFilesChange=
{
uploadFiles
}
/>
/>
</
Card
.
Content
>
</
Card
.
Content
>
<
XinyuanModal
footer=
{
(
<>
<
Button
isDisabled=
{
removing
}
variant=
"secondary"
onPress=
{
()
=>
setRemoveTarget
(
null
)
}
>
取消
</
Button
>
<
Button
isPending=
{
removing
}
variant=
"danger"
onPress=
{
confirmRemoveAttachment
}
>
确认移除
</
Button
>
</>
)
}
isOpen=
{
Boolean
(
removeTarget
)
}
onOpenChange=
{
(
open
)
=>
{
if
(
!
open
&&
!
removing
)
setRemoveTarget
(
null
);
}
}
size=
"sm"
title=
"移除附件"
>
<
p
>
确定移除“
{
removeTarget
?.
title
||
removeTarget
?.
name
||
removeTarget
?.
url
||
'该附件'
}
”吗?
</
p
>
{
removeError
?
<
p
className=
"mt-3 text-danger"
role=
"alert"
>
{
removeError
}
</
p
>
:
null
}
</
XinyuanModal
>
</
Card
>
</
Card
>
);
);
}
}
...
@@ -339,6 +366,8 @@ function LawRecordDetail() {
...
@@ -339,6 +366,8 @@ function LawRecordDetail() {
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
editing
,
setEditing
]
=
useState
(
false
);
const
[
editing
,
setEditing
]
=
useState
(
false
);
const
[
deletingRecord
,
setDeletingRecord
]
=
useState
(
false
);
const
[
deleteRecordOpen
,
setDeleteRecordOpen
]
=
useState
(
false
);
const
[
historyItems
,
setHistoryItems
]
=
useState
([]);
const
[
historyItems
,
setHistoryItems
]
=
useState
([]);
const
[
error
,
setError
]
=
useState
(
''
);
const
[
error
,
setError
]
=
useState
(
''
);
const
[
collections
,
setCollections
]
=
useState
(()
=>
loadStorageArray
(
COLLECTION_STORAGE_KEY
));
const
[
collections
,
setCollections
]
=
useState
(()
=>
loadStorageArray
(
COLLECTION_STORAGE_KEY
));
...
@@ -569,9 +598,10 @@ function LawRecordDetail() {
...
@@ -569,9 +598,10 @@ function LawRecordDetail() {
};
};
const
deleteRecord
=
async
()
=>
{
const
deleteRecord
=
async
()
=>
{
if
(
!
recordName
||
!
window
.
confirm
(
'确定删除这条记录吗?'
)
)
return
;
if
(
!
recordName
)
return
;
try
{
try
{
await
removeRecord
(
recordName
);
await
removeRecord
(
recordName
);
setDeleteRecordOpen
(
false
);
history
.
push
(
`/
${
subjectName
}
`
);
history
.
push
(
`/
${
subjectName
}
`
);
}
catch
(
requestError
)
{
}
catch
(
requestError
)
{
setError
(
requestError
?.
message
||
'删除失败'
);
setError
(
requestError
?.
message
||
'删除失败'
);
...
@@ -614,7 +644,7 @@ function LawRecordDetail() {
...
@@ -614,7 +644,7 @@ function LawRecordDetail() {
<
TableActionButton
icon=
{
isCollected
?
StarSolid
:
Star
}
label=
{
isCollected
?
'取消收藏'
:
'收藏'
}
onPress=
{
toggleCollection
}
/>
<
TableActionButton
icon=
{
isCollected
?
StarSolid
:
Star
}
label=
{
isCollected
?
'取消收藏'
:
'收藏'
}
onPress=
{
toggleCollection
}
/>
<
TableActionButton
icon=
{
ArrowDownTrayIcon
}
isDisabled=
{
!
firstFile
}
label=
"下载"
onPress=
{
()
=>
firstFile
?.
url
&&
window
.
open
(
firstFile
.
url
,
'_blank'
,
'noopener,noreferrer'
)
}
/>
<
TableActionButton
icon=
{
ArrowDownTrayIcon
}
isDisabled=
{
!
firstFile
}
label=
"下载"
onPress=
{
()
=>
firstFile
?.
url
&&
window
.
open
(
firstFile
.
url
,
'_blank'
,
'noopener,noreferrer'
)
}
/>
<
TableActionButton
icon=
{
Edit
}
label=
"编辑"
onPress=
{
openEditModal
}
/>
<
TableActionButton
icon=
{
Edit
}
label=
"编辑"
onPress=
{
openEditModal
}
/>
<
TableActionButton
icon=
{
Delete
}
label=
"删除"
tone=
"delete"
onPress=
{
deleteRecord
}
/>
<
TableActionButton
icon=
{
Delete
}
label=
"删除"
tone=
"delete"
onPress=
{
()
=>
{
setError
(
''
);
setDeleteRecordOpen
(
true
);
}
}
/>
</
TableActionGroup
>
</
TableActionGroup
>
)
:
null
}
)
:
null
}
</
div
>
</
div
>
...
@@ -790,6 +820,22 @@ function LawRecordDetail() {
...
@@ -790,6 +820,22 @@ function LawRecordDetail() {
</
div
>
</
div
>
</
section
>
</
section
>
</
XinyuanModal
>
</
XinyuanModal
>
<
XinyuanModal
footer=
{
(
<>
<
Button
isDisabled=
{
deletingRecord
}
variant=
"secondary"
onPress=
{
()
=>
setDeleteRecordOpen
(
false
)
}
>
取消
</
Button
>
<
Button
isPending=
{
deletingRecord
}
variant=
"danger"
onPress=
{
deleteRecord
}
>
确认删除
</
Button
>
</>
)
}
isOpen=
{
deleteRecordOpen
}
onOpenChange=
{
(
open
)
=>
{
if
(
!
open
&&
!
deletingRecord
)
setDeleteRecordOpen
(
false
);
}
}
size=
"sm"
title=
"删除记录"
>
<
p
>
确定删除“
{
record
?.
title
||
record
?.
name
}
”吗?
</
p
>
{
error
?
<
p
className=
"mt-3 text-danger"
role=
"alert"
>
{
error
}
</
p
>
:
null
}
</
XinyuanModal
>
</
div
>
</
div
>
);
);
}
}
src/pages/LawSubjectPage.jsx
View file @
86bbaf04
...
@@ -1302,23 +1302,9 @@ function SearchTable({ records, fields, subjectName, onEdit, onRemove }) {
...
@@ -1302,23 +1302,9 @@ function SearchTable({ records, fields, subjectName, onEdit, onRemove }) {
/>;
/>;
}
}
function
collectExpandableTreeKeys
(
nodes
=
[])
{
return
nodes
.
flatMap
((
node
)
=>
node
.
children
?.
length
?
[
node
.
key
,
...
collectExpandableTreeKeys
(
node
.
children
)]
:
[]);
}
function
FilterTreeCard
({
title
,
nodes
,
selectedKeys
,
onSelect
})
{
function
FilterTreeCard
({
title
,
nodes
,
selectedKeys
,
onSelect
})
{
const
[
open
,
setOpen
]
=
useState
(
false
);
const
[
open
,
setOpen
]
=
useState
(
true
);
const
[
expandedKeys
,
setExpandedKeys
]
=
useState
(()
=>
collectExpandableTreeKeys
(
nodes
));
const
[
expandedKeys
,
setExpandedKeys
]
=
useState
([]);
useEffect
(()
=>
{
const
availableKeys
=
new
Set
(
collectExpandableTreeKeys
(
nodes
));
setExpandedKeys
((
current
)
=>
{
const
retained
=
current
.
filter
((
key
)
=>
availableKeys
.
has
(
key
));
const
added
=
[...
availableKeys
].
filter
((
key
)
=>
!
current
.
includes
(
key
));
const
next
=
[...
retained
,
...
added
];
return
next
.
length
===
current
.
length
&&
next
.
every
((
key
,
index
)
=>
key
===
current
[
index
])
?
current
:
next
;
});
},
[
nodes
]);
return
(
return
(
<
section
className=
"law-filter-tree-card"
>
<
section
className=
"law-filter-tree-card"
>
...
...
src/pages/law-reference.business-flow.md
View file @
86bbaf04
This diff is collapsed.
Click to expand it.
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