package app import ( "encoding/json" "fmt" "io" "net/http" "strconv" "strings" "git.echol.cn/loser/st/server/global" "git.echol.cn/loser/st/server/middleware" "git.echol.cn/loser/st/server/model/app" "git.echol.cn/loser/st/server/model/app/request" "git.echol.cn/loser/st/server/model/app/response" sysResponse "git.echol.cn/loser/st/server/model/common/response" "git.echol.cn/loser/st/server/service" "github.com/gin-gonic/gin" "go.uber.org/zap" ) type RegexScriptApi struct{} var regexScriptService = service.ServiceGroupApp.AppServiceGroup.RegexScriptService // CreateRegexScript 创建正则脚本 // @Summary 创建正则脚本 // @Description 创建一个新的正则表达式脚本 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param data body request.CreateRegexScriptRequest true "脚本信息" // @Success 200 {object} response.Response{data=app.AIRegexScript} // @Router /app/regex [post] func (a *RegexScriptApi) CreateRegexScript(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.CreateRegexScriptRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } script, err := regexScriptService.CreateRegexScript(userID, &req) if err != nil { global.GVA_LOG.Error("创建正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("创建失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToRegexScriptResponse(script), c) } // UpdateRegexScript 更新正则脚本 // @Summary 更新正则脚本 // @Description 更新正则脚本信息 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param id path int true "脚本ID" // @Param data body request.UpdateRegexScriptRequest true "脚本信息" // @Success 200 {object} response.Response // @Router /app/regex/:id [put] func (a *RegexScriptApi) UpdateRegexScript(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的脚本ID", c) return } scriptID := uint(id) var req request.UpdateRegexScriptRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } if err := regexScriptService.UpdateRegexScript(userID, scriptID, &req); err != nil { global.GVA_LOG.Error("更新正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("更新失败: "+err.Error(), c) return } sysResponse.OkWithMessage("更新成功", c) } // DeleteRegexScript 删除正则脚本 // @Summary 删除正则脚本 // @Description 删除正则脚本 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param id path int true "脚本ID" // @Success 200 {object} response.Response // @Router /app/regex/:id [delete] func (a *RegexScriptApi) DeleteRegexScript(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的脚本ID", c) return } scriptID := uint(id) if err := regexScriptService.DeleteRegexScript(userID, scriptID); err != nil { global.GVA_LOG.Error("删除正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("删除失败: "+err.Error(), c) return } sysResponse.OkWithMessage("删除成功", c) } // GetRegexScript 获取正则脚本详情 // @Summary 获取正则脚本详情 // @Description 获取正则脚本详细信息 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param id path int true "脚本ID" // @Success 200 {object} response.Response{data=response.RegexScriptResponse} // @Router /app/regex/:id [get] func (a *RegexScriptApi) GetRegexScript(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的脚本ID", c) return } scriptID := uint(id) script, err := regexScriptService.GetRegexScript(userID, scriptID) if err != nil { global.GVA_LOG.Error("获取正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToRegexScriptResponse(script), c) } // GetRegexScriptList 获取正则脚本列表 // @Summary 获取正则脚本列表 // @Description 获取正则脚本列表 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param scriptName query string false "脚本名称" // @Param isGlobal query boolean false "是否全局" // @Param enabled query boolean false "是否启用" // @Param characterId query int false "关联角色ID" // @Param page query int false "页码" // @Param pageSize query int false "每页大小" // @Success 200 {object} response.Response{data=response.RegexScriptListResponse} // @Router /app/regex [get] func (a *RegexScriptApi) GetRegexScriptList(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.RegexScriptListRequest if err := c.ShouldBindQuery(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } // 设置默认值 if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 { req.PageSize = 20 } scripts, total, err := regexScriptService.GetRegexScriptList(userID, &req) if err != nil { global.GVA_LOG.Error("获取正则脚本列表失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } // 转换为响应格式 responses := make([]response.RegexScriptResponse, len(scripts)) for i, script := range scripts { responses[i] = response.ToRegexScriptResponse(&script) } sysResponse.OkWithData(response.RegexScriptListResponse{ List: responses, Total: total, Page: req.Page, PageSize: req.PageSize, }, c) } // LinkCharactersToRegex 关联角色到正则脚本 // @Summary 关联角色到正则脚本 // @Description 将角色关联到指定的正则脚本 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param id path int true "脚本ID" // @Param data body request.LinkCharacterToRegexRequest true "角色ID列表" // @Success 200 {object} response.Response // @Router /app/regex/:id/link [post] func (a *RegexScriptApi) LinkCharactersToRegex(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的脚本ID", c) return } scriptID := uint(id) var req request.LinkCharacterToRegexRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } if err := regexScriptService.LinkCharactersToRegex(userID, scriptID, req.CharacterIDs); err != nil { global.GVA_LOG.Error("关联角色失败", zap.Error(err)) sysResponse.FailWithMessage("关联失败: "+err.Error(), c) return } sysResponse.OkWithMessage("关联成功", c) } // GetCharacterRegexScripts 获取角色关联的正则脚本 // @Summary 获取角色关联的正则脚本 // @Description 获取特定角色关联的所有正则脚本 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param characterId path int true "角色ID" // @Success 200 {object} response.Response{data=[]response.RegexScriptResponse} // @Router /app/regex/character/:characterId [get] func (a *RegexScriptApi) GetCharacterRegexScripts(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("characterId") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的角色ID", c) return } characterID := uint(id) scripts, err := regexScriptService.GetCharacterRegexScripts(userID, characterID) if err != nil { global.GVA_LOG.Error("获取角色正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("获取失败: "+err.Error(), c) return } // 转换为响应格式 responses := make([]response.RegexScriptResponse, len(scripts)) for i, script := range scripts { responses[i] = response.ToRegexScriptResponse(&script) } sysResponse.OkWithData(responses, c) } // DuplicateRegexScript 复制正则脚本 // @Summary 复制正则脚本 // @Description 创建正则脚本的副本 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param id path int true "脚本ID" // @Success 200 {object} response.Response{data=app.AIRegexScript} // @Router /app/regex/:id/duplicate [post] func (a *RegexScriptApi) DuplicateRegexScript(c *gin.Context) { userID := middleware.GetAppUserID(c) // 从路径参数获取 ID idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { sysResponse.FailWithMessage("无效的脚本ID", c) return } scriptID := uint(id) newScript, err := regexScriptService.DuplicateRegexScript(userID, scriptID) if err != nil { global.GVA_LOG.Error("复制正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("复制失败: "+err.Error(), c) return } sysResponse.OkWithData(response.ToRegexScriptResponse(newScript), c) } // TestRegexScript 测试正则脚本 // @Summary 测试正则脚本 // @Description 测试正则表达式的匹配和替换效果 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param data body request.TestRegexScriptRequest true "测试数据" // @Success 200 {object} response.Response{data=response.TestRegexScriptResponse} // @Router /app/regex/test [post] func (a *RegexScriptApi) TestRegexScript(c *gin.Context) { var req request.TestRegexScriptRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } result, err := regexScriptService.TestRegexScript(&req) if err != nil { global.GVA_LOG.Error("测试正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("测试失败: "+err.Error(), c) return } sysResponse.OkWithData(result, c) } // ApplyRegexScripts 应用正则脚本 // @Summary 应用正则脚本 // @Description 对文本应用正则脚本进行处理 // @Tags 正则脚本管理 // @Accept json // @Produce json // @Param data body request.ApplyRegexScriptsRequest true "应用参数" // @Success 200 {object} response.Response{data=response.ApplyRegexScriptsResponse} // @Router /app/regex/apply [post] func (a *RegexScriptApi) ApplyRegexScripts(c *gin.Context) { userID := middleware.GetAppUserID(c) var req request.ApplyRegexScriptsRequest if err := c.ShouldBindJSON(&req); err != nil { sysResponse.FailWithMessage(err.Error(), c) return } result, err := regexScriptService.ApplyRegexScripts(userID, &req) if err != nil { global.GVA_LOG.Error("应用正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("应用失败: "+err.Error(), c) return } sysResponse.OkWithData(result, c) } // ImportRegexScripts 导入正则脚本 // @Summary 导入正则脚本 // @Description 从 JSON 文件导入正则脚本 // @Tags 正则脚本管理 // @Accept multipart/form-data // @Produce json // @Param file formData file true "JSON 文件" // @Param overwriteMode formData string false "覆盖模式: skip, overwrite, merge" // @Success 200 {object} response.Response // @Router /app/regex/import [post] func (a *RegexScriptApi) ImportRegexScripts(c *gin.Context) { userID := middleware.GetAppUserID(c) // 获取文件 file, err := c.FormFile("file") if err != nil { sysResponse.FailWithMessage("获取文件失败: "+err.Error(), c) return } // 获取覆盖模式 overwriteMode := c.DefaultPostForm("overwriteMode", "skip") // 读取文件内容 openedFile, err := file.Open() if err != nil { sysResponse.FailWithMessage("打开文件失败: "+err.Error(), c) return } defer openedFile.Close() content, err := io.ReadAll(openedFile) if err != nil { sysResponse.FailWithMessage("读取文件失败: "+err.Error(), c) return } // 解析 JSON var exportData response.RegexScriptExportData if err := json.Unmarshal(content, &exportData); err != nil { sysResponse.FailWithMessage("解析JSON失败: "+err.Error(), c) return } // 转换为 AIRegexScript scripts := make([]app.AIRegexScript, len(exportData.Scripts)) for i, resp := range exportData.Scripts { scripts[i] = app.AIRegexScript{ ScriptName: resp.ScriptName, Description: resp.Description, FindRegex: resp.FindRegex, ReplaceString: resp.ReplaceString, Enabled: resp.Enabled, IsGlobal: resp.IsGlobal, TrimStrings: resp.TrimStrings, OnlyFormat: resp.OnlyFormat, RunOnEdit: resp.RunOnEdit, SubstituteRegex: resp.SubstituteRegex, MinDepth: resp.MinDepth, MaxDepth: resp.MaxDepth, Placement: resp.Placement, AffectMinDepth: resp.AffectMinDepth, AffectMaxDepth: resp.AffectMaxDepth, LinkedChars: resp.LinkedChars, } } // 导入 imported, err := regexScriptService.ImportRegexScripts(userID, scripts, overwriteMode) if err != nil { global.GVA_LOG.Error("导入正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("导入失败: "+err.Error(), c) return } sysResponse.OkWithMessage(fmt.Sprintf("成功导入 %d 个脚本", imported), c) } // ExportRegexScripts 导出正则脚本 // @Summary 导出正则脚本 // @Description 导出正则脚本为 JSON 文件 // @Tags 正则脚本管理 // @Accept json // @Produce application/json // @Param scriptIds query string false "脚本ID列表(逗号分隔)" // @Success 200 {object} response.RegexScriptExportData // @Router /app/regex/export [get] func (a *RegexScriptApi) ExportRegexScripts(c *gin.Context) { userID := middleware.GetAppUserID(c) // 获取脚本ID列表 scriptIDsStr := c.Query("scriptIds") var scriptIDs []uint if scriptIDsStr != "" { var ids []uint for _, idStr := range strings.Split(scriptIDsStr, ",") { id, err := strconv.ParseUint(idStr, 10, 32) if err == nil { ids = append(ids, uint(id)) } } scriptIDs = ids } exportData, err := regexScriptService.ExportRegexScripts(userID, scriptIDs) if err != nil { global.GVA_LOG.Error("导出正则脚本失败", zap.Error(err)) sysResponse.FailWithMessage("导出失败: "+err.Error(), c) return } // 设置下载响应头 c.Header("Content-Type", "application/json") c.Header("Content-Disposition", "attachment; filename=regex_scripts_export.json") c.JSON(http.StatusOK, exportData) }