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 }