111
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:
@@ -33,7 +33,7 @@ import {
|
||||
} from '@/services/jobportal/competitiveness';
|
||||
import { isJobPortalLoggedIn } from '@/utils/jobPortalAuth';
|
||||
import { favoriteJob, unfavoriteJob, applyJob } from '@/services/jobportal/user';
|
||||
import { ensureJobPortalLogin, PORTAL_LOGIN_URL } from '@/utils/jobPortalAuth';
|
||||
import { ensureJobPortalLogin, requireJobPortalUserId } from '@/utils/jobPortalAuth';
|
||||
import { getDictLabel, resolveIndustryLabel } from '@/utils/jobPortalDict';
|
||||
import { getDictValueEnum } from '@/services/system/dict';
|
||||
import { getCmsIndustryTreeList } from '@/services/classify/industry';
|
||||
@@ -60,20 +60,6 @@ const experienceMap: { [key: string]: string } = {
|
||||
'0': '不限'
|
||||
};
|
||||
|
||||
// 从缓存获取用户信息
|
||||
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 formatSalary = (minSalary: number, maxSalary: number) => {
|
||||
if (minSalary && maxSalary) {
|
||||
@@ -228,8 +214,13 @@ const JobDetailPage: React.FC = () => {
|
||||
const scaleLabel = getDictLabel(scaleEnum, rawScale) || String(rawScale);
|
||||
if (scaleLabel) items.push(scaleLabel);
|
||||
}
|
||||
|
||||
const industryLabel = resolveIndustryLabel(industryTree, rawIndustry);
|
||||
if (industryLabel) items.push(industryLabel);
|
||||
const rawStr = rawIndustry == null ? '' : String(rawIndustry).trim();
|
||||
// 行业 id 未解析成名称时不展示裸数字,避免与行业名称重复
|
||||
if (industryLabel && !(/^\d+$/.test(rawStr) && industryLabel === rawStr)) {
|
||||
items.push(industryLabel);
|
||||
}
|
||||
|
||||
return items;
|
||||
}, [originalJobData, scaleEnum, industryTree]);
|
||||
@@ -257,13 +248,22 @@ const JobDetailPage: React.FC = () => {
|
||||
|
||||
}, [id, location.state]);
|
||||
|
||||
// 基于详情中的 id 再拉一次(避免从路由未传 id 的情况)
|
||||
// 仅登录且有真实岗位 id 时请求竞争力
|
||||
useEffect(() => {
|
||||
const jobIdNum = Number((jobDetail as any)?.id);
|
||||
if (!Number.isNaN(jobIdNum) && jobIdNum) {
|
||||
if (!isJobPortalLoggedIn()) {
|
||||
setOverallScore(0);
|
||||
setRadarData(getEmptyCompetitivenessRadar());
|
||||
return;
|
||||
}
|
||||
const jobIdRaw =
|
||||
originalJobData?.jobId
|
||||
?? originalJobData?.id
|
||||
?? id;
|
||||
const jobIdNum = Number(jobIdRaw);
|
||||
if (!Number.isNaN(jobIdNum) && jobIdNum > 0) {
|
||||
fetchCompetitiveness(jobIdNum);
|
||||
}
|
||||
}, [jobDetail?.id]);
|
||||
}, [originalJobData?.jobId, originalJobData?.id, id]);
|
||||
|
||||
const fetchCompetitiveness = async (jobIdNum: number) => {
|
||||
if (!isJobPortalLoggedIn()) {
|
||||
@@ -306,18 +306,13 @@ const JobDetailPage: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleCollect = async () => {
|
||||
if (!ensureJobPortalLogin('收藏职位')) {
|
||||
const userId = await requireJobPortalUserId('收藏职位');
|
||||
if (!userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是取消收藏,调用取消收藏接口
|
||||
if (isFavorited) {
|
||||
const userId = getUserIdFromCache();
|
||||
if (!userId) {
|
||||
message.warning('无法获取用户信息,请重新登录');
|
||||
window.location.href = PORTAL_LOGIN_URL;
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取职位ID(从原始数据或转换后的数据中获取)
|
||||
const jobId = originalJobData?.jobId || originalJobData?.id || (jobDetail as any)?.id || id;
|
||||
@@ -345,13 +340,6 @@ const JobDetailPage: React.FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const userId = getUserIdFromCache();
|
||||
if (!userId) {
|
||||
message.warning('无法获取用户信息,请重新登录');
|
||||
window.location.href = PORTAL_LOGIN_URL;
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取职位ID
|
||||
const jobId = originalJobData?.jobId || originalJobData?.id || (jobDetail as any)?.id || id;
|
||||
if (!jobId) {
|
||||
@@ -378,14 +366,8 @@ const JobDetailPage: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleApply = async () => {
|
||||
if (!ensureJobPortalLogin('申请职位')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userId = getUserIdFromCache();
|
||||
const userId = await requireJobPortalUserId('申请职位');
|
||||
if (!userId) {
|
||||
message.warning('无法获取用户信息,请重新登录');
|
||||
window.location.href = PORTAL_LOGIN_URL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -494,23 +476,41 @@ const JobDetailPage: React.FC = () => {
|
||||
</Card>
|
||||
|
||||
{/* 公司信息 */}
|
||||
<Card title="公司信息" className="info-card">
|
||||
<Card title="公司信息" className="info-card company-info-card">
|
||||
<div className="company-intro">
|
||||
<Space size={16}>
|
||||
<Avatar size={64} src={jobDetail.companyLogo} />
|
||||
<div>
|
||||
<Title level={4} style={{ margin: 0 }}>
|
||||
<div className="company-overview">
|
||||
<Avatar size={56} className="company-avatar" src={jobDetail.companyLogo}>
|
||||
企
|
||||
</Avatar>
|
||||
<div className="company-main">
|
||||
<Title level={5} className="company-name">
|
||||
{jobDetail.companyInfo.name}
|
||||
</Title>
|
||||
<Space className="company-meta" split={<Divider type="vertical" />}>
|
||||
{companyMetaItems.map((label) => (
|
||||
<Text key={label}>{label}</Text>
|
||||
))}
|
||||
</Space>
|
||||
{companyMetaItems.length > 0 && (
|
||||
<div className="company-meta-row">
|
||||
{companyMetaItems.map((label, index) => (
|
||||
<React.Fragment key={`${label}-${index}`}>
|
||||
{index > 0 && <span className="meta-separator">|</span>}
|
||||
<span>{label}</span>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{(originalJobData?.jobLocation || jobDetail.location) && (
|
||||
<div className="company-location">
|
||||
<EnvironmentOutlined />
|
||||
<span>{originalJobData?.jobLocation || jobDetail.location}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Space>
|
||||
<Divider />
|
||||
<Paragraph>{jobDetail.companyInfo.description}</Paragraph>
|
||||
</div>
|
||||
<Divider className="company-section-divider" />
|
||||
<div className="company-description-section">
|
||||
<div className="company-section-label">公司介绍</div>
|
||||
<Paragraph className="company-description">
|
||||
{jobDetail.companyInfo.description}
|
||||
</Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
@@ -527,53 +527,69 @@ const JobDetailPage: React.FC = () => {
|
||||
}
|
||||
className="competitiveness-card"
|
||||
>
|
||||
<div className="radar-chart-container">
|
||||
<Radar
|
||||
data={radarData}
|
||||
xField="item"
|
||||
yField="score"
|
||||
area={{
|
||||
style: {
|
||||
fill: 'rgba(24, 144, 255, 0.25)',
|
||||
fillOpacity: 0.5,
|
||||
},
|
||||
}}
|
||||
point={{
|
||||
size: 3,
|
||||
style: {
|
||||
fill: '#1890ff',
|
||||
stroke: '#1890ff',
|
||||
},
|
||||
}}
|
||||
line={{
|
||||
style: {
|
||||
stroke: '#1890ff',
|
||||
lineWidth: 2,
|
||||
},
|
||||
}}
|
||||
meta={{
|
||||
score: {
|
||||
alias: '评分',
|
||||
min: 0,
|
||||
max: 100,
|
||||
nice: true,
|
||||
},
|
||||
}}
|
||||
yAxis={{
|
||||
label: false,
|
||||
tickLine: null,
|
||||
line: null,
|
||||
grid: null,
|
||||
}}
|
||||
height={300}
|
||||
/>
|
||||
<div className="radar-summary">
|
||||
<div className="summary-score">
|
||||
<div className="score-value">{overallScore}</div>
|
||||
<div className="score-label">综合评分</div>
|
||||
{isJobPortalLoggedIn() ? (
|
||||
<div className="radar-chart-container">
|
||||
<Radar
|
||||
data={radarData}
|
||||
xField="item"
|
||||
yField="score"
|
||||
area={{
|
||||
style: {
|
||||
fill: 'rgba(24, 144, 255, 0.25)',
|
||||
fillOpacity: 0.5,
|
||||
},
|
||||
}}
|
||||
point={{
|
||||
size: 3,
|
||||
style: {
|
||||
fill: '#1890ff',
|
||||
stroke: '#1890ff',
|
||||
},
|
||||
}}
|
||||
line={{
|
||||
style: {
|
||||
stroke: '#1890ff',
|
||||
lineWidth: 2,
|
||||
},
|
||||
}}
|
||||
meta={{
|
||||
score: {
|
||||
alias: '评分',
|
||||
min: 0,
|
||||
max: 100,
|
||||
nice: true,
|
||||
},
|
||||
}}
|
||||
yAxis={{
|
||||
label: false,
|
||||
tickLine: null,
|
||||
line: null,
|
||||
grid: null,
|
||||
}}
|
||||
height={300}
|
||||
/>
|
||||
<div className="radar-summary">
|
||||
<div className="summary-score">
|
||||
<div className="score-value">{overallScore}</div>
|
||||
<div className="score-label">综合评分</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="competitiveness-login-placeholder">
|
||||
<TrophyOutlined className="placeholder-icon" />
|
||||
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
|
||||
登录后可查看您与该岗位的匹配度分析
|
||||
</Paragraph>
|
||||
<Text className="placeholder-hint">基于您的简历信息进行多维度对比</Text>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => ensureJobPortalLogin('查看竞争力分析')}
|
||||
>
|
||||
去登录
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
</Col>
|
||||
|
||||
Reference in New Issue
Block a user