package controllers import ( "encoding/json" "strconv" "strings" "time" ) // 本文件包含组织架构模块的请求参数解析工具。 // 前端存在 JSON、form-urlencoded 与 multipart/form-data 三种提交方式, // 因此每个取值函数都先读 JSON body,再回退到表单参数。 func (c *BackendOrganizationController) parseJSONBody() map[string]interface{} { body := map[string]interface{}{} contentType := strings.ToLower(c.Ctx.Input.Header("Content-Type")) if !strings.Contains(contentType, "json") { return body } if len(c.Ctx.Input.RequestBody) == 0 { return body } _ = json.Unmarshal(c.Ctx.Input.RequestBody, &body) return body } // ensureFormParsed 在读取表单参数前确保请求体已被解析。 func (c *BackendOrganizationController) ensureFormParsed() { if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil { _ = c.Ctx.Request.ParseMultipartForm(32 << 20) } } func (c *BackendOrganizationController) getStringValue(body map[string]interface{}, keys ...string) (string, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case string: return val, true case float64: return strconv.FormatFloat(val, 'f', -1, 64), true case bool: return strconv.FormatBool(val), true case nil: return "", true } } c.ensureFormParsed() if val := c.GetString(key); val != "" { return val, true } } return "", false } func (c *BackendOrganizationController) getIntValue(body map[string]interface{}, keys ...string) (int, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case float64: return int(val), true case int: return val, true case bool: return boolInt(val), true case string: trimmed := strings.TrimSpace(val) if trimmed == "" { return 0, true } parsed, err := strconv.Atoi(trimmed) return parsed, err == nil } } c.ensureFormParsed() if val := c.GetString(key); val != "" { parsed, err := strconv.Atoi(strings.TrimSpace(val)) return parsed, err == nil } } return 0, false } func (c *BackendOrganizationController) getUintValue(body map[string]interface{}, keys ...string) (uint, bool) { v, ok := c.getIntValue(body, keys...) if !ok || v < 0 { return 0, ok && v >= 0 } return uint(v), true } func (c *BackendOrganizationController) getUint64Value(body map[string]interface{}, keys ...string) (uint64, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case float64: if val < 0 { return 0, false } return uint64(val), true case int: if val < 0 { return 0, false } return uint64(val), true case nil: return 0, true case string: trimmed := strings.TrimSpace(val) if trimmed == "" { return 0, true } parsed, err := strconv.ParseUint(trimmed, 10, 64) return parsed, err == nil } } c.ensureFormParsed() if val := c.GetString(key); val != "" { parsed, err := strconv.ParseUint(strings.TrimSpace(val), 10, 64) return parsed, err == nil } } return 0, false } func (c *BackendOrganizationController) getBoolValue(body map[string]interface{}, keys ...string) (bool, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case bool: return val, true case float64: return val != 0, true case string: trimmed := strings.ToLower(strings.TrimSpace(val)) switch trimmed { case "1", "true", "yes", "on": return true, true case "0", "false", "no", "off", "": return false, true } } } c.ensureFormParsed() if val := c.GetString(key); val != "" { switch strings.ToLower(strings.TrimSpace(val)) { case "1", "true", "yes", "on": return true, true case "0", "false", "no", "off": return false, true } } } return false, false } // getUint64Slice 解析 ID 数组,兼容 JSON 数组与逗号分隔字符串。 func (c *BackendOrganizationController) getUint64Slice(body map[string]interface{}, keys ...string) []uint64 { result := make([]uint64, 0) seen := map[uint64]bool{} appendID := func(id uint64) { if id == 0 || seen[id] { return } seen[id] = true result = append(result, id) } for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case []interface{}: for _, item := range val { switch num := item.(type) { case float64: appendID(uint64(num)) case string: if parsed, err := strconv.ParseUint(strings.TrimSpace(num), 10, 64); err == nil { appendID(parsed) } } } case string: for _, part := range strings.Split(val, ",") { if parsed, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64); err == nil { appendID(parsed) } } case float64: appendID(uint64(val)) } } if len(result) > 0 { return result } c.ensureFormParsed() if raw := c.GetString(key); raw != "" { for _, part := range strings.Split(raw, ",") { if parsed, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64); err == nil { appendID(parsed) } } } if len(result) > 0 { return result } } return result } func (c *BackendOrganizationController) getUintSlice(body map[string]interface{}, keys ...string) []uint { ids := c.getUint64Slice(body, keys...) result := make([]uint, 0, len(ids)) for _, id := range ids { result = append(result, uint(id)) } return result } func (c *BackendOrganizationController) pathUint(name string) (uint, bool) { id, err := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64) return uint(id), err == nil && id > 0 } func (c *BackendOrganizationController) pathUint64(name string) (uint64, bool) { id, err := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64) return id, err == nil && id > 0 } func (c *BackendOrganizationController) nowString() string { return time.Now().Format("2006-01-02 15:04:05") } // --------------------------------------------------------------------------- // 与 ORM 交互的通用小工具 // --------------------------------------------------------------------------- func strPtrIfNotEmpty(v string) *string { v = strings.TrimSpace(v) if v == "" { return nil } return &v } // nullableString 空字符串写入 NULL,便于统一区分“未填写”与“空值”。 func nullableString(v string) interface{} { v = strings.TrimSpace(v) if v == "" { return nil } return v } func nullableUint64(v uint64) interface{} { if v == 0 { return nil } return v } func derefString(v *string) string { if v == nil { return "" } return *v } func boolInt(v bool) int { if v { return 1 } return 0 } func parseDatePtr(v string) *time.Time { v = strings.TrimSpace(v) if v == "" { return nil } if t, err := time.Parse("2006-01-02", v); err == nil { return &t } if t, err := time.Parse("2006-01-02 15:04:05", v); err == nil { return &t } return nil }