package utils import ( "bytes" "crypto/md5" "encoding/base64" "encoding/hex" "fmt" "net" "net/http" "strings" "time" "github.com/tealeg/xlsx" "golang.org/x/crypto/bcrypt" ) // GenerateAdminHashedPassword [管理端]生成密码 func GenerateAdminHashedPassword(password string) (string, error) { salt := "7M&7p7euU=CC" passwordWithSalt := password + salt hashedPassword, err := bcrypt.GenerateFromPassword([]byte(passwordWithSalt), bcrypt.DefaultCost) if err != nil { return "", err } return string(hashedPassword), nil } // VerifyAdminHashedPassword [管理端]验证密码 func VerifyAdminHashedPassword(hashedPassword, password string) bool { salt := "7M&7p7euU=CC" passwordWithSalt := password + salt err := bcrypt.CompareHashAndPassword([]byte(hashedPassword+salt), []byte(passwordWithSalt)) return err == nil } // ToExcel 生成 Excel func ToExcel(titleList []string, dataList []interface{}) []byte { // 生成一个新的文件 file := xlsx.NewFile() // 添加sheet页 sheet, _ := file.AddSheet("Sheet1") // 插入表头 titleRow := sheet.AddRow() for _, v := range titleList { cell := titleRow.AddCell() cell.Value = v } // 插入内容 for _, v := range dataList { row := sheet.AddRow() row.WriteStruct(v, -1) } var buffer bytes.Buffer _ = file.Write(&buffer) return buffer.Bytes() } func MD5(text string) string { hash := md5.New() hash.Write([]byte(text)) hashBytes := hash.Sum(nil) return hex.EncodeToString(hashBytes) } // GetIP 尝试从 HTTP 请求中获取真实的客户端 IP 地址 func GetIP(r *http.Request) string { // 从 X-Forwarded-For 头部获取IP地址 xForwardedFor := r.Header.Get("X-Forwarded-For") if xForwardedFor != "" { // 可能有多个IP地址,通常第一个是客户端的真实IP ips := strings.Split(xForwardedFor, ",") if len(ips) > 0 { return strings.TrimSpace(ips[0]) } } // 如果没有 X-Forwarded-For 头部,尝试从 X-Real-IP 获取 xRealIP := r.Header.Get("X-Real-IP") if xRealIP != "" { return strings.TrimSpace(xRealIP) } // 如果没有代理头部,最后退回到 RemoteAddr ip, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { // 如果处理RemoteAddr出错,返回空字符串 return "" } return ip } // FriendlyTimeAgo 友好时间 func FriendlyTimeAgo(date time.Time) string { now := time.Now() if date.After(now) { return "未来的日期" } diff := now.Sub(date) minutes := int(diff.Minutes()) hours := int(diff.Hours()) days := int(hours / 24) // 小于1分钟 if minutes < 1 { return "刚刚" } // 小于1小时 if hours < 1 { return fmt.Sprintf("%d分钟", minutes) } // 小于1天 if hours < 24 { return fmt.Sprintf("%d小时", hours) } // 小于1周 if days < 7 { return fmt.Sprintf("%d天", days) } // 小于1个月 if days < 30 { return fmt.Sprintf("%d周", days/7) } // 小于1年 if days < 365 { months := int(days / 30) if months < 1 { return fmt.Sprintf("%d天", days) } return fmt.Sprintf("%d个月", months) } // 大于等于1年 years := days / 365 remainingDays := days % 365 months := remainingDays / 30 if months == 0 { return fmt.Sprintf("%d年", years) } return fmt.Sprintf("%d年%d个月", years, months) } // FriendlySubTime 时间相减 func FriendlySubTime(birthday, date time.Time) string { diff := date.Sub(birthday) minutes := int(diff.Minutes()) hours := int(diff.Hours()) days := int(hours / 24) // 小于1分钟 if minutes < 1 { return "刚刚" } // 小于1小时 if hours < 1 { return fmt.Sprintf("%d分钟", minutes) } // 小于1天 if hours < 24 { return fmt.Sprintf("%d小时", hours) } // 小于1周 if days < 7 { return fmt.Sprintf("%d天", days) } // 小于1个月 if days < 30 { return fmt.Sprintf("%d周", days/7) } // 小于1年 if days < 365 { months := int(days / 30) if months < 1 { return fmt.Sprintf("%d天", days) } return fmt.Sprintf("%d个月", months) } // 大于等于1年 years := days / 365 remainingDays := days % 365 months := remainingDays / 30 if months == 0 { return fmt.Sprintf("%d岁", years) } return fmt.Sprintf("%d岁%d个月", years, months) } func XorEncrypt(phone, key string) string { result := make([]byte, len(phone)) for i := 0; i < len(phone); i++ { result[i] = phone[i] ^ key[i%len(key)] } return base64.StdEncoding.EncodeToString(result) } func XorDecrypt(encrypted, key string) (string, error) { data, err := base64.StdEncoding.DecodeString(encrypted) if err != nil { return "", err } result := make([]byte, len(data)) for i := 0; i < len(data); i++ { result[i] = data[i] ^ key[i%len(key)] } return string(result), nil }