94 lines
5.2 KiB
HTML
94 lines
5.2 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>
|
||
|
|
<div class="toolbar">
|
||
|
|
<button class="btn btn-primary" onclick="addRoutingModal()">+ 新增工艺路线</button>
|
||
|
|
</div>
|
||
|
|
<div id="routingCards"></div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<script src="../js/data.js"></script>
|
||
|
|
<script src="../js/common.js"></script>
|
||
|
|
<script>
|
||
|
|
initPage('routing');
|
||
|
|
function render() {
|
||
|
|
const container = document.getElementById('routingCards');
|
||
|
|
container.innerHTML = apsData.routings.map(r => {
|
||
|
|
const p = findById(apsData.materials, r.productId);
|
||
|
|
const steps = apsData.routingSteps.filter(s => s.routingId == r.id).sort((a, b) => a.sequenceNo - b.sequenceNo);
|
||
|
|
return `
|
||
|
|
<div class="card">
|
||
|
|
<div class="card-header">${r.versionName} <span class="text-muted">(${p ? p.name : ''})</span><span class="badge badge-${r.status==='ACTIVE'?'success':'default'} ml-2">${r.status}</span></div>
|
||
|
|
<div class="card-body">
|
||
|
|
<table>
|
||
|
|
<thead><tr><th>顺序</th><th>工序</th><th>准备时间</th><th>单位加工时间</th><th>等待时间</th><th>转移时间</th></tr></thead>
|
||
|
|
<tbody>
|
||
|
|
${steps.map(s => {
|
||
|
|
const op = findById(apsData.operations, s.operationId);
|
||
|
|
return `<tr><td>${s.sequenceNo}</td><td>${op ? op.name : ''}</td><td>${s.setupTime}</td><td>${s.runTimePerUnit}</td><td>${s.waitTime}</td><td>${s.transferTime}</td></tr>`;
|
||
|
|
}).join('')}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
<button class="btn btn-sm mt-2" onclick="addStepModal(${r.id})">+ 添加工序</button>
|
||
|
|
</div>
|
||
|
|
</div>`;
|
||
|
|
}).join('');
|
||
|
|
}
|
||
|
|
function addRoutingModal() {
|
||
|
|
const prodOpts = apsData.materials.filter(m => m.type === 'FINISHED_PRODUCT').map(m => `<option value="${m.id}">${m.name}</option>`).join('');
|
||
|
|
openModal('新增工艺路线', `
|
||
|
|
<div class="form-row"><div class="form-group"><label>产品</label><select id="r_prod">${prodOpts}</select></div><div class="form-group"><label>版本</label><input id="r_ver" value="V1.0"></div></div>
|
||
|
|
<div class="form-row"><div class="form-group"><label>版本名称</label><input id="r_name"></div></div>
|
||
|
|
`, `
|
||
|
|
<button class="btn" onclick="closeModal()">取消</button>
|
||
|
|
<button class="btn btn-primary" onclick="saveRouting()">保存</button>
|
||
|
|
`);
|
||
|
|
}
|
||
|
|
function saveRouting() {
|
||
|
|
const productId = Number(document.getElementById('r_prod').value);
|
||
|
|
const version = document.getElementById('r_ver').value.trim();
|
||
|
|
const name = document.getElementById('r_name').value.trim();
|
||
|
|
if (!version || !name) return showToast('校验失败', '请填写完整', 'error');
|
||
|
|
apsData.routings.push({ id: apsData.$utils.nextId('routing'), productId, version, versionName: name, isDefault: true, status: 'ACTIVE' });
|
||
|
|
apsData.$utils.save(apsData); closeModal(); showToast('保存成功'); render();
|
||
|
|
}
|
||
|
|
function addStepModal(routingId) {
|
||
|
|
const opOpts = apsData.operations.map(o => `<option value="${o.id}">${o.name}</option>`).join('');
|
||
|
|
openModal('添加工序', `
|
||
|
|
<div class="form-row"><div class="form-group"><label>工序</label><select id="s_op">${opOpts}</select></div><div class="form-group"><label>顺序</label><input id="s_seq" type="number" value="1"></div></div>
|
||
|
|
<div class="form-row"><div class="form-group"><label>准备时间(min)</label><input id="s_setup" type="number" value="30"></div><div class="form-group"><label>单位加工时间(min)</label><input id="s_run" type="number" step="0.1" value="1"></div></div>
|
||
|
|
<div class="form-row"><div class="form-group"><label>转移时间(min)</label><input id="s_transfer" type="number" value="10"></div></div>
|
||
|
|
`, `
|
||
|
|
<button class="btn" onclick="closeModal()">取消</button>
|
||
|
|
<button class="btn btn-primary" onclick="saveStep(${routingId})">保存</button>
|
||
|
|
`);
|
||
|
|
}
|
||
|
|
function saveStep(routingId) {
|
||
|
|
const steps = apsData.routingSteps.filter(s => s.routingId == routingId).sort((a, b) => a.sequenceNo - b.sequenceNo);
|
||
|
|
const seq = Number(document.getElementById('s_seq').value);
|
||
|
|
const prev = steps.find(s => s.sequenceNo == seq - 1);
|
||
|
|
apsData.routingSteps.push({
|
||
|
|
id: apsData.$utils.nextId('routingStep'), routingId, operationId: Number(document.getElementById('s_op').value), sequenceNo: seq,
|
||
|
|
prevStepId: prev ? prev.id : null, setupTime: Number(document.getElementById('s_setup').value),
|
||
|
|
runTimePerUnit: Number(document.getElementById('s_run').value), waitTime: 0, transferTime: Number(document.getElementById('s_transfer').value), isExternal: false
|
||
|
|
});
|
||
|
|
apsData.$utils.save(apsData); closeModal(); showToast('保存成功'); render();
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|