622 lines
23 KiB
Dart
622 lines
23 KiB
Dart
|
import 'package:collection/collection.dart';
|
|||
|
import 'package:flutter/material.dart';
|
|||
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
|||
|
import 'package:get/get.dart';
|
|||
|
import 'package:sk_base_mobile/app_theme.dart';
|
|||
|
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
|||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
|||
|
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_drawer.dart';
|
|||
|
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.controller.dart';
|
|||
|
import 'package:sk_base_mobile/util/common.util.dart';
|
|||
|
import 'package:sk_base_mobile/util/modal.util.dart';
|
|||
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
|||
|
import 'package:sk_base_mobile/widgets/form_item/sk_number_input.dart';
|
|||
|
import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart';
|
|||
|
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
|
|||
|
import 'package:flutter_sticky_header/flutter_sticky_header.dart';
|
|||
|
import 'package:math_expressions/math_expressions.dart';
|
|||
|
|
|||
|
class SaleQuotationPage extends StatelessWidget {
|
|||
|
SaleQuotationPage({super.key});
|
|||
|
final controller = Get.put(SaleQuotationController());
|
|||
|
final quantityWidth = 140.0;
|
|||
|
final unitPriceWidth = 140.0;
|
|||
|
final amountWidth = 140.0;
|
|||
|
final TextStyle? headerTitleStyle = TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30),
|
|||
|
fontWeight: FontWeight.w600,
|
|||
|
color: Theme.of(Get.context!).colorScheme.onPrimary);
|
|||
|
final headerBgcolor = AppTheme.appbarBgColor;
|
|||
|
|
|||
|
@override
|
|||
|
Widget build(BuildContext context) {
|
|||
|
return Obx(() => Scaffold(
|
|||
|
key: controller.scaffoldKey,
|
|||
|
backgroundColor: AppTheme.nearlyWhite,
|
|||
|
endDrawer: Drawer(
|
|||
|
// 从右到左出现
|
|||
|
child: SaleQuotationEndDrawer(),
|
|||
|
),
|
|||
|
appBar: SkAppbar(
|
|||
|
onPop: () async {
|
|||
|
// 在这里判断是否允许用户返回
|
|||
|
// 如果返回 true,用户可以返回
|
|||
|
// 如果返回 false,用户不能返回
|
|||
|
if (controller.templateName.value == '默认' &&
|
|||
|
controller.groups.isNotEmpty) {
|
|||
|
await ModalUtil.alert(
|
|||
|
confirmText: '保存',
|
|||
|
cancelText: '继续退出',
|
|||
|
contentText: '是否保存当前模板?',
|
|||
|
onConfirm: () {
|
|||
|
controller.openTemplateNameEditPopup(
|
|||
|
onConfirm: (title) async {
|
|||
|
controller.templateName.value = title;
|
|||
|
await controller.saveToLocal();
|
|||
|
await controller.saveToDatabase();
|
|||
|
RouterUtil.back();
|
|||
|
});
|
|||
|
},
|
|||
|
onCancel: () {
|
|||
|
RouterUtil.back();
|
|||
|
});
|
|||
|
} else {
|
|||
|
RouterUtil.back();
|
|||
|
}
|
|||
|
},
|
|||
|
title: '报价计算-${controller.templateName}',
|
|||
|
action: [
|
|||
|
IconButton(
|
|||
|
onPressed: () {
|
|||
|
controller.scaffoldKey.currentState?.openEndDrawer();
|
|||
|
},
|
|||
|
icon: const Icon(Icons.more_horiz_outlined,
|
|||
|
color: AppTheme.white),
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
body: SafeArea(
|
|||
|
bottom: ScreenAdaper.isLandspace() ? false : true,
|
|||
|
child: Stack(children: [
|
|||
|
Column(
|
|||
|
children: [
|
|||
|
builderHeader(),
|
|||
|
Expanded(
|
|||
|
child: Obx(() => controller.groups.isEmpty
|
|||
|
? Column(
|
|||
|
mainAxisAlignment: MainAxisAlignment.center,
|
|||
|
children: [
|
|||
|
Text(
|
|||
|
'请右上角选择模板',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30)),
|
|||
|
),
|
|||
|
Text('或者左上角加号添加分组',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30)))
|
|||
|
],
|
|||
|
)
|
|||
|
: CustomScrollView(
|
|||
|
slivers: controller.groups
|
|||
|
.mapIndexed<Widget>(
|
|||
|
(index, e) => buildBody(index))
|
|||
|
.toList(),
|
|||
|
))),
|
|||
|
// 当键盘弹起时,不显示
|
|||
|
|
|||
|
SizedBox(
|
|||
|
height: ScreenAdaper.height(100),
|
|||
|
child: buildTotalCostRow(),
|
|||
|
),
|
|||
|
SizedBox(
|
|||
|
height: ScreenAdaper.height(100),
|
|||
|
child: buildTotalSalesPriceRow(),
|
|||
|
)
|
|||
|
],
|
|||
|
),
|
|||
|
]),
|
|||
|
),
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
Widget buildTotalSalesPriceRow() {
|
|||
|
final formulaController =
|
|||
|
TextEditingController(text: controller.formula.value);
|
|||
|
return Container(
|
|||
|
padding: EdgeInsets.symmetric(
|
|||
|
horizontal: ScreenAdaper.width(20),
|
|||
|
vertical: ScreenAdaper.height(10)),
|
|||
|
decoration: BoxDecoration(
|
|||
|
border: Border(
|
|||
|
top: BorderSide(width: 1, color: Colors.grey[200]!),
|
|||
|
),
|
|||
|
),
|
|||
|
child: Row(
|
|||
|
children: [
|
|||
|
Text(
|
|||
|
'合计',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30), fontWeight: FontWeight.w600),
|
|||
|
),
|
|||
|
Expanded(
|
|||
|
child: Obx(
|
|||
|
() => Container(
|
|||
|
alignment: Alignment.centerLeft,
|
|||
|
padding:
|
|||
|
EdgeInsets.symmetric(horizontal: ScreenAdaper.width(10)),
|
|||
|
height: ScreenAdaper.height(100),
|
|||
|
width: ScreenAdaper.width(100),
|
|||
|
child: controller.isFormulaEditing.value
|
|||
|
? SkTextInput(
|
|||
|
hint: '',
|
|||
|
isDense: true,
|
|||
|
autoFocus: true,
|
|||
|
onFieldSubmitted: (value) {
|
|||
|
controller.formula.value = value;
|
|||
|
controller.isFormulaEditing.value = false;
|
|||
|
},
|
|||
|
validator: (String? value) {
|
|||
|
if (value == null) {
|
|||
|
return null;
|
|||
|
}
|
|||
|
try {
|
|||
|
Parser p = Parser();
|
|||
|
Expression exp = p.parse(value);
|
|||
|
Variable x = Variable('成本');
|
|||
|
ContextModel cm = ContextModel()
|
|||
|
..bindVariable(
|
|||
|
x, Number(controller.totalCost.value));
|
|||
|
exp.evaluate(EvaluationType.REAL, cm);
|
|||
|
return null;
|
|||
|
} catch (e) {
|
|||
|
return '公式错误';
|
|||
|
}
|
|||
|
},
|
|||
|
onChanged: (String formula) {
|
|||
|
try {
|
|||
|
controller.calculateTotal(newFormula: formula);
|
|||
|
} catch (e) {}
|
|||
|
},
|
|||
|
onTapOutside: (String value) {
|
|||
|
controller.formula.value = value;
|
|||
|
controller.isFormulaEditing.value = false;
|
|||
|
},
|
|||
|
contentPadding: EdgeInsets.symmetric(
|
|||
|
horizontal: ScreenAdaper.width(20),
|
|||
|
vertical: ScreenAdaper.height(10)),
|
|||
|
textController: formulaController)
|
|||
|
: InkWell(
|
|||
|
onTap: () {
|
|||
|
controller.isFormulaEditing.value = true;
|
|||
|
},
|
|||
|
child: Text('(${controller.formula})',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30),
|
|||
|
color: AppTheme.grey)),
|
|||
|
),
|
|||
|
),
|
|||
|
),
|
|||
|
),
|
|||
|
// IconButton(
|
|||
|
// onPressed: () {
|
|||
|
// controller.isFormulaEditing.value =
|
|||
|
// !controller.isFormulaEditing.value;
|
|||
|
// },
|
|||
|
// icon: Icon(Icons.edit, size: ScreenAdaper.height(30)),
|
|||
|
// ),
|
|||
|
Obx(
|
|||
|
() => Text(
|
|||
|
'¥${controller.totalPrice.value}',
|
|||
|
textAlign: TextAlign.right,
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30),
|
|||
|
fontWeight: FontWeight.w600),
|
|||
|
),
|
|||
|
)
|
|||
|
],
|
|||
|
),
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
Widget buildTotalCostRow() {
|
|||
|
return Container(
|
|||
|
padding: EdgeInsets.symmetric(
|
|||
|
horizontal: ScreenAdaper.width(20),
|
|||
|
vertical: ScreenAdaper.height(10)),
|
|||
|
decoration: BoxDecoration(
|
|||
|
border: Border(
|
|||
|
top: BorderSide(width: 1, color: Colors.grey[200]!),
|
|||
|
),
|
|||
|
),
|
|||
|
child: Row(
|
|||
|
children: [
|
|||
|
Text(
|
|||
|
'成本',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30), fontWeight: FontWeight.w600),
|
|||
|
),
|
|||
|
const Spacer(),
|
|||
|
Obx(
|
|||
|
() => Text(
|
|||
|
'¥${controller.totalCost.value}',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30),
|
|||
|
fontWeight: FontWeight.w600),
|
|||
|
),
|
|||
|
)
|
|||
|
],
|
|||
|
),
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
Widget builderHeader() {
|
|||
|
return Container(
|
|||
|
decoration: BoxDecoration(
|
|||
|
color: headerBgcolor,
|
|||
|
border: Border(
|
|||
|
bottom:
|
|||
|
BorderSide(color: AppTheme.nearlyBlack.withOpacity(0.5)))),
|
|||
|
padding: EdgeInsets.only(
|
|||
|
left: ScreenAdaper.width(20),
|
|||
|
top: ScreenAdaper.height(10),
|
|||
|
bottom: ScreenAdaper.height(10)),
|
|||
|
child: Row(
|
|||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|||
|
children: [
|
|||
|
GestureDetector(
|
|||
|
onTap: () {
|
|||
|
controller.addGroup();
|
|||
|
},
|
|||
|
child: Icon(
|
|||
|
Icons.add_circle_outline_outlined,
|
|||
|
size: ScreenAdaper.height(40),
|
|||
|
color: Theme.of(Get.context!).colorScheme.onPrimary,
|
|||
|
),
|
|||
|
),
|
|||
|
SizedBox(
|
|||
|
width: ScreenAdaper.width(5),
|
|||
|
),
|
|||
|
Text(
|
|||
|
'名称',
|
|||
|
style: headerTitleStyle,
|
|||
|
),
|
|||
|
const Spacer(),
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(quantityWidth),
|
|||
|
// constraints: BoxConstraints(minWidth: quantityWidth),
|
|||
|
child: Text(
|
|||
|
'数量',
|
|||
|
style: headerTitleStyle,
|
|||
|
),
|
|||
|
),
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(unitPriceWidth),
|
|||
|
// constraints: BoxConstraints(minWidth: ScreenAdaper.width(unitPriceWidth)),
|
|||
|
child: Text(
|
|||
|
'单价',
|
|||
|
style: headerTitleStyle,
|
|||
|
),
|
|||
|
),
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(amountWidth),
|
|||
|
child: Text(
|
|||
|
'总价',
|
|||
|
style: headerTitleStyle,
|
|||
|
),
|
|||
|
),
|
|||
|
],
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
Widget buildBody(int groupIndex) {
|
|||
|
return SliverStickyHeader.builder(
|
|||
|
builder: (context, state) => buildGroupHeader(groupIndex, state),
|
|||
|
sliver: Obx(() => !controller.groups[groupIndex].isExpanded.value
|
|||
|
? SliverList(
|
|||
|
delegate: SliverChildBuilderDelegate(
|
|||
|
(context, i) => const SizedBox(),
|
|||
|
childCount: 0,
|
|||
|
))
|
|||
|
: SliverList(
|
|||
|
delegate: SliverChildBuilderDelegate(
|
|||
|
(context, int i) => buildRow(groupIndex, i),
|
|||
|
childCount: !controller.groups[groupIndex].isExpanded.value
|
|||
|
? 0
|
|||
|
: controller.groups[groupIndex].items.length,
|
|||
|
),
|
|||
|
)),
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
Widget buildGroupHeader(int groupIndex, SliverStickyHeaderState state) {
|
|||
|
final titleStyle = TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30),
|
|||
|
color: AppTheme.nearlyBlack,
|
|||
|
fontWeight: FontWeight.w600);
|
|||
|
return Container(
|
|||
|
decoration: BoxDecoration(
|
|||
|
color: const Color.fromARGB(255, 235, 235, 235)
|
|||
|
.withOpacity(1.0 - state.scrollPercentage),
|
|||
|
border: const Border(
|
|||
|
top: BorderSide(width: 1, color: AppTheme.dividerColor),
|
|||
|
bottom: BorderSide(width: 1, color: AppTheme.dividerColor))),
|
|||
|
height: ScreenAdaper.height(80),
|
|||
|
alignment: Alignment.centerLeft,
|
|||
|
child: InkWell(
|
|||
|
onTap: () {
|
|||
|
controller.groups[groupIndex].isExpanded.value =
|
|||
|
!controller.groups[groupIndex].isExpanded.value;
|
|||
|
},
|
|||
|
child: Row(
|
|||
|
children: [
|
|||
|
Obx(() => controller.groups[groupIndex].isExpanded.value
|
|||
|
? IconButton(
|
|||
|
padding: EdgeInsets.zero,
|
|||
|
onPressed: () {
|
|||
|
controller.groups[groupIndex].isExpanded.value =
|
|||
|
false;
|
|||
|
},
|
|||
|
icon: const Icon(
|
|||
|
Icons.expand_more,
|
|||
|
color: AppTheme.nearlyBlack,
|
|||
|
),
|
|||
|
)
|
|||
|
: IconButton(
|
|||
|
padding: EdgeInsets.zero,
|
|||
|
onPressed: () {
|
|||
|
controller.groups[groupIndex].isExpanded.value = true;
|
|||
|
},
|
|||
|
icon: const Icon(
|
|||
|
Icons.chevron_right,
|
|||
|
color: AppTheme.nearlyBlack,
|
|||
|
),
|
|||
|
)),
|
|||
|
Text(
|
|||
|
controller.groups[groupIndex].name,
|
|||
|
style: titleStyle,
|
|||
|
),
|
|||
|
const Spacer(),
|
|||
|
IconButton(
|
|||
|
onPressed: () {
|
|||
|
ModalUtil.alert(
|
|||
|
contentText: '确定要删除此组吗?',
|
|||
|
onConfirm: () {
|
|||
|
controller.removeGroup(groupIndex);
|
|||
|
});
|
|||
|
},
|
|||
|
icon: const Icon(
|
|||
|
Icons.delete_outline,
|
|||
|
color: AppTheme.nearlyBlack,
|
|||
|
)),
|
|||
|
IconButton(
|
|||
|
onPressed: () {
|
|||
|
controller.addItems(groupIndex);
|
|||
|
},
|
|||
|
icon: const Icon(
|
|||
|
Icons.add,
|
|||
|
color: AppTheme.nearlyBlack,
|
|||
|
)),
|
|||
|
],
|
|||
|
)));
|
|||
|
}
|
|||
|
|
|||
|
Widget buildRow(int groupIndex, int rowIndex) {
|
|||
|
final subTextStyle =
|
|||
|
TextStyle(color: AppTheme.grey, fontSize: ScreenAdaper.height(23));
|
|||
|
return Slidable(
|
|||
|
key: UniqueKey(),
|
|||
|
endActionPane: ActionPane(
|
|||
|
extentRatio: 0.2,
|
|||
|
motion: const DrawerMotion(),
|
|||
|
children: [
|
|||
|
SlidableAction(
|
|||
|
padding: EdgeInsets.zero,
|
|||
|
onPressed: (_) {
|
|||
|
controller.removeItem(groupIndex, rowIndex);
|
|||
|
},
|
|||
|
backgroundColor: AppTheme.dangerColor,
|
|||
|
foregroundColor: Colors.white,
|
|||
|
icon: Icons.delete,
|
|||
|
label: '删除',
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
child: Container(
|
|||
|
padding: EdgeInsets.only(
|
|||
|
left: ScreenAdaper.width(20),
|
|||
|
top: ScreenAdaper.height(15),
|
|||
|
bottom: ScreenAdaper.height(15),
|
|||
|
),
|
|||
|
constraints: BoxConstraints(minHeight: ScreenAdaper.height(100)),
|
|||
|
decoration: BoxDecoration(
|
|||
|
border: Border(
|
|||
|
bottom: BorderSide(width: 1, color: Colors.grey[200]!),
|
|||
|
),
|
|||
|
),
|
|||
|
child: Row(
|
|||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|||
|
children: [
|
|||
|
Expanded(
|
|||
|
child: Column(
|
|||
|
mainAxisAlignment: MainAxisAlignment.center,
|
|||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|||
|
children: [
|
|||
|
Row(
|
|||
|
children: [
|
|||
|
Expanded(
|
|||
|
child: Text(
|
|||
|
controller.groups[groupIndex].items[rowIndex].name,
|
|||
|
style: TextStyle(
|
|||
|
fontWeight: FontWeight.w600,
|
|||
|
fontSize: ScreenAdaper.height(30)),
|
|||
|
),
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
if (controller.groups[groupIndex].items[rowIndex]
|
|||
|
.componentSpecification !=
|
|||
|
null)
|
|||
|
Row(
|
|||
|
children: [
|
|||
|
// Text(
|
|||
|
// '规格、型号: ',
|
|||
|
// style: subTextStyle,
|
|||
|
// ),
|
|||
|
Text(
|
|||
|
controller.groups[groupIndex].items[rowIndex]
|
|||
|
.componentSpecification ??
|
|||
|
'',
|
|||
|
style: subTextStyle,
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
if (controller.groups[groupIndex].items[rowIndex].unit !=
|
|||
|
null)
|
|||
|
Row(
|
|||
|
children: [
|
|||
|
Text(
|
|||
|
'单位: ',
|
|||
|
style: subTextStyle,
|
|||
|
),
|
|||
|
Text(
|
|||
|
controller.groups[groupIndex].items[rowIndex].unit ??
|
|||
|
'',
|
|||
|
style: subTextStyle,
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
if (controller.groups[groupIndex].items[rowIndex].remark !=
|
|||
|
null)
|
|||
|
Row(
|
|||
|
children: [
|
|||
|
Text(
|
|||
|
'备注: ',
|
|||
|
style: subTextStyle,
|
|||
|
),
|
|||
|
Expanded(
|
|||
|
child: Text(
|
|||
|
controller.groups[groupIndex].items[rowIndex]
|
|||
|
.remark ??
|
|||
|
'',
|
|||
|
overflow: TextOverflow.ellipsis,
|
|||
|
style: subTextStyle,
|
|||
|
),
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
],
|
|||
|
),
|
|||
|
),
|
|||
|
const VerticalDivider(),
|
|||
|
buildEditCell<int>(
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(quantityWidth),
|
|||
|
child: Text(
|
|||
|
'${controller.groups[groupIndex].items[rowIndex].quantity}',
|
|||
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
|||
|
),
|
|||
|
),
|
|||
|
groupIndex: groupIndex,
|
|||
|
rowIndex: rowIndex,
|
|||
|
field: 'quantity',
|
|||
|
inputWidth: ScreenAdaper.width(quantityWidth),
|
|||
|
value: controller.groups[groupIndex].items[rowIndex].quantity,
|
|||
|
func: (value) {
|
|||
|
// 取消失去焦点,并且弹窗警告
|
|||
|
// bool isValid = (value ?? 0) > 0;
|
|||
|
// if (!isValid) {
|
|||
|
// SnackBarUtil().error('数量必须>0,若想删除产品0,请左滑');
|
|||
|
// }
|
|||
|
return true;
|
|||
|
}),
|
|||
|
buildEditCell<double>(
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(unitPriceWidth),
|
|||
|
child: Text(
|
|||
|
CommonUtil.toNumberWithoutZero(controller
|
|||
|
.groups[groupIndex].items[rowIndex].unitPrice),
|
|||
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
|||
|
),
|
|||
|
),
|
|||
|
groupIndex: groupIndex,
|
|||
|
rowIndex: rowIndex,
|
|||
|
field: 'unitPrice',
|
|||
|
inputWidth: ScreenAdaper.width(unitPriceWidth),
|
|||
|
value: controller.groups[groupIndex].items[rowIndex].unitPrice),
|
|||
|
buildEditCell<double>(
|
|||
|
Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(amountWidth),
|
|||
|
child: Text(
|
|||
|
CommonUtil.toNumberWithoutZero(
|
|||
|
controller.groups[groupIndex].items[rowIndex].amount),
|
|||
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
|||
|
),
|
|||
|
),
|
|||
|
groupIndex: groupIndex,
|
|||
|
rowIndex: rowIndex,
|
|||
|
field: 'amount',
|
|||
|
inputWidth: ScreenAdaper.width(amountWidth),
|
|||
|
value: controller.groups[groupIndex].items[rowIndex].amount),
|
|||
|
],
|
|||
|
),
|
|||
|
),
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
Widget buildEditCell<T>(
|
|||
|
Widget content, {
|
|||
|
required int groupIndex,
|
|||
|
required int rowIndex,
|
|||
|
required String field,
|
|||
|
required double inputWidth,
|
|||
|
required dynamic value,
|
|||
|
Function(dynamic)? func,
|
|||
|
}) {
|
|||
|
return Obx(() => controller.editingcell[0] == groupIndex &&
|
|||
|
controller.editingcell[1] == rowIndex &&
|
|||
|
controller.editingcell[2] == field
|
|||
|
? SizedBox(
|
|||
|
width: inputWidth,
|
|||
|
child: SkNumberInput<T>(
|
|||
|
hint: '',
|
|||
|
isDense: true,
|
|||
|
autoFocus: true,
|
|||
|
validator: func,
|
|||
|
onFieldSubmitted: (value) {
|
|||
|
final editingData =
|
|||
|
controller.groups[groupIndex].items[rowIndex].toJson();
|
|||
|
editingData[field] = value;
|
|||
|
controller.afterRowChanges(groupIndex, rowIndex,
|
|||
|
SaleQuotationItemModel.fromJson(editingData), field);
|
|||
|
},
|
|||
|
onTapOutside: (dynamic value) {
|
|||
|
value = value ?? 0;
|
|||
|
final editingData =
|
|||
|
controller.groups[groupIndex].items[rowIndex].toJson();
|
|||
|
editingData[field] = value as T;
|
|||
|
controller.afterRowChanges(groupIndex, rowIndex,
|
|||
|
SaleQuotationItemModel.fromJson(editingData), field);
|
|||
|
},
|
|||
|
contentPadding: EdgeInsets.symmetric(
|
|||
|
horizontal: ScreenAdaper.width(20),
|
|||
|
vertical: ScreenAdaper.height(10)),
|
|||
|
textController: TextEditingController(
|
|||
|
text: value == 0
|
|||
|
? ''
|
|||
|
: CommonUtil.toNumberWithoutZero(value))),
|
|||
|
)
|
|||
|
: InkWell(
|
|||
|
onTap: () {
|
|||
|
controller.editingcell.value = [groupIndex, rowIndex, field];
|
|||
|
},
|
|||
|
child: content,
|
|||
|
));
|
|||
|
}
|
|||
|
}
|