78 lines
4.3 KiB
HTML
78 lines
4.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>工单拖拽调整 - 智能排产系统</title>
|
|
<link rel="stylesheet" href="../css/common.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<header class="header" id="header"></header>
|
|
<div class="body">
|
|
<aside class="sidebar" id="sidebar"></aside>
|
|
<main class="main">
|
|
<h1 class="page-title">工单拖拽调整</h1>
|
|
<p class="page-desc">对未冻结工单进行时间偏移、产线变更或状态调整,系统自动校验冲突。</p>
|
|
<div class="toolbar">
|
|
<select id="lineFilter" class="btn" style="padding:7px 10px" onchange="render()"><option value="">全部产线</option></select>
|
|
<button class="btn" onclick="render()">刷新</button>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-body table-wrap">
|
|
<table id="woTable">
|
|
<thead><tr><th>工单号</th><th>工序</th><th>产品</th><th>产线/工位</th><th>计划开始</th><th>偏移</th><th>新产线</th><th>操作</th></tr></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
<script src="../js/data.js"></script>
|
|
<script src="../js/common.js"></script>
|
|
<script>
|
|
initPage('work-order-adjust');
|
|
const lineSel = document.getElementById('lineFilter');
|
|
lineSel.innerHTML = '<option value="">全部产线</option>' + apsData.lines.map(l => `<option value="${l.id}">${l.name}</option>`).join('');
|
|
function render() {
|
|
const lineId = lineSel.value;
|
|
let rows = apsData.workOrders.filter(wo => !wo.isFrozen && wo.status !== 'COMPLETED' && wo.status !== 'CANCELLED');
|
|
if (lineId) rows = rows.filter(wo => wo.lineId == lineId);
|
|
rows.sort((a, b) => apsData.$utils.parseDate(a.plannedStartTime) - apsData.$utils.parseDate(b.plannedStartTime));
|
|
const tbody = document.querySelector('#woTable tbody');
|
|
tbody.innerHTML = rows.map(wo => {
|
|
const lineOpts = apsData.lines.map(l => `<option value="${l.id}" ${l.id==wo.lineId?'selected':''}>${l.name}</option>`).join('');
|
|
return `<tr>
|
|
<td>${wo.orderNo}</td><td>${wo.operationName}</td><td>${wo.productName}</td><td>${wo.lineName} / ${wo.workstationName}</td>
|
|
<td>${wo.plannedStartTime.slice(0,16)}</td>
|
|
<td><input type="number" id="off_${wo.id}" value="0" style="width:70px"> h</td>
|
|
<td><select id="line_${wo.id}">${lineOpts}</select></td>
|
|
<td class="actions"><button class="btn btn-sm btn-primary" onclick="applyAdjust(${wo.id})">应用</button></td>
|
|
</tr>`;
|
|
}).join('') || '<tr><td colspan="8" class="text-center text-muted">无数据</td></tr>';
|
|
}
|
|
function applyAdjust(id) {
|
|
const wo = findById(apsData.workOrders, id);
|
|
const offset = Number(document.getElementById('off_' + id).value) * 60;
|
|
const newLineId = Number(document.getElementById('line_' + id).value);
|
|
const newStart = apsData.$utils.addMinutes(apsData.$utils.parseDate(wo.plannedStartTime), offset);
|
|
const check = checkMoveConflict(wo, apsData.$utils.fmtDateTime(newStart));
|
|
if (!check.canApply) return showToast('调整失败', check.conflicts.map(c => c.message).join('; '), 'error');
|
|
const dur = apsData.$utils.parseDate(wo.plannedEndTime) - apsData.$utils.parseDate(wo.plannedStartTime);
|
|
wo.plannedStartTime = apsData.$utils.fmtDateTime(newStart);
|
|
wo.plannedEndTime = apsData.$utils.fmtDateTime(new Date(newStart.getTime() + dur));
|
|
if (newLineId !== wo.lineId) {
|
|
const line = findById(apsData.lines, newLineId);
|
|
wo.lineId = newLineId; wo.lineName = line.name;
|
|
const ws = findWorkstationForOperation(newLineId, wo.operationId);
|
|
if (ws) { wo.workstationId = ws.id; wo.workstationName = ws.name; }
|
|
}
|
|
apsData.logs.unshift({ id: apsData.$utils.nextId('log'), type: 'INFO', category: 'WO', operationType: 'ADJUST', targetType: 'WORK_ORDER', targetId: id, action: '工单调整', description: `工单 ${wo.orderNo} 时间偏移 ${offset/60}h`, operator: 'admin', createdAt: apsData.$utils.fmtDateTime(new Date()) });
|
|
apsData.$utils.save(apsData); showToast('调整成功', wo.orderNo); render();
|
|
}
|
|
render();
|
|
</script>
|
|
</body>
|
|
</html>
|