- 前端: 数量输入框改为 text/inputmode=numeric/maxlength=1,新增 capQty 实时拦截非个位(去非数字、限1位、超范围清空) - 后端: 新增 _bom_qty_invalid 校验,order_new/order_edit 拒绝非个位数量并回显已填内容,提示「每个 BOM 的生产数量需为 1–9 的个位正整数」 Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
72 lines
3.6 KiB
HTML
72 lines
3.6 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}{{ '编辑生产订单' if o else '新建生产订单' }}{% endblock %}
|
||
{% block content %}
|
||
<form method="post" class="card form-card" style="max-width:720px"
|
||
action="{{ url_for('order_edit', oid=o.id) if o else url_for('order_new') }}"
|
||
{% if o %}onsubmit="return confirm('确认保存修改?已录入的调入数量与已入账流水将保持不变(被移除 BOM 中已入账的物料仍保留其流水)。');"{% endif %}>
|
||
<h3>{{ '编辑生产订单' if o else '新建生产订单' }}</h3>
|
||
<label>订单号 {% if o %}(单号不可重复){% else %}(留空自动生成){% endif %}</label>
|
||
<input name="order_no" value="{{ o.order_no if o else '' }}" placeholder="如 WO20260911xxx">
|
||
|
||
<label>BOM 与生产数量 *</label>
|
||
<p class="small muted" style="margin:0 0 6px">可在同一订单中加入多个 BOM,每个 BOM 独立填写生产数量(限 <b>1–9 的个位正整数</b>);点击「+ 添加 BOM」增加一行,不需要的行可删除。</p>
|
||
<div id="bomRows" class="bom-rows"></div>
|
||
<button type="button" class="btn" style="margin:2px 0 12px" onclick="addBomRow()">+ 添加 BOM</button>
|
||
|
||
<label>生产工厂</label>
|
||
<select name="factory_id">
|
||
<option value="">-- 不指定(汇总库存校验)--</option>
|
||
{% for f in factories %}
|
||
<option value="{{ f.id }}" {% if o and o.factory_id == f.id %}selected{% endif %}>{{ f.code }} · {{ f.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<label>备注</label>
|
||
<input name="remark" value="{{ o.remark if o else '' }}" placeholder="选填">
|
||
<div class="row-actions">
|
||
<button class="primary">{{ '保存修改' if o else '生成订单' }}</button>
|
||
<a class="btn" href="{{ url_for('orders') }}">取消</a>
|
||
</div>
|
||
<p class="small muted">生成后可在订单详情页按各 BOM 展开领料需求, 并手动录入每个物料的「调入数量」。</p>
|
||
</form>
|
||
|
||
{# 隐藏模板: 供 JS 克隆(含全部 BOM 选项) #}
|
||
<template id="bomTpl">
|
||
<div class="bom-row" style="display:flex; gap:10px; align-items:center; margin-bottom:6px">
|
||
<select name="bom_id[]" required>
|
||
<option value="">-- 选择 BOM --</option>
|
||
{% for b in boms %}<option value="{{ b.id }}">{{ b.code }}{% if b.name %} · {{ b.name }}{% endif %}</option>{% endfor %}
|
||
</select>
|
||
<input name="qty[]" type="text" inputmode="numeric" maxlength="1" required placeholder="数量 1-9" style="width:110px" oninput="capQty(this)">
|
||
<button type="button" class="link-danger" onclick="this.closest('.bom-row').remove();checkRows()">删除</button>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
function capQty(el){
|
||
// 仅允许 1–9 的个位正整数: 去非数字、限制 1 位、超出范围清空
|
||
var v = (el.value || '').replace(/[^0-9]/g, '');
|
||
if (v.length > 1) v = v.slice(0, 1);
|
||
if (v !== '' && (parseInt(v, 10) < 1 || parseInt(v, 10) > 9)) v = '';
|
||
el.value = v;
|
||
}
|
||
function addBomRow(sel, qty){
|
||
var tpl = document.getElementById('bomTpl');
|
||
var row = tpl.content.firstElementChild.cloneNode(true);
|
||
if (sel) row.querySelector('select').value = String(sel);
|
||
if (qty != null && qty !== undefined) row.querySelector('input').value = qty;
|
||
document.getElementById('bomRows').appendChild(row);
|
||
checkRows();
|
||
}
|
||
function checkRows(){
|
||
var rows = document.querySelectorAll('#bomRows .bom-row');
|
||
rows.forEach(function(r){
|
||
var btn = r.querySelector('button');
|
||
if (btn) btn.style.display = rows.length > 1 ? '' : 'none';
|
||
});
|
||
}
|
||
var init = {{ initial_lines|tojson }};
|
||
if (init && init.length){ init.forEach(function(x){ addBomRow(x[0], x[1]); }); }
|
||
else { addBomRow(); }
|
||
</script>
|
||
{% endblock %}
|