feat: 优化岗位弹窗展示和添加投递权限限制
- 岗位描述和要求使用数字序号排序,左对齐展示 - 优化三个内容板块的间距和样式 - 添加岗位相关标签显示(专业相关/非专业相关/人才出海) - 创建投递权限提示弹窗,非学员无法投递 - 更新岗位面试状态数据,修复重复的会展策划师记录 - 支持弹窗内容滚动,自适应高度 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
[
|
||||
{
|
||||
"查询岗位名称": "会展策划师",
|
||||
"阶段日期": "2025/9/16",
|
||||
"面试状态": "收到Offer"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "商业会展执行专员",
|
||||
"阶段日期": "2025/7/30",
|
||||
@@ -39,39 +34,24 @@
|
||||
"阶段日期": "2025/7/23",
|
||||
"面试状态": "收到Offer"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "品牌推广专员",
|
||||
"阶段日期": "2025/8/2",
|
||||
"面试状态": "面试未通过"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "会展策划师",
|
||||
"阶段日期": "2025/9/16",
|
||||
"面试状态": "收到Offer"
|
||||
"面试状态": "等待HR通知"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "客服",
|
||||
"阶段日期": "2025/8/2",
|
||||
"面试状态": "拒绝Offer"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "境外展会操作助理",
|
||||
"阶段日期": "2025/8/9",
|
||||
"面试状态": "面试未通过"
|
||||
"面试状态": "未参与面试"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "海外活动策划专员",
|
||||
"阶段日期": "2025/7/17",
|
||||
"面试状态": "收到Offer"
|
||||
"阶段日期": "2025/9/2",
|
||||
"面试状态": "等待回复"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "品牌公关",
|
||||
"阶段日期": "2025/9/7",
|
||||
"面试状态": "等待面试"
|
||||
},
|
||||
{
|
||||
"查询岗位名称": "景区运营专员",
|
||||
"阶段日期": "2025/8/12",
|
||||
"面试状态": "面试未通过"
|
||||
"面试状态": "等待回复"
|
||||
}
|
||||
]
|
||||
@@ -110,7 +110,8 @@ const transformCompanyJobs = (jobsData) => {
|
||||
education: job["学历要求"],
|
||||
positions: job["招聘人数"],
|
||||
description: job["职位描述"],
|
||||
requirements: job["任职要求"] ? job["任职要求"].split(/[;;。\n]/).filter(r => r.trim()) : [],
|
||||
requirements: job["任职要求"] ? job["任职要求"].split(/\d+\.\s*/).filter(r => r.trim()) : [],
|
||||
requirementsText: job["任职要求"],
|
||||
benefits: job["福利标签"] || [],
|
||||
companyInfo: job["公司介绍"]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.job-info-modal-content {
|
||||
max-height: 720px;
|
||||
max-height: 80vh;
|
||||
width: 844px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -13,8 +13,28 @@
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 20px;
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #667eea;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: #764ba2;
|
||||
}
|
||||
}
|
||||
|
||||
.job-info-modal-search {
|
||||
width: 319px;
|
||||
@@ -35,13 +55,13 @@
|
||||
}
|
||||
.job-info-modal-user-resumes-list {
|
||||
width: 100%;
|
||||
min-height: 555px;
|
||||
min-height: 400px;
|
||||
margin-top: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr); /* 每行两列 */
|
||||
gap: 20px; /* 网格间距 */
|
||||
justify-items: start; /* 项目左对齐 */
|
||||
overflow-y: auto;
|
||||
justify-items: start; /* 项目左对龁 */
|
||||
overflow-y: visible;
|
||||
|
||||
.list-item {
|
||||
width: 390px;
|
||||
@@ -130,18 +150,32 @@
|
||||
|
||||
.job-info-modal-content-position-info {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
|
||||
.job-info-modal-content-position-info-position {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 30px;
|
||||
color: #1d2129;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.job-category-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 12px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border-radius: 12px;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.job-info-modal-content-position-info-num {
|
||||
@@ -187,10 +221,25 @@
|
||||
.job-info-modal-content-position-info-companyInfo {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
margin: 10px 0;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f7f8fa 100%);
|
||||
margin: 8px 0;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid rgba(102, 126, 234, 0.1);
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
min-height: auto;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
> p {
|
||||
width: 100%;
|
||||
@@ -199,28 +248,134 @@
|
||||
.description-title,
|
||||
.requirements-title,
|
||||
.companyInfo-title {
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 30px;
|
||||
color: #000;
|
||||
margin-bottom: 10px;
|
||||
line-height: 24px;
|
||||
color: #1d2129;
|
||||
margin-bottom: 16px;
|
||||
padding-left: 12px;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 16px;
|
||||
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.description-content,
|
||||
.description-content {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #4e5969;
|
||||
text-align: left;
|
||||
|
||||
.description-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
text-align: left;
|
||||
|
||||
.description-number {
|
||||
display: inline-block;
|
||||
min-width: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #667eea;
|
||||
margin-right: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #4e5969;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.companyInfo-content {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
color: #4e5969;
|
||||
|
||||
.company-paragraph {
|
||||
margin-bottom: 12px;
|
||||
text-indent: 2em;
|
||||
text-align: justify;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.requirements-content {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
.requirements-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
|
||||
.requirement-number {
|
||||
display: inline-block;
|
||||
min-width: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #667eea;
|
||||
margin-right: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.requirement-text {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #4e5969;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.requirement-line {
|
||||
margin-bottom: 8px;
|
||||
padding-left: 16px;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #4e5969;
|
||||
text-align: left;
|
||||
|
||||
&:before {
|
||||
content: "•";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #667eea;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import InfiniteScroll from "@/components/InfiniteScroll";
|
||||
import toast from "@/components/Toast";
|
||||
import FILEICON from "@/assets/images/CompanyJobsPage/file_icon.png";
|
||||
import ResumeInfoModal from "../ResumeInfoModal";
|
||||
import PermissionModal from "../PermissionModal";
|
||||
import { getResumesList, submitResume, getPageData } from "@/services";
|
||||
import "./index.css";
|
||||
|
||||
@@ -20,6 +21,7 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
const [resumeList, setResumeList] = useState([]); // 简历列表
|
||||
const [listPage, setListPage] = useState(1);
|
||||
const [listHasMore, setListHasMore] = useState(true);
|
||||
const [permissionModalVisible, setPermissionModalVisible] = useState(false);
|
||||
|
||||
// 处理directToResume参数变化
|
||||
useEffect(() => {
|
||||
@@ -67,6 +69,11 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
|
||||
// 选择简历投递
|
||||
const userResumesClick = async (item) => {
|
||||
// 显示权限提示弹窗
|
||||
setPermissionModalVisible(true);
|
||||
|
||||
// 原投递逻辑暂时注释,实际使用时可根据用户权限判断
|
||||
/*
|
||||
try {
|
||||
// 调用投递服务
|
||||
const result = await submitResume({
|
||||
@@ -102,6 +109,7 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
toast.error('投递失败,请重试');
|
||||
console.error('投递失败:', error);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
// 点击简历详情
|
||||
@@ -205,6 +213,12 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
<span className="job-info-modal-content-position-info-position">
|
||||
{data?.position}
|
||||
</span>
|
||||
{/* 岗位相关标签 */}
|
||||
{(data?.jobCategoryTag || data?.jobCategory) && (
|
||||
<span className="job-category-tag">
|
||||
{data?.jobCategoryTag || data?.jobCategory}
|
||||
</span>
|
||||
)}
|
||||
<span className="job-info-modal-content-position-info-num">
|
||||
该岗位仅剩{data?.remainingPositions}人
|
||||
</span>
|
||||
@@ -224,39 +238,47 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
{data?.details?.description && (
|
||||
<div className="job-info-modal-content-position-info-description">
|
||||
<p className="description-title">岗位描述</p>
|
||||
<p className="description-content">{data?.details?.description}</p>
|
||||
<div className="description-content">
|
||||
{data?.details?.description.split(/\d+\.\s*/).filter(item => item.trim()).map((item, index) => (
|
||||
<div key={index} className="description-item">
|
||||
<span className="description-number">{index + 1}.</span>
|
||||
<span className="description-text">{item.trim()}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{data?.details?.requirements?.length > 0 && (
|
||||
{(data?.details?.requirements?.length > 0 || data?.details?.requirementsText) && (
|
||||
<div className="job-info-modal-content-position-info-requirements">
|
||||
<p className="requirements-title">岗位要求</p>
|
||||
<ul className="requirements-content">
|
||||
{data?.details?.requirements?.map((item, index) => (
|
||||
<li key={index} className="requirements-item">
|
||||
{index + 1}. {item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="requirements-content">
|
||||
{data?.details?.requirements ? (
|
||||
data?.details?.requirements?.map((item, index) => (
|
||||
<div key={index} className="requirements-item">
|
||||
<span className="requirement-number">{index + 1}.</span>
|
||||
<span className="requirement-text">{item}</span>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
data?.details?.requirementsText?.split('\n').map((line, index) => (
|
||||
<p key={index} className="requirement-line">
|
||||
{line}
|
||||
</p>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* {data?.details?.requirements?.length > 0 && (
|
||||
<div className="job-info-modal-content-position-info-requirements">
|
||||
<p className="requirements-title">岗位要求</p>
|
||||
<ul className="requirements-content">
|
||||
{data?.details?.requirements?.map((item, index) => (
|
||||
<li key={index} className="requirements-item">
|
||||
{index + 1}.{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)} */}
|
||||
{data?.details?.companyInfo && (
|
||||
<div className="job-info-modal-content-position-info-companyInfo">
|
||||
<p className="companyInfo-title">公司介绍</p>
|
||||
<p className="companyInfo-content">
|
||||
{data?.details?.companyInfo}
|
||||
</p>
|
||||
<div className="companyInfo-content">
|
||||
{data?.details?.companyInfo.split('\n').map((paragraph, index) => (
|
||||
<p key={index} className="company-paragraph">
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
@@ -278,6 +300,10 @@ export default ({ visible, onClose, data, directToResume = false }) => {
|
||||
setResumeInfoData(null);
|
||||
}}
|
||||
/>
|
||||
<PermissionModal
|
||||
visible={permissionModalVisible}
|
||||
onClose={() => setPermissionModalVisible(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
.permission-modal-content {
|
||||
width: 360px;
|
||||
padding: 32px 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f7f8fa 100%);
|
||||
border-radius: 12px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
/* 装饰性背景 */
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle, rgba(102, 126, 234, 0.05) 0%, transparent 70%);
|
||||
animation: rotate 20s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.permission-modal-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin: 0 0 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.permission-modal-message {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #4e5969;
|
||||
margin: 0 0 28px;
|
||||
text-align: center;
|
||||
line-height: 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.permission-modal-btn {
|
||||
width: 120px;
|
||||
height: 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import Modal from "@/components/Modal";
|
||||
import './index.css';
|
||||
|
||||
export default ({ visible, onClose }) => {
|
||||
return (
|
||||
<Modal visible={visible} onClose={onClose}>
|
||||
<div className="permission-modal-content">
|
||||
<h2 className="permission-modal-title">权限提示</h2>
|
||||
|
||||
<p className="permission-modal-message">
|
||||
非学员本人无岗位投递权限
|
||||
</p>
|
||||
|
||||
|
||||
<button className="permission-modal-btn" onClick={onClose}>
|
||||
我知道了
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user