feat: 改为卡片下方直接展开动画效果

- 移除弹窗式展示,改为在面试状态卡片下方直接展开
- 创建新的InterviewStatusAnimation组件,只展示动画
- 点击面试状态按钮后在卡片下方展开动画区域
- 移除标题和描述文字,界面更简洁
- 支持点击同一按钮收起动画

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KQL
2025-09-08 05:34:24 +08:00
parent 481999f963
commit 01492feb5a
4 changed files with 157 additions and 69 deletions

View File

@@ -0,0 +1,33 @@
.interview-status-animation-wrapper {
width: 100%;
padding: 10px 0;
background: linear-gradient(135deg, #f7faff 0%, #ffffff 100%);
border-top: 1px solid #e5e6eb;
animation: slideDown 0.3s ease-out;
overflow: hidden;
}
@keyframes slideDown {
from {
max-height: 0;
opacity: 0;
}
to {
max-height: 200px;
opacity: 1;
}
}
.animation-container {
width: 100%;
height: 180px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.animation-container svg {
max-width: 100%;
max-height: 100%;
}

View File

@@ -0,0 +1,68 @@
import React, { useState, useEffect, useRef } from 'react';
import lottie from 'lottie-web';
import './index.css';
// 状态动画映射
const statusAnimationMap = {
'HR初筛未通过': () => import('@/assets/animations/interviewStatus/1-off_初筛未通过.json'),
'HR评估中': () => import('@/assets/animations/interviewStatus/1-on_hr评估中.json'),
'面试未通过': () => import('@/assets/animations/interviewStatus/2-off_面试未通过.json'),
'到场面试': () => import('@/assets/animations/interviewStatus/2-on_到场面试.json'),
'收到通知': () => import('@/assets/animations/interviewStatus/2-on_收到通知.json'),
'等待面试': () => import('@/assets/animations/interviewStatus/2-wati_等待面试.json'),
'未参与面试': () => import('@/assets/animations/interviewStatus/3-off_未参与面试.json'),
'等待HR通知': () => import('@/assets/animations/interviewStatus/3-wati_等待HR通知.json'),
'拒绝Offer': () => import('@/assets/animations/interviewStatus/4-off_拒绝Offer.json'),
'收到Offer': () => import('@/assets/animations/interviewStatus/4-on_收到Offer.json'),
'等待回复': () => import('@/assets/animations/interviewStatus/4-wati_等待回复.json'),
};
export default ({ statusText, isOpen }) => {
const animationContainer = useRef(null);
const lottieInstance = useRef(null);
const [animationData, setAnimationData] = useState(null);
useEffect(() => {
if (isOpen && statusText) {
// 加载对应的动画数据
const loadAnimation = statusAnimationMap[statusText];
if (loadAnimation) {
loadAnimation().then(module => {
setAnimationData(module.default);
});
}
}
}, [isOpen, statusText]);
useEffect(() => {
if (animationData && animationContainer.current && isOpen) {
// 清除之前的动画实例
if (lottieInstance.current) {
lottieInstance.current.destroy();
}
// 创建新的动画实例
lottieInstance.current = lottie.loadAnimation({
container: animationContainer.current,
renderer: 'svg',
loop: true,
autoplay: true,
animationData: animationData
});
return () => {
if (lottieInstance.current) {
lottieInstance.current.destroy();
}
};
}
}, [animationData, isOpen]);
if (!isOpen) return null;
return (
<div className="interview-status-animation-wrapper">
<div className="animation-container" ref={animationContainer} />
</div>
);
};