增加公告图片编辑, 增加取消归档
This commit is contained in:
@@ -173,6 +173,22 @@ func (h *Handler) Archive(c *gin.Context) {
|
||||
response.OK(c, gin.H{"message": "归档成功"})
|
||||
}
|
||||
|
||||
// Unarchive 取消归档公告
|
||||
func (h *Handler) Unarchive(c *gin.Context) {
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "公告ID不正确")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Unarchive(c.Request.Context(), id); err != nil {
|
||||
response.InternalServerError(c, "取消归档公告失败")
|
||||
return
|
||||
}
|
||||
|
||||
response.OK(c, gin.H{"message": "取消归档成功"})
|
||||
}
|
||||
|
||||
// Delete 删除公告
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id, err := parseID(c)
|
||||
|
||||
@@ -179,6 +179,17 @@ func (r *Repository) Archive(ctx context.Context, id uint64) error {
|
||||
Update("status", "archived").Error
|
||||
}
|
||||
|
||||
// Unarchive 取消归档公告,恢复为已发布状态
|
||||
func (r *Repository) Unarchive(ctx context.Context, id uint64) error {
|
||||
now := time.Now()
|
||||
return r.db.WithContext(ctx).Model(&model.Announcement{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": "published",
|
||||
"published_at": gorm.Expr("COALESCE(published_at, ?)", now),
|
||||
}).Error
|
||||
}
|
||||
|
||||
// Delete 删除公告
|
||||
func (r *Repository) Delete(ctx context.Context, id uint64) error {
|
||||
return r.db.WithContext(ctx).Where("id = ?", id).Delete(&model.Announcement{}).Error
|
||||
|
||||
@@ -95,6 +95,11 @@ func (s *Service) Archive(ctx context.Context, id uint64) error {
|
||||
return s.repo.Archive(ctx, id)
|
||||
}
|
||||
|
||||
// Unarchive 取消归档公告
|
||||
func (s *Service) Unarchive(ctx context.Context, id uint64) error {
|
||||
return s.repo.Unarchive(ctx, id)
|
||||
}
|
||||
|
||||
// Delete 删除公告
|
||||
func (s *Service) Delete(ctx context.Context, id uint64) error {
|
||||
return s.repo.Delete(ctx, id)
|
||||
|
||||
@@ -65,7 +65,7 @@ func (h *Handler) writeObject(c *gin.Context, publicOnly bool) {
|
||||
response.BadRequest(c, "文件 key 不正确")
|
||||
return
|
||||
}
|
||||
if publicOnly && !strings.HasPrefix(key, "home-banner/") && !strings.HasPrefix(key, "avatar/") && !strings.HasPrefix(key, "payment-cert/") {
|
||||
if publicOnly && !strings.HasPrefix(key, "home-banner/") && !strings.HasPrefix(key, "avatar/") && !strings.HasPrefix(key, "payment-cert/") && !strings.HasPrefix(key, "announcement/") {
|
||||
response.Error(c, http.StatusNotFound, "not_found", "文件不存在或暂不可访问")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func normalizeContentType(contentType string, data []byte) string {
|
||||
|
||||
func fileURLForScene(scene string, key string) string {
|
||||
fileURL := "/api/files/object?key=" + url.QueryEscape(key)
|
||||
if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" {
|
||||
if scene == "home-banner" || scene == "avatar" || scene == "payment-cert" || scene == "announcement" {
|
||||
fileURL = "/api/public/files/object?key=" + url.QueryEscape(key)
|
||||
}
|
||||
return fileURL
|
||||
@@ -115,7 +115,7 @@ func fileURLForScene(scene string, key string) string {
|
||||
func normalizeScene(scene string) string {
|
||||
scene = strings.TrimSpace(strings.ToLower(scene))
|
||||
switch scene {
|
||||
case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert":
|
||||
case "listing", "handoff", "dispute", "realname", "avatar", "home-banner", "chat", "payment-cert", "announcement":
|
||||
return scene
|
||||
default:
|
||||
return "misc"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package file
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSanitizeObjectMetadataEscapesNonASCII(t *testing.T) {
|
||||
got := sanitizeObjectMetadata(map[string]string{
|
||||
@@ -11,3 +14,18 @@ func TestSanitizeObjectMetadataEscapesNonASCII(t *testing.T) {
|
||||
t.Fatalf("metadata filename = %q", got["original-filename"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnnouncementSceneUsesPublicFileURL(t *testing.T) {
|
||||
key := "announcement/2026/06/15/example.webp"
|
||||
got := fileURLForScene("announcement", key)
|
||||
|
||||
if !strings.HasPrefix(got, "/api/public/files/object?") {
|
||||
t.Fatalf("announcement file url = %q, want public file endpoint", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeSceneAllowsAnnouncement(t *testing.T) {
|
||||
if got := normalizeScene("announcement"); got != "announcement" {
|
||||
t.Fatalf("normalize announcement scene = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +570,7 @@ func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine {
|
||||
adminRoutes.PUT("/announcements/:id", requirePerm("announcement:manage"), announcementHandler.Update)
|
||||
adminRoutes.POST("/announcements/:id/publish", requirePerm("announcement:manage"), announcementHandler.Publish)
|
||||
adminRoutes.POST("/announcements/:id/archive", requirePerm("announcement:manage"), announcementHandler.Archive)
|
||||
adminRoutes.POST("/announcements/:id/unarchive", requirePerm("announcement:manage"), announcementHandler.Unarchive)
|
||||
adminRoutes.DELETE("/announcements/:id", requirePerm("announcement:manage"), announcementHandler.Delete)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user