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', }, });