This commit is contained in:
oneao committed 2026-02-27 22:09:50 +08:00
1 parent 1b1a54f7dd
commit fc005e0fb4
22 files changed
+300 -193

No files matched your search

+5 -5
View File
@@ -55,12 +55,12 @@ export default function RootLayout() {
}, [pathname])
useEffect(() => {
if (!fontsLoaded)
if (!fontsLoaded) {
return
appStore.init().finally(() => {
SplashScreen.hideAsync()
})
}
SplashScreen.hideAsync()
// appStore.init().finally(() => {
// })
}, [fontsLoaded])
return (
+5 -3
View File
@@ -117,6 +117,8 @@ export default function Auth() {
// avatar: onGetUserInfo.figureurlQq_2 || onGetUserInfo.figureurl_2,
// })
// console.log(loginRes)
// if (loginRes.isSuccess) {
// userStore.setUserInfo({
// token: loginRes.data.token,
@@ -182,15 +184,15 @@ export default function Auth() {
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NjY3ODU5ODIxNjUwNjEsImlhdCI6MTc2OTM0ODI0Nn0.17ZNaHD3HSLM8dVn_JQK-gvsG9MKj47IRYV9D4xZkzs
userStore.setUserInfo({
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NzgxMTUwMzIxMDA5MzMsImlhdCI6MTc3MjExMDQ5N30.Ab7_YNwftJigktnPt8f-FwwcLeS45CkrH0jT2jLjRtA',
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NzgxMTUwMzIxMDA5MzMsImlhdCI6MTc3MjE5MDQ0Mn0.GF611RBvU47QuW2s4kOcdvh88ieIbHu7M_SmWeBOqLY',
id: 778115032100933,
nickname: 'Zhang',
avatar: 'http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100',
})
appStore.init()
// appStore.init()
router.push('/')
router.replace('/')
}
return (
+44 -85
View File
@@ -1,5 +1,5 @@
import type { Space } from '@/types/space/space'
import { useCallback, useState } from 'react'
import type { UserSpace } from '@/types/space'
import { useCallback, useEffect, useState } from 'react'
import { Pressable, Text, View } from 'react-native'
import Animated, { useAnimatedRef } from 'react-native-reanimated'
import Sortable from 'react-native-sortables'
@@ -9,9 +9,12 @@ import { AModal } from '@/components/common/ao/index'
import EmptyState from '@/components/common/EmptyStatus'
import CustomHeader from '@/components/custom/Header'
import { Badge, BadgeText } from '@/components/ui/badge'
import { createSpaceApi } from '@/request/api/space/space'
import { createSpaceApi, listUserSpacesApi } from '@/request/api/space/index'
import { useUserStore } from '@/store/user'
export default function AuthSpace() {
const userStore = useUserStore()
const scrollableRef = useAnimatedRef<Animated.ScrollView>()
const [selectedId, setSelectedId] = useState<number | null>(null)
@@ -22,74 +25,18 @@ export default function AuthSpace() {
name: '',
})
const spaces: Space[] = [
{
id: 1,
name: 'A 的空间',
role: 1,
member_count: 8,
is_default: 1,
sort_number: 1,
user_name: '张三',
},
{
id: 2,
name: 'B 的空间',
role: 2,
member_count: 5,
is_default: 0,
sort_number: 2,
user_name: '李四',
},
{
id: 3,
name: 'C 的空间',
role: 3,
member_count: 12,
is_default: 0,
sort_number: 3,
user_name: '王五',
},
{
id: 4,
name: 'D 的空间',
role: 2,
member_count: 6,
is_default: 0,
sort_number: 4,
user_name: '赵六',
},
{
id: 5,
name: 'E 的空间',
role: 1,
member_count: 3,
is_default: 0,
sort_number: 5,
user_name: '钱七',
},
{
id: 6,
name: 'F 的空间',
role: 2,
member_count: 9,
is_default: 0,
sort_number: 6,
user_name: '孙八',
},
{
id: 7,
name: 'G 的空间',
role: 3,
member_count: 4,
is_default: 0,
sort_number: 7,
user_name: '周九',
},
]
const [spaces, setSpaces] = useState<UserSpace[]>([])
const renderItem = useCallback(
({ item }: { item: Space }) => (
function listUserSpaces() {
listUserSpacesApi().then((res) => {
if (res.isSuccess) {
setSpaces(res.data.spaces)
}
})
}
const renderItem
= ({ item }: { item: UserSpace }) => (
<Pressable
key={item.id}
onPress={() => setSelectedId(item.id)}
@@ -112,22 +59,31 @@ export default function AuthSpace() {
{item.name}
</Text>
<Badge size="sm" variant="solid" action="muted">
<BadgeText>创建者</BadgeText>
</Badge>
{
item.owner_id === userStore.userInfo.id && (
<Badge size="sm" variant="solid" action="muted">
<BadgeText>创建者</BadgeText>
</Badge>
)
}
{
item.is_default === 1 && (
<Badge size="sm" variant="solid" action="info">
<BadgeText>默认</BadgeText>
</Badge>
)
}
<Badge size="sm" variant="solid" action="info">
<BadgeText>默认</BadgeText>
</Badge>
</View>
<View className="flex-row items-center gap-3 mt-2">
<View className="flex-row gap-1">
<LucideIcon icon="UserRound" size={12} />
<Text
className={`text-xs `}
className="text-xs"
>
用户A
{item.user_name}
</Text>
</View>
<View className="flex-row gap-1">
@@ -135,7 +91,7 @@ export default function AuthSpace() {
<Text
className={`text-xs `}
>
0
{item.member_count}
</Text>
</View>
</View>
@@ -148,9 +104,11 @@ export default function AuthSpace() {
className="p-1"
/>
</Pressable>
),
[],
)
)
useEffect(() => {
listUserSpaces()
}, [])
return (
<View className="flex-1 bg-white">
@@ -186,6 +144,7 @@ export default function AuthSpace() {
<Animated.ScrollView
className="flex-1"
showsVerticalScrollIndicator={false}
ref={scrollableRef}
>
{spaces.length === 0
@@ -256,18 +215,18 @@ export default function AuthSpace() {
toast.warning('请输入空间名称')
return
}
await createSpaceApi({
name: createForm.name,
user_name: userStore.userInfo.nickname,
sort_number: 0,
}).then((res) => {
console.log(res)
if (res.isSuccess) {
toast.success('创建成功')
setCreateOpen(false)
setCreateForm({
name: '',
})
}
})
}}
@@ -1,4 +1,4 @@
import type { SpaceMember } from '@/types/space/space'
import type { SpaceMember } from '@/types/space'
import * as Clipboard from 'expo-clipboard'
import { useState } from 'react'
import { FlatList, TouchableHighlight, TouchableOpacity, View } from 'react-native'
@@ -28,7 +28,7 @@ import { HStack } from '@/components/ui/hstack'
import { ChevronDownIcon, ChevronUpIcon } from '@/components/ui/icon'
import { Text } from '@/components/ui/text'
import { VStack } from '@/components/ui/vstack'
import { dissolveSpaceApi, exitSpaceApi, removeSpaceMemberApi } from '@/request/api/space/space'
import { dissolveSpaceApi, exitSpaceApi, removeSpaceMemberApi } from '@/request/api/space/index'
import { useUserStore } from '@/store/user'
import { formatRelativeTime } from '@/utils/time'
import { toast } from '@/utils/toast'
@@ -1,8 +1,8 @@
import type { SpaceMember } from '@/types/space/space'
import type { SpaceMember } from '@/types/space'
import { useEffect, useState } from 'react'
import { View } from 'react-native'
import CustomHeader from '@/components/custom/Header'
import { createSpaceApi, joinSpaceApi, listSpaceMembersApi } from '@/request/api/space/space'
import { createSpaceApi, joinSpaceApi, listSpaceMembersApi } from '@/request/api/space/index'
import { useSpaceStore } from '@/store/space'
import { useUserStore } from '@/store/user'
import JoinSpace from './components/JoinSpace'
@@ -9,25 +9,30 @@ import type {
JoinSpaceResult,
ListSpaceMembersParams,
ListSpaceMembersResult,
ListUserSpacesResult,
RemoveSpaceMemberParams,
RemoveSpaceMemberResult,
UpdateSpaceMemberRoleParams,
UpdateSpaceMemberRoleResult,
} from '@/types/space/space'
} from '@/types/space'
import alovaInstance from '../../index'
const API_PREFIX = '/space'
// Join Space API
export function joinSpaceApi(params: JoinSpaceParams) {
return alovaInstance.Post<ResponseData<JoinSpaceResult>>(`${API_PREFIX}/join`, params)
}
// Create Space API
export function createSpaceApi(params: CreateSpaceParams) {
return alovaInstance.Post<ResponseData<CreateSpaceResult>>(`${API_PREFIX}/create`, params)
}
export function listUserSpacesApi() {
return alovaInstance.Post<ResponseData<ListUserSpacesResult>>(`${API_PREFIX}/list`)
}
// 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)
+4 -37
View File
@@ -8,7 +8,7 @@ import { toast } from '@/utils/toast'
enum HttpCode {
Success = 1000,
Unauthorized = 401,
Unauthorized = 1001,
Fail = 500,
}
@@ -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,
@@ -46,46 +46,13 @@ const alovaInstance = createAlova({
if (resData.code === HttpCode.Unauthorized) {
useUserStore.getState().clear()
useNavStore.getState().navigateToAuth()
return Promise.reject(new Error('登录已失效'))
return result
}
return result
},
onError: (error: AxiosError) => {
const status = error.status
console.log(error)
switch (status) {
case 400:
toast.show({ title: '请求错误,请检查输入参数' })
break
case 401:
toast.show({ title: '未授权,请重新登录' })
break
case 403:
toast.show({ title: '没有权限访问该资源' })
break
case 404:
toast.show({ title: '请求丢失啦,请稍后再试!' })
break
case 500:
toast.show({ title: '服务器出错啦,请稍后重试' })
break
case 502:
toast.show({ title: '网关错误,请稍后重试' })
break
case 503:
toast.show({ title: '服务暂不可用,请稍后再试' })
break
case 504:
toast.show({ title: '网关超时,请稍后再试' })
break
default:
toast.show({ title: '服务器出错啦,请稍后重试' })
break
}
return Promise.reject(error)
},
},
@@ -36,7 +36,7 @@ export const useNavStore = create<NavState>()(
navigateToAuth: () => {
const pathname = useNavStore.getState().pathname
if (!pathname.startsWith('/auth')) {
if (pathname !== '/auth') {
router.replace('/auth')
}
},
@@ -44,7 +44,7 @@ export const useNavStore = create<NavState>()(
}),
{
name: 'nav-storage',
// storage: createJSONStorage(() => AsyncStorage),
storage: createJSONStorage(() => AsyncStorage),
},
),
)
+11 -4
View File
@@ -4,8 +4,8 @@ import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'
interface UserState {
userInfo: UserInfo | null
setUserInfo: (userInfo: UserInfo | null) => void
userInfo: UserInfo
setUserInfo: (userInfo: UserInfo) => void
clear: () => void
isLoggedIn: () => boolean
@@ -13,17 +13,24 @@ interface UserState {
setUserSpace: (userSpace: UserSpace | null) => void
}
const defaultUserInfo: UserInfo = {
id: 0,
token: '',
nickname: '',
avatar: '',
}
const useUserStore = create<UserState>()(
persist(
(set, get) => ({
userInfo: null,
userInfo: defaultUserInfo,
userSpace: null,
setUserInfo: userInfo => set({ userInfo }),
setUserSpace: userSpace => set({ userSpace }),
clear: () => {
set({ userInfo: null, userSpace: null })
set({ userInfo: defaultUserInfo, userSpace: null })
},
isLoggedIn: () => Boolean(get().userInfo?.token),
+2 -2
View File
@@ -12,8 +12,8 @@ declare global {
interface UserInfo {
id: number
token: string
nickname?: string
avatar?: string
nickname: string
avatar: string
}
interface UserSpace {
@@ -1,5 +1,6 @@
export interface Space {
export interface UserSpace {
id: number
owner_id: number
name: string
role: number
member_count: number
@@ -12,12 +13,19 @@ export interface Space {
// 创建空间
export interface CreateSpaceParams {
name: string
user_name: string
sort_number: number
}
export interface CreateSpaceResult {
space_id: number
invite_code: string
}
// 获取用户空间
export interface ListUserSpacesResult {
spaces: UserSpace[]
}
// 解散空间
export interface DissolveSpaceParams {
space_id: number