import 'dart:io'; import 'package:excel/excel.dart'; 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}); @override State createState() => _OrderListState(); } class _OrderListState extends State { final List lst = []; List _headers = []; List> _data = []; late Excel _excel; ScrollController scrollController = ScrollController(); final TextEditingController _logComController = TextEditingController(text: ""); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.white, title: const Text("订单列表"), actions: [ ElevatedButton( onPressed: () { importExcelFile(); }, child: const Row( children: [Icon(Icons.add_circle), Text("导入")], )), const SizedBox( width: 4, ), ElevatedButton( onPressed: () { exportExcelFile(); }, child: const Row( children: [Icon(CupertinoIcons.download_circle), Text("导出")], )), const SizedBox( width: 4, ), ], ), body: Container( width: double.infinity, padding: const EdgeInsets.all(20), child: _headers.isNotEmpty ? Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Card( color: Colors.white, margin: EdgeInsets.zero, 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: [ 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 == "物流信息" ? 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(), ), )), ) ], ) : const Center( child: Icon(CupertinoIcons.cloud_upload), ), )); } Future importExcelFile() async { FilePickerResult? result = await FilePicker.platform .pickFiles(type: FileType.custom, allowedExtensions: ["xlsx", "xls"]); if (result != null) { File file = File(result.files.single.path!); var bytes = file.readAsBytesSync(); Excel excel = Excel.decodeBytes(bytes); _excel = excel; String tableKey = excel.tables.keys.first; List headers = excel.tables[tableKey]?.rows.first.map((el) { return el?.value.toString() ?? ""; }).toList() ?? []; List> data = excel.tables[tableKey]?.rows .where((el) => (el.first?.value?.toString() ?? "").isNotEmpty) .toList() .sublist(1) .map((row) { return row.map((col) { return col?.value ?? ""; }).toList(); }).toList() ?? []; setState(() { _headers = headers; _data = data; }); } else { // 取消选择 } return ""; } exportExcelFile() async { _data.asMap().entries.forEach((row) { row.value.asMap().entries.forEach((col) { int rowIndex = row.key + 1; int colIndex = col.key; if (colIndex == 11 || colIndex == 12) { _excel.updateCell( "订单列表", CellIndex.indexByColumnRow( columnIndex: colIndex, rowIndex: rowIndex), TextCellValue(col.value.toString())); } }); }); var fileBytes = _excel.save(); 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(outputPath) ..createSync(recursive: true) ..writeAsBytesSync(fileBytes!); if (mounted) { 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, ), )); } } }