chore: release v1.0.24
Deploy / build-linux-web (push) Successful in 59s
Deploy / build-windows (push) Successful in 1m50s
Deploy / build-macos (push) Successful in 1m22s
Deploy / build-android (push) Successful in 1m26s
Deploy / build-ios (push) Successful in 7s
Deploy / release-deploy (push) Successful in 1m39s
Deploy / build-linux-web (push) Successful in 59s
Deploy / build-windows (push) Successful in 1m50s
Deploy / build-macos (push) Successful in 1m22s
Deploy / build-android (push) Successful in 1m26s
Deploy / build-ios (push) Successful in 7s
Deploy / release-deploy (push) Successful in 1m39s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:math' as math;
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import '../../core/config/app_config.dart';
|
||||
|
||||
@@ -119,6 +120,7 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
|
||||
final descriptionKeywords = (d['description_keywords'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ?? const <String>[];
|
||||
final salePrice = (d['sale_price'] as num?)?.toDouble() ?? 0.0;
|
||||
final origin = d['origin'] as String? ?? '';
|
||||
final shelfLife = d['shelf_life'] as String? ?? '无限期(适饮)';
|
||||
final storage = d['storage'] as String? ?? '阴凉干燥、避光保存';
|
||||
@@ -153,7 +155,12 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
|
||||
unit: unit,
|
||||
),
|
||||
),
|
||||
// 4. Quick specs (only if we could parse any)
|
||||
// 4a. Sale price badge (only when price > 0)
|
||||
if (salePrice > 0)
|
||||
SliverToBoxAdapter(
|
||||
child: _PriceBadge(price: salePrice),
|
||||
),
|
||||
// 4b. Quick specs (only if we could parse any)
|
||||
if (quickSpecs.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: _QuickSpecs(items: quickSpecs),
|
||||
@@ -607,6 +614,43 @@ class _VerifiedRibbon extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Price Badge ───────────────────────────────────────────────────────
|
||||
|
||||
class _PriceBadge extends StatelessWidget {
|
||||
final double price;
|
||||
const _PriceBadge({required this.price});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final priceStr = price % 1 == 0
|
||||
? price.toInt().toString()
|
||||
: price.toStringAsFixed(2);
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
decoration: const BoxDecoration(
|
||||
color: _kPaper,
|
||||
border: Border(bottom: BorderSide(color: _kBorder)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('建议零售价',
|
||||
style: TextStyle(fontSize: 13, color: _kTextMid)),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'¥$priceStr',
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: _kBurgundy,
|
||||
letterSpacing: 0.04,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Title Block ───────────────────────────────────────────────────────
|
||||
|
||||
class _TitleBlock extends StatelessWidget {
|
||||
@@ -1187,6 +1231,7 @@ class _ShopCard extends StatelessWidget {
|
||||
final address = shop['address'] as String? ?? '';
|
||||
final phone = shop['phone'] as String? ?? '';
|
||||
final hours = shop['business_hours'] as String? ?? '';
|
||||
final wechatId = shop['wechat_id'] as String? ?? '';
|
||||
|
||||
// Avatar text: first 2 chars of shop name
|
||||
final avatarText = name.length >= 2 ? name.substring(0, 2) : name;
|
||||
@@ -1249,7 +1294,10 @@ class _ShopCard extends StatelessWidget {
|
||||
SizedBox(
|
||||
width: double.infinity, height: 44,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {},
|
||||
onPressed: code.isNotEmpty
|
||||
? () => context.push(
|
||||
'/shop/$code?shopName=${Uri.encodeComponent(name)}')
|
||||
: null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF0A1F3B),
|
||||
foregroundColor: Colors.white,
|
||||
@@ -1260,27 +1308,58 @@ class _ShopCard extends StatelessWidget {
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, letterSpacing: 0.04)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: double.infinity, height: 40,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () {},
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: _kInkDeep,
|
||||
side: const BorderSide(color: _kBorder, width: 1.5),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
if (wechatId.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: double.infinity, height: 40,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _showWechatDialog(context, wechatId),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: _kInkDeep,
|
||||
side: const BorderSide(color: _kBorder, width: 1.5),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
icon: const Icon(Icons.person_outline, size: 16),
|
||||
label: const Text('添加门店微信',
|
||||
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500)),
|
||||
),
|
||||
icon: const Icon(Icons.person_outline, size: 16),
|
||||
label: const Text('添加门店微信',
|
||||
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500)),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _showWechatDialog(BuildContext context, String wechatId) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('门店微信号', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.wechat, size: 48, color: Color(0xFF07C160)),
|
||||
const SizedBox(height: 12),
|
||||
SelectableText(
|
||||
wechatId,
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, letterSpacing: 0.5),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text('长按上方微信号可复制', style: TextStyle(fontSize: 12, color: _kTextMid)),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('关闭'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _ShopInfoRow extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String text;
|
||||
|
||||
Reference in New Issue
Block a user