主要变更: - 将所有CSS文件迁移到Less预处理器 - 配置Vite支持Less编译 - 使用Less变量、嵌套和父选择器优化样式代码 - 添加用户注册和登录功能 - 实现用户认证中间件和保护路由 - 新增Profile和Login页面 - 添加底部导航栏组件TabBarLayout - 更新CLAUDE.md为中文文档 技术改进: - Less变量统一管理主题色和间距 - CSS嵌套提高代码可读性和可维护性 - 模块化样式组织更清晰 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
191 lines
4.0 KiB
Go
191 lines
4.0 KiB
Go
package handlers
|
||
|
||
import (
|
||
"ankao/internal/models"
|
||
"crypto/sha256"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"os"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
const usersFilePath = "users.json"
|
||
|
||
// loadUsers 从JSON文件加载用户数据
|
||
func loadUsers() (models.UserData, error) {
|
||
file, err := os.ReadFile(usersFilePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取用户文件失败: %w", err)
|
||
}
|
||
|
||
var users models.UserData
|
||
if err := json.Unmarshal(file, &users); err != nil {
|
||
return nil, fmt.Errorf("解析用户数据失败: %w", err)
|
||
}
|
||
|
||
return users, nil
|
||
}
|
||
|
||
// saveUsers 保存用户数据到JSON文件
|
||
func saveUsers(users models.UserData) error {
|
||
data, err := json.MarshalIndent(users, "", " ")
|
||
if err != nil {
|
||
return fmt.Errorf("序列化用户数据失败: %w", err)
|
||
}
|
||
|
||
if err := os.WriteFile(usersFilePath, data, 0644); err != nil {
|
||
return fmt.Errorf("保存用户文件失败: %w", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// generateToken 生成简单的token(实际项目应使用JWT)
|
||
func generateToken(username string) string {
|
||
data := fmt.Sprintf("%s:%d", username, time.Now().Unix())
|
||
hash := sha256.Sum256([]byte(data))
|
||
return hex.EncodeToString(hash[:])
|
||
}
|
||
|
||
// Login 用户登录处理
|
||
func Login(c *gin.Context) {
|
||
var req models.LoginRequest
|
||
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"success": false,
|
||
"message": "请求参数错误",
|
||
"error": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 加载用户数据
|
||
users, err := loadUsers()
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{
|
||
"success": false,
|
||
"message": "服务器错误",
|
||
"error": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证用户
|
||
user, exists := users[req.Username]
|
||
if !exists {
|
||
c.JSON(http.StatusUnauthorized, gin.H{
|
||
"success": false,
|
||
"message": "用户名或密码错误",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证密码
|
||
if user.Password != req.Password {
|
||
c.JSON(http.StatusUnauthorized, gin.H{
|
||
"success": false,
|
||
"message": "用户名或密码错误",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 生成token
|
||
token := generateToken(req.Username)
|
||
|
||
// 返回用户信息(不包含密码)
|
||
userInfo := models.UserInfoResponse{
|
||
Username: req.Username,
|
||
Avatar: user.Avatar,
|
||
Nickname: user.Nickname,
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": true,
|
||
"message": "登录成功",
|
||
"data": models.LoginResponse{
|
||
Token: token,
|
||
User: userInfo,
|
||
},
|
||
})
|
||
}
|
||
|
||
// Register 用户注册处理
|
||
func Register(c *gin.Context) {
|
||
var req models.RegisterRequest
|
||
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"success": false,
|
||
"message": "请求参数错误",
|
||
"error": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 加载现有用户数据
|
||
users, err := loadUsers()
|
||
if err != nil {
|
||
// 如果文件不存在,创建新的用户数据
|
||
users = make(models.UserData)
|
||
}
|
||
|
||
// 检查用户名是否已存在
|
||
if _, exists := users[req.Username]; exists {
|
||
c.JSON(http.StatusBadRequest, gin.H{
|
||
"success": false,
|
||
"message": "用户名已存在",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 创建新用户
|
||
newUser := models.User{
|
||
Username: req.Username,
|
||
Password: req.Password, // 实际项目应该加密存储
|
||
Nickname: req.Nickname,
|
||
Avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=" + req.Username, // 使用用户名生成默认头像
|
||
}
|
||
|
||
// 如果没有提供昵称,使用用户名
|
||
if newUser.Nickname == "" {
|
||
newUser.Nickname = req.Username
|
||
}
|
||
|
||
// 添加新用户
|
||
users[req.Username] = newUser
|
||
|
||
// 保存用户数据
|
||
if err := saveUsers(users); err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{
|
||
"success": false,
|
||
"message": "注册失败",
|
||
"error": err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 生成token
|
||
token := generateToken(req.Username)
|
||
|
||
// 返回用户信息
|
||
userInfo := models.UserInfoResponse{
|
||
Username: newUser.Username,
|
||
Avatar: newUser.Avatar,
|
||
Nickname: newUser.Nickname,
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"success": true,
|
||
"message": "注册成功",
|
||
"data": models.LoginResponse{
|
||
Token: token,
|
||
User: userInfo,
|
||
},
|
||
})
|
||
}
|