1.修改首页下载功能

This commit is contained in:
whm
2026-03-18 18:43:23 +08:00
parent c67346626a
commit b17e99eb93
4 changed files with 150 additions and 8 deletions

View File

@@ -32,13 +32,18 @@ func pathPrefix(siteID string) string {
return "sites/" + siteID + "/"
}
// ListSiteAssets 站点功能模块/上传文件列表query path 为当前目录相对路径(空为根)
// ListSiteAssets 站点功能模块/上传文件列表query path 为当前目录相对路径(空为根)downloadable=1 时返回该站点下所有可下载文件(供首页编辑选择)
func ListSiteAssets(c *gin.Context) {
siteID := c.Param("site_id")
if siteID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "请提供 site_id"})
return
}
onlyDownloadable := c.Query("downloadable") == "1" || c.Query("downloadable") == "true"
if onlyDownloadable {
listDownloadableAssets(c, siteID)
return
}
path := c.Query("path")
prefix := pathPrefix(siteID)
if path != "" {
@@ -52,7 +57,6 @@ func ListSiteAssets(c *gin.Context) {
defer cancel()
coll := config.GetDB(config.DBName).Collection("site_assets")
// 仅当前目录下直接文件file_path 为 prefix + 不含 / 的文件名)
filter := bson.M{"site_id": siteID, "file_path": bson.M{"$regex": "^" + regexp.QuoteMeta(prefix) + "[^/]+$"}}
opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}})
cursor, err := coll.Find(ctx, filter, opts)
@@ -68,11 +72,40 @@ func ListSiteAssets(c *gin.Context) {
return
}
total, _ := coll.CountDocuments(ctx, filter)
// 子目录列表:从 file_path 中提取当前 path 下的一级子目录名
subDirs := listSubDirs(c, siteID, path)
c.JSON(http.StatusOK, gin.H{"list": list, "total": total, "sub_dirs": subDirs})
}
func listDownloadableAssets(c *gin.Context, siteID string) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("site_assets")
filter := bson.M{"site_id": siteID, "downloadable": true}
opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}})
cursor, err := coll.Find(ctx, filter, opts)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer cursor.Close(ctx)
var list []models.SiteAsset
if err = cursor.All(ctx, &list); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"list": list, "total": len(list)})
}
// ListDownloadableAssets 仅返回可下载文件列表(供首页编辑选择,仅需 homepage:edit 权限)
func ListDownloadableAssets(c *gin.Context) {
siteID := c.Param("site_id")
if siteID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "请提供 site_id"})
return
}
listDownloadableAssets(c, siteID)
}
func listSubDirs(c *gin.Context, siteID, currentPath string) []string {
prefix := pathPrefix(siteID)
if currentPath != "" {
@@ -250,3 +283,41 @@ func CreateSiteFolder(c *gin.Context) {
}
c.JSON(http.StatusOK, gin.H{"message": "创建成功", "path": filepath.ToSlash(clean)})
}
// DownloadSiteAsset 前台公开下载:仅当资源标记为可下载时返回文件(供首页等使用)
func DownloadSiteAsset(c *gin.Context) {
siteID := c.Param("site_id")
assetIDStr := c.Param("asset_id")
if siteID == "" || assetIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
return
}
oid, err := bson.ObjectIDFromHex(assetIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的ID"})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("site_assets")
var asset models.SiteAsset
err = coll.FindOne(ctx, bson.M{"_id": oid, "site_id": siteID}).Decode(&asset)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "资源不存在"})
return
}
if !asset.Downloadable {
c.JSON(http.StatusForbidden, gin.H{"error": "该资源不可下载"})
return
}
fullPath := filepath.Join(getUploadDir(), filepath.FromSlash(asset.FilePath))
if _, err := os.Stat(fullPath); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"})
return
}
c.Header("Content-Disposition", "attachment; filename=\""+asset.Name+"\"")
if asset.ContentType != "" {
c.Header("Content-Type", asset.ContentType)
}
c.File(fullPath)
}

View File

@@ -161,6 +161,7 @@ func main() {
admin.GET("/sites/:site_id/homepage/download", handlers.RequirePermission(models.PermHomepageEdit), handlers.DownloadHomepage)
admin.GET("/sites/:site_id/homepage", handlers.RequirePermission(models.PermHomepageEdit), handlers.GetHomepage)
admin.PUT("/sites/:site_id/homepage", handlers.RequirePermission(models.PermHomepageEdit), handlers.UpdateHomepage)
admin.GET("/sites/:site_id/assets/downloadable", handlers.RequirePermission(models.PermHomepageEdit), handlers.ListDownloadableAssets)
admin.GET("/sites/:site_id/assets", handlers.RequirePermission(models.PermSiteManage), handlers.ListSiteAssets)
admin.POST("/sites/:site_id/assets", handlers.RequirePermission(models.PermModuleUpload), handlers.UploadSiteAsset)
admin.POST("/sites/:site_id/folders", handlers.RequirePermission(models.PermModuleUpload), handlers.CreateSiteFolder)
@@ -212,6 +213,8 @@ func main() {
web.GET("/info", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "web api"})
})
// 可下载资源公开下载(首页等链接指向此路径)
web.GET("/sites/:site_id/assets/:asset_id/download", handlers.DownloadSiteAsset)
}
port := os.Getenv("PORT")