<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>缺件排产优化工具</title>
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
<style>
/* 保持原有样式不变 */
</style>
<!-- 保持原有HTML结构不变 -->
<script>
// [之前的所有函数保持不变...]
// 修改后的生成排产计划函数(优化版)
function generateSchedule() {
const btn = document.getElementById('generateBtn');
const loading = document.getElementById('loading');
btn.disabled = true;
loading.style.display = 'inline';
setTimeout(() => {
try {
console.log("开始生成优化排产计划...");
// [之前的参数检查和数据验证保持不变...]
const workers = parseInt(document.getElementById('workers').value) || 3;
const productivity = parseInt(document.getElementById('productivity').value) || 70;
const startDateStr = document.getElementById('startDate').value;
const dailyCapacity = workers * productivity;
// 1. 按交付日期升序排序(最早交付的优先)
const sortedData = [...rawData].sort((a, b) => {
return new Date(a.deliveryDate) - new Date(b.deliveryDate);
});
// 2. 计算每个项目的最晚开始日期(交付日期前一天)
const itemsWithDeadline = sortedData.map(item => {
const deadline = new Date(item.deliveryDate);
deadline.setDate(deadline.getDate() - 1); // 交付前一天
return {
...item,
deadline: deadline,
productionDays: Math.ceil(item.quantity / dailyCapacity)
};
});
// 3. 初始化排产计划
scheduleData = [];
warningData = [];
let currentDate = new Date(startDateStr);
let dailyRemaining = dailyCapacity;
// 4. 优化排产算法 - 尽可能在截止日期前完成
for (const item of itemsWithDeadline) {
let productionDate = new Date(currentDate);
let quantityRemaining = item.quantity;
let isLate = false;
// 计算最合理的开始生产日期
// 尝试从截止日期倒推需要的生产天数
const requiredDays = Math.ceil(item.quantity / dailyCapacity);
let idealStartDate = new Date(item.deadline);
idealStartDate.setDate(idealStartDate.getDate() - requiredDays + 1);
// 如果理想开始日期比当前日期早,就从当前日期开始
if (idealStartDate < currentDate) {
idealStartDate = new Date(currentDate);
}
productionDate = new Date(idealStartDate);
// 分配生产日期
while (quantityRemaining > 0) {
if (dailyRemaining === 0) {
// 转到下一天
productionDate.setDate(productionDate.getDate() + 1);
dailyRemaining = dailyCapacity;
}
const allocate = Math.min(quantityRemaining, dailyRemaining);
// 检查是否超期
const currentIsLate = productionDate > item.deadline;
isLate = isLate || currentIsLate;
scheduleData.push({
productId: item.productId,
quantity: allocate,
deliveryDate: item.deliveryDate,
productionDate: productionDate.toISOString().split('T')[0],
isLate: currentIsLate
});
quantityRemaining -= allocate;
dailyRemaining -= allocate;
}
// 更新当前日期到最后生产日期的下一天
currentDate = new Date(productionDate);
currentDate.setDate(currentDate.getDate() + 1);
dailyRemaining = dailyCapacity;
// 如果整个项目超期,添加到预警
if (isLate) {
const lastProdDate = new Date(
scheduleData.filter(x => x.productId === item.productId)
.reduce((latest, curr) =>
new Date(curr.productionDate) > new Date(latest.productionDate) ? curr : latest
).productionDate
);
const lateDays = Math.ceil(
(new Date(lastProdDate) - new Date(item.deadline)) /
(1000 * 60 * 60 * 24)
);
warningData.push({
productId: item.productId,
quantity: item.quantity,
deliveryDate: item.deliveryDate,
productionDate: lastProdDate,
lateDays: lateDays
});
}
}
// [保持原有的显示和摘要更新函数不变...]
} catch (error) {
console.error("生成排产计划时出错:", error);
alert('生成排产计划时出错: ' + error.message);
} finally {
btn.disabled = false;
loading.style.display = 'none';
}
}, 100);
}
// [其余函数保持不变...]
</script>
评论 (0)