Files
workspace/code/allapp/allapp-go/api/handler/space/index.go
T
2026-03-02 22:09:47 +08:00

443 lines
8.8 KiB
Go

package space
import (
"allapp/api/router/middleware"
"allapp/api/types"
"allapp/db"
"allapp/db/repo"
"allapp/utils"
"allapp/utils/errorx"
"allapp/utils/requestx"
"allapp/utils/responsex"
"allapp/utils/uniqueid"
"context"
"github.com/gofiber/fiber/v3"
)
// CreateSpace 创建空间
func CreateSpace(c fiber.Ctx) error {
dto := new(types.CreateSpaceDTO)
vo := new(types.CreateSpaceVO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userID, err2 := middleware.GetUserID(c)
if err2 != nil {
return err2
}
var inviteCode string
for {
// 生成邀请码
code := utils.GenerateCode(6)
// 检查数据库是否存在
_, err := db.Queries.GetSpaceByInviteCode(c.Context(), code)
if err != nil {
if errorx.IsNotFound(err) {
inviteCode = code
break
} else {
return err
}
}
}
spaceId := uniqueid.NextId()
err := db.WithTx(c.Context(), func(q *repo.Queries) error {
// 查询是否存在空间
countSpaces, err3 := q.CountUserSpaces(c.Context(), userID)
if err3 != nil {
return err3
}
isDefault := 0
if countSpaces == 0 {
isDefault = 1
}
// 创建空间
params := repo.InsertSpaceParams{
ID: spaceId,
Name: dto.Name,
InviteCode: inviteCode,
OwnerID: userID,
}
err := q.InsertSpace(c.Context(), params)
if err != nil {
return err
}
// 将创建用户默认添加到该空间内
spaceMemberParams := repo.InsertSpaceMemberParams{
ID: uniqueid.NextId(),
SpaceID: spaceId,
UserID: userID,
Role: 0,
IsDefault: int16(isDefault),
MemberName: dto.MemberName,
SortNumber: dto.SortNumber,
}
err = q.InsertSpaceMember(c.Context(), spaceMemberParams)
if err != nil {
return err
}
// 初始化记账
err = initFinanceCategory(c.Context(), q, spaceId, userID)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
vo.SpaceId = spaceId
vo.InviteCode = inviteCode
return responsex.OK(c, vo)
}
// ListUserSpaces 查询该用户的空间
func ListUserSpaces(c fiber.Ctx) error {
vo := new(types.ListSpacesVO)
userID, err := middleware.GetUserID(c)
if err != nil {
return err
}
rows, err := db.Queries.ListSpacesByUserId(c.Context(), userID)
if err != nil {
return err
}
userSpaces := make([]types.UserSpace, 0, len(rows))
for _, row := range rows {
userSpaces = append(userSpaces, types.UserSpace{
SpaceId: row.SpaceID,
OwnerId: row.OwnerID,
Name: row.Name,
Role: row.Role,
MemberCount: row.MemberCount,
IsDefault: row.IsDefault,
MemberName: row.MemberName,
SortNumber: row.SortNumber,
})
}
vo.Spaces = userSpaces
return responsex.OK(c, vo)
}
// DissolveSpace 解散空间
func DissolveSpace(c fiber.Ctx) error {
dto := new(types.DissolveSpaceDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
spaceId := dto.SpaceId
space, err := db.Queries.GetSpaceById(c.Context(), spaceId)
if err != nil {
if errorx.IsNotFound(err) {
return responsex.Error(c, "空间不存在或已解散")
}
return err
}
if userId != space.OwnerID {
return responsex.Error(c, "您不是该空间的拥有者,无法解散")
}
if err := db.Queries.DissolveSpace(c.Context(), spaceId); err != nil {
return err
}
return responsex.OK(c, "空间已成功解散")
}
// ExitSpace 退出空间
func ExitSpace(c fiber.Ctx) error {
dto := new(types.ExitSpaceDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
spaceId := dto.SpaceId
_, err = db.Queries.GetSpaceById(c.Context(), spaceId)
if err != nil {
if errorx.IsNotFound(err) {
return responsex.Error(c, "空间不存在或已解散")
}
return err
}
if err := db.Queries.UpdateSpaceMemberExit(c.Context(), repo.UpdateSpaceMemberExitParams{
SpaceID: spaceId,
UserID: userId,
}); err != nil {
return err
}
return responsex.OK(c, "空间已成功退出")
}
// UpdateMemberName 更新群成员名称
func UpdateMemberName(c fiber.Ctx) error {
dto := new(types.UpdateMemberNameDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
err = db.Queries.UpdateSpaceMemberName(c.Context(), repo.UpdateSpaceMemberNameParams{
SpaceID: dto.SpaceId,
UserID: userId,
MemberName: dto.MemberName,
})
if err != nil {
return err
}
return responsex.OK(c, "更新成功")
}
// UpdateSpaceDefault 更新空间默认情况
func UpdateSpaceDefault(c fiber.Ctx) error {
dto := new(types.UpdateSpaceIsDefaultDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
err = db.WithTx(c.Context(), func(q *repo.Queries) error {
err = q.UpdateSpaceIsDefault(c.Context(), repo.UpdateSpaceIsDefaultParams{
SpaceID: dto.SpaceId,
UserID: userId,
IsDefault: dto.IsDefault,
})
if err != nil {
return err
}
var otherDefault int16
if dto.IsDefault == 1 {
otherDefault = 0
}
err = q.UpdateOtherSpacesIsDefault(c.Context(), repo.UpdateOtherSpacesIsDefaultParams{
IsDefault: otherDefault,
UserID: userId,
SpaceID: dto.SpaceId,
})
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return responsex.OK(c, "更新成功")
}
// UpdateSpaceName 更新空间名称
func UpdateSpaceName(c fiber.Ctx) error {
dto := new(types.UpdateSpaceNameDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
spaceId := dto.SpaceId
space, err := db.Queries.GetSpaceById(c.Context(), spaceId)
if err != nil {
if errorx.IsNotFound(err) {
return responsex.Error(c, "空间不存在或已解散")
}
return err
}
if userId != space.OwnerID {
return responsex.Error(c, "您不是该空间的拥有者,无法修改群名称")
}
err = db.Queries.UpdateSpaceName(c.Context(), repo.UpdateSpaceNameParams{
Name: dto.SpaceName,
ID: spaceId,
})
if err != nil {
return err
}
return responsex.OK(c, "更新成功")
}
// GetSpaceSettings 获取空间配置信息
func GetSpaceSettings(c fiber.Ctx) error {
dto := new(types.GetSpaceSettingDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
spaceId := dto.SpaceId
row, err := db.Queries.GetSpaceByUserIdAndSpaceId(c.Context(), repo.GetSpaceByUserIdAndSpaceIdParams{
UserID: userId,
ID: spaceId,
})
if err != nil {
if errorx.IsNotFound(err) {
return responsex.SpaceError(c, "不在该空间或该空间已解散")
}
return err
}
vo := new(types.UserSpace)
vo.SpaceId = row.SpaceID
vo.Name = row.Name
vo.IsDefault = row.IsDefault
vo.MemberName = row.MemberName
vo.Role = row.Role
vo.MemberCount = row.MemberCount
vo.OwnerId = row.OwnerID
vo.SortNumber = row.SortNumber
vo.InviteCode = row.InviteCode
return responsex.OK(c, vo)
}
// UpdateSpaceSortNumber 更新空间排序
func UpdateSpaceSortNumber(c fiber.Ctx) error {
dto := new(types.UpdateSpaceSortNumberDTO)
if err := requestx.BindAndValidate(c, dto); err != nil {
return err
}
userId, err := middleware.GetUserID(c)
if err != nil {
return err
}
// 组装批量更新参数
params := make([]repo.BatchUpdateSpaceSortNumberParams, 0, len(dto.Spaces))
for _, datum := range dto.Spaces {
params = append(params, repo.BatchUpdateSpaceSortNumberParams{
SortNumber: datum.SortNumber,
SpaceID: datum.SpaceId,
UserID: userId,
})
}
// 使用统一事务封装
err = db.WithTx(c.Context(), func(q *repo.Queries) error {
batch := q.BatchUpdateSpaceSortNumber(c.Context(), params)
if err := db.RunBatch(c.Context(), batch); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return responsex.OK(c, "更新成功")
}
// 初始化记账分类
func initFinanceCategory(ctx context.Context, q *repo.Queries, spaceId int64, userId int64) error {
categoryDefaults, err := q.ListFinanceCategoryDefault(ctx)
if err != nil {
return err
}
if len(categoryDefaults) == 0 {
return nil
}
categorySpaces := make([]repo.BatchInsertFinanceCategorySpaceParams, 0, len(categoryDefaults))
for _, sysCat := range categoryDefaults {
categorySpaces = append(categorySpaces, repo.BatchInsertFinanceCategorySpaceParams{
ID: uniqueid.NextId(),
SpaceID: spaceId,
Name: sysCat.Name,
Icon: sysCat.Icon,
Type: sysCat.Type,
SortNumber: sysCat.SortNumber,
CreateBy: userId,
UpdateBy: userId,
})
}
if _, err := q.BatchInsertFinanceCategorySpace(ctx, categorySpaces); err != nil {
return err
}
return nil
}