import { useLocalSearchParams, useRouter } from 'expo-router'; import { useEffect, useState } from 'react'; import { Alert, ScrollView, StyleSheet, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { PrimaryButton } from '../../components/onboarding/ui/PrimaryButton'; import { CenterState, EditHeader, Field, FormNote, IconAction, PageFooter, } from '../../components/resume/EditKit'; import { useResume } from '../../src/hooks'; import { colors , spacing } from '../../src/theme'; import type { ResumeEducation } from '../../src/types'; /** * 教育背景编辑页:一页两态(列表态 / 表单态)。 * * 入口三种:首页「添加教育经历」带 `?new=1` 直接进表单、条目「编辑」带 `?id=` 进表单、 * 首页「编辑 >」不带参数进列表。删除与编辑都在本页完成并**即时落盘**, * 不存在「改了没保存就走」的困惑。 */ export default function ResumeEducationScreen() { const router = useRouter(); const params = useLocalSearchParams<{ new?: string; id?: string }>(); const { resume, loading, error, refresh, saving, saveEducation } = useResume(); /** 非空 = 表单态;null = 列表态 */ const [editing, setEditing] = useState(null); /** 入口参数只解析一次:解析后再取数(或保存后的刷新)不该把用户拉回表单/列表 */ const [entryApplied, setEntryApplied] = useState(false); useEffect(() => { if (!resume || entryApplied) return; setEntryApplied(true); if (params.new === '1') { setEditing(EMPTY_FORM); return; } if (params.id !== undefined && params.id !== '') { const found = resume.education.find((it) => it.id === params.id); // 找不到就留在列表态:编一条空表单让用户改,等于凭空多出一条教育经历 if (found) setEditing(toForm(found)); } }, [resume, entryApplied, params.new, params.id]); const list = resume?.education ?? []; const header = ( (editing === null ? router.back() : setEditing(null))} /> ); if (resume === null) { return ( {header} {error !== null ? ( ) : ( )} ); } /* ===================== 表单态 ===================== */ if (editing !== null) { const school = editing.school.trim(); const startError = editing.startYear !== '' && !YEAR_RE.test(editing.startYear) ? '请输入 4 位年份' : ''; const endError = editing.endYear !== '' && !YEAR_RE.test(editing.endYear) ? '请输入 4 位年份' : ''; const orderError = startError === '' && endError === '' && editing.startYear !== '' && editing.endYear !== '' && editing.startYear > editing.endYear ? '毕业年份不能早于入学年份' : ''; const canSave = school !== '' && startError === '' && endError === '' && orderError === ''; const update = (field: keyof EduForm, text: string) => setEditing((prev) => ({ ...(prev ?? editing), [field]: text })); const handleSubmit = async () => { if (!canSave || saving) return; const fields = { school, major: editing.major.trim(), degree: editing.degree.trim(), startYear: editing.startYear, endYear: editing.endYear, }; // 交回整表。新增项**不带 id 字段**(而不是给空串):API 层用 `?? ` 判缺省, // 空串不是 nullish,会把 id 写成空的 const next = editing.id === undefined ? [...list, fields] : list.map((it) => (it.id === editing.id ? { ...fields, id: editing.id } : it)); await saveEducation(next); // 保存后回到列表态,让用户看见结果(不 router.back(),否则看不到自己刚加的那条) setEditing(null); }; return ( {header} update('school', v)} placeholder="请输入学校名称" maxLength={30} autoFocus /> update('major', v)} placeholder="如:计算机科学与技术" maxLength={30} /> update('degree', v)} placeholder="如:本科 / 硕士 非全日制" maxLength={20} hint="引导流程采集到的学历会带学习形式(如「硕士 非全日制」),这里可以照原样填" /> update('startYear', v.replace(/[^\d]/g, ''))} placeholder="如:2018" keyboardType="number-pad" maxLength={4} error={startError} /> update('endYear', v.replace(/[^\d]/g, ''))} placeholder="如:2022" keyboardType="number-pad" maxLength={4} error={endError} /> {orderError !== '' && {orderError}} ); } /* ===================== 列表态 ===================== */ const handleDelete = (item: ResumeEducation) => { Alert.alert('删除这条教育经历?', item.school, [ { text: '取消', style: 'cancel' }, { text: '删除', style: 'destructive', // 即时落盘:删掉就走也不用担心没保存 onPress: () => { void saveEducation(list.filter((it) => it.id !== item.id)); }, }, ]); }; return ( {header} {list.length === 0 ? ( ) : ( {list.map((edu) => { // 专业 / 学历 / 年份可能为空(引导只采集学校和学历),拼出来会剩「· 本科」这种半截值 const majorDegree = [edu.major, edu.degree].filter(Boolean).join(' · '); const years = [edu.startYear, edu.endYear].filter(Boolean).join('-'); return ( {edu.school} {majorDegree !== '' && {majorDegree}} {years !== '' && {years}} setEditing(toForm(edu))} /> handleDelete(edu)} /> ); })} )} setEditing(EMPTY_FORM)} /> ); } /* ===================== 表单与条目互转 ===================== */ interface EduForm { /** undefined = 新增项(由 API 层补 id) */ id?: string; school: string; major: string; degree: string; startYear: string; endYear: string; } const EMPTY_FORM: EduForm = { school: '', major: '', degree: '', startYear: '', endYear: '' }; const YEAR_RE = /^\d{4}$/; const toForm = (edu: ResumeEducation): EduForm => ({ id: edu.id, school: edu.school, major: edu.major, degree: edu.degree, startYear: edu.startYear, endYear: edu.endYear, }); const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: colors.pageBg }, body: { padding: spacing.card, paddingBottom: 24 }, row: { flexDirection: 'row', alignItems: 'center', backgroundColor: colors.white, borderRadius: spacing.card, padding: spacing.card, marginBottom: 8, borderWidth: 1, borderColor: colors.borderLight, }, rowBody: { flex: 1, gap: 4 }, rowTitle: { fontSize: 15, fontWeight: '700', color: colors.textPrimary }, rowSub: { fontSize: 13, color: colors.textSecondary }, yearRow: { flexDirection: 'row', gap: 12 }, yearItem: { flex: 1 }, formError: { fontSize: 13, color: colors.dangerText, marginBottom: 8 }, });