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:
@@ -14,6 +14,7 @@ import '../../screens/finance/finance_screen.dart';
|
||||
import '../../screens/products/products_screen.dart';
|
||||
import '../../screens/products/product_detail_screen.dart';
|
||||
import '../../screens/public/public_product_screen.dart';
|
||||
import '../../screens/public/public_shop_products_screen.dart';
|
||||
import '../../screens/settings/settings_screen.dart';
|
||||
import '../../screens/about/about_screen.dart';
|
||||
import '../auth/auth_state.dart';
|
||||
@@ -40,7 +41,8 @@ class _RouterNotifier extends ChangeNotifier {
|
||||
final isLoggedIn = authState.isLoggedIn;
|
||||
final loc = state.matchedLocation;
|
||||
final isPublicRoute = loc == '/login' ||
|
||||
loc.startsWith('/product/');
|
||||
loc.startsWith('/product/') ||
|
||||
loc.startsWith('/shop/');
|
||||
final result = !authState.initialized
|
||||
? null
|
||||
: (!isLoggedIn && !isPublicRoute)
|
||||
@@ -79,6 +81,14 @@ final appRouterProvider = Provider<GoRouter>((ref) {
|
||||
builder: (context, state) =>
|
||||
PublicProductScreen(publicId: state.pathParameters['public_id']!),
|
||||
),
|
||||
// Public shop product list — no auth, no shell nav bar
|
||||
GoRoute(
|
||||
path: '/shop/:shop_code',
|
||||
builder: (context, state) => PublicShopProductsScreen(
|
||||
shopCode: state.pathParameters['shop_code']!,
|
||||
shopName: state.uri.queryParameters['shopName'] ?? '',
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/login',
|
||||
builder: (context, state) => const LoginScreen(),
|
||||
|
||||
@@ -6,6 +6,7 @@ class ShopInfo {
|
||||
final String phone;
|
||||
final String managerName;
|
||||
final String logoUrl;
|
||||
final String wechatId;
|
||||
|
||||
const ShopInfo({
|
||||
required this.id,
|
||||
@@ -15,6 +16,7 @@ class ShopInfo {
|
||||
required this.phone,
|
||||
required this.managerName,
|
||||
this.logoUrl = '',
|
||||
this.wechatId = '',
|
||||
});
|
||||
|
||||
factory ShopInfo.fromJson(Map<String, dynamic> json) => ShopInfo(
|
||||
@@ -25,5 +27,6 @@ class ShopInfo {
|
||||
phone: json['phone'] as String? ?? '',
|
||||
managerName: json['manager_name'] as String? ?? '',
|
||||
logoUrl: json['logo_url'] as String? ?? '',
|
||||
wechatId: json['wechat_id'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../core/config/app_config.dart';
|
||||
|
||||
const _kPaper = Color(0xFFFAF8F5);
|
||||
const _kPaperDeep = Color(0xFFF4F1EB);
|
||||
const _kInkDeep = Color(0xFF161412);
|
||||
const _kTextMid = Color(0xFF6E7888);
|
||||
const _kBurgundy = Color(0xFF8B2331);
|
||||
const _kBorder = Color(0xFFE8E4DC);
|
||||
|
||||
class PublicShopProductsScreen extends StatefulWidget {
|
||||
final String shopCode;
|
||||
final String shopName;
|
||||
|
||||
const PublicShopProductsScreen({
|
||||
super.key,
|
||||
required this.shopCode,
|
||||
this.shopName = '',
|
||||
});
|
||||
|
||||
@override
|
||||
State<PublicShopProductsScreen> createState() =>
|
||||
_PublicShopProductsScreenState();
|
||||
}
|
||||
|
||||
class _PublicShopProductsScreenState
|
||||
extends State<PublicShopProductsScreen> {
|
||||
final _dio = Dio(BaseOptions(
|
||||
connectTimeout: const Duration(seconds: 10),
|
||||
receiveTimeout: const Duration(seconds: 15),
|
||||
));
|
||||
|
||||
final List<Map<String, dynamic>> _items = [];
|
||||
bool _loading = true;
|
||||
bool _loadingMore = false;
|
||||
String? _error;
|
||||
int _page = 1;
|
||||
bool _hasMore = true;
|
||||
int _total = 0;
|
||||
final _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_load(refresh: true);
|
||||
_scrollController.addListener(_onScroll);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (_scrollController.position.pixels >=
|
||||
_scrollController.position.maxScrollExtent - 200 &&
|
||||
!_loadingMore &&
|
||||
_hasMore) {
|
||||
_load();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _load({bool refresh = false}) async {
|
||||
if (refresh) {
|
||||
setState(() {
|
||||
_loading = true;
|
||||
_error = null;
|
||||
_page = 1;
|
||||
_hasMore = true;
|
||||
_items.clear();
|
||||
});
|
||||
} else {
|
||||
if (_loadingMore) return;
|
||||
setState(() => _loadingMore = true);
|
||||
}
|
||||
|
||||
try {
|
||||
final resp = await _dio.get(
|
||||
'${AppConfig.apiBaseUrl}/public/shops/${widget.shopCode}/products',
|
||||
queryParameters: {'page': _page, 'page_size': 20},
|
||||
);
|
||||
final body = resp.data as Map<String, dynamic>;
|
||||
final list = (body['data'] as List<dynamic>? ?? [])
|
||||
.cast<Map<String, dynamic>>();
|
||||
final total = (body['total'] as num?)?.toInt() ?? 0;
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_total = total;
|
||||
_items.addAll(list);
|
||||
_hasMore = _items.length < total;
|
||||
_page++;
|
||||
_loading = false;
|
||||
_loadingMore = false;
|
||||
});
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
_loading = false;
|
||||
_loadingMore = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final title =
|
||||
widget.shopName.isNotEmpty ? widget.shopName : '本店商品';
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: _kPaperDeep,
|
||||
appBar: AppBar(
|
||||
backgroundColor: _kPaper,
|
||||
elevation: 0,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios_new, size: 18),
|
||||
color: _kInkDeep,
|
||||
onPressed: () => context.pop(),
|
||||
),
|
||||
title: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: _kInkDeep),
|
||||
),
|
||||
centerTitle: true,
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1),
|
||||
child: Container(height: 1, color: _kBorder),
|
||||
),
|
||||
),
|
||||
body: _buildBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
if (_loading) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: _kBurgundy, strokeWidth: 2));
|
||||
}
|
||||
if (_error != null && _items.isEmpty) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 56,
|
||||
height: 56,
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFFDECEC), shape: BoxShape.circle),
|
||||
child: const Icon(Icons.error_outline,
|
||||
size: 28, color: Color(0xFFD14343)),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text('加载失败,请稍后重试',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: _kInkDeep)),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: () => _load(refresh: true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: _kBurgundy,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (_items.isEmpty) {
|
||||
return const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.inventory_2_outlined, size: 48, color: _kTextMid),
|
||||
SizedBox(height: 12),
|
||||
Text('暂无上架商品',
|
||||
style: TextStyle(fontSize: 15, color: _kTextMid)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
color: _kBurgundy,
|
||||
onRefresh: () => _load(refresh: true),
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 520),
|
||||
child: CustomScrollView(
|
||||
controller: _scrollController,
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 12, 12, 0),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Text(
|
||||
'共 $_total 件商品',
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: _kTextMid),
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
sliver: SliverGrid(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) =>
|
||||
_ProductCard(item: _items[index]),
|
||||
childCount: _items.length,
|
||||
),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
childAspectRatio: 0.72,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_loadingMore)
|
||||
const SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: _kBurgundy, strokeWidth: 2)),
|
||||
),
|
||||
),
|
||||
if (!_hasMore && _items.isNotEmpty)
|
||||
const SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Center(
|
||||
child: Text('已展示全部商品',
|
||||
style: TextStyle(
|
||||
fontSize: 12, color: _kTextMid))),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ProductCard extends StatelessWidget {
|
||||
final Map<String, dynamic> item;
|
||||
const _ProductCard({required this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final publicId = item['public_id'] as String? ?? '';
|
||||
final name = item['name'] as String? ?? '';
|
||||
final series = item['series'] as String? ?? '';
|
||||
final spec = item['spec'] as String? ?? '';
|
||||
final images = (item['images'] as List<dynamic>? ?? [])
|
||||
.cast<Map<String, dynamic>>();
|
||||
final imageUrl = images.isNotEmpty
|
||||
? AppConfig.baseUrl + (images.first['url'] as String)
|
||||
: null;
|
||||
|
||||
final subtitle = [series, spec].where((s) => s.isNotEmpty).join(' · ');
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (publicId.isNotEmpty) {
|
||||
context.push('/product/$publicId');
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: _kPaper,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: _kBorder, width: 1),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 商品图片
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.vertical(top: Radius.circular(10)),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: imageUrl != null
|
||||
? Image.network(
|
||||
imageUrl,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) =>
|
||||
_PlaceholderImg(),
|
||||
)
|
||||
: _PlaceholderImg(),
|
||||
),
|
||||
),
|
||||
// 商品信息
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(8, 6, 8, 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: _kInkDeep,
|
||||
height: 1.3),
|
||||
),
|
||||
if (subtitle.isNotEmpty) ...[
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
subtitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 11, color: _kTextMid),
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: _kBurgundy,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: const Text(
|
||||
'查看详情',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PlaceholderImg extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: _kPaperDeep,
|
||||
child: const Center(
|
||||
child: Icon(Icons.wine_bar_outlined, size: 40, color: _kBorder),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1822,6 +1822,7 @@ class _ShopEditDialogState extends ConsumerState<_ShopEditDialog> {
|
||||
late final TextEditingController _addressCtrl;
|
||||
late final TextEditingController _phoneCtrl;
|
||||
late final TextEditingController _managerCtrl;
|
||||
late final TextEditingController _wechatCtrl;
|
||||
bool _saving = false;
|
||||
bool _uploadingLogo = false;
|
||||
|
||||
@@ -1832,6 +1833,7 @@ class _ShopEditDialogState extends ConsumerState<_ShopEditDialog> {
|
||||
_addressCtrl = TextEditingController(text: widget.shop.address);
|
||||
_phoneCtrl = TextEditingController(text: widget.shop.phone);
|
||||
_managerCtrl = TextEditingController(text: widget.shop.managerName);
|
||||
_wechatCtrl = TextEditingController(text: widget.shop.wechatId);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1840,6 +1842,7 @@ class _ShopEditDialogState extends ConsumerState<_ShopEditDialog> {
|
||||
_addressCtrl.dispose();
|
||||
_phoneCtrl.dispose();
|
||||
_managerCtrl.dispose();
|
||||
_wechatCtrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -1882,6 +1885,7 @@ class _ShopEditDialogState extends ConsumerState<_ShopEditDialog> {
|
||||
'address': _addressCtrl.text.trim(),
|
||||
'phone': _phoneCtrl.text.trim(),
|
||||
'manager_name': _managerCtrl.text.trim(),
|
||||
'wechat_id': _wechatCtrl.text.trim(),
|
||||
});
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
@@ -1950,6 +1954,14 @@ class _ShopEditDialogState extends ConsumerState<_ShopEditDialog> {
|
||||
controller: _managerCtrl,
|
||||
decoration: const InputDecoration(labelText: '负责人'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: _wechatCtrl,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '微信号(可选)',
|
||||
hintText: '填写后顾客扫码可查看',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user