This commit is contained in:
oneao committed 2026-01-27 17:33:32 +08:00
1 parent 8663cb2e3d
commit 83cbf18572
34 files changed
+1938 -1350

No files matched your search

@@ -6,7 +6,10 @@ import (
"allapp/biz/router/middleware"
"allapp/db"
"allapp/db/repo"
"allapp/utils"
"allapp/utils/errorx"
"allapp/utils/idgen"
"allapp/utils/redisx"
"allapp/utils/response"
"context"
@@ -16,47 +19,29 @@ import (
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
// DissolveSpace .
// @router /space/dissolve [POST]
func DissolveSpace(ctx context.Context, c *app.RequestContext) {
var err error
var req space.DissolveSpaceParams
err = c.BindAndValidate(&req)
if err != nil {
// KickOutUser 踢出某人
// @router /space/kick [POST]
func KickOutUser(ctx context.Context, c *app.RequestContext) {
var req space.KickOutUserParams
if err := c.BindAndValidate(&req); err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
userID := middleware.GetUserID(ctx)
spaceByUserId, err := db.Queries.GetSpaceByUserId(ctx, userID)
spaceID := middleware.GetSpaceID(ctx)
hasPermission, err := CheckUserPermission(ctx, userID, spaceID)
if err != nil {
if errorx.IsNotFound(err) {
response.Success(c).Send()
return
} else {
errorx.AddError(c, err)
return
}
errorx.AddError(c, err)
return
}
if !hasPermission {
response.Fail(c).Message("无权限操作").Send()
return
}
spaceId := spaceByUserId.ID
err = db.WithTx(ctx, func(q *repo.Queries) error {
err := q.DeleteSpace(ctx, spaceId)
if err != nil {
return err
}
err = q.DeleteSpaceUserAll(ctx, spaceId)
if err != nil {
return err
}
return nil
})
if err != nil {
if err := LeaveSpace(ctx, req.UserId, spaceID); err != nil {
errorx.AddError(c, err)
return
}
@@ -64,20 +49,293 @@ func DissolveSpace(ctx context.Context, c *app.RequestContext) {
response.Success(c).Send()
}
// EnterSpace .
// @router /space/enter [POST]
func EnterSpace(ctx context.Context, c *app.RequestContext) {
// QuitSpace .
// @router /space/quit [POST]
func QuitSpace(ctx context.Context, c *app.RequestContext) {
var req space.QuitSpaceParams
if err := c.BindAndValidate(&req); err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
userID := middleware.GetUserID(ctx)
spaceID := req.SpaceId
// 检查权限
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, spaceID)
if err != nil {
errorx.AddError(c, err)
return
}
if !exists {
response.Fail(c).Message("已不在该空间内").Send()
return
}
err = db.WithTx(ctx, func(q *repo.Queries) error {
if role == 0 {
}
return nil
})
response.Success(c).Send()
}
// JoinSpace .
// @router /space/join [POST]
func JoinSpace(ctx context.Context, c *app.RequestContext) {
var err error
var req space.EnterSpaceParams
var req space.JoinSpaceParams
err = c.BindAndValidate(&req)
if err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp := new(space.EnterSpaceResult)
resp := new(space.JoinSpaceResult)
userID := middleware.GetUserID(ctx)
oldSpaceID := middleware.GetSpaceID(ctx)
inviteCode := req.InviteCode
spaceByInviteCode, err := db.Queries.FindSpaceByInviteCode(ctx, inviteCode)
if err != nil {
if errorx.IsNotFound(err) {
response.Fail(c).Message("邀请码错误或已过期").Send()
return
}
errorx.AddError(c, err)
return
}
joinSpaceID := spaceByInviteCode.ID
// 检查权限
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, oldSpaceID)
if err != nil {
errorx.AddError(c, err)
return
}
err = db.WithTx(ctx, func(q *repo.Queries) error {
// 判断权限, 如果角色为 0 则解散
if exists && role == 0 {
users, err2 := q.ListSpaceUsers(ctx, oldSpaceID)
if err2 != nil {
return err2
}
for _, user := range users {
if err2 := LeaveSpace(ctx, user.UserID, oldSpaceID); err2 != nil {
return err2
}
}
} else {
// 退出就行
if err2 := q.DeleteSpaceUser(ctx, repo.DeleteSpaceUserParams{
SpaceID: oldSpaceID,
UserID: userID,
}); err2 != nil {
return err2
}
if err2 := redisx.RemoveUserSpace(ctx, userID, oldSpaceID); err2 != nil {
return err2
}
// 再加入
if err2 := q.InsertSpaceUser(ctx, repo.InsertSpaceUserParams{
ID: idgen.NextId(),
UserID: userID,
SpaceID: joinSpaceID,
Role: 0,
}); err2 != nil {
return err2
}
if err2 := redisx.AddOrUpdateUserSpace(ctx, userID, joinSpaceID, 0); err2 != nil {
return err2
}
}
return nil
})
c.JSON(consts.StatusOK, resp)
}
// ListSpaceUsers .
// @router /space/users [POST]
func ListSpaceUsers(ctx context.Context, c *app.RequestContext) {
var err error
var req space.ListSpaceUsersParams
err = c.BindAndValidate(&req)
if err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp := new(space.ListSpaceUsersResult)
// 查询
users, err := db.Queries.ListSpaceUsers(ctx, req.SpaceId)
if err != nil {
errorx.AddError(c, err)
return
}
spaceUsers := make([]*space.SpaceUser, 0, len(users))
for _, user := range users {
spaceUsers = append(spaceUsers, &space.SpaceUser{
UserId: user.UserID,
UserName: user.UserName,
UserAvatar: user.UserAvatar,
Role: user.Role,
})
}
resp.Users = spaceUsers
response.Success(c).Data(spaceUsers).Send()
}
// CheckUserPermission 检查是否有权限
func CheckUserPermission(ctx context.Context, userID int64, spaceID int64) (bool, error) {
inSpace, err := redisx.InSpace(ctx, userID, spaceID)
if err != nil {
return false, err
}
if !inSpace {
return false, nil
}
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, spaceID)
if err != nil {
return false, err
}
if !exists {
return false, nil
}
return role == 0, nil
}
// LeaveSpace 处理用户离开空间逻辑(包括删除空间用户、清理 Redis、创建新空间)
func LeaveSpace(ctx context.Context, userID, spaceID int64) error {
return db.WithTx(ctx, func(q *repo.Queries) error {
// 1. 删除数据库空间用户
if err := q.DeleteSpaceUser(ctx, repo.DeleteSpaceUserParams{
UserID: userID,
SpaceID: spaceID,
}); err != nil {
return err
}
// 确保该用户加入了缓存
err := InitUserSpaces(ctx, userID)
if err != nil {
return err
}
// 2. 删除 Redis 缓存
if err := redisx.RemoveUserSpace(ctx, userID, spaceID); err != nil {
return err
}
// 3. 确保用户至少有一个空间
if err := EnsureUserHasSpaceWithTx(ctx, q, userID); err != nil {
return err
}
return nil
})
}
// InitUserSpaces 初始化用户空间信息
func InitUserSpaces(ctx context.Context, userID int64) error {
hasSpace, err := redisx.HasUserSpaces(ctx, userID)
if err != nil {
return err
}
if hasSpace {
return nil
}
spaces, err := db.Queries.ListUserSpaces(ctx, userID)
if err != nil {
return err
}
spaceRoles := make(map[int64]int32, len(spaces))
for _, row := range spaces {
spaceRoles[row.ID] = row.Role
}
return redisx.SetUserSpaces(ctx, userID, spaceRoles)
}
// EnsureUserHasSpaceWithTx 确保用户至少有一个空间,如果没有则创建新空间
// 注意:不管理事务,需要在外层传入 q *repo.Queries
func EnsureUserHasSpaceWithTx(ctx context.Context, q *repo.Queries, userID int64) error {
// 1. 查询用户现有空间
spaces, err := redisx.GetUserSpaces(ctx, userID)
if err != nil {
return err
}
if len(spaces) > 0 {
// 已经有空间,无需创建
return nil
}
// 2. 没有空间则创建
var inviteCode string
for {
code := utils.GenerateCode(6)
_, err := q.FindSpaceByInviteCode(ctx, code)
if errorx.IsNotFound(err) {
inviteCode = code
break
} else if err != nil {
return err
}
}
newSpaceID := idgen.NextId()
// 插入新空间
if err := q.InsertSpace(ctx, repo.InsertSpaceParams{
ID: newSpaceID,
InviteCode: inviteCode,
}); err != nil {
return err
}
// 插入空间用户
if err := q.InsertSpaceUser(ctx, repo.InsertSpaceUserParams{
ID: idgen.NextId(),
SpaceID: newSpaceID,
UserID: userID,
}); err != nil {
return err
}
// 同步到 Redis
if err := redisx.AddOrUpdateUserSpace(ctx, userID, newSpaceID, 0); err != nil {
return err
}
return nil
}