u
This commit is contained in:
1 parent
83cbf18572
commit
5ca04f85ca
32 files changed
+1308
-1804
No files matched your search
@@ -12,9 +12,6 @@ import (
|
||||
"allapp/utils/response"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
||||
money "allapp/biz/model/money"
|
||||
|
||||
@@ -31,85 +28,85 @@ func QueryMoneyRecord(ctx context.Context, c *app.RequestContext) {
|
||||
return
|
||||
}
|
||||
|
||||
// 解析年月
|
||||
startTime, err := time.Parse("2006-01", req.RecordTime)
|
||||
if err != nil {
|
||||
errorx.AddError(c, fmt.Errorf("invalid record_time format: %v", err))
|
||||
return
|
||||
}
|
||||
endTime := startTime.AddDate(0, 1, 0).Add(-time.Nanosecond)
|
||||
//// 解析年月
|
||||
//startTime, err := time.Parse("2006-01", req.RecordTime)
|
||||
//if err != nil {
|
||||
// errorx.AddError(c, fmt.Errorf("invalid record_time format: %v", err))
|
||||
// return
|
||||
//}
|
||||
//endTime := startTime.AddDate(0, 1, 0).Add(-time.Nanosecond)
|
||||
//
|
||||
//// 获取 userID 和 spaceID
|
||||
//userID := middleware.GetUserID(ctx)
|
||||
//spaceIspaceID := middleware.GetSpaceID(ctx)
|
||||
//
|
||||
//// 定义统一的 records 切片
|
||||
//var dbRecordsUser []repo.MoneyRecord
|
||||
//var dbRecordsSpace []repo.FindMoneyRecordsBySpaceRow
|
||||
//var errQuery error
|
||||
//
|
||||
//// 最终返回统一类型
|
||||
//var records []*money.MoneyRecord
|
||||
//
|
||||
//// 有空间ID,查询空间内所有用户
|
||||
//if ok {
|
||||
// params := repo.FindMoneyRecordsBySpaceParams{
|
||||
// SpaceID: spaceID,
|
||||
// RecordTime: pgtype.Date{Time: startTime, Valid: true},
|
||||
// RecordTime_2: pgtype.Date{Time: endTime, Valid: true},
|
||||
// }
|
||||
// dbRecordsSpace, errQuery = db.Queries.FindMoneyRecordsBySpace(ctx, params)
|
||||
// if errQuery != nil {
|
||||
// errorx.AddError(c, errQuery)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// for _, r := range dbRecordsSpace {
|
||||
// records = append(records, &money.MoneyRecord{
|
||||
// Id: r.ID,
|
||||
// CategoryId: r.CategoryID,
|
||||
// UserId: r.UserID,
|
||||
// Username: r.Username.String,
|
||||
// Amount: pgtypex.NumericToString(r.Amount),
|
||||
// Remark: r.Remark.String,
|
||||
// RecordTime: pgtypex.DateToString(r.RecordTime),
|
||||
// CreateTime: pgtypex.TimestampToMillis(r.CreateTime),
|
||||
// UpdateTime: pgtypex.TimestampToMillis(r.UpdateTime),
|
||||
// })
|
||||
// }
|
||||
//} else {
|
||||
// // 没有空间ID,只查询单用户
|
||||
// params := repo.FindUserMoneyRecordsParams{
|
||||
// UserID: userID,
|
||||
// RecordTime: pgtype.Date{Time: startTime, Valid: true},
|
||||
// RecordTime_2: pgtype.Date{Time: endTime, Valid: true},
|
||||
// }
|
||||
// dbRecordsUser, errQuery = db.Queries.FindUserMoneyRecords(ctx, params)
|
||||
// if errQuery != nil {
|
||||
// errorx.AddError(c, errQuery)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// for _, r := range dbRecordsUser {
|
||||
// records = append(records, &money.MoneyRecord{
|
||||
// Id: r.ID,
|
||||
// CategoryId: r.CategoryID,
|
||||
// UserId: r.UserID,
|
||||
// Username: "",
|
||||
// Amount: pgtypex.NumericToString(r.Amount),
|
||||
// Remark: r.Remark.String,
|
||||
// RecordTime: pgtypex.DateToString(r.RecordTime),
|
||||
// CreateTime: pgtypex.TimestampToMillis(r.CreateTime),
|
||||
// UpdateTime: pgtypex.TimestampToMillis(r.UpdateTime),
|
||||
// })
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//result := &money.QueryMoneyRecordsResult{
|
||||
// Records: records,
|
||||
//}
|
||||
|
||||
// 获取 userID 和 spaceID
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceID, ok := middleware.GetSpaceID(ctx)
|
||||
|
||||
// 定义统一的 records 切片
|
||||
var dbRecordsUser []repo.MoneyRecord
|
||||
var dbRecordsSpace []repo.FindMoneyRecordsBySpaceRow
|
||||
var errQuery error
|
||||
|
||||
// 最终返回统一类型
|
||||
var records []*money.MoneyRecord
|
||||
|
||||
// 有空间ID,查询空间内所有用户
|
||||
if ok {
|
||||
params := repo.FindMoneyRecordsBySpaceParams{
|
||||
SpaceID: spaceID,
|
||||
RecordTime: pgtype.Date{Time: startTime, Valid: true},
|
||||
RecordTime_2: pgtype.Date{Time: endTime, Valid: true},
|
||||
}
|
||||
dbRecordsSpace, errQuery = db.Queries.FindMoneyRecordsBySpace(ctx, params)
|
||||
if errQuery != nil {
|
||||
errorx.AddError(c, errQuery)
|
||||
return
|
||||
}
|
||||
|
||||
for _, r := range dbRecordsSpace {
|
||||
records = append(records, &money.MoneyRecord{
|
||||
Id: r.ID,
|
||||
CategoryId: r.CategoryID,
|
||||
UserId: r.UserID,
|
||||
Username: r.Username.String,
|
||||
Amount: pgtypex.NumericToString(r.Amount),
|
||||
Remark: r.Remark.String,
|
||||
RecordTime: pgtypex.DateToString(r.RecordTime),
|
||||
CreateTime: pgtypex.TimestampToMillis(r.CreateTime),
|
||||
UpdateTime: pgtypex.TimestampToMillis(r.UpdateTime),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 没有空间ID,只查询单用户
|
||||
params := repo.FindUserMoneyRecordsParams{
|
||||
UserID: userID,
|
||||
RecordTime: pgtype.Date{Time: startTime, Valid: true},
|
||||
RecordTime_2: pgtype.Date{Time: endTime, Valid: true},
|
||||
}
|
||||
dbRecordsUser, errQuery = db.Queries.FindUserMoneyRecords(ctx, params)
|
||||
if errQuery != nil {
|
||||
errorx.AddError(c, errQuery)
|
||||
return
|
||||
}
|
||||
|
||||
for _, r := range dbRecordsUser {
|
||||
records = append(records, &money.MoneyRecord{
|
||||
Id: r.ID,
|
||||
CategoryId: r.CategoryID,
|
||||
UserId: r.UserID,
|
||||
Username: "",
|
||||
Amount: pgtypex.NumericToString(r.Amount),
|
||||
Remark: r.Remark.String,
|
||||
RecordTime: pgtypex.DateToString(r.RecordTime),
|
||||
CreateTime: pgtypex.TimestampToMillis(r.CreateTime),
|
||||
UpdateTime: pgtypex.TimestampToMillis(r.UpdateTime),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
result := &money.QueryMoneyRecordsResult{
|
||||
Records: records,
|
||||
}
|
||||
|
||||
response.Success(c).Data(result).Send()
|
||||
response.Success(c).Send()
|
||||
}
|
||||
|
||||
// InsertMoneyRecord .
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"allapp/utils"
|
||||
"allapp/utils/errorx"
|
||||
"allapp/utils/idgen"
|
||||
"allapp/utils/redisx"
|
||||
"allapp/utils/pgtypex"
|
||||
"allapp/utils/response"
|
||||
"context"
|
||||
|
||||
@@ -19,70 +19,287 @@ import (
|
||||
"github.com/cloudwego/hertz/pkg/protocol/consts"
|
||||
)
|
||||
|
||||
// KickOutUser 踢出某人
|
||||
// @router /space/kick [POST]
|
||||
func KickOutUser(ctx context.Context, c *app.RequestContext) {
|
||||
var req space.KickOutUserParams
|
||||
if err := c.BindAndValidate(&req); err != nil {
|
||||
// CreateSpace .
|
||||
// @router /space/create [POST]
|
||||
func CreateSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.CreateSpaceParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceID := middleware.GetSpaceID(ctx)
|
||||
|
||||
hasPermission, err := CheckUserPermission(ctx, userID, spaceID)
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
if !hasPermission {
|
||||
response.Fail(c).Message("无权限操作").Send()
|
||||
return
|
||||
}
|
||||
|
||||
if err := LeaveSpace(ctx, req.UserId, spaceID); err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c).Send()
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
resp := new(space.CreateSpaceResult)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceID := req.SpaceId
|
||||
|
||||
// 检查权限
|
||||
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, spaceID)
|
||||
_, err = db.Queries.GetSpaceUser(ctx, userID)
|
||||
|
||||
var isExist = true
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
if errorx.IsNotFound(err) {
|
||||
isExist = false
|
||||
} else {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if isExist {
|
||||
response.Fail(c).Message("请先退出所在空间").Send()
|
||||
return
|
||||
}
|
||||
|
||||
if !exists {
|
||||
response.Fail(c).Message("已不在该空间内").Send()
|
||||
return
|
||||
// 生成邀请码
|
||||
var inviteCode string
|
||||
|
||||
for {
|
||||
// 生成邀请码
|
||||
code := utils.GenerateCode(6)
|
||||
|
||||
// 检查数据库是否存在
|
||||
_, err = db.Queries.FindSpaceByInviteCode(ctx, code)
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
// 不存在,唯一,直接使用
|
||||
inviteCode = code
|
||||
break
|
||||
} else {
|
||||
// 系统错误
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 如果存在,继续循环重新生成
|
||||
}
|
||||
|
||||
spaceId := idgen.NextId()
|
||||
|
||||
// 创建空间
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
if role == 0 {
|
||||
// 创建空间
|
||||
params := repo.InsertSpaceParams{
|
||||
ID: spaceId,
|
||||
Name: pgtypex.StringToText(req.Name),
|
||||
InviteCode: inviteCode,
|
||||
}
|
||||
|
||||
err = q.InsertSpace(ctx, params)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 将创建用户默认添加到该空间内
|
||||
userParams := repo.InsertSpaceUserParams{
|
||||
ID: idgen.NextId(),
|
||||
SpaceID: spaceId,
|
||||
UserID: userID,
|
||||
Role: 0,
|
||||
}
|
||||
err := q.InsertSpaceUser(ctx, userParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
response.Success(c).Send()
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp.Id = spaceId
|
||||
resp.InviteCode = inviteCode
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.DissolveSpaceResult)
|
||||
|
||||
spaceID := req.GetSpaceId()
|
||||
userID := middleware.GetUserID(ctx)
|
||||
|
||||
// 检查权限
|
||||
hasPermission, err := hasSpacePermission(ctx, userID, spaceID)
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !hasPermission {
|
||||
response.Fail(c).Message("无权限操作该空间").Send()
|
||||
return
|
||||
}
|
||||
|
||||
// 解散空间
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
err2 := q.DeleteSpace(ctx, spaceID)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
err2 = q.DeleteSpaceUsersBySpaceID(ctx, spaceID)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// ExitSpace .
|
||||
// @router /space/exit [POST]
|
||||
func ExitSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.ExitSpaceParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.ExitSpaceResult)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
|
||||
spaceUser, err := db.Queries.GetSpaceUser(ctx, userID)
|
||||
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Success(c).Data(resp).Send()
|
||||
} else {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if spaceUser.Role == 0 {
|
||||
response.Fail(c).Message("请选择解散空间").Send()
|
||||
return
|
||||
}
|
||||
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
err2 := q.DeleteSpaceUserByUserID(ctx, userID)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// ListSpaceUsers .
|
||||
// @router /space/users [POST]
|
||||
func ListSpaceUsers(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.ListSpaceUsersParams
|
||||
if err = c.BindAndValidate(&req); err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.ListSpaceUsersResult)
|
||||
|
||||
users, err := db.Queries.ListSpaceUsers(ctx, req.SpaceId)
|
||||
if err != nil {
|
||||
c.String(consts.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp.Users = make([]*space.SpaceUser, 0, len(users))
|
||||
|
||||
for _, u := range users {
|
||||
resp.Users = append(resp.Users, &space.SpaceUser{
|
||||
Id: u.UserID,
|
||||
Username: u.UserName,
|
||||
Avatar: u.UserAvatar,
|
||||
Role: u.Role,
|
||||
LastLoginTime: pgtypex.TimestamptzToMillis(u.LastLoginTime),
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// RemoveSpaceUser .
|
||||
// @router /space/remove [POST]
|
||||
func RemoveSpaceUser(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.RemoveSpaceUserParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.RemoveSpaceUserResult)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceID := req.SpaceId
|
||||
|
||||
// 检查权限
|
||||
hasPermission, err := hasSpacePermission(ctx, userID, spaceID)
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !hasPermission {
|
||||
response.Fail(c).Message("无权限操作该空间").Send()
|
||||
return
|
||||
}
|
||||
|
||||
// 移除
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
err2 := q.DeleteSpaceUserBySpaceIDAndUserID(ctx, repo.DeleteSpaceUserBySpaceIDAndUserIDParams{
|
||||
SpaceID: spaceID,
|
||||
UserID: req.UserId,
|
||||
})
|
||||
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// JoinSpace .
|
||||
@@ -99,243 +316,73 @@ func JoinSpace(ctx context.Context, c *app.RequestContext) {
|
||||
resp := new(space.JoinSpaceResult)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
oldSpaceID := middleware.GetSpaceID(ctx)
|
||||
inviteCode := req.InviteCode
|
||||
|
||||
spaceByInviteCode, err := db.Queries.FindSpaceByInviteCode(ctx, inviteCode)
|
||||
_, err = db.Queries.GetSpaceUser(ctx, userID)
|
||||
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Fail(c).Message("邀请码错误或已过期").Send()
|
||||
} else {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
errorx.AddError(c, err)
|
||||
} else {
|
||||
response.Fail(c).Message("请先退出已加入的空间").Send()
|
||||
return
|
||||
}
|
||||
|
||||
joinSpaceID := spaceByInviteCode.ID
|
||||
inviteCode := req.GetInviteCode()
|
||||
|
||||
spaceByInviteCode, err := db.Queries.FindSpaceByInviteCode(ctx, inviteCode)
|
||||
|
||||
// 检查权限
|
||||
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, oldSpaceID)
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Fail(c).Message("邀请码无效或过期").Send()
|
||||
return
|
||||
} else {
|
||||
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)
|
||||
err2 := q.InsertSpaceUser(ctx, repo.InsertSpaceUserParams{
|
||||
ID: idgen.NextId(),
|
||||
UserID: userID,
|
||||
SpaceID: spaceByInviteCode.ID,
|
||||
Role: 1,
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
if 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))
|
||||
resp.Id = spaceByInviteCode.ID
|
||||
resp.Name = spaceByInviteCode.Name.String
|
||||
|
||||
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()
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
|
||||
// CheckUserPermission 检查是否有权限
|
||||
func CheckUserPermission(ctx context.Context, userID int64, spaceID int64) (bool, error) {
|
||||
inSpace, err := redisx.InSpace(ctx, userID, spaceID)
|
||||
func hasSpacePermission(ctx context.Context, userID int64, spaceID int64) (bool, error) {
|
||||
user, err := db.Queries.GetSpaceUser(ctx, userID)
|
||||
|
||||
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
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
newSpaceID := idgen.NextId()
|
||||
|
||||
// 插入新空间
|
||||
if err := q.InsertSpace(ctx, repo.InsertSpaceParams{
|
||||
ID: newSpaceID,
|
||||
InviteCode: inviteCode,
|
||||
}); err != nil {
|
||||
return err
|
||||
if user.SpaceID != spaceID {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 插入空间用户
|
||||
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
|
||||
return user.Role == 0, nil
|
||||
}
|
||||
@@ -15,40 +15,37 @@ import (
|
||||
"github.com/cloudwego/hertz/pkg/protocol/consts"
|
||||
)
|
||||
|
||||
// ListUserSpaces .
|
||||
// @router /user/spaces [GET]
|
||||
func ListUserSpaces(ctx context.Context, c *app.RequestContext) {
|
||||
// GetUserSpace .
|
||||
// @router /user/space [GET]
|
||||
func GetUserSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req user.ListUserSpacesParams
|
||||
var req user.GetUserSpaceParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(user.ListUserSpacesResult)
|
||||
resp := new(user.UserSpace)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
|
||||
// 查询
|
||||
spaces, err := db.Queries.ListUserSpaces(ctx, userID)
|
||||
space, err := db.Queries.GetSpaceByUserId(ctx, userID)
|
||||
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Success(c).Data(resp).Send()
|
||||
return
|
||||
}
|
||||
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
userSpaces := make([]*user.UserSpace, 0, len(spaces))
|
||||
|
||||
for _, space := range spaces {
|
||||
userSpaces = append(userSpaces, &user.UserSpace{
|
||||
Id: space.ID,
|
||||
Name: space.Name.String,
|
||||
InviteCode: space.InviteCode,
|
||||
Role: space.Role,
|
||||
})
|
||||
}
|
||||
|
||||
resp.Spaces = userSpaces
|
||||
resp.Id = space.ID
|
||||
resp.Name = space.Name.String
|
||||
resp.InviteCode = space.InviteCode
|
||||
resp.Role = space.Role
|
||||
|
||||
response.Success(c).Data(resp).Send()
|
||||
}
|
||||
Reference in new issue
Block a user