638 lines
19 KiB
Go
638 lines
19 KiB
Go
package app
|
||
|
||
import (
|
||
"fmt"
|
||
"io"
|
||
"mime"
|
||
"net/http"
|
||
"os"
|
||
"path/filepath"
|
||
"strconv"
|
||
|
||
"git.echol.cn/loser/st/server/global"
|
||
"git.echol.cn/loser/st/server/middleware"
|
||
"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 ExtensionApi struct{}
|
||
|
||
var extensionService = service.ServiceGroupApp.AppServiceGroup.ExtensionService
|
||
|
||
// CreateExtension 创建/安装扩展
|
||
// @Summary 创建/安装扩展
|
||
// @Description 创建一个新的扩展或安装扩展
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param data body request.CreateExtensionRequest true "扩展信息"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension [post]
|
||
func (a *ExtensionApi) CreateExtension(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
var req request.CreateExtensionRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
extension, err := extensionService.CreateExtension(userID, &req)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("创建扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("创建失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// UpdateExtension 更新扩展
|
||
// @Summary 更新扩展
|
||
// @Description 更新扩展信息
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Param data body request.UpdateExtensionRequest true "扩展信息"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /app/extension/:id [put]
|
||
func (a *ExtensionApi) UpdateExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
var req request.UpdateExtensionRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
if err := extensionService.UpdateExtension(userID, extensionID, &req); err != nil {
|
||
global.GVA_LOG.Error("更新扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("更新失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithMessage("更新成功", c)
|
||
}
|
||
|
||
// DeleteExtension 删除/卸载扩展
|
||
// @Summary 删除/卸载扩展
|
||
// @Description 删除扩展
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Param deleteFiles query bool false "是否删除文件"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /app/extension/:id [delete]
|
||
func (a *ExtensionApi) DeleteExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
deleteFiles := c.Query("deleteFiles") == "true"
|
||
|
||
if err := extensionService.DeleteExtension(userID, extensionID, deleteFiles); err != nil {
|
||
global.GVA_LOG.Error("删除扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("删除失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithMessage("删除成功", c)
|
||
}
|
||
|
||
// GetExtension 获取扩展详情
|
||
// @Summary 获取扩展详情
|
||
// @Description 获取扩展详细信息
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension/:id [get]
|
||
func (a *ExtensionApi) GetExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
extension, err := extensionService.GetExtension(userID, extensionID)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("获取失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// GetExtensionList 获取扩展列表
|
||
// @Summary 获取扩展列表
|
||
// @Description 获取扩展列表
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param data query request.ExtensionListRequest true "查询参数"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionListResponse}
|
||
// @Router /app/extension/list [get]
|
||
func (a *ExtensionApi) GetExtensionList(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
var req request.ExtensionListRequest
|
||
if err := c.ShouldBindQuery(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
// 默认分页
|
||
if req.Page < 1 {
|
||
req.Page = 1
|
||
}
|
||
if req.PageSize < 1 {
|
||
req.PageSize = 20
|
||
}
|
||
|
||
result, err := extensionService.GetExtensionList(userID, &req)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取扩展列表失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("获取失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(result, c)
|
||
}
|
||
|
||
// ToggleExtension 启用/禁用扩展
|
||
// @Summary 启用/禁用扩展
|
||
// @Description 切换扩展的启用状态
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Param data body request.ToggleExtensionRequest true "启用状态"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /app/extension/:id/toggle [post]
|
||
func (a *ExtensionApi) ToggleExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
var req request.ToggleExtensionRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage("请求参数错误", c)
|
||
return
|
||
}
|
||
|
||
if req.IsEnabled == nil {
|
||
sysResponse.FailWithMessage("isEnabled 参数不能为空", c)
|
||
return
|
||
}
|
||
|
||
if err := extensionService.ToggleExtension(userID, extensionID, *req.IsEnabled); err != nil {
|
||
global.GVA_LOG.Error("切换扩展状态失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("操作失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithMessage("操作成功", c)
|
||
}
|
||
|
||
// UpdateExtensionSettings 更新扩展配置
|
||
// @Summary 更新扩展配置
|
||
// @Description 更新扩展的用户配置
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Param data body request.UpdateExtensionSettingsRequest true "配置信息"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /app/extension/:id/settings [put]
|
||
func (a *ExtensionApi) UpdateExtensionSettings(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
var req request.UpdateExtensionSettingsRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
if err := extensionService.UpdateExtensionSettings(userID, extensionID, req.Settings); err != nil {
|
||
global.GVA_LOG.Error("更新扩展配置失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("更新失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithMessage("更新成功", c)
|
||
}
|
||
|
||
// GetExtensionSettings 获取扩展配置
|
||
// @Summary 获取扩展配置
|
||
// @Description 获取扩展的用户配置
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||
// @Router /app/extension/:id/settings [get]
|
||
func (a *ExtensionApi) GetExtensionSettings(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
settings, err := extensionService.GetExtensionSettings(userID, extensionID)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取扩展配置失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("获取失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(settings, c)
|
||
}
|
||
|
||
// GetExtensionManifest 获取扩展 manifest
|
||
// @Summary 获取扩展 manifest
|
||
// @Description 获取扩展的 manifest.json
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionManifestResponse}
|
||
// @Router /app/extension/:id/manifest [get]
|
||
func (a *ExtensionApi) GetExtensionManifest(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
manifest, err := extensionService.GetExtensionManifest(userID, extensionID)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取扩展 manifest 失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("获取失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(manifest, c)
|
||
}
|
||
|
||
// ImportExtension 导入扩展
|
||
// @Summary 导入扩展
|
||
// @Description 从文件导入扩展
|
||
// @Tags 扩展管理
|
||
// @Accept multipart/form-data
|
||
// @Produce json
|
||
// @Param file formData file true "扩展文件(manifest.json)"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension/import [post]
|
||
func (a *ExtensionApi) ImportExtension(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
// 获取文件
|
||
file, err := c.FormFile("file")
|
||
if err != nil {
|
||
sysResponse.FailWithMessage("请上传扩展文件", c)
|
||
return
|
||
}
|
||
|
||
// 文件大小限制(5MB)
|
||
if file.Size > 5<<20 {
|
||
sysResponse.FailWithMessage("文件大小不能超过 5MB", c)
|
||
return
|
||
}
|
||
|
||
// 读取文件内容
|
||
src, err := file.Open()
|
||
if err != nil {
|
||
global.GVA_LOG.Error("打开文件失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("文件读取失败", c)
|
||
return
|
||
}
|
||
defer src.Close()
|
||
|
||
fileData, err := io.ReadAll(src)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("读取文件内容失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("文件读取失败", c)
|
||
return
|
||
}
|
||
|
||
// 导入扩展
|
||
extension, err := extensionService.ImportExtension(userID, fileData)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("导入扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("导入失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// ExportExtension 导出扩展
|
||
// @Summary 导出扩展
|
||
// @Description 导出扩展为 manifest.json 文件
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce application/json
|
||
// @Param id path int true "扩展ID"
|
||
// @Success 200 {object} response.ExtensionManifestResponse
|
||
// @Router /app/extension/:id/export [get]
|
||
func (a *ExtensionApi) ExportExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
exportData, err := extensionService.ExportExtension(userID, extensionID)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("导出扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("导出失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
// 设置响应头
|
||
filename := fmt.Sprintf("extension_%d_manifest.json", extensionID)
|
||
c.Header("Content-Type", "application/json")
|
||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
|
||
|
||
// 直接返回 JSON 数据
|
||
c.Data(http.StatusOK, "application/json", exportData)
|
||
}
|
||
|
||
// UpdateExtensionStats 更新扩展统计
|
||
// @Summary 更新扩展统计
|
||
// @Description 更新扩展的使用统计
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param data body request.ExtensionStatsRequest true "统计信息"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /app/extension/stats [post]
|
||
func (a *ExtensionApi) UpdateExtensionStats(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
var req request.ExtensionStatsRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
if err := extensionService.UpdateExtensionStats(userID, req.ExtensionID, req.Action, req.Value); err != nil {
|
||
global.GVA_LOG.Error("更新扩展统计失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("更新失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithMessage("更新成功", c)
|
||
}
|
||
|
||
// GetEnabledExtensions 获取启用的扩展列表
|
||
// @Summary 获取启用的扩展列表
|
||
// @Description 获取用户启用的所有扩展(用于前端加载)
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Success 200 {object} response.Response{data=[]response.ExtensionResponse}
|
||
// @Router /app/extension/enabled [get]
|
||
func (a *ExtensionApi) GetEnabledExtensions(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
extensions, err := extensionService.GetEnabledExtensions(userID)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取启用扩展列表失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("获取失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(extensions, c)
|
||
}
|
||
|
||
// InstallExtensionFromURL 智能安装扩展(自动识别 Git URL 或 Manifest URL)
|
||
// @Summary 智能安装扩展
|
||
// @Description 自动识别 Git 仓库 URL 或 Manifest.json URL 并安装扩展(兼容 SillyTavern)
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param data body request.InstallExtensionFromURLRequest true "安装 URL 信息"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension/install/url [post]
|
||
func (a *ExtensionApi) InstallExtensionFromURL(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
var req request.InstallExtensionFromURLRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage("请求参数错误: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
// 设置默认分支
|
||
if req.Branch == "" {
|
||
req.Branch = "main"
|
||
}
|
||
|
||
extension, err := extensionService.InstallExtensionFromURL(userID, req.URL, req.Branch)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("从 URL 安装扩展失败", zap.Error(err), zap.String("url", req.URL))
|
||
sysResponse.FailWithMessage("安装失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// UpgradeExtension 升级扩展版本
|
||
// @Summary 升级扩展版本
|
||
// @Description 根据扩展的安装来源自动选择更新方式(Git pull 或重新下载)
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path int true "扩展ID"
|
||
// @Param data body request.UpdateExtensionRequest false "更新选项"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension/:id/update [post]
|
||
func (a *ExtensionApi) UpgradeExtension(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
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
var req request.UpdateExtensionRequest
|
||
// 允许不传 body(使用默认值)
|
||
_ = c.ShouldBindJSON(&req)
|
||
|
||
extension, err := extensionService.UpgradeExtension(userID, extensionID, req.Force)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("升级扩展失败", zap.Error(err), zap.Uint("extensionID", extensionID))
|
||
sysResponse.FailWithMessage("升级失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// InstallExtensionFromGit 从 Git URL 安装扩展
|
||
// @Summary 从 Git URL 安装扩展
|
||
// @Description 从 Git 仓库 URL 克隆并安装扩展
|
||
// @Tags 扩展管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param data body request.InstallExtensionFromGitRequest true "Git URL 信息"
|
||
// @Success 200 {object} response.Response{data=response.ExtensionResponse}
|
||
// @Router /app/extension/install/git [post]
|
||
func (a *ExtensionApi) InstallExtensionFromGit(c *gin.Context) {
|
||
userID := middleware.GetAppUserID(c)
|
||
|
||
var req request.InstallExtensionFromGitRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
sysResponse.FailWithMessage(err.Error(), c)
|
||
return
|
||
}
|
||
|
||
// 设置默认分支
|
||
if req.Branch == "" {
|
||
req.Branch = "main"
|
||
}
|
||
|
||
extension, err := extensionService.InstallExtensionFromGit(userID, req.GitUrl, req.Branch)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("从 Git 安装扩展失败", zap.Error(err))
|
||
sysResponse.FailWithMessage("安装失败: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
sysResponse.OkWithData(response.ToExtensionResponse(extension), c)
|
||
}
|
||
|
||
// ProxyExtensionAsset 获取扩展资源文件(从本地文件系统读取)
|
||
// @Summary 获取扩展资源文件
|
||
// @Description 从本地存储读取扩展的 JS/CSS 等资源文件(与原版 SillyTavern 一致,扩展文件存储在本地)
|
||
// @Tags 扩展管理
|
||
// @Produce octet-stream
|
||
// @Param id path int true "扩展ID"
|
||
// @Param path path string true "资源文件路径"
|
||
// @Success 200 {file} binary
|
||
// @Router /app/extension/:id/asset/*path [get]
|
||
func (a *ExtensionApi) ProxyExtensionAsset(c *gin.Context) {
|
||
idStr := c.Param("id")
|
||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||
if err != nil {
|
||
sysResponse.FailWithMessage("无效的扩展ID", c)
|
||
return
|
||
}
|
||
extensionID := uint(id)
|
||
|
||
// 获取资源路径(去掉前导 /)
|
||
assetPath := c.Param("path")
|
||
if len(assetPath) > 0 && assetPath[0] == '/' {
|
||
assetPath = assetPath[1:]
|
||
}
|
||
if assetPath == "" {
|
||
sysResponse.FailWithMessage("资源路径不能为空", c)
|
||
return
|
||
}
|
||
|
||
// 通过扩展 ID 查库获取信息(公开路由,不做 userID 过滤)
|
||
extInfo, err := extensionService.GetExtensionByID(extensionID)
|
||
if err != nil {
|
||
sysResponse.FailWithMessage("扩展不存在", c)
|
||
return
|
||
}
|
||
|
||
// 从本地文件系统读取资源
|
||
localPath, err := extensionService.GetExtensionAssetLocalPath(extInfo.Name, assetPath)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("获取扩展资源失败",
|
||
zap.Error(err),
|
||
zap.String("name", extInfo.Name),
|
||
zap.String("asset", assetPath))
|
||
sysResponse.FailWithMessage("资源不存在: "+err.Error(), c)
|
||
return
|
||
}
|
||
|
||
// 读取文件内容
|
||
data, err := os.ReadFile(localPath)
|
||
if err != nil {
|
||
global.GVA_LOG.Error("读取扩展资源文件失败", zap.Error(err), zap.String("path", localPath))
|
||
sysResponse.FailWithMessage("资源读取失败", c)
|
||
return
|
||
}
|
||
|
||
// 根据文件扩展名设置正确的 Content-Type
|
||
fileExt := filepath.Ext(assetPath)
|
||
contentType := mime.TypeByExtension(fileExt)
|
||
if contentType == "" {
|
||
contentType = "application/octet-stream"
|
||
}
|
||
|
||
// 设置缓存和 CORS 头
|
||
c.Header("Content-Type", contentType)
|
||
c.Header("Cache-Control", "public, max-age=3600")
|
||
c.Header("Access-Control-Allow-Origin", "*")
|
||
|
||
c.Data(http.StatusOK, contentType, data)
|
||
}
|