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
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|