aps-agent/aps-frontend/pages/materials.html

111 lines
6.0 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>物料与BOM - 智能排产系统</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">物料与 BOM</h1>
<div class="toolbar">
<button class="btn btn-primary" onclick="addMaterialModal()">+ 新增物料</button>
<select id="typeFilter" class="btn" style="padding:7px 10px" onchange="render()">
<option value="">全部类型</option><option value="RAW_MATERIAL">原材料</option><option value="FINISHED_PRODUCT">成品</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="matTable">
<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>
</main>
</div>
</div>
<script src="../js/data.js"></script>
<script src="../js/common.js"></script>
<script>
initPage('materials');
function render() {
const type = document.getElementById('typeFilter').value;
const kw = document.getElementById('searchInput').value.toLowerCase();
const tbody = document.querySelector('#matTable tbody');
let rows = apsData.materials.filter(m => {
if (type && m.type !== type) return false;
return !kw || (m.code + ' ' + m.name).toLowerCase().includes(kw);
});
tbody.innerHTML = rows.map(m => `
<tr>
<td>${m.code}</td>
<td>${m.name}</td>
<td>${m.spec}</td>
<td>${m.type === 'RAW_MATERIAL' ? '原材料' : '成品'}</td>
<td>${m.unit}</td>
<td>${m.stock}</td>
<td>${m.inTransit}</td>
<td>${m.safetyStock}</td>
<td class="actions">
${m.type === 'FINISHED_PRODUCT' ? `<button class="btn btn-sm" onclick="viewBom(${m.id})">BOM</button>` : ''}
<button class="btn btn-sm" onclick="editStock(${m.id})">库存</button>
</td>
</tr>`).join('') || '<tr><td colspan="9" class="text-center text-muted">无数据</td></tr>';
}
function viewBom(productId) {
const p = findById(apsData.materials, productId);
const bom = apsData.boms.find(b => b.productId == productId && b.isDefault);
const items = bom ? apsData.bomItems.filter(i => i.bomId == bom.id).map(i => {
const m = findById(apsData.materials, i.materialId);
return `<tr><td>${m.code}</td><td>${m.name}</td><td>${i.quantity}</td><td>${m.unit}</td><td>${i.isKeyMaterial?'是':'否'}</td></tr>`;
}).join('') : '';
openModal(`${p.name} BOM`, `<table><thead><tr><th>物料编码</th><th>物料名称</th><th>用量</th><th>单位</th><th>关键物料</th></tr></thead><tbody>${items || '<tr><td colspan="5" class="text-center">无BOM</td></tr>'}</tbody></table>`, '', true);
}
function editStock(id) {
const m = findById(apsData.materials, id);
openModal('调整库存', `
<div class="form-row"><div class="form-group"><label>当前库存</label><input id="s_stock" type="number" value="${m.stock}"></div><div class="form-group"><label>在途库存</label><input id="s_transit" type="number" value="${m.inTransit}"></div></div>
`, `
<button class="btn" onclick="closeModal()">取消</button>
<button class="btn btn-primary" onclick="saveStock(${id})">保存</button>
`);
}
function saveStock(id) {
const m = findById(apsData.materials, id);
m.stock = Number(document.getElementById('s_stock').value);
m.inTransit = Number(document.getElementById('s_transit').value);
apsData.$utils.save(apsData); closeModal(); showToast('库存更新成功'); render();
}
function addMaterialModal() {
openModal('新增物料', `
<div class="form-row"><div class="form-group"><label>物料编码</label><input id="m_code"></div><div class="form-group"><label>物料名称</label><input id="m_name"></div></div>
<div class="form-row"><div class="form-group"><label>规格</label><input id="m_spec"></div><div class="form-group"><label>类型</label><select id="m_type"><option value="RAW_MATERIAL">原材料</option><option value="FINISHED_PRODUCT">成品</option></select></div></div>
<div class="form-row"><div class="form-group"><label>单位</label><input id="m_unit" value="件"></div><div class="form-group"><label>库存</label><input id="m_stock" type="number" value="0"></div></div>
`, `
<button class="btn" onclick="closeModal()">取消</button>
<button class="btn btn-primary" onclick="saveMaterial()">保存</button>
`);
}
function saveMaterial() {
const code = document.getElementById('m_code').value.trim();
const name = document.getElementById('m_name').value.trim();
if (!code || !name) return showToast('校验失败', '请填写编码和名称', 'error');
apsData.materials.push({
id: apsData.$utils.nextId('material'), code, name, spec: document.getElementById('m_spec').value,
type: document.getElementById('m_type').value, unit: document.getElementById('m_unit').value,
safetyStock: 0, procurementLeadTime: 0, stock: Number(document.getElementById('m_stock').value), inTransit: 0
});
apsData.$utils.save(apsData); closeModal(); showToast('保存成功'); render();
}
render();
</script>
</body>
</html>