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

109 lines
6.5 KiB
HTML
Raw Normal View History

2026-07-21 11:05:57 +08:00
<!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>