diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..2817600 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..eda96fa 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..ad697ee 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..6987f13 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..3f523f7 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/launcher_icon/icon.png b/assets/launcher_icon/icon.png new file mode 100644 index 0000000..821b2ca Binary files /dev/null and b/assets/launcher_icon/icon.png differ diff --git a/flutter_launcher_icons.yaml b/flutter_launcher_icons.yaml new file mode 100644 index 0000000..fd6de46 --- /dev/null +++ b/flutter_launcher_icons.yaml @@ -0,0 +1,8 @@ +flutter_launcher_icons: + android: true + ios: true + image_path: "assets/launcher_icon/icon.png" + windows: + generate: true + image_path: "assets/launcher_icon/icon.png" + icon_size: 48 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c816211..6d484af 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -427,7 +427,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -484,7 +484,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index dc9ada4..085cc1a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 7353c41..526423b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 797d452..5f89200 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 6ed2d93..d084e6a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cd7b00..b4fd095 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index fe73094..5e97cf0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 321773c..eb30b08 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 797d452..5f89200 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 502f463..062826f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 0ec3034..b5ce6fd 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000..b7cf9b4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000..d33d46b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000..ff38c06 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000..65f494e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 0ec3034..b5ce6fd 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index e9f5fea..a03c7bf 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000..2817600 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000..6987f13 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 84ac32a..462927d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 8953cba..7c3c057 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 0467bf1..6665c11 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/logistics.dart b/lib/logistics.dart index 4804353..db01944 100644 --- a/lib/logistics.dart +++ b/lib/logistics.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; @@ -18,7 +19,10 @@ class Logistics extends StatefulWidget { class _LogisticsState extends State { List goodsList = []; String _orderPayWay = ""; + + // String _logistics = ""; List _packages = []; + bool _packageInit = false; int _activePackage = 0; final TextEditingController _goodsNameController = TextEditingController(text: ""); @@ -43,6 +47,8 @@ class _LogisticsState extends State { GoRouterState.of(context).uri.queryParameters["orderNumber"]; String? orderPayWay = GoRouterState.of(context).uri.queryParameters["orderPayWay"]; + String? logistics = + GoRouterState.of(context).uri.queryParameters["logistics"]; _orderPayWay = orderPayWay!; if (orderNumber?.isEmpty ?? true) { @@ -54,6 +60,30 @@ class _LogisticsState extends State { queryParameters: {"orderNumber": orderNumber}); }); goodsList = response.data["value"]; + + if (logistics != null && logistics.isNotEmpty && !_packageInit) { + try { + List packages = jsonDecode(logistics); + + _packages = packages; + + if (_orderPayWay != "套餐商品") { + for (var p in _packages) { + p["goods"].forEach((g) { + var targetGoods = goodsList + .firstWhere((tg) => g["id"] == tg["id"], orElse: () => null); + if (targetGoods != null) { + targetGoods["goodsNum"] -= g["num"]; + } + }); + } + } + _packageInit = true; + } catch (e) { + e; + } + } + return response; } @@ -73,6 +103,7 @@ class _LogisticsState extends State { if (hasUnAddedGoods) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text("有未添加至包裹的商品"), + showCloseIcon: true, backgroundColor: Colors.redAccent, )); return; @@ -90,6 +121,7 @@ class _LogisticsState extends State { if (!result) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( backgroundColor: Colors.redAccent, + showCloseIcon: true, content: Text("有未填写的数据"))); return; } @@ -184,8 +216,9 @@ class _LogisticsState extends State { ScaffoldMessenger.of(context) .showSnackBar( const SnackBar( - content: Text( - "请填写完整商品信息"))); + content: Text("请填写完整商品信息"), + showCloseIcon: true, + )); return; } int goodsNum = int.parse( @@ -216,77 +249,89 @@ class _LogisticsState extends State { child: const Text("添加到包裹")) ], ) - : ListView.builder( - itemCount: goodsList + : goodsList .where((el) => el["goodsNum"] > 0) - .length, - itemBuilder: (context, index) { - final goods = goodsList - .where((el) => el["goodsNum"] > 0) - .toList()[index]; - return ListTile( - trailing: IconButton( - icon: const Icon(Icons.add), - onPressed: () { - // 检查商品及规格是否已存在于目标包裹 - int targetIndex = _packages[ - _activePackage]["goods"] - .indexWhere((el) => - el["id"] == - goods["id"] && - goods["wisdGoodsSpec"] - ["id"] == - el["specId"]); - if (targetIndex != -1) { - setState(() { - _packages[_activePackage] - ["goods"] - [targetIndex] - ["num"] += 1; - }); - } else { - setState(() { - _packages[_activePackage] + .isNotEmpty + ? ListView.builder( + itemCount: goodsList + .where( + (el) => el["goodsNum"] > 0) + .length, + itemBuilder: (context, index) { + final goods = goodsList + .where((el) => + el["goodsNum"] > 0) + .toList()[index]; + return ListTile( + trailing: IconButton( + icon: const Icon(Icons.add), + onPressed: () { + // 检查商品及规格是否已存在于目标包裹 + int targetIndex = _packages[ + _activePackage] ["goods"] - .add({ - "id": goods["id"], - "specId": - goods["wisdGoodsSpec"] + .indexWhere((el) => + el["id"] == + goods["id"] && + goods["wisdGoodsSpec"] + ["id"] == + el["specId"]); + if (targetIndex != -1) { + setState(() { + _packages[_activePackage] + ["goods"] + [targetIndex] + ["num"] += 1; + }); + } else { + setState(() { + _packages[_activePackage] + ["goods"] + .add({ + "id": goods["id"], + "specId": goods[ + "wisdGoodsSpec"] ["id"], - "name": - goods["goodsName"], - "spec": - goods?["wisdGoodsSpec"] + "name": goods[ + "goodsName"], + "spec": goods?[ + "wisdGoodsSpec"] ?[ "specName"] ?? "", - "num": 1 - }); - }); - } - var curGoods = - goodsList.firstWhere( - (el) => - el["id"] == - goods["id"], - orElse: () => -1); + "num": 1 + }); + }); + } + var curGoods = + goodsList.firstWhere( + (el) => + el["id"] == + goods["id"], + orElse: () => -1); - setState(() { - curGoods["goodsNum"] -= 1; - }); - }, + setState(() { + curGoods["goodsNum"] -= 1; + }); + }, + ), + leading: Image.network( + goods["goodsPhoto"], + width: 100, + height: 100, + ), + title: Text( + "${goods["goodsName"]} - ${goods?["wisdGoodsSpec"]?["specName"] ?? ''}"), + subtitle: Text( + "数量 : ${goods?["goodsNum"]}"), + ); + }) + : const Center( + child: Icon( + CupertinoIcons.circle, + size: 36, ), - leading: Image.network( - goods["goodsPhoto"], - width: 100, - height: 100, - ), - title: Text( - "${goods["goodsName"]} - ${goods?["wisdGoodsSpec"]?["specName"] ?? ''}"), - subtitle: Text( - "数量 : ${goods?["goodsNum"]}"), - ); - })), + )), const SizedBox( width: 20, ), @@ -300,10 +345,39 @@ class _LogisticsState extends State { itemBuilder: (BuildContext context, int index) { return PackageCard( + logisticsNumber: _packages[index] + ["logisticsNumber"], + onDeleteGoods: (goods) { + if (goods["num"] == 1) { + setState(() { + _packages[index]["goods"] = + _packages[index]["goods"] + .where((el) => + el["id"] != + goods["id"]) + .toList(); + }); + } else { + setState(() { + goods["num"] -= 1; + }); + } + if (_orderPayWay != "套餐商品") { + setState(() { + goodsList.firstWhere( + (e) => + goods["id"] == + e["id"], + orElse: () => null)?[ + "goodsNum"] += 1; + }); + } + }, onLogisticsChanged: (value) { _packages[index] ["logisticsNumber"] = value; }, + orderPayWay: _orderPayWay, onTap: () { setState(() { _activePackage = index; @@ -312,6 +386,23 @@ class _LogisticsState extends State { onClose: () { var curId = _packages[index]["id"]; + if (_orderPayWay != "套餐商品") { + _packages[index]["goods"] + .forEach((el) { + var targetGoods = + goodsList.firstWhere( + (goodsItem) => + goodsItem["id"] == + el["id"], + orElse: () => -1); + if (targetGoods != -1) { + setState(() { + targetGoods["goodsNum"] += + el["num"]; + }); + } + }); + } setState(() { _activePackage = _activePackage >= index @@ -341,6 +432,7 @@ class _LogisticsState extends State { "goods": [] } ]; + _activePackage += 1; }); }, child: const Text("添加包裹")) @@ -351,10 +443,14 @@ class _LogisticsState extends State { ); } else if (snapshot.hasError) { return const Center( - child: Icon( - Icons.error_outline, - color: Colors.red, - size: 60, + child: Column( + children: [ + Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + ], ), ); } else { @@ -375,21 +471,36 @@ class PackageCard extends StatefulWidget { required this.onLogisticsChanged, required this.totalPackagesCount, required this.onClose, + required this.orderPayWay, + required this.onDeleteGoods, + required this.logisticsNumber, }); final bool isActive; final Function() onTap; final Function() onClose; + final Function(Map goods) onDeleteGoods; final Map package; final int index; final Function(String) onLogisticsChanged; final int totalPackagesCount; + final String orderPayWay; + final String logisticsNumber; @override State createState() => _PackageCardState(); } class _PackageCardState extends State { + final TextEditingController _logisticsController = TextEditingController(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + _logisticsController.text = widget.logisticsNumber; + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -417,6 +528,7 @@ class _PackageCardState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextField( + controller: _logisticsController, onChanged: widget.onLogisticsChanged, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: "物流单号"), @@ -427,13 +539,26 @@ class _PackageCardState extends State { DataTable(columns: const [ DataColumn(label: Text("名称")), DataColumn(label: Text("规格")), - DataColumn(label: Text("数量")) + DataColumn(label: Text("数量")), + DataColumn(label: Text("操作")) ], rows: [ - for (var goodsItem in widget.package["goods"]) + for (var goodsItem + in widget.package["goods"].asMap().entries) DataRow(cells: [ - DataCell(Text("${goodsItem["name"]}")), - DataCell(Text("${goodsItem["spec"]}")), - DataCell(Text("${goodsItem["num"]}")), + DataCell(Text("${goodsItem.value["name"]}")), + DataCell(Text("${goodsItem.value["spec"]}")), + DataCell(Text("${goodsItem.value["num"]}")), + DataCell(SizedBox( + width: 24, + height: 24, + child: IconButton( + icon: const Icon(CupertinoIcons.delete), + iconSize: 16, + padding: const EdgeInsets.all(4), + onPressed: () { + widget.onDeleteGoods(goodsItem.value); + }), + )), ]) ]), ], diff --git a/lib/order_list.dart b/lib/order_list.dart index b2a1857..449eecb 100644 --- a/lib/order_list.dart +++ b/lib/order_list.dart @@ -5,6 +5,8 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:path/path.dart' as p; +import 'package:url_launcher/url_launcher.dart'; class OrderList extends StatefulWidget { const OrderList({super.key}); @@ -61,155 +63,163 @@ class _OrderListState extends State { Card( color: Colors.white, margin: EdgeInsets.zero, - child: /*Scrollbar( - // controller: scrollController, - child:*/ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.all(12.0), - child: DataTable( - columns: _headers.map((el) { - return DataColumn(label: Text(el)); - }).toList(), - rows: _data.asMap().entries.map((row) { - return DataRow( - cells: row.value.asMap().entries.map((col) { - String colTitle = _headers[col.key]; - return DataCell(colTitle == "物流名称" - ? Row( - children: [ - Text("${col.value}"), - IconButton( - // padding: EdgeInsets.all(2), - iconSize: 12, - onPressed: () { - _logComController.text = - _data[row.key][col.key] - .toString(); - showDialog( - context: context, - builder: (BuildContext - context) => - AlertDialog( - // icon: const Icon(Icons.edit), - title: const Text( - "填写物流公司"), - content: Column( - mainAxisSize: - MainAxisSize.min, - children: [ - TextField( - decoration: - const InputDecoration( - labelText: - "物流公司"), - controller: - _logComController, - ) - ], - ), - actions: [ - ElevatedButton( - onPressed: () { - context.pop(); - }, - child: const Text( - "取消")), - ElevatedButton( - onPressed: () { - String - logisticsCom = - _logComController - .text; - if (logisticsCom - .isEmpty) { - ScaffoldMessenger.of( - context) - .showSnackBar(const SnackBar( - content: - Text("请输入物流公司"))); - return; - } - final data = - _data; - _data[row.key][ - col.key] = - logisticsCom; - setState(() { - _data = data; - }); - context.pop(); - }, - child: const Text( - "确认")), - ], - )); - }, - icon: const Icon(Icons.edit)) - ], - ) - : colTitle == "物流信息" + child: Scrollbar( + controller: scrollController, + child: SingleChildScrollView( + controller: scrollController, + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.all(12.0), + child: DataTable( + columns: _headers.map((el) { + return DataColumn(label: Text(el)); + }).toList(), + rows: _data.asMap().entries.map((row) { + return DataRow( + cells: row.value.asMap().entries.map((col) { + String colTitle = _headers[col.key]; + return DataCell(colTitle == "物流名称" ? Row( children: [ - _data[row.key][col.key] - .toString() - .isNotEmpty - ? SizedBox( - width: 120, - child: Text( - _data[row.key][col.key].toString(), - overflow: - TextOverflow.ellipsis, - ), - ) - : const SizedBox(), - ElevatedButton( - onPressed: () { - String orderNumber = - _data[row.key][2] - .toString(); - String orderPayWay = - _data[row.key][15] - .toString(); - if (orderPayWay.isEmpty || - orderNumber.isEmpty) { - ScaffoldMessenger.of(context) - .showSnackBar( - const SnackBar( - content: Text( - "该行数据有误"))); - return; - } - context.pushNamed("logistics", - queryParameters: { - "orderNumber": - _data[row.key][2] - .toString(), - "orderPayWay": - _data[row.key][15] - .toString(), - }).then((value) { - if (value != null) { - var newData = _data; - newData[row.key][col.key] = - value; - setState(() { - _data = newData; - }); - } - }); - }, - child: const Text("填写"), - ) + Text("${col.value}"), + IconButton( + // padding: EdgeInsets.all(2), + iconSize: 12, + onPressed: () { + _logComController.text = + _data[row.key][col.key] + .toString(); + showDialog( + context: context, + builder: + (BuildContext + context) => + AlertDialog( + // icon: const Icon(Icons.edit), + title: const Text( + "填写物流公司"), + content: Column( + mainAxisSize: + MainAxisSize + .min, + children: [ + TextField( + decoration: + const InputDecoration( + labelText: "物流公司"), + controller: + _logComController, + ) + ], + ), + actions: [ + ElevatedButton( + onPressed: + () { + context + .pop(); + }, + child: const Text( + "取消")), + ElevatedButton( + onPressed: + () { + String + logisticsCom = + _logComController.text; + if (logisticsCom + .isEmpty) { + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar(content: Text("请输入物流公司"))); + return; + } + final data = + _data; + _data[row.key][col.key] = + logisticsCom; + setState( + () { + _data = + data; + }); + context + .pop(); + }, + child: const Text( + "确认")), + ], + )); + }, + icon: const Icon(Icons.edit)) ], ) - : Text("${col.value}")); - }).toList()); - }).toList(), - ), - ) - /*)*/ - , + : colTitle == "物流信息" + ? Row( + children: [ + _data[row.key][col.key] + .toString() + .isNotEmpty + ? SizedBox( + width: 120, + child: Text( + _data[row.key] + [col.key] + .toString(), + overflow: TextOverflow + .ellipsis, + ), + ) + : const SizedBox(), + ElevatedButton( + onPressed: () { + String orderNumber = + _data[row.key][2] + .toString(); + String orderPayWay = + _data[row.key][15] + .toString(); + if (orderPayWay.isEmpty || + orderNumber.isEmpty) { + ScaffoldMessenger.of( + context) + .showSnackBar( + const SnackBar( + content: Text("该行数据有误"), + showCloseIcon: true, + )); + return; + } + context.pushNamed( + "logistics", + queryParameters: { + "orderNumber": + _data[row.key][2] + .toString(), + "orderPayWay": + _data[row.key][15] + .toString(), + "logistics": + _data[row.key][12] + .toString() + }).then((value) { + if (value != null) { + var newData = _data; + newData[row.key] + [col.key] = value; + setState(() { + _data = newData; + }); + } + }); + }, + child: const Text("填写"), + ) + ], + ) + : Text("${col.value}")); + }).toList()); + }).toList(), + ), + )), ) ], ) @@ -268,18 +278,34 @@ class _OrderListState extends State { }); }); var fileBytes = _excel.save(); - String? directory = - await FilePicker.platform.getDirectoryPath(dialogTitle: "选择保存位置"); - if (directory == null || directory.isEmpty) { + String fileName = "导出订单${DateTime.now().millisecondsSinceEpoch}.xlsx"; + String? outputPath = await FilePicker.platform.saveFile( + dialogTitle: "选择保存位置", + fileName: fileName, + type: FileType.custom, + allowedExtensions: ["xlsx", "xls"]); + if (outputPath == null || outputPath.isEmpty) { return; } - File("$directory\\导出订单${DateTime.now().millisecondsSinceEpoch}.xlsx") + File(outputPath) ..createSync(recursive: true) ..writeAsBytesSync(fileBytes!); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar(const SnackBar( - content: Text("导出文件成功"), + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: const Text("导出文件成功"), backgroundColor: Colors.green, + action: SnackBarAction( + label: "打开文件所在位置", + onPressed: () { + final Uri fileUrl = Uri( + scheme: "file", + path: p.dirname(outputPath), + ); + launchUrl(fileUrl, mode: LaunchMode.externalApplication); + }, + backgroundColor: Colors.white, + textColor: Colors.green, + ), )); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..f6f23bf 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..f16b4c3 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index e777c67..a1cdfd0 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,9 @@ import FlutterMacOS import Foundation import path_provider_foundation +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index fe4a817..54b5566 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.9" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" async: dependency: "direct main" description: @@ -33,6 +41,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" clock: dependency: transitive description: @@ -142,6 +166,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" flutter_lints: dependency: "direct dev" description: @@ -184,6 +216,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" + url: "https://pub.dev" + source: hosted + version: "4.2.0" js: dependency: transitive description: @@ -192,6 +232,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" leak_tracker: dependency: transitive description: @@ -257,7 +305,7 @@ packages: source: hosted version: "1.12.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" @@ -413,6 +461,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf + url: "https://pub.dev" + source: hosted + version: "6.3.3" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" + source: hosted + version: "3.1.1" uuid: dependency: "direct main" description: @@ -469,6 +581,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" sdks: dart: ">=3.4.1 <4.0.0" flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5763814..fc10718 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,6 +42,9 @@ dependencies: path_provider: ^2.1.3 uuid: ^4.4.0 async: ^2.11.0 + url_launcher: ^6.3.0 + path: ^1.9.0 + flutter_launcher_icons: ^0.13.1 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..4f78848 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..88b22e5 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20c..5181220 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ