主要更新: - ✅ 完成主题配色从暗色到亮蓝白配色的全面转换 - ✅ 实现高薪岗位页面及后端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>
230 lines
6.4 KiB
JavaScript
230 lines
6.4 KiB
JavaScript
/**
|
|
* 培训单元控制器
|
|
* 基于high.html的最新数据结构
|
|
*/
|
|
|
|
const db = require('../../config/database');
|
|
|
|
/**
|
|
* 获取所有培训单元
|
|
* GET /api/training-units
|
|
* 支持optionalAuth
|
|
*/
|
|
exports.getList = async (req, res) => {
|
|
try {
|
|
const userId = req.user ? req.user.id : null;
|
|
|
|
let query, params;
|
|
|
|
if (userId) {
|
|
// 已登录:查询确认状态
|
|
query = `
|
|
SELECT
|
|
tu.*,
|
|
tc.id as confirmation_id,
|
|
tc.confirmed_at
|
|
FROM training_units tu
|
|
LEFT JOIN training_confirmations tc ON tu.id = tc.training_unit_id AND tc.user_id = ?
|
|
ORDER BY tu.display_order ASC, tu.start_date ASC
|
|
`;
|
|
params = [userId];
|
|
} else {
|
|
// 未登录:仅返回单元列表
|
|
query = `
|
|
SELECT * FROM training_units
|
|
ORDER BY display_order ASC, start_date ASC
|
|
`;
|
|
params = [];
|
|
}
|
|
|
|
const [units] = await db.query(query, params);
|
|
|
|
// 格式化数据
|
|
const formattedUnits = units.map(unit => ({
|
|
id: unit.id,
|
|
title: unit.title,
|
|
start_date: unit.start_date,
|
|
related_positions: unit.related_positions,
|
|
related_companies: unit.related_companies,
|
|
status: unit.status,
|
|
is_confirmed: !!unit.confirmation_id,
|
|
confirmed_at: unit.confirmed_at || null
|
|
}));
|
|
|
|
return res.json({
|
|
success: true,
|
|
data: formattedUnits
|
|
});
|
|
} catch (error) {
|
|
console.error('获取培训单元失败:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: '获取培训单元失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 确认预招录
|
|
* POST /api/training-units/:id/confirm
|
|
* 需要登录
|
|
*/
|
|
exports.confirm = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const userId = req.user.id;
|
|
|
|
// 检查单元是否存在
|
|
const [units] = await db.query(
|
|
'SELECT id, title FROM training_units WHERE id = ?',
|
|
[id]
|
|
);
|
|
|
|
if (units.length === 0) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '培训单元不存在'
|
|
});
|
|
}
|
|
|
|
// 检查是否已确认
|
|
const [existing] = await db.query(
|
|
'SELECT id FROM training_confirmations WHERE user_id = ? AND training_unit_id = ?',
|
|
[userId, id]
|
|
);
|
|
|
|
if (existing.length > 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '您已确认过该单元'
|
|
});
|
|
}
|
|
|
|
// 插入确认记录(设置较短的超时时间)
|
|
try {
|
|
await db.query(
|
|
'INSERT INTO training_confirmations (user_id, training_unit_id) VALUES (?, ?)',
|
|
[userId, id]
|
|
);
|
|
} catch (insertError) {
|
|
// 特殊处理数据库锁定错误
|
|
if (insertError.code === 'ER_LOCK_WAIT_TIMEOUT') {
|
|
return res.status(503).json({
|
|
success: false,
|
|
message: '系统繁忙,请稍后再试',
|
|
error: '数据库暂时无法处理请求'
|
|
});
|
|
}
|
|
throw insertError;
|
|
}
|
|
|
|
return res.json({
|
|
success: true,
|
|
message: '确认成功'
|
|
});
|
|
} catch (error) {
|
|
// 处理唯一键冲突
|
|
if (error.code === 'ER_DUP_ENTRY') {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: '您已确认过该单元'
|
|
});
|
|
}
|
|
|
|
// 处理数据库锁定错误
|
|
if (error.code === 'ER_LOCK_WAIT_TIMEOUT') {
|
|
console.error('数据库锁定:', error.message);
|
|
return res.status(503).json({
|
|
success: false,
|
|
message: '系统繁忙,请稍后再试',
|
|
error: '数据库暂时无法处理请求'
|
|
});
|
|
}
|
|
|
|
console.error('确认预招录失败:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: '确认失败,请稍后重试'
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 取消预招录
|
|
* DELETE /api/training-units/:id/confirm
|
|
* 需要登录
|
|
*/
|
|
exports.cancelConfirm = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const userId = req.user.id;
|
|
|
|
const [result] = await db.query(
|
|
'DELETE FROM training_confirmations WHERE user_id = ? AND training_unit_id = ?',
|
|
[userId, id]
|
|
);
|
|
|
|
if (result.affectedRows === 0) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: '未找到确认记录'
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
success: true,
|
|
message: '取消成功'
|
|
});
|
|
} catch (error) {
|
|
console.error('取消预招录失败:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: '取消预招录失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 获取我的确认列表
|
|
* GET /api/training-units/my-confirmations
|
|
* 需要登录
|
|
*/
|
|
exports.getMyConfirmations = async (req, res) => {
|
|
try {
|
|
const userId = req.user.id;
|
|
|
|
const [confirmations] = await db.query(`
|
|
SELECT
|
|
tu.*,
|
|
tc.confirmed_at
|
|
FROM training_confirmations tc
|
|
JOIN training_units tu ON tc.training_unit_id = tu.id
|
|
WHERE tc.user_id = ?
|
|
ORDER BY tc.confirmed_at DESC
|
|
`, [userId]);
|
|
|
|
const formattedData = confirmations.map(c => ({
|
|
id: c.id,
|
|
title: c.title,
|
|
start_date: c.start_date,
|
|
related_positions: c.related_positions,
|
|
related_companies: c.related_companies,
|
|
confirmed_at: c.confirmed_at
|
|
}));
|
|
|
|
return res.json({
|
|
success: true,
|
|
data: formattedData
|
|
});
|
|
} catch (error) {
|
|
console.error('获取确认列表失败:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: '获取确认列表失败',
|
|
error: error.message
|
|
});
|
|
}
|
|
};
|