diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9b79024..82db03e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ diff --git a/lib/apiclient/baseDio.dart b/lib/apiclient/baseDio.dart new file mode 100644 index 0000000..f429a9e --- /dev/null +++ b/lib/apiclient/baseDio.dart @@ -0,0 +1,18 @@ +import 'package:dio/dio.dart'; + +class BaseDio { + static Dio dio = Dio(); + static bool initializeComplete = false; + static Dio instance() { + if(!initializeComplete) { + final options = BaseOptions( + baseUrl: 'http://10.50.222.154:19990', + connectTimeout: const Duration(seconds: 5), + receiveTimeout: const Duration(seconds: 3), + ); + dio.options = options; + initializeComplete = true; + } + return dio; + } +} \ No newline at end of file diff --git a/lib/apiclient/pickApi.dart b/lib/apiclient/pickApi.dart new file mode 100644 index 0000000..f6d3348 --- /dev/null +++ b/lib/apiclient/pickApi.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart'; + +import 'baseDio.dart'; + +class PickApi{ + + /// 获取拣货任务 + static Future getPickTask(String boxNo, {int timeOut = 5000}) async { + final response = await BaseDio.instance().get( + '/api/mobile/pick/getPickTask', + queryParameters: {"vehicleNo" : boxNo}, + options: Options( + responseType: ResponseType.json, + sendTimeout: Duration(milliseconds: timeOut), + receiveTimeout: Duration(milliseconds: timeOut), + ) + ); + return { "code" : response.statusCode, "data": response.data }; + } + + + static Future pickComplete(List data , {int timeOut = 5000}) async { + final response = await BaseDio.instance().post( + "/api/mobile/pick/pickComplete", + data: jsonEncode(data), + options: Options( + responseType: ResponseType.json, + sendTimeout: Duration(milliseconds: timeOut), + receiveTimeout: Duration(milliseconds: timeOut), + ) + ); + return { "code" : response.statusCode, "data": response.data }; + } + + +} \ No newline at end of file diff --git a/lib/apiclient/WmsApiClient.dart b/lib/apiclient/wmsApiClient.dart similarity index 63% rename from lib/apiclient/WmsApiClient.dart rename to lib/apiclient/wmsApiClient.dart index 682dec9..74fe841 100644 --- a/lib/apiclient/WmsApiClient.dart +++ b/lib/apiclient/wmsApiClient.dart @@ -9,7 +9,7 @@ class WmsApiClient { static Dio instance() { if(!initializeComplete) { final options = BaseOptions( - baseUrl: 'http://10.168.1.100:19990', + baseUrl: 'http://10.50.222.154:19990', connectTimeout: const Duration(seconds: 5), receiveTimeout: const Duration(seconds: 3), ); @@ -35,6 +35,40 @@ class WmsApiClient { } + // -------- 冷冻仓 + /// 扫描之后从数据库获取数据 + static Future getGoodsCanUse(String orderId, String goodsId, {int timeOut = 5000}) async { + instance(); + final response = await dio.post( + "/api/mobile/stockIn/getCanUseGoods", + data: jsonEncode({"orderId": orderId, "goodsId": goodsId}), + options: Options( + responseType: ResponseType.json, + sendTimeout: Duration(milliseconds: timeOut), + receiveTimeout: Duration(milliseconds: timeOut), + ) + ); + return { "code" : response.statusCode, "data": response.data }; + } + + // ----------- 冷冻仓 + /// 码盘入库 + static Future bindingVehicleInLD(dynamic bindingVehicleData, {int timeOut = 5000}) async { + instance(); + final response = await dio.post( + "/api/mobile/stockIn/bindingVehicleIn", + data: jsonEncode(bindingVehicleData), + options: Options( + responseType: ResponseType.json, + sendTimeout: Duration(milliseconds: timeOut), + receiveTimeout: Duration(milliseconds: timeOut), + ) + ); + return { "code" : response.statusCode, "data": response.data }; + } + + + /// 获取扫描的箱号的详细信息 static Future getGoodsDetail(String boxNo, {int timeOut = 5000}) async { @@ -82,6 +116,20 @@ class WmsApiClient { /// EBS绑定入库 + static Future bindingVehicleInEbsOld(dynamic bindingVehicleData, {int timeOut = 5000}) async { + instance(); + final response = await dio.post( + "/api/mobile/stockIn/bindingVehicleInEbsOld", + data: jsonEncode(bindingVehicleData), + options: Options( + responseType: ResponseType.json, + sendTimeout: Duration(milliseconds: timeOut), + receiveTimeout: Duration(milliseconds: timeOut), + ) + ); + return { "code" : response.statusCode, "data": response.data }; + } + static Future bindingVehicleInEbs(dynamic bindingVehicleData, {int timeOut = 5000}) async { instance(); final response = await dio.post( @@ -96,4 +144,5 @@ class WmsApiClient { return { "code" : response.statusCode, "data": response.data }; } + } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 5ce8384..ce160d6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,7 +25,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'WMS 移动终端', + title: 'WMS移动终端(景旺冷冻)', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: ColorCommon.colorScheme), useMaterial3: true, diff --git a/lib/page/layout/home.dart b/lib/page/layout/home.dart index ba5a558..37512c9 100644 --- a/lib/page/layout/home.dart +++ b/lib/page/layout/home.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:wms_app/page/stockIn/StackInWheelEBS.dart'; +import 'package:wms_app/page/stockIn/stackInWheelEBS.dart'; import '../stock/stockCheck.dart'; import '/common/colorCom.dart'; import 'package:bruno/bruno.dart'; -import 'package:wms_app/page/stockIn/StackInWheelMes.dart'; -import 'package:wms_app/page/stockIn/StockInEmpty.dart'; +import 'package:wms_app/page/stockIn/stockInEmpty.dart'; import 'package:wms_app/page/stock/stockSearch.dart'; import 'package:wms_app/page/pick/pick.dart'; @@ -28,7 +27,7 @@ class _HomePageState extends State { centerTitle: true, backgroundColor: ColorCommon.colorScheme, title: const Text( - "景旺WMS移动终端", + "景旺WMS移动终端(冷冻)", style: TextStyle( color: Colors.white ), @@ -49,10 +48,10 @@ class _HomePageState extends State { ListTile(title: const Text("空载具入库"), trailing: const Icon(Icons.grain), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const StockInEmpty())); }), - ListTile(title: const Text("MES成品入库"), trailing: const Icon(Icons.add_box), onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => const StockInWheelMes())); - }), - ListTile(title: const Text("EBS成品入库"), trailing: const Icon(Icons.add_box), onTap: () { + // ListTile(title: const Text("MES成品入库"), trailing: const Icon(Icons.add_box), onTap: () { + // Navigator.push(context, MaterialPageRoute(builder: (context) => const StockInWheelMes())); + // }), + ListTile(title: const Text("码盘入库"), trailing: const Icon(Icons.add_box), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const StockInWheelEBS())); }), ListTile(title: const Text("出库拣货"), trailing: const Icon(Icons.back_hand), onTap: () { diff --git a/lib/page/layout/login.dart b/lib/page/layout/login.dart index 932f0d3..2fcf778 100644 --- a/lib/page/layout/login.dart +++ b/lib/page/layout/login.dart @@ -21,7 +21,7 @@ class _LoginPageState extends State { return Scaffold( appBar: AppBar( title: const Text( - "请登录(景旺成品仓)", + "请登录(景旺冷冻仓)", style: TextStyle( color: Colors.white ), @@ -32,6 +32,7 @@ class _LoginPageState extends State { body: Center( child: Column( children: [ + const Text("测试程序,禁止用于正式环境", style: TextStyle(color: Colors.redAccent)), Padding( padding: const EdgeInsets.only( top: 120, diff --git a/lib/page/pick/pick.dart b/lib/page/pick/pick.dart index 45e091e..948a2b4 100644 --- a/lib/page/pick/pick.dart +++ b/lib/page/pick/pick.dart @@ -1,6 +1,11 @@ +import 'dart:convert'; + import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import 'package:wms_app/utils/stringUtils.dart'; +import '../../apiclient/pickApi.dart'; +import '../../utils/dialogUtils.dart'; import '/common/colorCom.dart'; class Pick extends StatefulWidget { @@ -14,6 +19,7 @@ class _PickPageState extends State { final _vehicleNoTextController = TextEditingController(); // 查询输入框 List tableData = []; + int dataCount = 0; @override Widget build(BuildContext context) { @@ -60,7 +66,7 @@ class _PickPageState extends State { )), Padding(padding: const EdgeInsets.only( ), child: ElevatedButton( - onPressed: search, + onPressed: pickComplete, style: ButtonStyle( backgroundColor: WidgetStateProperty.all(ColorCommon.colorScheme), ), @@ -86,16 +92,15 @@ class _PickPageState extends State { backgroundColor: Colors.transparent, columns: [ TDTableCol(title: '序号', colKey: 'id', align: TDTableColAlign.center, width: 60), - TDTableCol(title: '载具号', colKey: 'vehicleNo', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '物料号', colKey: 'boxNo', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '拣货数', colKey: 'goodsNum', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '实际拣货数', colKey: 'goodsId', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '物料名称', colKey: 'boxNo', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '物料描述', colKey: 'boxNo', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '任务标识', colKey: 'boxNo', align: TDTableColAlign.center, ellipsis: true, width: 80) + TDTableCol(title: '载具号', colKey: 'vehicleNo', align: TDTableColAlign.center, ellipsis: true, width: 150), + TDTableCol(title: '物料号', colKey: 'goodsId', align: TDTableColAlign.center, ellipsis: true, width: 100), + TDTableCol(title: '需要拣货数', colKey: 'needNum', align: TDTableColAlign.center, ellipsis: true, width: 100), + TDTableCol(title: '实际拣货数', colKey: 'pickNum', align: TDTableColAlign.center, ellipsis: true, width: 100), + TDTableCol(title: '物料名称', colKey: 'goodsName', align: TDTableColAlign.center, ellipsis: true, width: 100), ], data: tableData, onCellTap: (index, dynamic, cell) { + clickLine(index, dynamic, cell); }), ) ], @@ -106,18 +111,158 @@ class _PickPageState extends State { /// 查询拣货数 void search() { + String vehicleNo = _vehicleNoTextController.text; + if(StringUtils.isEmpty(vehicleNo)) { + DialogUtils.showWarningMessage(context, "警告", "请先扫描或者输入载具号", btnLabel: "确定"); + return; + } + setState(() { + tableData = []; + }); + dataCount = 0; + BrnLoadingDialog.show(context, content: "正在查询..."); + PickApi.getPickTask(vehicleNo).then((response) { + if (response["code"] != 200) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器请求失败", btnLabel: "我知道了"); + } + return; + } + final data = Map.from(jsonDecode(response["data"])); + if (data["code"] == 200) { + final returnData = data["data"] as List; + // 请求成功 + setState(() { + for(var pickTask in returnData) { + dataCount ++; + tableData.add({ + "id" : dataCount.toString(), + "vehicleNo": pickTask["vehicleNo"].toString(), + "goodsId": pickTask["goodsId"].toString(), + "needNum": pickTask["pickingNum"].toString(), + "pickNum": pickTask["pickingNum"].toString(), + "goodsName": pickTask["goodsName"].toString(), + }); + } + }); + return; + } + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器返回失败:${data["message"]}", + btnLabel: "我知道了"); + } + return; + }).catchError((err) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showErrorMessage(thisContext, "请求发生错误", + "请求服务器发生错误:${err.toString()}", btnLabel: "我知道了"); + } + return; + }).whenComplete(() { + var thisContext = context; + if (thisContext.mounted) { + BrnLoadingDialog.dismiss(thisContext); + } + }); + } + /// 行数据点击事件 + void clickLine(index, dynamic, cell) { + if(cell.colKey == "pickNum") { // 点击数量 + showPickForm(index, dynamic); + return; + } + showDetails(index, dynamic); + } + + /// 点击行展示数据详情 + void showDetails(index, tableRow) { + List message = []; + message.add({"label":"序号:", "msg":tableRow["id"].toString()}); + message.add({"label":"载具号:", "msg":tableRow["vehicleNo"].toString()}); + message.add({"label":"物料号:", "msg":tableRow["goodsId"].toString()}); + message.add({"label":"需要拣货数:", "msg":tableRow["needNum"].toString()}); + message.add({"label":"实际拣货数:", "msg":tableRow["pickNum"].toString()}); + message.add({"label":"物料名称:", "msg":tableRow["goodsName"].toString()}); + DialogUtils.showMessageList(context, "数据详情", message, btnLabel: "我知道了"); } /// 展示拣货的弹窗 - void showPickForm() { - - + void showPickForm(index, dynamic) { + DialogUtils.showInputMessage(context, "请输入要拣货数量", message: "仅支持数字", confirm: (value) { + if(!StringUtils.isNumber(value)) { + DialogUtils.showWarningMessage(context, "警告", "该文本框仅支持数字"); + return; + } + setState((){ + tableData.where((w)=>w["id"] == dynamic["id"]).first["pickNum"] = value; + }); + }); } /// 拣货完成 void pickComplete() { - + if(tableData.isEmpty) { + DialogUtils.showWarningMessage(context, "警告", "没有拣货数据", btnLabel: "确定"); + return; + } + List data = []; + for(var pickData in tableData) { + data.add({ + "vehicleNo": pickData["vehicleNo"].toString(), + "goodsId": pickData["goodsId"].toString(), + "pickingNum": pickData["pickNum"].toString() + }); + } + BrnLoadingDialog.show(context, content: "请稍后..."); + PickApi.pickComplete(data).then((response) { + if (response["code"] != 200) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器请求失败", btnLabel: "我知道了"); + } + return; + } + final data = Map.from(jsonDecode(response["data"])); + if (data["code"] == 200) { + // 请求成功 + setState(() { + _vehicleNoTextController.clear(); + tableData = []; + }); + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showSuccessMessage( + thisContext, "拣货成功", "", btnLabel: "我知道了"); + } + return; + } + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器返回失败:${data["message"]}", + btnLabel: "我知道了"); + } + return; + }).catchError((err) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showErrorMessage(thisContext, "请求发生错误", + "请求服务器发生错误:${err.toString()}", btnLabel: "我知道了"); + } + return; + }).whenComplete(() { + var thisContext = context; + if (thisContext.mounted) { + BrnLoadingDialog.dismiss(thisContext); + } + }); } } \ No newline at end of file diff --git a/lib/page/stockIn/StackInWheelEBS.dart b/lib/page/stockIn/StackInWheelEBS.dart deleted file mode 100644 index 2ad9151..0000000 --- a/lib/page/stockIn/StackInWheelEBS.dart +++ /dev/null @@ -1,293 +0,0 @@ -import 'dart:convert'; - -import 'package:bruno/bruno.dart'; -import 'package:flutter/material.dart'; -import '/common/colorCom.dart'; -import 'package:tdesign_flutter/tdesign_flutter.dart'; -import 'package:wms_app/utils/DialogUtils.dart'; -import 'package:wms_app/apiclient/WmsApiClient.dart'; - -class StockInWheelEBS extends StatefulWidget { - const StockInWheelEBS({super.key}); - @override - State createState() => _StockInWheelEBSPageState(); -} - -/// EBS码盘入库 -class _StockInWheelEBSPageState extends State { - - final _vehicleTextController = TextEditingController(); // 载具号输入框 - List tableData = []; // 表格数据类型 - int tableIndex = 0; // 序号 - int selectCount = 0; // 已选择的数量 - String inArea = "立体库"; // 入库位置 - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - iconTheme: const IconThemeData( - color: Colors.white - ), - leading: IconButton(onPressed: () { - Navigator.of(context).pop(); - }, icon: const Icon(Icons.arrow_back)), - actions: [ - IconButton(onPressed: () { - getTableData(); // 刷新表格按钮 - }, icon: const Icon(Icons.refresh)) - ], - centerTitle: true, - backgroundColor: ColorCommon.colorScheme, - title: const Text( - "EBS成品入库", - style: TextStyle( - color: Colors.white - ), - ), - ), - body: Center( - child: Padding(padding: const EdgeInsets.only( - top: 5, - left: 10, - right: 10, - ), child: ListView( - children: [ - BrnTextInputFormItem( - controller: _vehicleTextController, - title: "载具号:", hint: "请扫描或输入", - isRequire: true, - ), - BrnRadioInputFormItem( - title: "选择目的地:", - options: [inArea, "装箱线"], - value: inArea, - onChanged: (oldValue, newValue) { - inArea = newValue ?? "立体库"; - }, - ), - Padding(padding: const EdgeInsets.only( - top: 5 - ), child: ElevatedButton( - onPressed: wheelComplete, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(ColorCommon.colorScheme), - ), - child: const Text( - "码盘完成", - style: TextStyle( - color: Colors.white - )) - )), - Padding(padding: const EdgeInsets.only( - top: 10, - bottom: 10 - ), child: Text("已经载入的入库单(已选择:$selectCount):"), - ), - Container( - decoration: BoxDecoration( - border: Border.all(color: const Color(0x4D0C0C05), width: 0.3),// border - borderRadius: BorderRadius.circular((5)), // 圆角 - ), - child: TDTable( - bordered: true, - width: MediaQuery.of(context).size.width, - backgroundColor: Colors.transparent, - columns: [ - TDTableCol(title: '*', colKey: 'action', width: 45, align: TDTableColAlign.center), - TDTableCol(title: '序号', colKey: 'id', align: TDTableColAlign.center, width: 80), - TDTableCol(title: '物料ID', colKey: 'itemId', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '物料编码', colKey: 'itemCode', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '数量', colKey: 'quantity', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '已接收数量', colKey: 'quantityReceives', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '物料描述', colKey: 'itemDesc', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '订单头主键', colKey: 'poHeaderId', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '订单行主键', colKey: 'poLineId', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '发运行主键', colKey: 'lineLocationId', align: TDTableColAlign.center, ellipsis: true, width: 100), - TDTableCol(title: '收货组织代码', colKey: 'shipToOrganization', align: TDTableColAlign.center, ellipsis: true, width: 110), - TDTableCol(title: '采购单位', colKey: 'purUomCode', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '库存单位', colKey: 'invUomCode', align: TDTableColAlign.center, ellipsis: true, width: 110), - TDTableCol(title: '发运行号', colKey: 'shipmentNum', align: TDTableColAlign.center, ellipsis: true, width: 80), - TDTableCol(title: '分配ID', colKey: 'poDistributionId', align: TDTableColAlign.center, ellipsis: true, width: 100), - ], - data: tableData, - onCellTap: (index, dynamic, cell) { - if(cell.colKey == "action") { - setState(() { - final action = dynamic["action"]; - dynamic["action"] = action == "✓" ? "" : "✓"; - selectCount = tableData.where((w) => w["action"] == "✓").length; - }); - } else { - showDetails(index, dynamic); - } - }), - ) - ], - )), - ), - ); - } - - /// 获取入库单数据 - void getTableData() { - BrnLoadingDialog.show(context, content: "正在拉取数据", barrierDismissible: false); - setState(() { - tableData = []; - tableIndex = 0; - }); - WmsApiClient.getCuxData().then((response){ - if(response["code"] != 200) { - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showWarningMessage(thisContext, "警告", "服务器请求失败", btnLabel: "我知道了"); - } - return; - } - final data = Map.from(jsonDecode(response["data"])); - if(data["code"] == 200) { - // 服务器返回成功 - final cuxData = data["data"] as List; - setState(() { - for (var item in cuxData) { - tableIndex ++; - tableData.add({ - 'id': (tableIndex).toString(), - 'itemId': item["itemId"].toString(), - 'itemCode': item["itemCode"], - 'quantity': item["quantity"].toString(), - 'quantityReceives': item["quantityReceives"].toString(), - 'itemDesc': item["itemDesc"], - 'poHeaderId': item["poHeaderId"].toString(), - 'poLineId': item["poLineId"].toString(), - 'lineLocationId': item["lineLocationId"].toString(), - 'shipToOrganization': item["shipToOrganization"], - 'purUomCode': item["purUomCode"], - 'invUomCode': item["invUomCode"], - 'shipmentNum': item["shipmentNum"].toString(), - 'poDistributionId': item["poDistributionId"].toString(), - }); - } - }); - return; - } - // 服务器返回失败 - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showWarningMessage(thisContext, "警告", "服务器返回失败:${data["message"]}", btnLabel: "我知道了"); - } - return; - }).catchError((err){ - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showErrorMessage(thisContext, "请求发生错误", "请求服务器发生错误:${err.toString()}", btnLabel: "我知道了"); - } - return; - }).whenComplete((){ - var thisContext = context; - if(thisContext.mounted) { - BrnLoadingDialog.dismiss(thisContext); - } - }); - } - - /// 显示详细信息 - void showDetails(index, dynamic) { - String goodsDetails = ""; - goodsDetails += "序号:${dynamic["id"]??""}\r\n"; - goodsDetails += "物料ID:${dynamic["itemId"]??""}\r\n"; - goodsDetails += "物料编码:${dynamic["itemCode"]??""}\r\n"; - goodsDetails += "数量:${dynamic["quantity"]??""}\r\n"; - goodsDetails += "已接收数量:${dynamic["quantityReceives"]??""}\r\n"; - goodsDetails += "物料描述:${dynamic["itemDesc"]??""}\r\n"; - goodsDetails += "订单头主键:${dynamic["poHeaderId"]??""}\r\n"; - goodsDetails += "订单行主键:${dynamic["poLineId"]??""}\r\n"; - goodsDetails += "发运行主键:${dynamic["lineLocationId"]??""}\r\n"; - goodsDetails += "收货组织代码:${dynamic["shipToOrganization"]??""}\r\n"; - goodsDetails += "采购单位:${dynamic["purUomCode"]??""}\r\n"; - goodsDetails += "库存单位:${dynamic["invUomCode"]??""}\r\n"; - goodsDetails += "发运行号:${dynamic["shipmentNum"]??""}\r\n"; - goodsDetails += "分配ID:${dynamic["poDistributionId"]??""}"; - DialogUtils.showMessage(context, "详情", goodsDetails, btnLabel: "我知道了"); - } - - /// 码盘完成 - void wheelComplete() { - if(tableData.isEmpty) { - DialogUtils.showWarningMessage(context, "警告", "您当前没有待入库的入库单", btnLabel: "确定"); - return; - } - String vehicleNo = _vehicleTextController.text; - if(vehicleNo == "") { - DialogUtils.showWarningMessage(context, "警告", "请先扫描载具号", btnLabel: "返回填写"); - return; - } - List selectData = tableData.where((w) => w["action"] == "✓").toList(); - if(selectCount < 1) { - DialogUtils.showWarningMessage(context, "警告", "您还没有选择入库单", btnLabel: "返回选择"); - return; - } - DialogUtils.showConfirmMessage(context, "完成确认?", "当前选择了 $selectCount 条入库单,是否继续?", confirmBtn: "继续", confirm: () { - int taskType = inArea == "立体库" ? 1 : 2; // 1 表示进库,2 表示进站台 - List bindingGoods = []; - dynamic requestData = {"vehicleNo" : vehicleNo, "taskType" : taskType, "bindingGoods" : bindingGoods }; - for (var item in selectData) { - bindingGoods.add({ - "boxNo": item["itemId"], - "numPerBox": item["quantityReceives"], - "goodsNum": item["quantity"], - "picketNum": item["quantity"], - "otherNum": item["quantity"], - "goodsId": item["itemCode"], - "saleOrderNo": item["lineLocationId"], - "packetLevel": "", - "cycle": "", - "customSaleOrderNo": item["shipToOrganization"], - "minorWarehouseId": item["poDistributionId"], - "goodsDesc": item["itemDesc"], - "poHeaderId":item["poHeaderId"], - "poLineId":item["poLineId"], - "lineLocationId":item["lineLocationId"], - }); - } - BrnLoadingDialog.show(context, content: "正在请求入库"); - WmsApiClient.bindingVehicleInEbs(requestData).then((response){ - final data = Map.from(jsonDecode(response["data"])); - if(data["code"] == 200) { - // 请求成功 - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showSuccessMessage(thisContext, "成功", "", btnLabel: "我知道了"); - getTableData(); // 刷新信息 - setState(() { - _vehicleTextController.text = ""; - }); - } - return; - } - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showWarningMessage(thisContext, "警告", "服务器返回失败:${data["message"]}", btnLabel: "我知道了"); - } - return; - }).catchError((err){ - var thisContext = context; - if(thisContext.mounted) { - DialogUtils.showErrorMessage(thisContext, "请求发生错误", "请求服务器发生错误:${err.toString()} \r\n ${jsonEncode(requestData)}", btnLabel: "我知道了"); - } - return; - }).whenComplete((){ - var thisContext = context; - if(thisContext.mounted) { - BrnLoadingDialog.dismiss(thisContext); - } - }); - }); - } - -} \ No newline at end of file diff --git a/lib/page/stockIn/stackInWheelEBS.dart b/lib/page/stockIn/stackInWheelEBS.dart new file mode 100644 index 0000000..11b0206 --- /dev/null +++ b/lib/page/stockIn/stackInWheelEBS.dart @@ -0,0 +1,355 @@ +import 'dart:convert'; + +import 'package:bruno/bruno.dart'; +import 'package:flutter/material.dart'; +import 'package:wms_app/utils/stringUtils.dart'; +import '/common/colorCom.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; +import 'package:wms_app/utils/dialogUtils.dart'; +import 'package:wms_app/apiclient/wmsApiClient.dart'; + +class StockInWheelEBS extends StatefulWidget { + const StockInWheelEBS({super.key}); + @override + State createState() => _StockInWheelEBSPageState(); +} + +/// EBS码盘入库 +class _StockInWheelEBSPageState extends State { + + final _vehicleTextController = TextEditingController(); // 载具号输入框 + final _goodsCodeController = TextEditingController(); // 条码输入框 + List tableData = []; // 表格数据类型 + List packageData = []; // 已经码盘的数据 + int packageDataId = 0; // 已经码盘的数据的序号 + List list = [ + BrnMultiSelectBottomPickerItem("102", "库区1", isChecked: true), + BrnMultiSelectBottomPickerItem("102", "库区2"), + BrnMultiSelectBottomPickerItem("102", "库区3"), + ]; + + + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + iconTheme: const IconThemeData( + color: Colors.white + ), + leading: IconButton(onPressed: () { + Navigator.of(context).pop(); + }, icon: const Icon(Icons.arrow_back)), + centerTitle: true, + backgroundColor: ColorCommon.colorScheme, + title: const Text( + "码盘入库", + style: TextStyle( + color: Colors.white + ), + ), + ), + body: Center( + child: Padding(padding: const EdgeInsets.only( + top: 5, + left: 10, + right: 10, + ), child: ListView( + children: [ + BrnTextInputFormItem( + controller: _vehicleTextController, + title: "载具号:", hint: "请扫描或输入", + isRequire: true, + ), + BrnTextInputFormItem( + controller: _goodsCodeController, + title: "条码:", hint: "请扫描物料二维码", + isRequire: true, + ), + Padding(padding: const EdgeInsets.only( + top: 5 + ), child: ElevatedButton( + onPressed: resolveCode, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(ColorCommon.colorScheme), + ), + child: const Text( + "添加物料", + style: TextStyle( + color: Colors.white + )) + )), + Padding(padding: const EdgeInsets.only( + top: 0 + ), child: ElevatedButton( + onPressed: wheelComplete, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(ColorCommon.colorScheme), + ), + child: const Text( + "码盘完成", + style: TextStyle( + color: Colors.white + )) + )), + const Padding(padding: EdgeInsets.only( + top: 10, + bottom: 10 + ), child: Text("添加在载具的物料:"), + ), + Container( + decoration: BoxDecoration( + border: Border.all(color: const Color(0x4D0C0C05), width: 0.3),// border + borderRadius: BorderRadius.circular((5)), // 圆角 + ), + child: TDTable( + bordered: true, + width: MediaQuery.of(context).size.width, + backgroundColor: Colors.transparent, + columns: [ + TDTableCol( + title: '*', + colKey: 'action', + width: 45, + align: TDTableColAlign.center, + cellBuilder: (BuildContext context) { + return const SizedBox( + child: Icon(TDIcons.delete, color: Colors.redAccent, size: 10), + ); + }, + ), + TDTableCol(title: '序号', colKey: 'id', align: TDTableColAlign.center, width: 80), + TDTableCol(title: '采购单号', colKey: 'segment1', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '物料号', colKey: 'itemId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '批次号', colKey: 'batch', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '数量', colKey: 'quantity', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '重量', colKey: 'weight', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '生产日期', colKey: 'productData', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '库区', colKey: 'area', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '送货单号', colKey: 'sendOrderId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: 'WMS批次', colKey: 'goodsTypeId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '供应商批次', colKey: 'pruBatch', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '物料描述', colKey: 'goodsName', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '单位', colKey: 'unit', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '订单头主键', colKey: 'poHeaderId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '订单行主键', colKey: 'poLineId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + TDTableCol(title: '发运行主键', colKey: 'lineLocationId', align: TDTableColAlign.center, ellipsis: true, ellipsisTitle: true, width: 100), + ], + data: packageData, + onCellTap: (index, dynamic, cell) { + clickLine(index, dynamic, cell); + }), + ), + ], + )), + ), + ); + } + + /// 行数据点击事件 + void clickLine(index, dynamic, cell) { + if(cell.colKey == "action") { // 点击删除 + delete(dynamic); + return; + } + if(cell.colKey == "quantity") { // 点击数量 + modifyNumber(index, dynamic); + return; + } + showDetails(index, dynamic); + } + + /// 解析条码 + void resolveCode() { + String code = _goodsCodeController.text; + if(StringUtils.isEmpty(code)) { + DialogUtils.showWarningMessage(context, "警告", "条码文本框内无数据,请先扫描或者输入数据"); + return; + } + List codeData = code.split(","); + if(codeData.length != 6 && codeData.length != 8) { + DialogUtils.showWarningMessage(context, "警告", "条码格式错误"); + return; + } + // 请求获取详细数据,发送订单号和物料号 + String sendOrderId = ""; + if(codeData.length == 7) { + sendOrderId = codeData[6]; + } + String orderId = codeData[0]; + String goodsId = codeData[1]; + BrnLoadingDialog.show(context, content: "正在请求服务器数据"); + WmsApiClient.getGoodsCanUse(orderId, goodsId).then((response){ + if(response["code"] != 200) { + var thisContext = context; + if(thisContext.mounted) { + DialogUtils.showWarningMessage(thisContext, "警告", "服务器请求失败", btnLabel: "我知道了"); + } + return; + } + final data = Map.from(jsonDecode(response["data"])); + if(data["code"] == 200) { + final item = data["data"] as dynamic; + setState(() { + packageDataId ++; + packageData.add({ + "id": packageDataId.toString(), + "segment1": codeData[0], + "itemId": codeData[1], + "batch": codeData[2], + "quantity": codeData[3], + "weight": codeData[4], + "productData": codeData[5], + "area": item["storageAreaId"].toString(), + "sendOrderId": sendOrderId, // 送货单号 + "goodsTypeId":item["goodsTypeId"].toString(), + "pruBatch": item["pruBatch"].toString(), + "goodsName": item["goodsName"].toString(), + "unit": item["unit"].toString(), + "poHeaderId": item["poHeaderId"].toString(), + "poLineId": item["poLineId"].toString(), + "lineLocationId": item["lineLocationId"].toString(), + }); + _goodsCodeController.clear(); + }); + return; + } + var thisContext = context; + if(thisContext.mounted) { + DialogUtils.showWarningMessage(thisContext, "数据异常", "服务器返回错误:${data["message"]} ", btnLabel: "我知道了"); + } + return; + }).catchError((err){ + var thisContext = context; + if(thisContext.mounted) { + DialogUtils.showErrorMessage(thisContext, "请求发生错误", "请求服务器发生错误:${err.toString()} ", btnLabel: "我知道了"); + } + return; + }).whenComplete((){ + var thisContext = context; + if(thisContext.mounted) { + BrnLoadingDialog.dismiss(thisContext); + } + }); + } + + /// 删除已经码盘的物料 + void delete(dynamic) { + setState(() { + packageData.removeWhere((r){ + return r["id"] == dynamic["id"]; + }); + }); + if(packageData.isEmpty) { + packageDataId = 0; + } + } + + /// 修改数量 + void modifyNumber(index, dynamic) { + DialogUtils.showInputMessage(context, "请输入要修改的数量", message: "仅支持数字", confirm: (value) { + if(!StringUtils.isNumber(value)) { + DialogUtils.showWarningMessage(context, "警告", "该文本框仅支持数字"); + return; + } + setState((){ + packageData.where((w)=>w["id"] == dynamic["id"]).first["quantity"] = value; + }); + }); + } + + /// 显示详细信息 + void showDetails(index, tableRow) { + List message = []; + message.add({"label":"序号:", "msg":tableRow["id"].toString()}); + message.add({"label":"采购单号:", "msg":tableRow["segment1"].toString()}); + message.add({"label":"物料号:", "msg":tableRow["itemId"].toString()}); + message.add({"label":"批次号:", "msg":tableRow["batch"].toString()}); + message.add({"label":"数量:", "msg":tableRow["quantity"].toString()}); + message.add({"label":"重量:", "msg":tableRow["weight"].toString()}); + message.add({"label":"生产日期:", "msg":tableRow["productData"].toString()}); + message.add({"label":"库区:", "msg":tableRow["area"].toString()}); + message.add({"label":"送货单号:", "msg":tableRow["sendOrderId"].toString()}); + message.add({"label":"供应商批次:", "msg":tableRow["pruBatch"].toString()}); + message.add({"label":"WMS批次:", "msg":tableRow["goodsTypeId"].toString()}); + message.add({"label":"物料描述:", "msg":tableRow["goodsName"].toString()}); + message.add({"label":"单位:", "msg":tableRow["unit"].toString()}); + message.add({"label":"订单头主键:", "msg":tableRow["poHeaderId"].toString()}); + message.add({"label":"订单行主键:", "msg":tableRow["poLineId"].toString()}); + message.add({"label":"发运行主键:", "msg":tableRow["lineLocationId"].toString()}); + DialogUtils.showMessageList(context, "数据详情", message, btnLabel: "我知道了"); + } + + /// 码盘完成 + void wheelComplete() { + if(packageData.isEmpty){ + DialogUtils.showWarningMessage(context, "警告", "您的码盘数据为空", btnLabel: "确定"); + return; + } + String vehicleNo = _vehicleTextController.text; + if(StringUtils.isEmpty(vehicleNo)) { + DialogUtils.showWarningMessage(context, "警告", "请先扫描载具号", btnLabel: "返回填写"); + return; + } + int dataCount = packageData.length; + DialogUtils.showConfirmMessage(context, "码盘完成", "载具:$vehicleNo 码盘 $dataCount 条数据,是否继续?", confirmBtn: "继续", confirm: () + { + int taskType = 1; // 1 表示进库,2 表示进站台 + BrnLoadingDialog.show(context, content: "正在请求入库"); + WmsApiClient.bindingVehicleInLD({ + "vehicleNo": vehicleNo, + "inArea": taskType.toString(), + "storageArea" : "", + "goods": packageData + }).then((response) { + if (response["code"] != 200) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器请求失败", btnLabel: "我知道了"); + } + return; + } + final data = Map.from(jsonDecode(response["data"])); + if (data["code"] == 200) { + // 请求成功 + setState(() { + _vehicleTextController.clear(); + packageData = []; + }); + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showSuccessMessage( + thisContext, "码盘成功", "", btnLabel: "我知道了"); + } + return; + } + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showWarningMessage( + thisContext, "警告", "服务器返回失败:${data["message"]}", + btnLabel: "我知道了"); + } + return; + }).catchError((err) { + var thisContext = context; + if (thisContext.mounted) { + DialogUtils.showErrorMessage(thisContext, "请求发生错误", + "请求服务器发生错误:${err.toString()}", btnLabel: "我知道了"); + } + return; + }).whenComplete(() { + var thisContext = context; + if (thisContext.mounted) { + BrnLoadingDialog.dismiss(thisContext); + } + }); + }); + } + +} \ No newline at end of file diff --git a/lib/page/stockIn/StackInWheelMes.dart b/lib/page/stockIn/stackInWheelMes.dart similarity index 99% rename from lib/page/stockIn/StackInWheelMes.dart rename to lib/page/stockIn/stackInWheelMes.dart index 4ed1471..8bf4e2d 100644 --- a/lib/page/stockIn/StackInWheelMes.dart +++ b/lib/page/stockIn/stackInWheelMes.dart @@ -4,8 +4,8 @@ import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; import '/common/colorCom.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -import 'package:wms_app/utils/DialogUtils.dart'; -import 'package:wms_app/apiclient/WmsApiClient.dart'; +import 'package:wms_app/utils/dialogUtils.dart'; +import 'package:wms_app/apiclient/wmsApiClient.dart'; class StockInWheelMes extends StatefulWidget { const StockInWheelMes({super.key}); diff --git a/lib/page/stockIn/StockInEmpty.dart b/lib/page/stockIn/stockInEmpty.dart similarity index 97% rename from lib/page/stockIn/StockInEmpty.dart rename to lib/page/stockIn/stockInEmpty.dart index 53c94c4..3dc57ac 100644 --- a/lib/page/stockIn/StockInEmpty.dart +++ b/lib/page/stockIn/stockInEmpty.dart @@ -3,8 +3,8 @@ import 'dart:convert'; import 'package:bruno/bruno.dart'; import 'package:flutter/material.dart'; import '/common/colorCom.dart'; -import 'package:wms_app/utils/DialogUtils.dart'; -import 'package:wms_app/apiclient/WmsApiClient.dart'; +import 'package:wms_app/utils/dialogUtils.dart'; +import 'package:wms_app/apiclient/wmsApiClient.dart'; class StockInEmpty extends StatefulWidget { const StockInEmpty({super.key}); diff --git a/lib/utils/DialogUtils.dart b/lib/utils/dialogUtils.dart similarity index 86% rename from lib/utils/DialogUtils.dart rename to lib/utils/dialogUtils.dart index 7a02818..6d6d206 100644 --- a/lib/utils/DialogUtils.dart +++ b/lib/utils/dialogUtils.dart @@ -15,6 +15,26 @@ class DialogUtils { ); } + /// 展示一个信息列 , message 必须是 label 和 msg + static void showMessageList(BuildContext context, String title, List message, {String btnLabel = '确定'}) { + List msg = []; + for(var msgData in message) { + msg.add(BrnInfoModal(keyPart: " ${msgData["label"]}", valuePart: msgData["msg"].toString())); + } + BrnDialogManager.showSingleButtonDialog(context, + label: btnLabel, + title: title, + messageWidget: BrnPairInfoTable( + expandAtIndex: 4, + isFolded: false, + children: msg, + ), + onTap: () { + Navigator.of(context).pop(); + } + ); + } + /// 弹出一个成功的提示框 static void showSuccessMessage(BuildContext context, String title, String message, {String btnLabel = '确定'}) { BrnDialogManager.showSingleButtonDialog(context, diff --git a/lib/utils/stringUtils.dart b/lib/utils/stringUtils.dart new file mode 100644 index 0000000..962e2ee --- /dev/null +++ b/lib/utils/stringUtils.dart @@ -0,0 +1,19 @@ +class StringUtils { + + static bool isEmpty(String? value) { + if(value == null || value == "") { + return true; + } + return false; + } + + static bool isNumber(String? value) { + if(isEmpty(value)) { + return false; + } + return RegExp(r'^\d+$').hasMatch(value!); + } + + + +} \ No newline at end of file