feat(client): 草稿 KPI 卡(暗黄)+ 出库详情总售价列 + 明细去¥缩号 + 建单默认值 + 若干列名
- 出入库列表加草稿 KPI 卡(DsKpiTone.warn 新档,审核卡后,点击筛选草稿) - 出库详情 7 列:售价后加总售价;明细行内价格去 ¥ 且缩一号(合计保留 ¥); 5/7 列宽重排(系列/数量左移、进价(单瓶)不折行) - 出库建单:数量默认=可用数量、售价默认=参考售价(product.sale_price) - 入库详情列名:进价(单瓶)/总价;库存列表「单价」→「总价」(库存×成本); 商品抽屉:成本价(单瓶)/总成本价 - 公开商品预览页加返回按钮(仅 App 内 canPop 时显示,扫码直达保持纯净) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
@@ -36,6 +36,7 @@ class _PickerItem {
|
||||
final String spec;
|
||||
final String unit;
|
||||
final double? costPrice; // 进价(成本,仅管理员可见列)
|
||||
final double? salePrice; // 参考售价(入库时填写,存 product.sale_price)
|
||||
final double availableQty;
|
||||
const _PickerItem({
|
||||
required this.productId,
|
||||
@@ -45,6 +46,7 @@ class _PickerItem {
|
||||
required this.spec,
|
||||
required this.unit,
|
||||
this.costPrice,
|
||||
this.salePrice,
|
||||
required this.availableQty,
|
||||
});
|
||||
}
|
||||
@@ -64,6 +66,7 @@ List<_PickerItem> _aggregatePickerItems(List<Inventory> rows) {
|
||||
spec: existing.spec,
|
||||
unit: existing.unit,
|
||||
costPrice: existing.costPrice ?? inv.unitPrice,
|
||||
salePrice: existing.salePrice ?? inv.salePrice,
|
||||
availableQty: existing.availableQty + inv.quantity,
|
||||
);
|
||||
} else {
|
||||
@@ -75,6 +78,7 @@ List<_PickerItem> _aggregatePickerItems(List<Inventory> rows) {
|
||||
spec: inv.spec,
|
||||
unit: inv.unit,
|
||||
costPrice: inv.unitPrice,
|
||||
salePrice: inv.salePrice,
|
||||
availableQty: inv.quantity,
|
||||
);
|
||||
}
|
||||
@@ -264,7 +268,7 @@ class _StockOutFormScreenState extends ConsumerState<StockOutFormScreen> {
|
||||
setState(() {
|
||||
for (final item in selected) {
|
||||
if (_items.any((row) => row.productId == item.productId)) continue;
|
||||
_items.add(_ItemRow(
|
||||
final row = _ItemRow(
|
||||
productId: item.productId,
|
||||
productCode: item.productCode,
|
||||
productName: item.productName,
|
||||
@@ -272,7 +276,11 @@ class _StockOutFormScreenState extends ConsumerState<StockOutFormScreen> {
|
||||
spec: item.spec,
|
||||
costPrice: item.costPrice,
|
||||
availableQty: item.availableQty,
|
||||
));
|
||||
salePrice: item.salePrice, // 售价默认带出入库时填的参考售价
|
||||
);
|
||||
// 数量默认带出可用数量(整箱出为主,改少比补多顺手)
|
||||
row.qtyCtrl.text = item.availableQty.toStringAsFixed(0);
|
||||
_items.add(row);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -532,6 +532,17 @@ class _StockOutListScreenState extends ConsumerState<StockOutListScreen> {
|
||||
ref.read(stockOutListProvider.notifier).setStatus('pending');
|
||||
},
|
||||
),
|
||||
DsKpi(
|
||||
title: '草稿单数 · 点击筛选',
|
||||
value: '${summary?.draftCount ?? 0}',
|
||||
icon: LucideIcons.filePen,
|
||||
tone: DsKpiTone.warn, // 暗黄(用户拍板)
|
||||
delta: (summary?.draftCount ?? 0) > 0 ? '待提交审核' : '点击筛选',
|
||||
onTap: () {
|
||||
setState(() => _statusFilter = 'draft');
|
||||
ref.read(stockOutListProvider.notifier).setStatus('draft');
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
final mobile = context.isMobile;
|
||||
@@ -845,6 +856,8 @@ class _StockOutListScreenState extends ConsumerState<StockOutListScreen> {
|
||||
|
||||
static final _money =
|
||||
NumberFormat.currency(locale: 'zh_CN', symbol: '¥', decimalDigits: 0);
|
||||
// 明细行内数字(去 ¥:列多时更紧凑,符号只留在合计)
|
||||
static final _num = NumberFormat('#,##0');
|
||||
static String _fmtQty(double q) =>
|
||||
q == q.roundToDouble() ? q.toStringAsFixed(0) : q.toString();
|
||||
|
||||
@@ -885,10 +898,10 @@ class _StockOutListScreenState extends ConsumerState<StockOutListScreen> {
|
||||
series: it.productSeries ?? '—',
|
||||
spec: it.productSpec ?? '',
|
||||
qty: _fmtQty(it.quantity),
|
||||
price: pending ? '待定价' : _money.format(it.salePrice),
|
||||
amount: pending ? '待定价' : _money.format(it.saleAmount),
|
||||
cost: admin ? _money.format(it.costPrice) : null,
|
||||
profit: admin ? (pending ? '待定价' : _money.format(profit)) : null,
|
||||
price: pending ? '待定价' : _num.format(it.salePrice),
|
||||
amount: pending ? '待定价' : _num.format(it.saleAmount),
|
||||
cost: admin ? _num.format(it.costPrice) : null,
|
||||
profit: admin ? (pending ? '待定价' : _num.format(profit)) : null,
|
||||
pending: pending,
|
||||
);
|
||||
}).toList(),
|
||||
|
||||
Reference in New Issue
Block a user