Browse Source
- 删除 app/(tabs)/index.tsx,Tab 入口改由 _layout 托管 - 删除迁移后失效的 4 个旧 hooks(useHomeData / useCategoryData / useMatchData / useUserProfile) - 删除随之失效的 src/types/home.tsmaster
6 changed files with 0 additions and 664 deletions
@ -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<typeof Ionicons>['name']; |
|
||||
|
|
||||
/* ===================== 配色映射(展示层,全部使用主题令牌) ===================== */ |
|
||||
|
|
||||
/** 分类图标配色:按分类 id 映射到语义色家族(浅底 + 图标色) */ |
|
||||
const CATEGORY_THEME: Record<string, { bg: string; icon: string }> = { |
|
||||
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 ( |
|
||||
<View style={styles.jobCard}> |
|
||||
<View style={styles.jobCardHeader}> |
|
||||
<Text style={styles.jobTitle} numberOfLines={1}> |
|
||||
{job.title} |
|
||||
</Text> |
|
||||
<View style={styles.scoreTag}> |
|
||||
<Text style={styles.scoreText}> |
|
||||
{job.score}分·{job.scoreLabel} |
|
||||
</Text> |
|
||||
</View> |
|
||||
</View> |
|
||||
<Text style={styles.jobSalary}>{job.salary}</Text> |
|
||||
<Text style={styles.jobMeta}> |
|
||||
{job.company} · {job.location} |
|
||||
</Text> |
|
||||
<Text style={styles.jobMeta}>经验{job.experience}</Text> |
|
||||
<View style={styles.jobTags}> |
|
||||
{job.benefits.map((benefit) => ( |
|
||||
<View key={benefit} style={styles.jobTag}> |
|
||||
<Text style={styles.jobTagText}>{benefit}</Text> |
|
||||
</View> |
|
||||
))} |
|
||||
</View> |
|
||||
</View> |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
/** 工具卡片(成长测评 / AI 智能工具共用结构) */ |
|
||||
function ToolCard({ |
|
||||
tool, |
|
||||
variant, |
|
||||
}: { |
|
||||
tool: AssessmentTool | HomeAITool; |
|
||||
variant: keyof typeof TOOL_THEME; |
|
||||
}) { |
|
||||
const theme = TOOL_THEME[variant]; |
|
||||
return ( |
|
||||
<Pressable |
|
||||
style={styles.toolCard} |
|
||||
onPress={() => { |
|
||||
/* TODO: 打开对应工具 */ |
|
||||
}} |
|
||||
> |
|
||||
<View style={[styles.toolIconBg, { backgroundColor: theme.iconBg }]}> |
|
||||
<Ionicons name={tool.icon as IconName} size={22} color={theme.icon} /> |
|
||||
</View> |
|
||||
<Text style={styles.toolTitle}>{tool.title}</Text> |
|
||||
<Text style={styles.toolDesc}>{tool.description}</Text> |
|
||||
<Text style={[styles.toolAction, { color: theme.action }]}>{tool.action}</Text> |
|
||||
</Pressable> |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 首页 |
|
||||
*/ |
|
||||
export default function HomeScreen() { |
|
||||
const { |
|
||||
user, |
|
||||
categories, |
|
||||
match, |
|
||||
hotJobs, |
|
||||
assessmentTools, |
|
||||
aiTools, |
|
||||
loading, |
|
||||
error, |
|
||||
refresh, |
|
||||
} = useHomeData(); |
|
||||
|
|
||||
// 错误态
|
|
||||
if (error) { |
|
||||
return ( |
|
||||
<SafeAreaView style={styles.safeArea} edges={['top']}> |
|
||||
<View style={styles.stateWrap}> |
|
||||
<Text style={styles.stateText}>加载失败,请重试</Text> |
|
||||
<Pressable style={styles.retryBtn} onPress={refresh}> |
|
||||
<Text style={styles.retryText}>重试</Text> |
|
||||
</Pressable> |
|
||||
</View> |
|
||||
</SafeAreaView> |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
// 加载态
|
|
||||
if (loading || !user || !match) { |
|
||||
return ( |
|
||||
<SafeAreaView style={styles.safeArea} edges={['top']}> |
|
||||
<View style={styles.stateWrap}> |
|
||||
<ActivityIndicator size="large" color={colors.primary} /> |
|
||||
</View> |
|
||||
</SafeAreaView> |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<SafeAreaView style={styles.safeArea} edges={['top']}> |
|
||||
<ScrollView |
|
||||
style={styles.scroll} |
|
||||
contentContainerStyle={styles.content} |
|
||||
showsVerticalScrollIndicator={false} |
|
||||
> |
|
||||
{/* 1. 问候区域 + 通知入口 */} |
|
||||
<View style={styles.header}> |
|
||||
<View style={styles.headerLeft}> |
|
||||
<Text style={styles.greeting}>早上好,{user.name}</Text> |
|
||||
<Text style={styles.subtitle}>{user.slogan}</Text> |
|
||||
</View> |
|
||||
<Pressable |
|
||||
style={styles.notice} |
|
||||
onPress={() => { |
|
||||
/* TODO: 打开通知列表 */ |
|
||||
}} |
|
||||
> |
|
||||
<Ionicons name="notifications-outline" size={22} color={colors.textPrimary} /> |
|
||||
<View style={styles.noticeDot} /> |
|
||||
</Pressable> |
|
||||
</View> |
|
||||
|
|
||||
{/* 2. 搜索框(点击跳转搜索) */} |
|
||||
<Pressable |
|
||||
style={styles.searchBox} |
|
||||
onPress={() => { |
|
||||
/* TODO: 跳转搜索页 */ |
|
||||
}} |
|
||||
> |
|
||||
<Ionicons name="search" size={18} color={colors.textSecondary} /> |
|
||||
<Text style={styles.searchPlaceholder}>搜索岗位、公司、关键词</Text> |
|
||||
</Pressable> |
|
||||
|
|
||||
{/* 3. 分类导航(两行四列网格) */} |
|
||||
<View style={styles.grid}> |
|
||||
{categories.map((cat) => { |
|
||||
const theme = CATEGORY_THEME[cat.id] ?? CATEGORY_THEME.it; |
|
||||
return ( |
|
||||
<Pressable |
|
||||
key={cat.id} |
|
||||
style={styles.gridItem} |
|
||||
onPress={() => { |
|
||||
/* TODO: 跳转到对应分类岗位列表 */ |
|
||||
}} |
|
||||
> |
|
||||
<View style={[styles.gridIconBg, { backgroundColor: theme.bg }]}> |
|
||||
<Ionicons name={cat.icon as IconName} size={24} color={theme.icon} /> |
|
||||
</View> |
|
||||
<Text style={styles.gridLabel}>{cat.name}</Text> |
|
||||
</Pressable> |
|
||||
); |
|
||||
})} |
|
||||
</View> |
|
||||
|
|
||||
{/* 4. 匹配度卡片 */} |
|
||||
<View style={styles.matchCard}> |
|
||||
<View style={styles.matchRow}> |
|
||||
<Text style={styles.matchTitle}>您与{match.position}匹配度</Text> |
|
||||
<Text style={styles.matchRate}>{match.matchRate}%</Text> |
|
||||
</View> |
|
||||
<Pressable |
|
||||
onPress={() => { |
|
||||
/* TODO: 立即沟通 */ |
|
||||
}} |
|
||||
> |
|
||||
<Text style={styles.matchAction}>{match.subtitle}</Text> |
|
||||
</Pressable> |
|
||||
</View> |
|
||||
|
|
||||
{/* 5. 高分优质岗位(横向滑动) */} |
|
||||
<View style={styles.sectionHeader}> |
|
||||
<Text style={styles.sectionTitle}>高分优质岗位</Text> |
|
||||
</View> |
|
||||
<ScrollView |
|
||||
horizontal |
|
||||
showsHorizontalScrollIndicator={false} |
|
||||
style={styles.hScroll} |
|
||||
contentContainerStyle={styles.hScrollContent} |
|
||||
> |
|
||||
{hotJobs.map((job) => ( |
|
||||
<HotJobCard key={job.id} job={job} /> |
|
||||
))} |
|
||||
</ScrollView> |
|
||||
|
|
||||
{/* 6. 成长测评工具(两列并排) */} |
|
||||
<View style={styles.sectionHeader}> |
|
||||
<Text style={styles.sectionTitle}>成长测评工具</Text> |
|
||||
</View> |
|
||||
<View style={styles.toolsRow}> |
|
||||
{assessmentTools.map((tool) => ( |
|
||||
<ToolCard key={tool.id} tool={tool} variant="primary" /> |
|
||||
))} |
|
||||
</View> |
|
||||
|
|
||||
{/* 7. AI 智能工具(两列并排) */} |
|
||||
<View style={styles.sectionHeader}> |
|
||||
<Text style={styles.sectionTitle}>AI智能工具</Text> |
|
||||
</View> |
|
||||
<View style={styles.toolsRow}> |
|
||||
{aiTools.map((tool) => ( |
|
||||
<ToolCard key={tool.id} tool={tool} variant="info" /> |
|
||||
))} |
|
||||
</View> |
|
||||
</ScrollView> |
|
||||
</SafeAreaView> |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
// 跨平台阴影
|
|
||||
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', |
|
||||
}, |
|
||||
}); |
|
||||
@ -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 }; |
|
||||
} |
|
||||
@ -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<HomeData> => { |
|
||||
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, |
|
||||
}; |
|
||||
} |
|
||||
@ -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 }; |
|
||||
} |
|
||||
@ -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 }; |
|
||||
} |
|
||||
@ -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; |
|
||||
Loading…
Reference in new issue