import { Ionicons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { useRouter } from 'expo-router'; import { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useOfferCompareData } from '../../src/hooks'; import { colors, headerGradientSolid } from '../../src/theme'; import type { OfferBenefitGroup, OfferItem, OfferScore, WorkLifeBalanceRow } from '../../src/types'; /* ===================== 子组件 ===================== */ /** 顶部导航:返回 + 标题 + 编辑 */ function Header({ onBack, onEdit }: { onBack: () => void; onEdit?: () => void }) { return ( Offer对比 编辑 ); } /** 单个 Offer 卡片 */ function OfferCard({ offer, selected }: { offer: OfferItem; selected: boolean }) { return ( {offer.company} {selected && } {offer.position} {offer.salary} ); } /** 添加 Offer */ function AddOfferCard({ onPress }: { onPress: () => void }) { return ( 添加Offer ); } /** 星级评分 */ function StarRating({ stars }: { stars: number }) { return ( {[1, 2, 3, 4, 5].map((i) => ( ))} ); } /** 综合评分对比 */ function ScoreComparison({ offers, scores }: { offers: OfferItem[]; scores: OfferScore[] }) { return ( 综合评分对比 {offers.map((offer, index) => { const score = scores[index]; if (!score) return null; const isWinner = score.score === Math.max(...scores.map((s) => s.score)); return ( {score.score} {score.level} 推荐指数 ); })} ); } /** 分组对比表格 */ function BenefitComparison({ offers, groups }: { offers: OfferItem[]; groups: OfferBenefitGroup[] }) { return ( 薪资福利对比 {/* 表头:公司名 */} {offers.map((offer) => ( {offer.company} ))} {groups.map((group) => ( {group.title} {group.rows.map((row) => ( {row.label} {row.values.map((value, colIndex) => { const highlight = row.highlights?.[colIndex]; return ( {value ?? '-'} ); })} ))} ))} ); } /** 工作生活平衡 */ function WorkLifeBalance({ offers, rows }: { offers: OfferItem[]; rows: WorkLifeBalanceRow[] }) { return ( 工作生活平衡 {offers.map((offer) => ( {offer.company} ))} {rows.map((row) => ( {row.label} {row.values.map((value, colIndex) => { const highlight = row.highlights?.[colIndex]; return ( {value} ); })} ))} ); } /** AI 智能建议 */ function AISuggestionCard({ summary, detail, reportAction }: { summary: string; detail: string; reportAction: string }) { return ( AI智能建议 {summary} {detail} console.log('查看完整分析报告')}> {reportAction} ); } /* ===================== 页面 ===================== */ /** * Offer 对比页:对比已收到 Offer 的薪资、福利、工作生活平衡与 AI 建议 */ export default function OfferCompareScreen() { const router = useRouter(); const { data, offers, scores, benefitGroups, workLifeBalance, aiSuggestion, actions, loading, error, refresh } = useOfferCompareData(); if (error) { return (
router.back()} /> 加载失败,请重试 重试 ); } if (loading || !data) { return (
router.back()} /> 正在加载 Offer 对比… ); } return (
router.back()} /> {/* Offer 卡片头部 */} {offers.map((offer) => ( ))} console.log('添加 Offer')} /> {/* 综合评分对比 */} {/* 薪资福利对比 */} {/* 工作生活平衡 */} {/* AI 智能建议 */} {aiSuggestion && ( )} {/* 底部操作栏 */} console.log('导出对比报告')}> {actions?.exportLabel ?? '导出对比报告'} console.log('接受 Offer', actions?.acceptOfferId)}> {actions?.acceptLabel ?? '接受Offer'} ); } const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: colors.pageBg, }, /* ---- 顶部导航 ---- */ header: { height: 48, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 8, backgroundColor: colors.pageBg, }, headerBtn: { width: 48, height: 40, alignItems: 'center', justifyContent: 'center', }, headerTitle: { flex: 1, textAlign: 'center', fontSize: 17, fontWeight: '700', color: colors.textPrimary, }, headerEdit: { fontSize: 14, color: colors.primary, fontWeight: '600', }, /* ---- 状态 ---- */ stateWrap: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24, }, stateText: { marginTop: 12, fontSize: 14, color: colors.textSecondary, textAlign: 'center', }, 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: 12, paddingTop: 8, paddingBottom: 12, }, bottomGap: { height: 80, }, /* ---- Offer 卡片 ---- */ offerList: { gap: 10, paddingVertical: 4, paddingHorizontal: 4, }, offerCard: { width: 150, padding: 14, borderRadius: 12, backgroundColor: colors.white, borderWidth: 1, borderColor: colors.border, }, offerCardSelected: { borderColor: colors.primary, backgroundColor: colors.primaryLight, }, offerCardTop: { flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'space-between', }, offerCompany: { flex: 1, fontSize: 14, fontWeight: '700', color: colors.textPrimary, }, checkCircle: { width: 18, height: 18, borderRadius: 9, borderWidth: 1.5, borderColor: colors.borderStrong, alignItems: 'center', justifyContent: 'center', marginLeft: 6, }, checkCircleActive: { backgroundColor: colors.primary, borderColor: colors.primary, }, offerPosition: { marginTop: 6, fontSize: 12, color: colors.textSecondary, }, offerSalary: { marginTop: 10, fontSize: 16, fontWeight: '800', }, addOfferCard: { width: 80, padding: 12, borderRadius: 12, borderWidth: 1, borderStyle: 'dashed', borderColor: colors.borderStrong, alignItems: 'center', justifyContent: 'center', }, addOfferText: { marginTop: 6, fontSize: 12, color: colors.textHint, }, /* ---- 通用卡片与分区标题 ---- */ card: { backgroundColor: colors.white, borderRadius: 12, padding: 16, marginTop: 12, }, sectionHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 14, }, sectionBar: { width: 4, height: 16, borderRadius: 2, backgroundColor: colors.primary, marginRight: 8, }, sectionTitle: { fontSize: 16, fontWeight: '700', color: colors.textPrimary, }, /* ---- 综合评分对比 ---- */ scoreRow: { flexDirection: 'row', justifyContent: 'space-around', paddingTop: 4, }, scoreCol: { alignItems: 'center', flex: 1, }, scoreNum: { fontSize: 44, fontWeight: '800', color: colors.textSecondary, }, scoreNumWinner: { color: colors.success, }, scoreMeta: { flexDirection: 'row', alignItems: 'center', marginTop: 6, gap: 6, }, scoreLevel: { fontSize: 13, fontWeight: '700', }, starRow: { flexDirection: 'row', }, starIcon: { marginHorizontal: 1, }, scoreHint: { marginTop: 6, fontSize: 11, color: colors.textHint, }, /* ---- 表格 ---- */ tableHeaderRow: { flexDirection: 'row', alignItems: 'center', paddingBottom: 10, borderBottomWidth: 1, borderBottomColor: colors.borderLight, }, tableRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.borderLight, }, tableLabelCell: { width: 88, }, tableLabelText: { width: 88, fontSize: 13, color: colors.textSecondary, }, tableValueCell: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: 8, marginHorizontal: 2, borderRadius: 8, }, tableHeaderText: { fontSize: 13, fontWeight: '600', color: colors.textPrimary, textAlign: 'center', }, tableValueText: { fontSize: 13, color: colors.textPrimary, textAlign: 'center', }, tableValueTextHighlight: { color: colors.primaryText, fontWeight: '700', }, tableValueTextSuccess: { color: colors.successText, fontWeight: '700', }, offerDot: { width: 6, height: 6, borderRadius: 3, marginRight: 4, }, groupTitle: { marginTop: 14, marginBottom: 8, fontSize: 14, fontWeight: '700', color: colors.textPrimary, }, /* ---- AI 建议 ---- */ aiCard: { marginTop: 12, borderRadius: 12, padding: 16, }, aiHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, }, aiTitle: { marginLeft: 6, fontSize: 16, fontWeight: '700', color: colors.textInverse, }, aiSummary: { fontSize: 14, fontWeight: '700', color: colors.textInverse, lineHeight: 20, }, aiDetail: { marginTop: 8, fontSize: 13, color: colors.textInverse, opacity: 0.9, lineHeight: 19, }, aiReportBtn: { marginTop: 12, flexDirection: 'row', alignItems: 'center', }, aiReportText: { fontSize: 13, color: colors.textInverse, fontWeight: '600', }, /* ---- 底部操作栏 ---- */ actionBar: { position: 'absolute', left: 0, right: 0, bottom: 0, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingTop: 10, paddingBottom: 16, backgroundColor: colors.white, borderTopWidth: 1, borderTopColor: colors.borderLight, gap: 10, }, exportBtn: { flex: 1, height: 44, borderRadius: 22, borderWidth: 1, borderColor: colors.border, alignItems: 'center', justifyContent: 'center', }, exportText: { fontSize: 14, fontWeight: '600', color: colors.textPrimary, }, acceptBtn: { flex: 1.4, height: 44, borderRadius: 22, backgroundColor: colors.primaryBtn, alignItems: 'center', justifyContent: 'center', }, acceptText: { fontSize: 14, fontWeight: '700', color: colors.white, }, });