配置后端对接
This commit is contained in:
@@ -1,17 +1,67 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { mockData } from "@/data/mockData";
|
||||
import { jobAPI } from "@/services/api";
|
||||
import { mapJobList } from "@/utils/dataMapper";
|
||||
import JobList from "@/pages/CompanyJobsPage/components/JobList";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
const CompanyJobsListPage = () => {
|
||||
const { companyJobs } = mockData;
|
||||
const [jobs, setJobs] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
fetchJobs();
|
||||
}, [page]);
|
||||
|
||||
const fetchJobs = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await jobAPI.getList({
|
||||
page,
|
||||
pageSize: 20,
|
||||
isActive: true
|
||||
});
|
||||
|
||||
const mappedJobs = mapJobList(response.data || response);
|
||||
setJobs(mappedJobs);
|
||||
setTotal(response.total || mappedJobs.length);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch jobs:", error);
|
||||
setJobs([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading && jobs.length === 0) {
|
||||
return (
|
||||
<div className="company-jobs-list-page-wrapper" style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
minHeight: '400px'
|
||||
}}>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="company-jobs-list-page-wrapper">
|
||||
<JobList data={companyJobs?.companyPositions} />
|
||||
<JobList data={jobs} />
|
||||
{jobs.length === 0 && !loading && (
|
||||
<div style={{
|
||||
textAlign: 'center',
|
||||
padding: '40px',
|
||||
color: '#999'
|
||||
}}>
|
||||
暂无岗位信息
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,20 +1,85 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { mockData } from "@/data/mockData";
|
||||
import { jobAPI, interviewAPI, studentAPI } from "@/services/api";
|
||||
import { mapJobList, mapInterviewList } from "@/utils/dataMapper";
|
||||
import JobList from "./components/JobList";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
const CompanyJobsPage = () => {
|
||||
const { companyJobs } = mockData;
|
||||
const [jobs, setJobs] = useState([]);
|
||||
const [interviews, setInterviews] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isExpand, setIsExpand] = useState(false); // 是否展开
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
// Get current user's student ID from API
|
||||
let studentId = null;
|
||||
try {
|
||||
const currentStudent = await studentAPI.getCurrentStudent();
|
||||
studentId = currentStudent?.id;
|
||||
} catch (err) {
|
||||
console.log('Could not get current student:', err);
|
||||
}
|
||||
|
||||
// Fetch jobs (and interviews if we have a student ID)
|
||||
const jobsData = await jobAPI.getList({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
isActive: true
|
||||
});
|
||||
|
||||
let interviewsData = { data: [] };
|
||||
if (studentId) {
|
||||
try {
|
||||
interviewsData = await interviewAPI.getList({
|
||||
studentId: studentId,
|
||||
status: 'SCHEDULED'
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('No interviews found or API error');
|
||||
}
|
||||
}
|
||||
|
||||
// Map data to frontend format
|
||||
const mappedJobs = mapJobList(jobsData.data || jobsData);
|
||||
const mappedInterviews = mapInterviewList(interviewsData.data || interviewsData);
|
||||
|
||||
setJobs(mappedJobs);
|
||||
setInterviews(mappedInterviews);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch data:", error);
|
||||
// Fallback to empty data
|
||||
setJobs([]);
|
||||
setInterviews([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleJobWrapperClick = () => {
|
||||
navigate("/company-jobs-list");
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="company-jobs-page-wrapper">
|
||||
<div className="company-jobs-page" style={{ justifyContent: 'center', alignItems: 'center' }}>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="company-jobs-page-wrapper">
|
||||
<div className="company-jobs-page">
|
||||
@@ -22,7 +87,7 @@ const CompanyJobsPage = () => {
|
||||
<p className="company-jobs-page-title">企业内推岗位库</p>
|
||||
<div className="company-jobs-page-left-list-wrapper">
|
||||
<JobList
|
||||
data={companyJobs?.companyPositions}
|
||||
data={jobs}
|
||||
backgroundColor="#F7F8FA"
|
||||
/>
|
||||
</div>
|
||||
@@ -37,15 +102,15 @@ const CompanyJobsPage = () => {
|
||||
>
|
||||
<p className="company-jobs-page-title">内推岗位面试</p>
|
||||
<ul className="company-jobs-page-interview-list">
|
||||
{companyJobs?.internalPositions?.map((item) => (
|
||||
{interviews.length > 0 ? interviews.map((item) => (
|
||||
<li className="company-jobs-page-interview-item" key={item.id}>
|
||||
<div className="company-jobs-page-interview-item-info">
|
||||
<p className="company-jobs-page-interview-item-info-position">
|
||||
{item.position}
|
||||
</p>
|
||||
{item?.tags?.length > 0 ? (
|
||||
{item.job?.tags?.length > 0 ? (
|
||||
<ul className="company-jobs-page-interview-item-info-tags">
|
||||
{item?.tags.map((tag) => (
|
||||
{item.job.tags.map((tag) => (
|
||||
<li
|
||||
className="company-jobs-page-interview-item-info-tag"
|
||||
key={tag}
|
||||
@@ -56,14 +121,14 @@ const CompanyJobsPage = () => {
|
||||
</ul>
|
||||
) : null}
|
||||
<span className="company-jobs-page-interview-item-info-salary">
|
||||
{item.salary}
|
||||
{item.job?.salary || '面议'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="company-jobs-page-interview-item-btn-wrapper">
|
||||
<span>{item.interviewTime}</span>
|
||||
<div
|
||||
className={`company-jobs-page-interview-item-btn ${
|
||||
item.status !== "completed" &&
|
||||
item.status !== "COMPLETED" &&
|
||||
"company-jobs-page-interview-item-btn-active"
|
||||
}`}
|
||||
>
|
||||
@@ -71,7 +136,13 @@ const CompanyJobsPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
)) : (
|
||||
<li className="company-jobs-page-interview-item">
|
||||
<p style={{ color: '#999', textAlign: 'center', width: '100%' }}>
|
||||
暂无面试安排
|
||||
</p>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,60 @@
|
||||
import { Avatar } from "@arco-design/web-react";
|
||||
import { mockData } from "@/data/mockData";
|
||||
import { useState, useEffect } from "react";
|
||||
import { studentAPI } from "@/services/api";
|
||||
import { mapProfile } from "@/utils/dataMapper";
|
||||
import "./index.css";
|
||||
|
||||
const ProfileCard = () => {
|
||||
const { profile } = mockData;
|
||||
const [profile, setProfile] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchProfile();
|
||||
}, []);
|
||||
|
||||
const fetchProfile = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
// Get current logged-in student information
|
||||
const studentData = await studentAPI.getCurrentStudent();
|
||||
|
||||
if (studentData) {
|
||||
const mappedProfile = mapProfile(studentData);
|
||||
setProfile(mappedProfile);
|
||||
} else {
|
||||
throw new Error("Failed to get current student data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch profile:", error);
|
||||
// Show error message instead of fake data
|
||||
setProfile({
|
||||
name: "数据加载失败",
|
||||
studentId: "请检查后端服务",
|
||||
school: error.message || "后端未运行",
|
||||
major: "请确保数据库已初始化",
|
||||
badges: {
|
||||
credits: 0,
|
||||
classRank: 0,
|
||||
mbti: "-"
|
||||
},
|
||||
courses: []
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="profile-card-wrapper" style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="profile-card-wrapper">
|
||||
@@ -15,9 +66,9 @@ const ProfileCard = () => {
|
||||
/>
|
||||
</Avatar>
|
||||
<div className="profile-card-user-name">
|
||||
<span className="profile-card-user-name-text">{profile.name}</span>
|
||||
<span className="profile-card-user-name-text">{profile?.name}</span>
|
||||
<p className="profile-card-user-name-student-id">
|
||||
学号: {profile.studentId}
|
||||
学号: {profile?.studentId}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,7 +76,7 @@ const ProfileCard = () => {
|
||||
<li className="profile-card-achievement-info-item">
|
||||
<span className="profile-card-achievement-info-item-title">学分</span>
|
||||
<span className="profile-card-achievement-info-item-text">
|
||||
{profile?.badges?.credits}
|
||||
{profile?.badges?.credits || 0}
|
||||
</span>
|
||||
</li>
|
||||
<li className="profile-card-achievement-info-item">
|
||||
@@ -33,13 +84,13 @@ const ProfileCard = () => {
|
||||
班级排名
|
||||
</span>
|
||||
<span className="profile-card-achievement-info-item-text">
|
||||
{profile?.badges?.classRank}
|
||||
{profile?.badges?.classRank || '-'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="profile-card-achievement-info-item">
|
||||
<span className="profile-card-achievement-info-item-title">MBTI</span>
|
||||
<span className="profile-card-achievement-info-item-text">
|
||||
{profile?.badges?.mbti}
|
||||
{profile?.badges?.mbti || '-'}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -48,30 +99,30 @@ const ProfileCard = () => {
|
||||
<i className="profile-card-class-info-item-icon icon-school" />
|
||||
<span className="profile-card-class-info-item-title">学校</span>
|
||||
<span className="profile-card-class-info-item-text">
|
||||
{profile?.school}
|
||||
{profile?.school || '-'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="profile-card-class-info-item">
|
||||
<i className="profile-card-class-info-item-icon icon-major" />
|
||||
<span className="profile-card-class-info-item-title">专业</span>
|
||||
<span className="profile-card-class-info-item-text">
|
||||
{profile?.major}
|
||||
{profile?.major || '-'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="profile-card-class-info-item">
|
||||
<i className="profile-card-class-info-item-icon icon-location" />
|
||||
<span className="profile-card-class-info-item-title">
|
||||
就业管家课程
|
||||
班级
|
||||
</span>
|
||||
<span className="profile-card-class-info-item-text">
|
||||
{profile?.course}
|
||||
{profile?.className || '-'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="profile-card-class-info-item">
|
||||
<i className="profile-card-class-info-item-icon icon-course" />
|
||||
<span className="profile-card-class-info-item-title">垂直方向</span>
|
||||
<span className="profile-card-class-info-item-title">学习阶段</span>
|
||||
<span className="profile-card-class-info-item-text">
|
||||
{profile?.course}
|
||||
{profile?.stageName || '-'}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user