import 'dart:convert'; import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:math_expressions/math_expressions.dart'; import 'package:sk_base_mobile/models/base_search_more_controller.dart'; import 'package:sk_base_mobile/models/sale_quotation.model.dart'; import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart'; import 'package:sk_base_mobile/services/storage.service.dart'; import 'package:sk_base_mobile/widgets/core/sk_muti_search_more.dart'; import 'package:sk_base_mobile/util/modal.util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:pinyin/pinyin.dart'; class SaleQuotationController extends GetxController { static SaleQuotationController get to => Get.find(); final RxList editingcell = RxList([null, null, null]); final GlobalKey scaffoldKey = GlobalKey(); RxList products = RxList([ SaleQuotationItemModel( name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z', cost: 4700), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700), SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500), SaleQuotationItemModel( name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000), SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700), SaleQuotationItemModel( name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200), SaleQuotationItemModel( name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500), SaleQuotationItemModel( name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000), SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'), SaleQuotationItemModel(name: '矿用本安型位移传感器'), SaleQuotationItemModel(name: '矿用本安型压力传感器'), SaleQuotationItemModel(name: '矿用本安型红外发射器'), SaleQuotationItemModel(name: '矿用本安型LED信号灯'), SaleQuotationItemModel(name: '倾角传感器'), SaleQuotationItemModel(name: '各类安装附件'), ]); RxList groups = RxList([]); RxInt totalCost = RxInt(0); RxDouble totalPrice = RxDouble(0.0); RxBool isFormulaEditing = false.obs; RxString formula = '成本 * 1.3 / 0.864'.obs; @override void onReady() { init(); super.onReady(); } Future init() async { String? salesQuotation = StorageService.to.getString('salesQuotation'); if (salesQuotation != null) { groups.assignAll((jsonDecode(salesQuotation) as List) .map((e) => SaleQuotationModel.fromJson(e)) .toList()); calculateTotal(); } } void calculateTotal({String? newFormula}) { //计算groups中所有items中的amout总和 totalCost.value = groups.fold(0, (previousValue, element) { return previousValue + element.items.fold(0, (previousValue, element) { return previousValue + element.amount; }); }); Parser p = Parser(); Expression exp = p.parse(newFormula ?? formula.value); Variable x = Variable('成本'); ContextModel cm = ContextModel()..bindVariable(x, Number(totalCost.value)); double eval = exp.evaluate(EvaluationType.REAL, cm); totalPrice.value = eval.toPrecision(2); } /// 实时计算数量,单价,总价之间的关系 SaleQuotationItemModel calculateRow( SaleQuotationItemModel data, String changedField) { Decimal quantity = Decimal.fromInt(0); Decimal cost = Decimal.fromInt(0); Decimal amount = Decimal.fromInt(0); if (data.quantity != 0) { quantity = Decimal.parse('${data.quantity}'); } if (data.cost != 0) { cost = Decimal.parse('${data.cost}'); } if (data.amount != 0) { amount = Decimal.parse('${data.amount}'); } // 入库一般是先输入单价和数量,然后计算单价 if (changedField != 'amount') { Decimal result = cost * quantity; data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0; } if (changedField == 'amount' && quantity != Decimal.zero) { Decimal result = (amount / quantity).toDecimal(scaleOnInfinitePrecision: 10); data.cost = result != Decimal.zero ? result.toBigInt().toInt() : 0; } else if (changedField != 'amount') { Decimal result = (cost * quantity); data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0; } return data; } void saveChanges(int groupIndex, int rowIndex, SaleQuotationItemModel data, String changedField) { data = calculateRow(data, changedField); groups[groupIndex].items[rowIndex] = data; calculateTotal(); stopEditing(); } void stopEditing() { editingcell.assignAll([null, null, null]); save(); } Future save() async { await StorageService.to .setString('salesQuotation', jsonEncode(groups.toJson())); // SnackBarUtil().success('已保存到本地'); } void addGroup() async { final controller = Get.put(GroupSearchMoreController()); // 选择组件 选择分组 ModalUtil.showGeneralDialog( content: SkMutilSearchMore( controller: controller, enablePullUp: false, enablePullDown: true, onOk: (List indexes) { groups.addAll(controller.list.where((element) { return indexes.contains(controller.list.indexOf(element)); })); save(); }, leadingBuilder: (index) { return Container( padding: EdgeInsets.symmetric( horizontal: ScreenAdaper.width(5), vertical: ScreenAdaper.height(10)), child: Row( children: [ Text( controller.list[index].name, style: TextStyle(fontSize: ScreenAdaper.height(30)), ), ], ), ); }, ), width: Get.width - ScreenAdaper.width(50)) .then((value) => Get.delete()); calculateTotal(); } void removeGroup(int index) { groups.removeAt(index); calculateTotal(); save(); } void addItems(int groupIndex) async { final controller = Get.put(ItemSearchMoreController()); // 选择产品 ModalUtil.showGeneralDialog( content: SkMutilSearchMore( controller: controller, enablePullUp: false, enablePullDown: true, isDialog: true, onOk: (List indexes) { groups[groupIndex].items.addAll(products.where((element) { return indexes.contains(products.indexOf(element)); })); save(); }, leadingBuilder: (index) { return Container( padding: EdgeInsets.symmetric( horizontal: ScreenAdaper.width(5), vertical: ScreenAdaper.height(10)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( controller.list[index].name, style: TextStyle( fontSize: ScreenAdaper.height(30)), ), ], ), if (controller.list[index].spec != null) Row( children: [ Text( '型号:${controller.list[index].spec ?? ''}', textAlign: TextAlign.start, style: TextStyle( fontSize: ScreenAdaper.height(25)), ), ], ), Row( children: [ Text( '单价:¥${controller.list[index].cost}', textAlign: TextAlign.start, style: TextStyle( fontSize: ScreenAdaper.height(25)), ), ], ), if (controller.list[index].remark != null) Row( children: [ Text( '备注:${controller.list[index].remark ?? ''}', textAlign: TextAlign.start, style: TextStyle( fontSize: ScreenAdaper.height(25)), ), ], ), ])); }, ), width: Get.width - ScreenAdaper.width(50)) .then((value) => Get.delete()); calculateTotal(); } void removeItem(int groupIndex, int rowIndex) { groups[groupIndex].items.removeAt(rowIndex); calculateTotal(); } } class GroupSearchMoreController extends GetxController with BaseSearchMoreController { @override Future> getData({bool isRefresh = false}) async { List newList = [ SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])), SaleQuotationModel(name: '端头架电控部分', items: RxList([])), SaleQuotationModel(name: '主阀部分', items: RxList([])), SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])), SaleQuotationModel(name: '位移测量部分', items: RxList([])), SaleQuotationModel(name: '压力检测部分', items: RxList([])), SaleQuotationModel(name: '煤机定位部分', items: RxList([])), SaleQuotationModel(name: '姿态检测部分', items: RxList([])), ]; list.assignAll(newList .where((element) => PinyinHelper.getPinyin(element.name, separator: '') .contains(searchKey.value)) .toList()); return newList; } } class ItemSearchMoreController extends GetxController with BaseSearchMoreController { @override Future> getData({bool isRefresh = false}) async { List newList = [ SaleQuotationItemModel( name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z', cost: 4700), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700), SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400), SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500), SaleQuotationItemModel( name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000), SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700), SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200), SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700), SaleQuotationItemModel( name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200), SaleQuotationItemModel( name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500), SaleQuotationItemModel( name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000), SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'), SaleQuotationItemModel(name: '矿用本安型位移传感器'), SaleQuotationItemModel(name: '矿用本安型压力传感器'), SaleQuotationItemModel(name: '矿用本安型红外发射器'), SaleQuotationItemModel(name: '矿用本安型LED信号灯'), SaleQuotationItemModel(name: '倾角传感器'), SaleQuotationItemModel(name: '各类安装附件'), ]; list.assignAll(newList .where((element) => PinyinHelper.getPinyin(element.name, separator: '') .contains(searchKey.value)) .toList()); return newList; } }