126 lines
2.5 KiB
Go
126 lines
2.5 KiB
Go
package commonservice
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"nl-pms-api/internal/config"
|
||
)
|
||
|
||
// AdminUserID 是 code_count 体系的超级管理员账号(users.id=1)。
|
||
const AdminUserID int64 = 1
|
||
|
||
// ParseID 把字符串解析为非负 int64;非法或负数视为 0。
|
||
func ParseID(s string) int64 {
|
||
n, _ := strconv.ParseInt(s, 10, 64)
|
||
if n < 0 {
|
||
return 0
|
||
}
|
||
return n
|
||
}
|
||
|
||
// Clip 按字节截断字符串到最多 n 字节。
|
||
func Clip(s string, n int) string {
|
||
if len(s) > n {
|
||
return s[:n]
|
||
}
|
||
return s
|
||
}
|
||
|
||
// ClipRunes 按 rune 截断到最多 n 个字符。
|
||
func ClipRunes(s string, n int) string {
|
||
r := []rune(strings.TrimSpace(s))
|
||
if len(r) > n {
|
||
return string(r[:n])
|
||
}
|
||
return string(r)
|
||
}
|
||
|
||
// NowRFC 返回当前 UTC 的 RFC3339 时间串(与 view 库惯例一致)。
|
||
func NowRFC() string {
|
||
return time.Now().UTC().Format(time.RFC3339)
|
||
}
|
||
|
||
// PublicURL 拼接文件公开访问地址:优先配置的 base_url,否则用 requestHost(可含 scheme://host)。
|
||
func PublicURL(cfg *config.Config, requestHost, name string) string {
|
||
base := cfg.BaseURL
|
||
if base == "" {
|
||
base = strings.TrimRight(requestHost, "/")
|
||
if !strings.Contains(base, "://") {
|
||
base = "http://" + base
|
||
}
|
||
}
|
||
return base + "/files/" + name
|
||
}
|
||
|
||
// NormalizeKind 规范化文件用途:avatar | content,其余为空。
|
||
func NormalizeKind(k string) string {
|
||
if k == "avatar" || k == "content" {
|
||
return k
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// StoredName 生成不可枚举的存储相对路径(日期目录 + 128 位随机 hex)。
|
||
func StoredName(ext string) string {
|
||
b := make([]byte, 16)
|
||
_, _ = rand.Read(b)
|
||
return time.Now().UTC().Format("2006/01/02") + "/" + hex.EncodeToString(b) + ext
|
||
}
|
||
|
||
// MapStr 从通用 JSON map 取字符串字段。
|
||
func MapStr(m map[string]any, key string) string {
|
||
v, ok := m[key]
|
||
if !ok || v == nil {
|
||
return ""
|
||
}
|
||
switch x := v.(type) {
|
||
case string:
|
||
return x
|
||
case []byte:
|
||
return string(x)
|
||
case float64:
|
||
if x == float64(int64(x)) {
|
||
return strconv.FormatInt(int64(x), 10)
|
||
}
|
||
return strconv.FormatFloat(x, 'f', -1, 64)
|
||
case bool:
|
||
if x {
|
||
return "1"
|
||
}
|
||
return "0"
|
||
default:
|
||
return fmt.Sprint(x)
|
||
}
|
||
}
|
||
|
||
// MapInt64 从通用 JSON map 取 int64 字段。
|
||
func MapInt64(m map[string]any, key string) int64 {
|
||
v, ok := m[key]
|
||
if !ok || v == nil {
|
||
return 0
|
||
}
|
||
switch x := v.(type) {
|
||
case float64:
|
||
return int64(x)
|
||
case int64:
|
||
return x
|
||
case int:
|
||
return int64(x)
|
||
case string:
|
||
n, _ := strconv.ParseInt(x, 10, 64)
|
||
return n
|
||
case bool:
|
||
if x {
|
||
return 1
|
||
}
|
||
return 0
|
||
default:
|
||
return 0
|
||
}
|
||
}
|