首页
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
Search
1
宝塔面板登录 phpMyAdmin 提示服务器和客户端上指示的HTTPS之间不匹配
259 阅读
2
Customer complaints evolve with in-car tech
184 阅读
3
测试
147 阅读
4
内连接,左连接,右连接作用及区别
95 阅读
5
所谓关系
94 阅读
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVA
java基础
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
登录
Search
标签搜索
期刊读物
古文
何瑜明
累计撰写
103
篇文章
累计收到
153
条评论
首页
栏目
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVA
java基础
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
页面
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
搜索到
16
篇与
的结果
2025-05-07
此内容被密码保护
加密文章,请前往内页查看详情
2025年05月07日
2 阅读
0 评论
0 点赞
2025-05-07
挤出逻辑
<body> <div class="container"> <h1>挤出排产</h1> <div class="input-group"> <input type="file" id="excelFile" accept=".xlsx"> <input type="date" id="startDate" required> <button onclick="startScheduling()">开始排产</button> </div> <div id="scheduleResult"></div> </div> <script> const PRODUCTION_PARAMS = { speed: { low: 5000, // ≤16mm medium: 4000, // 17-30mm high: 3500 // >30mm }, diameterGroups: [ { max: 8, name: '0-8mm' }, { max: 11, name: '9-11mm' }, { max: Infinity, name: '12mm+' } ] }; document.addEventListener('DOMContentLoaded', () => { if(typeof XLSX === 'undefined') { alert('错误:核心库加载失败,请检查网络连接'); return; } document.getElementById('startDate').valueAsDate = new Date(); }); function startScheduling() { const fileInput = document.getElementById('excelFile'); const startDate = document.getElementById('startDate').value; if(!fileInput.files.length) return alert("请选择Excel文件"); if(!startDate) return alert("请选择排产开始日期"); const reader = new FileReader(); reader.onload = processExcelFile; reader.readAsArrayBuffer(fileInput.files[0]); } function processExcelFile(event) { try { const workbook = XLSX.read(event.target.result, {type: 'array'}); const sheet = workbook.Sheets[workbook.SheetNames[0]]; const rawData = XLSX.utils.sheet_to_json(sheet, {header:1}); const orders = validateAndFormatData(rawData); const schedule = generateProductionSchedule(orders); renderScheduleTable(schedule); } catch (error) { handleError('文件处理失败', error); } } function validateAndFormatData(rawData) { return rawData.slice(1).map((row, index) => { const dateIndex = 2; if(row.length < 7) throw new Error(`第${index+2}行数据列数不足`); let demandDate; const excelDateValue = row[dateIndex]; if(typeof excelDateValue === 'number') { const parsed = XLSX.SSF.parse_date_code(excelDateValue); demandDate = new Date(parsed.y, parsed.m - 1, parsed.d); } else { demandDate = new Date(excelDateValue); } if(isNaN(demandDate.getTime())) { throw new Error(`第${index+2}行需求日期格式错误,值:${excelDateValue}`); } return { 订单号: String(row[0]).trim(), 需求数量: Number(row[1]), 需求日期: demandDate, 产品口径: Number(row[3]), 实际长度: parseFloat(Number(row[4]).toFixed(2)), 胶料类型: String(row[5]).trim(), 生产机台: String(row[6]).trim(), 挤出基数: Math.ceil(row[1] * 1.1 / 10) * 10, 剩余数量: Math.ceil(row[1] * 1.1 / 10) * 10 }; }).filter(order => order.需求数量 >= 10); } function generateProductionSchedule(orders) { const schedule = {}; const startDate = new Date(document.getElementById('startDate').value); const grouped = groupOrders(orders); const sortedKeys = Object.keys(grouped).sort(); sortedKeys.forEach(key => { const [machine, material, diameterGroup] = key.split('|'); const orderList = grouped[key]; let currentDate = new Date(startDate); const { maxQty: maxDailyQty } = calculateDailyCapacity(orderList[0].产品口径, orderList[0].实际长度); while (orderList.some(o => o.剩余数量 > 0)) { const dateKey = formatDate(currentDate); if (!schedule[machine]) schedule[machine] = {}; if (!schedule[machine][dateKey]) { schedule[machine][dateKey] = { items: [], totalLength: 0, usedQty: 0, capacity: maxDailyQty }; } const day = schedule[machine][dateKey]; let capacityLeft = day.capacity - day.usedQty; for (let order of orderList) { if (order.剩余数量 <= 0 || capacityLeft <= 0) continue; const canAlloc = Math.min(order.剩余数量, capacityLeft); day.items.push({ 订单号: order.订单号, 胶料类型: order.胶料类型, 产品口径: order.产品口径, 实际长度: order.实际长度, 排产数量: canAlloc, 排产长度: canAlloc * order.实际长度, 需求日期: order.需求日期 }); day.totalLength += canAlloc * order.实际长度; day.usedQty += canAlloc; order.剩余数量 -= canAlloc; capacityLeft -= canAlloc; } currentDate = addDays(currentDate, 1); } }); return schedule; } function groupOrders(orders) { const groups = {}; orders.forEach(order => { const diameterGroup = PRODUCTION_PARAMS.diameterGroups.find(g => order.产品口径 <= g.max).name; const key = `${order.生产机台}|${order.胶料类型}|${diameterGroup}`; if (!groups[key]) groups[key] = []; groups[key].push(order); }); return groups; } function calculateDailyCapacity(diameter, length) { let speed; if(diameter <= 16) speed = PRODUCTION_PARAMS.speed.low; else if(diameter <= 30) speed = PRODUCTION_PARAMS.speed.medium; else speed = PRODUCTION_PARAMS.speed.high; const maxQty = Math.floor(speed / length); return { value: speed, maxQty }; } function formatDate(date) { return date.toISOString().split('T')[0]; } function addDays(date, days) { const result = new Date(date); result.setDate(result.getDate() + days); return result; } function renderScheduleTable(schedule) { let html = ''; Object.entries(schedule).forEach(([machine, dateMap]) => { html += `<div class="machine-header"> <h3>${machine} 生产计划</h3> <div class="capacity-info">每日最大产能:${Object.values(dateMap)[0].capacity} 米</div> </div>`; html += `<table> <tr> <th>生产日期</th> <th>订单号</th> <th>口径(mm)</th> <th>长度(m)</th> <th>胶料类型</th> <th>排产数量</th> <th>总长度(m)</th> <th>需求日期</th> <th>状态</th> </tr>`; Object.entries(dateMap).forEach(([date, data]) => { data.items.forEach(item => { const isLate = new Date(date) > new Date(item.需求日期); html += `<tr${isLate ? ' class="warning"' : ''}> <td>${date}</td> <td>${item.订单号}</td> <td>${item.产品口径}</td> <td>${item.实际长度.toFixed(2)}</td> <td>${item.胶料类型}</td> <td>${item.排产数量}</td> <td>${item.排产长度.toFixed(1)}</td> <td>${item.需求日期.toISOString().split('T')[0]}</td> <td>${isLate ? '延迟' : '正常'}</td> </tr>`; }); html += `<tr class="summary-row"> <td colspan="5">当日汇总</td> <td>${data.usedQty}</td> <td>${data.totalLength.toFixed(1)}</td> <td colspan="3"> </td> </tr>`; }); html += `</table>`; }); document.getElementById('scheduleResult').innerHTML = html; } function handleError(message, error) { console.error(`${message}:`, error); alert(`${message},请检查控制台获取详细信息`); } </script> </body>
2025年05月07日
2 阅读
0 评论
0 点赞
2025-04-06
分班逻辑梳理
<script> function processFile() { const fileInput = document.getElementById("fileInput"); if (!fileInput.files.length) { alert("请上传 Excel 文件!"); return; } const reader = new FileReader(); reader.onload = function (e) { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: "array" }); const sheetName = workbook.SheetNames[0]; const sheet = workbook.Sheets[sheetName]; const jsonData = XLSX.utils.sheet_to_json(sheet, { header: 1 }); if (jsonData.length < 2) { alert("Excel 文件数据格式不正确!"); return; } const formattedData = jsonData.slice(1).map(row => [ row[0], Number(row[1]), formatExcelDate(row[2]) // 转换Excel日期 ]); const result = splitProduction(formattedData); displayResult(result); }; reader.readAsArrayBuffer(fileInput.files[0]); } function splitProduction(data) { const groupedByDate = {}; data.forEach(row => { const [productId, quantity, date] = row; if (!groupedByDate[date]) groupedByDate[date] = []; groupedByDate[date].push({ productId, quantity }); }); const result = {}; Object.keys(groupedByDate).forEach(date => { const products = groupedByDate[date].sort((a, b) => b.quantity - a.quantity); let A = [], B = []; let sumA = 0, sumB = 0; products.forEach(item => { if (sumA <= sumB) { A.push(item); sumA += item.quantity; } else { B.push(item); sumB += item.quantity; } }); result[date] = { A, B, sumA, sumB, typesA: new Set(A.map(p => p.productId)).size, typesB: new Set(B.map(p => p.productId)).size }; }); return result; } function displayResult(data) { let output = document.getElementById("output"); output.innerHTML = ""; Object.keys(data).forEach(date => { let summary = `<h3>排产日期:${date}</h3> <p class="summary">A 班:总数量 ${data[date].sumA},种类数 ${data[date].typesA} | B 班:总数量 ${data[date].sumB},种类数 ${data[date].typesB}</p>`; let table = `<table> <tr> <th>A 班 - 产品编号</th> <th>A 班 - 数量</th> <th>B 班 - 产品编号</th> <th>B 班 - 数量</th> </tr>`; const maxLength = Math.max(data[date].A.length, data[date].B.length); for (let i = 0; i < maxLength; i++) { const Aitem = data[date].A[i] || { productId: "", quantity: "" }; const Bitem = data[date].B[i] || { productId: "", quantity: "" }; table += `<tr> <td>${Aitem.productId}</td> <td>${Aitem.quantity}</td> <td>${Bitem.productId}</td> <td>${Bitem.quantity}</td> </tr>`; } table += `</table>`; output.innerHTML += summary + table; }); } function formatExcelDate(excelSerial) { if (typeof excelSerial === "number") { const date = new Date((excelSerial - 25569) * 86400 * 1000); return date.toISOString().split("T")[0]; // 转换为 YYYY-MM-DD 格式 } return excelSerial; // 非数字,可能已经是日期字符串 } </script>主要功能这是一个生产排班系统,能够:读取Excel文件中的生产数据按日期对产品进行分组将每个日期的生产任务智能分配到A班和B班尽量平衡两班的工作量(按产品数量)显示分配结果核心函数解析processFile() - 文件处理入口获取用户上传的Excel文件使用FileReader读取文件内容调用XLSX库解析Excel数据转换数据格式并调用分配逻辑splitProduction(data) - 核心分配逻辑按日期分组:groupedByDate对每个日期的产品按数量降序排序使用贪心算法分配:始终将当前产品分配给总数量较少的班次保持两班总数量尽可能平衡displayResult(data) - 结果展示为每个日期创建表格显示:A班和B班各自的产品列表两班的总数量对比产品种类数统计formatExcelDate() - 日期格式转换将Excel的序列日期值(如44197)转换为"YYYY-MM-DD"格式Excel日期是从1900年1月1日开始的天数数据结构输入数据格式:[[产品ID, 数量, 日期], ...]分组后结构:{ 日期: [{productId, quantity}, ...] }输出结果结构:{ 日期: { A:[], B:[], sumA, sumB, typesA, typesB } }算法特点使用贪心算法实现近似最优分配先排序再分配,确保大任务优先处理平衡两班总工作量,同时统计产品种类使用说明用户上传包含生产数据的Excel文件系统自动处理并显示分配结果结果展示包括:按日期分组的排班表两班工作量对比详细的产品分配情况这个系统适合生产制造企业用于日常生产任务分配,能有效平衡各班次的工作负荷,提高排班效率。核心分配逻辑 function splitProduction(data) { 定义名为 splitProduction 的函数,接收 data 参数(二维数组,格式为 [[产品ID, 数量, 日期], ...]) const groupedByDate = {}; 创建空对象 groupedByDate,用于按日期分组存储数据 javascript Copy Code data.forEach(row => { 遍历 data 数组中的每个元素 row const [productId, quantity, date] = row; 解构数组元素,将每行数据分解为 productId(产品ID)、quantity(数量)、date(日期) if (!groupedByDate[date]) groupedByDate[date] = []; 如果当前日期不存在于 groupedByDate 中,则创建空数组 groupedByDate[date].push({ productId, quantity }); 将当前行的产品ID和数量以对象形式存入对应日期的数组 }); 结束 data.forEach const result = {}; 创建空对象 result,用于存储最终结果 Object.keys(groupedByDate).forEach(date => { 遍历 groupedByDate 的所有日期键 const products = groupedByDate[date].sort((a, b) => b.quantity - a.quantity); 将当前日期的产品按数量降序排序(从大到小) let A = [], B = []; 初始化分组数组 A 和 B let sumA = 0, sumB = 0; 初始化分组总数量统计变量 products.forEach(item => { 遍历排序后的产品数组 if (sumA <= sumB) { 比较两组当前总数量,如果 A 组总和不大于 B 组 A.push(item); sumA += item.quantity; 将当前产品加入 A 组,并累加数量到 sumA } else { B.push(item); sumB += item.quantity; 否则加入 B 组,并累加数量到 sumB } }); 结束产品遍历 result[date] = { A, B, sumA, sumB, typesA: new Set(A.map(p => p.productId)).size, typesB: new Set(B.map(p => p.productId)).size }; 将结果存入 result 对象,包含: 分组数组 A/B 分组总数量 sumA/sumB 使用 Set 计算每组中不同产品ID的数量(去重后的种类数) }); 结束日期遍历 return result; } 返回最终结果对象主要功能:将每日的生产数据按数量降序排列后,通过贪心算法将产品分配到 A/B 两个组,尽可能平衡两组的总数量,同时统计每组的产品种类数量。返回按日期分组的结果。算法特点:优先分配大数量产品到当前总和较小的组,可有效减少分组后的数量差异,但不一定是最优解。时间复杂度为 O(n log n)(主要来自排序操作)。
2025年04月06日
4 阅读
0 评论
0 点赞
2025-04-03
自动排产实现
测试数据排产测试数据.xlsx分班测试.xlsx排产测试数据结果.xlsx排产逻辑:将缺件的产品先按缺件时间先后,再按数量从少到多的顺序进行排列,优先完成同一缺件时间的小批量订单。然后将无法完成的订单递延到第二天继续生产,仍然是优先完成同一缺件时间的小批量订单,检查排产日期是否超过交付时间,排产时间需要早交付时间一天,否则预警.考虑种类和难易程度对产量影响,建立内外嵌套循环,当种类超过阈值则自动终止,若未超过阈值则会排满
2025年04月03日
9 阅读
0 评论
0 点赞
2025-04-01
代码参数修改
function displaySchedule() { const tbody = document.querySelector('#scheduleTable tbody'); tbody.innerHTML = ''; // 按生产日期分组显示 const productionGroups = [...new Set(scheduleData.map(item => item.productionDate))].sort((a, b) => new Date(a) - new Date(b) ); console.log("fest",productionGroups); for (const productionDate of productionGroups) { // 获取该生产日期的所有排产记录 const productions = scheduleData.filter(item => item.productionDate === productionDate); // 检查该生产日期是否有超期订单 const hasLateOrders = productions.some(item => item.isLate); // 添加生产日期标题行 const headerRow = document.createElement('tr'); headerRow.style.backgroundColor = '#f0f0f0'; headerRow.innerHTML = ` <td colspan="6"> <strong>生产日期: ${productionDate}</strong> ${hasLateOrders ? '<span class="warning"> (有超期订单)</span>' : '<span class="on-time"> (全部按时)</span>'} </td> `; tbody.appendChild(headerRow); // 添加该生产日期的所有排产记录 for (const production of productions) { // 获取该生产记录对应的订单 const order = rawData.find(item => item.productId === production.productId && item.deliveryDate === production.deliveryDate ); if (order) { const row = document.createElement('tr'); if (production.isLate) { row.classList.add('warning'); } row.innerHTML = ` <td>${production.productId}</td> <td>${production.quantity}</td> <td>${production.deliveryDate}</td> <td>${production.dailyMax}</td> <td>${production.productionDate}</td> <td>${production.isLate ? '是' : '否'}</td> `; tbody.appendChild(row); } } } }调用API模块代码function generateSchedule() { const btn = document.getElementById('generateBtn'); const loading = document.getElementById('loading'); btn.disabled = true; loading.style.display = 'inline'; setTimeout(() => { try { console.log("开始调用后端生成排产计划..."); if (rawData.length === 0) { alert('请先导入Excel数据'); return; } const workers = parseInt(document.getElementById('workers').value) || 3; const productivity = parseInt(document.getElementById('productivity').value) || 70; const startDateStr = document.getElementById('startDate').value; if (!startDateStr) { alert('请设置排产开始日期'); return; } fetch('https://ytpmc.anhuihym.top/pmc/schedule.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: rawData, workers: workers, productivity: productivity, startDate: startDateStr }) }) .then(response => response.json()) .then(result => { if (result.success) { console.log("排产数据:", result.scheduleData); console.log("预警数据:", result.warningData); displaySchedule(result.scheduleData); displayWarnings(result.warningData); updateSummary(); // 5. 显示结果 displaySchedule(); displayWarnings(); updateSummary(); } else { alert('排产失败: ' + result.message); } }) .catch(error => { console.error("调用排产API出错:", error); alert('调用排产API出错: ' + error.message); }) .finally(() => { btn.disabled = false; loading.style.display = 'none'; }); } catch (error) { console.error("生成排产计划时出错:", error); alert('生成排产计划时出错: ' + error.message); btn.disabled = false; loading.style.display = 'none'; } }, 100); }函数概述displaySchedule() 函数负责将排产计划数据 scheduleData 显示在 HTML 表格中。它首先清空表格的 tbody 部分,然后根据生产日期对数据进行分组,并为每个组添加标题行和相应的排产记录行。外部变量依赖scheduleData:包含排产计划数据的数组。每个元素应包含 productionDate, productId, quantity, deliveryDate, dailyMax, 和 isLate 等属性。rawData:包含原始订单数据的数组。每个元素应包含 productId 和 deliveryDate 等属性,用于与 scheduleData 中的记录进行匹配。函数逻辑清空表格:使用 tbody.innerHTML = ''; 清空表格的 tbody 部分。按生产日期分组:使用 Set 和 map 方法获取唯一的生产日期列表,并按日期排序。遍历每个生产日期:为每个生产日期创建一个标题行,并根据是否有超期订单添加相应的警告信息。遍历该生产日期的所有排产记录:为每个排产记录创建一个表格行,并根据是否超期添加警告类。匹配订单数据:在创建排产记录行时,从 rawData 中找到对应的订单数据,以获取更详细的信息(虽然在当前函数实现中并未直接使用这些信息,但可能是为了后续扩展)。导致无法显示的主要原因是后端赋值时被全局变量作用域污染导致仍然时空数组、修复后如下if (result.success) { // 深拷贝数据(如需独立性) scheduleData = JSON.parse(JSON.stringify(result.scheduleData)); warningData = JSON.parse(JSON.stringify(result.warningData)); // 使用全局变量渲染 displaySchedule(scheduleData); displayWarnings(warningData); updateSummary(); }
2025年04月01日
15 阅读
0 评论
0 点赞
1
2
...
4
0:00