浏览代码

编辑任务

urbanu 1 月之前
父节点
当前提交
0c98a2efec
共有 1 个文件被更改,包括 65 次插入2 次删除
  1. 65 2
      service/base/query_handle_base.go

+ 65 - 2
service/base/query_handle_base.go

@@ -5,6 +5,7 @@ import (
 	"github.com/gin-gonic/gin"
 	"go_server/model/common/response"
 	"gorm.io/gorm"
+	"reflect"
 )
 
 // gin 封装模型curd处理
@@ -62,15 +63,17 @@ func (*ModelBaseHandler[T]) UpdateOne(c *gin.Context, db *gorm.DB) {
 		response.Resp(c, err.Error())
 		return
 	}
-	// 将 req.Data 转换为结构体,以便 GORM 能正确映射 json tag 到数据库列名
+	// 构建 json tag -> 数据库列名 的映射,用 map 更新以支持零值字段
 	updateData := new(T)
 	body, _ := json.Marshal(req.Data)
 	if err := json.Unmarshal(body, updateData); err != nil {
 		response.Resp(c, err.Error())
 		return
 	}
+	// 将 struct 转为 map,保留零值字段
+	updateMap := structToMapWithZero(updateData, req.Data)
 	dbEx := db.Model(&tempInfo).Where("id", req.Id).
-		Updates(updateData)
+		Updates(updateMap)
 	if dbEx.Error != nil {
 		response.Resp(c, dbEx.Error.Error())
 		return
@@ -147,3 +150,63 @@ func (*ModelBaseHandler[T]) List(c *gin.Context, db *gorm.DB) {
 	response.Resp(c, resp)
 	return
 }
+
+// structToMapWithZero 将 struct 转为 map,只包含前端实际传递的字段(含零值)
+// dataMap 是前端传来的原始 map,用于判断哪些字段是前端实际传递的
+func structToMapWithZero(s any, dataMap map[string]any) map[string]any {
+	result := make(map[string]any)
+	v := reflect.ValueOf(s)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+	t := v.Type()
+	for i := 0; i < t.NumField(); i++ {
+		field := t.Field(i)
+		jsonTag := field.Tag.Get("json")
+		if jsonTag == "" || jsonTag == "-" {
+			continue
+		}
+		// 去掉 omitempty 等选项
+		if idx := len(jsonTag); idx > 0 {
+			parts := jsonTag
+			for j := 0; j < len(parts); j++ {
+				if parts[j] == ',' {
+					jsonTag = parts[:j]
+					break
+				}
+			}
+		}
+		// 只更新前端实际传递的字段
+		if _, exists := dataMap[jsonTag]; !exists {
+			continue
+		}
+		// 获取 gorm column tag 作为数据库列名
+		gormTag := field.Tag.Get("gorm")
+		colName := ""
+		if gormTag != "" {
+			for _, part := range splitGormTag(gormTag) {
+				if len(part) > 7 && part[:7] == "column:" {
+					colName = part[7:]
+					break
+				}
+			}
+		}
+		if colName == "" {
+			colName = jsonTag
+		}
+		result[colName] = v.Field(i).Interface()
+	}
+	return result
+}
+
+func splitGormTag(tag string) []string {
+	var parts []string
+	start := 0
+	for i := 0; i <= len(tag); i++ {
+		if i == len(tag) || tag[i] == ';' {
+			parts = append(parts, tag[start:i])
+			start = i + 1
+		}
+	}
+	return parts
+}