Files
jiang13-bbs/backend/handler/announcement.go
freefire 996a870015 feat: 新增站点公告系统与多项体验优化
此提交完成了以下核心功能与优化:
1. 新增站点公告全流程支持:包含公告模型、CRUD接口、管理后台页面、公告详情页与首页展示
2. 实现评论楼层化与回复嵌套:重构评论系统为树状结构,支持回复评论与层级限制
3. 添加用户在线状态追踪:异步更新用户最后活跃时间并做SQL限频
4. 优化用户体验:移动端浮动操作条、统一板块标签样式、用户页签到积分展示、注册即登录优化
5. 其他细节优化:SEO站点地图新增公告页、评论分页与统计、登录/注册表单增强等
2026-09-13 21:38:01 +08:00

112 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"errors"
"net/http"
"strconv"
"github.com/freefire/jiang13-bbs/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ===== 公开接口 =====
// AnnouncementsList 已发布公告列表(首页右栏 / 公告页)
func (h *Handlers) AnnouncementsList(c *gin.Context) {
list, err := h.Announcement.ListPublished(10)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公告失败"})
return
}
c.JSON(http.StatusOK, gin.H{"announcements": list})
}
// AnnouncementDetail 已发布公告详情
func (h *Handlers) AnnouncementDetail(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的公告 ID"})
return
}
a, err := h.Announcement.GetPublished(uint(id))
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "公告不存在"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公告失败"})
return
}
c.JSON(http.StatusOK, gin.H{"announcement": a})
}
// ===== 管理接口(RequireAdmin 兜底,前端不做权限判定) =====
// AdminListAnnouncements 全部公告(含草稿)
func (h *Handlers) AdminListAnnouncements(c *gin.Context) {
list, err := h.Announcement.ListAll()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公告失败"})
return
}
c.JSON(http.StatusOK, gin.H{"announcements": list})
}
// AdminCreateAnnouncement 新建公告
func (h *Handlers) AdminCreateAnnouncement(c *gin.Context) {
var in service.AnnouncementInput
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
a, err := h.Announcement.Create(&in)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"announcement": a})
}
// AdminUpdateAnnouncement 编辑公告
func (h *Handlers) AdminUpdateAnnouncement(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的公告 ID"})
return
}
var in service.AnnouncementInput
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"})
return
}
a, err := h.Announcement.Update(uint(id), &in)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "公告不存在"})
return
}
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"announcement": a})
}
// AdminDeleteAnnouncement 删除公告
func (h *Handlers) AdminDeleteAnnouncement(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的公告 ID"})
return
}
if err := h.Announcement.Delete(uint(id)); err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "公告不存在"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除失败"})
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}