feat(client): 库存商品抽屉增加供应商与批次号信息行(两端,原型同步)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -129,6 +129,8 @@ class _InventoryListScreenState extends ConsumerState<InventoryListScreen> {
|
|||||||
status: _statusOf(item),
|
status: _statusOf(item),
|
||||||
inventoryId: item.id,
|
inventoryId: item.id,
|
||||||
inventoryStatus: item.status,
|
inventoryStatus: item.status,
|
||||||
|
supplier: item.supplierName.isEmpty ? null : item.supplierName,
|
||||||
|
batchNo: item.batchNo.isEmpty ? null : item.batchNo,
|
||||||
onStatusChanged: () =>
|
onStatusChanged: () =>
|
||||||
ref.read(inventoryListProvider.notifier).reload(),
|
ref.read(inventoryListProvider.notifier).reload(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ Future<void> showProductEditorDrawer(
|
|||||||
String? status, // 在售 / 库存 / 已售(三态显示标签)
|
String? status, // 在售 / 库存 / 已售(三态显示标签)
|
||||||
int? inventoryId, // 库存行 id:非空时状态行显示挂售 switch
|
int? inventoryId, // 库存行 id:非空时状态行显示挂售 switch
|
||||||
String? inventoryStatus, // stock / on_sale / sold(switch 初始态)
|
String? inventoryStatus, // stock / on_sale / sold(switch 初始态)
|
||||||
|
String? supplier, // 供应商(生产日期行后,非空才显示,2026-07-14)
|
||||||
|
String? batchNo, // 批次号(生产日期行后,非空才显示,2026-07-14)
|
||||||
VoidCallback? onStatusChanged, // switch 切换成功后回调(列表刷新)
|
VoidCallback? onStatusChanged, // switch 切换成功后回调(列表刷新)
|
||||||
}) {
|
}) {
|
||||||
// 窄屏:底部 sheet 形态(原型 m-inventory openItem 内嵌公开页编辑)
|
// 窄屏:底部 sheet 形态(原型 m-inventory openItem 内嵌公开页编辑)
|
||||||
@@ -64,6 +66,8 @@ Future<void> showProductEditorDrawer(
|
|||||||
status: status,
|
status: status,
|
||||||
inventoryId: inventoryId,
|
inventoryId: inventoryId,
|
||||||
inventoryStatus: inventoryStatus,
|
inventoryStatus: inventoryStatus,
|
||||||
|
supplier: supplier,
|
||||||
|
batchNo: batchNo,
|
||||||
onStatusChanged: onStatusChanged),
|
onStatusChanged: onStatusChanged),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -94,6 +98,8 @@ Future<void> showProductEditorDrawer(
|
|||||||
status: status,
|
status: status,
|
||||||
inventoryId: inventoryId,
|
inventoryId: inventoryId,
|
||||||
inventoryStatus: inventoryStatus,
|
inventoryStatus: inventoryStatus,
|
||||||
|
supplier: supplier,
|
||||||
|
batchNo: batchNo,
|
||||||
onStatusChanged: onStatusChanged),
|
onStatusChanged: onStatusChanged),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -119,6 +125,8 @@ class _ProductEditorDrawer extends ConsumerStatefulWidget {
|
|||||||
final String? status;
|
final String? status;
|
||||||
final int? inventoryId;
|
final int? inventoryId;
|
||||||
final String? inventoryStatus;
|
final String? inventoryStatus;
|
||||||
|
final String? supplier;
|
||||||
|
final String? batchNo;
|
||||||
final VoidCallback? onStatusChanged;
|
final VoidCallback? onStatusChanged;
|
||||||
const _ProductEditorDrawer({
|
const _ProductEditorDrawer({
|
||||||
required this.productId,
|
required this.productId,
|
||||||
@@ -128,6 +136,8 @@ class _ProductEditorDrawer extends ConsumerStatefulWidget {
|
|||||||
this.status,
|
this.status,
|
||||||
this.inventoryId,
|
this.inventoryId,
|
||||||
this.inventoryStatus,
|
this.inventoryStatus,
|
||||||
|
this.supplier,
|
||||||
|
this.batchNo,
|
||||||
this.onStatusChanged,
|
this.onStatusChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -397,6 +407,13 @@ class _ProductEditorDrawerState extends ConsumerState<_ProductEditorDrawer> {
|
|||||||
if ((p.productionDate ?? '').isNotEmpty) {
|
if ((p.productionDate ?? '').isNotEmpty) {
|
||||||
rows.add(('生产日期', b(p.productionDate!, mono: true)));
|
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) {
|
if (widget.qty != null) {
|
||||||
rows.add((
|
rows.add((
|
||||||
'当前库存',
|
'当前库存',
|
||||||
|
|||||||
@@ -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 mfTgl(k,v){ state[k].has(v)?state[k].delete(v):state[k].add(v); drawFilterSheet(); render(); }
|
||||||
function openFilterSheet(){ drawFilterSheet(); }
|
function openFilterSheet(){ drawFilterSheet(); }
|
||||||
// 详情 sheet 行序对齐真实商品抽屉(编码/系列/规格/生产日期/当前库存/成本×2/状态);
|
// 详情 sheet 行序对齐真实商品抽屉(编码/系列/规格/生产日期/批次号/供应商/当前库存/成本×2/状态);
|
||||||
// 成本两行仅管理员可见(2026-07-06),原型=管理员形态;生产日期行 2026-07-10。
|
// 成本两行仅管理员可见(2026-07-06),原型=管理员形态;生产日期行 2026-07-10;批次号/供应商行 2026-07-14。
|
||||||
function openItem(idx){ const it=ITEMS[idx];
|
function openItem(idx){ const it=ITEMS[idx];
|
||||||
if(!peEdit||peEdit.idx!==idx) peEdit={idx,imgs:[PE_SAMPLE[0],'',''],introName:'',introBody:''};
|
if(!peEdit||peEdit.idx!==idx) peEdit={idx,imgs:[PE_SAMPLE[0],'',''],introName:'',introBody:''};
|
||||||
const hasIntro=!!peEdit.introName;
|
const hasIntro=!!peEdit.introName;
|
||||||
const totalCost='¥'+Math.round(parseFloat(it.cost.replace(/[¥,]/g,''))*it.qty).toLocaleString();
|
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-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-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>
|
<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
@@ -1,7 +1,7 @@
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
// 商品编辑抽屉 单一真源 —— 商品信息 + 商品图片 + 商品介绍 + 预览
|
// 商品编辑抽屉 单一真源 —— 商品信息 + 商品图片 + 商品介绍 + 预览
|
||||||
// 用法:任意屏引入 <script src="product-editor.js"></script>(需先引 shell.js 取 openMenu/toast),
|
// 用法:任意屏引入 <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-* 样式。
|
// 改这个抽屉(库存 / 基础数据共用)= 只改此文件 + atoms.css 的 .pe-* 样式。
|
||||||
// ============================================================
|
// ============================================================
|
||||||
(function () {
|
(function () {
|
||||||
@@ -65,6 +65,9 @@
|
|||||||
if (it.cat) r.push(['分类', `<b>${it.cat}</b>`]);
|
if (it.cat) r.push(['分类', `<b>${it.cat}</b>`]);
|
||||||
// 生产日期行(分类后、当前库存前,mono,2026-07-10)
|
// 生产日期行(分类后、当前库存前,mono,2026-07-10)
|
||||||
if (it.prodDate) r.push(['生产日期', `<b style="font-family:var(--font-mono)">${it.prodDate}</b>`]);
|
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>`]);
|
if (it.qty != null) r.push(['当前库存', `<b>${it.qty} ${it.unit || ''}</b>`]);
|
||||||
// 成本两行仅管理员可见(非管理员隐藏,与库存列表/出库同口径,2026-07-06);原型=管理员形态
|
// 成本两行仅管理员可见(非管理员隐藏,与库存列表/出库同口径,2026-07-06);原型=管理员形态
|
||||||
if (it.cost) r.push(['成本价(单瓶)', `<b>${it.cost}</b>`]);
|
if (it.cost) r.push(['成本价(单瓶)', `<b>${it.cost}</b>`]);
|
||||||
|
|||||||
Reference in New Issue
Block a user