Files
ai_english/serve/internal/utils/utils.go

223 lines
5.3 KiB
Go
Raw Permalink Normal View History

2025-11-17 13:39:05 +08:00
package utils
import (
"crypto/rand"
"encoding/hex"
"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
)
// HashPassword 对密码进行哈希加密
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bytes), err
}
// CheckPasswordHash 验证密码哈希
func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
// GenerateUUID 生成UUID
func GenerateUUID() string {
return uuid.New().String()
}
// GenerateRandomString 生成指定长度的随机字符串
func GenerateRandomString(length int) (string, error) {
bytes := make([]byte, length/2)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
// IsValidEmail 验证邮箱格式
func IsValidEmail(email string) bool {
pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(email)
}
// IsValidPhone 验证手机号格式(中国大陆)
func IsValidPhone(phone string) bool {
pattern := `^1[3-9]\d{9}$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(phone)
}
// IsStrongPassword 验证密码强度
func IsStrongPassword(password string) bool {
if len(password) < 8 {
return false
}
// 至少包含一个数字
hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password)
// 至少包含一个小写字母
hasLower := regexp.MustCompile(`[a-z]`).MatchString(password)
// 至少包含一个大写字母
hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password)
// 至少包含一个特殊字符
hasSpecial := regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`).MatchString(password)
return hasNumber && hasLower && hasUpper && hasSpecial
}
// GetPaginationParams 从请求中获取分页参数
func GetPaginationParams(c *gin.Context) (page, pageSize int) {
pageStr := c.DefaultQuery("page", "1")
pageSizeStr := c.DefaultQuery("page_size", "20")
page, err := strconv.Atoi(pageStr)
if err != nil || page < 1 {
page = 1
}
pageSize, err = strconv.Atoi(pageSizeStr)
if err != nil || pageSize < 1 || pageSize > 100 {
pageSize = 20
}
return page, pageSize
}
// CalculateOffset 计算数据库查询偏移量
func CalculateOffset(page, pageSize int) int {
return (page - 1) * pageSize
}
// CalculateTotalPages 计算总页数
func CalculateTotalPages(total, pageSize int) int {
if total == 0 {
return 0
}
return (total + pageSize - 1) / pageSize
}
// StringToInt 字符串转整数,带默认值
func StringToInt(str string, defaultValue int) int {
if str == "" {
return defaultValue
}
value, err := strconv.Atoi(str)
if err != nil {
return defaultValue
}
return value
}
// StringToBool 字符串转布尔值,带默认值
func StringToBool(str string, defaultValue bool) bool {
if str == "" {
return defaultValue
}
value, err := strconv.ParseBool(str)
if err != nil {
return defaultValue
}
return value
}
// TrimSpaces 去除字符串前后空格
func TrimSpaces(str string) string {
return strings.TrimSpace(str)
}
// FormatTime 格式化时间
func FormatTime(t time.Time) string {
return t.Format("2006-01-02 15:04:05")
}
// ParseTime 解析时间字符串
func ParseTime(timeStr string) (time.Time, error) {
return time.Parse("2006-01-02 15:04:05", timeStr)
}
// GetUserIDFromContext 从上下文中获取用户ID
func GetUserIDFromContext(c *gin.Context) (int64, bool) {
userID, exists := c.Get("user_id")
if !exists {
return 0, false
}
if id, ok := userID.(int64); ok {
return id, true
}
return 0, false
}
// SetUserIDToContext 设置用户ID到上下文
func SetUserIDToContext(c *gin.Context, userID int64) {
c.Set("user_id", userID)
}
// Int64ToString 将int64转换为string
func Int64ToString(i int64) string {
return strconv.FormatInt(i, 10)
}
// StringToInt64 将string转换为int64
func StringToInt64(str string) (int64, error) {
return strconv.ParseInt(str, 10, 64)
}
// Contains 检查切片是否包含指定元素
func Contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}
// RemoveDuplicates 去除字符串切片中的重复元素
func RemoveDuplicates(slice []string) []string {
keys := make(map[string]bool)
result := []string{}
for _, item := range slice {
if !keys[item] {
keys[item] = true
result = append(result, item)
}
}
return result
}
// GenerateFileName 生成文件名
func GenerateFileName(originalName string) string {
ext := ""
if dotIndex := strings.LastIndex(originalName, "."); dotIndex != -1 {
ext = originalName[dotIndex:]
}
return fmt.Sprintf("%d_%s%s", time.Now().Unix(), GenerateUUID()[:8], ext)
}
// GetClientIP 获取客户端IP地址
func GetClientIP(c *gin.Context) string {
// 尝试从X-Forwarded-For头获取
if ip := c.GetHeader("X-Forwarded-For"); ip != "" {
if index := strings.Index(ip, ","); index != -1 {
return strings.TrimSpace(ip[:index])
}
return strings.TrimSpace(ip)
}
// 尝试从X-Real-IP头获取
if ip := c.GetHeader("X-Real-IP"); ip != "" {
return strings.TrimSpace(ip)
}
// 使用RemoteAddr
return c.ClientIP()
}