|
|
@@ -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
|
|
|
+}
|