diff --git a/backend/internal/handler/instance_group.go b/backend/internal/handler/instance_group.go index 3e443a2..bcffce1 100644 --- a/backend/internal/handler/instance_group.go +++ b/backend/internal/handler/instance_group.go @@ -25,15 +25,55 @@ func GetInstanceGroup(c *gin.Context) { // POST /api/v1/instance-groups func CreateInstanceGroup(c *gin.Context) { - var group model.InstanceGroup - if err := c.ShouldBindJSON(&group); err != nil { + var input struct { + Name string `json:"name"` + Description *string `json:"description"` + DBType string `json:"db_type"` + IsActive *bool `json:"is_active"` + ReadonlyInstanceIDs []int `json:"readonly_instance_ids"` + WriteInstanceIDs []int `json:"write_instance_ids"` + } + if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()}) return } + + desc := "" + if input.Description != nil { + desc = *input.Description + } + isActive := true + if input.IsActive != nil { + isActive = *input.IsActive + } + dbType := input.DBType + if dbType == "" { + dbType = "all" + } + + group := model.InstanceGroup{ + Name: input.Name, + Description: &desc, + DBType: dbType, + IsActive: &isActive, + } if err := model.DB.Create(&group).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": err.Error()}) return } + + // Create instance members + for _, iid := range input.ReadonlyInstanceIDs { + model.DB.Create(&model.InstanceGroupMember{ + GroupID: group.ID, InstanceID: iid, AccessType: "readonly", + }) + } + for _, iid := range input.WriteInstanceIDs { + model.DB.Create(&model.InstanceGroupMember{ + GroupID: group.ID, InstanceID: iid, AccessType: "write", + }) + } + c.JSON(http.StatusCreated, enrichGroup(group)) } diff --git a/frontend/src/pages/InstanceGroupPage.tsx b/frontend/src/pages/InstanceGroupPage.tsx index d27fd64..f88dd77 100644 --- a/frontend/src/pages/InstanceGroupPage.tsx +++ b/frontend/src/pages/InstanceGroupPage.tsx @@ -257,10 +257,13 @@ export default function InstanceGroupPage() { const close = () => { setShowCreateModal(false); setShowEditModal(false); resetForm(); }; const submit = mode === 'create' ? handleCreate : handleEdit; return show ? ( -
-
e.stopPropagation()}> -

{mode === 'create' ? '新建权限策略' : '编辑权限策略'}

-
+
+
e.stopPropagation()}> +
+

{mode === 'create' ? '新建权限策略' : '编辑权限策略'}

+ +
+
@@ -293,8 +296,8 @@ export default function InstanceGroupPage() {
- - +
@@ -438,9 +441,13 @@ export default function InstanceGroupPage() { {/* User Modal */} {showUserModal && ( -
-
e.stopPropagation()}> -

关联用户

+
+
e.stopPropagation()}> +
+

关联用户

+ +
+
setUserSearch(e.target.value)} placeholder="搜索用户..." className="w-full pl-10 pr-4 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none" /> @@ -456,9 +463,10 @@ export default function InstanceGroupPage() { ))}
- - + +
+
{/* end px-6 py-4 */}
)}