import { Ionicons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import {
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useEnterpriseOverview } from '../../src/hooks';
import { LoadingState, ErrorState } from '../../src/components/StateView';
import { useRole } from '../../src/context/RoleContext';
import { colors, headerGradient, semanticColorTokens } from '../../src/theme';
import type { EnterpriseOverview, EnterpriseQuickAction, EnterpriseStat, JobEvaluationSummary, MenuItem } from '../../src/types';
/* ===================== 子组件:顶部导航 ===================== */
function Header({ onSettings }: { onSettings: () => void }) {
return (
我的
);
}
/* ===================== 子组件:企业信息卡 ===================== */
function CompanyCard({ overview }: { overview: EnterpriseOverview }) {
return (
{overview.logo}
{overview.name}
{overview.industry} · {overview.scale} · {overview.stage}
{overview.overallScore}
综合评分
{overview.reviewCount}
评价人数
{overview.stats[0]?.value ?? 0}
在招岗位
);
}
/* ===================== 子组件:统计四宫格 ===================== */
function StatGrid({ stats }: { stats: EnterpriseStat[] }) {
return (
{stats.map((stat) => {
const color = semanticColorTokens[stat.color] ?? colors.primary;
const up = stat.change >= 0;
return (
{stat.value.toLocaleString()}
{stat.label}
{up ? '↑' : '↓'} {Math.abs(stat.change)}
);
})}
);
}
/* ===================== 子组件:快捷入口 ===================== */
function QuickActions({ actions }: { actions: EnterpriseQuickAction[] }) {
const router = useRouter();
return (
快捷入口
{actions.map((action) => {
const color = semanticColorTokens[action.color] ?? colors.primary;
return (
action.route && router.push(action.route as string)}
>
{action.label}
);
})}
);
}
/* ===================== 子组件:岗位评价列表 ===================== */
function JobEvaluationList({ jobs }: { jobs: JobEvaluationSummary[] }) {
const router = useRouter();
return (
岗位评价管理
router.push('/job-evaluations')}>
查看全部
{jobs.map((job) => {
const up = job.change >= 0;
return (
{job.positionName}
{job.department}
{job.score.toFixed(1)}
{up ? '↑' : '↓'} {Math.abs(job.change).toFixed(1)}
);
})}
);
}
/* ===================== 子组件:管理后台 ===================== */
/**
* 管理后台入口:运营规则配置 / 数据审计等低频管理操作。
* 单独成区纵向排列,既不挤占快捷入口的横排位,也避免后台术语出现在求职者端。
*/
function ManageList({ actions }: { actions: EnterpriseQuickAction[] }) {
const router = useRouter();
if (actions.length === 0) return null;
return (
管理后台
{actions.map((action) => {
const color = semanticColorTokens[action.color] ?? colors.primary;
return (
action.route && router.push(action.route as string)}
>
{action.label}
);
})}
);
}
/* ===================== 子组件:企业功能菜单 ===================== */
/**
* 企业端功能菜单(更多服务):发布岗位 / 岗位管理 / 人才推荐等业务功能。
* 与求职者端菜单严格隔离,由 AppRole='enterprise' 下发,避免角色混淆。
*/
function MenuList({ items }: { items: MenuItem[] }) {
const router = useRouter();
if (items.length === 0) return null;
return (
更多服务
{items.map((item) => (
item.route && router.push(item.route as string)}
>
{item.title}
))}
);
}
/* ===================== 子组件:切换到求职端卡片 ===================== */
/**
* 企业端「我的」页回切求职端,与求职端「切换到企业端」卡片对称,
* 避免经「设置→身份切换」进入企业端后返回栈为空、回不去求职端。
*/
function CandidateEntryCard() {
const router = useRouter();
const { setRole } = useRole();
return (
{
setRole('candidate');
router.replace('/(tabs)/jobs');
}}
hitSlop={4}
>
切换到求职端
返回求职者端,浏览岗位与你的竞争力数据
去求职端 →
);
}
/* ===================== 页面主组件 ===================== */
export default function EnterpriseOverviewScreen() {
const router = useRouter();
const { overview, loading, error, refresh } = useEnterpriseOverview();
if (loading) {
return (
);
}
if (error || !overview) {
return (
);
}
return (
router.push('/settings')} />
);
}
/* ===================== 样式 ===================== */
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.pageBg,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.pageBg,
},
gradientHeader: {
paddingBottom: 16,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
},
headerBtn: {
width: 36,
height: 36,
justifyContent: 'center',
alignItems: 'center',
},
headerTitle: {
fontSize: 17,
fontWeight: '600',
color: colors.textInverse,
},
companyCard: {
marginHorizontal: 16,
marginTop: 8,
padding: 16,
backgroundColor: colors.white,
borderRadius: 8,
},
companyHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16,
},
logoBox: {
width: 52,
height: 52,
borderRadius: 12,
backgroundColor: colors.primaryLight,
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,
},
logoText: {
fontSize: 22,
fontWeight: '700',
color: colors.primary,
},
companyMeta: {
flex: 1,
},
companyName: {
fontSize: 18,
fontWeight: '700',
color: colors.textPrimary,
marginBottom: 4,
},
companyTags: {
fontSize: 13,
color: colors.textSecondary,
},
scoreRow: {
flexDirection: 'row',
alignItems: 'center',
paddingTop: 16,
borderTopWidth: 1,
borderTopColor: colors.borderLight,
},
scoreBox: {
flex: 1,
alignItems: 'center',
},
scoreValue: {
fontSize: 20,
fontWeight: '700',
color: colors.primary,
marginBottom: 2,
},
scoreLabel: {
fontSize: 12,
color: colors.textSecondary,
},
divider: {
width: 1,
height: 32,
backgroundColor: colors.borderLight,
},
scroll: {
flex: 1,
},
scrollContent: {
padding: 16,
paddingBottom: 32,
},
card: {
backgroundColor: colors.white,
borderRadius: 8,
padding: 16,
marginBottom: 16,
},
cardHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12,
},
cardTitle: {
fontSize: 16,
fontWeight: '700',
color: colors.textPrimary,
},
cardMore: {
fontSize: 13,
color: colors.primary,
},
statGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
marginHorizontal: -6,
},
statItem: {
width: '25%',
paddingHorizontal: 6,
alignItems: 'center',
},
statIcon: {
width: 44,
height: 44,
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center',
marginBottom: 8,
},
statValue: {
fontSize: 17,
fontWeight: '700',
color: colors.textPrimary,
marginBottom: 2,
},
statLabel: {
fontSize: 12,
color: colors.textSecondary,
marginBottom: 2,
},
statChange: {
fontSize: 11,
fontWeight: '500',
},
quickGrid: {
flexDirection: 'row',
marginHorizontal: -8,
},
quickItem: {
flex: 1,
alignItems: 'center',
paddingVertical: 8,
},
quickIcon: {
width: 48,
height: 48,
borderRadius: 14,
justifyContent: 'center',
alignItems: 'center',
marginBottom: 8,
},
quickLabel: {
fontSize: 13,
color: colors.textPrimary,
},
jobRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: colors.borderLight,
},
jobInfo: {
flex: 1,
},
jobName: {
fontSize: 15,
fontWeight: '600',
color: colors.textPrimary,
marginBottom: 2,
},
jobDepartment: {
fontSize: 12,
color: colors.textSecondary,
},
jobScoreBox: {
alignItems: 'flex-end',
},
jobScore: {
fontSize: 18,
fontWeight: '700',
color: colors.primary,
},
jobChange: {
fontSize: 11,
fontWeight: '500',
marginTop: 2,
},
standaloneTitle: {
fontSize: 16,
fontWeight: '700',
color: colors.textPrimary,
marginBottom: 8,
},
manageRow: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: colors.borderLight,
},
manageIcon: {
width: 38,
height: 38,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,
},
manageLabel: {
flex: 1,
fontSize: 15,
fontWeight: '500',
color: colors.textPrimary,
},
candidateCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.white,
borderRadius: 8,
padding: 16,
marginBottom: 16,
},
candidateIconWrap: {
width: 44,
height: 44,
borderRadius: 12,
backgroundColor: colors.primaryLight,
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,
},
candidateText: {
flex: 1,
},
candidateTitle: {
fontSize: 15,
fontWeight: '600',
color: colors.textPrimary,
marginBottom: 2,
},
candidateDesc: {
fontSize: 12,
color: colors.textSecondary,
},
candidateAction: {
fontSize: 13,
fontWeight: '600',
color: colors.primary,
marginLeft: 8,
},
});