diff --git a/code/allapp/allapp-go/api/handler/space/index.go b/code/allapp/allapp-go/api/handler/space/index.go index 5c6b9f30..8cbcd1fd 100644 --- a/code/allapp/allapp-go/api/handler/space/index.go +++ b/code/allapp/allapp-go/api/handler/space/index.go @@ -183,6 +183,38 @@ func DissolveSpace(c fiber.Ctx) error { 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) @@ -257,6 +289,7 @@ func UpdateSpaceDefault(c fiber.Ctx) error { return responsex.OK(c, "更新成功") } +// UpdateSpaceName 更新空间名称 func UpdateSpaceName(c fiber.Ctx) error { dto := new(types.UpdateSpaceNameDTO) if err := requestx.BindAndValidate(c, dto); err != nil { @@ -295,6 +328,7 @@ func UpdateSpaceName(c fiber.Ctx) error { return responsex.OK(c, "更新成功") } +// GetSpaceSettings 获取空间配置信息 func GetSpaceSettings(c fiber.Ctx) error { dto := new(types.GetSpaceSettingDTO) if err := requestx.BindAndValidate(c, dto); err != nil { @@ -329,6 +363,7 @@ func GetSpaceSettings(c fiber.Ctx) error { vo.MemberCount = row.MemberCount vo.OwnerId = row.OwnerID vo.SortNumber = row.SortNumber + vo.InviteCode = row.InviteCode return responsex.OK(c, vo) } diff --git a/code/allapp/allapp-go/api/router/router.go b/code/allapp/allapp-go/api/router/router.go index da2c6d69..61b7e9b0 100644 --- a/code/allapp/allapp-go/api/router/router.go +++ b/code/allapp/allapp-go/api/router/router.go @@ -30,6 +30,7 @@ func SetupRouters(app *fiber.App) { spaceRouter.Post("/member/default", space.UpdateSpaceDefault) spaceRouter.Post("/member/name", space.UpdateMemberName) spaceRouter.Post("/member/sortNumber", space.UpdateSpaceSortNumber) + spaceRouter.Post("/member/exit", space.ExitSpace) // 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 666f24b6..fdc07d23 100644 --- a/code/allapp/allapp-go/api/types/space.go +++ b/code/allapp/allapp-go/api/types/space.go @@ -21,6 +21,7 @@ type UserSpace struct { IsDefault int16 `json:"is_default"` MemberName string `json:"member_name"` SortNumber int32 `json:"sort_number"` + InviteCode string `json:"invite_code"` } type ListSpacesVO struct { @@ -31,6 +32,10 @@ type DissolveSpaceDTO struct { SpaceId int64 `json:"space_id" validate:"required"` } +type ExitSpaceDTO 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"` diff --git a/code/allapp/allapp-go/db/queries/space.sql b/code/allapp/allapp-go/db/queries/space.sql index 08466b49..0ae0731d 100644 --- a/code/allapp/allapp-go/db/queries/space.sql +++ b/code/allapp/allapp-go/db/queries/space.sql @@ -39,7 +39,7 @@ FROM space s GROUP BY space_id ) mc ON s.id = mc.space_id -WHERE sm.user_id = $1 +WHERE sm.user_id = $1 AND s.status != 2 AND sm.status != 2 ORDER BY sm.is_default DESC, sm.sort_number ASC; -- name: GetSpaceByUserIdAndSpaceId :one @@ -51,7 +51,8 @@ SELECT COALESCE(mc.member_count, 0) AS member_count, sm.is_default, sm.member_name, - sm.sort_number + sm.sort_number, + s.invite_code FROM space s JOIN space_member sm ON s.id = sm.space_id @@ -61,7 +62,7 @@ FROM space s GROUP BY space_id ) mc ON s.id = mc.space_id -WHERE sm.user_id = $1 AND s.id = $2 +WHERE sm.user_id = $1 AND s.id = $2 AND s.status != 2 AND sm.status != 2 ORDER BY sm.is_default DESC, sm.sort_number ASC; -- name: UpdateSpaceName :exec diff --git a/code/allapp/allapp-go/db/queries/space_member.sql b/code/allapp/allapp-go/db/queries/space_member.sql index ff3b0693..258e0bf9 100644 --- a/code/allapp/allapp-go/db/queries/space_member.sql +++ b/code/allapp/allapp-go/db/queries/space_member.sql @@ -38,4 +38,11 @@ WHERE user_id = $2 UPDATE space_member SET sort_number = $1 WHERE user_id = $2 - AND space_id = $3; \ No newline at end of file + AND space_id = $3; + +-- 退出空间 +-- name: UpdateSpaceMemberExit :exec +UPDATE space_member +SET status = 2 AND exit_time = NOW() +WHERE space_id = $1 + AND user_id = $2; \ No newline at end of file diff --git a/code/allapp/allapp-go/db/repo/space.sql.go b/code/allapp/allapp-go/db/repo/space.sql.go index cd07e10a..4c9cbed8 100644 --- a/code/allapp/allapp-go/db/repo/space.sql.go +++ b/code/allapp/allapp-go/db/repo/space.sql.go @@ -75,7 +75,8 @@ SELECT COALESCE(mc.member_count, 0) AS member_count, sm.is_default, sm.member_name, - sm.sort_number + sm.sort_number, + s.invite_code FROM space s JOIN space_member sm ON s.id = sm.space_id @@ -85,7 +86,7 @@ FROM space s GROUP BY space_id ) mc ON s.id = mc.space_id -WHERE sm.user_id = $1 AND s.id = $2 +WHERE sm.user_id = $1 AND s.id = $2 AND s.status != 2 AND sm.status != 2 ORDER BY sm.is_default DESC, sm.sort_number ASC ` @@ -103,6 +104,7 @@ type GetSpaceByUserIdAndSpaceIdRow struct { IsDefault int16 MemberName string SortNumber int32 + InviteCode string } func (q *Queries) GetSpaceByUserIdAndSpaceId(ctx context.Context, arg GetSpaceByUserIdAndSpaceIdParams) (GetSpaceByUserIdAndSpaceIdRow, error) { @@ -117,6 +119,7 @@ func (q *Queries) GetSpaceByUserIdAndSpaceId(ctx context.Context, arg GetSpaceBy &i.IsDefault, &i.MemberName, &i.SortNumber, + &i.InviteCode, ) return i, err } @@ -164,7 +167,7 @@ FROM space s GROUP BY space_id ) mc ON s.id = mc.space_id -WHERE sm.user_id = $1 +WHERE sm.user_id = $1 AND s.status != 2 AND sm.status != 2 ORDER BY sm.is_default DESC, sm.sort_number ASC ` 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 680476f8..3eccdd99 100644 --- a/code/allapp/allapp-go/db/repo/space_member.sql.go +++ b/code/allapp/allapp-go/db/repo/space_member.sql.go @@ -108,6 +108,24 @@ func (q *Queries) UpdateSpaceIsDefault(ctx context.Context, arg UpdateSpaceIsDef return err } +const updateSpaceMemberExit = `-- name: UpdateSpaceMemberExit :exec +UPDATE space_member +SET status = 2 AND exit_time = NOW() +WHERE space_id = $1 + AND user_id = $2 +` + +type UpdateSpaceMemberExitParams struct { + SpaceID int64 + UserID int64 +} + +// 退出空间 +func (q *Queries) UpdateSpaceMemberExit(ctx context.Context, arg UpdateSpaceMemberExitParams) error { + _, err := q.db.Exec(ctx, updateSpaceMemberExit, 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 diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx b/code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx new file mode 100644 index 00000000..5981ba3c --- /dev/null +++ b/code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx @@ -0,0 +1,96 @@ +import * as Clipboard from 'expo-clipboard' +import { useLocalSearchParams } from 'expo-router' +import { useEffect, useState } from 'react' +import { + Modal, + Pressable, + Text, + TouchableOpacity, + View, +} from 'react-native' +import QRCode from 'react-native-qrcode-svg' +import { toast } from 'sonner-native' +import { AButton, ADivider, LucideIcon } from '@/components/common/ao' +import CustomHeader from '@/components/custom/Header' + +export default function Invite() { + const params = useLocalSearchParams<{ invite_code: string }>() + const { invite_code } = params + + const [qrcode, setQrcode] = useState('space:') + + const [previewVisible, setPreviewVisible] = useState(false) + + async function copyInviteCode() { + await Clipboard.setStringAsync(invite_code) + toast.success('邀请码已复制') + } + + useEffect(() => { + setQrcode(`space:${invite_code}`) + console.log(`space:${invite_code}`) + }, [invite_code]) + + return ( + + + + + + {/* 邀请码卡片 */} + + + 复制邀请码邀请家庭成员加入 + + + + {invite_code} + + + + } + > + 复制邀请码 + + + + + + + + {/* 二维码卡片 */} + setPreviewVisible(true)} + className="bg-white rounded-2xl py-8 items-center" + > + + + + + + {/* 全屏预览(无动画) */} + + setPreviewVisible(false)} + className="flex-1 bg-white items-center justify-center" + > + + + + + ) +} diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/member-manage/index.tsx b/code/allapp/allapp-rn/src/app/space/manage/sub-page/member-manage/index.tsx new file mode 100644 index 00000000..48587626 --- /dev/null +++ b/code/allapp/allapp-rn/src/app/space/manage/sub-page/member-manage/index.tsx @@ -0,0 +1,10 @@ +import { View } from 'react-native' +import CustomHeader from '@/components/custom/Header' + +export default function () { + return ( + + + + ) +} diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx b/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx index c9078c30..49f6632f 100644 --- a/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx +++ b/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx @@ -14,7 +14,7 @@ import { ActionsheetDragIndicator, ActionsheetDragIndicatorWrapper, } from '@/components/ui/actionsheet' -import { dissolveSpaceApi, getSpaceSettingsApi, updateSpaceDefaultApi, updateSpaceMemberNameApi, updateSpaceNameApi } from '@/request/api/space' +import { dissolveSpaceApi, exitSpaceApi, getSpaceSettingsApi, updateSpaceDefaultApi, updateSpaceMemberNameApi, updateSpaceNameApi } from '@/request/api/space' import { useUserStore } from '@/store/user' interface ItemProps { @@ -65,6 +65,8 @@ export default function Settings() { const { spaceId } = params const [space, setSpace] = useState(null) + // 是否自己的空间 + const [isOwner, setIsOwner] = useState(false) // 空间名称 const [showName, setShowName] = useState(false) @@ -114,6 +116,15 @@ export default function Settings() { } }, [spaceId]) + useEffect(() => { + if (space) { + setIsOwner(space.owner_id === userStore.userInfo.id) + } + else { + setIsOwner(false) + } + }, [space]) + return ( @@ -124,13 +135,14 @@ export default function Settings() { ) : ( + 常用设置 { - space?.owner_id === userStore.userInfo.id && ( + isOwner && ( + + 分享 + + + + { + router.navigate({ + pathname: '/space/manage/sub-page/invite', + params: { + invite_code: space.invite_code, + }, + }) + }} + /> + + 其它操作 - + { + isOwner && ( + + ) + } { setShowDissolve(true) @@ -397,7 +432,7 @@ export default function Settings() { {/* 解散 */} { setShowDissolve(false) @@ -411,18 +446,34 @@ export default function Settings() { return } - await dissolveSpaceApi({ - space_id: space.space_id, - }).then((res) => { - if (res.isSuccess) { - setShowDissolve(false) - toast.success('解散成功') + if (isOwner) { + await dissolveSpaceApi({ + space_id: space.space_id, + }).then((res) => { + if (res.isSuccess) { + setShowDissolve(false) + toast.success('已解散该空间') - setTimeout(() => { - router.back() - }, 300) - } - }) + setTimeout(() => { + router.back() + }, 300) + } + }) + } + else { + await exitSpaceApi({ + space_id: space.space_id, + }).then((res) => { + if (res.isSuccess) { + setShowDissolve(false) + toast.success('已退出该空间') + + setTimeout(() => { + router.back() + }, 300) + } + }) + } }} /> diff --git a/code/allapp/allapp-rn/src/request/api/space/index.ts b/code/allapp/allapp-rn/src/request/api/space/index.ts index f8a697ba..3313e245 100644 --- a/code/allapp/allapp-rn/src/request/api/space/index.ts +++ b/code/allapp/allapp-rn/src/request/api/space/index.ts @@ -2,9 +2,7 @@ import type { CreateSpaceParams, CreateSpaceResult, DissolveSpaceParams, - DissolveSpaceResult, ExitSpaceParams, - ExitSpaceResult, GetSpaceSettingsParams, JoinSpaceParams, JoinSpaceResult, @@ -60,21 +58,21 @@ export function getSpaceSettingsApi(params: GetSpaceSettingsParams) { return alovaInstance.Post>(`${API_PREFIX}/settings`, params) } +// 解散空间 +export function dissolveSpaceApi(params: DissolveSpaceParams) { + return alovaInstance.Post>(`${API_PREFIX}/dissolve`, params) +} + +// 退出空间 +export function exitSpaceApi(params: ExitSpaceParams) { + return alovaInstance.Post>(`${API_PREFIX}/member/exit`, params) +} + // Join Space API export function joinSpaceApi(params: JoinSpaceParams) { return alovaInstance.Post>(`${API_PREFIX}/join`, params) } -// Dissolve Space API -export function dissolveSpaceApi(params: DissolveSpaceParams) { - return alovaInstance.Post>(`${API_PREFIX}/dissolve`, params) -} - -// Exit Space API -export function exitSpaceApi(params: ExitSpaceParams) { - return alovaInstance.Post>(`${API_PREFIX}/exit`, params) -} - // Remove Space User API export function removeSpaceMemberApi(params: RemoveSpaceMemberParams) { return alovaInstance.Post>(`${API_PREFIX}/remove`, params) diff --git a/code/allapp/allapp-rn/src/request/index.ts b/code/allapp/allapp-rn/src/request/index.ts index f12e2875..d52bee1f 100644 --- a/code/allapp/allapp-rn/src/request/index.ts +++ b/code/allapp/allapp-rn/src/request/index.ts @@ -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, diff --git a/code/allapp/allapp-rn/src/types/space/index.ts b/code/allapp/allapp-rn/src/types/space/index.ts index 4e0c0673..fea0657c 100644 --- a/code/allapp/allapp-rn/src/types/space/index.ts +++ b/code/allapp/allapp-rn/src/types/space/index.ts @@ -8,6 +8,8 @@ export interface UserSpace { member_name: string sort_number: number + + invite_code: string } // 创建空间 @@ -31,9 +33,11 @@ export interface ListUserSpacesResult { export interface DissolveSpaceParams { space_id: number } -export interface DissolveSpaceResult { -} +// 退出空间 +export interface ExitSpaceParams { + space_id: number +} // 更新空间名称 export interface UpdateSpaceNameParams { space_id: number @@ -74,13 +78,6 @@ export interface JoinSpaceResult { space_name: string } -// 退出空间 -export interface ExitSpaceParams { - space_id: number -} -export interface ExitSpaceResult { -} - // 踢出用户 export interface RemoveSpaceMemberParams { space_id: number