feat(client): 库存商品抽屉增加供应商与批次号信息行(两端,原型同步)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-14 09:40:16 +08:00
parent 7a9f480ae3
commit 7e020a04b3
4 changed files with 26 additions and 4 deletions
@@ -129,6 +129,8 @@ class _InventoryListScreenState extends ConsumerState<InventoryListScreen> {
status: _statusOf(item),
inventoryId: item.id,
inventoryStatus: item.status,
supplier: item.supplierName.isEmpty ? null : item.supplierName,
batchNo: item.batchNo.isEmpty ? null : item.batchNo,
onStatusChanged: () =>
ref.read(inventoryListProvider.notifier).reload(),
);
@@ -46,6 +46,8 @@ Future<void> showProductEditorDrawer(
String? status, // 在售 / 库存 / 已售(三态显示标签)
int? inventoryId, // 库存行 id:非空时状态行显示挂售 switch
String? inventoryStatus, // stock / on_sale / soldswitch 初始态)
String? supplier, // 供应商(生产日期行后,非空才显示,2026-07-14)
String? batchNo, // 批次号(生产日期行后,非空才显示,2026-07-14)
VoidCallback? onStatusChanged, // switch 切换成功后回调(列表刷新)
}) {
// 窄屏:底部 sheet 形态(原型 m-inventory openItem 内嵌公开页编辑)
@@ -64,6 +66,8 @@ Future<void> showProductEditorDrawer(
status: status,
inventoryId: inventoryId,
inventoryStatus: inventoryStatus,
supplier: supplier,
batchNo: batchNo,
onStatusChanged: onStatusChanged),
),
);
@@ -94,6 +98,8 @@ Future<void> showProductEditorDrawer(
status: status,
inventoryId: inventoryId,
inventoryStatus: inventoryStatus,
supplier: supplier,
batchNo: batchNo,
onStatusChanged: onStatusChanged),
),
),
@@ -119,6 +125,8 @@ class _ProductEditorDrawer extends ConsumerStatefulWidget {
final String? status;
final int? inventoryId;
final String? inventoryStatus;
final String? supplier;
final String? batchNo;
final VoidCallback? onStatusChanged;
const _ProductEditorDrawer({
required this.productId,
@@ -128,6 +136,8 @@ class _ProductEditorDrawer extends ConsumerStatefulWidget {
this.status,
this.inventoryId,
this.inventoryStatus,
this.supplier,
this.batchNo,
this.onStatusChanged,
});
@@ -397,6 +407,13 @@ class _ProductEditorDrawerState extends ConsumerState<_ProductEditorDrawer> {
if ((p.productionDate ?? '').isNotEmpty) {
rows.add(('生产日期', b(p.productionDate!, mono: true)));
}
// 批次号/供应商行(生产日期后,非空才渲染,2026-07-14)
if ((widget.batchNo ?? '').isNotEmpty) {
rows.add(('批次号', b(widget.batchNo!, mono: true)));
}
if ((widget.supplier ?? '').isNotEmpty) {
rows.add(('供应商', b(widget.supplier!)));
}
if (widget.qty != null) {
rows.add((
'当前库存',
+3 -3
View File
@@ -89,13 +89,13 @@ function drawFilterSheet(){
}
function mfTgl(k,v){ state[k].has(v)?state[k].delete(v):state[k].add(v); drawFilterSheet(); render(); }
function openFilterSheet(){ drawFilterSheet(); }
// 详情 sheet 行序对齐真实商品抽屉(编码/系列/规格/生产日期/当前库存/成本×2/状态);
// 成本两行仅管理员可见(2026-07-06),原型=管理员形态;生产日期行 2026-07-10。
// 详情 sheet 行序对齐真实商品抽屉(编码/系列/规格/生产日期/批次号/供应商/当前库存/成本×2/状态);
// 成本两行仅管理员可见(2026-07-06),原型=管理员形态;生产日期行 2026-07-10;批次号/供应商行 2026-07-14
function openItem(idx){ const it=ITEMS[idx];
if(!peEdit||peEdit.idx!==idx) peEdit={idx,imgs:[PE_SAMPLE[0],'',''],introName:'',introBody:''};
const hasIntro=!!peEdit.introName;
const totalCost='¥'+Math.round(parseFloat(it.cost.replace(/[¥,]/g,''))*it.qty).toLocaleString();
openSheet(it.name, `<div class="drow"><span>编码</span><b style="font-family:var(--font-mono)">${it.code}</b></div><div class="drow"><span>系列</span><b>${it.series}</b></div><div class="drow"><span>规格</span><b>${it.spec}</b></div><div class="drow"><span>生产日期</span><b style="font-family:var(--font-mono)">${it.prod}</b></div><div class="drow"><span>当前库存</span><b>${it.qty} ${it.unit}</b></div><div class="drow"><span>成本价(单瓶)</span><b>${it.cost}</b></div><div class="drow"><span>总成本价</span><b>${totalCost}</b></div><div class="drow" style="border-bottom:none"><span>状态</span><b style="display:flex;align-items:center;gap:10px"><span class="badge b-${it.status}">${it.status}</span>${it.status==='已售'?'':`<button class="switch ${it.status==='在售'?'on':''}" aria-label="挂售切换" onclick="this.classList.toggle('on');const b=this.previousElementSibling;const on=this.classList.contains('on');b.textContent=on?'在售':'库存';b.className='badge '+(on?'b-在售':'b-库存');"></button>`}</b></div>
openSheet(it.name, `<div class="drow"><span>编码</span><b style="font-family:var(--font-mono)">${it.code}</b></div><div class="drow"><span>系列</span><b>${it.series}</b></div><div class="drow"><span>规格</span><b>${it.spec}</b></div><div class="drow"><span>生产日期</span><b style="font-family:var(--font-mono)">${it.prod}</b></div><div class="drow"><span>批次号</span><b style="font-family:var(--font-mono)">${it.batch}</b></div><div class="drow"><span>供应商</span><b>${it.supplier}</b></div><div class="drow"><span>当前库存</span><b>${it.qty} ${it.unit}</b></div><div class="drow"><span>成本价(单瓶)</span><b>${it.cost}</b></div><div class="drow"><span>总成本价</span><b>${totalCost}</b></div><div class="drow" style="border-bottom:none"><span>状态</span><b style="display:flex;align-items:center;gap:10px"><span class="badge b-${it.status}">${it.status}</span>${it.status==='已售'?'':`<button class="switch ${it.status==='在售'?'on':''}" aria-label="挂售切换" onclick="this.classList.toggle('on');const b=this.previousElementSibling;const on=this.classList.contains('on');b.textContent=on?'在售':'库存';b.className='badge '+(on?'b-在售':'b-库存');"></button>`}</b></div>
<div class="pe-card" style="margin-top:14px"><div class="pe-h"><span class="pe-ic"><svg viewBox="0 0 24 24"><use href="#i-ic27"/></svg></span>商品图片</div>
<div class="pe-b"><div class="pe-gallery" id="mGallery"></div><div class="pe-note">建议主图为白底产品图,可再加细节图(瓶身/防伪)与场景图。</div></div></div>
<div class="pe-card"><div class="pe-h"><span class="pe-ic"><svg viewBox="0 0 24 24"><use href="#i-ic28"/></svg></span>商品介绍 / 卖点</div>
+4 -1
View File
@@ -1,7 +1,7 @@
// ============================================================
// 商品编辑抽屉 单一真源 —— 商品信息 + 商品图片 + 商品介绍 + 预览
// 用法:任意屏引入 <script src="product-editor.js"></script>(需先引 shell.js 取 openMenu/toast),
// 行点击调用 openProductEditor(item)。item 字段按需:{name,code,series,spec,cat,prodDate,qty,unit,cost,value,status}
// 行点击调用 openProductEditor(item)。item 字段按需:{name,code,series,spec,cat,prodDate,batch,supplier,qty,unit,cost,value,status}
// 改这个抽屉(库存 / 基础数据共用)= 只改此文件 + atoms.css 的 .pe-* 样式。
// ============================================================
(function () {
@@ -65,6 +65,9 @@
if (it.cat) r.push(['分类', `<b>${it.cat}</b>`]);
// 生产日期行(分类后、当前库存前,mono,2026-07-10
if (it.prodDate) r.push(['生产日期', `<b style="font-family:var(--font-mono)">${it.prodDate}</b>`]);
// 批次号/供应商行(生产日期后,2026-07-14)
if (it.batch) r.push(['批次号', `<b style="font-family:var(--font-mono)">${it.batch}</b>`]);
if (it.supplier) r.push(['供应商', `<b>${it.supplier}</b>`]);
if (it.qty != null) r.push(['当前库存', `<b>${it.qty} ${it.unit || ''}</b>`]);
// 成本两行仅管理员可见(非管理员隐藏,与库存列表/出库同口径,2026-07-06);原型=管理员形态
if (it.cost) r.push(['成本价(单瓶)', `<b>${it.cost}</b>`]);