备份:大改造前的完整版本 - 修复合同细节/付款节点/文件上传/施工管理/项目保存等BUG

This commit is contained in:
root
2026-05-15 12:02:24 +08:00
parent 1cad1e438d
commit fad28741bd
6157 changed files with 5147 additions and 877912 deletions
+73 -33
View File
@@ -37,7 +37,7 @@ router.get('/', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -130,7 +130,7 @@ router.get('/:id', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目详情失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -154,7 +154,7 @@ router.get('/:id/contracts', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目合同失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -192,7 +192,7 @@ router.get('/:id/subcontracts', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目分包失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -206,7 +206,8 @@ router.post('/:id/subcontracts', async (req, res) => {
const result = await db.query(
`INSERT INTO subcontracts (project_id, subcontractor_id, subcontractor_name, contract_amount, currency, settlement_type, other_terms, payment_description, unit_price_items, start_date, end_date, work_days, paid_amount, status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id`,
[id, subcontractor_id, subcontractor_name, contract_amount, currency || 'CNY', settlement_type || 'lump_sum', other_terms, payment_description, unitPriceItemsJson, start_date, end_date, work_days, 0, status || 'active']
);
@@ -239,7 +240,7 @@ router.post('/:id/subcontracts', async (req, res) => {
res.status(500).json({
success: false,
message: '新增项目分包失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -263,7 +264,7 @@ router.get('/:id/materials', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目材料失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -287,7 +288,7 @@ router.get('/:id/milestones', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目施工节点失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -311,7 +312,7 @@ router.get('/:id/finances', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目财务失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -335,7 +336,7 @@ router.get('/:id/warranty-deposits', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目质保金失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -354,7 +355,7 @@ router.get('/:id/construction-logs', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目施工日志失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -366,9 +367,10 @@ router.post('/', async (req, res) => {
const projectCode = code || 'PROJ' + new Date().toISOString().slice(0, 10).replace(/-/g, '') +
String(Math.floor(Math.random() * 10000)).padStart(4, '0');
const result = await db.query(
`INSERT INTO projects (name, code, customer_id, manager_id, contract_amount, start_date, end_date, description, status, location, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
const result = await db.query(
`INSERT INTO projects (name, code, customer_id, project_manager_id, contract_amount, start_date, end_date, description, status, location, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id`,
[name, projectCode, customer_id || null, manager_id || null, contract_amount || 0, start_date || '', end_date || '', description || '', status || 'planning', location || '']
);
@@ -382,7 +384,7 @@ router.post('/', async (req, res) => {
res.status(500).json({
success: false,
message: '创建项目失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});
@@ -394,7 +396,7 @@ router.delete('/:id', authenticate, requireAdmin, async (req, res) => {
res.json({ success: true, message: '项目已删除' });
} catch (error) {
console.error('删除项目失败:', error);
res.status(500).json({ success: false, message: error.message });
res.status(500).json({ success: false, message: '操作失败' });
}
});
@@ -403,33 +405,69 @@ router.put('/:id', async (req, res) => {
const { id } = req.params;
const { name, manager_id, location, start_date, end_date, description, status, contract_amount } = req.body;
console.log('收到项目更新请求:', { id, name, manager_id, location, start_date, end_date, description });
const updates = [];
const values = [];
let paramIndex = 1;
if (name !== undefined && name !== null) {
updates.push(`name = $${paramIndex++}`);
values.push(name);
}
if (manager_id !== undefined && manager_id !== null) {
updates.push(`project_manager_id = $${paramIndex++}`);
values.push(manager_id);
}
if (location !== undefined && location !== null) {
updates.push(`location = $${paramIndex++}`);
values.push(location);
}
if (start_date !== undefined && start_date !== null) {
updates.push(`start_date = $${paramIndex++}`);
values.push(start_date);
}
if (end_date !== undefined && end_date !== null) {
updates.push(`end_date = $${paramIndex++}`);
values.push(end_date);
}
if (description !== undefined && description !== null) {
updates.push(`description = $${paramIndex++}`);
values.push(description);
}
if (status !== undefined && status !== null) {
updates.push(`status = $${paramIndex++}`);
values.push(status);
}
if (contract_amount !== undefined && contract_amount !== null) {
updates.push(`contract_amount = $${paramIndex++}`);
values.push(contract_amount);
}
updates.push(`updated_at = CURRENT_TIMESTAMP`);
if (updates.length > 1) {
values.push(id);
await db.query(
`UPDATE projects SET ${updates.join(', ')} WHERE id = $${paramIndex}`,
values
);
}
// 更新项目信息
await db.query(
'UPDATE projects SET name = CASE WHEN $1 IS NOT NULL THEN $2 ELSE name END, manager_id = CASE WHEN $3 IS NOT NULL THEN $4 ELSE manager_id END, location = CASE WHEN $5 IS NOT NULL THEN $6 ELSE location END, start_date = CASE WHEN $7 IS NOT NULL THEN $8 ELSE start_date END, end_date = CASE WHEN $9 IS NOT NULL THEN $10 ELSE end_date END, description = CASE WHEN $11 IS NOT NULL THEN $12 ELSE description END, status = CASE WHEN $13 IS NOT NULL THEN $14 ELSE status END, contract_amount = CASE WHEN $15 IS NOT NULL THEN $16 ELSE contract_amount END, updated_at = CURRENT_TIMESTAMP WHERE id = $17',
[name, name, manager_id, manager_id, location, location, start_date, start_date, end_date, end_date, description, description, status, status, contract_amount, contract_amount, id]
);
// 如果提供了开始和结束日期,更新合同的工期信息
if (start_date && end_date) {
const start = new Date(start_date);
const end = new Date(end_date);
const contractPeriod = Math.floor((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)) + 1;
// 更新合同信息
await db.query(
'UPDATE project_contracts SET start_date = $1, end_date = $2, contract_period = $3 WHERE project_id = $4',
[start_date, end_date, contractPeriod, id]
);
}
// 查询更新后的数据
const updatedResult = await db.query('SELECT * FROM projects WHERE id = $1', [id]);
res.json({ success: true, data: updatedResult.rows[0] });
} catch (error) {
console.error('更新项目失败:', error);
res.status(500).json({ success: false, message: error.message });
res.status(500).json({ success: false, message: '操作失败' });
}
});
@@ -447,7 +485,6 @@ router.put('/:id/contract', async (req, res) => {
contract_file
} = req.body;
console.log('收到合同细节保存请求:', { id, project_overview, settlement_type, contract_total, tax_included, contract_file });
// 1. 更新项目基本信息
await db.query(
@@ -476,7 +513,8 @@ router.put('/:id/contract', async (req, res) => {
const contractCode = `CONTRACT-${Date.now()}`;
await db.query(
`INSERT INTO project_contracts (project_id, contract_code, contract_amount, settlement_method, contract_file, other_info, tax_included, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
VALUES ($1, $2, $3, $4, $5, $6, $7, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id`,
[id, contractCode, contract_total, settlement_type, contract_file, other_info, tax_included]
);
}
@@ -490,7 +528,8 @@ router.put('/:id/contract', async (req, res) => {
for (const node of payment_nodes) {
await db.query(
`INSERT INTO project_milestones (project_id, milestone_name, condition, percentage, amount, status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id`,
[id, node.name, node.condition || '', node.percentage, node.amount, 'pending']
);
}
@@ -505,7 +544,8 @@ router.put('/:id/contract', async (req, res) => {
for (const item of unit_price_items) {
await db.query(
`INSERT INTO project_materials (project_id, product_name, unit, budget_quantity, average_price, total_amount, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
RETURNING id`,
[id, item.name, item.unit, item.quantity, item.price, item.total]
);
}
@@ -517,7 +557,7 @@ router.put('/:id/contract', async (req, res) => {
});
} catch (error) {
console.error('保存合同细节失败:', error);
res.status(500).json({ success: false, message: error.message });
res.status(500).json({ success: false, message: '操作失败' });
}
});
@@ -577,7 +617,7 @@ router.get('/:id/cost-summary', async (req, res) => {
res.status(500).json({
success: false,
message: '获取项目成本统计失败',
error: error.message
error: process.env.NODE_ENV === 'development' ? error.message : '操作失败'
});
}
});