feat: 添加HR访问量弹窗和日历事项样式优化
- 新增HR访问详情弹窗组件,支持左右切换查看不同HR信息 - 优化日历事项样式系统,基于事件类型匹配样式配置 - 完善侧边栏HR访问量组件,添加重叠头像和点击交互 - 增加班级排名弹窗组件 - 更新专家支持页面布局和样式 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,12 @@
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { useState } from "react";
|
||||
import { Avatar, Spin, Empty } from "@arco-design/web-react";
|
||||
import IconFont from "@/components/IconFont";
|
||||
import ClassRankModal from "@/components/ClassRankModal";
|
||||
import "./index.css";
|
||||
|
||||
const positions = ["item2", "item1", "item3"];
|
||||
const icons = ["icon2", "icon1", "icon3"];
|
||||
|
||||
const Rank = ({ className, data, loading }) => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const rankings = data?.rankings?.slice(0, 6) || [];
|
||||
|
||||
// 安全处理领奖台学生,确保至少有3个位置
|
||||
@@ -17,8 +20,17 @@ const Rank = ({ className, data, loading }) => {
|
||||
|
||||
const listStudents = rankings.slice(3);
|
||||
|
||||
const handleClick = () => {
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`module-class-rank ${className}`}>
|
||||
<>
|
||||
<div
|
||||
className={`module-class-rank ${className}`}
|
||||
onClick={handleClick}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<p className="module-class-rank-title">
|
||||
<IconFont className="title-icon" src="recuUY5nNf7DWT" />
|
||||
<span>班级排名</span>
|
||||
@@ -74,7 +86,14 @@ const Rank = ({ className, data, loading }) => {
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 班级排名弹窗 */}
|
||||
<ClassRankModal
|
||||
visible={modalVisible}
|
||||
onClose={() => setModalVisible(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
273
src/components/ClassRankModal/index.css
Normal file
273
src/components/ClassRankModal/index.css
Normal file
@@ -0,0 +1,273 @@
|
||||
/* 班级排名弹窗样式 */
|
||||
.class-rank-modal {
|
||||
width: 600px;
|
||||
max-height: 80vh;
|
||||
background-color: #fff7f1;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.class-rank-modal-header {
|
||||
padding: 20px 30px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, #fff7f1 0%, #ffe8d6 100%);
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
width: 180px;
|
||||
height: 110px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background-image: url("@/assets/images/Rank/bg.png");
|
||||
background-size: 100% 100%;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.class-rank-modal-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #262626;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("@/assets/images/icon/close.png");
|
||||
background-size: 100% 100%;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.class-rank-modal-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 复用班级排名板块的领奖台样式 */
|
||||
.class-rank-modal-content .module-class-rank-podium {
|
||||
width: 333px;
|
||||
height: 138px;
|
||||
margin: 20px auto 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
|
||||
> li {
|
||||
width: 88px;
|
||||
border-radius: 8px;
|
||||
position: relative;
|
||||
background-image: linear-gradient(
|
||||
to bottom,
|
||||
rgba(255, 255, 255, 1),
|
||||
rgba(255, 255, 255, 0)
|
||||
);
|
||||
|
||||
.module-class-rank-podium-avatar {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -24px;
|
||||
transform: translateX(-50%);
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 1px solid;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: -10px;
|
||||
width: 57px;
|
||||
height: 16px;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.module-class-rank-podium-name {
|
||||
color: #1d2129;
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 30px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
> i {
|
||||
height: 27px;
|
||||
background-size: 100% 100%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.module-class-rank-podium-item1 {
|
||||
height: 98px;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: -40px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("@/assets/images/Rank/first_icon.png");
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.module-class-rank-podium-avatar {
|
||||
border-color: #ffc15b;
|
||||
|
||||
&::before {
|
||||
background-image: url("@/assets/images/Rank/icon1.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.module-class-rank-podium-item2 {
|
||||
height: 80px;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: -40px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("@/assets/images/Rank/second_icon.png");
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.module-class-rank-podium-avatar {
|
||||
border-color: #9ab9e3;
|
||||
&::before {
|
||||
background-image: url("@/assets/images/Rank/icon2.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.module-class-rank-podium-item3 {
|
||||
height: 70px;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: -40px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("@/assets/images/Rank/third_icon.png");
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.module-class-rank-podium-avatar {
|
||||
border-color: #d7a770;
|
||||
&::before {
|
||||
background-image: url("@/assets/images/Rank/icon3.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 其余排名列表 */
|
||||
.class-rank-modal-list {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.class-rank-modal-list-item {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
> em {
|
||||
margin-left: 5px;
|
||||
color: #86909c;
|
||||
font-size: 22px;
|
||||
font-family: "HarmonyOS_Sans_TC_Bold";
|
||||
font-style: normal;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
> p {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
color: #1d2129;
|
||||
margin-left: 20px;
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
> span {
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #86909c;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
src/components/ClassRankModal/index.jsx
Normal file
108
src/components/ClassRankModal/index.jsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Avatar } from "@arco-design/web-react";
|
||||
import Modal from "@/components/Modal";
|
||||
import classRankData from "../../../网页未导入数据/文旅产业/班级排名.json";
|
||||
import "./index.css";
|
||||
|
||||
const positions = ["item2", "item1", "item3"];
|
||||
const icons = ["icon2", "icon1", "icon3"];
|
||||
|
||||
const ClassRankModal = ({ visible, onClose }) => {
|
||||
const [rankings, setRankings] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// 处理班级排名数据,确保按排名排序
|
||||
const sortedData = [...classRankData].sort(
|
||||
(a, b) => parseInt(a.班级排名) - parseInt(b.班级排名)
|
||||
);
|
||||
setRankings(sortedData);
|
||||
}, []);
|
||||
|
||||
// 获取前三名的数据,按照领奖台顺序排列
|
||||
const podiumStudents = [
|
||||
rankings[1] || null, // 第2名
|
||||
rankings[0] || null, // 第1名
|
||||
rankings[2] || null, // 第3名
|
||||
];
|
||||
// 获取第4名及以后的数据
|
||||
const restRankings = rankings.slice(3);
|
||||
|
||||
return (
|
||||
<Modal visible={visible} onClose={onClose}>
|
||||
<div className="class-rank-modal">
|
||||
<div className="class-rank-modal-header">
|
||||
<h2 className="class-rank-modal-title">
|
||||
<span>班级排名</span>
|
||||
</h2>
|
||||
<i className="close-icon" onClick={onClose} />
|
||||
</div>
|
||||
|
||||
<div className="class-rank-modal-content">
|
||||
{/* 前三名展示区 - 复用ClassRank组件的样式 */}
|
||||
<ul className="module-class-rank-podium">
|
||||
{podiumStudents.map((student, index) => {
|
||||
// 使用具体的头像URL
|
||||
let avatarUrl = null;
|
||||
if (student) {
|
||||
const name = student.学员名称.trim();
|
||||
switch(name) {
|
||||
case "万圆":
|
||||
avatarUrl = "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/avatar/douyin/02393125baa474d558c484c0677664b1.jpg";
|
||||
break;
|
||||
case "李阳":
|
||||
avatarUrl = "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/avatar/douyin/07a0a14c8c8d5476b2c8d54de12e6a06.jpg";
|
||||
break;
|
||||
case "何晓彤":
|
||||
avatarUrl = "https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/avatar/douyin/13823046201f0ef17517fb46da12bc35.jpg";
|
||||
break;
|
||||
default:
|
||||
avatarUrl = "https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp";
|
||||
}
|
||||
}
|
||||
|
||||
return student ? (
|
||||
<li
|
||||
key={student.班级排名}
|
||||
className={`module-class-rank-podium-${positions[index]}`}
|
||||
>
|
||||
<Avatar className="module-class-rank-podium-avatar">
|
||||
<img alt="avatar" src={avatarUrl} />
|
||||
</Avatar>
|
||||
<span className="module-class-rank-podium-name">
|
||||
{student.学员名称.trim()}
|
||||
</span>
|
||||
<i className={`module-class-rank-podium-${icons[index]}`}></i>
|
||||
</li>
|
||||
) : (
|
||||
<li
|
||||
key={`empty-${index}`}
|
||||
className={`module-class-rank-podium-${positions[index]} empty`}
|
||||
>
|
||||
<div className="module-class-rank-podium-placeholder">
|
||||
<span>-</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{/* 其余排名列表 */}
|
||||
<div className="class-rank-modal-list">
|
||||
{restRankings.map((item) => (
|
||||
<div
|
||||
key={item.班级排名}
|
||||
className="class-rank-modal-list-item"
|
||||
>
|
||||
<em>{item.班级排名}</em>
|
||||
<p>{item.学员名称.trim()}</p>
|
||||
<span>{item.学分}学分</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClassRankModal;
|
||||
202
src/components/HRVisitModal/index.css
Normal file
202
src/components/HRVisitModal/index.css
Normal file
@@ -0,0 +1,202 @@
|
||||
.hr-visit-modal .arco-modal {
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hr-visit-modal .arco-modal-content {
|
||||
padding: 0;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hr-visit-modal-content {
|
||||
padding: 40px 30px 30px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #a8e6cf 0%, #88c999 50%, #67b26f 100%);
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-close-btn {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
transition: background 0.3s ease;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.modal-close-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.hr-avatars-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.avatar-navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 16px;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
.nav-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.avatars-container {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-item {
|
||||
position: absolute;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.avatar-item.hidden {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.hr-avatar-large {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
border: 4px solid rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
|
||||
.avatar-item.active .hr-avatar-large {
|
||||
border-color: white;
|
||||
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.company-info {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 12px 0;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.hr-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 20px;
|
||||
padding: 6px 16px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.hr-label {
|
||||
background: #007AFF;
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.hr-name {
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.visit-info {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.visit-message {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.indicators {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.indicator.active {
|
||||
background: white;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.indicator:hover {
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* 动画效果 */
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px) scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.hr-visit-modal .arco-modal-content {
|
||||
animation: modalSlideIn 0.4s ease-out;
|
||||
}
|
||||
134
src/components/HRVisitModal/index.jsx
Normal file
134
src/components/HRVisitModal/index.jsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Modal } from '@arco-design/web-react';
|
||||
import { IconLeft, IconRight, IconClose } from '@arco-design/web-react/icon';
|
||||
import './index.css';
|
||||
|
||||
const HRVisitModal = ({ visible, onClose }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// 模拟HR数据
|
||||
const hrData = [
|
||||
{
|
||||
id: 1,
|
||||
name: '王先生',
|
||||
company: '武汉联影科技有限公司',
|
||||
avatar: '//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
|
||||
visitMessage: '访问了您的个人档案'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '李女士',
|
||||
company: '腾讯科技有限公司',
|
||||
avatar: '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/581b17753093199839f2e327e726b157.svg~tplv-49unhts6dw-image.image',
|
||||
visitMessage: '访问了您的项目经验'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '张先生',
|
||||
company: '阿里巴巴集团',
|
||||
avatar: '//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/e278888093bef8910e829486fb45dd69.png~tplv-uwbnlip3yd-webp.webp',
|
||||
visitMessage: '访问了您的技能证书'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '陈女士',
|
||||
company: '字节跳动科技有限公司',
|
||||
avatar: '//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
|
||||
visitMessage: '访问了您的求职意向'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '刘先生',
|
||||
company: '华为技术有限公司',
|
||||
avatar: '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/581b17753093199839f2e327e726b157.svg~tplv-49unhts6dw-image.image',
|
||||
visitMessage: '访问了您的工作经历'
|
||||
}
|
||||
];
|
||||
|
||||
const handlePrev = () => {
|
||||
setCurrentIndex(prev => prev === 0 ? hrData.length - 1 : prev - 1);
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
setCurrentIndex(prev => prev === hrData.length - 1 ? 0 : prev + 1);
|
||||
};
|
||||
|
||||
const currentHR = hrData[currentIndex];
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={onClose}
|
||||
footer={null}
|
||||
closable={false}
|
||||
className="hr-visit-modal"
|
||||
width={500}
|
||||
>
|
||||
<div className="hr-visit-modal-content">
|
||||
{/* 关闭按钮 */}
|
||||
<div className="modal-close-btn" onClick={onClose}>
|
||||
<IconClose />
|
||||
</div>
|
||||
|
||||
{/* 头像区域 */}
|
||||
<div className="hr-avatars-section">
|
||||
<div className="avatar-navigation">
|
||||
<button className="nav-btn" onClick={handlePrev}>
|
||||
<IconLeft />
|
||||
</button>
|
||||
|
||||
<div className="avatars-container">
|
||||
{hrData.map((hr, index) => (
|
||||
<div
|
||||
key={hr.id}
|
||||
className={`avatar-item ${index === currentIndex ? 'active' : ''} ${
|
||||
Math.abs(index - currentIndex) > 2 ? 'hidden' : ''
|
||||
}`}
|
||||
style={{
|
||||
transform: `translateX(${(index - currentIndex) * 80}px)`,
|
||||
opacity: index === currentIndex ? 1 : 0.6,
|
||||
zIndex: index === currentIndex ? 10 : 5,
|
||||
scale: index === currentIndex ? 1.2 : 1
|
||||
}}
|
||||
>
|
||||
<img src={hr.avatar} alt={hr.name} className="hr-avatar-large" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button className="nav-btn" onClick={handleNext}>
|
||||
<IconRight />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 公司信息 */}
|
||||
<div className="company-info">
|
||||
<h3 className="company-name">{currentHR.company}</h3>
|
||||
<div className="hr-tag">
|
||||
<span className="hr-label">HR</span>
|
||||
<span className="hr-name">{currentHR.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 访问信息 */}
|
||||
<div className="visit-info">
|
||||
<p className="visit-message">{currentHR.visitMessage}</p>
|
||||
</div>
|
||||
|
||||
{/* 指示器 */}
|
||||
<div className="indicators">
|
||||
{hrData.map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`indicator ${index === currentIndex ? 'active' : ''}`}
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default HRVisitModal;
|
||||
@@ -86,13 +86,22 @@
|
||||
}
|
||||
.visitor-count {
|
||||
width: 208px;
|
||||
height: 44px;
|
||||
height: 64px;
|
||||
border-radius: 8px;
|
||||
background-color: #e5f1ff;
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
@@ -103,12 +112,63 @@
|
||||
height: 100%;
|
||||
background-image: url("@/assets/images/Sidebar/visitor_count_bg.png");
|
||||
background-size: 100% 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.arco-statistic-value {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 41px;
|
||||
.hr-visitor-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.hr-visitor-text {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.hr-avatars-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.hr-avatars {
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.hr-avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #fff;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
&.hr-avatar-1 {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
&.hr-avatar-2 {
|
||||
z-index: 2;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
&.hr-avatar-3 {
|
||||
z-index: 1;
|
||||
margin-left: -8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hr-count-text {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #4e5969;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sidebar-menu {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { Statistic } from "@arco-design/web-react";
|
||||
import { useSelector } from "react-redux";
|
||||
import IconFont from "@/components/IconFont";
|
||||
import HRVisitModal from "@/components/HRVisitModal";
|
||||
import ICON from "@/assets/images/Sidebar/sidebar_icon.png";
|
||||
import ICONRETRACT from "@/assets/images/Sidebar/logo.png";
|
||||
import BTNICON from "@/assets/images/Sidebar/btn_icon.png";
|
||||
@@ -12,6 +13,7 @@ const Sidebar = ({ isCollapsed, setIsCollapsed }) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const studentInfo = useSelector((state) => state.student.studentInfo);
|
||||
const [hrModalVisible, setHrModalVisible] = useState(false);
|
||||
const handleNavClick = (path) => {
|
||||
navigate(path);
|
||||
};
|
||||
@@ -21,6 +23,16 @@ const Sidebar = ({ isCollapsed, setIsCollapsed }) => {
|
||||
setIsCollapsed((prev) => !prev);
|
||||
};
|
||||
|
||||
// 打开HR访问详情弹窗
|
||||
const handleHRClick = () => {
|
||||
setHrModalVisible(true);
|
||||
};
|
||||
|
||||
// 关闭HR访问详情弹窗
|
||||
const handleCloseHRModal = () => {
|
||||
setHrModalVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
@@ -45,12 +57,31 @@ const Sidebar = ({ isCollapsed, setIsCollapsed }) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Statistic
|
||||
className="visitor-count"
|
||||
groupSeparator
|
||||
value={87}
|
||||
prefix="HR访问量:"
|
||||
/>
|
||||
<div className="visitor-count" onClick={handleHRClick}>
|
||||
<div className="hr-visitor-content">
|
||||
<span className="hr-visitor-text">HR访问量</span>
|
||||
<div className="hr-avatars-wrapper">
|
||||
<div className="hr-avatars">
|
||||
<img
|
||||
src="//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp"
|
||||
alt="HR头像"
|
||||
className="hr-avatar hr-avatar-1"
|
||||
/>
|
||||
<img
|
||||
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/581b17753093199839f2e327e726b157.svg~tplv-49unhts6dw-image.image"
|
||||
alt="HR头像"
|
||||
className="hr-avatar hr-avatar-2"
|
||||
/>
|
||||
<img
|
||||
src="//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/e278888093bef8910e829486fb45dd69.png~tplv-uwbnlip3yd-webp.webp"
|
||||
alt="HR头像"
|
||||
className="hr-avatar hr-avatar-3"
|
||||
/>
|
||||
</div>
|
||||
<span className="hr-count-text">等87位HR</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="sidebar-menu">
|
||||
{routes
|
||||
.filter((item) => item.showMenu)
|
||||
@@ -90,6 +121,12 @@ const Sidebar = ({ isCollapsed, setIsCollapsed }) => {
|
||||
<div className="sidebar-btn" onClick={toggleSidebar}>
|
||||
<img src={BTNICON} alt="btn" className="sidebar-btn-icon" />
|
||||
</div>
|
||||
|
||||
{/* HR访问详情弹窗 */}
|
||||
<HRVisitModal
|
||||
visible={hrModalVisible}
|
||||
onClose={handleCloseHRModal}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user