🎨 优化角色卡编辑

Signed-off-by: Echo <1711788888@qq.com>
This commit is contained in:
2026-02-28 15:09:53 +08:00
parent 81b552b689
commit a6234e7bb0
8 changed files with 530 additions and 9 deletions

View File

@@ -8,4 +8,5 @@ type ApiGroup struct {
PresetApi
UploadApi
WorldbookApi
RegexScriptApi
}

View File

@@ -88,6 +88,7 @@ func RegisterTables() {
app.AIPreset{},
app.Worldbook{},
app.WorldbookEntry{},
app.RegexScript{},
)
if err != nil {
global.GVA_LOG.Error("register table failed", zap.Error(err))

View File

@@ -154,6 +154,7 @@ func Routers() *gin.Engine {
appRouter.InitPresetRouter(appGroup) // 预设路由:/app/preset/*
appRouter.InitUploadRouter(appGroup) // 上传路由:/app/upload/*
appRouter.InitWorldbookRouter(appGroup) // 世界书路由:/app/worldbook/*
appRouter.InitRegexScriptRouter(appGroup) // 正则脚本路由:/app/regex/*
}
//插件路由安装

View File

@@ -8,4 +8,5 @@ type RouterGroup struct {
PresetRouter
UploadRouter
WorldbookRouter
RegexScriptRouter
}

View File

@@ -267,7 +267,18 @@ func (s *CharacterService) ImportCharacterFromPNG(userID uint, file *multipart.F
IsPublic: false,
}
return s.CreateCharacter(userID, req)
// 创建角色卡
resp, err := s.CreateCharacter(userID, req)
if err != nil {
return nil, err
}
// 处理扩展数据中的正则脚本
if card.Data.Extensions != nil {
s.processRegexScriptsFromExtensions(userID, resp.ID, card.Data.Extensions)
}
return resp, nil
}
// ImportCharacterFromJSON 从 JSON 文件导入角色卡
@@ -312,7 +323,18 @@ func (s *CharacterService) ImportCharacterFromJSON(userID uint, file *multipart.
IsPublic: false,
}
return s.CreateCharacter(userID, req)
// 创建角色卡
resp, err := s.CreateCharacter(userID, req)
if err != nil {
return nil, err
}
// 处理扩展数据中的正则脚本
if card.Data.Extensions != nil {
s.processRegexScriptsFromExtensions(userID, resp.ID, card.Data.Extensions)
}
return resp, nil
}
// ExportCharacterToJSON 导出角色卡为 JSON
@@ -339,6 +361,16 @@ func (s *CharacterService) ExportCharacterToJSON(userID, characterID uint) (*uti
json.Unmarshal(character.CharacterBook, &characterBook)
json.Unmarshal(character.Extensions, &extensions)
// 查询角色关联的正则脚本并添加到 extensions
var regexScripts []app.RegexScript
global.GVA_DB.Where("owner_char_id = ? AND scope = 1", characterID).Find(&regexScripts)
if len(regexScripts) > 0 {
if extensions == nil {
extensions = make(map[string]interface{})
}
extensions["regex_scripts"] = regexScripts
}
// 构建 V2 格式
card := &utils.CharacterCardV2{
Spec: character.Spec,
@@ -364,3 +396,94 @@ func (s *CharacterService) ExportCharacterToJSON(userID, characterID uint) (*uti
return card, nil
}
// processRegexScriptsFromExtensions 从扩展数据中提取并创建正则脚本
func (s *CharacterService) processRegexScriptsFromExtensions(userID, characterID uint, extensions map[string]interface{}) {
// 检查是否包含正则脚本
regexScriptsData, ok := extensions["regex_scripts"]
if !ok {
return
}
// 转换为 JSON 以便解析
scriptsJSON, err := json.Marshal(regexScriptsData)
if err != nil {
global.GVA_LOG.Error("序列化正则脚本失败: " + err.Error())
return
}
// 解析正则脚本数组
var scripts []map[string]interface{}
if err := json.Unmarshal(scriptsJSON, &scripts); err != nil {
global.GVA_LOG.Error("解析正则脚本失败: " + err.Error())
return
}
// 创建正则脚本记录
for _, scriptData := range scripts {
script := app.RegexScript{
UserID: userID,
Scope: 1, // 角色作用域
OwnerCharID: &characterID,
}
// 提取字段
if name, ok := scriptData["name"].(string); ok {
script.Name = name
}
if findRegex, ok := scriptData["findRegex"].(string); ok {
script.FindRegex = findRegex
}
if replaceWith, ok := scriptData["replaceWith"].(string); ok {
script.ReplaceWith = replaceWith
}
if placement, ok := scriptData["placement"].(float64); ok {
script.Placement = int(placement)
}
if disabled, ok := scriptData["disabled"].(bool); ok {
script.Disabled = disabled
}
if markdownOnly, ok := scriptData["markdownOnly"].(bool); ok {
script.MarkdownOnly = markdownOnly
}
if runOnEdit, ok := scriptData["runOnEdit"].(bool); ok {
script.RunOnEdit = runOnEdit
}
if promptOnly, ok := scriptData["promptOnly"].(bool); ok {
script.PromptOnly = promptOnly
}
if substituteRegex, ok := scriptData["substituteRegex"].(bool); ok {
script.SubstituteRegex = substituteRegex
}
if order, ok := scriptData["order"].(float64); ok {
script.Order = int(order)
}
// 处理可选的整数字段
if minDepth, ok := scriptData["minDepth"].(float64); ok {
depth := int(minDepth)
script.MinDepth = &depth
}
if maxDepth, ok := scriptData["maxDepth"].(float64); ok {
depth := int(maxDepth)
script.MaxDepth = &depth
}
// 处理 trimStrings 数组
if trimStrings, ok := scriptData["trimStrings"].([]interface{}); ok {
trimStringsJSON, _ := json.Marshal(trimStrings)
script.TrimStrings = datatypes.JSON(trimStringsJSON)
}
// 处理扩展字段
if scriptExtensions, ok := scriptData["extensions"].(map[string]interface{}); ok {
extensionsJSON, _ := json.Marshal(scriptExtensions)
script.Extensions = datatypes.JSON(extensionsJSON)
}
// 创建记录
if err := global.GVA_DB.Create(&script).Error; err != nil {
global.GVA_LOG.Error("创建正则脚本失败: " + err.Error())
}
}
}

View File

@@ -8,4 +8,5 @@ type AppServiceGroup struct {
PresetService
UploadService
WorldbookService
RegexScriptService
}