Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
M
model_analysis
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
model_analysis
Commits
f8264ec9
Commit
f8264ec9
authored
Sep 03, 2026
by
Andy-bubu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: align model groups with HeroUI file tree
parent
00b6e86c
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
126 additions
and
53 deletions
+126
-53
Models.jsx
src/pages/project_manager_xy/Models.jsx
+126
-53
No files found.
src/pages/project_manager_xy/Models.jsx
View file @
f8264ec9
import
XinyuanAutocomplete
from
'@/components/XinyuanAutocomplete'
;
import
XinyuanAutocomplete
from
'@/components/XinyuanAutocomplete'
;
import
XinyuanModal
from
'@/components/XinyuanModal'
;
import
XinyuanModal
from
'@/components/XinyuanModal'
;
import
{
UserContext
}
from
'@/wrapper/Auth'
;
import
{
UserContext
}
from
'@/wrapper/Auth'
;
import
{
Edit
,
Eye
}
from
'@/components/AppIcons'
;
import
{
Delete
,
Edit
,
Eye
,
FolderOpenIcon
,
More
,
PlusIcon
}
from
'@/components/AppIcons'
;
import
{
import
{
AlertDialog
,
AlertDialog
,
Button
,
Button
,
Checkbox
,
Checkbox
,
Description
,
Description
,
Dropdown
,
Input
,
Input
,
Label
,
Label
,
ProgressBar
,
ProgressBar
,
ScrollShadow
,
ScrollShadow
,
Surface
,
Surface
,
Tabs
,
TextArea
,
TextArea
,
TextField
,
TextField
,
}
from
'@heroui/react'
;
}
from
'@heroui/react'
;
import
{
DataGrid
}
from
'@heroui-pro/react/data-grid'
;
import
{
DataGrid
}
from
'@heroui-pro/react/data-grid'
;
import
{
FileTree
}
from
'@heroui-pro/react/file-tree'
;
import
{
ListView
}
from
'@heroui-pro/react/list-view'
;
import
{
ListView
}
from
'@heroui-pro/react/list-view'
;
import
{
Stepper
}
from
'@heroui-pro/react/stepper'
;
import
{
Stepper
}
from
'@heroui-pro/react/stepper'
;
import
{
useContext
,
useEffect
,
useMemo
,
useState
}
from
'react'
;
import
{
useContext
,
useEffect
,
useMemo
,
useState
}
from
'react'
;
...
@@ -76,13 +77,45 @@ function flattenGroupOptions(nodes, depth = 0) {
...
@@ -76,13 +77,45 @@ function flattenGroupOptions(nodes, depth = 0) {
]);
]);
}
}
function
flattenGroupTabs
(
nodes
,
ancestors
=
[])
{
function
groupTreeItemClassName
({
isHovered
,
isSelected
})
{
return
nodes
.
flatMap
((
node
)
=>
{
const
stateClass
=
isSelected
?
'!bg-surface-secondary'
:
isHovered
?
'!bg-surface-tertiary'
:
''
;
const
path
=
[...
ancestors
,
node
.
groupName
];
return
[
'mb-1'
,
stateClass
].
filter
(
Boolean
).
join
(
' '
);
return
[
}
{
value
:
node
.
id
,
label
:
path
.
join
(
' / '
)
},
...
flattenGroupTabs
(
node
.
children
||
[],
path
),
function
GroupTreeItems
({
nodes
,
onEditGroup
,
onRequestDelete
})
{
];
return
nodes
.
map
((
node
)
=>
{
const
hasChildItems
=
Boolean
(
node
.
children
?.
length
);
return
(
<
FileTree
.
Item
hasChildItems=
{
hasChildItems
}
icon=
{
<
FolderOpenIcon
/>
}
id=
{
node
.
id
}
key=
{
node
.
id
}
className=
{
groupTreeItemClassName
}
textValue=
{
node
.
groupName
}
title=
{
(
<
span
className=
"flex min-w-0 items-center justify-between gap-2"
>
<
span
className=
"truncate"
>
{
node
.
groupName
}
</
span
>
<
Dropdown
>
<
Dropdown
.
Trigger
aria
-
label=
{
`分组操作 ${node.groupName}`
}
isIconOnly
size=
"sm"
variant=
"ghost"
>
<
More
/>
</
Dropdown
.
Trigger
>
<
Dropdown
.
Popover
className=
"w-40 min-w-0"
placement=
"bottom end"
>
<
Dropdown
.
Menu
aria
-
label=
{
`${node.groupName}操作`
}
className=
"w-full min-w-0"
onAction=
{
(
key
)
=>
{
if
(
key
===
'edit'
)
onEditGroup
(
node
);
if
(
key
===
'delete'
)
onRequestDelete
(
node
);
}
}
>
<
Dropdown
.
Item
id=
"edit"
textValue=
"编辑分组"
><
Edit
slot=
"icon"
/>
编辑分组
</
Dropdown
.
Item
>
<
Dropdown
.
Item
id=
"delete"
textValue=
"删除分组"
variant=
"danger"
><
Delete
slot=
"icon"
/>
删除分组
</
Dropdown
.
Item
>
</
Dropdown
.
Menu
>
</
Dropdown
.
Popover
>
</
Dropdown
>
</
span
>
)
}
>
{
hasChildItems
?
<
GroupTreeItems
nodes=
{
node
.
children
}
onEditGroup=
{
onEditGroup
}
onRequestDelete=
{
onRequestDelete
}
/>
:
null
}
</
FileTree
.
Item
>
);
});
});
}
}
...
@@ -106,6 +139,7 @@ export default function Models() {
...
@@ -106,6 +139,7 @@ export default function Models() {
const
[
models
,
setModels
]
=
useState
([]);
const
[
models
,
setModels
]
=
useState
([]);
const
[
groups
,
setGroups
]
=
useState
([]);
const
[
groups
,
setGroups
]
=
useState
([]);
const
[
activeGroupId
,
setActiveGroupId
]
=
useState
(
ROOT_GROUP_ID
);
const
[
activeGroupId
,
setActiveGroupId
]
=
useState
(
ROOT_GROUP_ID
);
const
[
expandedGroupIds
,
setExpandedGroupIds
]
=
useState
(
new
Set
([
ROOT_GROUP_ID
]));
const
[
keyword
,
setKeyword
]
=
useState
(
''
);
const
[
keyword
,
setKeyword
]
=
useState
(
''
);
const
[
page
,
setPage
]
=
useState
(
0
);
const
[
page
,
setPage
]
=
useState
(
0
);
const
[
pageSize
,
setPageSize
]
=
useState
(
DEFAULT_PAGE_SIZE
);
const
[
pageSize
,
setPageSize
]
=
useState
(
DEFAULT_PAGE_SIZE
);
...
@@ -115,6 +149,7 @@ export default function Models() {
...
@@ -115,6 +149,7 @@ export default function Models() {
const
[
isGroupDialogOpen
,
setIsGroupDialogOpen
]
=
useState
(
false
);
const
[
isGroupDialogOpen
,
setIsGroupDialogOpen
]
=
useState
(
false
);
const
[
isDeleteGroupDialogOpen
,
setIsDeleteGroupDialogOpen
]
=
useState
(
false
);
const
[
isDeleteGroupDialogOpen
,
setIsDeleteGroupDialogOpen
]
=
useState
(
false
);
const
[
deleteTargetGroup
,
setDeleteTargetGroup
]
=
useState
(
null
);
const
[
groupForm
,
setGroupForm
]
=
useState
({
recordName
:
''
,
groupName
:
''
,
parentGroupId
:
''
});
const
[
groupForm
,
setGroupForm
]
=
useState
({
recordName
:
''
,
groupName
:
''
,
parentGroupId
:
''
});
const
[
isModelDialogOpen
,
setIsModelDialogOpen
]
=
useState
(
false
);
const
[
isModelDialogOpen
,
setIsModelDialogOpen
]
=
useState
(
false
);
const
[
editingModel
,
setEditingModel
]
=
useState
(
null
);
const
[
editingModel
,
setEditingModel
]
=
useState
(
null
);
...
@@ -155,7 +190,6 @@ export default function Models() {
...
@@ -155,7 +190,6 @@ export default function Models() {
const
groupTree
=
useMemo
(()
=>
buildGroupTree
(
groups
),
[
groups
]);
const
groupTree
=
useMemo
(()
=>
buildGroupTree
(
groups
),
[
groups
]);
const
groupOptions
=
useMemo
(()
=>
flattenGroupOptions
(
groupTree
),
[
groupTree
]);
const
groupOptions
=
useMemo
(()
=>
flattenGroupOptions
(
groupTree
),
[
groupTree
]);
const
groupTabs
=
useMemo
(()
=>
flattenGroupTabs
(
groupTree
),
[
groupTree
]);
const
selectedGroup
=
groups
.
find
((
group
)
=>
group
.
id
===
activeGroupId
);
const
selectedGroup
=
groups
.
find
((
group
)
=>
group
.
id
===
activeGroupId
);
const
filteredModels
=
useMemo
(()
=>
{
const
filteredModels
=
useMemo
(()
=>
{
const
groupIds
=
activeGroupId
===
ROOT_GROUP_ID
?
null
:
collectDescendantIds
(
groups
,
activeGroupId
);
const
groupIds
=
activeGroupId
===
ROOT_GROUP_ID
?
null
:
collectDescendantIds
(
groups
,
activeGroupId
);
...
@@ -195,7 +229,7 @@ export default function Models() {
...
@@ -195,7 +229,7 @@ export default function Models() {
{
id
:
'status'
,
header
:
'同步状态'
,
minWidth
:
120
,
cell
:
(
model
)
=>
<
SyncStatusTag
status=
{
model
.
lastSyncStatus
}
/>
},
{
id
:
'status'
,
header
:
'同步状态'
,
minWidth
:
120
,
cell
:
(
model
)
=>
<
SyncStatusTag
status=
{
model
.
lastSyncStatus
}
/>
},
{
id
:
'syncedAt'
,
header
:
'最近同步'
,
minWidth
:
180
,
allowsSorting
:
true
,
cell
:
(
model
)
=>
formatDateTime
(
model
.
lastSyncedAt
)
},
{
id
:
'syncedAt'
,
header
:
'最近同步'
,
minWidth
:
180
,
allowsSorting
:
true
,
cell
:
(
model
)
=>
formatDateTime
(
model
.
lastSyncedAt
)
},
{
{
id
:
'actions'
,
header
:
'操作'
,
width
:
112
,
id
:
'actions'
,
header
:
'操作'
,
width
:
112
,
minWidth
:
112
,
maxWidth
:
112
,
pinned
:
'end'
,
cell
:
(
model
)
=>
<
div
className=
"flex items-center gap-2"
><
DataGridActionButton
label=
{
`查看 ${model.modelName}`
}
onPress=
{
()
=>
history
.
push
(
`/models/${model.id}/batches`
)
}
><
Eye
/></
DataGridActionButton
><
DataGridActionButton
label=
{
`编辑 ${model.modelName}`
}
onPress=
{
()
=>
openModelDialog
(
model
)
}
><
Edit
/></
DataGridActionButton
></
div
>,
cell
:
(
model
)
=>
<
div
className=
"flex items-center gap-2"
><
DataGridActionButton
label=
{
`查看 ${model.modelName}`
}
onPress=
{
()
=>
history
.
push
(
`/models/${model.id}/batches`
)
}
><
Eye
/></
DataGridActionButton
><
DataGridActionButton
label=
{
`编辑 ${model.modelName}`
}
onPress=
{
()
=>
openModelDialog
(
model
)
}
><
Edit
/></
DataGridActionButton
></
div
>,
},
},
],
[
groups
]);
],
[
groups
]);
...
@@ -205,9 +239,9 @@ export default function Models() {
...
@@ -205,9 +239,9 @@ export default function Models() {
setIsGroupDialogOpen
(
true
);
setIsGroupDialogOpen
(
true
);
}
}
function
openEditGroup
()
{
function
openEditGroup
(
group
=
selectedGroup
)
{
if
(
!
selectedG
roup
)
return
;
if
(
!
g
roup
)
return
;
setGroupForm
({
recordName
:
selectedGroup
.
recordName
,
groupName
:
selectedGroup
.
groupName
,
parentGroupId
:
selectedG
roup
.
parentGroupId
});
setGroupForm
({
recordName
:
group
.
recordName
,
groupName
:
group
.
groupName
,
parentGroupId
:
g
roup
.
parentGroupId
});
setIsGroupDialogOpen
(
true
);
setIsGroupDialogOpen
(
true
);
}
}
...
@@ -233,19 +267,21 @@ export default function Models() {
...
@@ -233,19 +267,21 @@ export default function Models() {
}
}
async
function
handleDeleteGroup
()
{
async
function
handleDeleteGroup
()
{
if
(
!
selectedGroup
)
return
;
const
group
=
deleteTargetGroup
||
selectedGroup
;
const
hasChildren
=
groups
.
some
((
group
)
=>
group
.
parentGroupId
===
selectedGroup
.
id
);
if
(
!
group
)
return
;
const
hasModels
=
models
.
some
((
model
)
=>
model
.
groupId
===
selectedGroup
.
id
);
const
hasChildren
=
groups
.
some
((
item
)
=>
item
.
parentGroupId
===
group
.
id
);
const
hasModels
=
models
.
some
((
model
)
=>
model
.
groupId
===
group
.
id
);
if
(
hasChildren
||
hasModels
)
{
if
(
hasChildren
||
hasModels
)
{
setError
(
'请先迁移当前分组中的子分组和模型。'
);
setError
(
'请先迁移当前分组中的子分组和模型。'
);
return
;
return
;
}
}
try
{
try
{
await
deleteModelGroup
(
selectedG
roup
);
await
deleteModelGroup
(
g
roup
);
setActiveGroupId
(
ROOT_GROUP_ID
);
setActiveGroupId
(
ROOT_GROUP_ID
);
await
refresh
();
await
refresh
();
setNotice
(
'空分组已删除。'
);
setNotice
(
'空分组已删除。'
);
setIsDeleteGroupDialogOpen
(
false
);
setIsDeleteGroupDialogOpen
(
false
);
setDeleteTargetGroup
(
null
);
}
catch
(
deleteError
)
{
}
catch
(
deleteError
)
{
setError
(
deleteError
?.
message
||
'模型分组删除失败。'
);
setError
(
deleteError
?.
message
||
'模型分组删除失败。'
);
}
}
...
@@ -427,41 +463,78 @@ export default function Models() {
...
@@ -427,41 +463,78 @@ export default function Models() {
{
!
loading
?
(
{
!
loading
?
(
<>
<>
<
div
className=
"min-w-0 max-w-full"
>
<
div
className=
"grid min-w-0 gap-5 lg:grid-cols-[15rem_minmax(0,1fr)] lg:items-start"
>
<
Tabs
className=
"w-fit max-w-full min-w-0"
selectedKey=
{
activeGroupId
}
variant=
"primary"
onSelectionChange=
{
(
key
)
=>
{
setActiveGroupId
(
String
(
key
));
setPage
(
0
);
}
}
>
<
Surface
className=
"min-w-0 rounded-3xl p-4"
variant=
"default"
>
<
Tabs
.
ListContainer
className=
"w-fit max-w-full min-w-0"
>
<
div
className=
"flex min-w-0 items-center justify-between gap-3"
>
<
Tabs
.
List
aria
-
label=
"模型分组"
className=
"w-max min-w-max"
>
<
h2
className=
"rc-module-title min-w-0 truncate"
>
视图分组
</
h2
>
<
Tabs
.
Tab
className=
"w-auto min-w-max flex-none whitespace-nowrap"
id=
{
ROOT_GROUP_ID
}
>
全部模型
<
Tabs
.
Indicator
/></
Tabs
.
Tab
>
<
Button
aria
-
label=
"新建分组"
isIconOnly
size=
"sm"
variant=
"tertiary"
onPress=
{
()
=>
openCreateGroup
()
}
>
{
groupTabs
.
map
((
group
)
=>
<
Tabs
.
Tab
className=
"w-auto min-w-max flex-none whitespace-nowrap"
id=
{
group
.
value
}
key=
{
group
.
value
}
>
{
group
.
label
}
<
Tabs
.
Indicator
/></
Tabs
.
Tab
>)
}
<
PlusIcon
/>
</
Tabs
.
List
>
</
Button
>
</
Tabs
.
ListContainer
>
</
Tabs
>
</
div
>
<
section
className=
"w-full min-w-0 space-y-4"
>
<
div
className=
"flex min-w-0 flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center"
>
<
div
className=
"w-full min-w-0 flex-none sm:w-80 lg:w-96"
>
<
SearchInput
value=
{
keyword
}
onChange=
{
(
value
)
=>
{
setKeyword
(
value
);
setPage
(
0
);
}
}
placeholder=
"搜索模型名称、编码、说明或标签"
variant=
"primary"
/>
</
div
>
</
div
>
<
div
className=
"flex min-w-0 flex-1 flex-wrap items-center justify-end gap-2"
>
<
div
className=
"mt-4 min-w-0 overflow-x-auto"
>
{
selectedGroup
?
<
Button
size=
"sm"
variant=
"secondary"
onPress=
{
openEditGroup
}
>
编辑分组
</
Button
>
:
null
}
<
FileTree
.
Root
{
selectedGroup
?
<
Button
size=
"sm"
variant=
"danger-soft"
onPress=
{
()
=>
setIsDeleteGroupDialogOpen
(
true
)
}
>
删除分组
</
Button
>
:
null
}
aria
-
label=
"模型分组"
<
Button
size=
"sm"
variant=
"secondary"
onPress=
{
()
=>
openCreateGroup
()
}
>
新建分组
</
Button
>
className=
"min-w-max"
<
Button
size=
"sm"
variant=
"primary"
onPress=
{
openSyncDialog
}
>
同步模型数据
</
Button
>
expandedKeys=
{
expandedGroupIds
}
selectedKeys=
{
new
Set
([
activeGroupId
])
}
selectionBehavior=
"replace"
selectionMode=
"single"
showGuideLines=
"hover"
size=
"md"
onExpandedChange=
{
setExpandedGroupIds
}
onSelectionChange=
{
(
keys
)
=>
{
if
(
keys
===
'all'
)
return
;
const
nextKey
=
[...
keys
][
0
];
if
(
nextKey
===
undefined
)
return
;
setActiveGroupId
(
String
(
nextKey
));
setPage
(
0
);
}
}
>
<
FileTree
.
Item
className=
{
groupTreeItemClassName
}
hasChildItems=
{
groupTree
.
length
>
0
}
icon=
{
<
FolderOpenIcon
/>
}
id=
{
ROOT_GROUP_ID
}
textValue=
"全部模型"
title=
"全部模型"
>
{
groupTree
.
length
?
(
<
GroupTreeItems
nodes=
{
groupTree
}
onEditGroup=
{
openEditGroup
}
onRequestDelete=
{
(
group
)
=>
{
setDeleteTargetGroup
(
group
);
setIsDeleteGroupDialogOpen
(
true
);
}
}
/>
)
:
null
}
</
FileTree
.
Item
>
</
FileTree
.
Root
>
</
div
>
</
div
>
</
div
>
</
Surface
>
<
DataGrid
aria
-
label=
"模型列表"
columns=
{
modelColumns
}
contentClassName=
"min-w-max"
data=
{
visibleModels
}
getRowId=
{
(
model
)
=>
model
.
id
}
renderEmptyState=
{
()
=>
<
EmptyCollection
title=
"当前分组还没有模型"
description=
"点击“同步模型数据”,从外部模型与批次列表中选择一项完成首次同步。"
action=
{
<
Button
variant=
"primary"
onPress=
{
openSyncDialog
}
>
同步模型数据
</
Button
>
}
/>
}
verticalAlign=
"middle"
/>
{
filteredModels
.
length
>
0
?
(
<
section
className=
"w-full min-w-0 space-y-4"
>
<
BusinessPagination
<
div
className=
"flex min-w-0 flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center"
>
page=
{
page
+
1
}
<
div
className=
"w-full min-w-0 flex-none sm:w-80 lg:w-96"
>
pageSize=
{
pageSize
}
<
SearchInput
value=
{
keyword
}
onChange=
{
(
value
)
=>
{
setKeyword
(
value
);
setPage
(
0
);
}
}
placeholder=
"搜索模型名称、编码、说明或标签"
variant=
"primary"
/>
pageSizeOptions=
{
PAGE_SIZE_OPTIONS
}
</
div
>
total=
{
filteredModels
.
length
}
<
div
className=
"flex min-w-0 flex-1 flex-wrap items-center justify-end gap-2"
>
onPageChange=
{
(
nextPage
)
=>
setPage
(
nextPage
-
1
)
}
<
Button
size=
"sm"
variant=
"primary"
onPress=
{
openSyncDialog
}
>
同步模型数据
</
Button
>
onPageSizeChange=
{
(
nextPageSize
)
=>
{
setPageSize
(
nextPageSize
);
setPage
(
0
);
}
}
</
div
>
/>
</
div
>
)
:
null
}
<
DataGrid
aria
-
label=
"模型列表"
columns=
{
modelColumns
}
contentClassName=
"min-w-max"
data=
{
visibleModels
}
getRowId=
{
(
model
)
=>
model
.
id
}
renderEmptyState=
{
()
=>
<
EmptyCollection
title=
"当前分组还没有模型"
description=
"点击“同步模型数据”,从外部模型与批次列表中选择一项完成首次同步。"
action=
{
<
Button
variant=
"primary"
onPress=
{
openSyncDialog
}
>
同步模型数据
</
Button
>
}
/>
}
verticalAlign=
"middle"
/>
</
section
>
{
filteredModels
.
length
>
0
?
(
<
BusinessPagination
page=
{
page
+
1
}
pageSize=
{
pageSize
}
pageSizeOptions=
{
PAGE_SIZE_OPTIONS
}
total=
{
filteredModels
.
length
}
onPageChange=
{
(
nextPage
)
=>
setPage
(
nextPage
-
1
)
}
onPageSizeChange=
{
(
nextPageSize
)
=>
{
setPageSize
(
nextPageSize
);
setPage
(
0
);
}
}
/>
)
:
null
}
</
section
>
</
div
>
</>
</>
)
:
null
}
)
:
null
}
</
div
>
</
div
>
...
@@ -485,8 +558,8 @@ export default function Models() {
...
@@ -485,8 +558,8 @@ export default function Models() {
<
AlertDialog
.
Container
placement=
"center"
size=
"md"
>
<
AlertDialog
.
Container
placement=
"center"
size=
"md"
>
<
AlertDialog
.
Dialog
className=
"xy-modal-dialog"
>
<
AlertDialog
.
Dialog
className=
"xy-modal-dialog"
>
<
AlertDialog
.
Header
><
AlertDialog
.
Icon
status=
"danger"
/><
AlertDialog
.
Heading
>
删除模型分组
</
AlertDialog
.
Heading
></
AlertDialog
.
Header
>
<
AlertDialog
.
Header
><
AlertDialog
.
Icon
status=
"danger"
/><
AlertDialog
.
Heading
>
删除模型分组
</
AlertDialog
.
Heading
></
AlertDialog
.
Header
>
<
AlertDialog
.
Body
>
{
`确认删除空分组“${selectedGroup?.groupName || ''}”吗?此操作不会删除模型或批次。`
}
</
AlertDialog
.
Body
>
<
AlertDialog
.
Body
>
{
`确认删除空分组“${
deleteTargetGroup?.groupName ||
selectedGroup?.groupName || ''}”吗?此操作不会删除模型或批次。`
}
</
AlertDialog
.
Body
>
<
AlertDialog
.
Footer
><
Button
variant=
"secondary"
onPress=
{
()
=>
setIsDeleteGroupDialogOpen
(
false
)
}
>
取消
</
Button
><
Button
variant=
"danger"
onPress=
{
handleDeleteGroup
}
>
确认删除
</
Button
></
AlertDialog
.
Footer
>
<
AlertDialog
.
Footer
><
Button
variant=
"secondary"
onPress=
{
()
=>
{
setIsDeleteGroupDialogOpen
(
false
);
setDeleteTargetGroup
(
null
);
}
}
>
取消
</
Button
><
Button
variant=
"danger"
onPress=
{
handleDeleteGroup
}
>
确认删除
</
Button
></
AlertDialog
.
Footer
>
</
AlertDialog
.
Dialog
>
</
AlertDialog
.
Dialog
>
</
AlertDialog
.
Container
>
</
AlertDialog
.
Container
>
</
AlertDialog
.
Backdrop
>
</
AlertDialog
.
Backdrop
>
...
...
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