轻松聘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

248 lines
6.2 KiB

import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import { Alert, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { colors } from '../src/theme';
import { useAuth } from '../src/context/AuthContext';
/* ===================== 设置项结构 ===================== */
type SettingsItem = {
id: string;
title: string;
icon: keyof typeof Ionicons.glyphMap;
/** 有值则展示在右侧(如缓存大小) */
value?: string;
/** 跳转路由;未配置的为待开发项 */
route?: string;
};
type SettingsGroup = {
title: string;
items: SettingsItem[];
};
/** 设置分组(参考 Boss 直聘:账号 / 求职 / 通知 / 通用) */
const SETTINGS_GROUPS: SettingsGroup[] = [
{
title: '账号',
items: [
{
id: 'account',
title: '账号与安全',
icon: 'shield-checkmark-outline',
route: '/settings/account',
},
{ id: 'privacy', title: '隐私设置', icon: 'lock-closed-outline', route: '/settings/privacy' },
{
id: 'identity',
title: '身份切换',
icon: 'swap-horizontal-outline',
route: '/identity-select',
},
],
},
{
title: '求职',
items: [
{ id: 'weight-settings', title: '评分权重设置', icon: 'options-outline', route: '/jobs/weight-settings' },
],
},
{
title: '通知',
items: [
{
id: 'notification',
title: '消息通知',
icon: 'notifications-outline',
route: '/settings/notification',
},
],
},
{
title: '通用',
items: [
{ id: 'cache', title: '清除缓存', icon: 'trash-outline', value: '12.8MB' },
{
id: 'about',
title: '关于我们',
icon: 'information-circle-outline',
route: '/settings/about',
},
],
},
];
/* ===================== 子组件:顶部导航 ===================== */
function Header({ onBack }: { onBack: () => void }) {
return (
<View style={styles.header}>
<Pressable style={styles.headerBtn} onPress={onBack} hitSlop={8}>
<Ionicons name="chevron-back" size={24} color={colors.textPrimary} />
</Pressable>
<Text style={styles.headerTitle}>设置</Text>
<View style={styles.headerBtn} />
</View>
);
}
/* ===================== 设置页 ===================== */
export default function SettingsScreen() {
const router = useRouter();
const { logout } = useAuth();
const handleLogout = () => {
Alert.alert('确认退出登录', '退出后需要重新登录', [
{ text: '取消', style: 'cancel' },
{
text: '退出',
style: 'destructive',
onPress: () => {
logout();
router.replace('/login');
},
},
]);
};
const handlePress = (item: SettingsItem) => {
if (item.route) {
router.push(item.route);
return;
}
// 待开发项:仅占位,避免死路由
};
return (
<SafeAreaView style={styles.safeArea} edges={['top']}>
<Header onBack={() => router.back()} />
<ScrollView
style={styles.scroll}
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
>
{SETTINGS_GROUPS.map((group) => (
<View key={group.title} style={styles.group}>
<Text style={styles.groupTitle}>{group.title}</Text>
<View style={styles.card}>
{group.items.map((item, index) => {
const isLast = index === group.items.length - 1;
return (
<Pressable
key={item.id}
style={[styles.row, isLast && styles.rowLast]}
onPress={() => handlePress(item)}
hitSlop={4}
>
<View style={styles.iconWrap}>
<Ionicons name={item.icon} size={18} color={colors.primaryDark} />
</View>
<Text style={styles.rowTitle}>{item.title}</Text>
{item.value ? <Text style={styles.rowValue}>{item.value}</Text> : null}
<Ionicons name="chevron-forward" size={16} color={colors.textHint} />
</Pressable>
);
})}
</View>
</View>
))}
{/* 退出登录 */}
<Pressable style={styles.logoutBtn} onPress={handleLogout}>
<Text style={styles.logoutText}>退出登录</Text>
</Pressable>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: colors.pageBg,
},
header: {
height: 44,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 8,
},
headerBtn: {
width: 36,
height: 36,
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
fontSize: 17,
fontWeight: '700',
color: colors.textPrimary,
},
scroll: {
flex: 1,
},
scrollContent: {
paddingBottom: 32,
},
group: {
marginTop: 16,
paddingHorizontal: 8,
},
groupTitle: {
marginBottom: 8,
marginLeft: 8,
fontSize: 13,
color: colors.textSecondary,
},
card: {
backgroundColor: colors.surface,
borderRadius: 8,
paddingHorizontal: 16,
},
row: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 14,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: colors.borderLight,
},
rowLast: {
borderBottomWidth: 0,
},
iconWrap: {
width: 32,
height: 32,
borderRadius: 8,
backgroundColor: colors.primaryLight,
alignItems: 'center',
justifyContent: 'center',
marginRight: 12,
},
rowTitle: {
flex: 1,
fontSize: 14,
fontWeight: '500',
color: colors.textPrimary,
},
rowValue: {
marginRight: 4,
fontSize: 13,
color: colors.textHint,
},
logoutBtn: {
marginTop: 24,
marginHorizontal: 8,
backgroundColor: colors.surface,
borderRadius: 8,
paddingVertical: 14,
alignItems: 'center',
},
logoutText: {
fontSize: 15,
fontWeight: '600',
color: colors.dangerText,
},
});