From ed582e30e65e07181face90cf82ff7aec0fa10bc Mon Sep 17 00:00:00 2001 From: logan Date: Wed, 27 May 2026 02:38:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9D=83=E9=99=90=E7=BB=84=E7=A9=BF?= =?UTF-8?q?=E6=A2=AD=E6=A1=86=E4=BF=9D=E5=AD=98=E4=B8=8D=E7=94=9F=E6=95=88?= =?UTF-8?q?=20+=20=E5=BC=B9=E6=A1=86=E5=B8=83=E5=B1=80=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 后端 CreateInstanceGroup 改用 input struct 接收 readonly_instance_ids/write_instance_ids - 旧代码直接绑定 model.InstanceGroup(不含关联ID字段),导致穿梭框数据被丢弃 - 新代码解析后写入 instance_group_members 表 - 与 UpdateInstanceGroup 保持一致的逻辑 2. 弹框布局修复 - z-50 → z-[100] 避免被顶部栏遮挡 - flex-col + overflow-y-auto 独立滚动区域 - 添加 header bar + X 关闭按钮 - 背景加 backdrop-blur-sm 3. 全局排查确认:其他 handler 均使用 input struct 或 map,无同类问题 --- backend/internal/handler/instance_group.go | 44 +++++++++++++++++++++- frontend/src/pages/InstanceGroupPage.tsx | 30 +++++++++------ 2 files changed, 61 insertions(+), 13 deletions(-) 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 */}
)}