新增面试邀约功能。
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
This commit is contained in:
179
src/pages/JobPortal/PersonalCenter/Interviews/index.tsx
Normal file
179
src/pages/JobPortal/PersonalCenter/Interviews/index.tsx
Normal file
@@ -0,0 +1,179 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Row,
|
||||
Col,
|
||||
Tag,
|
||||
Space,
|
||||
Typography,
|
||||
Button,
|
||||
Empty,
|
||||
message,
|
||||
Spin
|
||||
} from 'antd';
|
||||
import {
|
||||
EnvironmentOutlined,
|
||||
ArrowLeftOutlined,
|
||||
ClockCircleOutlined,
|
||||
VideoCameraOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { history } from '@umijs/max';
|
||||
import JobPortalHeader from '@/components/JobPortalHeader';
|
||||
import { getCmsInterviewList } from '@/services/Management/list';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
// 面试状态映射
|
||||
const statusMap: Record<string, { text: string; color: string }> = {
|
||||
pending: { text: '待确认', color: 'blue' },
|
||||
accepted: { text: '已接受', color: 'green' },
|
||||
rejected: { text: '已拒绝', color: 'red' },
|
||||
completed: { text: '已完成', color: 'purple' },
|
||||
};
|
||||
|
||||
// 从缓存获取用户信息
|
||||
const getUserIdFromCache = (): number | null => {
|
||||
try {
|
||||
const cached = localStorage.getItem('userInfo');
|
||||
if (cached) {
|
||||
const userInfo = JSON.parse(cached);
|
||||
return userInfo?.userId || null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('读取缓存用户信息失败:', error);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const InterviewsPage: React.FC = () => {
|
||||
const [interviews, setInterviews] = useState<API.Management.InterviewInvitation[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchInterviews();
|
||||
}, []);
|
||||
|
||||
const fetchInterviews = async () => {
|
||||
const userId = getUserIdFromCache();
|
||||
if (!userId) {
|
||||
message.warning('请先登录');
|
||||
history.push('/job-portal/personal-center');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await getCmsInterviewList({ userId });
|
||||
if (response.code === 200) {
|
||||
setInterviews(response.rows || []);
|
||||
} else {
|
||||
message.error(response.msg || '获取面试邀约列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取面试邀约列表失败:', error);
|
||||
message.error('获取面试邀约列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
history.push('/job-portal/personal-center');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="interviews-page">
|
||||
<JobPortalHeader showSearch={false} showHotJobs={false} />
|
||||
|
||||
<Spin spinning={loading}>
|
||||
<div className="page-content">
|
||||
<div className="back-button">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<ArrowLeftOutlined />}
|
||||
onClick={handleBack}
|
||||
>
|
||||
返回个人中心
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="page-header">
|
||||
<Title level={2}>我的面试邀约</Title>
|
||||
<Text type="secondary">共 {interviews.length} 条记录</Text>
|
||||
</div>
|
||||
|
||||
{interviews.length === 0 && !loading ? (
|
||||
<Empty
|
||||
description="暂无面试邀约"
|
||||
style={{ marginTop: '100px' }}
|
||||
/>
|
||||
) : (
|
||||
<div className="job-list">
|
||||
{interviews.map((item, index) => {
|
||||
const st = statusMap[item.status || 'pending'] || statusMap.pending;
|
||||
return (
|
||||
<Card
|
||||
key={item.id || index}
|
||||
className="job-card"
|
||||
hoverable
|
||||
>
|
||||
<Row gutter={16}>
|
||||
<Col span={18}>
|
||||
<div className="job-info">
|
||||
<Title level={4} style={{ marginBottom: 8 }}>
|
||||
<ClockCircleOutlined /> 面试时间:{item.interviewTime || '未指定'}
|
||||
</Title>
|
||||
<Space style={{ marginBottom: 8 }}>
|
||||
<Tag color={item.interviewMethod === 'online' ? 'blue' : 'orange'}>
|
||||
{item.interviewMethod === 'online' ? '线上' : '线下'}
|
||||
</Tag>
|
||||
<Tag color={st.color}>{st.text}</Tag>
|
||||
</Space>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
{item.interviewMethod === 'online' ? (
|
||||
<Space direction="vertical" size={4}>
|
||||
<Text>
|
||||
<VideoCameraOutlined /> 腾讯会议
|
||||
</Text>
|
||||
{item.meetingLink && (
|
||||
<Text type="secondary">
|
||||
链接:{item.meetingLink}
|
||||
</Text>
|
||||
)}
|
||||
{item.meetingPassword && (
|
||||
<Text type="secondary">
|
||||
密码:{item.meetingPassword}
|
||||
</Text>
|
||||
)}
|
||||
</Space>
|
||||
) : (
|
||||
<Text>
|
||||
<EnvironmentOutlined /> {item.interviewLocation || '未指定地点'}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
{item.contactPhone && (
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Text type="secondary">面试官联系方式:{item.contactPhone}</Text>
|
||||
</div>
|
||||
)}
|
||||
{item.remark && (
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Text type="secondary">备注:{item.remark}</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InterviewsPage;
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
SafetyCertificateOutlined,
|
||||
BellOutlined,
|
||||
FileTextOutlined,
|
||||
CameraOutlined
|
||||
CameraOutlined,
|
||||
CalendarOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { history } from '@umijs/max';
|
||||
import JobPortalHeader from '@/components/JobPortalHeader';
|
||||
@@ -179,6 +180,15 @@ const PersonalCenter: React.FC = () => {
|
||||
color: '#722ed1',
|
||||
link: '/job-portal/personal-center/showcase'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: '我的面试邀约',
|
||||
icon: <CalendarOutlined />,
|
||||
status: '',
|
||||
hasArrow: true,
|
||||
color: '#1677ff',
|
||||
link: '/job-portal/personal-center/interviews'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '在线面试',
|
||||
|
||||
Reference in New Issue
Block a user