u
This commit is contained in:
1 parent
cf23acdabc
commit
2efeb7cee2
13 files changed
+271
-49
No files matched your search
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -38,4 +38,11 @@ WHERE user_id = $2
|
||||
UPDATE space_member
|
||||
SET sort_number = $1
|
||||
WHERE user_id = $2
|
||||
AND space_id = $3;
|
||||
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;
|
||||
@@ -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
|
||||
`
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
<View className="flex-1 bg-[#f5f6f8]">
|
||||
<CustomHeader title="分享空间" />
|
||||
|
||||
<View className="px-5 pt-6">
|
||||
|
||||
{/* 邀请码卡片 */}
|
||||
<View className="bg-white rounded-2xl p-6 items-center">
|
||||
<Text className="text-gray-500 text-sm mb-3">
|
||||
复制邀请码邀请家庭成员加入
|
||||
</Text>
|
||||
|
||||
<Text className="text-4xl font-bold tracking-[8px] text-gray-900 mb-4">
|
||||
{invite_code}
|
||||
</Text>
|
||||
|
||||
<AButton
|
||||
onPress={copyInviteCode}
|
||||
className="rounded-full"
|
||||
leftIcon={
|
||||
<LucideIcon icon="Copy" size={16} color="#fff" clickable={false} />
|
||||
}
|
||||
>
|
||||
复制邀请码
|
||||
</AButton>
|
||||
</View>
|
||||
|
||||
<View className="my-8">
|
||||
<ADivider direction="horizontal" text="或扫描二维码" />
|
||||
</View>
|
||||
|
||||
{/* 二维码卡片 */}
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.9}
|
||||
onPress={() => setPreviewVisible(true)}
|
||||
className="bg-white rounded-2xl py-8 items-center"
|
||||
>
|
||||
<QRCode
|
||||
size={160}
|
||||
value={qrcode || ''}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
</View>
|
||||
|
||||
{/* 全屏预览(无动画) */}
|
||||
<Modal
|
||||
visible={previewVisible}
|
||||
transparent={false}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => setPreviewVisible(false)}
|
||||
className="flex-1 bg-white items-center justify-center"
|
||||
>
|
||||
<QRCode
|
||||
size={280}
|
||||
value={qrcode || ''}
|
||||
/>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { View } from 'react-native'
|
||||
import CustomHeader from '@/components/custom/Header'
|
||||
|
||||
export default function () {
|
||||
return (
|
||||
<View className="flex-1">
|
||||
<CustomHeader title="成员管理" />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -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<UserSpace | null>(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 (
|
||||
<View className="flex-1 bg-[#f5f6f8]">
|
||||
<CustomHeader title="空间设置" />
|
||||
@@ -124,13 +135,14 @@ export default function Settings() {
|
||||
)
|
||||
: (
|
||||
<View className="flex-1 px-4 pt-4">
|
||||
|
||||
<Text className="text-sm font-semibold text-gray-400 mb-2 tracking-wider">
|
||||
常用设置
|
||||
</Text>
|
||||
|
||||
<View className="bg-white rounded-xl overflow-hidden mb-6">
|
||||
{
|
||||
space?.owner_id === userStore.userInfo.id && (
|
||||
isOwner && (
|
||||
<Item
|
||||
icon="Earth"
|
||||
title="空间名称"
|
||||
@@ -205,19 +217,42 @@ export default function Settings() {
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Text className="text-sm font-semibold text-gray-400 mb-2 tracking-wider">
|
||||
分享
|
||||
</Text>
|
||||
|
||||
<View className="bg-white rounded-xl overflow-hidden mb-6">
|
||||
<Item
|
||||
icon="Share2"
|
||||
title="邀请"
|
||||
onPress={() => {
|
||||
router.navigate({
|
||||
pathname: '/space/manage/sub-page/invite',
|
||||
params: {
|
||||
invite_code: space.invite_code,
|
||||
},
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Text className="text-sm font-semibold text-gray-400 mb-2 tracking-wider">
|
||||
其它操作
|
||||
</Text>
|
||||
|
||||
<View className="bg-white rounded-xl overflow-hidden">
|
||||
<Item
|
||||
icon="Users"
|
||||
title="成员管理"
|
||||
/>
|
||||
{
|
||||
isOwner && (
|
||||
<Item
|
||||
icon="Users"
|
||||
title="成员管理"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
<Item
|
||||
icon="LogOut"
|
||||
title={userStore.userInfo.id === space.owner_id ? '解散空间' : '退出空间'}
|
||||
title={isOwner ? '解散空间' : '退出空间'}
|
||||
isLast
|
||||
onPress={() => {
|
||||
setShowDissolve(true)
|
||||
@@ -397,7 +432,7 @@ export default function Settings() {
|
||||
{/* 解散 */}
|
||||
<AModal
|
||||
title="提示"
|
||||
body="确认解散该空间么?"
|
||||
body={isOwner ? '确认解散该空间么?' : '确定解散空间么?'}
|
||||
isOpen={showDissolve}
|
||||
onClose={() => {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -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<ResponseData<UserSpace>>(`${API_PREFIX}/settings`, params)
|
||||
}
|
||||
|
||||
// 解散空间
|
||||
export function dissolveSpaceApi(params: DissolveSpaceParams) {
|
||||
return alovaInstance.Post<ResponseData<void>>(`${API_PREFIX}/dissolve`, params)
|
||||
}
|
||||
|
||||
// 退出空间
|
||||
export function exitSpaceApi(params: ExitSpaceParams) {
|
||||
return alovaInstance.Post<ResponseData<void>>(`${API_PREFIX}/member/exit`, params)
|
||||
}
|
||||
|
||||
// Join Space API
|
||||
export function joinSpaceApi(params: JoinSpaceParams) {
|
||||
return alovaInstance.Post<ResponseData<JoinSpaceResult>>(`${API_PREFIX}/join`, params)
|
||||
}
|
||||
|
||||
// Dissolve Space API
|
||||
export function dissolveSpaceApi(params: DissolveSpaceParams) {
|
||||
return alovaInstance.Post<ResponseData<DissolveSpaceResult>>(`${API_PREFIX}/dissolve`, params)
|
||||
}
|
||||
|
||||
// Exit Space API
|
||||
export function exitSpaceApi(params: ExitSpaceParams) {
|
||||
return alovaInstance.Post<ResponseData<ExitSpaceResult>>(`${API_PREFIX}/exit`, params)
|
||||
}
|
||||
|
||||
// Remove Space User API
|
||||
export function removeSpaceMemberApi(params: RemoveSpaceMemberParams) {
|
||||
return alovaInstance.Post<ResponseData<RemoveSpaceMemberResult>>(`${API_PREFIX}/remove`, params)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user