refactor: 重构后端架构为 go-zero 框架,优化项目结构

主要变更:
- 采用 go-zero 框架替代 Gin,提升开发效率
- 重构项目结构,API 文件模块化组织
- 将 model 移至 api/internal/model 目录
- 移除 common 包,改为标准 pkg 目录结构
- 实现统一的仓储模式,支持配置驱动数据库切换
- 简化测试策略,专注 API 集成测试
- 更新 CLAUDE.md 文档,提供详细的开发指导

技术栈更新:
- 框架: Gin → go-zero v1.6.0+
- 代码生成: 引入 goctl 工具
- 架构模式: 四层架构 → go-zero 三层架构 (Handler→Logic→Model)
- 项目布局: 遵循 Go 社区标准和 go-zero 最佳实践
This commit is contained in:
xujiang
2025-07-10 15:05:52 +08:00
parent a2f2f66f88
commit 39a42695d3
52 changed files with 6047 additions and 2349 deletions

View File

@ -0,0 +1,128 @@
package utils
import (
"regexp"
"strings"
"unicode"
)
// IsValidEmail 验证邮箱格式
func IsValidEmail(email string) bool {
emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
return emailRegex.MatchString(email)
}
// IsValidUsername 验证用户名格式
func IsValidUsername(username string) bool {
// 用户名长度3-20只能包含字母、数字、下划线
if len(username) < 3 || len(username) > 20 {
return false
}
usernameRegex := regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
return usernameRegex.MatchString(username)
}
// IsValidPassword 验证密码强度
func IsValidPassword(password string) bool {
// 密码长度至少6位
if len(password) < 6 {
return false
}
// 检查是否包含字母和数字
hasLetter := false
hasNumber := false
for _, char := range password {
if unicode.IsLetter(char) {
hasLetter = true
}
if unicode.IsNumber(char) {
hasNumber = true
}
}
return hasLetter && hasNumber
}
// IsValidSlug 验证slug格式
func IsValidSlug(slug string) bool {
// slug只能包含小写字母、数字和连字符
if len(slug) == 0 || len(slug) > 100 {
return false
}
slugRegex := regexp.MustCompile(`^[a-z0-9-]+$`)
return slugRegex.MatchString(slug) && !strings.HasPrefix(slug, "-") && !strings.HasSuffix(slug, "-")
}
// IsValidHexColor 验证十六进制颜色代码
func IsValidHexColor(color string) bool {
colorRegex := regexp.MustCompile(`^#[a-fA-F0-9]{6}$`)
return colorRegex.MatchString(color)
}
// IsValidURL 验证URL格式
func IsValidURL(url string) bool {
urlRegex := regexp.MustCompile(`^https?://[^\s/$.?#].[^\s]*$`)
return urlRegex.MatchString(url)
}
// SanitizeString 清理字符串移除HTML标签和特殊字符
func SanitizeString(input string) string {
// 移除HTML标签
htmlRegex := regexp.MustCompile(`<[^>]*>`)
cleaned := htmlRegex.ReplaceAllString(input, "")
// 移除多余的空白字符
whitespaceRegex := regexp.MustCompile(`\s+`)
cleaned = whitespaceRegex.ReplaceAllString(cleaned, " ")
return strings.TrimSpace(cleaned)
}
// ValidateImageFormat 验证图片格式
func ValidateImageFormat(filename string) bool {
allowedExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".webp"}
lowerFilename := strings.ToLower(filename)
for _, ext := range allowedExtensions {
if strings.HasSuffix(lowerFilename, ext) {
return true
}
}
return false
}
// ValidateFileSize 验证文件大小(字节)
func ValidateFileSize(size int64, maxSizeMB int64) bool {
maxSizeBytes := maxSizeMB * 1024 * 1024
return size <= maxSizeBytes && size > 0
}
// NormalizeString 标准化字符串(去空格、转小写)
func NormalizeString(s string) string {
return strings.ToLower(strings.TrimSpace(s))
}
// ContainsOnlyASCII 检查字符串是否只包含ASCII字符
func ContainsOnlyASCII(s string) bool {
for _, char := range s {
if char > 127 {
return false
}
}
return true
}
// Contains 检查切片是否包含指定元素
func Contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}