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:
wangjia
2026-07-03 14:31:50 +08:00
parent 4d1d69595b
commit 2bf5b98ba2
28 changed files with 132 additions and 35 deletions
@@ -128,6 +128,17 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
if (_error != null || _data == null) {
return Scaffold(
backgroundColor: _kPaper,
// 加载失败态也要能退回 App(canPop 时显示返回,扫码直达不显示)
appBar: Navigator.of(context).canPop()
? AppBar(
backgroundColor: _kPaper,
elevation: 0,
leading: IconButton(
icon: const Icon(LucideIcons.arrowLeft, color: _kBurgundy),
onPressed: () => Navigator.of(context).pop(),
),
)
: null,
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
@@ -199,10 +210,14 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
_parseQuickSpecs(spec, batch?['production_date'] as String?);
final productionDate = batch?['production_date'] as String?;
// App 内「预览」推入时可返回(canPop);顾客扫码/网页直达无返回栈则不渲染,
// 页面对外保持纯净(本页为独立品牌样式,按钮用自有暖纸/酒红配色)。
final canPop = Navigator.of(context).canPop();
return Scaffold(
backgroundColor: _kPaperDeep,
body: SafeArea(
child: Center(
child: Stack(children: [
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 520),
child: CustomScrollView(
@@ -286,7 +301,28 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
],
),
),
),
),
if (canPop)
Positioned(
top: 12,
left: 12,
child: Material(
color: _kPaper.withValues(alpha: 0.92),
shape: const CircleBorder(
side: BorderSide(color: _kBurgundyLight)),
elevation: 2,
child: InkWell(
customBorder: const CircleBorder(),
onTap: () => Navigator.of(context).pop(),
child: const Padding(
padding: EdgeInsets.all(9),
child:
Icon(LucideIcons.arrowLeft, size: 20, color: _kBurgundy),
),
),
),
),
]),
),
);
}