更新小程序开发文档,新增2026-03-03的最佳实践记录,优化个人中心类页面的卡片区边距规范,确保一致性与可用性。调整相关页面以反映最新设计稿,提升用户体验与功能一致性。

This commit is contained in:
Alex-larget
2026-03-04 19:06:06 +08:00
parent 7064f82126
commit 5a5f0087d2
66 changed files with 2555 additions and 1059 deletions

View File

@@ -5,8 +5,12 @@ import (
"soul-api/internal/auth"
"soul-api/internal/config"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
// AdminCheck GET /api/admin 鉴权检查JWTAuthorization Bearer 或 Cookie已登录返回 success 或概览占位
@@ -39,7 +43,7 @@ func AdminCheck(c *gin.Context) {
})
}
// AdminLogin POST /api/admin 登录(校验 ADMIN_USERNAME/PASSWORD,返回 JWT前端存 token 并带 Authorization: Bearer
// AdminLogin POST /api/admin 登录(优先校验 admin_users 表,表空时回退 ADMIN_USERNAME/PASSWORD 并自动初始化
func AdminLogin(c *gin.Context) {
cfg := config.Get()
if cfg == nil {
@@ -56,11 +60,69 @@ func AdminLogin(c *gin.Context) {
}
username := trimSpace(body.Username)
password := body.Password
db := database.DB()
// 1. 尝试从 admin_users 表校验
var u model.AdminUser
err := db.Where("username = ?", username).First(&u).Error
if err == nil {
if u.Status != "active" {
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "账号已禁用"})
return
}
if bcryptErr := bcrypt.CompareHashAndPassword([]byte(u.PasswordHash), []byte(password)); bcryptErr != nil {
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "用户名或密码错误"})
return
}
token, err := auth.IssueAdminJWT(cfg.AdminSessionSecret, u.Username, u.Role)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "签发失败"})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"token": token,
"user": gin.H{"id": u.ID, "username": u.Username, "role": u.Role, "name": u.Name},
})
return
}
// 2. 表内无匹配:若表为空且 env 账号正确,则创建初始 super_admin 并登录
if err != gorm.ErrRecordNotFound {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "系统错误"})
return
}
if cfg.AdminUsername == "" || cfg.AdminPassword == "" {
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "用户名或密码错误"})
return
}
if username != cfg.AdminUsername || password != cfg.AdminPassword {
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "用户名或密码错误"})
return
}
token, err := auth.IssueAdminJWT(cfg.AdminSessionSecret, username)
// 表为空时初始化超级管理员
var cnt int64
if db.Model(&model.AdminUser{}).Count(&cnt).Error != nil || cnt > 0 {
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "用户名或密码错误"})
return
}
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "初始化失败"})
return
}
initial := model.AdminUser{
Username: cfg.AdminUsername,
PasswordHash: string(hash),
Role: "super_admin",
Name: "卡若",
Status: "active",
}
if err := db.Create(&initial).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "初始化失败"})
return
}
token, err := auth.IssueAdminJWT(cfg.AdminSessionSecret, initial.Username, initial.Role)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "签发失败"})
return
@@ -68,9 +130,7 @@ func AdminLogin(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"success": true,
"token": token,
"user": gin.H{
"id": "admin", "username": cfg.AdminUsername, "role": "admin", "name": "卡若",
},
"user": gin.H{"id": initial.ID, "username": initial.Username, "role": initial.Role, "name": initial.Name},
})
}