大改造:施工进度系统+模板管理+物流收货+分包评分
- 新增5张数据库表:logistics_records, receiving_confirms, project_type_templates, project_phases, subcontractor_events - 修改3张表:projects(增加type_template_id/current_phase/phase_progress), purchase_orders(增加expected_delivery_date/receiving_status), subcontractors(增加score/initial_score) - 插入5套预设工程模板(配电安装/架空线路/电缆敷设/变电站/小型工程) - 后端新增:模板管理API、项目阶段管理API、收货确认API、分包商事件API - 后端修改:项目创建/预算签约支持模板选择,自动初始化阶段 - 前端新增:工程模板设计器(后台管理)、施工总览页、施工进度页(手机友好) - 前端修改:项目详情页重构为7个Tab,增加施工进度预览条和进入施工管理按钮 - 菜单更新:施工管理增加施工总览子菜单,后台管理增加工程模板管理
This commit is contained in:
@@ -514,4 +514,63 @@ router.delete('/payment-infos/:infoId', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
router.get('/:id/events', async (req, res) => {
|
||||
try {
|
||||
const result = await db.query(
|
||||
'SELECT * FROM subcontractor_events WHERE subcontractor_id = $1 ORDER BY event_date DESC, created_at DESC',
|
||||
[req.params.id]
|
||||
);
|
||||
res.json({ success: true, data: result.rows });
|
||||
} catch (error) {
|
||||
console.error('获取分包商事件失败:', error);
|
||||
res.status(500).json({ success: false, message: '获取分包商事件失败' });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/:id/events', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { project_id, event_type, score_change, event_date, title, description, created_by } = req.body;
|
||||
if (!event_type || !score_change || !event_date || !title) {
|
||||
return res.status(400).json({ success: false, message: '缺少必填字段' });
|
||||
}
|
||||
if (!['positive', 'negative'].includes(event_type)) {
|
||||
return res.status(400).json({ success: false, message: '事件类型必须是positive或negative' });
|
||||
}
|
||||
const actualChange = event_type === 'positive' ? Math.abs(score_change) : -Math.abs(score_change);
|
||||
const result = await db.query(
|
||||
`INSERT INTO subcontractor_events (subcontractor_id, project_id, event_type, score_change, event_date, title, description, created_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id`,
|
||||
[id, project_id || null, event_type, actualChange, event_date, title, description || '', created_by || null]
|
||||
);
|
||||
await db.query(
|
||||
'UPDATE subcontractors SET score = GREATEST(0, score + $1) WHERE id = $2',
|
||||
[actualChange, id]
|
||||
);
|
||||
res.json({ success: true, message: '事件添加成功', data: { id: result.rows[0].id } });
|
||||
} catch (error) {
|
||||
console.error('添加分包商事件失败:', error);
|
||||
res.status(500).json({ success: false, message: '添加分包商事件失败' });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/:id/events/:eventId', async (req, res) => {
|
||||
try {
|
||||
const { id, eventId } = req.params;
|
||||
const eventResult = await db.query('SELECT score_change FROM subcontractor_events WHERE id = $1 AND subcontractor_id = $2', [eventId, id]);
|
||||
if (eventResult.rows.length === 0) {
|
||||
return res.status(404).json({ success: false, message: '事件不存在' });
|
||||
}
|
||||
const scoreChange = eventResult.rows[0].score_change;
|
||||
await db.query('DELETE FROM subcontractor_events WHERE id = $1', [eventId]);
|
||||
await db.query(
|
||||
'UPDATE subcontractors SET score = GREATEST(0, LEAST(200, score - $1)) WHERE id = $2',
|
||||
[scoreChange, id]
|
||||
);
|
||||
res.json({ success: true, message: '事件删除成功' });
|
||||
} catch (error) {
|
||||
console.error('删除分包商事件失败:', error);
|
||||
res.status(500).json({ success: false, message: '删除分包商事件失败' });
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user