u
This commit is contained in:
1 parent
c0531c1d0a
commit
46106d0c76
13 files changed
+171
-146
No files matched your search
@@ -57,7 +57,7 @@ export default function TabsLayout() {
|
|||||||
"
|
"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setShowNavDrawer(false)
|
setShowNavDrawer(false)
|
||||||
router.push(item.path)
|
router.navigate(item.path)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<LucideIcon icon={item.icon} size={24} strokeWidth={2} clickable={false} />
|
<LucideIcon icon={item.icon} size={24} strokeWidth={2} clickable={false} />
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import React, { useState } from 'react'
|
|||||||
import { Text, View } from 'react-native'
|
import { Text, View } from 'react-native'
|
||||||
import { AButton, AModal } from '@/components/common/ao'
|
import { AButton, AModal } from '@/components/common/ao'
|
||||||
import AnimatedSwitch from '@/components/common/ao/Switch'
|
import AnimatedSwitch from '@/components/common/ao/Switch'
|
||||||
|
import { useSpaceStore } from '@/store/space'
|
||||||
|
|
||||||
export default function TestScreen() {
|
export default function TestScreen() {
|
||||||
const [showDissolve, setShowDissolve] = useState(false)
|
const [showDissolve, setShowDissolve] = useState(false)
|
||||||
|
const spaceStore = useSpaceStore()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||||
@@ -12,7 +14,7 @@ export default function TestScreen() {
|
|||||||
setShowDissolve(true)
|
setShowDissolve(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
测试
|
{spaceStore.currentSpace?.space_id}
|
||||||
</AButton>
|
</AButton>
|
||||||
<AModal
|
<AModal
|
||||||
title="提示"
|
title="提示"
|
||||||
|
|||||||
@@ -26,21 +26,21 @@ export default function Index() {
|
|||||||
|
|
||||||
{/* <AButton
|
{/* <AButton
|
||||||
className="w-full"
|
className="w-full"
|
||||||
onPress={() => router.replace('/money')}
|
onPress={() => ('/money')}
|
||||||
>
|
>
|
||||||
开始使用
|
开始使用
|
||||||
</AButton> */}
|
</AButton> */}
|
||||||
<View className="flex flex-row gap-3 mt-4">
|
<View className="flex flex-row gap-3 mt-4">
|
||||||
<AButton
|
<AButton
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
onPress={() => router.replace('/money')}
|
onPress={() => ('/money')}
|
||||||
>
|
>
|
||||||
创建空间
|
创建空间
|
||||||
</AButton>
|
</AButton>
|
||||||
<AButton
|
<AButton
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onPress={() => router.replace('/money')}
|
onPress={() => ('/money')}
|
||||||
>
|
>
|
||||||
加入空间
|
加入空间
|
||||||
</AButton>
|
</AButton>
|
||||||
|
|||||||
@@ -42,9 +42,10 @@ export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) {
|
|||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
|
||||||
const navStore = useNavStore()
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
const navStore = useNavStore()
|
||||||
|
|
||||||
const [fontsLoaded] = useFonts({
|
const [fontsLoaded] = useFonts({
|
||||||
SpaceMono: require('@/static/fonts/SpaceMono-Regular.ttf'),
|
SpaceMono: require('@/static/fonts/SpaceMono-Regular.ttf'),
|
||||||
})
|
})
|
||||||
@@ -54,12 +55,19 @@ export default function RootLayout() {
|
|||||||
}, [pathname])
|
}, [pathname])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!fontsLoaded) {
|
if (!fontsLoaded)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
const bootstrap = async () => {
|
||||||
|
try {
|
||||||
|
await appStore.init()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
SplashScreen.hideAsync()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SplashScreen.hideAsync()
|
|
||||||
// appStore.init().finally(() => {
|
bootstrap()
|
||||||
// })
|
|
||||||
}, [fontsLoaded])
|
}, [fontsLoaded])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
import { useEvent } from 'expo'
|
import { useEvent } from 'expo'
|
||||||
// import ExpoQQ from 'expo-qq'
|
// import ExpoQQ from 'expo-qq'
|
||||||
import { useRouter } from 'expo-router'
|
import { useNavigation, useRouter } from 'expo-router'
|
||||||
// import ExpoWeChat from 'expo-wechat'
|
// import ExpoWeChat from 'expo-wechat'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Image, Text, View } from 'react-native'
|
import { Image, Text, View } from 'react-native'
|
||||||
|
import { toast } from 'sonner-native'
|
||||||
import { AButton, ACheckbox } from '@/components/common/ao'
|
import { AButton, ACheckbox } from '@/components/common/ao'
|
||||||
import CustomHeader from '@/components/custom/Header'
|
import CustomHeader from '@/components/custom/Header'
|
||||||
import { IconQq, IconWeixin } from '@/components/iconfont'
|
import { IconQq, IconWeixin } from '@/components/iconfont'
|
||||||
import { loginQqApi, loginWxApi } from '@/request/api/auth'
|
import { loginQqApi, loginWxApi } from '@/request/api/auth'
|
||||||
import { useAppStore } from '@/store/app'
|
import { useAppStore } from '@/store/app'
|
||||||
|
import { useSpaceStore } from '@/store/space'
|
||||||
import { useUserStore } from '@/store/user'
|
import { useUserStore } from '@/store/user'
|
||||||
import { toast } from '@/utils/toast'
|
|
||||||
|
|
||||||
export default function Auth() {
|
export default function Auth() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
const navigation = useNavigation()
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [isAgree, setIsAgree] = useState(true)
|
const [isAgree, setIsAgree] = useState(true)
|
||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
@@ -23,7 +27,6 @@ export default function Auth() {
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const appStore = useAppStore()
|
|
||||||
|
|
||||||
// const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished')
|
// const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished')
|
||||||
// const onGetUserInfo = useEvent(ExpoQQ, 'onGetUserInfo')
|
// const onGetUserInfo = useEvent(ExpoQQ, 'onGetUserInfo')
|
||||||
@@ -44,9 +47,7 @@ export default function Auth() {
|
|||||||
// // 检查微信是否安装
|
// // 检查微信是否安装
|
||||||
// const isInstalled = await ExpoWeChat.isWXAppInstalled()
|
// const isInstalled = await ExpoWeChat.isWXAppInstalled()
|
||||||
// if (!isInstalled) {
|
// if (!isInstalled) {
|
||||||
// toast.show({
|
// toast.warning(onLoginFinished?.errorMessage || '请先安装微信')
|
||||||
// title: onLoginFinished?.errorMessage || '请先安装微信',
|
|
||||||
// })
|
|
||||||
// setLoading(false)
|
// setLoading(false)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@@ -70,9 +71,7 @@ export default function Auth() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// if (!onLoginFinished.success) {
|
// if (!onLoginFinished.success) {
|
||||||
// toast.show({
|
// toast.warning(onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权')
|
||||||
// title: onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
|
|
||||||
// })
|
|
||||||
// setLoading(false)
|
// setLoading(false)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@@ -81,9 +80,7 @@ export default function Auth() {
|
|||||||
// try {
|
// try {
|
||||||
// const tokenInfo = await ExpoQQ.getLoginTokenInfo()
|
// const tokenInfo = await ExpoQQ.getLoginTokenInfo()
|
||||||
// if (!tokenInfo.openId) {
|
// if (!tokenInfo.openId) {
|
||||||
// toast.show({
|
// toast.warning(tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权')
|
||||||
// title: tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
|
|
||||||
// })
|
|
||||||
// setLoading(false)
|
// setLoading(false)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@@ -126,8 +123,7 @@ export default function Auth() {
|
|||||||
// nickname: loginRes.data.nickname,
|
// nickname: loginRes.data.nickname,
|
||||||
// avatar: loginRes.data.avatar,
|
// avatar: loginRes.data.avatar,
|
||||||
// })
|
// })
|
||||||
|
// await appStore.init()
|
||||||
// router.push('/space/manage')
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// catch (err) {
|
// catch (err) {
|
||||||
@@ -161,7 +157,7 @@ export default function Auth() {
|
|||||||
// avatar: loginRes.data.avatar,
|
// avatar: loginRes.data.avatar,
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// router.push('/')
|
// await appStore.init()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// catch (err) {
|
// catch (err) {
|
||||||
@@ -180,19 +176,27 @@ export default function Auth() {
|
|||||||
// handleLogin()
|
// handleLogin()
|
||||||
// }, [authResult])
|
// }, [authResult])
|
||||||
|
|
||||||
function testLogin() {
|
async function testLogin() {
|
||||||
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NjY3ODU5ODIxNjUwNjEsImlhdCI6MTc2OTM0ODI0Nn0.17ZNaHD3HSLM8dVn_JQK-gvsG9MKj47IRYV9D4xZkzs
|
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NjY3ODU5ODIxNjUwNjEsImlhdCI6MTc2OTM0ODI0Nn0.17ZNaHD3HSLM8dVn_JQK-gvsG9MKj47IRYV9D4xZkzs
|
||||||
|
|
||||||
userStore.setUserInfo({
|
userStore.setUserInfo({
|
||||||
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NzgxMTUwMzIxMDA5MzMsImlhdCI6MTc3MjE5MDQ0Mn0.GF611RBvU47QuW2s4kOcdvh88ieIbHu7M_SmWeBOqLY',
|
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3Nzk4OTU0MTkxMjE3MzMsImlhdCI6MTc3MjU0MDU1OH0.M5KqfPWdpOAlCCtZrJRxwKc8bRpGBjEt9BNCfgBZgnc',
|
||||||
id: 778115032100933,
|
id: 778115032100933,
|
||||||
nickname: 'Zhang',
|
nickname: 'Zhang',
|
||||||
avatar: 'http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100',
|
avatar: 'http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100',
|
||||||
})
|
})
|
||||||
|
|
||||||
// appStore.init()
|
await appStore.init()
|
||||||
|
|
||||||
router.replace('/')
|
// navigationRef.reset({
|
||||||
|
// index: 0,
|
||||||
|
// routes: [{
|
||||||
|
// name: '(tabs)' as never,
|
||||||
|
// }],
|
||||||
|
// })
|
||||||
|
// console.log(navigation.getState()?.routeNames)
|
||||||
|
|
||||||
|
// ('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+12
-10
@@ -84,8 +84,8 @@ export default function AuthSpace() {
|
|||||||
<Pressable
|
<Pressable
|
||||||
key={item.space_id}
|
key={item.space_id}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push({
|
router.navigate({
|
||||||
pathname: '/space/manage/sub-page/settings',
|
pathname: '/space/sub-page/settings',
|
||||||
params: {
|
params: {
|
||||||
spaceId: item.space_id,
|
spaceId: item.space_id,
|
||||||
},
|
},
|
||||||
@@ -238,11 +238,12 @@ export default function AuthSpace() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
loading ? (
|
loading
|
||||||
<View className="flex-1 items-center justify-center">
|
? (
|
||||||
<ActivityIndicator size="large" color="#333" />
|
<View className="flex-1 items-center justify-center">
|
||||||
</View>
|
<ActivityIndicator size="large" color="#333" />
|
||||||
)
|
</View>
|
||||||
|
)
|
||||||
: spaces.length === 0
|
: spaces.length === 0
|
||||||
? (
|
? (
|
||||||
<View className="flex-1 items-center justify-center mt-12">
|
<View className="flex-1 items-center justify-center mt-12">
|
||||||
@@ -251,7 +252,8 @@ export default function AuthSpace() {
|
|||||||
description="请选择 创建 或 加入 空间"
|
description="请选择 创建 或 加入 空间"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
)
|
||||||
|
: (
|
||||||
<Sortable.Grid
|
<Sortable.Grid
|
||||||
scrollableRef={scrollableRef}
|
scrollableRef={scrollableRef}
|
||||||
keyExtractor={(item: UserSpace) => {
|
keyExtractor={(item: UserSpace) => {
|
||||||
@@ -334,7 +336,7 @@ export default function AuthSpace() {
|
|||||||
<AButton
|
<AButton
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
loading={createLoading}
|
loading={createLoading}
|
||||||
onPress={() => {
|
onPress={async () => {
|
||||||
if (!createForm.name) {
|
if (!createForm.name) {
|
||||||
toast.warning('请输入空间名称')
|
toast.warning('请输入空间名称')
|
||||||
return
|
return
|
||||||
@@ -343,7 +345,7 @@ export default function AuthSpace() {
|
|||||||
setCreateLoading(true)
|
setCreateLoading(true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
createSpaceApi({
|
await createSpaceApi({
|
||||||
name: createForm.name,
|
name: createForm.name,
|
||||||
member_name: userStore.userInfo.nickname,
|
member_name: userStore.userInfo.nickname,
|
||||||
sort_number: spaces.length,
|
sort_number: spaces.length,
|
||||||
+53
-61
@@ -101,71 +101,63 @@ export default function Invite() {
|
|||||||
<CustomHeader title="分享空间" />
|
<CustomHeader title="分享空间" />
|
||||||
|
|
||||||
{
|
{
|
||||||
loading ? (
|
loading
|
||||||
<View className="flex-1 items-center justify-center">
|
? (
|
||||||
<ActivityIndicator size="large" color="#333" />
|
<View className="flex-1 items-center justify-center">
|
||||||
</View>
|
<ActivityIndicator size="large" color="#333" />
|
||||||
) : (
|
|
||||||
<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">
|
|
||||||
{space?.invite_code}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<View className="flex-row gap-3">
|
|
||||||
<AButton
|
|
||||||
onPress={copyInviteCode}
|
|
||||||
className="rounded-full flex-1"
|
|
||||||
leftIcon={
|
|
||||||
<LucideIcon icon="Copy" size={16} color="#fff" clickable={false} />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
复制邀请码
|
|
||||||
</AButton>
|
|
||||||
|
|
||||||
{
|
|
||||||
userStore.userInfo.id === space?.owner_id && (
|
|
||||||
<AButton
|
|
||||||
variant="outline"
|
|
||||||
className="rounded-full px-4"
|
|
||||||
leftIcon={
|
|
||||||
<LucideIcon icon="RefreshCw" size={16} clickable={false} />
|
|
||||||
}
|
|
||||||
loading={refreshLoading}
|
|
||||||
onPress={refreshInviteCode}
|
|
||||||
>
|
|
||||||
刷新
|
|
||||||
</AButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)
|
||||||
|
: (
|
||||||
|
<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>
|
||||||
|
|
||||||
<View className="my-8">
|
<Text className="text-4xl font-bold tracking-[8px] text-gray-900 mb-4">
|
||||||
<ADivider direction="horizontal" text="或扫描二维码" />
|
{space?.invite_code}
|
||||||
</View>
|
</Text>
|
||||||
|
|
||||||
{/* 二维码卡片 */}
|
<View className="flex-row gap-3">
|
||||||
<TouchableOpacity
|
<AButton
|
||||||
activeOpacity={0.9}
|
onPress={copyInviteCode}
|
||||||
onPress={() => setPreviewVisible(true)}
|
className="rounded-full flex-1"
|
||||||
className="bg-white rounded-2xl py-8 items-center"
|
leftIcon={
|
||||||
>
|
<LucideIcon icon="Copy" size={16} color="#fff" clickable={false} />
|
||||||
<QRCode
|
}
|
||||||
size={160}
|
>
|
||||||
value={qrcode || ''}
|
复制邀请码
|
||||||
/>
|
</AButton>
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
</View>
|
{userStore.userInfo.id === space?.owner_id && (
|
||||||
)
|
<AButton
|
||||||
|
variant="outline"
|
||||||
|
className="rounded-full px-4"
|
||||||
|
leftIcon={
|
||||||
|
<LucideIcon icon="RefreshCw" size={16} clickable={false} />
|
||||||
|
}
|
||||||
|
loading={refreshLoading}
|
||||||
|
onPress={refreshInviteCode}
|
||||||
|
>
|
||||||
|
刷新
|
||||||
|
</AButton>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</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>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
{/* 全屏预览(无动画) */}
|
{/* 全屏预览(无动画) */}
|
||||||
File renamed without changes.
+18
-5
@@ -1,5 +1,5 @@
|
|||||||
import type { UserSpace } from '@/types/space'
|
import type { UserSpace } from '@/types/space'
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from 'expo-router'
|
import { router, useFocusEffect, useLocalSearchParams, useNavigation } from 'expo-router'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native'
|
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native'
|
||||||
import { KeyboardAvoidingView } from 'react-native-keyboard-controller'
|
import { KeyboardAvoidingView } from 'react-native-keyboard-controller'
|
||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
ActionsheetDragIndicatorWrapper,
|
ActionsheetDragIndicatorWrapper,
|
||||||
} from '@/components/ui/actionsheet'
|
} from '@/components/ui/actionsheet'
|
||||||
import { dissolveSpaceApi, enterSpaceApi, exitSpaceApi, getSpaceSettingsApi, updateSpaceDefaultApi, updateSpaceMemberNameApi, updateSpaceNameApi } from '@/request/api/space'
|
import { dissolveSpaceApi, enterSpaceApi, exitSpaceApi, getSpaceSettingsApi, updateSpaceDefaultApi, updateSpaceMemberNameApi, updateSpaceNameApi } from '@/request/api/space'
|
||||||
|
import { useNavStore } from '@/store/navigation'
|
||||||
import { useSpaceStore } from '@/store/space'
|
import { useSpaceStore } from '@/store/space'
|
||||||
import { useUserStore } from '@/store/user'
|
import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ function Item({
|
|||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const spaceStore = useSpaceStore()
|
const spaceStore = useSpaceStore()
|
||||||
|
const navStore = useNavStore()
|
||||||
|
|
||||||
const params = useLocalSearchParams<{ spaceId: string }>()
|
const params = useLocalSearchParams<{ spaceId: string }>()
|
||||||
const { spaceId } = params
|
const { spaceId } = params
|
||||||
@@ -102,6 +104,16 @@ export default function Settings() {
|
|||||||
}
|
}
|
||||||
}, [showName])
|
}, [showName])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showMemberName) {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
memberNameInputRef.current?.focus()
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
return () => clearTimeout(timer)
|
||||||
|
}
|
||||||
|
}, [showMemberName])
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
if (spaceId) {
|
if (spaceId) {
|
||||||
@@ -147,7 +159,7 @@ export default function Settings() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
enterSpaceApi({
|
await enterSpaceApi({
|
||||||
space_id: space.space_id,
|
space_id: space.space_id,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
@@ -156,7 +168,8 @@ export default function Settings() {
|
|||||||
space_id: space.space_id,
|
space_id: space.space_id,
|
||||||
role: space.role,
|
role: space.role,
|
||||||
})
|
})
|
||||||
router.navigate('/money')
|
|
||||||
|
navStore.replace('(tabs)')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -258,7 +271,7 @@ export default function Settings() {
|
|||||||
title="邀请"
|
title="邀请"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.navigate({
|
router.navigate({
|
||||||
pathname: '/space/manage/sub-page/invite',
|
pathname: '/space/sub-page/invite',
|
||||||
params: {
|
params: {
|
||||||
space_id: space.space_id,
|
space_id: space.space_id,
|
||||||
},
|
},
|
||||||
@@ -279,7 +292,7 @@ export default function Settings() {
|
|||||||
title="空间成员"
|
title="空间成员"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.navigate({
|
router.navigate({
|
||||||
pathname: '/space/manage/sub-page/member',
|
pathname: '/space/sub-page/member',
|
||||||
params: {
|
params: {
|
||||||
space_id: space.space_id,
|
space_id: space.space_id,
|
||||||
},
|
},
|
||||||
@@ -3,19 +3,21 @@ import { useState } from 'react'
|
|||||||
import { Text, TouchableOpacity, View } from 'react-native'
|
import { Text, TouchableOpacity, View } from 'react-native'
|
||||||
import CustomHeader from '@/components/custom/Header'
|
import CustomHeader from '@/components/custom/Header'
|
||||||
import { useAppStore } from '@/store/app'
|
import { useAppStore } from '@/store/app'
|
||||||
|
import { useNavStore } from '@/store/navigation'
|
||||||
|
|
||||||
export default function Share() {
|
export default function Share() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
const navStore = useNavStore()
|
||||||
|
|
||||||
const [showExitModal, setShowExitModal] = useState(false)
|
const [showExitModal, setShowExitModal] = useState(false)
|
||||||
|
|
||||||
function exitLogin() {
|
function exitLogin() {
|
||||||
setShowExitModal(false)
|
setShowExitModal(false)
|
||||||
|
|
||||||
// appStore.reset()
|
appStore.reset()
|
||||||
|
|
||||||
router.replace('/auth')
|
navStore.replace('/auth')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { axiosRequestAdapter } from '@alova/adapter-axios'
|
|||||||
import { createAlova } from 'alova'
|
import { createAlova } from 'alova'
|
||||||
import { toast } from 'sonner-native'
|
import { toast } from 'sonner-native'
|
||||||
import { useNavStore } from '@/store/navigation'
|
import { useNavStore } from '@/store/navigation'
|
||||||
|
import { useSpaceStore } from '@/store/space'
|
||||||
import { useUserStore } from '@/store/user'
|
import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
enum HttpCode {
|
enum HttpCode {
|
||||||
@@ -11,6 +12,7 @@ enum HttpCode {
|
|||||||
Unauthorized = 1001,
|
Unauthorized = 1001,
|
||||||
Fail = 500,
|
Fail = 500,
|
||||||
BusinessError = 2000,
|
BusinessError = 2000,
|
||||||
|
SystemError = 3000,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 仅保留「无需登录」接口
|
// 仅保留「无需登录」接口
|
||||||
@@ -29,8 +31,8 @@ function isWhiteListed(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const alovaInstance = createAlova({
|
const alovaInstance = createAlova({
|
||||||
// baseURL: 'http://192.168.5.6:8086/app',
|
baseURL: 'http://192.168.5.6:8086/app',
|
||||||
baseURL: 'http://192.168.1.137:8086/app',
|
// baseURL: 'http://192.168.1.137:8086/app',
|
||||||
requestAdapter: axiosRequestAdapter(),
|
requestAdapter: axiosRequestAdapter(),
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
cacheFor: null,
|
cacheFor: null,
|
||||||
@@ -54,6 +56,10 @@ const alovaInstance = createAlova({
|
|||||||
toast.error(resData.message || '业务异常,请稍后再试')
|
toast.error(resData.message || '业务异常,请稍后再试')
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
else if (resData.code === HttpCode.SystemError) {
|
||||||
|
toast.error(resData.message || '系统异常,请稍后再试')
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
@@ -69,6 +75,7 @@ const alovaInstance = createAlova({
|
|||||||
return
|
return
|
||||||
|
|
||||||
const userStore = useUserStore.getState()
|
const userStore = useUserStore.getState()
|
||||||
|
const spaceStore = useSpaceStore.getState()
|
||||||
|
|
||||||
// 未登录直接拦截
|
// 未登录直接拦截
|
||||||
if (!userStore.isLoggedIn()) {
|
if (!userStore.isLoggedIn()) {
|
||||||
@@ -78,6 +85,10 @@ const alovaInstance = createAlova({
|
|||||||
|
|
||||||
// 注入 JWT
|
// 注入 JWT
|
||||||
method.config.headers.Token = userStore.userInfo!.token
|
method.config.headers.Token = userStore.userInfo!.token
|
||||||
|
|
||||||
|
if (spaceStore.inSpace()) {
|
||||||
|
method.config.headers.SPACE_ID = spaceStore.currentSpace?.space_id
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +1,45 @@
|
|||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
import { enterDefaultSpaceApi } from '@/request/api/space'
|
import { enterDefaultSpaceApi } from '@/request/api/space'
|
||||||
import { getUserSpaceApi } from '@/request/api/user'
|
|
||||||
import { useMoneyCategoryStore } from './moneyCategory'
|
|
||||||
import { useNavStore } from './navigation'
|
import { useNavStore } from './navigation'
|
||||||
import { useSpaceStore } from './space'
|
import { useSpaceStore } from './space'
|
||||||
import { useUserStore } from './user'
|
import { useUserStore } from './user'
|
||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
ready: boolean
|
|
||||||
setReady: (v: boolean) => void
|
|
||||||
init: () => Promise<void>
|
init: () => Promise<void>
|
||||||
reset: () => void
|
reset: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAppStore = create<AppState>((set, get) => ({
|
export const useAppStore = create<AppState>((set, get) => ({
|
||||||
ready: false,
|
|
||||||
|
|
||||||
setReady: (v: boolean) => set({ ready: v }),
|
|
||||||
|
|
||||||
init: async () => {
|
init: async () => {
|
||||||
if (get().ready)
|
|
||||||
return
|
|
||||||
|
|
||||||
const userStore = useUserStore.getState()
|
const userStore = useUserStore.getState()
|
||||||
const navStore = useNavStore.getState()
|
const navStore = useNavStore.getState()
|
||||||
const moneyCategoryStore = useMoneyCategoryStore.getState()
|
|
||||||
const spaceStore = useSpaceStore.getState()
|
const spaceStore = useSpaceStore.getState()
|
||||||
|
|
||||||
// 如果没登录,跳转到登录页,但不退出初始化
|
|
||||||
if (!userStore.isLoggedIn()) {
|
if (!userStore.isLoggedIn()) {
|
||||||
navStore.navigateToAuth()
|
// navStore.navigateToAuth()
|
||||||
|
navStore.replace(`/auth`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (spaceStore.inSpace())
|
||||||
// 1️⃣ 初始化默认空间(如果用户当前没选中空间)
|
return
|
||||||
if (!spaceStore.inSpace()) {
|
|
||||||
const res = await enterDefaultSpaceApi()
|
|
||||||
if (res.isSuccess) {
|
|
||||||
if (res.data.space_id === 0) {
|
|
||||||
// 跳转到空间管理页面
|
|
||||||
}
|
|
||||||
spaceStore.setCurrentSpace(res.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2️⃣ 初始化分类
|
const res = await enterDefaultSpaceApi()
|
||||||
await moneyCategoryStore.init()
|
if (!res.isSuccess)
|
||||||
|
return
|
||||||
|
|
||||||
|
const space = res.data
|
||||||
|
if (space.space_id === 0) {
|
||||||
|
navStore.navigateTo(`/space`)
|
||||||
}
|
}
|
||||||
catch (err) {
|
else {
|
||||||
console.error('App init error:', err)
|
spaceStore.setCurrentSpace(space)
|
||||||
}
|
|
||||||
finally {
|
navStore.replace(`(tabs)`)
|
||||||
// 5️⃣ 初始化完成
|
|
||||||
set({ ready: true })
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
reset: () => {
|
reset: () => {
|
||||||
set({ ready: false })
|
|
||||||
useMoneyCategoryStore.getState().clear()
|
|
||||||
useUserStore.getState().clear()
|
useUserStore.getState().clear()
|
||||||
useSpaceStore.getState().clear()
|
useSpaceStore.getState().clear()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { icons } from 'lucide-react-native'
|
import type { icons } from 'lucide-react-native'
|
||||||
import { router } from 'expo-router'
|
import { router, useNavigation } from 'expo-router'
|
||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
|
|
||||||
export interface NavItem {
|
export interface NavItem {
|
||||||
@@ -11,8 +11,10 @@ export interface NavItem {
|
|||||||
interface NavState {
|
interface NavState {
|
||||||
navMenus: NavItem[]
|
navMenus: NavItem[]
|
||||||
pathname: string
|
pathname: string
|
||||||
|
replace: (p: string) => void
|
||||||
setPathname: (p: string) => void
|
setPathname: (p: string) => void
|
||||||
navigateToAuth: () => void
|
navigateToAuth: () => void
|
||||||
|
navigateTo: (p: string) => void
|
||||||
setNavMenus: (menus: NavItem[]) => void
|
setNavMenus: (menus: NavItem[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ const DEFAULT_NAV_MENUS: NavItem[] = [
|
|||||||
{ label: '恋爱记', path: '/love', icon: 'Heart' },
|
{ label: '恋爱记', path: '/love', icon: 'Heart' },
|
||||||
{ label: '聊天', path: '/chat', icon: 'MessageCircle' },
|
{ label: '聊天', path: '/chat', icon: 'MessageCircle' },
|
||||||
{ label: '个人中心', path: '/user', icon: 'CircleUserRound' },
|
{ label: '个人中心', path: '/user', icon: 'CircleUserRound' },
|
||||||
{ label: '空间管理', path: '/space/manage', icon: 'Earth' },
|
{ label: '空间管理', path: '/space', icon: 'Earth' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export const useNavStore = create<NavState>()(
|
export const useNavStore = create<NavState>()(
|
||||||
@@ -37,6 +39,15 @@ export const useNavStore = create<NavState>()(
|
|||||||
router.replace('/auth')
|
router.replace('/auth')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
navigateTo: (p: string) => {
|
||||||
|
router.navigate(p)
|
||||||
|
},
|
||||||
|
replace: (p: string) => {
|
||||||
|
if (router.canDismiss()) {
|
||||||
|
router.dismissAll()
|
||||||
|
}
|
||||||
|
router.replace(p)
|
||||||
|
},
|
||||||
setNavMenus: navMenus => set({ navMenus }),
|
setNavMenus: navMenus => set({ navMenus }),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
Reference in new issue
Block a user