Files
all-in-one-sys/index copy.html
KQL 61698639ef feat: 完成多多畅职就业服务平台核心功能开发
主要更新:
-  完成主题配色从暗色到亮蓝白配色的全面转换
-  实现高薪岗位页面及后端API集成
-  完成登录注册页面及认证系统
-  实现预招录确认功能
-  添加数据库管理和维护工具脚本
-  优化错误处理和用户体验

核心功能:
1. 首页 (index.html) - 3D地球、专业分类、过渡岗位
2. 高薪岗位页面 (high.html) - 岗位详情、预招录确认、成功案例
3. 登录注册 (auth.html) - 用户认证、专业分类选择
4. 后端API - RESTful接口,JWT认证,MySQL数据库

技术栈:
- 前端:Three.js, GSAP, 原生JavaScript
- 后端:Node.js, Express, MySQL
- 认证:JWT, bcrypt
- 样式:自定义CSS,响应式设计

数据库工具:
- kill-by-ids.js - 批量终止MySQL进程
- unlock-all-tables.js - 解锁数据库表
- init-db.js - 初始化数据库
- 其他管理脚本

🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 15:40:55 +08:00

1601 lines
101 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="referrer" content="no-referrer">
<title>大专生就业服务平台</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="./css/layout.css">
<link rel="stylesheet" href="./css/components.css">
<link rel="stylesheet" href="./css/effects.css">
<script src="js/utils/auth-helper.js"></script>
<script>
// 立即检查登录状态,未登录则跳转到登录页
if (!AuthHelper.isLoggedIn()) {
window.location.href = 'auth.html';
}
</script>
<style>
/* 引入字体 */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;500;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: 'Noto Sans SC', 'Microsoft YaHei', sans-serif;
color: #fff;
margin: 0;
padding: 0;
background-color: #020617;
}
/* 首页包裹容器 */
#home-wrapper {
background-color: #020617;
background-image:
radial-gradient(ellipse at 50% 50%, rgba(56, 189, 248, 0.2) 0%, rgba(30, 64, 175, 0.15) 40%, transparent 80%),
radial-gradient(circle at center, #0f172a 0%, #020617 100%);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
overflow: hidden;
}
.bg-glow {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 120vw;
height: 120vw;
background: radial-gradient(circle, rgba(79, 70, 229, 0.1) 0%, transparent 60%);
filter: blur(120px);
z-index: -1;
pointer-events: none;
}
.container {
width: 90%;
max-width: 1300px;
height: 85vh;
display: flex;
flex-direction: column;
gap: 24px;
z-index: 1;
}
/* Header 样式 */
.glass-header {
flex: 0 0 140px;
position: relative;
background: rgba(255, 255, 255, 0.03);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
display: flex;
align-items: center;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
padding: 0 20px;
z-index: 50;
}
.text-gradient {
background: linear-gradient(90deg, #e0f2fe, #38bdf8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
filter: drop-shadow(0 0 10px rgba(56, 189, 248, 0.3));
}
.text-glow {
color: #38bdf8;
text-shadow: 0 0 10px rgba(56, 189, 248, 0.4);
}
.card-wrapper {
flex: 1;
display: flex;
gap: 20px;
transition: all 0.3s ease;
}
.card {
position: relative;
flex: 1;
border-radius: 20px;
overflow: hidden;
cursor: pointer;
text-decoration: none;
box-shadow: 0 15px 35px rgba(0,0,0,0.5);
border: 1px solid rgba(255, 255, 255, 0.05);
background: #020617;
transition: flex 0.6s cubic-bezier(0.25, 1, 0.5, 1);
}
.card-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
filter: grayscale(100%) blur(4px);
transform: scale(1.1);
transition: all 0.6s ease;
}
.card-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(2, 6, 23, 0.6);
transition: background 0.6s ease;
z-index: 1;
}
.card-content {
position: relative;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px;
}
.card-content h2 {
color: #fff;
font-size: 32px;
font-weight: 700;
letter-spacing: 2px;
text-shadow: 0 4px 15px rgba(0,0,0,0.8);
transform: translateY(0);
transition: transform 0.6s cubic-bezier(0.25, 1, 0.5, 1);
}
.sub-text {
margin-top: 15px;
font-size: 16px;
color: rgba(255,255,255,0.9);
background: rgba(255, 255, 255, 0.05);
padding: 6px 16px;
border-radius: 50px;
backdrop-filter: blur(4px);
border: 1px solid rgba(255,255,255,0.1);
opacity: 0;
transform: translateY(20px);
transition: all 0.6s cubic-bezier(0.25, 1, 0.5, 1);
}
@media (min-width: 769px) {
.card:hover { flex: 3.2; }
.card:hover .card-bg { filter: grayscale(0%) blur(0px); transform: scale(1.05); }
.card:hover .card-overlay { background: rgba(2, 6, 23, 0.2); }
a.card:hover h2 { transform: translateY(-10px); }
a.card:hover .sub-text { opacity: 1; transform: translateY(0); }
.special-card:hover .default-view { opacity: 0; transform: translateY(-20px); pointer-events: none; }
.special-card:hover .split-view { opacity: 1; transform: translateY(0); }
}
.hidden { display: none !important; }
.default-view {
position: absolute; width: 100%; height: 100%;
display: flex; flex-direction: column; justify-content: center; align-items: center;
transition: all 0.6s cubic-bezier(0.25, 1, 0.5, 1); opacity: 1; transform: translateY(0);
}
.split-view {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
display: flex; opacity: 0; transform: translateY(20px);
transition: all 0.6s cubic-bezier(0.25, 1, 0.5, 1) 0.1s;
}
.split-item {
flex: 1; text-decoration: none; display: flex; justify-content: center; align-items: center;
color: white; position: relative; transition: background 0.3s ease;
}
.split-item:hover { background: rgba(255, 255, 255, 0.1); }
.panel-inner { text-align: center; transform: scale(0.9); transition: transform 0.3s ease; }
.split-item:hover .panel-inner { transform: scale(1); }
.split-item h3 { font-size: 22px; font-weight: 700; margin-bottom: 8px; color: #fff; white-space: nowrap; }
.split-item p { font-size: 12px; color: rgba(255, 255, 255, 0.7); margin-bottom: 12px; white-space: nowrap; }
.mini-arrow { font-size: 20px; opacity: 0; transform: translateX(-10px); transition: all 0.3s ease; color: #38bdf8; }
.split-item:hover .mini-arrow { opacity: 1; transform: translateX(0); }
.vertical-divider { width: 1px; height: 60%; background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.3), transparent); align-self: center; }
.mobile-pc-only-mask {
display: none; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(5px); z-index: 10; flex-direction: column; justify-content: center; align-items: center; text-align: center; padding: 20px;
}
.mobile-pc-only-mask i { font-size: 28px; color: #94a3b8; margin-bottom: 10px; }
.mobile-pc-only-mask p { font-size: 14px; color: #e2e8f0; font-weight: bold; }
.mobile-pc-only-mask span { font-size: 12px; color: #64748b; margin-top: 5px; }
/* ========= 移动端 首页适配重点区域 ========= */
@media (max-width: 768px) {
.container { height: 100vh; padding: 10px 0; gap: 15px; width: 95%; }
.glass-header {
flex: 0 0 auto; min-height: 80px;
padding: 15px 15px;
justify-content: space-between;
}
.card-wrapper { flex-direction: column; gap: 12px; overflow-y: auto; padding-bottom: 20px; }
.card { flex: none !important; width: 100%; min-height: 140px; transition: min-height 0.4s cubic-bezier(0.25, 1, 0.5, 1); }
.card-content h2 { font-size: 24px; }
.sub-text { font-size: 12px; margin-top: 8px; }
.special-card { min-height: 420px; }
.special-card .default-view { display: none !important; }
.special-card .split-view { opacity: 1 !important; transform: translateY(0) !important; position: relative; flex-direction: column; padding: 10px 0; }
.special-card .card-bg { filter: grayscale(0%); transform: scale(1.05); }
.vertical-divider { width: 80%; height: 1px; margin: 10px 0; background: rgba(255,255,255,0.2); }
.split-item { width: 100%; padding: 10px 0; }
.split-item h3 { font-size: 18px; }
.mini-arrow { opacity: 1; transform: translateX(0); display: inline-block; margin-left: 8px; }
#career-card .mobile-pc-only-mask, #education-card .mobile-pc-only-mask { display: flex; }
}
/* -----------------------------------------------------
修复PC端 Iframe 全屏显示问题
----------------------------------------------------- */
.iframe-container {
position: fixed !important;
top: 0; left: 0; right: 0; bottom: 0;
width: 100vw !important;
height: 100vh !important;
z-index: 100;
background: #020617;
display: flex;
flex-direction: column;
}
.fullscreen-iframe {
flex: 1;
width: 100% !important;
height: 100% !important;
border: none;
display: block;
}
.iframe-back-btn {
position: fixed; top: 20px; left: 20px; z-index: 101;
display: flex; align-items: center; gap: 8px; padding: 12px 24px;
background: rgba(11, 16, 38, 0.95); backdrop-filter: blur(12px);
border: 1px solid rgba(56, 189, 248, 0.3); border-radius: 50px;
color: #38bdf8; font-size: 14px; cursor: pointer; transition: all 0.3s ease;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
@media (max-width: 768px) {
.iframe-back-btn { top: 15px; left: 15px; padding: 8px 16px; font-size: 12px; }
}
/* -----------------------------------------------------
修复:教务系统快速访问按钮组 (之前丢失的样式)
----------------------------------------------------- */
.category-button-group {
position: fixed;
right: 120px;
top: 50%;
transform: translateY(-50%);
z-index: 102; /* 高于返回按钮的101 */
display: flex;
flex-direction: column;
gap: 16px;
pointer-events: auto;
}
.category-btn {
width: 246px;
height: 76px;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 12px;
padding: 12px 20px;
font-size: 16px;
font-weight: 600;
color: #1e293b;
text-align: center;
cursor: pointer;
outline: none;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.category-btn:hover {
background: rgba(56, 189, 248, 0.95);
border-color: rgba(56, 189, 248, 0.5);
color: #ffffff;
transform: translateX(-8px) scale(1.05);
box-shadow: 0 8px 25px rgba(56, 189, 248, 0.3);
}
.category-btn:active {
transform: translateX(-8px) scale(0.98);
}
.category-btn span {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 按钮组 - 平板适配 */
@media (max-width: 1024px) {
.category-button-group {
right: 80px;
gap: 12px;
}
.category-btn {
width: 200px;
height: 64px;
font-size: 14px;
padding: 10px 16px;
}
}
/* 按钮组 - 手机适配 */
@media (max-width: 768px) {
.category-button-group {
position: fixed;
right: 10px;
top: auto;
bottom: 80px;
transform: none;
gap: 10px;
}
.category-btn {
width: 120px;
height: 48px;
font-size: 12px;
padding: 8px 12px;
border-radius: 8px;
}
.category-btn:hover {
transform: translateX(-4px) scale(1.02);
}
}
/* ========= 过渡岗位页面样式 ========= */
:root {
--bg-color: #05070a; --card-bg: #11141a; --accent-cyan: #00f0ff; --accent-blue: #2563eb;
--accent-orange: #ff9d00; --text-main: #ffffff; --text-sub: #94a3b8; --border-color: rgba(255,255,255,0.08);
}
#transition-jobs-page {
background-color: var(--bg-color); height: 100vh; overflow: hidden; position: relative;
}
#transition-jobs-page::before {
content: ''; position: fixed; top: -50%; left: -50%; width: 150%; height: 150%; z-index: -2;
background: radial-gradient(circle at center, rgba(0, 240, 255, 0.1) 0%, transparent 60%); filter: blur(100px); opacity: 0.8; pointer-events: none;
}
#transition-jobs-page::after {
content: ''; position: fixed; bottom: -30%; right: -30%; width: 120%; height: 120%; z-index: -2;
background: radial-gradient(circle at center, rgba(25, 50, 150, 0.2) 0%, transparent 50%); filter: blur(120px); opacity: 0.6; pointer-events: none;
}
.commander-layout {
display: flex; flex-direction: column; height: 100vh;
max-width: 1440px; margin: 0 auto; padding: 20px 40px; box-sizing: border-box; position: relative; z-index: 1;
}
.hud-split-wrapper { display: flex; gap: 20px; margin-bottom: 25px; flex-shrink: 0; }
.hud-panel {
background: rgba(17, 20, 26, 0.7); backdrop-filter: blur(20px);
border-radius: 16px; padding: 20px; border: 1px solid var(--border-color);
box-shadow: 0 20px 40px -10px rgba(0,0,0,0.5); display: flex; flex-direction: column;
}
.hud-left { flex: 3; } .hud-right { flex: 1; border-color: rgba(255, 157, 0, 0.3); background: rgba(20, 15, 10, 0.7); }
.hud-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 1px solid var(--border-color); padding-bottom: 10px; }
.hud-title-group { display: flex; align-items: center; gap: 10px; }
.hud-icon { font-size: 1.2rem; text-shadow: 0 0 10px rgba(255,255,255,0.3); }
.hud-left .hud-icon { color: var(--accent-cyan); } .hud-right .hud-icon { color: var(--accent-orange); }
.hud-title { font-size: 1rem; font-weight: bold; letter-spacing: 1px; color: #fff; }
.hud-subtitle { font-size: 0.7rem; color: #666; margin-left: 6px; font-weight: normal; }
.slots-container { display: grid; gap: 15px; flex: 1; }
.slots-left { grid-template-columns: repeat(3, 1fr); } .slots-right { grid-template-columns: 1fr; }
.slot-module {
height: 120px; background: rgba(0,0,0,0.3); border: 1px dashed #333; border-radius: 8px;
display: flex; flex-direction: column; justify-content: center; align-items: center;
transition: all 0.3s; position: relative; overflow: hidden;
}
.slot-module.empty:hover { border-color: #555; background: rgba(255,255,255,0.02); }
.hud-left .slot-module.filled { background: linear-gradient(160deg, #1e232e, #13161c); border: 1px solid var(--accent-cyan); box-shadow: 0 0 15px rgba(0, 240, 255, 0.1); cursor: pointer; }
.hud-right .slot-module.filled { background: linear-gradient(160deg, #2e251e, #1c1613); border: 1px solid var(--accent-orange); box-shadow: 0 0 15px rgba(255, 157, 0, 0.2); cursor: pointer; }
.slot-remove-mask { position: absolute; inset: 0; background: rgba(0,0,0,0.85); display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s; color: #ff4d4d; }
.slot-module.filled:hover .slot-remove-mask { opacity: 1; }
.slot-content-title { font-size: 0.9rem; font-weight: bold; color: white; margin-bottom: 2px; text-align: center; width: 90%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.slot-content-salary { font-weight: bold; font-size: 0.85rem; font-family: 'Arial', sans-serif; }
.hud-left .slot-content-salary { color: var(--accent-cyan); } .hud-right .slot-content-salary { color: var(--accent-orange); }
.slot-content-company { font-size: 0.7rem; color: var(--text-sub); }
.slot-index { position: absolute; top: 5px; left: 8px; font-size: 1.2rem; font-weight: 900; color: rgba(255,255,255,0.05); pointer-events: none; }
.action-btn {
width: 100%; margin-top: 15px; padding: 10px; border-radius: 6px;
font-weight: 800; font-size: 0.9rem; letter-spacing: 1px; border: none; cursor: pointer;
transition: all 0.3s; display: flex; justify-content: center; align-items: center; gap: 8px;
opacity: 0.5; pointer-events: none; filter: grayscale(100%);
}
.action-btn.active { opacity: 1; pointer-events: auto; filter: grayscale(0%); }
.btn-submit { background: linear-gradient(90deg, var(--accent-blue), var(--accent-cyan)); color: #000; box-shadow: 0 0 15px rgba(0, 240, 255, 0.2); }
.btn-confirm { background: linear-gradient(90deg, #d97706, var(--accent-orange)); color: #000; box-shadow: 0 0 15px rgba(255, 157, 0, 0.2); }
.list-section { flex: 1; overflow-y: auto; padding-right: 5px; }
.list-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; border-left: 4px solid var(--accent-cyan); padding-left: 12px; }
.list-title { font-size: 1.1rem; font-weight: bold; color: #fff; letter-spacing: 1px; }
.filter-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; gap: 15px; position: relative; z-index: 40; }
.city-quick-select { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.city-btn { padding: 6px 16px; border-radius: 4px; font-size: 0.85rem; color: var(--text-sub); background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.1); cursor: pointer; transition: all 0.3s; }
.city-btn.active { background: rgba(0, 240, 255, 0.1); border-color: var(--accent-cyan); color: var(--accent-cyan); font-weight: bold; }
.more-city-btn { display: flex; align-items: center; gap: 6px; padding: 6px 16px; background: linear-gradient(145deg, #2a2e3a, #20232c); border: 1px solid var(--accent-cyan); color: var(--accent-cyan); border-radius: 4px; cursor: pointer; font-size: 0.85rem; font-weight: bold; transition: all 0.3s; }
.type-selector { position: relative; min-width: 140px; }
.type-btn { width: 100%; background: linear-gradient(145deg, #1e232e, #13161c); border: 1px solid rgba(255,255,255,0.1); color: #fff; padding: 8px 15px; border-radius: 8px; font-size: 0.85rem; display: flex; justify-content: space-between; align-items: center; cursor: pointer; transition: all 0.3s; }
.type-dropdown { position: absolute; top: 110%; right: 0; width: 160px; z-index: 50; background: #151820; border: 1px solid var(--border-color); border-radius: 6px; box-shadow: 0 10px 30px rgba(0,0,0,0.8); padding: 5px; display: none; }
.type-dropdown.show { display: block; }
.type-option { padding: 8px 12px; font-size: 0.85rem; color: #999; cursor: pointer; border-radius: 4px; }
.type-option.selected { color: var(--accent-blue); background: rgba(37, 99, 235, 0.1); font-weight: bold; }
.job-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; padding-bottom: 40px; }
.job-card { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 12px; padding: 24px; position: relative; cursor: pointer; transition: all 0.25s ease-out; display: flex; flex-direction: column; justify-content: space-between; min-height: 190px; }
.job-card.disabled { opacity: 0.4; filter: grayscale(100%); background: #0a0c10; border-color: #333; pointer-events: none; cursor: default; }
.card-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.card-icon { width: 44px; height: 44px; border-radius: 8px; background: rgba(255,255,255,0.03); display: flex; align-items: center; justify-content: center; font-size: 1.2rem; color: var(--text-sub); }
.card-salary { color: var(--accent-cyan); font-weight: bold; font-size: 1rem; }
.card-title { font-size: 1.1rem; font-weight: bold; color: #fff; margin-bottom: 6px; }
.card-company { font-size: 0.85rem; color: var(--text-sub); display: flex; align-items: center; gap: 6px; }
.card-tags { margin-top: 12px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.tag { font-size: 0.75rem; padding: 3px 8px; border-radius: 4px; background: rgba(255,255,255,0.03); color: #888; border: 1px solid rgba(255,255,255,0.02); }
.type-badge { display: inline-block; font-size: 0.75rem; padding: 3px 8px; border-radius: 4px; margin-right: 6px; font-weight: bold; letter-spacing: 0.5px; }
.type-produce { background: rgba(37, 99, 235, 0.15); color: #60a5fa; border: 1px solid rgba(37, 99, 235, 0.3); }
.type-service { background: rgba(0, 255, 157, 0.1); color: #34d399; border: 1px solid rgba(0, 255, 157, 0.3); }
.check-mark { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.6); color: var(--accent-cyan); font-size: 2rem; opacity: 0; transition: all 0.3s; pointer-events: none; z-index: 10; }
.job-card.disabled .check-mark { opacity: 1; }
.quota-badge { position: absolute; top: 0; right: 0; background: rgba(255, 157, 0, 0.15); border-bottom-left-radius: 12px; padding: 4px 10px; border-left: 1px solid rgba(255, 157, 0, 0.3); border-bottom: 1px solid rgba(255, 157, 0, 0.3); font-size: 0.75rem; color: var(--accent-orange); font-weight: bold; letter-spacing: 0.5px; }
.btn-detail { width: 100%; padding: 8px 0; border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.03); color: var(--text-sub); font-size: 0.8rem; border-radius: 6px; cursor: pointer; transition: all 0.2s; margin-top: auto; display: flex; align-items: center; justify-content: center; gap: 6px; }
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.85); backdrop-filter: blur(8px); z-index: 100; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.3s; }
.modal-overlay.show { opacity: 1; pointer-events: auto; }
.detail-modal { width: 1000px; max-width: 95vw; height: 80vh; background: #11141a; border: 1px solid var(--border-color); border-radius: 16px; box-shadow: 0 0 50px rgba(0,0,0,0.9); display: flex; flex-direction: column; overflow: hidden; position: relative; }
.detail-header { padding: 24px 30px; background: linear-gradient(90deg, rgba(0, 240, 255, 0.05), transparent); border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: flex-start; }
.detail-title-area { flex: 1; }
.detail-job-title { font-size: 1.8rem; font-weight: bold; color: white; margin-bottom: 8px; display: flex; align-items: center; gap: 15px; flex-wrap: wrap; }
.detail-salary-tag { font-size: 1.2rem; color: var(--accent-cyan); font-family: 'Arial', sans-serif; background: rgba(0, 240, 255, 0.1); padding: 2px 12px; border-radius: 4px; border: 1px solid rgba(0, 240, 255, 0.3); }
.detail-company-name { font-size: 1rem; color: var(--text-sub); display: flex; align-items: center; gap: 8px; }
.detail-body { display: flex; flex: 1; overflow: hidden; }
.detail-sidebar { width: 320px; background: rgba(0,0,0,0.2); border-right: 1px solid var(--border-color); padding: 25px; overflow-y: auto; display: flex; flex-direction: column; gap: 20px; }
.detail-content { flex: 1; padding: 30px; overflow-y: auto; }
.param-group { background: rgba(255,255,255,0.03); padding: 15px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.05); }
.param-label { color: #666; font-size: 0.8rem; margin-bottom: 5px; text-transform: uppercase; }
.param-value { color: white; font-weight: bold; font-size: 0.95rem; display: flex; align-items: center; gap: 8px; }
.section-title { font-size: 1.1rem; font-weight: bold; color: white; margin-bottom: 15px; padding-left: 10px; border-left: 3px solid var(--accent-cyan); display: flex; align-items: center; gap: 10px; }
.req-list { list-style: none; padding: 0; margin-bottom: 30px; }
.req-item { position: relative; padding-left: 20px; margin-bottom: 10px; color: #ccc; line-height: 1.6; font-size: 0.95rem; }
.req-item::before { content: '▹'; position: absolute; left: 0; color: var(--accent-cyan); }
.welfare-grid { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 30px; }
.welfare-tag { background: rgba(37, 99, 235, 0.1); border: 1px solid rgba(37, 99, 235, 0.3); color: #93c5fd; padding: 6px 12px; border-radius: 20px; font-size: 0.85rem; }
.company-intro { color: #999; line-height: 1.7; font-size: 0.9rem; text-align: justify; }
.modal-close-btn { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(255,255,255,0.1); color: white; cursor: pointer; transition: all 0.2s; }
.city-modal { width: 900px; max-width: 90vw; height: 600px; background: #1a1e26; border: 1px solid var(--border-color); border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.8); display: flex; flex-direction: column; }
.modal-header { padding: 15px 25px; border-bottom: 1px solid #333; display: flex; justify-content: space-between; align-items: center; background: #151820; }
.modal-title { font-size: 1.1rem; font-weight: bold; color: white; letter-spacing: 1px; }
.modal-body { display: flex; flex: 1; overflow: hidden; }
.region-sidebar { width: 160px; background: #111; border-right: 1px solid #333; overflow-y: auto; }
.region-item { padding: 15px 20px; color: #888; cursor: pointer; border-left: 3px solid transparent; transition: all 0.2s; }
.region-item.active { background: #222; color: var(--accent-cyan); border-left-color: var(--accent-cyan); font-weight: bold; }
.city-grid-area { flex: 1; padding: 25px; overflow-y: auto; background: #1a1e26; }
.city-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 12px; }
.city-option { padding: 8px; text-align: center; border-radius: 4px; background: #252a33; cursor: pointer; color: #ccc; font-size: 0.9rem; transition: all 0.2s; }
@media (max-width: 768px) {
#transition-jobs-page {
height: auto !important;
min-height: 100vh;
overflow-y: auto !important;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
.commander-layout {
height: auto !important;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 10px;
padding-top: 80px !important;
overflow: visible !important;
}
.hud-split-wrapper {
flex-direction: column;
gap: 15px;
margin-bottom: 15px;
height: auto;
flex-shrink: 0;
}
.hud-panel { padding: 15px; }
.slots-container.slots-left { grid-template-columns: repeat(3, 1fr); gap: 8px; }
.slot-module { height: 90px; }
.slot-content-title { font-size: 0.7rem; }
.slot-content-salary { font-size: 0.7rem; }
.slot-content-company { display: none; }
.list-section {
padding-right: 0;
overflow: visible !important;
height: auto !important;
flex: none;
}
.filter-bar {
flex-direction: column;
align-items: flex-start;
gap: 10px;
margin-bottom: 15px;
}
.city-quick-select { width: 100%; overflow-x: auto; white-space: nowrap; padding-bottom: 5px; flex-wrap: nowrap; }
.city-btn { flex-shrink: 0; }
.type-selector { width: 100%; }
.job-grid {
grid-template-columns: 1fr;
gap: 15px;
padding-bottom: 40px;
}
.job-card { padding: 15px; min-height: auto; }
.card-salary {
margin-top: 22px;
position: relative;
z-index: 2;
}
.detail-modal {
height: 85vh !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch;
display: flex;
flex-direction: column;
}
.detail-body {
flex: 1;
flex-direction: column !important;
overflow-y: auto !important;
overflow-x: hidden;
height: auto !important;
}
.detail-sidebar {
width: 100% !important;
height: auto !important;
overflow: visible !important;
max-height: none !important;
border-right: none;
border-bottom: 1px solid var(--border-color);
padding: 15px;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
flex-shrink: 0;
}
.detail-content {
flex: 1;
height: auto !important;
overflow: visible !important;
padding: 15px;
}
.param-group { flex: 1; min-width: 45%; padding: 10px; }
.city-modal { height: 90vh; }
.modal-body { flex-direction: column; }
.region-sidebar { width: 100%; height: 120px; border-right: none; border-bottom: 1px solid #333; display: flex; overflow-x: auto; white-space: nowrap; }
.region-item { padding: 10px 15px; border-left: none; border-bottom: 3px solid transparent; }
.region-item.active { border-left-color: transparent; border-bottom-color: var(--accent-cyan); }
.city-grid { grid-template-columns: repeat(3, 1fr); }
}
</style>
</head>
<body>
<body>
<div id="home-wrapper">
<div class="bg-glow"></div>
<div id="home-container" class="container">
<header class="glass-header">
<div class="hidden md:block flex-1"></div>
<div class="
flex flex-col justify-center
text-left md:text-center
flex-1 md:flex-none
md:absolute md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2
z-20 pointer-events-none
">
<h1 class="text-gradient font-bold" style="margin-bottom: 4px;">
<span class="text-base md:text-3xl tracking-widest">多多畅职大专生就业服务平台</span>
</h1>
<p class="text-glow font-bold block" style="margin: 0;">
<span class="text-[10px] md:text-lg tracking-[2px] md:tracking-[4px] opacity-90">江苏大学生就业服务中心</span>
</p>
</div>
<div class="flex-none flex justify-end items-center gap-2 md:gap-4 z-30">
<span id="user-info" class="hidden md:inline" style="font-size: 14px; color: rgba(255, 255, 255, 0.7);"></span>
<button onclick="AuthHelper.logout()" style="
background: rgba(255, 59, 48, 0.2);
border: 1px solid rgba(255, 59, 48, 0.5);
color: #ff3b30;
padding: 6px 12px;
border-radius: 20px;
cursor: pointer;
font-size: 12px;
transition: all 0.3s;
backdrop-filter: blur(10px);
display: flex;
align-items: center;
gap: 4px;
white-space: nowrap;
" class="md:px-4 md:py-2 md:text-sm">
<i class="fa-solid fa-right-from-bracket"></i>
<span class="hidden md:inline">退出登录</span>
</button>
</div>
</header>
<div class="card-wrapper">
<div class="card special-card">
<div class="card-bg" style="background-image: url('https://images.unsplash.com/photo-1497366216548-37526070297c?q=80&w=2301&auto=format&fit=crop');"></div>
<div class="card-overlay"></div>
<div class="card-content">
<div class="default-view">
<h2>企业资源</h2>
<span class="sub-text">优质岗位 · 多样选择</span>
</div>
<div class="split-view">
<a href="javascript:void(0)" id="referral-split-card" class="split-item">
<div class="panel-inner">
<h3>合作企业名录</h3>
<p>校友直通车</p>
<div class="mini-arrow"></div>
</div>
</a>
<div class="vertical-divider"></div>
<a href="javascript:void(0)" id="transition-split-card" class="split-item">
<div class="panel-inner">
<h3>过渡岗位</h3>
<p>短期 & 实习</p>
<div class="mini-arrow"></div>
</div>
</a>
<div class="vertical-divider"></div>
<a href="javascript:void(0)" id="high-salary-split-card" class="split-item">
<div class="panel-inner">
<h3>高薪岗位</h3>
<p>挑战高年薪</p>
<div class="mini-arrow"></div>
</div>
</a>
</div>
</div>
</div>
<a href="javascript:void(0)" id="career-card" class="card">
<div class="mobile-pc-only-mask">
<i class="fa-solid fa-desktop"></i>
<p>请在 PC 端使用</p>
<span>就业规划功能仅支持电脑访问</span>
</div>
<div class="card-bg" style="background-image: url('https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?q=80&w=2070&auto=format&fit=crop');"></div>
<div class="card-overlay"></div>
<div class="card-content">
<h2>就业规划</h2>
<span class="sub-text">生涯指导 · 前景分析</span>
</div>
</a>
<a href="javascript:void(0)" id="education-card" class="card">
<div class="mobile-pc-only-mask">
<i class="fa-solid fa-desktop"></i>
<p>请在 PC 端使用</p>
<span>教务系统仅支持电脑访问</span>
</div>
<div class="card-bg" style="background-image: url('https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?q=80&w=2340&auto=format&fit=crop');"></div>
<div class="card-overlay"></div>
<div class="card-content">
<h2>教务系统</h2>
<span class="sub-text">技能提升 · 在线课程</span>
</div>
</a>
</div>
</div>
</div>
<div id="education-iframe" class="iframe-container hidden">
<button class="iframe-back-btn" onclick="backToHomeFromIframe()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
<span>返回首页</span>
</button>
<iframe
id="education-frame"
src="https://duoduochangzhi.cn/"
frameborder="0"
allowfullscreen
class="fullscreen-iframe"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-top-navigation allow-modals"
></iframe>
<div id="education-category-buttons" class="category-button-group">
<button class="category-btn" data-category="智能制造" data-url="http://146.56.220.156:1534"><span>智能制造</span></button>
<button class="category-btn" data-category="智能开发" data-url="http://146.56.220.156:1535"><span>智能开发</span></button>
<button class="category-btn" data-category="大健康" data-url="http://146.56.220.156:1533"><span>大健康</span></button>
<button class="category-btn" data-category="财经商贸与设计" data-url="http://146.56.220.156:1536"><span>财经商贸与设计</span></button>
</div>
</div>
<div id="career-iframe" class="iframe-container hidden">
<button class="iframe-back-btn" onclick="backToHomeFromIframe()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
<span>返回首页</span>
</button>
<div id="career-warning-banner" style="position: fixed; top: 70px; left: 50%; transform: translateX(-50%); z-index: 101; background: rgba(255, 152, 0, 0.95); backdrop-filter: blur(12px); border: 1px solid rgba(255, 193, 7, 0.5); border-radius: 12px; padding: 12px 24px; color: #fff; font-size: 13px; box-shadow: 0 4px 20px rgba(255, 152, 0, 0.3); max-width: 90%; text-align: center; display: flex; align-items: center; gap: 12px; opacity: 1; transition: opacity 0.5s ease-out;">
<i class="fa-solid fa-circle-info" style="font-size: 16px;"></i>
<div style="line-height: 1.5;">
<strong>温馨提示:</strong>该就业规划系统有访问频率限制5分钟内限访问1次<br>页面显示"访问受限"请稍后重试。
</div>
</div>
<iframe id="career-frame" src="http://192.168.2.10:5173/" frameborder="0" allowfullscreen class="fullscreen-iframe"></iframe>
</div>
<div id="transition-jobs-page" class="fixed inset-0 hidden" style="z-index: 100;">
<button class="iframe-back-btn" onclick="backToHomeFromTransition()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
<span>返回首页</span>
</button>
<div class="commander-layout">
<div class="hud-split-wrapper">
<div class="hud-panel hud-left">
<div class="hud-header">
<div class="hud-title-group">
<i class="fa-solid fa-cube hud-icon"></i>
<div>
<div class="hud-title">意向过渡岗位</div>
<span class="hud-subtitle hidden md:inline">INTENDED POSITIONS</span>
</div>
</div>
<div class="text-gray-500 font-mono text-sm">
已选: <span id="count-left" class="text-cyan-400 font-bold text-lg">0</span> / 3
</div>
</div>
<div class="slots-container slots-left" id="slots-left"></div>
<button id="btn-submit-intent" class="action-btn btn-submit">
提交清单 <i class="fa-solid fa-cloud-arrow-up"></i>
</button>
</div>
<div class="hud-panel hud-right">
<div class="hud-header">
<div class="hud-title-group">
<i class="fa-solid fa-star hud-icon"></i>
<div>
<div class="hud-title">确认锁定</div>
<span class="hud-subtitle hidden md:inline">FINAL LOCK</span>
</div>
</div>
</div>
<div class="slots-container slots-right" id="slots-right"></div>
<button id="btn-confirm-final" class="action-btn btn-confirm">
确认锁定 <i class="fa-solid fa-lock"></i>
</button>
</div>
</div>
<section class="list-section custom-scrollbar">
<div class="list-header">
<div class="list-title">资源库</div>
</div>
<div class="filter-bar">
<div class="city-quick-select" id="city-quick-select"></div>
<div class="type-selector" id="type-selector">
<button class="type-btn" onclick="toggleTypeDropdown()">
<span id="current-type">全部类型</span>
<i class="fa-solid fa-chevron-down text-xs text-gray-500"></i>
</button>
<div class="type-dropdown" id="type-dropdown"></div>
</div>
</div>
<div class="job-grid" id="job-grid"></div>
</section>
</div>
<div class="modal-overlay" id="city-modal-overlay">
<div class="city-modal">
<div class="modal-header">
<div class="modal-title">选择城市</div>
<div class="modal-close text-gray-400 hover:text-white cursor-pointer" onclick="closeCityModal()"><i class="fa-solid fa-xmark text-xl"></i></div>
</div>
<div class="modal-body">
<ul class="region-sidebar" id="region-sidebar"></ul>
<div class="city-grid-area">
<div class="city-grid" id="city-grid"></div>
</div>
</div>
</div>
</div>
<div class="modal-overlay" id="detail-modal-overlay">
<div class="detail-modal">
<div class="detail-header">
<div class="detail-title-area">
<div class="detail-job-title">
<span id="detail-title">岗位名称</span>
<span id="detail-salary" class="detail-salary-tag">--</span>
</div>
<div class="detail-company-name">
<i class="fa-regular fa-building"></i> <span id="detail-company">--</span>
<span class="text-gray-600 mx-2">|</span>
<span id="detail-type" class="text-blue-400">--</span>
</div>
</div>
<div class="modal-close-btn" onclick="closeDetailModal()"><i class="fa-solid fa-xmark"></i></div>
</div>
<div class="detail-body">
<div class="detail-sidebar">
<div class="param-group">
<div class="param-label">到岗时间</div>
<div class="param-value"><i class="fa-regular fa-calendar param-icon"></i> <span id="detail-start-date">--</span></div>
</div>
<div class="param-group">
<div class="param-label">工作周期</div>
<div class="param-value"><i class="fa-solid fa-rotate param-icon"></i> <span id="detail-duration">--</span></div>
</div>
<div class="param-group">
<div class="param-label">地点</div>
<div class="param-value"><i class="fa-solid fa-location-dot param-icon"></i> <span id="detail-location">--</span></div>
</div>
<div class="param-group">
<div class="param-label">吃住</div>
<div class="param-value"><i class="fa-solid fa-utensils param-icon"></i> <span id="detail-roomboard">--</span></div>
</div>
<div class="param-group">
<div class="param-label">名额</div>
<div class="param-value text-orange-500"><i class="fa-solid fa-users param-icon text-orange-500"></i> <span id="detail-quota">--</span></div>
</div>
</div>
<div class="detail-content">
<div class="section-title"><i class="fa-solid fa-list-check"></i> 岗位要求</div>
<ul class="req-list" id="detail-requirements"></ul>
<div class="section-title"><i class="fa-solid fa-gift"></i> 福利待遇</div>
<div class="welfare-grid" id="detail-benefits"></div>
<div class="section-title"><i class="fa-solid fa-building"></i> 企业名称</div>
<div class="company-name-display" id="detail-company-name-display" style="font-size: 0.95rem; color: #ccc; margin-bottom: 25px; line-height: 1.6;">
<span id="detail-company-name-text">--</span>
</div>
<div class="section-title"><i class="fa-regular fa-building"></i> 企业介绍</div>
<div class="company-intro" id="detail-company-intro"></div>
</div>
</div>
</div>
</div>
</div>
<!-- ============================================
3D内推平台部分
============================================ -->
<div id="app-container" class="fixed inset-0 hidden" style="z-index: 10; background: radial-gradient(circle at 50% 30%, #1e293b 0%, #0b1026 100%);">
<div id="speed-lines"></div>
<div id="cloud-fog"></div>
<div id="ui-layer">
<h1 class="v1-title">多多畅职合作企业名录</h1>
<p class="v1-subtitle">链接人才与企业</p>
</div>
<div class="instruction-hint">点击地球</div>
<div id="canvas-container"></div>
<div id="map-interface">
<header class="glass-header fixed top-0 w-full h-16 flex items-center justify-between px-4 md:px-8 z-50">
<div class="flex items-center gap-4 flex-shrink-0">
<button id="map-back-btn" class="hidden items-center gap-1 md:gap-2 text-gray-400 hover:text-white transition" onclick="window.resetMapToChina()">
<svg class="w-4 h-4 md:w-5 md:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
<span class="text-xs md:text-sm">返回全国</span>
</button>
<div id="map-logo-area" class="flex items-center gap-2 cursor-pointer">
<img src="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/duoduo_logo/LOGO_1097x300.png" alt="多多畅职" class="h-6 md:h-8 w-auto object-contain">
<div class="text-white font-bold text-xs md:text-sm tracking-wide hidden sm:block">多多畅职企业内推平台</div>
<span class="text-gray-400 text-xs ml-2 hidden lg:inline">点击返回首页</span>
</div>
</div>
<div class="relative w-0 md:w-1/3 overflow-hidden md:overflow-visible">
<input type="text" id="search-input" placeholder="搜索省份、城市、企业..." class="search-input w-full py-2 px-5 rounded-full text-center text-sm placeholder-gray-400">
</div>
<div class="flex items-center gap-2 text-white text-xs md:text-sm flex-shrink-0">
<span class="text-gray-400 hidden sm:inline">当前区域:</span>
<span id="top-region-name" class="text-cyan-300 font-bold">全国</span>
</div>
</header>
<div class="md:hidden fixed top-16 left-0 right-0 px-4 py-2 z-40" style="background: rgba(11, 16, 38, 0.95); backdrop-filter: blur(12px);">
<input type="text" id="search-input-mobile" placeholder="搜索省份、城市、企业..." class="search-input w-full py-2 px-4 rounded-full text-sm placeholder-gray-400">
</div>
<main class="w-full h-full relative">
<div id="breadcrumb-container" class="absolute left-4 md:left-8 text-gray-400 text-xs md:text-sm z-40 hidden">
<span class="hover:text-white cursor-pointer transition" onclick="resetMapToChina()">全国</span>
<span class="mx-2 text-gray-600">/</span>
<span class="text-cyan-400 font-bold">江苏省</span>
</div>
<div id="map-chart" style="width: 100%; min-height: 400px;"></div>
</main>
</div>
<div id="list-interface">
<header class="glass-header fixed top-0 w-full h-16 flex items-center justify-between px-4 md:px-8 z-50">
<button onclick="backToMap()" class="flex items-center gap-1 md:gap-2 text-gray-400 hover:text-white transition flex-shrink-0">
<svg class="w-4 h-4 md:w-5 md:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
<span class="text-xs md:text-sm">返回地图</span>
</button>
<h2 id="list-city-title" class="text-sm md:text-lg font-bold text-white tracking-tight">苏州市 · 企业名录</h2>
<div class="w-12 md:w-20 flex-shrink-0"></div>
</header>
<div class="flex h-full pt-16">
<aside class="w-64 h-full border-r border-white/10 p-6 hidden md:block">
<div class="mb-8">
<h3 class="text-cyan-400 text-xs font-bold uppercase tracking-widest mb-4">筛选 Filter</h3>
<div class="space-y-4">
<div>
<label class="text-gray-500 text-xs mb-2 block">所属行业</label>
<div class="flex flex-wrap gap-2">
<span class="tag-badge cursor-pointer hover:bg-blue-500 hover:text-white transition">互联网</span>
<span class="tag-badge cursor-pointer hover:bg-blue-500 hover:text-white transition">金融</span>
<span class="tag-badge cursor-pointer hover:bg-blue-500 hover:text-white transition">硬科技</span>
</div>
</div>
<div>
<label class="text-gray-500 text-xs mb-2 block">企业规模</label>
<div class="space-y-2 text-gray-400 text-sm">
<div class="flex items-center gap-2"><input type="checkbox" class="accent-cyan-400"> <span>上市企业</span></div>
<div class="flex items-center gap-2"><input type="checkbox" class="accent-cyan-400"> <span>独角兽</span></div>
<div class="flex items-center gap-2"><input type="checkbox" class="accent-cyan-400"> <span>国企/央企</span></div>
</div>
</div>
</div>
</div>
<div class="p-4 bg-white/5 rounded-lg border border-white/5">
<div class="text-gray-400 text-xs mb-1">当前城市收录</div>
<div class="text-2xl font-bold text-white"><span id="company-count">124</span> <span class="text-sm text-gray-500 font-normal">家企业</span></div>
<div class="text-2xl font-bold text-white mt-2"><span id="job-count">892</span> <span class="text-sm text-gray-500 font-normal">个岗位</span></div>
</div>
</aside>
<main class="flex-1 h-full overflow-y-auto p-8">
<div id="cards-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 pb-20"></div>
</main>
</div>
</div>
<div id="detail-interface" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 7; display: none; opacity: 0; background: #050b14;">
<header class="glass-header fixed top-0 w-full h-16 flex items-center justify-between px-4 md:px-8 z-50">
<button onclick="backToList()" class="flex items-center gap-1 md:gap-2 text-cyan-400 hover:text-white transition group">
<span class="group-hover:-translate-x-1 transition"></span>
<span class="text-xs md:text-sm">返回企业列表</span>
</button>
<div class="w-12 md:w-20"></div>
</header>
<div class="h-full pt-16 overflow-y-auto md:overflow-hidden md:flex">
<aside class="w-full md:w-1/3 md:h-full md:overflow-y-auto border-b md:border-b-0 md:border-r border-white/10 p-4 md:p-8 bg-black/20">
<div class="flex flex-col items-center mb-6 md:mb-8">
<h1 id="d-name" class="text-xl md:text-3xl font-bold text-white text-center mb-2"></h1>
<div id="d-tags" class="flex flex-wrap gap-2 justify-center"></div>
</div>
<div class="space-y-4 md:space-y-6">
<div>
<h3 class="text-cyan-500 text-xs font-bold uppercase mb-2">企业简介 About</h3>
<p id="d-intro" class="text-gray-300 text-xs md:text-sm leading-relaxed text-justify"></p>
</div>
<div class="bg-gradient-to-br from-cyan-900/30 to-transparent border border-cyan-500/20 p-3 md:p-4 rounded-lg">
<h3 class="text-cyan-400 text-xs md:text-sm font-bold mb-2 flex items-center">🔥 推荐理由 Highlight</h3>
<p id="d-reason" class="text-gray-400 text-xs leading-relaxed"></p>
</div>
<div>
<h3 class="text-cyan-500 text-xs font-bold uppercase mb-2">地区 Location</h3>
<p id="d-region" class="text-gray-400 text-xs md:text-sm whitespace-pre-line"></p>
</div>
<div>
<h3 class="text-cyan-500 text-xs font-bold uppercase mb-2">企业风采 Gallery</h3>
<div id="d-gallery" class="grid grid-cols-3 gap-2"></div>
</div>
</div>
</aside>
<main class="w-full md:flex-1 md:h-full md:overflow-y-auto p-4 md:p-8 bg-gradient-to-br from-gray-900 to-black">
<div class="mb-4 md:mb-6">
<h2 class="text-lg md:text-2xl font-bold text-white mb-1">业务板块 & 内推岗位</h2>
<span class="text-gray-500 text-xs md:text-sm">Business Segments & Opportunities</span>
</div>
<div id="d-segments" class="grid grid-cols-1 gap-4 md:gap-6"></div>
<div class="h-20"></div>
</main>
</div>
</div>
<div id="image-lightbox" class="fixed inset-0 z-[100] bg-black/95 backdrop-blur-sm hidden items-center justify-center">
<button id="lightbox-close" class="absolute top-4 right-4 md:top-8 md:right-8 w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-white hover:text-cyan-400 transition text-2xl md:text-3xl z-10"><i class="fa-solid fa-xmark"></i></button>
<button id="lightbox-prev" class="absolute left-2 md:left-8 top-1/2 -translate-y-1/2 w-10 h-10 md:w-14 md:h-14 flex items-center justify-center text-white hover:text-cyan-400 transition text-2xl md:text-4xl z-10"><i class="fa-solid fa-chevron-left"></i></button>
<button id="lightbox-next" class="absolute right-2 md:right-8 top-1/2 -translate-y-1/2 w-10 h-10 md:w-14 md:h-14 flex items-center justify-center text-white hover:text-cyan-400 transition text-2xl md:text-4xl z-10"><i class="fa-solid fa-chevron-right"></i></button>
<div class="relative w-full h-full flex items-center justify-center p-4 md:p-16">
<img id="lightbox-image" src="" alt="" class="max-w-full max-h-full object-contain">
</div>
<div id="lightbox-counter" class="absolute bottom-4 md:bottom-8 left-1/2 -translate-x-1/2 text-white text-sm md:text-base bg-black/50 px-4 py-2 rounded-full"><span id="lightbox-current">1</span> / <span id="lightbox-total">1</span></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"></script>
<script>
window.appInstance = null;
// 【新增】手机端点击展开特殊卡片逻辑
window.toggleMobileSpecialCard = function(element) {
// 只有在移动端屏幕下生效
if (window.innerWidth <= 768) {
element.classList.toggle('mobile-expanded');
}
}
// 3D内推平台点击逻辑
document.getElementById('referral-split-card').addEventListener('click', function(e) {
e.preventDefault(); e.stopPropagation();
document.getElementById('home-wrapper').classList.add('hidden');
document.getElementById('app-container').classList.remove('hidden');
const tryStartApp = () => {
if (window.appInstance && typeof window.appInstance.switchToApp === 'function') {
window.appInstance.switchToApp();
} else { setTimeout(tryStartApp, 50); }
};
tryStartApp();
});
// 教务系统点击
document.getElementById('education-card').addEventListener('click', function(e) {
// 移动端点击被遮罩层拦截此处不需要额外处理除非需要JS逻辑
if (window.innerWidth > 768) {
e.preventDefault();
document.getElementById('home-wrapper').classList.add('hidden');
document.getElementById('education-iframe').classList.remove('hidden');
// 首次访问提示(应对浏览器可能拦截弹窗)
const hasShownPopupTip = sessionStorage.getItem('education_popup_tip_shown');
if (!hasShownPopupTip && window.innerWidth > 768) {
setTimeout(() => {
alert('提示:教务系统的微信登录回调将在新标签页打开,请允许浏览器弹窗。');
sessionStorage.setItem('education_popup_tip_shown', 'true');
}, 1000);
}
}
});
// ========== iframe监控代码可选调试用 ==========
(function() {
const educationFrame = document.getElementById('education-frame');
if (!educationFrame) return;
// 记录iframe加载事件
educationFrame.addEventListener('load', function() {
try {
const currentSrc = educationFrame.contentWindow.location.href;
console.log('[教务系统] iframe已加载:', currentSrc);
} catch (e) {
// 跨域访问被阻止是正常的
console.log('[教务系统] iframe已加载跨域内容');
}
});
// 首次加载提示
educationFrame.addEventListener('load', function() {
console.log('[教务系统] 提示:微信登录回调将在新标签页中打开');
}, { once: true });
})();
// ========== 监控代码结束 ==========
// 就业规划点击
document.getElementById('career-card').addEventListener('click', function(e) {
if (window.innerWidth > 768) {
e.preventDefault();
const userInfo = AuthHelper.getUserInfo();
if (!userInfo || !userInfo.professional_category_code) {
showProfessionalCategoryPrompt();
return;
}
const careerIframe = document.getElementById('career-frame');
const baseUrl = 'http://146.56.220.156:1448/';
const code = userInfo.professional_category_code;
careerIframe.src = `${baseUrl}?code=${code}`;
document.getElementById('home-wrapper').classList.add('hidden');
document.getElementById('career-iframe').classList.remove('hidden');
const warningBanner = document.getElementById('career-warning-banner');
warningBanner.style.opacity = '1'; warningBanner.style.display = 'flex';
setTimeout(() => {
warningBanner.style.opacity = '0';
setTimeout(() => { warningBanner.style.display = 'none'; }, 500);
}, 3000);
}
});
// 专业大类相关逻辑
let professionalCategoriesData = [];
async function loadProfessionalCategoriesForModal() {
try {
const response = await fetch('/专业大类.json');
professionalCategoriesData = await response.json();
const selectElement = document.getElementById('modal-professional-category');
if (selectElement && selectElement.options.length === 1) {
professionalCategoriesData.forEach(category => {
const option = document.createElement('option');
option.value = category.大类代码; option.textContent = category.大类名称;
selectElement.appendChild(option);
});
}
} catch (error) { console.error('加载专业大类失败:', error); }
}
function showProfessionalCategoryPrompt() {
const modal = document.getElementById('professional-category-modal');
modal.classList.remove('hidden');
if (professionalCategoriesData.length === 0) { loadProfessionalCategoriesForModal(); }
}
function closeProfessionalCategoryModal() { document.getElementById('professional-category-modal').classList.add('hidden'); }
async function saveProfessionalCategory() {
const selectElement = document.getElementById('modal-professional-category');
const professionalCategoryCode = selectElement.value;
if (!professionalCategoryCode) { alert('请先选择专业大类'); return; }
const category = professionalCategoriesData.find(c => c.大类代码 === professionalCategoryCode);
try {
const success = await AuthHelper.updateProfile({
professional_category_code: professionalCategoryCode,
professional_category: category.大类名称
});
if (success) {
closeProfessionalCategoryModal();
const careerIframe = document.getElementById('career-frame');
careerIframe.src = `http://146.56.220.156:1448/?code=${professionalCategoryCode}`;
document.getElementById('home-wrapper').classList.add('hidden');
document.getElementById('career-iframe').classList.remove('hidden');
} else { alert('保存失败,请重试'); }
} catch (error) { console.error('保存专业大类失败:', error); alert('保存失败,请检查网络连接'); }
}
document.addEventListener('DOMContentLoaded', function() { loadProfessionalCategoriesForModal(); });
window.backToHomeFromIframe = function() {
document.getElementById('education-iframe').classList.add('hidden');
document.getElementById('career-iframe').classList.add('hidden');
document.getElementById('home-wrapper').classList.remove('hidden');
const warningBanner = document.getElementById('career-warning-banner');
if (warningBanner) { warningBanner.style.opacity = '1'; warningBanner.style.display = 'flex'; }
};
// 过渡岗位点击
document.getElementById('transition-split-card').addEventListener('click', function(e) {
e.preventDefault(); e.stopPropagation();
document.getElementById('home-wrapper').classList.add('hidden');
document.getElementById('transition-jobs-page').classList.remove('hidden');
});
// 高薪岗位点击
document.getElementById('high-salary-split-card').addEventListener('click', function(e) {
e.preventDefault(); e.stopPropagation();
window.location.href = 'high.html';
});
window.backToHomeFromTransition = function() {
document.getElementById('transition-jobs-page').classList.add('hidden');
document.getElementById('home-wrapper').classList.remove('hidden');
};
window.backToHome = function() {
const appContainer = document.getElementById('app-container');
const homeWrapper = document.getElementById('home-wrapper');
appContainer.classList.add('hidden');
homeWrapper.classList.remove('hidden');
if (window.appInstance) { window.appInstance.is2DInitialized = false; }
};
// 教务系统快速访问按钮点击处理
(function() {
const categoryUrls = {
'智能制造': 'http://146.56.220.156:1534',
'智能开发': 'http://146.56.220.156:1535',
'大健康': 'http://146.56.220.156:1533',
'财经商贸与设计': 'http://146.56.220.156:1536'
};
document.addEventListener('click', function(e) {
const btn = e.target.closest('.category-btn');
if (!btn) return;
const category = btn.getAttribute('data-category');
const url = categoryUrls[category];
if (!url || url.includes('example.com')) {
alert(`"${category}"功能即将开放,敬请期待!`); return;
}
window.open(url, '_blank', 'noopener,noreferrer');
});
function initCategoryButtons() {
const buttons = document.querySelectorAll('.category-btn');
buttons.forEach(btn => {
const category = btn.getAttribute('data-category');
if (categoryUrls[category]) { btn.setAttribute('data-url', categoryUrls[category]); }
});
}
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCategoryButtons); } else { initCategoryButtons(); }
})();
</script>
<script>
(function() {
const regionData = {
"热门城市": ["全部", "北京市", "上海市", "广州市", "深圳市", "成都市", "杭州市", "武汉市", "苏州市", "南京市", "重庆市", "天津市", "西安市"],
"直辖市": ["北京市", "上海市", "天津市", "重庆市"],
"广东省": ["广州市", "深圳市", "珠海市", "汕头市", "佛山市", "韶关市", "湛江市", "肇庆市", "江门市", "茂名市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市", "东莞市", "中山市", "潮州市", "揭阳市", "云浮市"],
"江苏省": ["南京市", "无锡市", "徐州市", "常州市", "苏州市", "南通市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市"],
"浙江省": ["杭州市", "宁波市", "温州市", "嘉兴市", "湖州市", "绍兴市", "金华市", "衢州市", "舟山市", "台州市", "丽水市"],
"山东省": ["济南市", "青岛市", "淄博市", "枣庄市", "东营市", "烟台市", "潍坊市", "济宁市", "泰安市", "威海市", "日照市", "临沂市", "德州市", "聊城市", "滨州市", "菏泽市"],
"四川省": ["成都市", "自贡市", "攀枝花市", "泸州市", "德阳市", "绵阳市", "广元市", "遂宁市", "内江市", "乐山市", "南充市", "眉山市", "宜宾市", "广安市", "达州市", "雅安市", "巴中市", "资阳市"],
"河南省": ["郑州市", "开封市", "洛阳市", "平顶山市", "安阳市", "鹤壁市", "新乡市", "焦作市", "濮阳市", "许昌市", "漯河市", "三门峡市", "南阳市", "商丘市", "信阳市", "周口市", "驻马店市"],
"湖北省": ["武汉市", "黄石市", "十堰市", "宜昌市", "襄阳市", "鄂州市", "荆门市", "孝感市", "荆州市", "黄冈市", "咸宁市", "随州市", "恩施州"],
"湖南省": ["长沙市", "株洲市", "湘潭市", "衡阳市", "邵阳市", "岳阳市", "常德市", "张家界市", "益阳市", "郴州市", "永州市", "怀化市", "娄底市"],
"福建省": ["福州市", "厦门市", "莆田市", "三明市", "泉州市", "漳州市", "南平市", "龙岩市", "宁德市"],
"安徽省": ["合肥市", "芜湖市", "蚌埠市", "淮南市", "马鞍山市", "淮北市", "铜陵市", "安庆市", "黄山市", "滁州市", "阜阳市", "宿州市", "六安市", "亳州市", "池州市", "宣城市"],
"河北省": ["石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市"],
"陕西省": ["西安市", "铜川市", "宝鸡市", "咸阳市", "渭南市", "延安市", "汉中市", "榆林市", "安康市", "商洛市"],
"辽宁省": ["沈阳市", "大连市", "鞍山市", "抚顺市", "本溪市", "丹东市", "锦州市", "营口市", "阜新市", "辽阳市", "盘锦市", "铁岭市", "朝阳市", "葫芦岛市"]
};
const allJobs = [
{ id: 1, title: "自动化技术员", company: "恒力集团", salary: "4K-6K", icon: "fa-microchip", tags: ["苏州", "包吃住"], type: "生产类岗位", city: "苏州市", quota: 150, occupied: 45, startDate: "2026/3/5", reportLocation: "江苏省苏州市吴江区盛泽镇南麻恒力路1号", duration: "3个月", roomBoard: "包吃包住", requirements: "电气、自动化或相关专业,大专及以上学历;\n熟悉 PLC继电器电气控制原理能独立完成设备电气线路安装与调试\n有自动化设备维护、故障分析经验者优先\n工作认真负责有团队协作精神。", benefits: ["五险一金", "年终奖", "项目奖金", "单休", "员工宿舍", "绩效奖金"], companyIntro: "恒力集团有限公司成立于1994年总部位于江苏省苏州市吴江区是立足实业发展的全球化民营企业。集团注册资产达520亿元人民币全球员工总数超12万人2022年实现营业收入6117亿元连续七年跻身世界500强企业榜单。" },
{ id: 2, title: "跨境电商运营总监", company: "SHEIN", salary: "40-70k", icon: "fa-globe", tags: ["广州", "欧美"], type: "服务类岗位", city: "广州市", quota: 2, occupied: 1, startDate: "2025/12/1", reportLocation: "广州市番禺区万博商务区", duration: "长期", roomBoard: "提供餐补", requirements: "5年以上跨境电商运营经验\n英语流利可作为工作语言\n具备优秀的团队管理能力。", benefits: ["股票期权", "带薪年假", "年度旅游"], companyIntro: "SHEIN是一家全球领先的时尚和生活方式在线零售商。" },
{ id: 3, title: "AI 大模型算法专家", company: "未来智能", salary: "50-80k", icon: "fa-brain", tags: ["北京", "NLP"], type: "生产类岗位", city: "北京市", quota: 3, occupied: 3, startDate: "2025/11/15", reportLocation: "北京市海淀区中关村软件园", duration: "长期", roomBoard: "不包吃住", requirements: "计算机相关专业博士学历;\n在NLP领域有顶级会议论文发表\n熟悉PyTorch/TensorFlow。", benefits: ["补充医疗保险", "弹性工作", "定期体检"], companyIntro: "未来智能致力于构建通用人工智能。" },
{ id: 4, title: "资深产品经理", company: "字节跳动", salary: "30-55k", icon: "fa-cube", tags: ["上海", "SaaS"], type: "生产类岗位", city: "上海市", quota: 4, occupied: 2, startDate: "尽快", reportLocation: "上海市闵行区宜山路", duration: "长期", roomBoard: "免费三餐", requirements: "3年以上B端产品经验\n逻辑思维清晰具备优秀的数据分析能力。", benefits: ["房补", "免费健身房", "下午茶"], companyIntro: "字节跳动是最早将人工智能应用于移动互联网场景的科技企业之一。" },
{ id: 5, title: "供应链数据分析师", company: "恒力集团", salary: "18-30k", icon: "fa-chart-pie", tags: ["大连", "SQL"], type: "服务类岗位", city: "大连市", quota: 8, occupied: 5, startDate: "2026/1/10", reportLocation: "大连市长兴岛经济区", duration: "1年", roomBoard: "提供宿舍", requirements: "统计学或数学相关专业;\n精通SQL/Python\n对数字敏感。", benefits: ["五险一金", "班车接送"], companyIntro: "恒力石化(大连)有限公司是恒力集团在东北地区的重要产业基地。" },
{ id: 6, title: "嵌入式系统架构师", company: "科沃斯", salary: "35-60k", icon: "fa-microchip", tags: ["苏州", "ROS"], type: "生产类岗位", city: "苏州市", quota: 1, occupied: 0, startDate: "2025/12/20", reportLocation: "苏州市吴中区石湖西路", duration: "长期", roomBoard: "餐补", requirements: "熟悉嵌入式Linux开发\n精通C/C++。", benefits: ["年终奖", "股票期权"], companyIntro: "科沃斯机器人是全球最早的服务机器人研发与生产商之一。" },
{ id: 7, title: "HRBP (研发向)", company: "阿里巴巴", salary: "25-40k", icon: "fa-users", tags: ["杭州", "OD"], type: "服务类岗位", city: "杭州市", quota: 2, occupied: 1, startDate: "2025/11/30", reportLocation: "杭州市余杭区文一西路", duration: "长期", roomBoard: "餐补", requirements: "5年以上HR经验\n熟悉互联网研发团队特点。", benefits: ["主要看阿里福报"], companyIntro: "阿里巴巴集团旨在构建未来的商业基础设施。" },
{ id: 8, title: "高级前端工程师", company: "微软", salary: "30-50k", icon: "fa-code", tags: ["苏州", "React"], type: "生产类岗位", city: "苏州市", quota: 6, occupied: 4, startDate: "2026/2/1", reportLocation: "苏州市工业园区星湖街", duration: "长期", roomBoard: "不包", requirements: "精通React/Vue\n英语读写流利。", benefits: ["15天年假", "补充医疗"], companyIntro: "微软(中国)有限公司是微软公司在中国设立的子公司。" },
{ id: 9, title: "品牌视觉设计专家", company: "腾讯", salary: "25-45k", icon: "fa-pen-nib", tags: ["深圳", "C4D"], type: "生产类岗位", city: "深圳市", quota: 3, occupied: 2, startDate: "2025/12/15", reportLocation: "深圳市南山区深南大道", duration: "长期", roomBoard: "班车", requirements: "美术类专业;\n精通C4D/PS/AI。", benefits: ["Q币", "公仔"], companyIntro: "腾讯是一家世界领先的互联网科技公司。" },
{ id: 10, title: "财务主管", company: "美团", salary: "20-35k", icon: "fa-calculator", tags: ["北京", "CPA"], type: "服务类岗位", city: "北京市", quota: 2, occupied: 0, startDate: "2026/1/5", reportLocation: "北京市朝阳区望京东路", duration: "长期", roomBoard: "餐补", requirements: "持有CPA证书\n3年以上财务主管经验。", benefits: ["六险一金"], companyIntro: "美团的使命是'帮大家吃得更好,生活更好'。" },
{ id: 11, title: "新媒体运营", company: "小红书", salary: "15-25k", icon: "fa-hashtag", tags: ["上海", "营销"], type: "服务类岗位", city: "上海市", quota: 10, occupied: 8, startDate: "2025/11/25", reportLocation: "上海市黄浦区马当路", duration: "长期", roomBoard: "下午茶", requirements: "网感好;\n熟悉小红书平台规则。", benefits: ["宠物友好"], companyIntro: "小红书是年轻人的生活方式平台。" },
{ id: 12, title: "游戏客户端开发", company: "米哈游", salary: "30-60k", icon: "fa-gamepad", tags: ["上海", "Unity"], type: "生产类岗位", city: "上海市", quota: 5, occupied: 1, startDate: "2025/12/10", reportLocation: "上海市徐汇区宜山路", duration: "长期", roomBoard: "免费晚餐", requirements: "热爱二次元;\n精通Unity3D。", benefits: ["免费咖啡", "年会大奖"], companyIntro: "技术宅拯救世界。" }
];
let selectedJobs = [];
let filterState = { city: "全部", type: "全部" };
let currentRegion = "热门城市";
const MAX_SELECTION = 4;
const slotsLeft = document.getElementById('slots-left');
const slotsRight = document.getElementById('slots-right');
const jobGrid = document.getElementById('job-grid');
const countLeft = document.getElementById('count-left');
const btnSubmit = document.getElementById('btn-submit-intent');
const btnConfirm = document.getElementById('btn-confirm-final');
const cityModalOverlay = document.getElementById('city-modal-overlay');
const detailModalOverlay = document.getElementById('detail-modal-overlay');
function initSlots() {
slotsLeft.innerHTML = ''; slotsRight.innerHTML = '';
for (let i = 0; i < 3; i++) createSlot(i, slotsLeft);
createSlot(3, slotsRight);
}
function createSlot(index, container) {
const slot = document.createElement('div');
slot.className = 'slot-module empty';
slot.id = `slot-${index}`;
slot.onclick = () => removeJobByIndex(index);
const iconClass = index === 3 ? "fa-star text-yellow-500 opacity-30" : "fa-plus text-gray-500 opacity-20";
const text = index === 3 ? "最终确认位" : "意向岗位";
slot.innerHTML = `<div class="slot-index">0${index+1}</div><i class="fa-solid ${iconClass} text-2xl mb-2"></i><div class="text-xs text-gray-600 font-bold tracking-widest">${text}</div>`;
container.appendChild(slot);
}
function initFilters() {
const types = ["全部", "生产类岗位", "服务类岗位"];
const quickCities = regionData["热门城市"].slice(0, 5);
const cityQuickContainer = document.getElementById('city-quick-select');
const renderQuickCities = () => {
cityQuickContainer.innerHTML = '';
quickCities.forEach(city => {
const btn = document.createElement('div');
btn.className = `city-btn ${filterState.city === city ? 'active' : ''}`;
btn.innerText = city;
btn.onclick = () => { filterState.city = city; renderQuickCities(); renderJobGrid(); };
cityQuickContainer.appendChild(btn);
});
const moreBtn = document.createElement('div');
moreBtn.className = 'more-city-btn';
moreBtn.innerHTML = `<span>${filterState.city === '全部' || quickCities.includes(filterState.city) ? '切换城市' : filterState.city}</span> <i class="fa-solid fa-location-crosshairs"></i>`;
moreBtn.onclick = openCityModal;
cityQuickContainer.appendChild(moreBtn);
};
renderQuickCities();
const typeContainer = document.getElementById('type-dropdown');
typeContainer.innerHTML = '';
types.forEach(type => {
const option = document.createElement('div');
option.className = `type-option ${type === '全部' ? 'selected' : ''}`;
option.innerHTML = `<span>${type}</span>`;
option.onclick = () => {
document.getElementById('current-type').innerText = type === '全部' ? '全部类型' : type;
document.querySelectorAll('.type-option').forEach(el => el.classList.remove('selected'));
option.classList.add('selected');
toggleTypeDropdown();
filterState.type = type;
renderJobGrid();
};
typeContainer.appendChild(option);
});
document.addEventListener('click', (e) => {
if (!document.getElementById('type-selector').contains(e.target)) {
document.getElementById('type-dropdown').classList.remove('show');
document.querySelector('.type-btn').classList.remove('active');
}
if (e.target === cityModalOverlay) closeCityModal();
if (e.target === detailModalOverlay) closeDetailModal();
});
}
function toggleTypeDropdown() {
document.getElementById('type-dropdown').classList.toggle('show');
document.querySelector('.type-btn').classList.toggle('active');
}
window.toggleTypeDropdown = toggleTypeDropdown;
function openCityModal() {
cityModalOverlay.classList.add('show');
renderRegionSidebar();
renderCityGrid(currentRegion);
}
function closeCityModal() { cityModalOverlay.classList.remove('show'); }
window.openCityModal = openCityModal; window.closeCityModal = closeCityModal;
function renderRegionSidebar() {
const sidebar = document.getElementById('region-sidebar');
sidebar.innerHTML = '';
Object.keys(regionData).forEach(region => {
const item = document.createElement('li');
item.className = `region-item ${currentRegion === region ? 'active' : ''}`;
let icon = '';
if (region === '热门城市') icon = '<i class="fa-solid fa-fire text-red-500 mr-2"></i>';
else if (region === '直辖市') icon = '<i class="fa-solid fa-star text-yellow-500 mr-2"></i>';
item.innerHTML = `${icon}${region}`;
item.onclick = () => {
currentRegion = region;
renderRegionSidebar();
renderCityGrid(region);
document.querySelector('.city-grid-area').scrollTop = 0;
};
sidebar.appendChild(item);
});
}
function renderCityGrid(region) {
const grid = document.getElementById('city-grid');
grid.innerHTML = '';
const cities = regionData[region] || [];
cities.forEach(city => {
const item = document.createElement('div');
item.className = `city-option ${filterState.city === city ? 'selected' : ''}`;
item.innerText = city;
item.onclick = () => { filterState.city = city; closeCityModal(); initFilters(); renderJobGrid(); };
grid.appendChild(item);
});
}
function openJobDetail(event, id) {
event.stopPropagation();
const job = allJobs.find(j => j.id === id);
if(!job) return;
document.getElementById('detail-title').innerText = job.title;
document.getElementById('detail-salary').innerText = job.salary;
document.getElementById('detail-company').innerText = job.company;
document.getElementById('detail-type').innerText = job.type;
document.getElementById('detail-start-date').innerText = job.startDate || "待定";
document.getElementById('detail-duration').innerText = job.duration || "长期";
document.getElementById('detail-location').innerText = job.reportLocation || job.city;
document.getElementById('detail-roomboard').innerText = job.roomBoard || "不提供";
document.getElementById('detail-quota').innerText = `已招 ${job.occupied} / 共 ${job.quota}`;
const reqList = document.getElementById('detail-requirements');
reqList.innerHTML = '';
if(job.requirements) {
const reqs = job.requirements.split('\n');
reqs.forEach(req => { if(req.trim()){ const li = document.createElement('li'); li.className = 'req-item'; li.innerText = req.trim(); reqList.appendChild(li); } });
} else { reqList.innerHTML = '<li class="req-item">暂无详细要求</li>'; }
const benefitsContainer = document.getElementById('detail-benefits');
benefitsContainer.innerHTML = '';
if(job.benefits && job.benefits.length > 0) {
job.benefits.forEach(b => { const tag = document.createElement('span'); tag.className = 'welfare-tag'; tag.innerText = b; benefitsContainer.appendChild(tag); });
} else { benefitsContainer.innerHTML = '<span class="text-gray-500 text-sm">暂无福利信息</span>'; }
document.getElementById('detail-company-name-text').innerText = job.company;
document.getElementById('detail-company-intro').innerText = job.companyIntro || "暂无企业介绍。";
detailModalOverlay.classList.add('show');
}
function closeDetailModal() { detailModalOverlay.classList.remove('show'); }
window.openJobDetail = openJobDetail; window.closeDetailModal = closeDetailModal;
function renderJobGrid() {
jobGrid.innerHTML = '';
const filteredJobs = allJobs.filter(job => {
const matchCity = filterState.city === "全部" || job.city === filterState.city;
const matchType = filterState.type === "全部" || job.type === filterState.type;
return matchCity && matchType;
});
if (filteredJobs.length === 0) { jobGrid.innerHTML = `<div class="col-span-3 text-center py-10 text-gray-600"><p>暂无匹配岗位</p></div>`; return; }
filteredJobs.forEach(job => {
const isSelected = selectedJobs.includes(job.id);
const card = document.createElement('div');
card.className = `job-card ${isSelected ? 'disabled' : ''}`;
card.id = `job-card-${job.id}`;
card.onclick = () => selectJob(job.id);
const typeClass = job.type === "生产类岗位" ? "type-produce" : "type-service";
const typeLabelHtml = `<span class="type-badge ${typeClass}">${job.type}</span>`;
const tagsHtml = job.tags.map(t => `<span class="tag">${t}</span>`).join('');
card.innerHTML = `
<div class="quota-badge">已选 ${job.occupied} / ${job.quota}</div>
<div class="card-top"><div class="card-icon"><i class="fa-solid ${job.icon}"></i></div><div class="card-salary">${job.salary}</div></div>
<div><div class="card-title">${job.title}</div><div class="card-company"><i class="fa-regular fa-building"></i> ${job.company}</div><div class="card-tags">${typeLabelHtml}${tagsHtml}</div></div>
<button class="btn-detail" onclick="openJobDetail(event, ${job.id})"><i class="fa-regular fa-eye"></i> 查看详情</button>
<div class="check-mark"><i class="fa-solid fa-circle-check"></i></div>
`;
jobGrid.appendChild(card);
});
}
function selectJob(id) {
if (selectedJobs.includes(id)) return;
if (selectedJobs.length >= MAX_SELECTION) { gsap.fromTo([slotsLeft, slotsRight], { x: -5 }, { x: 0, duration: 0.4, ease: "elastic.out(1, 0.3)" }); return; }
selectedJobs.push(id); updateUI(true, id);
}
function removeJobByIndex(index) {
if (index >= selectedJobs.length) return;
const removedId = selectedJobs[index];
selectedJobs.splice(index, 1); updateUI(false, removedId);
}
function updateUI(isAdding, targetId) {
for (let i = 0; i < MAX_SELECTION; i++) {
const slot = document.getElementById(`slot-${i}`);
const jobId = selectedJobs[i];
if (jobId) {
const job = allJobs.find(j => j.id === jobId);
if (slot.classList.contains('empty') || slot.dataset.lastId != jobId) {
slot.className = 'slot-module filled';
slot.dataset.lastId = jobId;
const isFinal = (i === 3);
const removeText = isFinal ? "撤销确认" : "移除意向";
slot.innerHTML = `
<div class="slot-index">0${i+1}</div>
<div class="slot-content-title">${job.title}</div>
<div class="slot-content-salary">${job.salary}</div>
<div class="slot-content-company">${job.company}</div>
<div class="slot-remove-mask"><i class="fa-solid fa-xmark text-2xl mb-2"></i><span class="text-xs font-bold tracking-widest">${removeText}</span></div>
`;
if(isAdding && i === selectedJobs.length - 1) { gsap.fromTo(slot, { y: -30, opacity: 0, scale: 0.8 }, { y: 0, opacity: 1, scale: 1, duration: 0.5, ease: "back.out(1.5)" }); }
}
} else {
if (!slot.classList.contains('empty')) {
slot.className = 'slot-module empty'; delete slot.dataset.lastId;
const isFinal = (i === 3);
const iconClass = isFinal ? "fa-star text-yellow-500 opacity-30" : "fa-plus text-gray-500 opacity-20";
const text = isFinal ? "最终确认位" : "意向岗位";
slot.innerHTML = `<div class="slot-index">0${i+1}</div><i class="fa-solid ${iconClass} text-2xl mb-2"></i><div class="text-xs text-gray-600 font-bold tracking-widest">${text}</div>`;
}
}
}
if (targetId) {
const card = document.getElementById(`job-card-${targetId}`);
if (card) {
if (isAdding) { card.classList.add('disabled'); gsap.to(card, { scale: 0.92, opacity: 0.3, duration: 0.3, ease: "power2.out" }); }
else { card.classList.remove('disabled'); gsap.to(card, { scale: 1, opacity: 1, duration: 0.4, ease: "back.out(1.2)", clearProps: "all" }); }
}
}
const hasIntent = selectedJobs.length > 0;
countLeft.innerText = Math.min(selectedJobs.length, 3);
if (hasIntent) btnSubmit.classList.add('active'); else btnSubmit.classList.remove('active');
const hasFinal = selectedJobs.length === 4;
if (hasFinal) btnConfirm.classList.add('active'); else btnConfirm.classList.remove('active');
}
initSlots(); initFilters(); renderJobGrid();
})();
</script>
<script type="module" src="./js/main.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const userInfo = AuthHelper.getUserInfo();
if (userInfo) {
const userInfoElement = document.getElementById('user-info');
if (userInfoElement) { userInfoElement.textContent = `欢迎, ${userInfo.username}`; }
}
});
</script>
<div id="professional-category-modal" class="hidden" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(10px); z-index: 9999; display: flex; justify-content: center; align-items: center;">
<div style="background: linear-gradient(135deg, rgba(15, 23, 42, 0.95), rgba(30, 41, 59, 0.95)); border: 1px solid rgba(56, 189, 248, 0.3); border-radius: 20px; padding: 40px; max-width: 500px; width: 90%; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); text-align: center;">
<div style="font-size: 48px; margin-bottom: 20px;">💼</div>
<h3 style="font-size: 24px; font-weight: 700; color: #fff; margin-bottom: 12px;">请先设置专业大类</h3>
<p style="font-size: 14px; color: rgba(255, 255, 255, 0.7); margin-bottom: 30px; line-height: 1.6;">为了提供更精准的就业规划服务,<br>请先在个人资料中设置您的专业大类</p>
<div id="category-select-container" style="margin-bottom: 20px;">
<select id="modal-professional-category" style="width: 100%; padding: 12px 16px; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(56, 189, 248, 0.3); border-radius: 12px; color: #fff; font-size: 15px; outline: none; cursor: pointer;">
<option value="">请选择您的专业大类</option>
</select>
</div>
<div style="display: flex; gap: 12px; justify-content: center;">
<button onclick="closeProfessionalCategoryModal()" style="padding: 12px 24px; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; color: #fff; cursor: pointer; font-size: 14px; transition: all 0.3s;">取消</button>
<button onclick="saveProfessionalCategory()" style="padding: 12px 24px; background: linear-gradient(135deg, #0ea5e9, #2563eb); border: none; border-radius: 12px; color: #fff; cursor: pointer; font-size: 14px; font-weight: 600; transition: all 0.3s; box-shadow: 0 4px 15px rgba(37, 99, 235, 0.4);">保存并继续</button>
</div>
</div>
</div>
</body>
</html>