# 01-APP React Native 项目结构初始化 ## 目标 使用 React Native CLI 创建项目,配置基础依赖和目录结构。 --- ## 前置要求 - React Native 环境已搭建 - Node.js 18+ 已安装 - Android Studio / Xcode 已配置 --- ## 实施步骤 ### 步骤 1:创建 React Native 项目 ```bash cd I:\apps\demo\healthApps # 创建项目 npx react-native init app --template react-native-template-typescript cd app ``` ### 步骤 2:安装核心依赖 ```bash # 导航 npm install @react-navigation/native @react-navigation/native-stack @react-navigation/bottom-tabs npm install react-native-screens react-native-safe-area-context # 状态管理 npm install zustand # 网络请求 npm install axios # 图表(体质雷达图) npm install react-native-svg npm install react-native-gifted-charts # 存储 npm install @react-native-async-storage/async-storage # 表单 npm install react-hook-form # UI 组件 npm install react-native-paper react-native-vector-icons npm install @types/react-native-vector-icons -D # 工具 npm install dayjs ``` ### 步骤 3:配置 iOS 依赖(macOS) ```bash cd ios pod install cd .. ``` ### 步骤 4:创建目录结构 ```bash mkdir -p src/api mkdir -p src/components/common mkdir -p src/components/survey mkdir -p src/components/constitution mkdir -p src/components/chat mkdir -p src/screens/auth mkdir -p src/screens/survey mkdir -p src/screens/constitution mkdir -p src/screens/chat mkdir -p src/screens/profile mkdir -p src/navigation mkdir -p src/stores mkdir -p src/hooks mkdir -p src/utils mkdir -p src/types mkdir -p src/assets ``` ### 步骤 5:创建类型定义 创建 `src/types/index.ts`: ```typescript export interface User { id: number phone: string email: string nickname: string avatar: string survey_completed: boolean } export interface HealthProfile { id: number name: string birth_date: string gender: string height: number weight: number bmi: number blood_type: string } export interface Question { id: number constitution_type: string question_text: string options: string[] order_num: number } export interface ConstitutionScore { type: string name: string score: number description: string } export interface ConstitutionResult { primary_constitution: ConstitutionScore secondary_constitutions: ConstitutionScore[] all_scores: ConstitutionScore[] recommendations: Record> assessed_at: string } export interface Conversation { id: number title: string created_at: string updated_at: string } export interface Message { id: number role: 'user' | 'assistant' | 'system' content: string created_at: string } export interface ApiResponse { code: number message: string data: T } ``` ### 步骤 6:创建 API 请求基础配置 创建 `src/api/request.ts`: ```typescript import axios from 'axios' import AsyncStorage from '@react-native-async-storage/async-storage' import { Alert } from 'react-native' import type { ApiResponse } from '../types' const API_BASE_URL = __DEV__ ? 'http://10.0.2.2:8080/api' // Android 模拟器 : 'https://your-production-url.com/api' const request = axios.create({ baseURL: API_BASE_URL, timeout: 30000, }) // 请求拦截器 request.interceptors.request.use( async (config) => { const token = await AsyncStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, (error) => Promise.reject(error) ) // 响应拦截器 request.interceptors.response.use( (response) => { const res = response.data as ApiResponse if (res.code !== 0) { Alert.alert('提示', res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res.data }, (error) => { if (error.response?.status === 401) { AsyncStorage.removeItem('token') // 这里需要导航到登录页,后续在导航配置中处理 } Alert.alert('错误', error.message || '网络错误') return Promise.reject(error) } ) export default request ``` ### 步骤 7:创建用户 Store 创建 `src/stores/userStore.ts`: ```typescript import { create } from 'zustand' import AsyncStorage from '@react-native-async-storage/async-storage' import type { User } from '../types' interface UserState { token: string user: User | null isLoggedIn: boolean surveyCompleted: boolean setToken: (token: string) => void setUser: (user: User) => void logout: () => void loadToken: () => Promise } export const useUserStore = create((set, get) => ({ token: '', user: null, isLoggedIn: false, surveyCompleted: false, setToken: async (token: string) => { await AsyncStorage.setItem('token', token) set({ token, isLoggedIn: !!token }) }, setUser: (user: User) => { set({ user, surveyCompleted: user.survey_completed }) }, logout: async () => { await AsyncStorage.removeItem('token') set({ token: '', user: null, isLoggedIn: false, surveyCompleted: false }) }, loadToken: async () => { const token = await AsyncStorage.getItem('token') if (token) { set({ token, isLoggedIn: true }) } }, })) ``` ### 步骤 8:更新 App.tsx 更新 `App.tsx`: ```typescript import React, { useEffect, useState } from 'react' import { StatusBar } from 'react-native' import { NavigationContainer } from '@react-navigation/native' import { Provider as PaperProvider } from 'react-native-paper' import { SafeAreaProvider } from 'react-native-safe-area-context' import { useUserStore } from './src/stores/userStore' import RootNavigator from './src/navigation/RootNavigator' const App = () => { const [isReady, setIsReady] = useState(false) const loadToken = useUserStore((state) => state.loadToken) useEffect(() => { const init = async () => { await loadToken() setIsReady(true) } init() }, []) if (!isReady) { return null // 或者显示 Splash Screen } return ( ) } export default App ``` ### 步骤 9:验证项目 ```bash # Android npm run android # iOS (macOS) npm run ios ``` --- ## 需要创建的文件清单 | 文件路径 | 说明 | |----------|------| | `src/types/index.ts` | 类型定义 | | `src/api/request.ts` | 请求封装 | | `src/stores/userStore.ts` | 用户状态管理 | | `App.tsx` | 应用入口(更新) | --- ## 最终目录结构 ``` app/ ├── src/ │ ├── api/ │ │ └── request.ts │ ├── components/ │ │ ├── common/ │ │ ├── survey/ │ │ ├── constitution/ │ │ └── chat/ │ ├── screens/ │ │ ├── auth/ │ │ ├── survey/ │ │ ├── constitution/ │ │ ├── chat/ │ │ └── profile/ │ ├── navigation/ │ ├── stores/ │ │ └── userStore.ts │ ├── hooks/ │ ├── utils/ │ ├── types/ │ │ └── index.ts │ └── assets/ ├── App.tsx ├── package.json ├── android/ └── ios/ ``` --- ## 验收标准 - [ ] 项目创建成功 - [ ] 依赖安装完成 - [ ] 目录结构创建完整 - [ ] 模拟器启动正常 - [ ] 无报错 --- ## 预计耗时 20-30 分钟 --- ## 下一步 完成后进入 `04-APP开发/02-导航和布局设计.md`