aps-agent/aps-frontend/pages/production-orders.html

109 lines
6.5 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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">
<select id="statusFilter" class="btn" style="padding:7px 10px" onchange="render()">
<option value="">全部状态</option>
<option value="DRAFT">草稿</option>
<option value="CONFIRMED">已确认</option>
<option value="ISSUED">已下发</option>
<option value="IN_PROGRESS">执行中</option>
<option value="COMPLETED">已完成</option>
<option value="CLOSED">已关闭</option>
</select>
<div class="search-box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg><input id="searchInput" placeholder="搜索订单号/产品" oninput="render()"></div>
</div>
<div class="card">
<div class="card-body table-wrap">
<table id="poTable">
<thead><tr><th>生产订单</th><th>销售订单</th><th>产品</th><th>数量</th><th>产线</th><th>计划起止</th><th>状态</th><th>冲突</th><th>操作</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="card-footer flex justify-between">
<span id="totalInfo" class="text-muted"></span>
<div id="pagination" class="pagination"></div>
</div>
</div>
</main>
</div>
</div>
<script src="../js/data.js"></script>
<script src="../js/common.js"></script>
<script>
initPage('production-orders');
let page = 1, pageSize = 10;
function render(pg) {
if (pg) page = pg;
const st = document.getElementById('statusFilter').value;
const kw = document.getElementById('searchInput').value.toLowerCase();
let rows = apsData.productionOrders.filter(po => {
if (st && po.status !== st) return false;
const text = (po.orderNo + ' ' + po.productName + ' ' + po.salesOrderNo).toLowerCase();
return !kw || text.includes(kw);
}).sort((a, b) => b.id - a.id);
const total = rows.length;
rows = rows.slice((page - 1) * pageSize, page * pageSize);
const tbody = document.querySelector('#poTable tbody');
tbody.innerHTML = rows.map(po => `
<tr>
<td>${po.orderNo}</td>
<td><a href="orders.html">${po.salesOrderNo}</a></td>
<td>${po.productName}</td>
<td>${po.quantity}</td>
<td>${po.lineName}</td>
<td>${po.plannedStartDate ? po.plannedStartDate.slice(0,10) : ''} ~ ${po.plannedEndDate ? po.plannedEndDate.slice(0,10) : ''}</td>
<td>${statusBadge(po.status, { DRAFT:'default', CONFIRMED:'primary', ISSUED:'warning', IN_PROGRESS:'warning', COMPLETED:'success', CLOSED:'default', CANCELLED:'danger' })}</td>
<td>${po.conflictCount || 0}</td>
<td class="actions">
<button class="btn btn-sm" onclick="viewPo(${po.id})">详情</button>
${po.status === 'DRAFT' ? `<button class="btn btn-sm btn-success" onclick="confirmPo(${po.id})">确认</button>` : ''}
${po.status === 'CONFIRMED' ? `<button class="btn btn-sm btn-danger" onclick="revokePo(${po.id})">撤销</button>` : ''}
</td>
</tr>`).join('') || '<tr><td colspan="9" class="text-center text-muted">无数据</td></tr>';
document.getElementById('totalInfo').textContent = `共 ${total} 条`;
renderPagination('pagination', page, total, pageSize, 'render');
}
function viewPo(id) {
const po = findById(apsData.productionOrders, id);
const wos = apsData.workOrders.filter(wo => wo.productionOrderId == id).map(wo => `<li>${wo.orderNo} ${wo.operationName} ${wo.plannedStartTime.slice(0,16)} ~ ${wo.plannedEndTime.slice(0,16)}</li>`).join('');
openModal('生产订单详情', `
<div class="form-row"><div class="form-group"><label>生产订单号</label><input value="${po.orderNo}" readonly></div><div class="form-group"><label>销售订单</label><input value="${po.salesOrderNo}" readonly></div></div>
<div class="form-row"><div class="form-group"><label>产品</label><input value="${po.productName} × ${po.quantity}" readonly></div><div class="form-group"><label>产线</label><input value="${po.lineName}" readonly></div></div>
<div class="form-row"><div class="form-group"><label>计划开始</label><input value="${po.plannedStartDate}" readonly></div><div class="form-group"><label>计划结束</label><input value="${po.plannedEndDate}" readonly></div></div>
<div class="form-row"><div class="form-group"><label>排产引擎</label><input value="${po.schedulingEngine}" readonly></div><div class="form-group"><label>约束状态</label><input value="${po.constraintCheckStatus}" readonly></div></div>
<p><strong>工单清单:</strong></p><ul>${wos}</ul>
`, '', true);
}
function confirmPo(id) {
const po = findById(apsData.productionOrders, id); po.status = 'CONFIRMED';
apsData.logs.unshift({ id: apsData.$utils.nextId('log'), type: 'INFO', category: 'ORDER', operationType: 'CONFIRM', targetType: 'PRODUCTION_ORDER', targetId: id, action: '确认生产订单', description: `生产订单 ${po.orderNo} 已确认`, operator: 'admin', createdAt: apsData.$utils.fmtDateTime(new Date()) });
apsData.$utils.save(apsData); showToast('确认成功', po.orderNo); render();
}
function revokePo(id) {
confirmAction('撤销后资源将释放,确定吗?', `revokePoExec(${id})`);
}
function revokePoExec(id) {
const po = findById(apsData.productionOrders, id); po.status = 'CANCELLED';
apsData.workOrders.filter(wo => wo.productionOrderId == id).forEach(wo => wo.status = 'CANCELLED');
apsData.logs.unshift({ id: apsData.$utils.nextId('log'), type: 'WARNING', category: 'ORDER', operationType: 'CANCEL', targetType: 'PRODUCTION_ORDER', targetId: id, action: '撤销生产订单', description: `生产订单 ${po.orderNo} 已撤销`, operator: 'admin', createdAt: apsData.$utils.fmtDateTime(new Date()) });
apsData.$utils.save(apsData); showToast('撤销成功', po.orderNo); render();
}
render();
</script>
</body>
</html>