Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
I
internal_regulation_manager_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
internal_regulation_manager_new
Commits
a6b49d2c
Commit
a6b49d2c
authored
Sep 28, 2026
by
drigle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 制度目录行操作对齐 streams-admin 修订/废止/备注逻辑
parent
f82fd5d5
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
93 additions
and
18 deletions
+93
-18
RegulationList.jsx
src/pages/internal_regulation_manager/RegulationList.jsx
+79
-16
internal-regulation.business-flow.md
...l_regulation_manager/internal-regulation.business-flow.md
+2
-2
internalRegulationService.js
src/services/internalRegulationService.js
+12
-0
No files found.
src/pages/internal_regulation_manager/RegulationList.jsx
View file @
a6b49d2c
import
{
Button
,
Chip
,
Input
,
Label
,
Spinner
,
TextArea
,
TextField
}
from
'@heroui/react'
;
import
{
Button
,
Chip
,
Input
,
Label
,
Spinner
,
TextArea
,
TextField
,
toast
}
from
'@heroui/react'
;
import
{
Download
,
Edit
,
Eye
,
PlusIcon
,
Search
}
from
'@/components/AppIcons'
;
import
{
Close
,
Download
,
Edit
,
Eye
,
FileText
,
PlusIcon
,
Search
}
from
'@/components/AppIcons'
;
import
ListPagination
from
'@/components/ListPagination'
;
import
ListPagination
from
'@/components/ListPagination'
;
import
XinyuanAutocomplete
from
'@/components/XinyuanAutocomplete'
;
import
XinyuanAutocomplete
from
'@/components/XinyuanAutocomplete'
;
import
XinyuanModal
from
'@/components/XinyuanModal'
;
import
XinyuanModal
from
'@/components/XinyuanModal'
;
...
@@ -11,11 +11,11 @@ import {
...
@@ -11,11 +11,11 @@ import {
queryAll
,
queryAll
,
REGULATION_SUBJECT
,
REGULATION_SUBJECT
,
REGULATION_LEVELS
,
REGULATION_LEVELS
,
updateRe
vision
,
updateRe
gulationComment
,
}
from
'@/services/internalRegulationService'
;
}
from
'@/services/internalRegulationService'
;
import
{
downloadCsv
}
from
'./csv'
;
import
{
downloadCsv
}
from
'./csv'
;
const
INITIAL_FORM
=
{
regulation_name
:
''
,
type
:
'新增'
,
level
:
'1级'
,
approve
:
[],
departments
:
[],
comment
:
''
};
const
INITIAL_FORM
=
{
regulation_name
:
''
,
level
:
'1级'
,
approve
:
[],
departments
:
[],
comment
:
''
};
const
PAGE_SIZE
=
20
;
const
PAGE_SIZE
=
20
;
function
fieldOptions
(
options
,
field
)
{
function
fieldOptions
(
options
,
field
)
{
...
@@ -28,6 +28,10 @@ function dateText(value) {
...
@@ -28,6 +28,10 @@ function dateText(value) {
return
Number
.
isNaN
(
date
.
getTime
())
?
String
(
value
).
slice
(
0
,
10
)
:
date
.
toLocaleDateString
(
'zh-CN'
);
return
Number
.
isNaN
(
date
.
getTime
())
?
String
(
value
).
slice
(
0
,
10
)
:
date
.
toLocaleDateString
(
'zh-CN'
);
}
}
function
recordTitle
(
record
)
{
return
record
.
regulation_name
||
record
.
title
||
'-'
;
}
export
default
function
RegulationList
({
options
=
{}
})
{
export
default
function
RegulationList
({
options
=
{}
})
{
const
[
records
,
setRecords
]
=
useState
([]);
const
[
records
,
setRecords
]
=
useState
([]);
const
[
searchText
,
setSearchText
]
=
useState
(
''
);
const
[
searchText
,
setSearchText
]
=
useState
(
''
);
...
@@ -39,9 +43,10 @@ export default function RegulationList({ options = {} }) {
...
@@ -39,9 +43,10 @@ export default function RegulationList({ options = {} }) {
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
error
,
setError
]
=
useState
(
''
);
const
[
error
,
setError
]
=
useState
(
''
);
const
[
dialogOpen
,
setDialogOpen
]
=
useState
(
false
);
const
[
dialogOpen
,
setDialogOpen
]
=
useState
(
false
);
const
[
editing
,
setEditing
]
=
useState
(
null
);
const
[
form
,
setForm
]
=
useState
(
INITIAL_FORM
);
const
[
form
,
setForm
]
=
useState
(
INITIAL_FORM
);
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
saving
,
setSaving
]
=
useState
(
false
);
const
[
confirmState
,
setConfirmState
]
=
useState
({
open
:
false
,
type
:
''
,
record
:
null
});
const
[
commentState
,
setCommentState
]
=
useState
({
open
:
false
,
record
:
null
,
comment
:
''
});
const
[
filters
,
setFilters
]
=
useState
({
effective_status
:
''
,
level
:
''
,
departments
:
''
,
approve
:
''
});
const
[
filters
,
setFilters
]
=
useState
({
effective_status
:
''
,
level
:
''
,
departments
:
''
,
approve
:
''
});
const
refresh
=
async
()
=>
{
const
refresh
=
async
()
=>
{
...
@@ -72,7 +77,7 @@ export default function RegulationList({ options = {} }) {
...
@@ -72,7 +77,7 @@ export default function RegulationList({ options = {} }) {
useEffect
(()
=>
{
refresh
();
},
[
page
,
pageSize
,
keyword
,
filters
]);
useEffect
(()
=>
{
refresh
();
},
[
page
,
pageSize
,
keyword
,
filters
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
const
open
=
()
=>
{
set
Editing
(
null
);
set
Form
(
INITIAL_FORM
);
setDialogOpen
(
true
);
};
const
open
=
()
=>
{
setForm
(
INITIAL_FORM
);
setDialogOpen
(
true
);
};
window
.
addEventListener
(
'internal-regulation:create'
,
open
);
window
.
addEventListener
(
'internal-regulation:create'
,
open
);
return
()
=>
window
.
removeEventListener
(
'internal-regulation:create'
,
open
);
return
()
=>
window
.
removeEventListener
(
'internal-regulation:create'
,
open
);
},
[]);
},
[]);
...
@@ -103,9 +108,36 @@ export default function RegulationList({ options = {} }) {
...
@@ -103,9 +108,36 @@ export default function RegulationList({ options = {} }) {
if
(
!
form
.
regulation_name
.
trim
())
return
;
if
(
!
form
.
regulation_name
.
trim
())
return
;
try
{
try
{
setSaving
(
true
);
setSaving
(
true
);
if
(
editing
)
await
updateRevision
(
editing
.
name
,
form
);
await
createRevision
(
form
);
else
await
createRevision
(
form
);
setDialogOpen
(
false
);
setDialogOpen
(
false
);
toast
.
success
(
'制度创建成功'
);
await
refresh
();
}
catch
(
saveError
)
{
setError
(
saveError
?.
message
||
'保存失败,请检查字段后重试。'
);
}
finally
{
setSaving
(
false
);
}
};
const
requestRevision
=
(
record
,
type
)
=>
{
setConfirmState
({
open
:
true
,
type
,
record
});
};
const
confirmRevision
=
async
()
=>
{
const
{
type
,
record
}
=
confirmState
;
if
(
!
record
)
return
;
try
{
setSaving
(
true
);
await
createRevision
({
regulation_name
:
recordTitle
(
record
),
type
,
level
:
record
.
level
,
departments
:
record
.
departments
,
approve
:
record
.
approve
,
origin_regulation
:
record
.
_id
,
});
setConfirmState
({
open
:
false
,
type
:
''
,
record
:
null
});
toast
.
success
(
type
===
'修订'
?
'修订制度创建成功'
:
'废除制度创建成功'
);
await
refresh
();
await
refresh
();
}
catch
(
saveError
)
{
}
catch
(
saveError
)
{
setError
(
saveError
?.
message
||
'保存失败,请检查字段后重试。'
);
setError
(
saveError
?.
message
||
'保存失败,请检查字段后重试。'
);
...
@@ -114,6 +146,26 @@ export default function RegulationList({ options = {} }) {
...
@@ -114,6 +146,26 @@ export default function RegulationList({ options = {} }) {
}
}
};
};
const
openComment
=
(
record
)
=>
{
setCommentState
({
open
:
true
,
record
,
comment
:
record
.
comment
||
''
});
};
const
saveComment
=
async
()
=>
{
const
{
record
}
=
commentState
;
if
(
!
record
)
return
;
try
{
setSaving
(
true
);
await
updateRegulationComment
(
record
,
commentState
.
comment
);
setCommentState
({
open
:
false
,
record
:
null
,
comment
:
''
});
toast
.
success
(
'已成功添加备注'
);
await
refresh
();
}
catch
(
saveError
)
{
setError
(
saveError
?.
message
||
'备注保存失败,请稍后重试。'
);
}
finally
{
setSaving
(
false
);
}
};
return
(
return
(
<
div
className=
"space-y-4"
>
<
div
className=
"space-y-4"
>
<
div
className=
"flex flex-col gap-3 md:flex-row md:items-center md:justify-between"
>
<
div
className=
"flex flex-col gap-3 md:flex-row md:items-center md:justify-between"
>
...
@@ -124,7 +176,7 @@ export default function RegulationList({ options = {} }) {
...
@@ -124,7 +176,7 @@ export default function RegulationList({ options = {} }) {
</
TextField
>
</
TextField
>
<
Button
isDisabled=
{
loading
}
variant=
"secondary"
onPress=
{
submitSearch
}
>
查询
</
Button
>
<
Button
isDisabled=
{
loading
}
variant=
"secondary"
onPress=
{
submitSearch
}
>
查询
</
Button
>
</
div
>
</
div
>
<
div
className=
"flex flex-wrap items-center gap-2"
><
Button
variant=
"tertiary"
onPress=
{
exportList
}
><
Download
size=
{
16
}
/>
批量下载
</
Button
><
Button
variant=
"primary"
onPress=
{
()
=>
{
set
Editing
(
null
);
set
Form
(
INITIAL_FORM
);
setDialogOpen
(
true
);
}
}
><
PlusIcon
size=
{
16
}
/>
创建修订计划
</
Button
></
div
>
<
div
className=
"flex flex-wrap items-center gap-2"
><
Button
variant=
"tertiary"
onPress=
{
exportList
}
><
Download
size=
{
16
}
/>
批量下载
</
Button
><
Button
variant=
"primary"
onPress=
{
()
=>
{
setForm
(
INITIAL_FORM
);
setDialogOpen
(
true
);
}
}
><
PlusIcon
size=
{
16
}
/>
创建修订计划
</
Button
></
div
>
</
div
>
</
div
>
<
div
className=
"flex flex-wrap items-end gap-3 rounded-xl border border-separator bg-surface-secondary/50 p-3"
>
<
div
className=
"flex flex-wrap items-end gap-3 rounded-xl border border-separator bg-surface-secondary/50 p-3"
>
<
XinyuanAutocomplete
className=
"w-44"
label=
"时效性"
options=
{
[{
value
:
''
,
label
:
'全部'
},
...
effectiveStatusOptions
]
}
selectedKey=
{
filters
.
effective_status
}
onSelectionChange=
{
(
value
)
=>
{
setFilters
((
current
)
=>
({
...
current
,
effective_status
:
String
(
value
||
''
)
}));
setPage
(
0
);
}
}
/>
<
XinyuanAutocomplete
className=
"w-44"
label=
"时效性"
options=
{
[{
value
:
''
,
label
:
'全部'
},
...
effectiveStatusOptions
]
}
selectedKey=
{
filters
.
effective_status
}
onSelectionChange=
{
(
value
)
=>
{
setFilters
((
current
)
=>
({
...
current
,
effective_status
:
String
(
value
||
''
)
}));
setPage
(
0
);
}
}
/>
...
@@ -135,33 +187,44 @@ export default function RegulationList({ options = {} }) {
...
@@ -135,33 +187,44 @@ export default function RegulationList({ options = {} }) {
{
error
?
<
div
className=
"rounded-xl border border-danger/30 bg-danger/5 p-3 text-sm text-danger"
>
{
error
}
</
div
>
:
null
}
{
error
?
<
div
className=
"rounded-xl border border-danger/30 bg-danger/5 p-3 text-sm text-danger"
>
{
error
}
</
div
>
:
null
}
{
loading
?
<
div
className=
"flex min-h-48 items-center justify-center"
><
Spinner
label=
"正在加载制度..."
/></
div
>
:
records
.
length
===
0
?
<
div
className=
"rounded-2xl border border-dashed border-separator p-10 text-center text-sm text-muted"
>
暂无制度记录
</
div
>
:
(
{
loading
?
<
div
className=
"flex min-h-48 items-center justify-center"
><
Spinner
label=
"正在加载制度..."
/></
div
>
:
records
.
length
===
0
?
<
div
className=
"rounded-2xl border border-dashed border-separator p-10 text-center text-sm text-muted"
>
暂无制度记录
</
div
>
:
(
<
div
className=
"overflow-x-auto rounded-2xl border border-separator"
>
<
div
className=
"overflow-x-auto rounded-2xl border border-separator"
>
<
table
className=
"w-full min-w-[
98
0px] text-left text-sm"
>
<
table
className=
"w-full min-w-[
104
0px] text-left text-sm"
>
<
thead
className=
"bg-surface-secondary text-muted"
><
tr
>
{
[
'制度名称'
,
'修订状态'
,
'时效性'
,
'效力位阶'
,
'制定部门'
,
'审批主体'
,
'发文日期'
,
'操作'
].
map
((
title
)
=>
<
th
className=
"px-4 py-3 font-medium"
key=
{
title
}
>
{
title
}
</
th
>)
}
</
tr
></
thead
>
<
thead
className=
"bg-surface-secondary text-muted"
><
tr
>
{
[
'制度名称'
,
'修订状态'
,
'时效性'
,
'效力位阶'
,
'制定部门'
,
'审批主体'
,
'发文日期'
,
'
备注'
,
'
操作'
].
map
((
title
)
=>
<
th
className=
"px-4 py-3 font-medium"
key=
{
title
}
>
{
title
}
</
th
>)
}
</
tr
></
thead
>
<
tbody
className=
"divide-y divide-separator"
>
<
tbody
className=
"divide-y divide-separator"
>
{
records
.
map
((
record
)
=>
<
tr
className=
"hover:bg-surface-secondary/50"
key=
{
record
.
_id
||
record
.
name
}
>
{
records
.
map
((
record
)
=>
<
tr
className=
"hover:bg-surface-secondary/50"
key=
{
record
.
_id
||
record
.
name
}
>
<
td
className=
"px-4 py-3"
><
button
className=
"max-w-64 truncate font-medium text-accent hover:underline"
onClick=
{
()
=>
history
.
push
(
`/internal_regulation/${record.name || record._id}`
)
}
>
{
record
.
regulation_name
||
record
.
title
||
'-'
}
</
button
></
td
>
<
td
className=
"px-4 py-3"
><
button
className=
"max-w-64 truncate font-medium text-accent hover:underline"
onClick=
{
()
=>
history
.
push
(
`/internal_regulation/${record.name || record._id}`
)
}
>
{
record
Title
(
record
)
}
</
button
></
td
>
<
td
className=
"px-4 py-3"
>
{
record
.
revision_type
?
<
Chip
color=
{
record
.
revision_type
===
'修订'
?
'warning'
:
'accent'
}
size=
"sm"
variant=
"soft"
><
Chip
.
Label
>
待
{
record
.
revision_type
}
</
Chip
.
Label
></
Chip
>
:
<
span
className=
"text-muted"
>
-
</
span
>
}
</
td
>
<
td
className=
"px-4 py-3"
>
{
record
.
revision_type
?
<
Chip
color=
{
record
.
revision_type
===
'修订'
?
'warning'
:
record
.
revision_type
===
'废止'
?
'default'
:
'accent'
}
size=
"sm"
variant=
"soft"
><
Chip
.
Label
>
待
{
record
.
revision_type
}
</
Chip
.
Label
></
Chip
>
:
<
span
className=
"text-muted"
>
-
</
span
>
}
</
td
>
<
td
className=
"px-4 py-3"
>
{
record
.
effective_status
||
'-'
}
</
td
><
td
className=
"px-4 py-3"
>
{
record
.
level
||
'-'
}
</
td
>
<
td
className=
"px-4 py-3"
>
{
record
.
effective_status
||
'-'
}
</
td
><
td
className=
"px-4 py-3"
>
{
record
.
level
||
'-'
}
</
td
>
<
td
className=
"max-w-52 truncate px-4 py-3"
>
{
Array
.
isArray
(
record
.
departments
)
?
record
.
departments
.
join
(
'、'
)
:
record
.
departments
||
'-'
}
</
td
>
<
td
className=
"max-w-52 truncate px-4 py-3"
>
{
Array
.
isArray
(
record
.
departments
)
?
record
.
departments
.
join
(
'、'
)
:
record
.
departments
||
'-'
}
</
td
>
<
td
className=
"max-w-52 truncate px-4 py-3"
>
{
Array
.
isArray
(
record
.
approve
)
?
record
.
approve
.
join
(
'、'
)
:
record
.
approve
||
'-'
}
</
td
>
<
td
className=
"max-w-52 truncate px-4 py-3"
>
{
Array
.
isArray
(
record
.
approve
)
?
record
.
approve
.
join
(
'、'
)
:
record
.
approve
||
'-'
}
</
td
>
<
td
className=
"px-4 py-3"
>
{
dateText
(
record
.
public_date
)
}
</
td
>
<
td
className=
"px-4 py-3"
>
{
dateText
(
record
.
public_date
)
}
</
td
>
<
td
className=
"px-4 py-3"
><
div
className=
"flex items-center gap-1"
><
Button
isIconOnly
aria
-
label=
"查看详情"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
history
.
push
(
`/internal_regulation/${record.name || record._id}`
)
}
><
Eye
size=
{
16
}
/></
Button
><
Button
isIconOnly
aria
-
label=
"编辑修订计划"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
{
setEditing
(
record
);
setForm
({
...
INITIAL_FORM
,
...
record
});
setDialogOpen
(
true
);
}
}
><
Edit
size=
{
16
}
/></
Button
></
div
></
td
>
<
td
className=
"max-w-40 truncate px-4 py-3 text-muted"
title=
{
record
.
comment
||
''
}
>
{
record
.
comment
||
'-'
}
</
td
>
<
td
className=
"px-4 py-3"
><
div
className=
"flex items-center gap-1"
>
<
Button
isIconOnly
aria
-
label=
"查看详情"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
history
.
push
(
`/internal_regulation/${record.name || record._id}`
)
}
><
Eye
size=
{
16
}
/></
Button
>
<
Button
isIconOnly
aria
-
label=
"修订制度"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
requestRevision
(
record
,
'修订'
)
}
><
Edit
size=
{
16
}
/></
Button
>
<
Button
isIconOnly
aria
-
label=
"废止制度"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
requestRevision
(
record
,
'废止'
)
}
><
Close
size=
{
16
}
/></
Button
>
<
Button
isIconOnly
aria
-
label=
"编辑备注"
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
openComment
(
record
)
}
><
FileText
size=
{
16
}
/></
Button
>
</
div
></
td
>
</
tr
>)
}
</
tr
>)
}
</
tbody
>
</
tbody
>
</
table
>
</
table
>
</
div
>
</
div
>
)
}
)
}
<
ListPagination
isDisabled=
{
loading
}
page=
{
page
}
pageSize=
{
pageSize
}
total=
{
total
}
totalPages=
{
totalPages
}
onPageChange=
{
setPage
}
onPageSizeChange=
{
changePageSize
}
/>
<
ListPagination
isDisabled=
{
loading
}
page=
{
page
}
pageSize=
{
pageSize
}
total=
{
total
}
totalPages=
{
totalPages
}
onPageChange=
{
setPage
}
onPageSizeChange=
{
changePageSize
}
/>
<
XinyuanModal
isOpen=
{
dialogOpen
}
onOpenChange=
{
setDialogOpen
}
size=
"2xl"
title=
{
editing
?
'编辑修订计划'
:
'创建修订计划'
}
footer=
{
<
div
className=
"flex justify-end gap-2"
><
Button
variant=
"tertiary"
onPress=
{
()
=>
setDialogOpen
(
false
)
}
>
取消
</
Button
><
Button
isDisabled=
{
saving
||
!
form
.
regulation_name
.
trim
()
}
variant=
"primary"
onPress=
{
submit
}
>
{
saving
?
'保存中...'
:
'保存'
}
</
Button
></
div
>
}
>
<
XinyuanModal
isOpen=
{
dialogOpen
}
onOpenChange=
{
setDialogOpen
}
size=
"2xl"
title=
"创建修订计划"
footer=
{
<
div
className=
"flex justify-end gap-2"
><
Button
variant=
"tertiary"
onPress=
{
()
=>
setDialogOpen
(
false
)
}
>
取消
</
Button
><
Button
isDisabled=
{
saving
||
!
form
.
regulation_name
.
trim
()
}
variant=
"primary"
onPress=
{
submit
}
>
{
saving
?
'保存中...'
:
'保存'
}
</
Button
></
div
>
}
>
<
div
className=
"grid gap-4 sm:grid-cols-2"
>
<
div
className=
"grid gap-4 sm:grid-cols-2"
>
<
TextField
className=
"sm:col-span-2"
fullWidth
isRequired
value=
{
form
.
regulation_name
}
onChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
regulation_name
:
value
}))
}
><
Label
>
制度名称
</
Label
><
Input
fullWidth
placeholder=
"请输入制度名称"
variant=
"secondary"
/></
TextField
>
<
TextField
className=
"sm:col-span-2"
fullWidth
isRequired
value=
{
form
.
regulation_name
}
onChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
regulation_name
:
value
}))
}
><
Label
>
制度名称
</
Label
><
Input
fullWidth
placeholder=
"请输入制度名称"
variant=
"secondary"
/></
TextField
>
<
XinyuanAutocomplete
isRequired
label=
"修订类型"
options=
{
[
'新增'
,
'修订'
,
'废止'
].
map
((
value
)
=>
({
value
,
label
:
value
}))
}
selectedKey=
{
form
.
type
}
onSelectionChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
type
:
String
(
value
)
}))
}
/>
<
XinyuanAutocomplete
label=
"效力位阶"
options=
{
REGULATION_LEVELS
.
map
((
value
)
=>
({
value
,
label
:
value
}))
}
selectedKey=
{
form
.
level
}
onSelectionChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
level
:
String
(
value
)
}))
}
/>
<
XinyuanAutocomplete
label=
"效力位阶"
options=
{
REGULATION_LEVELS
.
map
((
value
)
=>
({
value
,
label
:
value
}))
}
selectedKey=
{
form
.
level
}
onSelectionChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
level
:
String
(
value
)
}))
}
/>
<
XinyuanAutocomplete
label=
"审批主体"
options=
{
approveOptions
}
selectedKeys=
{
new
Set
(
form
.
approve
||
[])
}
selectionMode=
"multiple"
onSelectionChange=
{
(
values
)
=>
setForm
((
current
)
=>
({
...
current
,
approve
:
values
===
'all'
?
approveOptions
.
map
((
item
)
=>
item
.
value
)
:
Array
.
from
(
values
||
[])
}))
}
/>
<
XinyuanAutocomplete
label=
"审批主体"
options=
{
approveOptions
}
selectedKeys=
{
new
Set
(
form
.
approve
||
[])
}
selectionMode=
"multiple"
onSelectionChange=
{
(
values
)
=>
setForm
((
current
)
=>
({
...
current
,
approve
:
values
===
'all'
?
approveOptions
.
map
((
item
)
=>
item
.
value
)
:
Array
.
from
(
values
||
[])
}))
}
/>
<
XinyuanAutocomplete
label=
"制定部门"
options=
{
departmentOptions
}
selectedKeys=
{
new
Set
(
form
.
departments
||
[])
}
selectionMode=
"multiple"
onSelectionChange=
{
(
values
)
=>
setForm
((
current
)
=>
({
...
current
,
departments
:
values
===
'all'
?
departmentOptions
.
map
((
item
)
=>
item
.
value
)
:
Array
.
from
(
values
||
[])
}))
}
/>
<
XinyuanAutocomplete
label=
"制定部门"
options=
{
departmentOptions
}
selectedKeys=
{
new
Set
(
form
.
departments
||
[])
}
selectionMode=
"multiple"
onSelectionChange=
{
(
values
)
=>
setForm
((
current
)
=>
({
...
current
,
departments
:
values
===
'all'
?
departmentOptions
.
map
((
item
)
=>
item
.
value
)
:
Array
.
from
(
values
||
[])
}))
}
/>
<
TextField
className=
"sm:col-span-2"
fullWidth
value=
{
form
.
comment
}
onChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
comment
:
value
}))
}
><
Label
>
备注
</
Label
><
TextArea
fullWidth
rows=
{
4
}
placeholder=
"补充说明"
variant=
"secondary"
/></
TextField
>
<
TextField
className=
"sm:col-span-2"
fullWidth
value=
{
form
.
comment
}
onChange=
{
(
value
)
=>
setForm
((
current
)
=>
({
...
current
,
comment
:
value
}))
}
><
Label
>
备注
</
Label
><
TextArea
fullWidth
rows=
{
4
}
placeholder=
"补充说明"
variant=
"secondary"
/></
TextField
>
</
div
>
</
div
>
</
XinyuanModal
>
</
XinyuanModal
>
<
XinyuanModal
isOpen=
{
confirmState
.
open
}
onOpenChange=
{
(
open
)
=>
setConfirmState
((
current
)
=>
({
...
current
,
open
}))
}
size=
"md"
title=
{
confirmState
.
type
===
'修订'
?
'确定要修订这条制度吗?'
:
'确认要废止这条制度吗?'
}
description=
{
confirmState
.
record
?
`制度名称:${recordTitle(confirmState.record)}`
:
''
}
footer=
{
<
div
className=
"flex justify-end gap-2"
><
Button
variant=
"tertiary"
onPress=
{
()
=>
setConfirmState
((
current
)
=>
({
...
current
,
open
:
false
}))
}
>
取消
</
Button
><
Button
isDisabled=
{
saving
}
variant=
"primary"
onPress=
{
confirmRevision
}
>
{
saving
?
'创建中...'
:
'确定'
}
</
Button
></
div
>
}
>
{
confirmState
.
type
===
'废止'
?
<
div
className=
"text-sm text-danger"
>
废止后该制度将在发文时标记为“已失效”,请确认已完成相关审批流程。
</
div
>
:
null
}
</
XinyuanModal
>
<
XinyuanModal
isOpen=
{
commentState
.
open
}
onOpenChange=
{
(
open
)
=>
setCommentState
((
current
)
=>
({
...
current
,
open
}))
}
size=
"md"
title=
"编辑备注"
description=
{
commentState
.
record
?
`制度名称:${recordTitle(commentState.record)}`
:
''
}
footer=
{
<
div
className=
"flex justify-end gap-2"
><
Button
variant=
"tertiary"
onPress=
{
()
=>
setCommentState
((
current
)
=>
({
...
current
,
open
:
false
}))
}
>
取消
</
Button
><
Button
isDisabled=
{
saving
}
variant=
"primary"
onPress=
{
saveComment
}
>
{
saving
?
'保存中...'
:
'保存'
}
</
Button
></
div
>
}
>
<
TextField
fullWidth
value=
{
commentState
.
comment
}
onChange=
{
(
value
)
=>
setCommentState
((
current
)
=>
({
...
current
,
comment
:
value
}))
}
><
Label
>
备注
</
Label
><
TextArea
fullWidth
rows=
{
5
}
placeholder=
"补充说明"
variant=
"secondary"
/></
TextField
>
</
XinyuanModal
>
</
div
>
</
div
>
);
);
}
}
src/pages/internal_regulation_manager/internal-regulation.business-flow.md
View file @
a6b49d2c
...
@@ -11,8 +11,8 @@
...
@@ -11,8 +11,8 @@
1.
页面读取
`internal_regulation`
Subject 定义,并从字段
`settings.options`
生成审批主体、制定部门等选项。
1.
页面读取
`internal_regulation`
Subject 定义,并从字段
`settings.options`
生成审批主体、制定部门等选项。
2.
列表按
`metadata.public_date`
倒序查询,支持制度名称搜索、时效性/位阶/部门/审批主体筛选与展示;制度名称输入后点击“查询”或按 Enter 才提交搜索,输入过程不实时请求;“批量下载”按当前已提交的搜索和筛选条件导出 CSV。
2.
列表按
`metadata.public_date`
倒序查询,支持制度名称搜索、时效性/位阶/部门/审批主体筛选与展示;制度名称输入后点击“查询”或按 Enter 才提交搜索,输入过程不实时请求;“批量下载”按当前已提交的搜索和筛选条件导出 CSV。
3.
创建修订计划时写入
`internal_regulation_revision`
,业务字段全部放入
`metadata`
,初始状态为“起草中”。
3.
“创建修订计划”固定生成“新增”类型的
`internal_regulation_revision`
记录
,业务字段全部放入
`metadata`
,初始状态为“起草中”。
4.
制度
名称进入详情路由;编辑仅更新制度允许修改的
`metadata`
字段,引用字段只保存 ID
。
4.
制度
目录行操作与旧版 streams-admin 保持一致:制度名称进入详情路由;行内“修订制度/废止制度”按钮弹出确认框,确认后以当前制度的
`regulation_name/level/departments/approve`
复制生成一条
`internal_regulation_revision`
记录,
`type`
为“修订”或“废止”,
`origin_regulation`
只保存现行制度 ID,初始状态为“起草中”,列表“修订状态”列刷新为“待修订/待废止”;行内“编辑备注”打开备注弹窗,仅更新现行制度
`metadata.comment`
,不覆盖其余字段
。
## 修订计划与状态
## 修订计划与状态
...
...
src/services/internalRegulationService.js
View file @
a6b49d2c
...
@@ -209,6 +209,18 @@ export async function updateRevision(name, values = {}) {
...
@@ -209,6 +209,18 @@ export async function updateRevision(name, values = {}) {
});
});
}
}
export
async
function
updateRegulationComment
(
record
,
comment
)
{
const
name
=
record
?.
name
;
if
(
!
name
)
throw
new
Error
(
'制度记录缺少标识,无法保存备注。'
);
const
payload
=
{
name
,
title
:
record
.
title
,
metadata
:
normalizeMetadata
({
...
metadataOf
(
record
),
comment
}),
};
if
(
record
.
content
!==
undefined
)
payload
.
content
=
record
.
content
;
return
updateRecord
(
name
,
payload
);
}
export
async
function
setRevisionStatus
(
name
,
status
)
{
export
async
function
setRevisionStatus
(
name
,
status
)
{
const
current
=
await
loadRecord
(
name
);
const
current
=
await
loadRecord
(
name
);
if
(
!
current
)
throw
new
Error
(
'修订计划不存在。'
);
if
(
!
current
)
throw
new
Error
(
'修订计划不存在。'
);
...
...
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