feat(client): 库存三态 UI——抽屉挂售 switch + 三态徽章/筛选/已售 KPI 卡

- 新组件 DsSwitch(原型 atoms .switch 对照,L1 已登记:38×22 pill,on=primary)
- 商品抽屉状态行:三态徽章后跟挂售 switch(在售⇄库存 即时生效,已售只读,
  readonly 禁用),桌面 drawer / 移动 sheet 同组件
- 列表状态列/卡片徽章三态化(在售绿/库存蓝/已售灰,icons BADGE_ICON 补两词);
  状态筛选改「全部/在售/库存/已售」走服务端;预警缺货退出状态维度由数量染色承担
- KPI 第四卡「缺货预警」→「已售」(sold_count,点击筛选已售)
- 原型同步:atoms/index 登记 switch 与 b-库存/b-已售、inventory 两屏三态数据、
  抽屉状态行 switch;12 道 ds 闸 + L1 同源闸全过
- golden 重录 ×9(三态徽章 + 已售卡形态)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
wangjia
2026-07-07 13:35:19 +08:00
parent 73955a139c
commit 65c672b4ad
26 changed files with 264 additions and 56 deletions
+8
View File
@@ -9,6 +9,9 @@ class Inventory {
final int? productId;
final int? stockInItemId;
final double quantity;
/// 库存三态(2026-07-07):stock=库存 / on_sale=在售(公开酒单) / sold=已售(卖光留痕)
final String status;
final String productCode;
final String productName;
final String series;
@@ -31,6 +34,7 @@ class Inventory {
this.productId,
this.stockInItemId,
required this.quantity,
this.status = 'stock',
this.productCode = '',
this.productName = '',
this.series = '',
@@ -54,6 +58,7 @@ class Inventory {
productId: (json['product_id'] as num?)?.toInt(),
stockInItemId: (json['stock_in_item_id'] as num?)?.toInt(),
quantity: (json['quantity'] as num).toDouble(),
status: json['status'] as String? ?? 'stock',
productCode: json['product_code'] as String? ?? '',
productName: json['product_name'] as String? ?? '',
series: json['series'] as String? ?? '',
@@ -77,6 +82,7 @@ class InventorySummary {
final int skuCount;
final double stockValue;
final double inStockQty;
final int soldCount; // 已售留痕行数(status=sold
final int shortageCount;
final int warningCount;
// 月初快照(KPI 环比):由 inventory_logs 反推
@@ -87,6 +93,7 @@ class InventorySummary {
this.skuCount = 0,
this.stockValue = 0,
this.inStockQty = 0,
this.soldCount = 0,
this.shortageCount = 0,
this.warningCount = 0,
this.lastMonthSku = 0,
@@ -97,6 +104,7 @@ class InventorySummary {
skuCount: (j['sku_count'] as num?)?.toInt() ?? 0,
stockValue: (j['stock_value'] as num?)?.toDouble() ?? 0,
inStockQty: (j['in_stock_qty'] as num?)?.toDouble() ?? 0,
soldCount: (j['sold_count'] as num?)?.toInt() ?? 0,
shortageCount: (j['shortage_count'] as num?)?.toInt() ?? 0,
warningCount: (j['warning_count'] as num?)?.toInt() ?? 0,
lastMonthSku: (j['last_month_sku'] as num?)?.toInt() ?? 0,