refactor: upgrade to Go 1.26 and modernize code idioms
All checks were successful
Build Backend / build (push) Successful in 3m51s
Build Backend / build-docker (push) Successful in 1m0s

- Replace `interface{}` with `any` type alias across all packages
- Use built-in `min()`/`max()` for parameter clamping
- Use `slices.SortFunc`, `slices.Min`, `slices.Max` for cleaner code
- Use `strings.Cut()` for simpler string parsing in auth middleware
- Use `errors.Is()` for proper error comparison in handlers
- Update dependencies: golang.org/x/image 0.37.0 -> 0.38.0
- Add Wire code generation guidelines to ARCHITECTURE.md
- Disable Go cache in CI build workflow
This commit is contained in:
lafay
2026-03-30 04:49:35 +08:00
parent a69b2026f4
commit b640c9a249
47 changed files with 368 additions and 352 deletions

View File

@@ -36,14 +36,9 @@ func (h *AdminDashboardHandler) GetStats(c *gin.Context) {
// GetUserActivityTrend 获取用户活跃度趋势
// GET /api/v1/admin/dashboard/user-activity
func (h *AdminDashboardHandler) GetUserActivityTrend(c *gin.Context) {
// 解析天数参数默认7天
// 解析天数参数默认7天限制在1-30天
days, _ := strconv.Atoi(c.DefaultQuery("days", "7"))
if days <= 0 {
days = 7
}
if days > 30 {
days = 30
}
days = min(max(days, 1), 30)
trend, err := h.dashboardService.GetUserActivityTrend(c.Request.Context(), days)
if err != nil {
@@ -69,14 +64,9 @@ func (h *AdminDashboardHandler) GetContentStats(c *gin.Context) {
// GetPendingContent 获取待审核内容
// GET /api/v1/admin/dashboard/pending-content
func (h *AdminDashboardHandler) GetPendingContent(c *gin.Context) {
// 解析limit参数默认10条
// 解析limit参数默认10条限制在1-50条
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
if limit <= 0 {
limit = 10
}
if limit > 50 {
limit = 50
}
limit = min(max(limit, 1), 50)
content, err := h.dashboardService.GetPendingContent(c.Request.Context(), limit)
if err != nil {

View File

@@ -1,6 +1,7 @@
package handler
import (
"errors"
"strconv"
"github.com/gin-gonic/gin"
@@ -90,7 +91,7 @@ func (h *GroupHandler) GetGroup(c *gin.Context) {
group, err := h.groupService.GetGroupByID(groupID)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -129,7 +130,7 @@ func (h *GroupHandler) UpdateGroup(c *gin.Context) {
return
}
updates := make(map[string]interface{})
updates := make(map[string]any)
if req.Name != "" {
updates["name"] = req.Name
}
@@ -145,7 +146,7 @@ func (h *GroupHandler) UpdateGroup(c *gin.Context) {
response.Forbidden(c, "没有权限修改群组信息")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -178,7 +179,7 @@ func (h *GroupHandler) DissolveGroup(c *gin.Context) {
response.Forbidden(c, "只有群主可以解散群组")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -215,7 +216,7 @@ func (h *GroupHandler) TransferOwner(c *gin.Context) {
response.Forbidden(c, "只有群主可以转让群主")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -279,7 +280,7 @@ func (h *GroupHandler) InviteMembers(c *gin.Context) {
response.Forbidden(c, "只有群成员可以邀请他人")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -314,7 +315,7 @@ func (h *GroupHandler) JoinGroup(c *gin.Context) {
response.Forbidden(c, "该群不允许加入")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -353,7 +354,7 @@ func (h *GroupHandler) LeaveGroup(c *gin.Context) {
response.BadRequest(c, "不是群成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -390,7 +391,7 @@ func (h *GroupHandler) RemoveMember(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以移除成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -429,7 +430,7 @@ func (h *GroupHandler) GetMembers(c *gin.Context) {
members, total, err := h.groupService.GetMembers(groupID, page, pageSize)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -517,7 +518,7 @@ func (h *GroupHandler) HandleGetMyMemberInfo(c *gin.Context) {
// 获取群组信息
group, err := h.groupService.GetGroupByID(groupID)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -542,7 +543,7 @@ func (h *GroupHandler) HandleGetMyMemberInfo(c *gin.Context) {
}
// 添加群组禁言状态信息
response.Success(c, map[string]interface{}{
response.Success(c, map[string]any{
"member": memberResp,
"mute_all": group.MuteAll,
"is_muted": member.Muted || group.MuteAll,
@@ -570,7 +571,7 @@ func (h *GroupHandler) HandleDissolveGroup(c *gin.Context) {
response.Forbidden(c, "只有群主可以解散群组")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -612,7 +613,7 @@ func (h *GroupHandler) HandleTransferOwner(c *gin.Context) {
response.Forbidden(c, "只有群主可以转让群主")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -657,7 +658,7 @@ func (h *GroupHandler) HandleInviteMembers(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以邀请他人")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -696,7 +697,7 @@ func (h *GroupHandler) HandleJoinGroup(c *gin.Context) {
response.Forbidden(c, "该群不允许加入")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -741,7 +742,7 @@ func (h *GroupHandler) HandleSetNickname(c *gin.Context) {
response.BadRequest(c, "不是群成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -778,7 +779,7 @@ func (h *GroupHandler) HandleSetJoinType(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置加群方式")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -824,7 +825,7 @@ func (h *GroupHandler) HandleCreateAnnouncement(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以发布公告")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -855,7 +856,7 @@ func (h *GroupHandler) HandleGetAnnouncements(c *gin.Context) {
announcements, total, err := h.groupService.GetAnnouncements(groupID, page, pageSize)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -916,7 +917,7 @@ func (h *GroupHandler) GetMyMemberInfo(c *gin.Context) {
// 获取群组信息
group, err := h.groupService.GetGroupByID(groupID)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -941,7 +942,7 @@ func (h *GroupHandler) GetMyMemberInfo(c *gin.Context) {
}
// 添加群组禁言状态信息
response.Success(c, map[string]interface{}{
response.Success(c, map[string]any{
"member": memberResp,
"mute_all": group.MuteAll,
"is_muted": member.Muted || group.MuteAll,
@@ -981,7 +982,7 @@ func (h *GroupHandler) SetMemberRole(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置成员角色")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1022,7 +1023,7 @@ func (h *GroupHandler) SetNickname(c *gin.Context) {
response.BadRequest(c, "不是群成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1065,7 +1066,7 @@ func (h *GroupHandler) MuteMember(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以禁言成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1116,7 +1117,7 @@ func (h *GroupHandler) SetMuteAll(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置全员禁言")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1157,7 +1158,7 @@ func (h *GroupHandler) SetJoinType(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置加群方式")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1205,7 +1206,7 @@ func (h *GroupHandler) CreateAnnouncement(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以发布公告")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1236,7 +1237,7 @@ func (h *GroupHandler) GetAnnouncements(c *gin.Context) {
announcements, total, err := h.groupService.GetAnnouncements(groupID, page, pageSize)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1363,7 +1364,7 @@ func (h *GroupHandler) GetMembersByCursor(c *gin.Context) {
// 调用游标分页服务
result, err := h.groupService.GetMembersByCursor(c.Request.Context(), groupID, req)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1406,7 +1407,7 @@ func (h *GroupHandler) GetAnnouncementsByCursor(c *gin.Context) {
// 调用游标分页服务
result, err := h.groupService.GetAnnouncementsByCursor(c.Request.Context(), groupID, req)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1472,7 +1473,7 @@ func (h *GroupHandler) HandleSetGroupKick(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以移除成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1543,7 +1544,7 @@ func (h *GroupHandler) HandleSetGroupBan(c *gin.Context) {
response.Forbidden(c, "只有群主或管理员可以禁言成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1593,7 +1594,7 @@ func (h *GroupHandler) HandleSetGroupWholeBan(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置全员禁言")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1646,7 +1647,7 @@ func (h *GroupHandler) HandleSetGroupAdmin(c *gin.Context) {
response.Forbidden(c, "只有群主可以设置管理员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1691,7 +1692,7 @@ func (h *GroupHandler) HandleSetGroupName(c *gin.Context) {
return
}
updates := map[string]interface{}{
updates := map[string]any{
"name": params.GroupName,
}
@@ -1701,7 +1702,7 @@ func (h *GroupHandler) HandleSetGroupName(c *gin.Context) {
response.Forbidden(c, "没有权限修改群组信息")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1740,7 +1741,7 @@ func (h *GroupHandler) HandleSetGroupAvatar(c *gin.Context) {
return
}
updates := map[string]interface{}{
updates := map[string]any{
"avatar": params.Avatar,
}
@@ -1750,7 +1751,7 @@ func (h *GroupHandler) HandleSetGroupAvatar(c *gin.Context) {
response.Forbidden(c, "没有权限修改群组信息")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1784,7 +1785,7 @@ func (h *GroupHandler) HandleSetGroupLeave(c *gin.Context) {
response.BadRequest(c, "不是群成员")
return
}
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1907,7 +1908,7 @@ func (h *GroupHandler) HandleGetGroupInfo(c *gin.Context) {
group, err := h.groupService.GetGroupByID(groupID)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}
@@ -1945,7 +1946,7 @@ func (h *GroupHandler) HandleGetGroupMemberList(c *gin.Context) {
members, total, err := h.groupService.GetMembers(groupID, page, pageSize)
if err != nil {
if err == service.ErrGroupNotFound {
if errors.Is(err, service.ErrGroupNotFound) {
response.NotFound(c, "群组不存在")
return
}

View File

@@ -1,6 +1,7 @@
package handler
import (
"errors"
"strconv"
"carrot_bbs/internal/dto"
@@ -39,21 +40,21 @@ type subjectResponse struct {
}
type materialResponse struct {
ID string `json:"id"`
SubjectID string `json:"subject_id"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
FileType string `json:"file_type"`
FileSize int64 `json:"file_size"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
DownloadCount int `json:"download_count"`
AuthorID string `json:"author_id,omitempty"`
Tags []string `json:"tags,omitempty"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Subject *subjectResponse `json:"subject,omitempty"`
ID string `json:"id"`
SubjectID string `json:"subject_id"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
FileType string `json:"file_type"`
FileSize int64 `json:"file_size"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
DownloadCount int `json:"download_count"`
AuthorID string `json:"author_id,omitempty"`
Tags []string `json:"tags,omitempty"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Subject *subjectResponse `json:"subject,omitempty"`
}
// =====================================================
@@ -170,11 +171,11 @@ func (h *MaterialHandler) ListMaterials(c *gin.Context) {
}
response.Success(c, gin.H{
"list": result,
"total": total,
"page": page,
"page_size": pageSize,
"has_more": int64(page*pageSize) < total,
"list": result,
"total": total,
"page": page,
"page_size": pageSize,
"has_more": int64(page*pageSize) < total,
})
}
@@ -305,7 +306,7 @@ func (h *MaterialHandler) AdminUpdateSubject(c *gin.Context) {
func (h *MaterialHandler) AdminDeleteSubject(c *gin.Context) {
id := c.Param("id")
if err := h.materialService.DeleteSubject(id); err != nil {
if err == service.ErrSubjectHasMaterials {
if errors.Is(err, service.ErrSubjectHasMaterials) {
response.BadRequest(c, "学科下存在资料,无法删除")
return
}

View File

@@ -1,6 +1,7 @@
package handler
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
@@ -81,11 +82,11 @@ func (h *StickerHandler) AddSticker(c *gin.Context) {
sticker, err := h.stickerService.AddSticker(userID, req.URL, req.Width, req.Height)
if err != nil {
if err == service.ErrStickerAlreadyExists {
if errors.Is(err, service.ErrStickerAlreadyExists) {
response.Error(c, http.StatusConflict, "sticker already exists")
return
}
if err == service.ErrInvalidStickerURL {
if errors.Is(err, service.ErrInvalidStickerURL) {
response.BadRequest(c, "invalid sticker url, only http/https is allowed")
return
}

View File

@@ -67,9 +67,9 @@ func (h *WSHandler) HandleWebSocket(c *gin.Context) {
if token == "" {
authHeader := c.GetHeader("Authorization")
if authHeader != "" {
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) == 2 && parts[0] == "Bearer" {
token = parts[1]
prefix, rest, found := strings.Cut(authHeader, " ")
if found && prefix == "Bearer" {
token = rest
}
}
}
@@ -489,7 +489,7 @@ func (h *WSHandler) handleCallInvite(ctx context.Context, client *ws.Client, pay
EventID: h.wsHub.NextID(),
Type: "call_invited",
TS: time.Now().UnixMilli(),
Payload: map[string]interface{}{
Payload: map[string]any{
"call_id": call.ID,
"conversation_id": req.ConversationID,
"callee_id": req.CalleeID,
@@ -528,7 +528,7 @@ func (h *WSHandler) handleCallAnswer(ctx context.Context, client *ws.Client, pay
EventID: h.wsHub.NextID(),
Type: "call_accepted",
TS: time.Now().UnixMilli(),
Payload: map[string]interface{}{
Payload: map[string]any{
"call_id": call.ID,
"started_at": call.StartedAt,
},
@@ -582,7 +582,7 @@ func (h *WSHandler) handleCallSDP(ctx context.Context, client *ws.Client, payloa
return
}
signalPayload, _ := json.Marshal(map[string]interface{}{
signalPayload, _ := json.Marshal(map[string]any{
"sdp_type": req.SDPType,
"sdp": json.RawMessage(req.SDP),
})
@@ -602,7 +602,7 @@ func (h *WSHandler) handleCallICE(ctx context.Context, client *ws.Client, payloa
return
}
signalPayload, _ := json.Marshal(map[string]interface{}{
signalPayload, _ := json.Marshal(map[string]any{
"candidate": json.RawMessage(req.Candidate),
})
if err := h.callService.RelaySignal(ctx, req.CallID, client.UserID, "call_ice", signalPayload); err != nil {
@@ -631,7 +631,7 @@ func (h *WSHandler) handleCallEnd(ctx context.Context, client *ws.Client, payloa
EventID: h.wsHub.NextID(),
Type: "call_ended",
TS: time.Now().UnixMilli(),
Payload: map[string]interface{}{
Payload: map[string]any{
"call_id": call.ID,
"duration": call.Duration,
},