Files
yunzerwebsiteallinone/go/controllers/backend_organization_params.go
T
2026-08-27 21:25:39 +08:00

290 lines
6.9 KiB
Go

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
}