Files
Mycontent/soul-api/internal/handler/admin_mbti_avatars.go
卡若 6d11fb295d feat: 同步本地三端改动并清理上传凭证风险
整合小程序、管理端与后端的最新本地改动,补齐用户管理与首页入口相关能力;提交前已完成敏感信息扫描,并移除本地 gitea 远程 URL 中的明文凭证,避免隐私信息进入远程仓库。

Made-with: Cursor
2026-04-06 15:59:34 +08:00

146 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"encoding/json"
"errors"
"net/http"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
const mbtiAvatarsConfigKey = "mbti_avatars"
const mbtiAvatarsDescription = "MBTI 16型人格头像映射"
// AdminMbtiAvatarsGet GET /api/admin/mbti-avatars 读取 MBTI 头像映射system_config.mbti_avatars
func AdminMbtiAvatarsGet(c *gin.Context) {
db := database.DB()
var row model.SystemConfig
err := db.Where("config_key = ?", mbtiAvatarsConfigKey).First(&row).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusOK, gin.H{"success": true, "avatars": map[string]string{}})
return
}
c.JSON(http.StatusOK, gin.H{"success": false, "error": "读取配置失败: " + err.Error()})
return
}
out := make(map[string]string)
if len(row.ConfigValue) > 0 {
if uerr := json.Unmarshal(row.ConfigValue, &out); uerr != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "配置 JSON 无效: " + uerr.Error()})
return
}
}
c.JSON(http.StatusOK, gin.H{"success": true, "avatars": out})
}
// AdminMbtiAvatarsPost POST /api/admin/mbti-avatars 保存 MBTI 头像映射upsert
func AdminMbtiAvatarsPost(c *gin.Context) {
var body struct {
Avatars map[string]string `json:"avatars"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "请求体无效"})
return
}
avatars := body.Avatars
if avatars == nil {
avatars = map[string]string{}
}
valBytes, err := json.Marshal(avatars)
if err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "序列化失败: " + err.Error()})
return
}
db := database.DB()
desc := mbtiAvatarsDescription
var row model.SystemConfig
err = db.Where("config_key = ?", mbtiAvatarsConfigKey).First(&row).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
row = model.SystemConfig{
ConfigKey: mbtiAvatarsConfigKey,
ConfigValue: valBytes,
Description: &desc,
}
if cerr := db.Create(&row).Error; cerr != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "保存失败: " + cerr.Error()})
return
}
} else {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "查询配置失败: " + err.Error()})
return
}
} else {
row.ConfigValue = valBytes
row.Description = &desc
if serr := db.Save(&row).Error; serr != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "保存失败: " + serr.Error()})
return
}
}
_mbtiAvatarCacheTs = 0
c.JSON(http.StatusOK, gin.H{"success": true, "message": "MBTI 头像映射已保存"})
}
// AdminMbtiAvatarsBatchAssign POST /api/admin/mbti-avatars/batch-assign
// 为无头像avatar IS NULL 或空)的用户批量分配 MBTI 默认头像。
// 有 MBTI 的按 MBTI 匹配;无 MBTI 的随机分配。
func AdminMbtiAvatarsBatchAssign(c *gin.Context) {
db := database.DB()
var row model.SystemConfig
if err := db.Where("config_key = ?", mbtiAvatarsConfigKey).First(&row).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "请先配置 MBTI 头像映射"})
return
}
avatarMap := make(map[string]string)
if err := json.Unmarshal(row.ConfigValue, &avatarMap); err != nil || len(avatarMap) == 0 {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "MBTI 头像映射为空"})
return
}
allTypes := make([]string, 0, len(avatarMap))
for k, v := range avatarMap {
if v != "" {
allTypes = append(allTypes, k)
}
}
if len(allTypes) == 0 {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "无可用头像"})
return
}
var users []model.User
db.Where("(avatar IS NULL OR avatar = '')").Limit(500).Find(&users)
if len(users) == 0 {
c.JSON(http.StatusOK, gin.H{"success": true, "assigned": 0, "message": "无需分配"})
return
}
assigned := 0
for i := range users {
mbti := ""
if users[i].Mbti != nil {
mbti = *users[i].Mbti
}
url := ""
if mbti != "" {
url = avatarMap[mbti]
}
if url == "" {
idx := (int(users[i].CreatedAt.UnixNano()) + i) % len(allTypes)
url = avatarMap[allTypes[idx]]
}
if url == "" {
continue
}
if err := db.Model(&model.User{}).Where("id = ?", users[i].ID).Update("avatar", url).Error; err == nil {
assigned++
}
}
c.JSON(http.StatusOK, gin.H{"success": true, "assigned": assigned, "total": len(users), "message": "批量分配完成"})
}