🐛 修复角色卡导出失败的bug

This commit is contained in:
2026-02-11 14:34:34 +08:00
parent cf3197929e
commit 1757b92b5f
8 changed files with 198 additions and 37 deletions

View File

@@ -8,6 +8,7 @@ import (
"fmt"
"image"
_ "image/jpeg"
_ "image/png"
"os"
"strings"
"time"
@@ -624,10 +625,17 @@ func (cs *CharacterService) ExportCharacterAsPNG(characterID uint, userID *uint)
// 获取角色头像
var img image.Image
var loadErr error
if character.Avatar != "" {
// TODO: 从 URL 或文件系统加载头像
// 这里暂时创建一个默认图片
img = createDefaultAvatar()
// 尝试从文件系统或 URL 加载头像
img, loadErr = loadAvatarImage(character.Avatar)
if loadErr != nil {
global.GVA_LOG.Warn("加载角色头像失败,使用默认头像",
zap.String("avatar", character.Avatar),
zap.Error(loadErr))
img = createDefaultAvatar()
}
} else {
img = createDefaultAvatar()
}
@@ -635,9 +643,14 @@ func (cs *CharacterService) ExportCharacterAsPNG(characterID uint, userID *uint)
// 将角色卡数据嵌入到 PNG
pngData, err := utils.EmbedCharacterToPNG(img, card)
if err != nil {
global.GVA_LOG.Error("生成 PNG 失败", zap.Error(err))
return nil, errors.New("生成 PNG 失败: " + err.Error())
}
global.GVA_LOG.Info("PNG 导出成功",
zap.Uint("characterID", characterID),
zap.Int("size", len(pngData)))
return pngData, nil
}
@@ -745,28 +758,49 @@ func convertCharacterToCard(character *app.AICharacter) *utils.CharacterCardV2 {
}
}
// loadAvatarImage 从文件系统或 URL 加载头像
func loadAvatarImage(avatarPath string) (image.Image, error) {
// 如果是 URL暂时不支持
if strings.HasPrefix(avatarPath, "http://") || strings.HasPrefix(avatarPath, "https://") {
return nil, errors.New("暂不支持从 URL 加载头像")
}
// 从文件系统加载
file, err := os.Open(avatarPath)
if err != nil {
return nil, fmt.Errorf("打开头像文件失败: %w", err)
}
defer file.Close()
// 解码图片(自动检测格式)
img, _, err := image.Decode(file)
if err != nil {
return nil, fmt.Errorf("解码头像图片失败: %w", err)
}
return img, nil
}
// createDefaultAvatar 创建默认头像
func createDefaultAvatar() image.Image {
// 创建一个 400x533 的默认图片3:4 比例)
width, height := 400, 533
img := image.NewRGBA(image.Rect(0, 0, width, height))
// 填充渐变色
// 填充渐变色(从紫色到蓝色)
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// 简单的渐变效果
// 计算渐变颜色
r := uint8(102 + y*155/height)
g := uint8(126 + y*138/height)
b := uint8(234 - y*72/height)
img.Set(x, y, image.NewRGBA(image.Rect(0, 0, 1, 1)).At(0, 0))
img.SetRGBA(x, y, image.NewRGBA(image.Rect(0, 0, 1, 1)).RGBAAt(0, 0))
// 设置颜色
img.SetRGBA(x, y, image.NewRGBA(image.Rect(0, 0, 1, 1)).RGBAAt(0, 0))
// 直接设置像素颜色
pix := img.Pix[y*img.Stride+x*4:]
pix[0] = r
pix[1] = g
pix[2] = b
pix[3] = 255
pix[3] = 255 // 完全不透明
}
}