feat: 优化班级排名展示并集成Lottie动画
- 限制班级排名详情页只展示前10名学员 - 替换面试状态数据为文旅产业15个岗位数据 - 将面试状态展开动画从静态图片改为Lottie动画 - 添加5个面试状态的Lottie动画文件 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1
public/lottie/interview-status/1-off_初筛未通过.json
Normal file
1
public/lottie/interview-status/1-off_初筛未通过.json
Normal file
File diff suppressed because one or more lines are too long
1
public/lottie/interview-status/2-off_面试未通过.json
Normal file
1
public/lottie/interview-status/2-off_面试未通过.json
Normal file
File diff suppressed because one or more lines are too long
1
public/lottie/interview-status/3-off_未参与面试.json
Normal file
1
public/lottie/interview-status/3-off_未参与面试.json
Normal file
File diff suppressed because one or more lines are too long
1
public/lottie/interview-status/4-off_拒绝Offer.json
Normal file
1
public/lottie/interview-status/4-off_拒绝Offer.json
Normal file
File diff suppressed because one or more lines are too long
1
public/lottie/interview-status/4-on_收到Offer.json
Normal file
1
public/lottie/interview-status/4-on_收到Offer.json
Normal file
File diff suppressed because one or more lines are too long
@@ -24,15 +24,15 @@ const ClassRankModal = ({ visible, onClose }) => {
|
|||||||
rankings[0] || null, // 第1名
|
rankings[0] || null, // 第1名
|
||||||
rankings[2] || null, // 第3名
|
rankings[2] || null, // 第3名
|
||||||
];
|
];
|
||||||
// 获取第4名及以后的数据
|
// 获取第4-10名的数据(只展示前10名)
|
||||||
const restRankings = rankings.slice(3);
|
const restRankings = rankings.slice(3, 10);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal visible={visible} onClose={onClose}>
|
<Modal visible={visible} onClose={onClose}>
|
||||||
<div className="class-rank-modal">
|
<div className="class-rank-modal">
|
||||||
<div className="class-rank-modal-header">
|
<div className="class-rank-modal-header">
|
||||||
<h2 className="class-rank-modal-title">
|
<h2 className="class-rank-modal-title">
|
||||||
<span>班级排名</span>
|
<span>班级排名(前10名)</span>
|
||||||
</h2>
|
</h2>
|
||||||
<i className="close-icon" onClick={onClose} />
|
<i className="close-icon" onClick={onClose} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,57 +1,77 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"查询岗位名称": "HR人事专员",
|
||||||
|
"阶段日期": "面试未通过:2025/8/22 14:12",
|
||||||
|
"面试状态": "面试未通过,岗位内推结束"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "商业会展执行专员",
|
"查询岗位名称": "商业会展执行专员",
|
||||||
"阶段日期": "2025/7/30",
|
"阶段日期": "Offer已拒绝:2025/7/30 09:45",
|
||||||
"面试状态": "拒绝Offer"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "活动策划师",
|
"查询岗位名称": "活动策划师",
|
||||||
"阶段日期": "2025/7/26",
|
"阶段日期": "Offer已拒绝:2025/7/16 14:33",
|
||||||
"面试状态": "收到Offer"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "SEO专员",
|
"查询岗位名称": "SEO专员",
|
||||||
"阶段日期": "2025/7/28",
|
"阶段日期": "Offer已拒绝:2025/7/28 17:01",
|
||||||
"面试状态": "拒绝Offer"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "新媒体运营专员",
|
"查询岗位名称": "新媒体运营专员",
|
||||||
"阶段日期": "2025/7/31",
|
"阶段日期": "Offer已拒绝:2025/7/31 14:38",
|
||||||
"面试状态": "拒绝Offer"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "ip运营",
|
"查询岗位名称": "ip运营",
|
||||||
"阶段日期": "2025/7/10",
|
"阶段日期": "Offer已拒绝:2025/7/10 11:13",
|
||||||
"面试状态": "收到Offer"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "二次元周边店店长",
|
"查询岗位名称": "二次元周边店店长",
|
||||||
"阶段日期": "2025/6/27",
|
"阶段日期": "简历未通过:2025/6/27 15:45",
|
||||||
"面试状态": "HR初筛未通过"
|
"面试状态": "简历未通过,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "社群运营",
|
"查询岗位名称": "社群运营",
|
||||||
"阶段日期": "2025/7/23",
|
"阶段日期": "简历未通过:2025/7/23 11:10",
|
||||||
"面试状态": "收到Offer"
|
"面试状态": "简历未通过,岗位内推结束"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"查询岗位名称": "品牌推广专员",
|
||||||
|
"阶段日期": "面试未通过:2025/8/2 13:32",
|
||||||
|
"面试状态": "面试未通过,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "会展策划师",
|
"查询岗位名称": "会展策划师",
|
||||||
"阶段日期": "回复截至2025-09-12",
|
"阶段日期": "Offer已接收:2025/9/11 16:39",
|
||||||
"面试状态": "等待HR通知"
|
"面试状态": "Offer已接收,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "客服",
|
"查询岗位名称": "客服",
|
||||||
"阶段日期": "2025/8/2",
|
"阶段日期": "Offer已拒绝:2025/8/2 09:31",
|
||||||
"面试状态": "未参与面试"
|
"面试状态": "Offer已拒绝,岗位内推结束"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"查询岗位名称": "境外展会操作助理",
|
||||||
|
"阶段日期": "面试未通过:2025/8/9 12:01",
|
||||||
|
"面试状态": "面试未通过,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "海外活动策划专员",
|
"查询岗位名称": "海外活动策划专员",
|
||||||
"阶段日期": "2025/9/2",
|
"阶段日期": "面试未通过:2025/7/17 20:18",
|
||||||
"面试状态": "等待回复"
|
"面试状态": "面试未通过,岗位内推结束"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"查询岗位名称": "品牌公关",
|
"查询岗位名称": "品牌公关",
|
||||||
"阶段日期": "面试完成2025-09-02",
|
"阶段日期": "面试日期:2025/9/7 18:35",
|
||||||
"面试状态": "面试完成"
|
"面试状态": "面试日期已确定,等待面试"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"查询岗位名称": "景区运营专员",
|
||||||
|
"阶段日期": "面试未通过:2025/8/12 14:53",
|
||||||
|
"面试状态": "面试未通过,岗位内推结束"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -40,7 +40,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.animation-container {
|
.lottie-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 136px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: scale(0.9);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interview-status-animation-wrapper.expanding .lottie-container {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 保留原有的图片样式作为后备方案 */
|
||||||
|
.image-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 180px;
|
height: 180px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -51,11 +67,14 @@
|
|||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.interview-status-animation-wrapper.expanding .animation-container {
|
.interview-status-animation-wrapper.expanding .image-container {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.animation-container svg {
|
.status-image {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
@@ -2,27 +2,25 @@ import React, { useState, useEffect, useRef } from 'react';
|
|||||||
import lottie from 'lottie-web';
|
import lottie from 'lottie-web';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
// 状态动画映射
|
// 状态到lottie动画文件的映射
|
||||||
const statusAnimationMap = {
|
const statusLottieMap = {
|
||||||
'HR初筛未通过': () => import('@/assets/animations/interviewStatus/1-off_初筛未通过.json'),
|
'Offer已拒绝,岗位内推结束': '/lottie/interview-status/4-off_拒绝Offer.json',
|
||||||
'HR评估中': () => import('@/assets/animations/interviewStatus/1-on_hr评估中.json'),
|
'Offer已接收,岗位内推结束': '/lottie/interview-status/4-on_收到Offer.json',
|
||||||
'面试未通过': () => import('@/assets/animations/interviewStatus/2-off_面试未通过.json'),
|
'Offer已接受,岗位内推结束': '/lottie/interview-status/4-on_收到Offer.json',
|
||||||
'到场面试': () => import('@/assets/animations/interviewStatus/2-on_到场面试.json'),
|
'已收到Offer,请于2天内答复': '/lottie/interview-status/4-on_收到Offer.json',
|
||||||
'收到通知': () => import('@/assets/animations/interviewStatus/2-on_收到通知.json'),
|
'面试日期已确定,等待面试': '/lottie/interview-status/4-on_收到Offer.json',
|
||||||
'等待面试': () => import('@/assets/animations/interviewStatus/2-wati_等待面试.json'),
|
'简历未通过,岗位内推结束': '/lottie/interview-status/1-off_初筛未通过.json',
|
||||||
'未参与面试': () => import('@/assets/animations/interviewStatus/3-off_未参与面试.json'),
|
'未参与面试,岗位内推结束': '/lottie/interview-status/3-off_未参与面试.json',
|
||||||
'等待HR通知': () => import('@/assets/animations/interviewStatus/3-wati_等待HR通知.json'),
|
'面试未通过,岗位内推结束': '/lottie/interview-status/2-off_面试未通过.json',
|
||||||
'拒绝Offer': () => import('@/assets/animations/interviewStatus/4-off_拒绝Offer.json'),
|
// 兼容其他可能的状态文本
|
||||||
'收到Offer': () => import('@/assets/animations/interviewStatus/4-on_收到Offer.json'),
|
'岗位内推结束': '/lottie/interview-status/1-off_初筛未通过.json', // 默认动画
|
||||||
'等待回复': () => import('@/assets/animations/interviewStatus/4-wati_等待回复.json'),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ({ statusText, isOpen }) => {
|
export default ({ statusText, isOpen, stageDate }) => {
|
||||||
const animationContainer = useRef(null);
|
|
||||||
const lottieInstance = useRef(null);
|
|
||||||
const [animationData, setAnimationData] = useState(null);
|
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
const [animationClass, setAnimationClass] = useState('');
|
const [animationClass, setAnimationClass] = useState('');
|
||||||
|
const lottieContainer = useRef(null);
|
||||||
|
const lottieInstance = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -38,47 +36,87 @@ export default ({ statusText, isOpen }) => {
|
|||||||
}
|
}
|
||||||
}, [isOpen, isVisible]);
|
}, [isOpen, isVisible]);
|
||||||
|
|
||||||
useEffect(() => {
|
// 获取对应的lottie动画路径
|
||||||
if (isOpen && statusText) {
|
const getLottiePath = (status, stageDate) => {
|
||||||
// 加载对应的动画数据
|
// 首先尝试精确匹配
|
||||||
const loadAnimation = statusAnimationMap[statusText];
|
if (statusLottieMap[status]) {
|
||||||
if (loadAnimation) {
|
return statusLottieMap[status];
|
||||||
loadAnimation().then(module => {
|
|
||||||
setAnimationData(module.default);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, [isOpen, statusText]);
|
|
||||||
|
|
||||||
|
// 如果精确匹配失败,尝试模糊匹配
|
||||||
|
if (status && status.includes('简历未通过')) {
|
||||||
|
return statusLottieMap['简历未通过,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (status && status.includes('未参与面试')) {
|
||||||
|
return statusLottieMap['未参与面试,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (status && status.includes('面试未通过')) {
|
||||||
|
return statusLottieMap['面试未通过,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (status && status.includes('Offer已拒绝')) {
|
||||||
|
return statusLottieMap['Offer已拒绝,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (status && (status.includes('Offer已接受') || status.includes('Offer已接收'))) {
|
||||||
|
return statusLottieMap['Offer已接收,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (status && status.includes('面试日期已确定')) {
|
||||||
|
return statusLottieMap['面试日期已确定,等待面试'];
|
||||||
|
}
|
||||||
|
if (status && status.includes('已收到Offer')) {
|
||||||
|
return statusLottieMap['已收到Offer,请于2天内答复'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于通用的"岗位内推结束"状态,根据阶段日期判断具体原因
|
||||||
|
if (status === '岗位内推结束' && stageDate) {
|
||||||
|
if (stageDate.includes('简历未通过')) {
|
||||||
|
return statusLottieMap['简历未通过,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (stageDate.includes('未参与面试')) {
|
||||||
|
return statusLottieMap['未参与面试,岗位内推结束'];
|
||||||
|
}
|
||||||
|
if (stageDate.includes('面试未通过')) {
|
||||||
|
return statusLottieMap['面试未通过,岗位内推结束'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回通用动画
|
||||||
|
return statusLottieMap['岗位内推结束'];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载lottie动画
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (animationData && animationContainer.current && isVisible) {
|
if (isVisible && lottieContainer.current) {
|
||||||
// 清除之前的动画实例
|
// 清理之前的动画实例
|
||||||
if (lottieInstance.current) {
|
if (lottieInstance.current) {
|
||||||
lottieInstance.current.destroy();
|
lottieInstance.current.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新的动画实例
|
const lottiePath = getLottiePath(statusText, stageDate);
|
||||||
|
|
||||||
|
// 加载新的lottie动画
|
||||||
lottieInstance.current = lottie.loadAnimation({
|
lottieInstance.current = lottie.loadAnimation({
|
||||||
container: animationContainer.current,
|
container: lottieContainer.current,
|
||||||
renderer: 'svg',
|
renderer: 'svg',
|
||||||
loop: true,
|
loop: true,
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
animationData: animationData
|
path: lottiePath
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理函数
|
||||||
return () => {
|
return () => {
|
||||||
if (lottieInstance.current) {
|
if (lottieInstance.current) {
|
||||||
lottieInstance.current.destroy();
|
lottieInstance.current.destroy();
|
||||||
|
lottieInstance.current = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}, [isVisible, statusText, stageDate]);
|
||||||
}, [animationData, isVisible]);
|
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`interview-status-animation-wrapper ${animationClass}`}>
|
<div className={`interview-status-animation-wrapper ${animationClass}`}>
|
||||||
<div className="animation-container" ref={animationContainer} />
|
<div className="lottie-container" ref={lottieContainer} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
1613
网页未导入数据/岗位面试状态(全产业).json
Normal file
1613
网页未导入数据/岗位面试状态(全产业).json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user