diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx deleted file mode 100644 index 1f56793..0000000 --- a/app/(tabs)/index.tsx +++ /dev/null @@ -1,528 +0,0 @@ -import { Ionicons } from '@expo/vector-icons'; -import type { ComponentProps } from 'react'; -import { - ActivityIndicator, - Pressable, - ScrollView, - StyleSheet, - Text, - View, -} from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { useHomeData } from '../../src/hooks'; -import { colors } from '../../src/theme'; -import type { AssessmentTool, HomeAITool, HotJob } from '../../src/types'; - -type IconName = ComponentProps['name']; - -/* ===================== 配色映射(展示层,全部使用主题令牌) ===================== */ - -/** 分类图标配色:按分类 id 映射到语义色家族(浅底 + 图标色) */ -const CATEGORY_THEME: Record = { - it: { bg: colors.primaryLight, icon: colors.primary }, - finance: { bg: colors.actionLight, icon: colors.actionText }, - edu: { bg: colors.successLight, icon: colors.successText }, - health: { bg: colors.dangerLight, icon: colors.dangerText }, - mfg: { bg: colors.infoLight, icon: colors.infoText }, - house: { bg: colors.primaryLight, icon: colors.primaryDark }, - retail: { bg: colors.actionLight, icon: colors.action }, - media: { bg: colors.infoLight, icon: colors.info }, -}; - -/** 工具卡片配色:测评工具用主色,AI 工具用信息色 */ -const TOOL_THEME = { - primary: { - iconBg: colors.primaryLight, - icon: colors.primary, - action: colors.primaryText, - }, - info: { - iconBg: colors.infoLight, - icon: colors.info, - action: colors.infoText, - }, -} as const; - -/* ===================== 子组件 ===================== */ - -/** 高分优质岗位卡片 */ -function HotJobCard({ job }: { job: HotJob }) { - return ( - - - - {job.title} - - - - {job.score}分·{job.scoreLabel} - - - - {job.salary} - - {job.company} · {job.location} - - 经验{job.experience} - - {job.benefits.map((benefit) => ( - - {benefit} - - ))} - - - ); -} - -/** 工具卡片(成长测评 / AI 智能工具共用结构) */ -function ToolCard({ - tool, - variant, -}: { - tool: AssessmentTool | HomeAITool; - variant: keyof typeof TOOL_THEME; -}) { - const theme = TOOL_THEME[variant]; - return ( - { - /* TODO: 打开对应工具 */ - }} - > - - - - {tool.title} - {tool.description} - {tool.action} - - ); -} - -/** - * 首页 - */ -export default function HomeScreen() { - const { - user, - categories, - match, - hotJobs, - assessmentTools, - aiTools, - loading, - error, - refresh, - } = useHomeData(); - - // 错误态 - if (error) { - return ( - - - 加载失败,请重试 - - 重试 - - - - ); - } - - // 加载态 - if (loading || !user || !match) { - return ( - - - - - - ); - } - - return ( - - - {/* 1. 问候区域 + 通知入口 */} - - - 早上好,{user.name} - {user.slogan} - - { - /* TODO: 打开通知列表 */ - }} - > - - - - - - {/* 2. 搜索框(点击跳转搜索) */} - { - /* TODO: 跳转搜索页 */ - }} - > - - 搜索岗位、公司、关键词 - - - {/* 3. 分类导航(两行四列网格) */} - - {categories.map((cat) => { - const theme = CATEGORY_THEME[cat.id] ?? CATEGORY_THEME.it; - return ( - { - /* TODO: 跳转到对应分类岗位列表 */ - }} - > - - - - {cat.name} - - ); - })} - - - {/* 4. 匹配度卡片 */} - - - 您与{match.position}匹配度 - {match.matchRate}% - - { - /* TODO: 立即沟通 */ - }} - > - {match.subtitle} - - - - {/* 5. 高分优质岗位(横向滑动) */} - - 高分优质岗位 - - - {hotJobs.map((job) => ( - - ))} - - - {/* 6. 成长测评工具(两列并排) */} - - 成长测评工具 - - - {assessmentTools.map((tool) => ( - - ))} - - - {/* 7. AI 智能工具(两列并排) */} - - AI智能工具 - - - {aiTools.map((tool) => ( - - ))} - - - - ); -} - -// 跨平台阴影 -const shadow = { - shadowColor: colors.textPrimary, - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.06, - shadowRadius: 8, - elevation: 3, -}; - -const styles = StyleSheet.create({ - safeArea: { - flex: 1, - backgroundColor: colors.pageBg, - }, - stateWrap: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - stateText: { - marginTop: 12, - fontSize: 14, - color: colors.textSecondary, - }, - retryBtn: { - marginTop: 16, - paddingHorizontal: 24, - paddingVertical: 8, - borderRadius: 18, - backgroundColor: colors.primaryBtn, - }, - retryText: { - fontSize: 13, - fontWeight: '600', - color: colors.white, - }, - scroll: { - flex: 1, - }, - content: { - paddingHorizontal: 20, - paddingBottom: 24, - }, - /* ---- 问候 + 通知 ---- */ - header: { - flexDirection: 'row', - alignItems: 'flex-start', - justifyContent: 'space-between', - paddingTop: 8, - paddingBottom: 16, - }, - headerLeft: { - flex: 1, - }, - greeting: { - fontSize: 24, - fontWeight: '700', - color: colors.textPrimary, - }, - subtitle: { - marginTop: 8, - fontSize: 12, - color: colors.textSecondary, - }, - notice: { - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: colors.white, - alignItems: 'center', - justifyContent: 'center', - }, - noticeDot: { - position: 'absolute', - top: 8, - right: 9, - width: 8, - height: 8, - borderRadius: 4, - backgroundColor: colors.danger, - borderWidth: 1.5, - borderColor: colors.white, - }, - /* ---- 搜索框 ---- */ - searchBox: { - flexDirection: 'row', - alignItems: 'center', - height: 44, - borderRadius: 12, - backgroundColor: colors.white, - borderWidth: 1, - borderColor: colors.border, - paddingHorizontal: 12, - }, - searchPlaceholder: { - flex: 1, - marginLeft: 8, - fontSize: 14, - color: colors.textHint, - }, - /* ---- 分类网格 ---- */ - grid: { - flexDirection: 'row', - flexWrap: 'wrap', - marginTop: 20, - }, - gridItem: { - width: '25%', - alignItems: 'center', - marginBottom: 20, - }, - gridIconBg: { - width: 52, - height: 52, - borderRadius: 26, - alignItems: 'center', - justifyContent: 'center', - }, - gridLabel: { - marginTop: 8, - fontSize: 12, - color: colors.textPrimary, - textAlign: 'center', - }, - /* ---- 匹配度卡片 ---- */ - matchCard: { - marginTop: 4, - borderRadius: 16, - padding: 16, - backgroundColor: colors.primaryLight, - }, - matchRow: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, - matchTitle: { - flex: 1, - marginRight: 12, - fontSize: 15, - fontWeight: '600', - color: colors.textPrimary, - }, - matchRate: { - fontSize: 28, - fontWeight: '700', - color: colors.primary, - }, - matchAction: { - marginTop: 12, - fontSize: 13, - fontWeight: '600', - color: colors.primaryText, - }, - /* ---- 分区标题 ---- */ - sectionHeader: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginTop: 24, - marginBottom: 12, - }, - sectionTitle: { - fontSize: 18, - fontWeight: '700', - color: colors.textPrimary, - }, - /* ---- 横向滚动 ---- */ - hScroll: { - flexGrow: 0, - marginHorizontal: -20, - }, - hScrollContent: { - paddingHorizontal: 20, - paddingBottom: 4, - gap: 12, - }, - /* ---- 高分岗位卡片 ---- */ - jobCard: { - width: 240, - backgroundColor: colors.white, - borderRadius: 16, - padding: 16, - ...shadow, - }, - jobCardHeader: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, - jobTitle: { - flex: 1, - marginRight: 8, - fontSize: 16, - fontWeight: '700', - color: colors.textPrimary, - }, - scoreTag: { - backgroundColor: colors.primaryLight, - paddingHorizontal: 8, - paddingVertical: 4, - borderRadius: 6, - }, - scoreText: { - fontSize: 12, - fontWeight: '600', - color: colors.primaryDark, - }, - jobSalary: { - marginTop: 12, - fontSize: 18, - fontWeight: '700', - color: colors.primary, - }, - jobMeta: { - marginTop: 8, - fontSize: 13, - color: colors.textSecondary, - }, - jobTags: { - flexDirection: 'row', - flexWrap: 'wrap', - marginTop: 12, - }, - jobTag: { - backgroundColor: colors.primaryLight, - borderWidth: 1, - borderColor: colors.primaryBorder, - borderRadius: 12, - paddingHorizontal: 10, - paddingVertical: 4, - marginRight: 8, - marginBottom: 8, - }, - jobTagText: { - fontSize: 12, - color: colors.primary, - }, - /* ---- 工具卡片 ---- */ - toolsRow: { - flexDirection: 'row', - gap: 12, - }, - toolCard: { - flex: 1, - backgroundColor: colors.white, - borderRadius: 16, - padding: 16, - ...shadow, - }, - toolIconBg: { - width: 44, - height: 44, - borderRadius: 22, - alignItems: 'center', - justifyContent: 'center', - }, - toolTitle: { - marginTop: 12, - fontSize: 15, - fontWeight: '700', - color: colors.textPrimary, - }, - toolDesc: { - marginTop: 6, - fontSize: 12, - color: colors.textSecondary, - }, - toolAction: { - marginTop: 12, - fontSize: 13, - fontWeight: '600', - }, -}); diff --git a/src/hooks/useCategoryData.ts b/src/hooks/useCategoryData.ts deleted file mode 100644 index 8fc934f..0000000 --- a/src/hooks/useCategoryData.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 岗位分类数据 hook - */ -import { fetchCategories } from '../api'; -import { useAsyncData } from './useAsyncData'; - -export function useCategoryData() { - const { data: categories, loading, error, refresh } = useAsyncData(fetchCategories); - return { categories, loading, error, refresh }; -} diff --git a/src/hooks/useHomeData.ts b/src/hooks/useHomeData.ts deleted file mode 100644 index 123172a..0000000 --- a/src/hooks/useHomeData.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 首页数据 hook:并行组合用户信息、分类、匹配度、高分岗位、成长测评工具、AI 工具, - * 统一管理 loading / error / refresh 三态。 - */ -import { useCallback } from 'react'; -import { - fetchAssessmentTools, - fetchCategories, - fetchHomeAITools, - fetchHotJobs, - fetchMatchData, - fetchUserInfo, -} from '../api'; -import type { - AssessmentTool, - Category, - HomeAITool, - HotJob, - MatchData, - UserInfo, -} from '../types'; -import { useAsyncData } from './useAsyncData'; - -/** 首页聚合数据 */ -interface HomeData { - user: UserInfo; - categories: Category[]; - match: MatchData; - hotJobs: HotJob[]; - assessmentTools: AssessmentTool[]; - aiTools: HomeAITool[]; -} - -export function useHomeData() { - const fetcher = useCallback(async (): Promise => { - const [user, categories, match, hotJobs, assessmentTools, aiTools] = await Promise.all([ - fetchUserInfo(), - fetchCategories(), - fetchMatchData(), - fetchHotJobs(), - fetchAssessmentTools(), - fetchHomeAITools(), - ]); - return { user, categories, match, hotJobs, assessmentTools, aiTools }; - }, []); - - const { data, loading, error, refresh } = useAsyncData(fetcher); - - return { - user: data?.user ?? null, - categories: data?.categories ?? [], - match: data?.match ?? null, - hotJobs: data?.hotJobs ?? [], - assessmentTools: data?.assessmentTools ?? [], - aiTools: data?.aiTools ?? [], - loading, - error, - refresh, - }; -} \ No newline at end of file diff --git a/src/hooks/useMatchData.ts b/src/hooks/useMatchData.ts deleted file mode 100644 index 5b6dbd7..0000000 --- a/src/hooks/useMatchData.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 岗位匹配度数据 hook - */ -import { fetchMatchData } from '../api'; -import { useAsyncData } from './useAsyncData'; - -export function useMatchData() { - const { data: match, loading, error, refresh } = useAsyncData(fetchMatchData); - return { match, loading, error, refresh }; -} diff --git a/src/hooks/useUserProfile.ts b/src/hooks/useUserProfile.ts deleted file mode 100644 index c66cb03..0000000 --- a/src/hooks/useUserProfile.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 当前用户信息数据 hook - */ -import { fetchUserInfo } from '../api'; -import { useAsyncData } from './useAsyncData'; - -export function useUserProfile() { - const { data: user, loading, error, refresh } = useAsyncData(fetchUserInfo); - return { user, loading, error, refresh }; -} diff --git a/src/types/home.ts b/src/types/home.ts deleted file mode 100644 index ef1b251..0000000 --- a/src/types/home.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 首页相关类型定义 - */ - -/** 热门岗位(首页「高分优质岗位」横向卡片;薪资/评分文案已由接口层格式化) */ -export interface HotJob { - id: string; - /** 岗位名称 */ - title: string; - /** 匹配分数(0-100) */ - score: number; - /** 评级文案,如 "优秀" */ - scoreLabel: string; - /** 已格式化薪资,如 "25-40K·15薪" */ - salary: string; - /** 公司名 */ - company: string; - /** 城市,如 "北京" */ - location: string; - /** 经验要求,如 "3-5年" */ - experience: string; - /** 福利标签 */ - benefits: string[]; -} - -/** 首页工具卡片(成长测评工具 / AI 智能工具共用的卡片结构) */ -export interface HomeTool { - id: string; - /** 工具名称 */ - title: string; - /** 工具描述 */ - description: string; - /** Ionicons 图标名 */ - icon: string; - /** 操作文案,如 "立即测评 →" */ - action: string; -} - -/** - * 测评工具(与 HomeTool 结构一致,语义化别名)。 - * 说明:成长页已存在带 variant 字段的 AITool,首页 AI 工具独立命名为 HomeAITool 以规避重名。 - */ -export type AssessmentTool = HomeTool; - -/** AI 智能工具(首页) */ -export type HomeAITool = HomeTool; \ No newline at end of file