|
@@ -0,0 +1,2070 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>智能简历筛选系统</title>
|
|
|
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
|
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
|
+ <style>
|
|
|
+ :root {
|
|
|
+ --primary: #4361ee;
|
|
|
+ --primary-dark: #3a0ca3;
|
|
|
+ --secondary: #4cc9f0;
|
|
|
+ --success: #2ecc71;
|
|
|
+ --warning: #f39c12;
|
|
|
+ --danger: #e74c3c;
|
|
|
+ --light: #f8f9fa;
|
|
|
+ --dark: #212529;
|
|
|
+ --gray: #6c757d;
|
|
|
+ --light-gray: #e9ecef;
|
|
|
+ --border: #dee2e6;
|
|
|
+ --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ --transition: all 0.3s ease;
|
|
|
+ --radius: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ * {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ body {
|
|
|
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
|
|
|
+ color: var(--dark);
|
|
|
+ line-height: 1.6;
|
|
|
+ min-height: 100vh;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ max-width: 1400px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 顶部导航栏 */
|
|
|
+ header {
|
|
|
+ background: white;
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ border-radius: var(--radius);
|
|
|
+ margin-bottom: 25px;
|
|
|
+ position: sticky;
|
|
|
+ top: 10px;
|
|
|
+ z-index: 100;
|
|
|
+ }
|
|
|
+
|
|
|
+ .navbar {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 15px 30px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .logo {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 15px;
|
|
|
+ font-size: 1.8rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: var(--primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .logo i {
|
|
|
+ color: var(--primary-dark);
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-links {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-link {
|
|
|
+ padding: 10px 20px;
|
|
|
+ border-radius: 30px;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: var(--transition);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-link:hover {
|
|
|
+ background: var(--light);
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-link.active {
|
|
|
+ background: var(--primary);
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .system-info {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .resume-count {
|
|
|
+ background: var(--light);
|
|
|
+ padding: 8px 15px;
|
|
|
+ border-radius: 30px;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ background: var(--primary);
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ padding: 10px 20px;
|
|
|
+ border-radius: 30px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-weight: 600;
|
|
|
+ transition: var(--transition);
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn:hover {
|
|
|
+ background: var(--primary-dark);
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 4px 8px rgba(67, 97, 238, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-success {
|
|
|
+ background: var(--success);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-success:hover {
|
|
|
+ background: #27ae60;
|
|
|
+ box-shadow: 0 4px 8px rgba(46, 204, 113, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-warning {
|
|
|
+ background: var(--warning);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-warning:hover {
|
|
|
+ background: #e67e22;
|
|
|
+ box-shadow: 0 4px 8px rgba(243, 156, 18, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-light {
|
|
|
+ background: var(--light);
|
|
|
+ color: var(--dark);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-light:hover {
|
|
|
+ background: #e2e6ea;
|
|
|
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 页面容器 */
|
|
|
+ .page-container {
|
|
|
+ display: none;
|
|
|
+ animation: fadeIn 0.5s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ .page-container.active {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes fadeIn {
|
|
|
+ from { opacity: 0; transform: translateY(10px); }
|
|
|
+ to { opacity: 1; transform: translateY(0); }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 面板样式 */
|
|
|
+ .panel {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ padding: 25px;
|
|
|
+ margin-bottom: 25px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .panel-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding-bottom: 15px;
|
|
|
+ border-bottom: 1px solid var(--light-gray);
|
|
|
+ }
|
|
|
+
|
|
|
+ .panel-title {
|
|
|
+ font-size: 1.5rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: var(--primary-dark);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 简历列表页 */
|
|
|
+ .filters-bar {
|
|
|
+ display: flex;
|
|
|
+ gap: 15px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding: 15px;
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-group {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-width: 200px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-label {
|
|
|
+ font-weight: 600;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ color: var(--gray);
|
|
|
+ font-size: 0.9rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-control {
|
|
|
+ padding: 10px 15px;
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-card {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ transition: var(--transition);
|
|
|
+ border: 1px solid var(--border);
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-card:hover {
|
|
|
+ transform: translateY(-5px);
|
|
|
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-header {
|
|
|
+ background: linear-gradient(135deg, var(--primary), var(--primary-dark));
|
|
|
+ color: white;
|
|
|
+ padding: 20px;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-status {
|
|
|
+ position: absolute;
|
|
|
+ top: 15px;
|
|
|
+ right: 15px;
|
|
|
+ background: rgba(255, 255, 255, 0.2);
|
|
|
+ padding: 5px 15px;
|
|
|
+ border-radius: 20px;
|
|
|
+ font-size: 0.85rem;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-passed {
|
|
|
+ background: rgba(46, 204, 113, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-pending {
|
|
|
+ background: rgba(243, 156, 18, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-avatar {
|
|
|
+ width: 80px;
|
|
|
+ height: 80px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: white;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 2rem;
|
|
|
+ color: var(--primary);
|
|
|
+ margin-bottom: 15px;
|
|
|
+ border: 3px solid rgba(255, 255, 255, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-name {
|
|
|
+ font-size: 1.5rem;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-title {
|
|
|
+ opacity: 0.9;
|
|
|
+ font-size: 1rem;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-score {
|
|
|
+ display: inline-block;
|
|
|
+ background: rgba(255, 255, 255, 0.2);
|
|
|
+ padding: 5px 15px;
|
|
|
+ border-radius: 20px;
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-body {
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-info {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info-item {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info-label {
|
|
|
+ width: 100px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--gray);
|
|
|
+ }
|
|
|
+
|
|
|
+ .skills {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill {
|
|
|
+ background: var(--light);
|
|
|
+ padding: 5px 12px;
|
|
|
+ border-radius: 20px;
|
|
|
+ font-size: 0.85rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-actions {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 15px 20px;
|
|
|
+ border-top: 1px solid var(--light-gray);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 筛选配置页 */
|
|
|
+ .config-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
|
+ gap: 25px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-section {
|
|
|
+ background: var(--light);
|
|
|
+ border-radius: var(--radius);
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-title {
|
|
|
+ font-size: 1.2rem;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ color: var(--primary-dark);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .criteria-list {
|
|
|
+ list-style: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .criteria-item {
|
|
|
+ padding: 12px 0;
|
|
|
+ border-bottom: 1px solid var(--border);
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .criteria-name {
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .criteria-controls {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .slider-container {
|
|
|
+ padding: 10px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .slider-label {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .slider-value {
|
|
|
+ font-weight: 700;
|
|
|
+ color: var(--primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ input[type="range"] {
|
|
|
+ width: 100%;
|
|
|
+ height: 8px;
|
|
|
+ border-radius: 5px;
|
|
|
+ background: var(--light-gray);
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 简历详情页 */
|
|
|
+ .resume-detail-container {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 300px 1fr;
|
|
|
+ gap: 30px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .resume-sidebar {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ padding: 25px;
|
|
|
+ position: sticky;
|
|
|
+ top: 100px;
|
|
|
+ align-self: start;
|
|
|
+ }
|
|
|
+
|
|
|
+ .candidate-basic {
|
|
|
+ text-align: center;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ border-bottom: 1px solid var(--light-gray);
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-avatar {
|
|
|
+ width: 120px;
|
|
|
+ height: 120px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: var(--light);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 3rem;
|
|
|
+ color: var(--primary);
|
|
|
+ margin: 0 auto 15px;
|
|
|
+ border: 5px solid var(--light-gray);
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-name {
|
|
|
+ font-size: 1.8rem;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-title {
|
|
|
+ font-size: 1.2rem;
|
|
|
+ color: var(--gray);
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-score {
|
|
|
+ display: inline-block;
|
|
|
+ background: var(--primary);
|
|
|
+ color: white;
|
|
|
+ padding: 8px 25px;
|
|
|
+ border-radius: 30px;
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 1.3rem;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .contact-info {
|
|
|
+ margin: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .contact-item {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .resume-content {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ padding: 30px;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .back-button {
|
|
|
+ position: absolute;
|
|
|
+ top: 25px;
|
|
|
+ right: 25px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ font-size: 1.4rem;
|
|
|
+ color: var(--primary-dark);
|
|
|
+ margin: 30px 0 20px;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ border-bottom: 2px solid var(--light-gray);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-content {
|
|
|
+ line-height: 1.8;
|
|
|
+ }
|
|
|
+
|
|
|
+ .timeline-item {
|
|
|
+ margin-bottom: 25px;
|
|
|
+ padding-left: 20px;
|
|
|
+ border-left: 2px solid var(--primary);
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .timeline-item:before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: -8px;
|
|
|
+ top: 5px;
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: var(--primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .timeline-period {
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--primary);
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .timeline-title {
|
|
|
+ font-weight: 700;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill-bars {
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill-bar {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill-info {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill-progress {
|
|
|
+ height: 10px;
|
|
|
+ background: var(--light-gray);
|
|
|
+ border-radius: 5px;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .skill-progress-inner {
|
|
|
+ height: 100%;
|
|
|
+ background: var(--primary);
|
|
|
+ border-radius: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 数据看板页 */
|
|
|
+ .dashboard-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .metric-card {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ padding: 25px;
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .metric-icon {
|
|
|
+ width: 70px;
|
|
|
+ height: 70px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: rgba(67, 97, 238, 0.1);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 1.8rem;
|
|
|
+ color: var(--primary);
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .metric-value {
|
|
|
+ font-size: 2.5rem;
|
|
|
+ font-weight: 700;
|
|
|
+ margin: 10px 0;
|
|
|
+ color: var(--primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .metric-label {
|
|
|
+ color: var(--gray);
|
|
|
+ font-size: 1.1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .metric-change {
|
|
|
+ margin-top: 10px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--success);
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart-container {
|
|
|
+ background: white;
|
|
|
+ border-radius: var(--radius);
|
|
|
+ padding: 25px;
|
|
|
+ box-shadow: var(--shadow);
|
|
|
+ margin-top: 25px;
|
|
|
+ height: 400px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chart-title {
|
|
|
+ font-size: 1.3rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: var(--dark);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 响应式设计 */
|
|
|
+ @media (max-width: 992px) {
|
|
|
+ .resume-detail-container {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ }
|
|
|
+
|
|
|
+ .resume-sidebar {
|
|
|
+ position: static;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 768px) {
|
|
|
+ .navbar {
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-links {
|
|
|
+ width: 100%;
|
|
|
+ justify-content: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .system-info {
|
|
|
+ width: 100%;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filters-bar {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-actions {
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-actions .btn {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <div class="container">
|
|
|
+ <!-- 顶部导航栏 -->
|
|
|
+ <header>
|
|
|
+ <div class="navbar">
|
|
|
+ <div class="logo">
|
|
|
+ <i class="fas fa-file-alt"></i>
|
|
|
+ <span>智能简历筛选系统</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="nav-links">
|
|
|
+ <div class="nav-link active" data-page="resume-list">
|
|
|
+ <i class="fas fa-list"></i>
|
|
|
+ <span>简历列表</span>
|
|
|
+ </div>
|
|
|
+ <div class="nav-link" data-page="filter-config">
|
|
|
+ <i class="fas fa-sliders-h"></i>
|
|
|
+ <span>筛选配置</span>
|
|
|
+ </div>
|
|
|
+ <div class="nav-link" data-page="dashboard">
|
|
|
+ <i class="fas fa-chart-bar"></i>
|
|
|
+ <span>数据看板</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="system-info">
|
|
|
+ <div class="resume-count">
|
|
|
+ <i class="fas fa-file"></i>
|
|
|
+ <span>简历总数: <span id="total-resumes">24</span></span>
|
|
|
+ </div>
|
|
|
+ <button class="btn btn-success" id="filter-action">
|
|
|
+ <i class="fas fa-filter"></i>
|
|
|
+ <span>一键筛选 (<span id="passed-resumes">16</span>通过)</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </header>
|
|
|
+
|
|
|
+ <!-- 简历列表页 -->
|
|
|
+ <div class="page-container active" id="resume-list-page">
|
|
|
+ <div class="panel">
|
|
|
+ <div class="panel-header">
|
|
|
+ <h2 class="panel-title">
|
|
|
+ <i class="fas fa-users"></i>
|
|
|
+ <span>候选人列表</span>
|
|
|
+ </h2>
|
|
|
+ <div class="filters-bar">
|
|
|
+ <div class="filter-group">
|
|
|
+ <label class="filter-label">职位类型</label>
|
|
|
+ <select class="filter-control" id="position-filter">
|
|
|
+ <option value="">所有职位</option>
|
|
|
+ <option>前端开发</option>
|
|
|
+ <option>后端开发</option>
|
|
|
+ <option>UI/UX设计</option>
|
|
|
+ <option>数据分析</option>
|
|
|
+ <option>产品经理</option>
|
|
|
+ <option>测试工程师</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="filter-group">
|
|
|
+ <label class="filter-label">工作经验</label>
|
|
|
+ <select class="filter-control" id="experience-filter">
|
|
|
+ <option value="0">不限经验</option>
|
|
|
+ <option value="1">1年以下</option>
|
|
|
+ <option value="3">1-3年</option>
|
|
|
+ <option value="5">3-5年</option>
|
|
|
+ <option value="10">5年以上</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="filter-group">
|
|
|
+ <label class="filter-label">学历要求</label>
|
|
|
+ <select class="filter-control" id="education-filter">
|
|
|
+ <option value="">不限学历</option>
|
|
|
+ <option>大专</option>
|
|
|
+ <option>本科</option>
|
|
|
+ <option>硕士</option>
|
|
|
+ <option>博士</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="filter-group">
|
|
|
+ <label class="filter-label">最低评分</label>
|
|
|
+ <input type="number" class="filter-control" min="0" max="100" value="70" id="min-score">
|
|
|
+ </div>
|
|
|
+ <button class="btn" id="apply-filters">
|
|
|
+ <i class="fas fa-search"></i>
|
|
|
+ <span>应用筛选</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="candidate-grid" id="candidate-container">
|
|
|
+ <!-- 候选人卡片将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 筛选配置页 -->
|
|
|
+ <div class="page-container" id="filter-config-page">
|
|
|
+ <div class="panel">
|
|
|
+ <div class="panel-header">
|
|
|
+ <h2 class="panel-title">
|
|
|
+ <i class="fas fa-cog"></i>
|
|
|
+ <span>筛选配置</span>
|
|
|
+ </h2>
|
|
|
+ <button class="btn" id="save-config">
|
|
|
+ <i class="fas fa-save"></i>
|
|
|
+ <span>保存配置</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-grid">
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-graduation-cap"></i>
|
|
|
+ <span>学历要求</span>
|
|
|
+ </h3>
|
|
|
+ <ul class="criteria-list">
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">大专</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="education" data-value="大专">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">本科</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="education" data-value="本科">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">硕士</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="education" data-value="硕士">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">博士</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="education" data-value="博士">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-briefcase"></i>
|
|
|
+ <span>工作经验</span>
|
|
|
+ </h3>
|
|
|
+ <div class="slider-container">
|
|
|
+ <div class="slider-label">
|
|
|
+ <span>最低年限</span>
|
|
|
+ <span class="slider-value" id="exp-value">3年</span>
|
|
|
+ </div>
|
|
|
+ <input type="range" min="0" max="10" value="3" id="exp-slider">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-money-bill-wave"></i>
|
|
|
+ <span>薪资范围</span>
|
|
|
+ </h3>
|
|
|
+ <div class="slider-container">
|
|
|
+ <div class="slider-label">
|
|
|
+ <span>最高薪资</span>
|
|
|
+ <span class="slider-value" id="salary-value">20K</span>
|
|
|
+ </div>
|
|
|
+ <input type="range" min="5" max="50" value="20" step="5" id="salary-slider">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-star"></i>
|
|
|
+ <span>评分设置</span>
|
|
|
+ </h3>
|
|
|
+ <div class="slider-container">
|
|
|
+ <div class="slider-label">
|
|
|
+ <span>通过阈值</span>
|
|
|
+ <span class="slider-value" id="score-value">70分</span>
|
|
|
+ </div>
|
|
|
+ <input type="range" min="50" max="100" value="70" id="score-slider">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-code"></i>
|
|
|
+ <span>技能要求</span>
|
|
|
+ </h3>
|
|
|
+ <ul class="criteria-list">
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">JavaScript</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="skill" data-value="JavaScript">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">React</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="skill" data-value="React">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">Node.js</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" data-type="skill" data-value="Node.js">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">Python</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" data-type="skill" data-value="Python">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">SQL</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" data-type="skill" data-value="SQL">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">AWS</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" data-type="skill" data-value="AWS">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">Docker</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" data-type="skill" data-value="Docker">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ <li class="criteria-item">
|
|
|
+ <span class="criteria-name">Git</span>
|
|
|
+ <div class="criteria-controls">
|
|
|
+ <input type="checkbox" checked data-type="skill" data-value="Git">
|
|
|
+ </div>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 简历详情页 -->
|
|
|
+ <div class="page-container" id="resume-detail-page">
|
|
|
+ <div class="resume-detail-container">
|
|
|
+ <div class="resume-sidebar">
|
|
|
+ <div class="candidate-basic">
|
|
|
+ <div class="detail-avatar">
|
|
|
+ <i class="fas fa-user"></i>
|
|
|
+ </div>
|
|
|
+ <h2 class="detail-name" id="detail-name">张明</h2>
|
|
|
+ <div class="detail-title" id="detail-title">高级前端开发工程师</div>
|
|
|
+ <div class="detail-score" id="detail-score">86分</div>
|
|
|
+ <div class="candidate-status" id="detail-status">已通过</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="contact-info" id="contact-info">
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-envelope"></i>
|
|
|
+ <span>zhangming@example.com</span>
|
|
|
+ </div>
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-phone"></i>
|
|
|
+ <span>13800138000</span>
|
|
|
+ </div>
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-map-marker-alt"></i>
|
|
|
+ <span>北京市海淀区</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="skills">
|
|
|
+ <h3 class="section-title">
|
|
|
+ <i class="fas fa-code"></i>
|
|
|
+ <span>技能专长</span>
|
|
|
+ </h3>
|
|
|
+ <div class="skill-bars" id="skill-bars">
|
|
|
+ <!-- 技能条将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="resume-content">
|
|
|
+ <button class="btn btn-light back-button" id="back-to-list">
|
|
|
+ <i class="fas fa-arrow-left"></i>
|
|
|
+ <span>返回列表</span>
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-user"></i>
|
|
|
+ <span>个人简介</span>
|
|
|
+ </h2>
|
|
|
+ <div class="section-content" id="personal-profile">
|
|
|
+ <!-- 个人简介内容将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-briefcase"></i>
|
|
|
+ <span>工作经历</span>
|
|
|
+ </h2>
|
|
|
+ <div class="section-content" id="work-experience">
|
|
|
+ <!-- 工作经历内容将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-graduation-cap"></i>
|
|
|
+ <span>教育背景</span>
|
|
|
+ </h2>
|
|
|
+ <div class="section-content" id="education-background">
|
|
|
+ <!-- 教育背景内容将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-medal"></i>
|
|
|
+ <span>项目经验</span>
|
|
|
+ </h2>
|
|
|
+ <div class="section-content" id="project-experience">
|
|
|
+ <!-- 项目经验内容将通过JS动态生成 -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 数据看板页 -->
|
|
|
+ <div class="page-container" id="dashboard-page">
|
|
|
+ <div class="dashboard-grid">
|
|
|
+ <div class="metric-card">
|
|
|
+ <div class="metric-icon">
|
|
|
+ <i class="fas fa-file"></i>
|
|
|
+ </div>
|
|
|
+ <div class="metric-value" id="total-resumes-dash">24</div>
|
|
|
+ <div class="metric-label">简历总数</div>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <div class="metric-icon">
|
|
|
+ <i class="fas fa-check-circle"></i>
|
|
|
+ </div>
|
|
|
+ <div class="metric-value" id="passed-resumes-dash">16</div>
|
|
|
+ <div class="metric-label">通过筛选</div>
|
|
|
+ <div class="metric-change">+2 较昨日</div>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <div class="metric-icon">
|
|
|
+ <i class="fas fa-percentage"></i>
|
|
|
+ </div>
|
|
|
+ <div class="metric-value">66.7%</div>
|
|
|
+ <div class="metric-label">筛选通过率</div>
|
|
|
+ <div class="metric-change">+3.5% 较上周</div>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <div class="metric-icon">
|
|
|
+ <i class="fas fa-star"></i>
|
|
|
+ </div>
|
|
|
+ <div class="metric-value">78.4</div>
|
|
|
+ <div class="metric-label">平均评分</div>
|
|
|
+ <div class="metric-change">+1.2 较上月</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="chart-container">
|
|
|
+ <div class="chart-header">
|
|
|
+ <div class="chart-title">简历评分分布</div>
|
|
|
+ <div class="filter-control">
|
|
|
+ <select id="score-chart-range">
|
|
|
+ <option>最近7天</option>
|
|
|
+ <option>最近30天</option>
|
|
|
+ <option>全部时间</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <canvas id="score-distribution-chart"></canvas>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="chart-container">
|
|
|
+ <div class="chart-header">
|
|
|
+ <div class="chart-title">岗位类型分布</div>
|
|
|
+ </div>
|
|
|
+ <canvas id="position-distribution-chart"></canvas>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ // 简历数据 - 增加更多示例
|
|
|
+ const resumes = [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ name: "张明",
|
|
|
+ title: "高级前端开发工程师",
|
|
|
+ education: "本科",
|
|
|
+ experience: 5,
|
|
|
+ salary: 25,
|
|
|
+ score: 86,
|
|
|
+ skills: ["JavaScript", "HTML", "CSS", "React", "Vue", "TypeScript", "Webpack"],
|
|
|
+ status: "passed",
|
|
|
+ location: "北京",
|
|
|
+ email: "zhangming@example.com",
|
|
|
+ phone: "13800138000",
|
|
|
+ profile: "5年前端开发经验,专注于构建高性能、用户友好的Web应用程序。精通现代JavaScript框架和响应式设计,对前端工程化和性能优化有深入研究。具有良好的团队协作能力和沟通技巧,能够高效地解决复杂问题并交付高质量产品。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2020年6月 - 至今",
|
|
|
+ company: "科技有限公司",
|
|
|
+ position: "高级前端工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "负责公司核心产品的前端架构设计和实现",
|
|
|
+ "优化应用性能,提升页面加载速度40%",
|
|
|
+ "设计和实现组件库,提高团队开发效率",
|
|
|
+ "指导初级开发人员,组织技术分享会"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ period: "2018年3月 - 2020年5月",
|
|
|
+ company: "网络科技有限公司",
|
|
|
+ position: "前端开发工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "参与电商平台的前端开发",
|
|
|
+ "实现响应式设计,优化移动端体验",
|
|
|
+ "与后端团队协作开发API接口",
|
|
|
+ "参与代码审查和团队技术决策"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2014年9月 - 2018年6月",
|
|
|
+ school: "北京大学",
|
|
|
+ major: "计算机科学与技术",
|
|
|
+ degree: "本科"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "企业级管理系统重构",
|
|
|
+ description: "将遗留系统从AngularJS迁移到React + TypeScript",
|
|
|
+ responsibilities: [
|
|
|
+ "设计并实现组件库,统一UI风格",
|
|
|
+ "优化构建流程,减少构建时间50%",
|
|
|
+ "实现自动化测试,覆盖率从30%提升到85%"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "移动电商平台",
|
|
|
+ description: "使用Vue.js开发高性能移动端应用",
|
|
|
+ responsibilities: [
|
|
|
+ "实现服务端渲染(SSR)提升首屏加载速度",
|
|
|
+ "集成支付系统和物流跟踪功能",
|
|
|
+ "优化SEO,提升自然搜索流量30%"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "JavaScript", level: 95 },
|
|
|
+ { name: "React", level: 90 },
|
|
|
+ { name: "Vue.js", level: 85 },
|
|
|
+ { name: "HTML/CSS", level: 92 },
|
|
|
+ { name: "TypeScript", level: 88 },
|
|
|
+ { name: "Webpack", level: 80 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ name: "李华",
|
|
|
+ title: "Java后端工程师",
|
|
|
+ education: "硕士",
|
|
|
+ experience: 6,
|
|
|
+ salary: 28,
|
|
|
+ score: 92,
|
|
|
+ skills: ["Java", "Spring", "MySQL", "Redis", "Linux", "Docker"],
|
|
|
+ status: "passed",
|
|
|
+ location: "上海",
|
|
|
+ email: "lihua@example.com",
|
|
|
+ phone: "13900139000",
|
|
|
+ profile: "6年Java后端开发经验,精通Spring生态和微服务架构。熟悉高并发、分布式系统设计,有丰富的性能调优经验。主导过多个大型企业级应用的后端架构设计和实现,对系统安全和稳定性有深刻理解。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2019年7月 - 至今",
|
|
|
+ company: "信息技术有限公司",
|
|
|
+ position: "高级Java工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "设计和实现微服务架构",
|
|
|
+ "优化数据库查询性能,减少响应时间60%",
|
|
|
+ "实现分布式缓存系统",
|
|
|
+ "负责系统安全设计和实现"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ period: "2017年2月 - 2019年6月",
|
|
|
+ company: "软件科技有限公司",
|
|
|
+ position: "Java开发工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "参与企业ERP系统开发",
|
|
|
+ "设计和实现RESTful API",
|
|
|
+ "优化SQL查询,提高系统性能",
|
|
|
+ "参与系统架构设计"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2013年9月 - 2017年6月",
|
|
|
+ school: "清华大学",
|
|
|
+ major: "软件工程",
|
|
|
+ degree: "硕士"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "电商平台后端系统",
|
|
|
+ description: "高并发电商平台后端架构设计和实现",
|
|
|
+ responsibilities: [
|
|
|
+ "设计微服务架构",
|
|
|
+ "实现分布式事务处理",
|
|
|
+ "优化数据库性能"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "支付系统",
|
|
|
+ description: "企业级支付系统开发",
|
|
|
+ responsibilities: [
|
|
|
+ "设计支付流程",
|
|
|
+ "实现与第三方支付平台对接",
|
|
|
+ "确保系统安全性和稳定性"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Java", level: 98 },
|
|
|
+ { name: "Spring", level: 95 },
|
|
|
+ { name: "MySQL", level: 90 },
|
|
|
+ { name: "Redis", level: 88 },
|
|
|
+ { name: "Docker", level: 85 },
|
|
|
+ { name: "Linux", level: 80 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ name: "王芳",
|
|
|
+ title: "全栈工程师",
|
|
|
+ education: "本科",
|
|
|
+ experience: 4,
|
|
|
+ salary: 22,
|
|
|
+ score: 78,
|
|
|
+ skills: ["JavaScript", "Node.js", "Express", "MongoDB", "React"],
|
|
|
+ status: "passed",
|
|
|
+ location: "深圳",
|
|
|
+ email: "wangfang@example.com",
|
|
|
+ phone: "13700137000",
|
|
|
+ profile: "4年全栈开发经验,熟悉JavaScript全栈技术。能够独立完成从前端到后端的完整开发流程。对Web性能优化和用户体验有深入研究,擅长快速学习和应用新技术。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2019年1月 - 至今",
|
|
|
+ company: "互联网科技有限公司",
|
|
|
+ position: "全栈工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "负责Web应用全栈开发",
|
|
|
+ "设计和实现RESTful API",
|
|
|
+ "优化前端性能",
|
|
|
+ "参与数据库设计和优化"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2015年9月 - 2019年6月",
|
|
|
+ school: "浙江大学",
|
|
|
+ major: "计算机科学与技术",
|
|
|
+ degree: "本科"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "内容管理系统",
|
|
|
+ description: "基于MERN技术栈的内容管理系统",
|
|
|
+ responsibilities: [
|
|
|
+ "全栈开发",
|
|
|
+ "实现用户权限管理",
|
|
|
+ "优化编辑器体验"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "JavaScript", level: 90 },
|
|
|
+ { name: "Node.js", level: 85 },
|
|
|
+ { name: "React", level: 80 },
|
|
|
+ { name: "MongoDB", level: 75 },
|
|
|
+ { name: "Express", level: 70 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ name: "刘伟",
|
|
|
+ title: "Python数据分析师",
|
|
|
+ education: "硕士",
|
|
|
+ experience: 3,
|
|
|
+ salary: 18,
|
|
|
+ score: 72,
|
|
|
+ skills: ["Python", "Pandas", "NumPy", "Matplotlib", "SQL"],
|
|
|
+ status: "passed",
|
|
|
+ location: "广州",
|
|
|
+ email: "liuwei@example.com",
|
|
|
+ phone: "13600136000",
|
|
|
+ profile: "3年数据分析经验,精通Python数据分析工具链。擅长数据清洗、分析和可视化,能够从海量数据中提取有价值的信息。有丰富的商业分析和预测建模经验。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2020年5月 - 至今",
|
|
|
+ company: "数据科技有限公司",
|
|
|
+ position: "数据分析师",
|
|
|
+ responsibilities: [
|
|
|
+ "数据清洗和分析",
|
|
|
+ "构建预测模型",
|
|
|
+ "生成数据报告",
|
|
|
+ "可视化数据展示"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2017年9月 - 2020年6月",
|
|
|
+ school: "中山大学",
|
|
|
+ major: "数据科学",
|
|
|
+ degree: "硕士"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "销售预测系统",
|
|
|
+ description: "基于历史数据的销售预测模型",
|
|
|
+ responsibilities: [
|
|
|
+ "数据收集和清洗",
|
|
|
+ "特征工程",
|
|
|
+ "模型训练和评估"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Python", level: 90 },
|
|
|
+ { name: "Pandas", level: 85 },
|
|
|
+ { name: "NumPy", level: 80 },
|
|
|
+ { name: "Matplotlib", level: 75 },
|
|
|
+ { name: "SQL", level: 70 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 5,
|
|
|
+ name: "陈静",
|
|
|
+ title: "UI/UX设计师",
|
|
|
+ education: "本科",
|
|
|
+ experience: 4,
|
|
|
+ salary: 20,
|
|
|
+ score: 65,
|
|
|
+ skills: ["Figma", "Sketch", "Photoshop", "Illustrator", "UI设计"],
|
|
|
+ status: "pending",
|
|
|
+ location: "杭州",
|
|
|
+ email: "chenjing@example.com",
|
|
|
+ phone: "13500135000",
|
|
|
+ profile: "4年UI/UX设计经验,擅长移动端和Web端界面设计。对用户体验有深刻理解,能够将复杂需求转化为直观易用的界面。熟悉设计系统和组件化设计方法。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2019年3月 - 至今",
|
|
|
+ company: "设计工作室",
|
|
|
+ position: "UI设计师",
|
|
|
+ responsibilities: [
|
|
|
+ "移动应用界面设计",
|
|
|
+ "设计规范制定",
|
|
|
+ "用户研究",
|
|
|
+ "原型设计"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2015年9月 - 2019年6月",
|
|
|
+ school: "中国美术学院",
|
|
|
+ major: "视觉传达设计",
|
|
|
+ degree: "本科"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "电商App设计",
|
|
|
+ description: "从0到1设计电商App",
|
|
|
+ responsibilities: [
|
|
|
+ "用户调研",
|
|
|
+ "信息架构设计",
|
|
|
+ "界面设计",
|
|
|
+ "设计规范制定"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Figma", level: 95 },
|
|
|
+ { name: "Sketch", level: 90 },
|
|
|
+ { name: "Photoshop", level: 85 },
|
|
|
+ { name: "Illustrator", level: 80 },
|
|
|
+ { name: "UI设计", level: 90 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 6,
|
|
|
+ name: "杨阳",
|
|
|
+ title: "DevOps工程师",
|
|
|
+ education: "本科",
|
|
|
+ experience: 7,
|
|
|
+ salary: 32,
|
|
|
+ score: 88,
|
|
|
+ skills: ["Docker", "Kubernetes", "AWS", "Jenkins", "Linux"],
|
|
|
+ status: "passed",
|
|
|
+ location: "成都",
|
|
|
+ email: "yangyang@example.com",
|
|
|
+ phone: "13400134000",
|
|
|
+ profile: "7年DevOps经验,精通云原生技术和自动化部署。熟悉CI/CD流程优化,能够构建高可用、可扩展的基础设施。对系统监控和性能调优有丰富经验。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2018年8月 - 至今",
|
|
|
+ company: "云计算有限公司",
|
|
|
+ position: "DevOps工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "设计和维护CI/CD流程",
|
|
|
+ "容器化应用部署",
|
|
|
+ "云基础设施管理",
|
|
|
+ "系统监控和告警"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2011年9月 - 2015年6月",
|
|
|
+ school: "电子科技大学",
|
|
|
+ major: "计算机科学与技术",
|
|
|
+ degree: "本科"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "微服务架构部署",
|
|
|
+ description: "将单体应用迁移到微服务架构",
|
|
|
+ responsibilities: [
|
|
|
+ "容器化部署",
|
|
|
+ "服务网格配置",
|
|
|
+ "自动化扩缩容"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Docker", level: 95 },
|
|
|
+ { name: "Kubernetes", level: 90 },
|
|
|
+ { name: "AWS", level: 85 },
|
|
|
+ { name: "Jenkins", level: 80 },
|
|
|
+ { name: "Linux", level: 90 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 7,
|
|
|
+ name: "赵琳",
|
|
|
+ title: "移动开发工程师",
|
|
|
+ education: "硕士",
|
|
|
+ experience: 3,
|
|
|
+ salary: 21,
|
|
|
+ score: 75,
|
|
|
+ skills: ["Swift", "Kotlin", "React Native", "Flutter", "iOS"],
|
|
|
+ status: "pending",
|
|
|
+ location: "南京",
|
|
|
+ email: "zhaolin@example.com",
|
|
|
+ phone: "13300133000",
|
|
|
+ profile: "3年移动开发经验,熟悉iOS和Android原生开发以及跨平台框架。对移动端性能优化和用户体验有深入研究。能够快速学习和应用新技术。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2020年2月 - 至今",
|
|
|
+ company: "移动科技有限公司",
|
|
|
+ position: "移动开发工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "iOS原生应用开发",
|
|
|
+ "Android原生应用开发",
|
|
|
+ "跨平台应用开发",
|
|
|
+ "性能优化"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2017年9月 - 2020年6月",
|
|
|
+ school: "东南大学",
|
|
|
+ major: "软件工程",
|
|
|
+ degree: "硕士"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "社交App开发",
|
|
|
+ description: "基于React Native的跨平台社交应用",
|
|
|
+ responsibilities: [
|
|
|
+ "核心功能开发",
|
|
|
+ "性能优化",
|
|
|
+ "与后端API对接"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Swift", level: 85 },
|
|
|
+ { name: "Kotlin", level: 80 },
|
|
|
+ { name: "React Native", level: 75 },
|
|
|
+ { name: "Flutter", level: 70 },
|
|
|
+ { name: "iOS", level: 85 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 8,
|
|
|
+ name: "周涛",
|
|
|
+ title: "大数据工程师",
|
|
|
+ education: "博士",
|
|
|
+ experience: 8,
|
|
|
+ salary: 38,
|
|
|
+ score: 90,
|
|
|
+ skills: ["Hadoop", "Spark", "Hive", "Scala", "Python"],
|
|
|
+ status: "passed",
|
|
|
+ location: "武汉",
|
|
|
+ email: "zhoutao@example.com",
|
|
|
+ phone: "13200132000",
|
|
|
+ profile: "8年大数据领域经验,精通Hadoop生态和Spark计算框架。擅长海量数据处理和分析,有丰富的分布式系统优化经验。能够设计和实现高效的数据处理流程。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2017年5月 - 至今",
|
|
|
+ company: "大数据科技有限公司",
|
|
|
+ position: "大数据工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "大数据平台架构设计",
|
|
|
+ "数据处理流程优化",
|
|
|
+ "实时计算系统开发",
|
|
|
+ "团队技术指导"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2012年9月 - 2017年6月",
|
|
|
+ school: "华中科技大学",
|
|
|
+ major: "计算机科学与技术",
|
|
|
+ degree: "博士"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "实时数据分析平台",
|
|
|
+ description: "基于Spark Streaming的实时数据处理平台",
|
|
|
+ responsibilities: [
|
|
|
+ "架构设计",
|
|
|
+ "性能优化",
|
|
|
+ "数据管道开发"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "Hadoop", level: 95 },
|
|
|
+ { name: "Spark", level: 90 },
|
|
|
+ { name: "Hive", level: 85 },
|
|
|
+ { name: "Scala", level: 80 },
|
|
|
+ { name: "Python", level: 75 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 9,
|
|
|
+ name: "吴强",
|
|
|
+ title: "测试工程师",
|
|
|
+ education: "本科",
|
|
|
+ experience: 5,
|
|
|
+ salary: 18,
|
|
|
+ score: 68,
|
|
|
+ skills: ["自动化测试", "Selenium", "JMeter", "Postman", "JIRA"],
|
|
|
+ status: "pending",
|
|
|
+ location: "西安",
|
|
|
+ email: "wuqiang@example.com",
|
|
|
+ phone: "13100131000",
|
|
|
+ profile: "5年软件测试经验,精通自动化测试和性能测试。熟悉敏捷开发流程,能够设计和实施全面的测试策略。对质量保证和缺陷管理有丰富经验。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2018年4月 - 至今",
|
|
|
+ company: "软件测试有限公司",
|
|
|
+ position: "测试工程师",
|
|
|
+ responsibilities: [
|
|
|
+ "自动化测试脚本开发",
|
|
|
+ "性能测试",
|
|
|
+ "测试用例设计",
|
|
|
+ "缺陷跟踪和管理"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2014年9月 - 2018年6月",
|
|
|
+ school: "西安电子科技大学",
|
|
|
+ major: "软件工程",
|
|
|
+ degree: "本科"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "电商平台测试",
|
|
|
+ description: "全流程测试电商平台",
|
|
|
+ responsibilities: [
|
|
|
+ "功能测试",
|
|
|
+ "性能测试",
|
|
|
+ "安全测试",
|
|
|
+ "测试报告生成"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "自动化测试", level: 85 },
|
|
|
+ { name: "Selenium", level: 80 },
|
|
|
+ { name: "JMeter", level: 75 },
|
|
|
+ { name: "Postman", level: 70 },
|
|
|
+ { name: "JIRA", level: 65 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 10,
|
|
|
+ name: "郑雪",
|
|
|
+ title: "产品经理",
|
|
|
+ education: "硕士",
|
|
|
+ experience: 6,
|
|
|
+ salary: 25,
|
|
|
+ score: 82,
|
|
|
+ skills: ["产品规划", "用户研究", "Axure", "数据分析", "项目管理"],
|
|
|
+ status: "passed",
|
|
|
+ location: "重庆",
|
|
|
+ email: "zhengxue@example.com",
|
|
|
+ phone: "13000130000",
|
|
|
+ profile: "6年产品管理经验,熟悉从0到1的产品开发全流程。擅长用户需求分析和产品设计,能够协调跨部门团队推动产品落地。对数据驱动决策有深刻理解。",
|
|
|
+ workExperience: [
|
|
|
+ {
|
|
|
+ period: "2019年1月 - 至今",
|
|
|
+ company: "互联网产品有限公司",
|
|
|
+ position: "产品经理",
|
|
|
+ responsibilities: [
|
|
|
+ "产品路线图规划",
|
|
|
+ "用户需求分析",
|
|
|
+ "产品原型设计",
|
|
|
+ "跨部门协调"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ education: [
|
|
|
+ {
|
|
|
+ period: "2016年9月 - 2019年6月",
|
|
|
+ school: "重庆大学",
|
|
|
+ major: "工商管理",
|
|
|
+ degree: "硕士"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ projects: [
|
|
|
+ {
|
|
|
+ name: "企业SaaS产品",
|
|
|
+ description: "从0到1设计并推出企业级SaaS产品",
|
|
|
+ responsibilities: [
|
|
|
+ "市场调研",
|
|
|
+ "产品功能设计",
|
|
|
+ "用户体验优化",
|
|
|
+ "产品上线推广"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ skillLevels: [
|
|
|
+ { name: "产品规划", level: 90 },
|
|
|
+ { name: "用户研究", level: 85 },
|
|
|
+ { name: "Axure", level: 80 },
|
|
|
+ { name: "数据分析", level: 75 },
|
|
|
+ { name: "项目管理", level: 70 }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 当前查看的简历ID
|
|
|
+ let currentViewingResumeId = null;
|
|
|
+
|
|
|
+ // 初始化应用
|
|
|
+ document.addEventListener('DOMContentLoaded', function() {
|
|
|
+ renderCandidates(resumes);
|
|
|
+ setupEventListeners();
|
|
|
+ updateResumeCounts();
|
|
|
+ initSliders();
|
|
|
+ initCharts();
|
|
|
+ });
|
|
|
+
|
|
|
+ // 渲染候选人列表
|
|
|
+ function renderCandidates(candidates) {
|
|
|
+ const container = document.getElementById('candidate-container');
|
|
|
+
|
|
|
+ if (candidates.length === 0) {
|
|
|
+ container.innerHTML = `<div class="no-results">没有找到匹配的候选人,请调整筛选条件</div>`;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let html = '';
|
|
|
+
|
|
|
+ candidates.forEach(candidate => {
|
|
|
+ const statusClass = candidate.status === "passed" ? "status-passed" : "status-pending";
|
|
|
+ const statusText = candidate.status === "passed" ? "已通过" : "待审核";
|
|
|
+
|
|
|
+ html += `
|
|
|
+ <div class="candidate-card" data-id="${candidate.id}">
|
|
|
+ <div class="candidate-header">
|
|
|
+ <div class="candidate-status ${statusClass}">${statusText}</div>
|
|
|
+ <div class="candidate-avatar">
|
|
|
+ <i class="fas fa-user"></i>
|
|
|
+ </div>
|
|
|
+ <div class="candidate-name">${candidate.name}</div>
|
|
|
+ <div class="candidate-title">${candidate.title}</div>
|
|
|
+ <div class="candidate-score">${candidate.score}分</div>
|
|
|
+ </div>
|
|
|
+ <div class="candidate-body">
|
|
|
+ <div class="candidate-info">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">学历:</span>
|
|
|
+ <span>${candidate.education}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">经验:</span>
|
|
|
+ <span>${candidate.experience}年</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">期望薪资:</span>
|
|
|
+ <span>${candidate.salary}K/月</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">所在地:</span>
|
|
|
+ <span>${candidate.location}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="candidate-skills">
|
|
|
+ <div class="info-label">技能:</div>
|
|
|
+ <div class="skills">
|
|
|
+ ${candidate.skills.map(skill => `<div class="skill">${skill}</div>`).join('')}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card-actions">
|
|
|
+ <button class="btn btn-warning view-detail">
|
|
|
+ <i class="fas fa-eye"></i> 查看详情
|
|
|
+ </button>
|
|
|
+ <button class="btn ${candidate.status === "passed" ? "btn-success" : ""} toggle-status">
|
|
|
+ <i class="fas ${candidate.status === "passed" ? "fa-check" : "fa-hourglass-half"}"></i>
|
|
|
+ ${candidate.status === "passed" ? "已通过" : "标记通过"}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ });
|
|
|
+
|
|
|
+ container.innerHTML = html;
|
|
|
+
|
|
|
+ // 添加查看详情事件
|
|
|
+ document.querySelectorAll('.view-detail').forEach(button => {
|
|
|
+ button.addEventListener('click', function() {
|
|
|
+ const card = this.closest('.candidate-card');
|
|
|
+ const candidateId = parseInt(card.dataset.id);
|
|
|
+ viewResumeDetail(candidateId);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加标记通过事件
|
|
|
+ document.querySelectorAll('.toggle-status').forEach(button => {
|
|
|
+ button.addEventListener('click', function() {
|
|
|
+ const card = this.closest('.candidate-card');
|
|
|
+ const candidateId = parseInt(card.dataset.id);
|
|
|
+ toggleCandidateStatus(candidateId);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置事件监听器
|
|
|
+ function setupEventListeners() {
|
|
|
+ // 导航切换
|
|
|
+ document.querySelectorAll('.nav-link').forEach(link => {
|
|
|
+ link.addEventListener('click', function() {
|
|
|
+ if (this.dataset.page === 'resume-detail') return;
|
|
|
+
|
|
|
+ document.querySelectorAll('.nav-link').forEach(el => {
|
|
|
+ el.classList.remove('active');
|
|
|
+ });
|
|
|
+ this.classList.add('active');
|
|
|
+
|
|
|
+ const pageId = this.dataset.page + '-page';
|
|
|
+ document.querySelectorAll('.page-container').forEach(page => {
|
|
|
+ page.classList.remove('active');
|
|
|
+ });
|
|
|
+ document.getElementById(pageId).classList.add('active');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 一键筛选按钮
|
|
|
+ document.getElementById('filter-action').addEventListener('click', function() {
|
|
|
+ const minScore = parseInt(document.getElementById('min-score').value);
|
|
|
+ filterCandidates(minScore);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 应用筛选按钮
|
|
|
+ document.getElementById('apply-filters').addEventListener('click', applyFilters);
|
|
|
+
|
|
|
+ // 返回列表按钮
|
|
|
+ document.getElementById('back-to-list').addEventListener('click', backToList);
|
|
|
+
|
|
|
+ // 保存配置按钮
|
|
|
+ document.getElementById('save-config').addEventListener('click', saveConfig);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化滑块控件
|
|
|
+ function initSliders() {
|
|
|
+ const expSlider = document.getElementById('exp-slider');
|
|
|
+ const expValue = document.getElementById('exp-value');
|
|
|
+ const salarySlider = document.getElementById('salary-slider');
|
|
|
+ const salaryValue = document.getElementById('salary-value');
|
|
|
+ const scoreSlider = document.getElementById('score-slider');
|
|
|
+ const scoreValue = document.getElementById('score-value');
|
|
|
+
|
|
|
+ expSlider.addEventListener('input', () => {
|
|
|
+ expValue.textContent = expSlider.value + '年';
|
|
|
+ });
|
|
|
+
|
|
|
+ salarySlider.addEventListener('input', () => {
|
|
|
+ salaryValue.textContent = salarySlider.value + 'K';
|
|
|
+ });
|
|
|
+
|
|
|
+ scoreSlider.addEventListener('input', () => {
|
|
|
+ scoreValue.textContent = scoreSlider.value + '分';
|
|
|
+ document.getElementById('min-score').value = scoreSlider.value;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化图表
|
|
|
+ function initCharts() {
|
|
|
+ // 评分分布图
|
|
|
+ const scoreCtx = document.getElementById('score-distribution-chart').getContext('2d');
|
|
|
+ new Chart(scoreCtx, {
|
|
|
+ type: 'bar',
|
|
|
+ data: {
|
|
|
+ labels: ['50-59', '60-69', '70-79', '80-89', '90-100'],
|
|
|
+ datasets: [{
|
|
|
+ label: '人数',
|
|
|
+ data: [2, 5, 8, 6, 3],
|
|
|
+ backgroundColor: '#4361ee'
|
|
|
+ }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ responsive: true,
|
|
|
+ scales: {
|
|
|
+ y: {
|
|
|
+ beginAtZero: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 岗位类型分布图
|
|
|
+ const positionCtx = document.getElementById('position-distribution-chart').getContext('2d');
|
|
|
+ new Chart(positionCtx, {
|
|
|
+ type: 'doughnut',
|
|
|
+ data: {
|
|
|
+ labels: ['前端开发', '后端开发', 'UI/UX设计', '数据分析', '产品经理', '测试工程师'],
|
|
|
+ datasets: [{
|
|
|
+ data: [3, 2, 1, 1, 1, 1],
|
|
|
+ backgroundColor: [
|
|
|
+ '#4361ee',
|
|
|
+ '#4cc9f0',
|
|
|
+ '#3a0ca3',
|
|
|
+ '#7209b7',
|
|
|
+ '#f72585',
|
|
|
+ '#4895ef'
|
|
|
+ ]
|
|
|
+ }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ responsive: true,
|
|
|
+ plugins: {
|
|
|
+ legend: {
|
|
|
+ position: 'right'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 筛选候选人
|
|
|
+ function filterCandidates(minScore) {
|
|
|
+ const filtered = resumes.filter(candidate => candidate.score >= minScore);
|
|
|
+ renderCandidates(filtered);
|
|
|
+
|
|
|
+ // 更新通过人数
|
|
|
+ const passedCount = filtered.filter(c => c.status === "passed").length;
|
|
|
+ document.getElementById('passed-resumes').textContent = passedCount;
|
|
|
+ document.getElementById('passed-resumes-dash').textContent = passedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应用筛选条件
|
|
|
+ function applyFilters() {
|
|
|
+ const position = document.getElementById('position-filter').value;
|
|
|
+ const experience = parseInt(document.getElementById('experience-filter').value);
|
|
|
+ const education = document.getElementById('education-filter').value;
|
|
|
+ const minScore = parseInt(document.getElementById('min-score').value);
|
|
|
+
|
|
|
+ const filtered = resumes.filter(candidate => {
|
|
|
+ // 职位筛选
|
|
|
+ if (position && !candidate.title.includes(position)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 经验筛选
|
|
|
+ if (experience > 0 && candidate.experience < experience) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 学历筛选
|
|
|
+ if (education && candidate.education !== education) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 评分筛选
|
|
|
+ if (candidate.score < minScore) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ renderCandidates(filtered);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查看简历详情
|
|
|
+ function viewResumeDetail(candidateId) {
|
|
|
+ const candidate = resumes.find(c => c.id === candidateId);
|
|
|
+ if (!candidate) return;
|
|
|
+
|
|
|
+ currentViewingResumeId = candidateId;
|
|
|
+
|
|
|
+ // 更新基本信息
|
|
|
+ document.getElementById('detail-name').textContent = candidate.name;
|
|
|
+ document.getElementById('detail-title').textContent = candidate.title;
|
|
|
+ document.getElementById('detail-score').textContent = candidate.score + '分';
|
|
|
+
|
|
|
+ const statusElement = document.getElementById('detail-status');
|
|
|
+ statusElement.textContent = candidate.status === "passed" ? "已通过" : "待审核";
|
|
|
+ statusElement.className = `candidate-status status-${candidate.status}`;
|
|
|
+
|
|
|
+ // 更新联系方式
|
|
|
+ const contactInfo = document.getElementById('contact-info');
|
|
|
+ contactInfo.innerHTML = `
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-envelope"></i>
|
|
|
+ <span>${candidate.email}</span>
|
|
|
+ </div>
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-phone"></i>
|
|
|
+ <span>${candidate.phone}</span>
|
|
|
+ </div>
|
|
|
+ <div class="contact-item">
|
|
|
+ <i class="fas fa-map-marker-alt"></i>
|
|
|
+ <span>${candidate.location}</span>
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+
|
|
|
+ // 更新技能条
|
|
|
+ const skillBars = document.getElementById('skill-bars');
|
|
|
+ skillBars.innerHTML = candidate.skillLevels.map(skill => `
|
|
|
+ <div class="skill-bar">
|
|
|
+ <div class="skill-info">
|
|
|
+ <span>${skill.name}</span>
|
|
|
+ <span>${skill.level}%</span>
|
|
|
+ </div>
|
|
|
+ <div class="skill-progress">
|
|
|
+ <div class="skill-progress-inner" style="width: ${skill.level}%"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+
|
|
|
+ // 更新个人简介
|
|
|
+ document.getElementById('personal-profile').innerHTML = `
|
|
|
+ <p>${candidate.profile}</p>
|
|
|
+ `;
|
|
|
+
|
|
|
+ // 更新工作经历
|
|
|
+ const workExperience = document.getElementById('work-experience');
|
|
|
+ workExperience.innerHTML = candidate.workExperience.map(exp => `
|
|
|
+ <div class="timeline-item">
|
|
|
+ <div class="timeline-period">${exp.period}</div>
|
|
|
+ <div class="timeline-title">${exp.position} - ${exp.company}</div>
|
|
|
+ <ul>
|
|
|
+ ${exp.responsibilities.map(resp => `<li>${resp}</li>`).join('')}
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+
|
|
|
+ // 更新教育背景
|
|
|
+ const educationBackground = document.getElementById('education-background');
|
|
|
+ educationBackground.innerHTML = candidate.education.map(edu => `
|
|
|
+ <div class="timeline-item">
|
|
|
+ <div class="timeline-period">${edu.period}</div>
|
|
|
+ <div class="timeline-title">${edu.major} ${edu.degree}</div>
|
|
|
+ <div>${edu.school}</div>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+
|
|
|
+ // 更新项目经验
|
|
|
+ const projectExperience = document.getElementById('project-experience');
|
|
|
+ projectExperience.innerHTML = candidate.projects.map(project => `
|
|
|
+ <div class="timeline-item">
|
|
|
+ <div class="timeline-title">${project.name}</div>
|
|
|
+ <p>${project.description}</p>
|
|
|
+ <ul>
|
|
|
+ ${project.responsibilities.map(resp => `<li>${resp}</li>`).join('')}
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+
|
|
|
+ // 切换到详情页
|
|
|
+ document.querySelectorAll('.page-container').forEach(page => {
|
|
|
+ page.classList.remove('active');
|
|
|
+ });
|
|
|
+ document.getElementById('resume-detail-page').classList.add('active');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回列表
|
|
|
+ function backToList() {
|
|
|
+ document.querySelectorAll('.page-container').forEach(page => {
|
|
|
+ page.classList.remove('active');
|
|
|
+ });
|
|
|
+ document.getElementById('resume-list-page').classList.add('active');
|
|
|
+
|
|
|
+ // 确保列表页的导航按钮高亮
|
|
|
+ document.querySelectorAll('.nav-link').forEach(link => {
|
|
|
+ link.classList.remove('active');
|
|
|
+ });
|
|
|
+ document.querySelector('[data-page="resume-list"]').classList.add('active');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 切换候选人状态
|
|
|
+ function toggleCandidateStatus(candidateId) {
|
|
|
+ const candidate = resumes.find(c => c.id === candidateId);
|
|
|
+ if (!candidate) return;
|
|
|
+
|
|
|
+ candidate.status = candidate.status === "passed" ? "pending" : "passed";
|
|
|
+ renderCandidates(resumes);
|
|
|
+ updateResumeCounts();
|
|
|
+
|
|
|
+ // 如果当前正在查看这个候选人的详情,更新详情页状态
|
|
|
+ if (currentViewingResumeId === candidateId) {
|
|
|
+ const statusElement = document.getElementById('detail-status');
|
|
|
+ statusElement.textContent = candidate.status === "passed" ? "已通过" : "待审核";
|
|
|
+ statusElement.className = `candidate-status status-${candidate.status}`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新简历数量统计
|
|
|
+ function updateResumeCounts() {
|
|
|
+ const total = resumes.length;
|
|
|
+ const passed = resumes.filter(c => c.status === "passed").length;
|
|
|
+
|
|
|
+ document.getElementById('total-resumes').textContent = total;
|
|
|
+ document.getElementById('passed-resumes').textContent = passed;
|
|
|
+ document.getElementById('total-resumes-dash').textContent = total;
|
|
|
+ document.getElementById('passed-resumes-dash').textContent = passed;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存配置
|
|
|
+ function saveConfig() {
|
|
|
+ alert('筛选配置已保存');
|
|
|
+ // 在实际应用中,这里会将配置保存到本地存储或后端
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|