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