From 46106d0c76f466db555fccf33551098e2cf8cb9c Mon Sep 17 00:00:00 2001 From: oneao Date: Tue, 3 Mar 2026 22:05:25 +0800 Subject: [PATCH] u --- .../allapp-rn/src/app/(tabs)/_layout.tsx | 2 +- code/allapp/allapp-rn/src/app/(tabs)/chat.tsx | 4 +- .../allapp/allapp-rn/src/app/(tabs)/index.tsx | 6 +- code/allapp/allapp-rn/src/app/_layout.tsx | 18 ++- code/allapp/allapp-rn/src/app/auth/index.tsx | 42 ++++--- .../src/app/space/{manage => }/index.tsx | 22 ++-- .../{manage => }/sub-page/invite/index.tsx | 114 ++++++++---------- .../{manage => }/sub-page/member/index.tsx | 0 .../{manage => }/sub-page/settings/index.tsx | 23 +++- .../src/app/system/settings/index.tsx | 6 +- code/allapp/allapp-rn/src/request/index.ts | 15 ++- code/allapp/allapp-rn/src/store/app.ts | 50 +++----- code/allapp/allapp-rn/src/store/navigation.ts | 15 ++- 13 files changed, 171 insertions(+), 146 deletions(-) rename code/allapp/allapp-rn/src/app/space/{manage => }/index.tsx (96%) rename code/allapp/allapp-rn/src/app/space/{manage => }/sub-page/invite/index.tsx (60%) rename code/allapp/allapp-rn/src/app/space/{manage => }/sub-page/member/index.tsx (100%) rename code/allapp/allapp-rn/src/app/space/{manage => }/sub-page/settings/index.tsx (96%) diff --git a/code/allapp/allapp-rn/src/app/(tabs)/_layout.tsx b/code/allapp/allapp-rn/src/app/(tabs)/_layout.tsx index 4a2bb641..c853301e 100644 --- a/code/allapp/allapp-rn/src/app/(tabs)/_layout.tsx +++ b/code/allapp/allapp-rn/src/app/(tabs)/_layout.tsx @@ -57,7 +57,7 @@ export default function TabsLayout() { " onPress={() => { setShowNavDrawer(false) - router.push(item.path) + router.navigate(item.path) }} > diff --git a/code/allapp/allapp-rn/src/app/(tabs)/chat.tsx b/code/allapp/allapp-rn/src/app/(tabs)/chat.tsx index fa652522..dcebbb8d 100644 --- a/code/allapp/allapp-rn/src/app/(tabs)/chat.tsx +++ b/code/allapp/allapp-rn/src/app/(tabs)/chat.tsx @@ -2,9 +2,11 @@ import React, { useState } from 'react' import { Text, View } from 'react-native' import { AButton, AModal } from '@/components/common/ao' import AnimatedSwitch from '@/components/common/ao/Switch' +import { useSpaceStore } from '@/store/space' export default function TestScreen() { const [showDissolve, setShowDissolve] = useState(false) + const spaceStore = useSpaceStore() return ( @@ -12,7 +14,7 @@ export default function TestScreen() { setShowDissolve(true) }} > - 测试 + {spaceStore.currentSpace?.space_id} router.replace('/money')} + onPress={() => ('/money')} > 开始使用 */} router.replace('/money')} + onPress={() => ('/money')} > 创建空间 router.replace('/money')} + onPress={() => ('/money')} > 加入空间 diff --git a/code/allapp/allapp-rn/src/app/_layout.tsx b/code/allapp/allapp-rn/src/app/_layout.tsx index eb87597f..706b43ee 100644 --- a/code/allapp/allapp-rn/src/app/_layout.tsx +++ b/code/allapp/allapp-rn/src/app/_layout.tsx @@ -42,9 +42,10 @@ export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) { export default function RootLayout() { const pathname = usePathname() - const navStore = useNavStore() const appStore = useAppStore() + const navStore = useNavStore() + const [fontsLoaded] = useFonts({ SpaceMono: require('@/static/fonts/SpaceMono-Regular.ttf'), }) @@ -54,12 +55,19 @@ export default function RootLayout() { }, [pathname]) useEffect(() => { - if (!fontsLoaded) { + if (!fontsLoaded) return + + const bootstrap = async () => { + try { + await appStore.init() + } + finally { + SplashScreen.hideAsync() + } } - SplashScreen.hideAsync() - // appStore.init().finally(() => { - // }) + + bootstrap() }, [fontsLoaded]) return ( diff --git a/code/allapp/allapp-rn/src/app/auth/index.tsx b/code/allapp/allapp-rn/src/app/auth/index.tsx index e2d1c8c2..f5fd8458 100644 --- a/code/allapp/allapp-rn/src/app/auth/index.tsx +++ b/code/allapp/allapp-rn/src/app/auth/index.tsx @@ -1,18 +1,22 @@ import { useEvent } from 'expo' // import ExpoQQ from 'expo-qq' -import { useRouter } from 'expo-router' +import { useNavigation, useRouter } from 'expo-router' // import ExpoWeChat from 'expo-wechat' import { useEffect, useState } from 'react' import { Image, Text, View } from 'react-native' +import { toast } from 'sonner-native' import { AButton, ACheckbox } from '@/components/common/ao' import CustomHeader from '@/components/custom/Header' import { IconQq, IconWeixin } from '@/components/iconfont' import { loginQqApi, loginWxApi } from '@/request/api/auth' import { useAppStore } from '@/store/app' +import { useSpaceStore } from '@/store/space' import { useUserStore } from '@/store/user' -import { toast } from '@/utils/toast' export default function Auth() { + const appStore = useAppStore() + const navigation = useNavigation() + const [loading, setLoading] = useState(false) const [isAgree, setIsAgree] = useState(true) const [form, setForm] = useState({ @@ -23,7 +27,6 @@ export default function Auth() { const router = useRouter() const userStore = useUserStore() - const appStore = useAppStore() // const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished') // const onGetUserInfo = useEvent(ExpoQQ, 'onGetUserInfo') @@ -44,9 +47,7 @@ export default function Auth() { // // 检查微信是否安装 // const isInstalled = await ExpoWeChat.isWXAppInstalled() // if (!isInstalled) { - // toast.show({ - // title: onLoginFinished?.errorMessage || '请先安装微信', - // }) + // toast.warning(onLoginFinished?.errorMessage || '请先安装微信') // setLoading(false) // return // } @@ -70,9 +71,7 @@ export default function Auth() { // } // if (!onLoginFinished.success) { - // toast.show({ - // title: onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权', - // }) + // toast.warning(onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权') // setLoading(false) // return // } @@ -81,9 +80,7 @@ export default function Auth() { // try { // const tokenInfo = await ExpoQQ.getLoginTokenInfo() // if (!tokenInfo.openId) { - // toast.show({ - // title: tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权', - // }) + // toast.warning(tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权') // setLoading(false) // return // } @@ -126,8 +123,7 @@ export default function Auth() { // nickname: loginRes.data.nickname, // avatar: loginRes.data.avatar, // }) - - // router.push('/space/manage') + // await appStore.init() // } // } // catch (err) { @@ -161,7 +157,7 @@ export default function Auth() { // avatar: loginRes.data.avatar, // }) - // router.push('/') + // await appStore.init() // } // } // catch (err) { @@ -180,19 +176,27 @@ export default function Auth() { // handleLogin() // }, [authResult]) - function testLogin() { + async function testLogin() { // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NjY3ODU5ODIxNjUwNjEsImlhdCI6MTc2OTM0ODI0Nn0.17ZNaHD3HSLM8dVn_JQK-gvsG9MKj47IRYV9D4xZkzs userStore.setUserInfo({ - token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NzgxMTUwMzIxMDA5MzMsImlhdCI6MTc3MjE5MDQ0Mn0.GF611RBvU47QuW2s4kOcdvh88ieIbHu7M_SmWeBOqLY', + token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3Nzk4OTU0MTkxMjE3MzMsImlhdCI6MTc3MjU0MDU1OH0.M5KqfPWdpOAlCCtZrJRxwKc8bRpGBjEt9BNCfgBZgnc', id: 778115032100933, nickname: 'Zhang', 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 ( diff --git a/code/allapp/allapp-rn/src/app/space/manage/index.tsx b/code/allapp/allapp-rn/src/app/space/index.tsx similarity index 96% rename from code/allapp/allapp-rn/src/app/space/manage/index.tsx rename to code/allapp/allapp-rn/src/app/space/index.tsx index 48b39d08..3d3b38c4 100644 --- a/code/allapp/allapp-rn/src/app/space/manage/index.tsx +++ b/code/allapp/allapp-rn/src/app/space/index.tsx @@ -84,8 +84,8 @@ export default function AuthSpace() { { - router.push({ - pathname: '/space/manage/sub-page/settings', + router.navigate({ + pathname: '/space/sub-page/settings', params: { spaceId: item.space_id, }, @@ -238,11 +238,12 @@ export default function AuthSpace() { )} > { - loading ? ( - - - - ) + loading + ? ( + + + + ) : spaces.length === 0 ? ( @@ -251,7 +252,8 @@ export default function AuthSpace() { description="请选择 创建 或 加入 空间" /> - ) : ( + ) + : ( { @@ -334,7 +336,7 @@ export default function AuthSpace() { { + onPress={async () => { if (!createForm.name) { toast.warning('请输入空间名称') return @@ -343,7 +345,7 @@ export default function AuthSpace() { setCreateLoading(true) try { - createSpaceApi({ + await createSpaceApi({ name: createForm.name, member_name: userStore.userInfo.nickname, sort_number: spaces.length, diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx b/code/allapp/allapp-rn/src/app/space/sub-page/invite/index.tsx similarity index 60% rename from code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx rename to code/allapp/allapp-rn/src/app/space/sub-page/invite/index.tsx index 6e146b89..241b57e4 100644 --- a/code/allapp/allapp-rn/src/app/space/manage/sub-page/invite/index.tsx +++ b/code/allapp/allapp-rn/src/app/space/sub-page/invite/index.tsx @@ -101,71 +101,63 @@ export default function Invite() { { - loading ? ( - - - - ) : ( - - - {/* 邀请码卡片 */} - - - 复制邀请码邀请家庭成员加入 - - - - {space?.invite_code} - - - - - } - > - 复制邀请码 - - - { - userStore.userInfo.id === space?.owner_id && ( - - } - loading={refreshLoading} - onPress={refreshInviteCode} - > - 刷新 - - ) - } - + loading + ? ( + + - + ) + : ( + + + + 复制邀请码邀请家庭成员加入 + - - - + + {space?.invite_code} + - {/* 二维码卡片 */} - setPreviewVisible(true)} - className="bg-white rounded-2xl py-8 items-center" - > - - + + + } + > + 复制邀请码 + - - ) + {userStore.userInfo.id === space?.owner_id && ( + + } + loading={refreshLoading} + onPress={refreshInviteCode} + > + 刷新 + + )} + + + + + + + + setPreviewVisible(true)} + className="bg-white rounded-2xl py-8 items-center" + > + + + + ) } {/* 全屏预览(无动画) */} diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/member/index.tsx b/code/allapp/allapp-rn/src/app/space/sub-page/member/index.tsx similarity index 100% rename from code/allapp/allapp-rn/src/app/space/manage/sub-page/member/index.tsx rename to code/allapp/allapp-rn/src/app/space/sub-page/member/index.tsx diff --git a/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx b/code/allapp/allapp-rn/src/app/space/sub-page/settings/index.tsx similarity index 96% rename from code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx rename to code/allapp/allapp-rn/src/app/space/sub-page/settings/index.tsx index 41e02044..db2e6267 100644 --- a/code/allapp/allapp-rn/src/app/space/manage/sub-page/settings/index.tsx +++ b/code/allapp/allapp-rn/src/app/space/sub-page/settings/index.tsx @@ -1,5 +1,5 @@ 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 { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native' import { KeyboardAvoidingView } from 'react-native-keyboard-controller' @@ -15,6 +15,7 @@ import { ActionsheetDragIndicatorWrapper, } from '@/components/ui/actionsheet' import { dissolveSpaceApi, enterSpaceApi, exitSpaceApi, getSpaceSettingsApi, updateSpaceDefaultApi, updateSpaceMemberNameApi, updateSpaceNameApi } from '@/request/api/space' +import { useNavStore } from '@/store/navigation' import { useSpaceStore } from '@/store/space' import { useUserStore } from '@/store/user' @@ -62,6 +63,7 @@ function Item({ export default function Settings() { const userStore = useUserStore() const spaceStore = useSpaceStore() + const navStore = useNavStore() const params = useLocalSearchParams<{ spaceId: string }>() const { spaceId } = params @@ -102,6 +104,16 @@ export default function Settings() { } }, [showName]) + useEffect(() => { + if (showMemberName) { + const timer = setTimeout(() => { + memberNameInputRef.current?.focus() + }, 300) + + return () => clearTimeout(timer) + } + }, [showMemberName]) + useFocusEffect( useCallback(() => { if (spaceId) { @@ -147,7 +159,7 @@ export default function Settings() { }) try { - enterSpaceApi({ + await enterSpaceApi({ space_id: space.space_id, }).then((res) => { if (res.isSuccess) { @@ -156,7 +168,8 @@ export default function Settings() { space_id: space.space_id, role: space.role, }) - router.navigate('/money') + + navStore.replace('(tabs)') } }) } @@ -258,7 +271,7 @@ export default function Settings() { title="邀请" onPress={() => { router.navigate({ - pathname: '/space/manage/sub-page/invite', + pathname: '/space/sub-page/invite', params: { space_id: space.space_id, }, @@ -279,7 +292,7 @@ export default function Settings() { title="空间成员" onPress={() => { router.navigate({ - pathname: '/space/manage/sub-page/member', + pathname: '/space/sub-page/member', params: { space_id: space.space_id, }, diff --git a/code/allapp/allapp-rn/src/app/system/settings/index.tsx b/code/allapp/allapp-rn/src/app/system/settings/index.tsx index 5d43da4d..e7d9018a 100644 --- a/code/allapp/allapp-rn/src/app/system/settings/index.tsx +++ b/code/allapp/allapp-rn/src/app/system/settings/index.tsx @@ -3,19 +3,21 @@ import { useState } from 'react' import { Text, TouchableOpacity, View } from 'react-native' import CustomHeader from '@/components/custom/Header' import { useAppStore } from '@/store/app' +import { useNavStore } from '@/store/navigation' export default function Share() { const router = useRouter() const appStore = useAppStore() + const navStore = useNavStore() const [showExitModal, setShowExitModal] = useState(false) function exitLogin() { setShowExitModal(false) - // appStore.reset() + appStore.reset() - router.replace('/auth') + navStore.replace('/auth') } return ( diff --git a/code/allapp/allapp-rn/src/request/index.ts b/code/allapp/allapp-rn/src/request/index.ts index 32c49953..e1b1517e 100644 --- a/code/allapp/allapp-rn/src/request/index.ts +++ b/code/allapp/allapp-rn/src/request/index.ts @@ -4,6 +4,7 @@ import { axiosRequestAdapter } from '@alova/adapter-axios' import { createAlova } from 'alova' import { toast } from 'sonner-native' import { useNavStore } from '@/store/navigation' +import { useSpaceStore } from '@/store/space' import { useUserStore } from '@/store/user' enum HttpCode { @@ -11,6 +12,7 @@ enum HttpCode { Unauthorized = 1001, Fail = 500, BusinessError = 2000, + SystemError = 3000, } // 仅保留「无需登录」接口 @@ -29,8 +31,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, @@ -54,6 +56,10 @@ const alovaInstance = createAlova({ toast.error(resData.message || '业务异常,请稍后再试') return result } + else if (resData.code === HttpCode.SystemError) { + toast.error(resData.message || '系统异常,请稍后再试') + return result + } return result }, @@ -69,6 +75,7 @@ const alovaInstance = createAlova({ return const userStore = useUserStore.getState() + const spaceStore = useSpaceStore.getState() // 未登录直接拦截 if (!userStore.isLoggedIn()) { @@ -78,6 +85,10 @@ const alovaInstance = createAlova({ // 注入 JWT method.config.headers.Token = userStore.userInfo!.token + + if (spaceStore.inSpace()) { + method.config.headers.SPACE_ID = spaceStore.currentSpace?.space_id + } }, }) diff --git a/code/allapp/allapp-rn/src/store/app.ts b/code/allapp/allapp-rn/src/store/app.ts index 25bee585..9010a463 100644 --- a/code/allapp/allapp-rn/src/store/app.ts +++ b/code/allapp/allapp-rn/src/store/app.ts @@ -1,65 +1,45 @@ import { create } from 'zustand' import { enterDefaultSpaceApi } from '@/request/api/space' -import { getUserSpaceApi } from '@/request/api/user' -import { useMoneyCategoryStore } from './moneyCategory' import { useNavStore } from './navigation' import { useSpaceStore } from './space' import { useUserStore } from './user' interface AppState { - ready: boolean - setReady: (v: boolean) => void init: () => Promise reset: () => void } export const useAppStore = create((set, get) => ({ - ready: false, - - setReady: (v: boolean) => set({ ready: v }), - init: async () => { - if (get().ready) - return - const userStore = useUserStore.getState() const navStore = useNavStore.getState() - const moneyCategoryStore = useMoneyCategoryStore.getState() const spaceStore = useSpaceStore.getState() - // 如果没登录,跳转到登录页,但不退出初始化 if (!userStore.isLoggedIn()) { - navStore.navigateToAuth() + // navStore.navigateToAuth() + navStore.replace(`/auth`) return } - try { - // 1️⃣ 初始化默认空间(如果用户当前没选中空间) - if (!spaceStore.inSpace()) { - const res = await enterDefaultSpaceApi() - if (res.isSuccess) { - if (res.data.space_id === 0) { - // 跳转到空间管理页面 - } - spaceStore.setCurrentSpace(res.data) - } - } + if (spaceStore.inSpace()) + return - // 2️⃣ 初始化分类 - await moneyCategoryStore.init() + const res = await enterDefaultSpaceApi() + if (!res.isSuccess) + return + + const space = res.data + if (space.space_id === 0) { + navStore.navigateTo(`/space`) } - catch (err) { - console.error('App init error:', err) - } - finally { - // 5️⃣ 初始化完成 - set({ ready: true }) + else { + spaceStore.setCurrentSpace(space) + + navStore.replace(`(tabs)`) } }, reset: () => { - set({ ready: false }) - useMoneyCategoryStore.getState().clear() useUserStore.getState().clear() useSpaceStore.getState().clear() }, diff --git a/code/allapp/allapp-rn/src/store/navigation.ts b/code/allapp/allapp-rn/src/store/navigation.ts index 93027270..97486647 100644 --- a/code/allapp/allapp-rn/src/store/navigation.ts +++ b/code/allapp/allapp-rn/src/store/navigation.ts @@ -1,5 +1,5 @@ import type { icons } from 'lucide-react-native' -import { router } from 'expo-router' +import { router, useNavigation } from 'expo-router' import { create } from 'zustand' export interface NavItem { @@ -11,8 +11,10 @@ export interface NavItem { interface NavState { navMenus: NavItem[] pathname: string + replace: (p: string) => void setPathname: (p: string) => void navigateToAuth: () => void + navigateTo: (p: string) => void setNavMenus: (menus: NavItem[]) => void } @@ -21,7 +23,7 @@ const DEFAULT_NAV_MENUS: NavItem[] = [ { label: '恋爱记', path: '/love', icon: 'Heart' }, { label: '聊天', path: '/chat', icon: 'MessageCircle' }, { label: '个人中心', path: '/user', icon: 'CircleUserRound' }, - { label: '空间管理', path: '/space/manage', icon: 'Earth' }, + { label: '空间管理', path: '/space', icon: 'Earth' }, ] export const useNavStore = create()( @@ -37,6 +39,15 @@ export const useNavStore = create()( router.replace('/auth') } }, + navigateTo: (p: string) => { + router.navigate(p) + }, + replace: (p: string) => { + if (router.canDismiss()) { + router.dismissAll() + } + router.replace(p) + }, setNavMenus: navMenus => set({ navMenus }), }), )