From 10d0cadfe3c229a50d52de82e67a9db143def7a5 Mon Sep 17 00:00:00 2001 From: ZhangAo Date: Sat, 28 Feb 2026 17:02:35 +0800 Subject: [PATCH] u --- .../allapp-go/.idea/data_source_mapping.xml | 1 + .../allapp-go/api/handler/space/index.go | 128 ++++++++++++- code/allapp/allapp-go/api/router/router.go | 5 + code/allapp/allapp-go/api/types/space.go | 25 ++- code/allapp/allapp-go/db/queries/space.sql | 19 +- .../allapp-go/db/queries/space_member.sql | 16 +- code/allapp/allapp-go/db/repo/models.go | 36 ++-- code/allapp/allapp-go/db/repo/space.sql.go | 50 +++-- .../allapp-go/db/repo/space_member.sql.go | 38 +++- code/allapp/allapp-go/db/schema.sql | 54 ++++-- code/allapp/allapp-rn/package.json | 2 - code/allapp/allapp-rn/pnpm-lock.yaml | 30 --- code/allapp/allapp-rn/src/app/auth/index.tsx | 2 +- .../manage/components/SettingActions.tsx | 179 ++++++++++++++++++ .../space.tsx => space/manage/index.tsx} | 94 +++++++-- code/allapp/allapp-rn/src/request/index.ts | 7 +- code/allapp/allapp-rn/src/store/navigation.ts | 30 ++- .../allapp/allapp-rn/src/types/space/index.ts | 8 +- 18 files changed, 591 insertions(+), 133 deletions(-) create mode 100644 code/allapp/allapp-rn/src/app/space/manage/components/SettingActions.tsx rename code/allapp/allapp-rn/src/app/{auth/space.tsx => space/manage/index.tsx} (73%) diff --git a/code/allapp/allapp-go/.idea/data_source_mapping.xml b/code/allapp/allapp-go/.idea/data_source_mapping.xml index 8267c753..1c9b86ee 100644 --- a/code/allapp/allapp-go/.idea/data_source_mapping.xml +++ b/code/allapp/allapp-go/.idea/data_source_mapping.xml @@ -1,6 +1,7 @@ + diff --git a/code/allapp/allapp-go/api/handler/space/index.go b/code/allapp/allapp-go/api/handler/space/index.go index bc83660b..23034a77 100644 --- a/code/allapp/allapp-go/api/handler/space/index.go +++ b/code/allapp/allapp-go/api/handler/space/index.go @@ -86,7 +86,7 @@ func CreateSpace(c fiber.Ctx) error { UserID: userID, Role: 0, IsDefault: int16(isDefault), - UserName: dto.UserName, + MemberName: dto.MemberName, SortNumber: dto.SortNumber, } @@ -114,6 +114,7 @@ func CreateSpace(c fiber.Ctx) error { return responsex.OK(c, vo) } +// ListUserSpaces 查询该用户的空间 func ListUserSpaces(c fiber.Ctx) error { vo := new(types.ListSpacesVO) @@ -133,13 +134,13 @@ func ListUserSpaces(c fiber.Ctx) error { for _, row := range rows { userSpaces = append(userSpaces, types.UserSpace{ - Id: row.ID, + SpaceId: row.SpaceID, OwnerId: row.OwnerID, Name: row.Name, Role: row.Role, MemberCount: row.MemberCount, IsDefault: row.IsDefault, - UserName: row.UserName, + MemberName: row.MemberName, SortNumber: row.SortNumber, }) } @@ -149,6 +150,127 @@ func ListUserSpaces(c fiber.Ctx) error { 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, "空间已成功解散") +} + +// 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.Queries.UpdateSpaceIsDefault(c.Context(), repo.UpdateSpaceIsDefaultParams{ + SpaceID: dto.SpaceId, + UserID: userId, + IsDefault: dto.IsDefault, + }) + if err != nil { + return err + } + + return responsex.OK(c, "更新成功") +} + +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, "更新成功") +} + +// 初始化记账分类 func initFinanceCategory(ctx context.Context, q *repo.Queries, spaceId int64, userId int64) error { categoryDefaults, err := q.ListFinanceCategoryDefault(ctx) if err != nil { diff --git a/code/allapp/allapp-go/api/router/router.go b/code/allapp/allapp-go/api/router/router.go index fe0ec329..02d7c9d5 100644 --- a/code/allapp/allapp-go/api/router/router.go +++ b/code/allapp/allapp-go/api/router/router.go @@ -23,6 +23,11 @@ func SetupRouters(app *fiber.App) { spaceRouter.Post("/create", space.CreateSpace) spaceRouter.Post("/list", space.ListUserSpaces) + spaceRouter.Post("/dissolve", space.DissolveSpace) + spaceRouter.Post("/name", space.UpdateSpaceName) + + spaceRouter.Post("/member/default", space.UpdateSpaceDefault) + spaceRouter.Post("/member/name", space.UpdateMemberName) // authGroup.Get("/user/profile", user.GetProfile) // spaceGroup.Get("/space/info", space.GetInfo) diff --git a/code/allapp/allapp-go/api/types/space.go b/code/allapp/allapp-go/api/types/space.go index 3fd4c0f7..083b9860 100644 --- a/code/allapp/allapp-go/api/types/space.go +++ b/code/allapp/allapp-go/api/types/space.go @@ -2,7 +2,7 @@ package types type CreateSpaceDTO struct { Name string `json:"name" validate:"required"` - UserName string `json:"user_name" validate:"required"` + MemberName string `json:"member_name" validate:"required"` SortNumber int32 `json:"sort_number" validate:"required"` } @@ -13,16 +13,35 @@ type CreateSpaceVO struct { } type UserSpace struct { - Id int64 `json:"id"` + SpaceId int64 `json:"space_id"` OwnerId int64 `json:"owner_id"` Name string `json:"name"` Role int16 `json:"role"` MemberCount int64 `json:"member_count"` IsDefault int16 `json:"is_default"` - UserName string `json:"user_name"` + MemberName string `json:"member_name"` SortNumber int32 `json:"sort_number"` } type ListSpacesVO struct { Spaces []UserSpace `json:"spaces"` } + +type DissolveSpaceDTO struct { + SpaceId int64 `json:"space_id" validate:"required"` +} + +type UpdateMemberNameDTO struct { + SpaceId int64 `json:"space_id" validate:"required"` + MemberName string `json:"member_name" validate:"required"` +} + +type UpdateSpaceIsDefaultDTO struct { + IsDefault int16 `json:"is_default" validate:"required"` + SpaceId int64 `json:"space_id" validate:"required"` +} + +type UpdateSpaceNameDTO struct { + SpaceId int64 `json:"space_id" validate:"required"` + SpaceName string `json:"space_name" validate:"required"` +} diff --git a/code/allapp/allapp-go/db/queries/space.sql b/code/allapp/allapp-go/db/queries/space.sql index 019b9d65..a843de5f 100644 --- a/code/allapp/allapp-go/db/queries/space.sql +++ b/code/allapp/allapp-go/db/queries/space.sql @@ -9,9 +9,12 @@ INSERT INTO space ( id,name,invite_code,owner_id,create_time,update_time ) VALUES ($1,$2,$3,$4,NOW(),NOW()); --- 删除空间 --- name: DeleteSpace :exec -DELETE FROM space WHERE id = $1; +-- name: DissolveSpace :exec +UPDATE space SET + status = 2, + dissolve_time = NOW(), + update_time = NOW() +WHERE id = $1; -- 根据邀请码获取 -- name: GetSpaceByInviteCode :one @@ -19,13 +22,13 @@ SELECT * FROM space WHERE invite_code = $1; -- name: ListSpacesByUserId :many SELECT - s.id, + s.id AS space_id, s.owner_id, s.name, sm.role, COALESCE(mc.member_count, 0) AS member_count, sm.is_default, - sm.user_name, + sm.member_name, sm.sort_number FROM space s JOIN space_member sm @@ -37,4 +40,8 @@ FROM space s ) mc ON s.id = mc.space_id WHERE sm.user_id = $1 -ORDER BY sm.is_default DESC, sm.sort_number ASC; \ No newline at end of file +ORDER BY sm.is_default DESC, sm.sort_number ASC; + +-- name: UpdateSpaceName :exec +UPDATE space SET name = $1 +WHERE id = $2; diff --git a/code/allapp/allapp-go/db/queries/space_member.sql b/code/allapp/allapp-go/db/queries/space_member.sql index b4c257a8..6725528a 100644 --- a/code/allapp/allapp-go/db/queries/space_member.sql +++ b/code/allapp/allapp-go/db/queries/space_member.sql @@ -5,11 +5,23 @@ FROM space_member WHERE user_id = $1 AND space_id = $2; +-- 插入空间用户 -- name: InsertSpaceMember :exec -INSERT INTO space_member(id,space_id,user_id,role,is_default,user_name,sort_number,join_time,update_time) +INSERT INTO space_member(id,space_id,user_id,role,is_default,member_name,sort_number,join_time,update_time) VALUES ($1,$2,$3,$4,$5,$6,$7,NOW(),NOW()); +-- 合计某个用户的空间数量 -- name: CountUserSpaces :one SELECT COUNT(1) FROM space_member -WHERE user_id = $1; \ No newline at end of file +WHERE user_id = $1; + +-- 更新用户在空间内的名称 +-- name: UpdateSpaceMemberName :exec +UPDATE space_member SET member_name = $1 +WHERE space_id = $2 AND user_id = $3; + +-- 更新空间是否为默认 +-- name: UpdateSpaceIsDefault :exec +UPDATE space_member SET is_default = $1 +WHERE space_id = $2 AND user_id = $3; diff --git a/code/allapp/allapp-go/db/repo/models.go b/code/allapp/allapp-go/db/repo/models.go index 032fe164..8c602775 100644 --- a/code/allapp/allapp-go/db/repo/models.go +++ b/code/allapp/allapp-go/db/repo/models.go @@ -32,24 +32,30 @@ type FinanceCategorySpace struct { } type Space struct { - ID int64 - Name string - InviteCode string - OwnerID int64 - CreateTime pgtype.Timestamptz - UpdateTime pgtype.Timestamptz + ID int64 + Name string + InviteCode string + OwnerID int64 + Status int16 + DisabledTime pgtype.Timestamptz + DissolveTime pgtype.Timestamptz + CreateTime pgtype.Timestamptz + UpdateTime pgtype.Timestamptz } type SpaceMember struct { - ID int64 - SpaceID int64 - UserID int64 - Role int16 - IsDefault int16 - UserName string - SortNumber int32 - JoinTime pgtype.Timestamptz - UpdateTime pgtype.Timestamptz + ID int64 + SpaceID int64 + UserID int64 + Role int16 + IsDefault int16 + SortNumber int32 + MemberName string + Status int16 + DisabledTime pgtype.Timestamptz + ExitTime pgtype.Timestamptz + JoinTime pgtype.Timestamptz + UpdateTime pgtype.Timestamptz } type User struct { diff --git a/code/allapp/allapp-go/db/repo/space.sql.go b/code/allapp/allapp-go/db/repo/space.sql.go index a89d30c1..245243c3 100644 --- a/code/allapp/allapp-go/db/repo/space.sql.go +++ b/code/allapp/allapp-go/db/repo/space.sql.go @@ -9,18 +9,21 @@ import ( "context" ) -const deleteSpace = `-- name: DeleteSpace :exec -DELETE FROM space WHERE id = $1 +const dissolveSpace = `-- name: DissolveSpace :exec +UPDATE space SET + status = 2, + dissolve_time = NOW(), + update_time = NOW() +WHERE id = $1 ` -// 删除空间 -func (q *Queries) DeleteSpace(ctx context.Context, id int64) error { - _, err := q.db.Exec(ctx, deleteSpace, id) +func (q *Queries) DissolveSpace(ctx context.Context, id int64) error { + _, err := q.db.Exec(ctx, dissolveSpace, id) return err } const getSpaceById = `-- name: GetSpaceById :one -SELECT id, name, invite_code, owner_id, create_time, update_time FROM space WHERE id = $1 +SELECT id, name, invite_code, owner_id, status, disabled_time, dissolve_time, create_time, update_time FROM space WHERE id = $1 ` // 根据id获取分享空间信息 @@ -32,6 +35,9 @@ func (q *Queries) GetSpaceById(ctx context.Context, id int64) (Space, error) { &i.Name, &i.InviteCode, &i.OwnerID, + &i.Status, + &i.DisabledTime, + &i.DissolveTime, &i.CreateTime, &i.UpdateTime, ) @@ -39,7 +45,7 @@ func (q *Queries) GetSpaceById(ctx context.Context, id int64) (Space, error) { } const getSpaceByInviteCode = `-- name: GetSpaceByInviteCode :one -SELECT id, name, invite_code, owner_id, create_time, update_time FROM space WHERE invite_code = $1 +SELECT id, name, invite_code, owner_id, status, disabled_time, dissolve_time, create_time, update_time FROM space WHERE invite_code = $1 ` // 根据邀请码获取 @@ -51,6 +57,9 @@ func (q *Queries) GetSpaceByInviteCode(ctx context.Context, inviteCode string) ( &i.Name, &i.InviteCode, &i.OwnerID, + &i.Status, + &i.DisabledTime, + &i.DissolveTime, &i.CreateTime, &i.UpdateTime, ) @@ -83,13 +92,13 @@ func (q *Queries) InsertSpace(ctx context.Context, arg InsertSpaceParams) error const listSpacesByUserId = `-- name: ListSpacesByUserId :many SELECT - s.id, + s.id AS space_id, s.owner_id, s.name, sm.role, COALESCE(mc.member_count, 0) AS member_count, sm.is_default, - sm.user_name, + sm.member_name, sm.sort_number FROM space s JOIN space_member sm @@ -105,13 +114,13 @@ ORDER BY sm.is_default DESC, sm.sort_number ASC ` type ListSpacesByUserIdRow struct { - ID int64 + SpaceID int64 OwnerID int64 Name string Role int16 MemberCount int64 IsDefault int16 - UserName string + MemberName string SortNumber int32 } @@ -125,13 +134,13 @@ func (q *Queries) ListSpacesByUserId(ctx context.Context, userID int64) ([]ListS for rows.Next() { var i ListSpacesByUserIdRow if err := rows.Scan( - &i.ID, + &i.SpaceID, &i.OwnerID, &i.Name, &i.Role, &i.MemberCount, &i.IsDefault, - &i.UserName, + &i.MemberName, &i.SortNumber, ); err != nil { return nil, err @@ -143,3 +152,18 @@ func (q *Queries) ListSpacesByUserId(ctx context.Context, userID int64) ([]ListS } return items, nil } + +const updateSpaceName = `-- name: UpdateSpaceName :exec +UPDATE space SET name = $1 +WHERE id = $2 +` + +type UpdateSpaceNameParams struct { + Name string + ID int64 +} + +func (q *Queries) UpdateSpaceName(ctx context.Context, arg UpdateSpaceNameParams) error { + _, err := q.db.Exec(ctx, updateSpaceName, arg.Name, arg.ID) + return err +} diff --git a/code/allapp/allapp-go/db/repo/space_member.sql.go b/code/allapp/allapp-go/db/repo/space_member.sql.go index e6693a2f..086ee0c2 100644 --- a/code/allapp/allapp-go/db/repo/space_member.sql.go +++ b/code/allapp/allapp-go/db/repo/space_member.sql.go @@ -43,7 +43,7 @@ func (q *Queries) GetUserSpaceRole(ctx context.Context, arg GetUserSpaceRolePara } const insertSpaceMember = `-- name: InsertSpaceMember :exec -INSERT INTO space_member(id,space_id,user_id,role,is_default,user_name,sort_number,join_time,update_time) +INSERT INTO space_member(id,space_id,user_id,role,is_default,member_name,sort_number,join_time,update_time) VALUES ($1,$2,$3,$4,$5,$6,$7,NOW(),NOW()) ` @@ -53,7 +53,7 @@ type InsertSpaceMemberParams struct { UserID int64 Role int16 IsDefault int16 - UserName string + MemberName string SortNumber int32 } @@ -64,8 +64,40 @@ func (q *Queries) InsertSpaceMember(ctx context.Context, arg InsertSpaceMemberPa arg.UserID, arg.Role, arg.IsDefault, - arg.UserName, + arg.MemberName, arg.SortNumber, ) return err } + +const updateSpaceIsDefault = `-- name: UpdateSpaceIsDefault :exec +UPDATE space_member SET is_default = $1 +WHERE space_id = $2 AND user_id = $3 +` + +type UpdateSpaceIsDefaultParams struct { + IsDefault int16 + SpaceID int64 + UserID int64 +} + +func (q *Queries) UpdateSpaceIsDefault(ctx context.Context, arg UpdateSpaceIsDefaultParams) error { + _, err := q.db.Exec(ctx, updateSpaceIsDefault, arg.IsDefault, arg.SpaceID, arg.UserID) + return err +} + +const updateSpaceMemberName = `-- name: UpdateSpaceMemberName :exec +UPDATE space_member SET member_name = $1 +WHERE space_id = $2 AND user_id = $3 +` + +type UpdateSpaceMemberNameParams struct { + MemberName string + SpaceID int64 + UserID int64 +} + +func (q *Queries) UpdateSpaceMemberName(ctx context.Context, arg UpdateSpaceMemberNameParams) error { + _, err := q.db.Exec(ctx, updateSpaceMemberName, arg.MemberName, arg.SpaceID, arg.UserID) + return err +} diff --git a/code/allapp/allapp-go/db/schema.sql b/code/allapp/allapp-go/db/schema.sql index 5a40d3fe..f9b48b4e 100644 --- a/code/allapp/allapp-go/db/schema.sql +++ b/code/allapp/allapp-go/db/schema.sql @@ -23,27 +23,47 @@ primary key, create table space ( - id bigint not null - primary key, - name varchar(255) not null, - invite_code varchar(30) not null, - owner_id bigint not null, - create_time timestamp with time zone default now(), - update_time timestamp with time zone default now() + id bigint primary key, + + -- 核心业务字段 + name varchar(255) not null, + invite_code varchar(30) not null unique, + owner_id bigint not null, + + -- 状态字段 + status smallint default 0 not null, -- 0 active 1 disabled 2 dissolved + disabled_time timestamp with time zone, + dissolve_time timestamp with time zone, + + -- 时间字段 + create_time timestamp with time zone default now() not null, + update_time timestamp with time zone default now() not null ); create table space_member ( - id bigint not null - primary key, - space_id bigint not null, - user_id bigint not null, - role smallint default 2 not null, - is_default smallint default 0 not null, - user_name varchar(255) not null, - sort_number integer default 0 not null, - join_time timestamp with time zone default now(), - update_time timestamp with time zone default now() + id bigint primary key, + + -- 关系核心字段 + space_id bigint not null, + user_id bigint not null, + + -- 角色 & 默认 + role smallint default 2 not null, + is_default smallint default 0 not null, + sort_number integer default 0 not null, + member_name varchar(255) not null, + + -- 成员状态 + status smallint default 0 not null, -- 0 active 1 disabled 2 exited + disabled_time timestamp with time zone, + exit_time timestamp with time zone, + + -- 时间字段 + join_time timestamp with time zone default now() not null, + update_time timestamp with time zone default now() not null, + + unique (space_id, user_id) ); create table finance_category_default diff --git a/code/allapp/allapp-rn/package.json b/code/allapp/allapp-rn/package.json index f9fccdea..1c56b96c 100644 --- a/code/allapp/allapp-rn/package.json +++ b/code/allapp/allapp-rn/package.json @@ -56,10 +56,8 @@ "react-native-screens": "~4.16.0", "react-native-sortables": "^1.9.3", "react-native-svg": "15.12.1", - "react-native-toast-message": "^2.3.3", "react-native-web": "^0.21.0", "react-native-worklets": "0.5.1", - "react-native-z-view": "^0.2.4", "sonner-native": "^0.23.1", "tailwind-merge": "^3.4.0", "victory-native": "^37.3.6", diff --git a/code/allapp/allapp-rn/pnpm-lock.yaml b/code/allapp/allapp-rn/pnpm-lock.yaml index afade9dc..47f683bc 100644 --- a/code/allapp/allapp-rn/pnpm-lock.yaml +++ b/code/allapp/allapp-rn/pnpm-lock.yaml @@ -146,18 +146,12 @@ importers: react-native-svg: specifier: 15.12.1 version: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) - react-native-toast-message: - specifier: ^2.3.3 - version: 2.3.3(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) react-native-web: specifier: ^0.21.0 version: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-native-worklets: specifier: 0.5.1 version: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) - react-native-z-view: - specifier: ^0.2.4 - version: 0.2.4(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) sonner-native: specifier: ^0.23.1 version: 0.23.1(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.5(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) @@ -5123,12 +5117,6 @@ packages: react: '*' react-native: '*' - react-native-toast-message@2.3.3: - resolution: {integrity: sha512-4IIUHwUPvKHu4gjD0Vj2aGQzqPATiblL1ey8tOqsxOWRPGGu52iIbL8M/mCz4uyqecvPdIcMY38AfwRuUADfQQ==} - peerDependencies: - react: '*' - react-native: '*' - react-native-web@0.21.2: resolution: {integrity: sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==} peerDependencies: @@ -5142,13 +5130,6 @@ packages: react: '*' react-native: '*' - react-native-z-view@0.2.4: - resolution: {integrity: sha512-K/z6GhHmDsyEZAy6ib8DEmITSyPb0rCJ95IZjilZbAarx8xB6prdvHvtgmCg67nFKO/l/ldBuYhvxQmClda+pQ==} - peerDependencies: - react: '*' - react-native: '*' - react-native-screens: '*' - react-native@0.81.5: resolution: {integrity: sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==} engines: {node: '>= 20.19.4'} @@ -12365,11 +12346,6 @@ snapshots: react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) warn-once: 0.1.1 - react-native-toast-message@2.3.3(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): - dependencies: - react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) - react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@babel/runtime': 7.28.4 @@ -12404,12 +12380,6 @@ snapshots: transitivePeerDependencies: - supports-color - react-native-z-view@0.2.4(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): - dependencies: - react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) - react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) - react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0): dependencies: '@jest/create-cache-key-function': 29.7.0 diff --git a/code/allapp/allapp-rn/src/app/auth/index.tsx b/code/allapp/allapp-rn/src/app/auth/index.tsx index 21911afb..e2d1c8c2 100644 --- a/code/allapp/allapp-rn/src/app/auth/index.tsx +++ b/code/allapp/allapp-rn/src/app/auth/index.tsx @@ -127,7 +127,7 @@ export default function Auth() { // avatar: loginRes.data.avatar, // }) - // router.push('/auth/space') + // router.push('/space/manage') // } // } // catch (err) { diff --git a/code/allapp/allapp-rn/src/app/space/manage/components/SettingActions.tsx b/code/allapp/allapp-rn/src/app/space/manage/components/SettingActions.tsx new file mode 100644 index 00000000..cf99c891 --- /dev/null +++ b/code/allapp/allapp-rn/src/app/space/manage/components/SettingActions.tsx @@ -0,0 +1,179 @@ +import type { UserSpace } from '@/types/space' +import { useEffect, useState } from 'react' +import { Text, View } from 'react-native' +import { toast } from 'sonner-native' +import { LucideIcon } from '@/components/common/ao' +import { AInput, AModal } from '@/components/common/ao/index' +import { + Actionsheet, + ActionsheetBackdrop, + ActionsheetContent, + ActionsheetDragIndicator, + ActionsheetDragIndicatorWrapper, + ActionsheetIcon, + ActionsheetItem, + ActionsheetItemText, +} from '@/components/ui/actionsheet' +import { dissolveSpaceApi } from '@/request/api/space' +import { useUserStore } from '@/store/user' + +interface SettingActionsProps { + isOpen: boolean + onClose: () => void + + space: UserSpace | null + + onActionSuccess?: () => void +} + +export default function SettingActions( + { + isOpen, + onClose, + space, + onActionSuccess + }: SettingActionsProps, +) { + const userStore = useUserStore() + + const [localSpace, setLocalSpace] = useState(space) + + const [showNameModal, setShowNameModal] = useState(false) + + const [showMemberNameModal, setShowMemberNameModal] = useState(false) + + useEffect(() => { + setLocalSpace(space) + }, [space]) + return ( + <> + { + onClose() + }} + > + + + + + + { + space?.role === 0 && ( + + } + /> + 成员管理 + + ) + } + + { + space?.owner_id === userStore.userInfo.id && ( + { + setShowNameModal(true) + }} + > + } + /> + 修改空间名称 + + ) + } + + + } + /> + 修改我的空间昵称 + + + + } + /> + + {space?.is_default === 1 ? '取消' : '设置'} + 默认 + + + + { + if (space?.owner_id === userStore.userInfo.id) { + // 解散空间 + dissolveSpaceApi({ + space_id: space.space_id, + }).then((res) => { + if (res.isSuccess) { + toast.success('空间已解散') + onActionSuccess?. + } + }, + ) + } + else { + // 退出空间 + } + }} + > + } + /> + + {space?.owner_id === userStore.userInfo.id ? '解散' : '退出'} + 空间 + + + + + + + + 空间名称 + { + setLocalSpace(prev => prev + ? ({ + ...prev, + name: val, + }) + : null) + }} + className="flex-1" + /> + + ) + } + isOpen={showNameModal} + onCancel={() => { + setShowNameModal(false) + setLocalSpace(space) + }} + onClose={() => { + setShowNameModal(false) + setLocalSpace(space) + }} + onConfirm={async () => { + // 更新名称 + if (!localSpace?.name) { + toast.warning('请输入空间名称') + } + }} + > + + + + ) +} diff --git a/code/allapp/allapp-rn/src/app/auth/space.tsx b/code/allapp/allapp-rn/src/app/space/manage/index.tsx similarity index 73% rename from code/allapp/allapp-rn/src/app/auth/space.tsx rename to code/allapp/allapp-rn/src/app/space/manage/index.tsx index 390de382..3703e318 100644 --- a/code/allapp/allapp-rn/src/app/auth/space.tsx +++ b/code/allapp/allapp-rn/src/app/space/manage/index.tsx @@ -1,5 +1,5 @@ import type { UserSpace } from '@/types/space' -import { useCallback, useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { Pressable, Text, View } from 'react-native' import Animated, { useAnimatedRef } from 'react-native-reanimated' import Sortable from 'react-native-sortables' @@ -11,12 +11,18 @@ import CustomHeader from '@/components/custom/Header' import { Badge, BadgeText } from '@/components/ui/badge' import { createSpaceApi, listUserSpacesApi } from '@/request/api/space/index' import { useUserStore } from '@/store/user' +import SettingActions from './components/SettingActions' export default function AuthSpace() { const userStore = useUserStore() + // scrollView 相关 const scrollableRef = useAnimatedRef() + const [scrollHeight, setScrollHeight] = useState(0) + const ITEM_HEIGHT = 64 + // 空间列表 + const [spaces, setSpaces] = useState([]) const [selectedId, setSelectedId] = useState(null) // 新建 @@ -25,8 +31,11 @@ export default function AuthSpace() { name: '', }) - const [spaces, setSpaces] = useState([]) + // 设置 + const [showSettings, setShowSettings] = useState(false) + const [settingCurrentSpace, setSettingCurrentSpace] = useState(null) + // 获取空间列表 function listUserSpaces() { listUserSpacesApi().then((res) => { if (res.isSuccess) { @@ -36,12 +45,18 @@ export default function AuthSpace() { } const renderItem - = ({ item }: { item: UserSpace }) => ( + = ({ item, index }: { item: UserSpace, index: number }) => ( setSelectedId(item.id)} + key={item.space_id} + onPress={() => { + setSelectedId(item.space_id) + scrollToCenter(index) + }} + style={{ + height: ITEM_HEIGHT, + }} className={`rounded-md flex-row items-center justify-between px-4 py-3 border - ${item.id === selectedId ? 'border-gray-700' : 'border-gray-300'}`} + ${item.space_id === selectedId ? 'border-gray-700' : 'border-gray-300'}`} > @@ -83,7 +98,7 @@ export default function AuthSpace() { - {item.user_name} + {item.member_name} @@ -98,21 +113,55 @@ export default function AuthSpace() { - + + + + + + { + e.stopPropagation() + setSettingCurrentSpace(item) + setShowSettings(true) + }} + > + + + ) + const scrollToCenter = (index: number) => { + if (!scrollHeight) + return + + const itemTop = index * ITEM_HEIGHT + + const scrollY + = itemTop - scrollHeight / 2 + ITEM_HEIGHT / 2 + + scrollableRef.current?.scrollTo({ + y: Math.max(0, scrollY), + animated: true, + }) + } + useEffect(() => { listUserSpaces() }, []) return ( - {/* Header */} @@ -146,6 +195,9 @@ export default function AuthSpace() { className="flex-1" showsVerticalScrollIndicator={false} ref={scrollableRef} + onLayout={(e) => { + setScrollHeight(e.nativeEvent.layout.height) + }} > {spaces.length === 0 ? ( @@ -218,7 +270,7 @@ export default function AuthSpace() { await createSpaceApi({ name: createForm.name, - user_name: userStore.userInfo.nickname, + member_name: userStore.userInfo.nickname, sort_number: 0, }).then((res) => { if (res.isSuccess) { @@ -227,11 +279,25 @@ export default function AuthSpace() { setCreateForm({ name: '', }) + + listUserSpaces() } }) }} > + + { + setShowSettings(false) + + setTimeout(() => { + setSettingCurrentSpace(null) + }, 300) + }} + space={settingCurrentSpace} + /> ) } diff --git a/code/allapp/allapp-rn/src/request/index.ts b/code/allapp/allapp-rn/src/request/index.ts index fcb0f7c5..6f234895 100644 --- a/code/allapp/allapp-rn/src/request/index.ts +++ b/code/allapp/allapp-rn/src/request/index.ts @@ -2,9 +2,9 @@ import type { Method } from 'alova' import type { AxiosError } from 'axios' import { axiosRequestAdapter } from '@alova/adapter-axios' import { createAlova } from 'alova' +import { toast } from 'sonner-native' import { useNavStore } from '@/store/navigation' import { useUserStore } from '@/store/user' -import { toast } from '@/utils/toast' enum HttpCode { Success = 1000, @@ -28,8 +28,8 @@ function isWhiteListed(url: string) { } const alovaInstance = createAlova({ - baseURL: 'http://192.168.5.6:8086/app', - // baseURL: 'http://192.168.1.137:8086/app', + // baseURL: 'http://192.168.5.6:8086/app', + baseURL: 'http://192.168.1.137:8086/app', requestAdapter: axiosRequestAdapter(), timeout: 5000, cacheFor: null, @@ -44,6 +44,7 @@ const alovaInstance = createAlova({ } if (resData.code === HttpCode.Unauthorized) { + toast.error('登录状态已过期,请重新登录') useUserStore.getState().clear() useNavStore.getState().navigateToAuth() return result diff --git a/code/allapp/allapp-rn/src/store/navigation.ts b/code/allapp/allapp-rn/src/store/navigation.ts index 2051d607..5cedfe2e 100644 --- a/code/allapp/allapp-rn/src/store/navigation.ts +++ b/code/allapp/allapp-rn/src/store/navigation.ts @@ -23,28 +23,22 @@ const DEFAULT_NAV_MENUS: NavItem[] = [ { label: '恋爱记', path: '/love', icon: 'Heart' }, { label: '聊天', path: '/chat', icon: 'MessageCircle' }, { label: '个人中心', path: '/user', icon: 'CircleUserRound' }, - { label: '我的空间', path: '/auth/space', icon: 'Earth' }, + { label: '我的空间', path: '/space/manage', icon: 'Earth' }, ] export const useNavStore = create()( - persist( - (set, get) => ({ - pathname: '/', - navMenus: DEFAULT_NAV_MENUS, + (set, get) => ({ + pathname: '/', + navMenus: DEFAULT_NAV_MENUS, - setPathname: (p: string) => set({ pathname: p }), - navigateToAuth: () => { - const pathname = useNavStore.getState().pathname + setPathname: (p: string) => set({ pathname: p }), + navigateToAuth: () => { + const pathname = useNavStore.getState().pathname - if (pathname !== '/auth') { - router.replace('/auth') - } - }, - setNavMenus: navMenus => set({ navMenus }), - }), - { - name: 'nav-storage', - storage: createJSONStorage(() => AsyncStorage), + if (pathname !== '/auth') { + router.replace('/auth') + } }, - ), + setNavMenus: navMenus => set({ navMenus }), + }), ) diff --git a/code/allapp/allapp-rn/src/types/space/index.ts b/code/allapp/allapp-rn/src/types/space/index.ts index db25a983..ec924083 100644 --- a/code/allapp/allapp-rn/src/types/space/index.ts +++ b/code/allapp/allapp-rn/src/types/space/index.ts @@ -1,21 +1,22 @@ export interface UserSpace { - id: number + space_id: number owner_id: number name: string role: number member_count: number is_default: number - user_name: string + member_name: string sort_number: number } // 创建空间 export interface CreateSpaceParams { name: string - user_name: string + member_name: string sort_number: number } + export interface CreateSpaceResult { space_id: number invite_code: string @@ -37,6 +38,7 @@ export interface DissolveSpaceResult { export interface JoinSpaceParams { invite_code: string } + export interface JoinSpaceResult { space_id: number space_name: string