This commit is contained in:
louis 2024-04-02 16:22:21 +08:00
parent 1a3f57ce0e
commit 49ddf62751
9 changed files with 249 additions and 234 deletions

View File

@ -3,7 +3,7 @@ import 'package:get/get_rx/src/rx_types/rx_types.dart';
class SaleQuotationModel { class SaleQuotationModel {
final String name; final String name;
RxBool isExpanded = true.obs; RxBool isExpanded = true.obs;
List<SaleQuotationItemModel> items; RxList<SaleQuotationItemModel> items;
SaleQuotationModel({required this.name, required this.items}); SaleQuotationModel({required this.name, required this.items});
} }

View File

@ -199,173 +199,170 @@ class InventorySearch extends StatelessWidget {
controller: controller.refreshController, controller: controller.refreshController,
onLoading: controller.onLoading, onLoading: controller.onLoading,
onRefresh: controller.onRefresh, onRefresh: controller.onRefresh,
child: controller.refreshController.isLoading child: controller.inventories.isEmpty
? const SizedBox() ? const Center(
: controller.inventories.isEmpty child: Empty(text: '暂无库存'),
? const Center( )
child: Empty(text: '暂无库存'), : !ScreenAdaper.isLandspace()
) ? buildPortraitList()
: !ScreenAdaper.isLandspace() : Table(columnWidths: {
? buildPortraitList() 0: const MinColumnWidth(
: Table(columnWidths: { FixedColumnWidth(80), FixedColumnWidth(80)),
0: const MinColumnWidth( 1: MinColumnWidth(
FixedColumnWidth(80), FixedColumnWidth(80)), FixedColumnWidth(
1: MinColumnWidth( ScreenAdaper.screenShortDistance() / 5),
FixedColumnWidth( FixedColumnWidth(
ScreenAdaper.screenShortDistance() / 5), ScreenAdaper.screenShortDistance() / 5)),
FixedColumnWidth( 2: FlexColumnWidth(
ScreenAdaper.screenShortDistance() / 5)), ScreenAdaper.screenShortDistance() / 4),
2: FlexColumnWidth( 3: FlexColumnWidth(
ScreenAdaper.screenShortDistance() / 4), ScreenAdaper.screenShortDistance() / 4),
3: FlexColumnWidth( 4: MinColumnWidth(
ScreenAdaper.screenShortDistance() / 4), FixedColumnWidth(
4: MinColumnWidth( ScreenAdaper.screenShortDistance() / 5),
FixedColumnWidth( FixedColumnWidth(
ScreenAdaper.screenShortDistance() / 5), ScreenAdaper.screenShortDistance() / 5)),
FixedColumnWidth( 5: MinColumnWidth(
ScreenAdaper.screenShortDistance() / 5)), FixedColumnWidth(
5: MinColumnWidth( ScreenAdaper.screenShortDistance() / 6),
FixedColumnWidth( FixedColumnWidth(
ScreenAdaper.screenShortDistance() / 6), ScreenAdaper.screenShortDistance() / 6)),
FixedColumnWidth( }, children: [
ScreenAdaper.screenShortDistance() / 6)), // table header
}, children: [ TableRow(
// table header decoration: const BoxDecoration(
TableRow( border: Border(
decoration: const BoxDecoration( bottom: BorderSide(
border: Border( color: AppTheme.dividerColor))),
bottom: BorderSide( children: [
color: AppTheme.dividerColor))), TableCell(
children: [ verticalAlignment:
TableCell( TableCellVerticalAlignment.middle,
verticalAlignment: child: Container(
TableCellVerticalAlignment.middle, alignment: Alignment.centerLeft,
child: Container( height: ScreenAdaper.height(60),
alignment: Alignment.centerLeft,
height: ScreenAdaper.height(60),
child: Text(
'库存编号',
style: listTitleTextStyle,
),
)),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'所属项目',
style: listTitleTextStyle,
)),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'产品名称',
style: listTitleTextStyle,
)),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text( child: Text(
'规格', '库存编号',
style: listTitleTextStyle, style: listTitleTextStyle,
), ),
), )),
TableCell( TableCell(
verticalAlignment: verticalAlignment:
TableCellVerticalAlignment.middle, TableCellVerticalAlignment.middle,
child: Text( child: Text(
'单价', '所属项目',
style: listTitleTextStyle, style: listTitleTextStyle,
)),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'产品名称',
style: listTitleTextStyle,
)),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'规格',
style: listTitleTextStyle,
),
),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'单价',
style: listTitleTextStyle,
),
),
TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: Text(
'数量',
textAlign: TextAlign.right,
style: listTitleTextStyle,
),
),
]),
...controller.inventories.map((itemData) {
return TableRow(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: AppTheme.dividerColor))),
children: [
buildTableCell(
Text(
itemData.inventoryNumber!,
style: textStyle,
), ),
), itemData: itemData),
TableCell(
verticalAlignment: //
TableCellVerticalAlignment.middle, buildTableCell(
child: Text( Column(
'数量', mainAxisAlignment:
textAlign: TextAlign.right, MainAxisAlignment.center,
style: listTitleTextStyle, crossAxisAlignment:
), CrossAxisAlignment.start,
), children: [
]),
...controller.inventories.map((itemData) {
return TableRow(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: AppTheme.dividerColor))),
children: [
buildTableCell(
Text( Text(
itemData.inventoryNumber!, '${itemData.project?.name}',
style: textStyle, style: textStyle,
), ),
itemData: itemData), ],
),
// itemData: itemData),
buildTableCell( //
Column( buildTableCell(
mainAxisAlignment: Column(
MainAxisAlignment.center, mainAxisAlignment:
crossAxisAlignment: MainAxisAlignment.center,
CrossAxisAlignment.start, crossAxisAlignment:
children: [ CrossAxisAlignment.start,
Text( children: [
'${itemData.project?.name}',
style: textStyle,
),
],
),
itemData: itemData),
//
buildTableCell(
Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'${itemData.product?.name}',
style: textStyle,
),
Text(
'${itemData.product?.company?.name}',
style: TextStyle(
fontSize:
ScreenAdaper.height(15),
color: AppTheme.grey),
)
],
),
itemData: itemData),
//
buildTableCell(
Text( Text(
itemData.product '${itemData.product?.name}',
?.productSpecification ??
'',
style: textStyle),
itemData: itemData),
//
buildTableCell(
Text(
'${double.parse('${itemData.unitPrice}')}',
style: textStyle, style: textStyle,
), ),
itemData: itemData),
//
buildTableCell(
Text( Text(
'${itemData.quantity}${itemData.product?.unit?.label ?? ''}', '${itemData.product?.company?.name}',
textAlign: TextAlign.right, style: TextStyle(
style: textStyle), fontSize: ScreenAdaper.height(15),
itemData: itemData, color: AppTheme.grey),
alignment: Alignment.centerRight), )
]); ],
}) ),
])))); itemData: itemData),
//
buildTableCell(
Text(
itemData.product
?.productSpecification ??
'',
style: textStyle),
itemData: itemData),
//
buildTableCell(
Text(
'${double.parse('${itemData.unitPrice}')}',
style: textStyle,
),
itemData: itemData),
//
buildTableCell(
Text(
'${itemData.quantity}${itemData.product?.unit?.label ?? ''}',
textAlign: TextAlign.right,
style: textStyle),
itemData: itemData,
alignment: Alignment.centerRight),
]);
})
]))));
} }
Widget buildTableCell(Widget child, Widget buildTableCell(Widget child,

View File

@ -175,14 +175,14 @@ class GroupSearchController extends GetxController {
// isRefresh == true ? list.assignAll(newList) : list.addAll(newList); // isRefresh == true ? list.assignAll(newList) : list.addAll(newList);
List<SaleQuotationModel> newList = [ List<SaleQuotationModel> newList = [
SaleQuotationModel(name: '中间过渡架电控部分', items: []), SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])),
SaleQuotationModel(name: '端头架电控部分', items: []), SaleQuotationModel(name: '端头架电控部分', items: RxList([])),
SaleQuotationModel(name: '主阀部分', items: []), SaleQuotationModel(name: '主阀部分', items: RxList([])),
SaleQuotationModel(name: '自动反冲洗过滤器部分', items: []), SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])),
SaleQuotationModel(name: '位移测量部分', items: []), SaleQuotationModel(name: '位移测量部分', items: RxList([])),
SaleQuotationModel(name: '压力检测部分', items: []), SaleQuotationModel(name: '压力检测部分', items: RxList([])),
SaleQuotationModel(name: '煤机定位部分', items: []), SaleQuotationModel(name: '煤机定位部分', items: RxList([])),
SaleQuotationModel(name: '姿态检测部分', items: []), SaleQuotationModel(name: '姿态检测部分', items: RxList([])),
]; ];
list.assignAll(newList); list.assignAll(newList);
return newList; return newList;

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:sk_base_mobile/models/base_search_more.dart'; import 'package:sk_base_mobile/models/base_search_more.dart';
import 'package:sk_base_mobile/models/sale_quotation.model.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/screens/sale_quotation/components/sale_quotation_group_search.dart';
import 'package:sk_base_mobile/widgets/core/sk_single_search_more.dart'; import 'package:sk_base_mobile/widgets/core/sk_single_search_more.dart';
import 'package:sk_base_mobile/util/modal.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/util/screen_adaper_util.dart';
import 'package:pinyin/pinyin.dart';
class SaleQuotationController extends GetxController { class SaleQuotationController extends GetxController {
static SaleQuotationController get to => Get.find(); static SaleQuotationController get to => Get.find();
@ -37,15 +37,6 @@ class SaleQuotationController extends GetxController {
@override @override
void onReady() { void onReady() {
// groups.assignAll();
// SaleQuotationModel(name: '中间过渡架电控部分', items: products),
// SaleQuotationModel(name: '端头架电控部分', items: products),
// SaleQuotationModel(name: '主阀部分', items: products),
// SaleQuotationModel(name: '自动反冲洗过滤器部分', items: products),
// SaleQuotationModel(name: '位移测量部分', items: products),
// SaleQuotationModel(name: '压力检测部分', items: products),
// SaleQuotationModel(name: '煤机定位部分', items: products),
// SaleQuotationModel(name: '姿态检测部分', items: products),
super.onReady(); super.onReady();
} }
@ -86,7 +77,7 @@ class SaleQuotationController extends GetxController {
groups.removeAt(index); groups.removeAt(index);
} }
Future<void> addItems() async { Future<void> addItems(int groupIndex) async {
final controller = Get.put(ItemSearchMoreController()); final controller = Get.put(ItemSearchMoreController());
// //
ModalUtil.showGeneralDialog( ModalUtil.showGeneralDialog(
@ -99,13 +90,7 @@ class SaleQuotationController extends GetxController {
return InkWell( return InkWell(
onTap: () { onTap: () {
Get.back(); Get.back();
// if (beforeSelectedCheck != null) groups[groupIndex].items.add(controller.list[index]);
// {
// if (beforeSelectedCheck!(controller.list[index]))
// {onSelected!(controller.list[index])}
// }
// else
// {onSelected!(controller.list[index])}
}, },
child: Container( child: Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
@ -136,16 +121,19 @@ class GroupSearchMoreController extends GetxController
@override @override
Future<List<SaleQuotationModel>> getData({bool isRefresh = false}) async { Future<List<SaleQuotationModel>> getData({bool isRefresh = false}) async {
List<SaleQuotationModel> newList = [ List<SaleQuotationModel> newList = [
SaleQuotationModel(name: '中间过渡架电控部分', items: []), SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])),
SaleQuotationModel(name: '端头架电控部分', items: []), SaleQuotationModel(name: '端头架电控部分', items: RxList([])),
SaleQuotationModel(name: '主阀部分', items: []), SaleQuotationModel(name: '主阀部分', items: RxList([])),
SaleQuotationModel(name: '自动反冲洗过滤器部分', items: []), SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])),
SaleQuotationModel(name: '位移测量部分', items: []), SaleQuotationModel(name: '位移测量部分', items: RxList([])),
SaleQuotationModel(name: '压力检测部分', items: []), SaleQuotationModel(name: '压力检测部分', items: RxList([])),
SaleQuotationModel(name: '煤机定位部分', items: []), SaleQuotationModel(name: '煤机定位部分', items: RxList([])),
SaleQuotationModel(name: '姿态检测部分', items: []), SaleQuotationModel(name: '姿态检测部分', items: RxList([])),
]; ];
list.assignAll(newList); list.assignAll(newList
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
.contains(searchKey.value))
.toList());
return newList; return newList;
} }
} }
@ -176,7 +164,10 @@ class ItemSearchMoreController extends GetxController
SaleQuotationItemModel(name: '倾角传感器'), SaleQuotationItemModel(name: '倾角传感器'),
SaleQuotationItemModel(name: '各类安装附件'), SaleQuotationItemModel(name: '各类安装附件'),
]; ];
list.assignAll(newList); list.assignAll(newList
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
.contains(searchKey.value))
.toList());
return newList; return newList;
} }
} }

View File

@ -128,7 +128,7 @@ class SaleQuotationPage extends StatelessWidget {
)); ));
} }
Widget buildBody(SaleQuotationModel group, int index) { Widget buildBody(SaleQuotationModel group, int groupIndex) {
final titleStyle = TextStyle( final titleStyle = TextStyle(
fontSize: ScreenAdaper.height(30), fontSize: ScreenAdaper.height(30),
color: AppTheme.nearlyBlack, color: AppTheme.nearlyBlack,
@ -143,16 +143,17 @@ class SaleQuotationPage extends StatelessWidget {
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
controller.groups[index].isExpanded.value = controller.groups[groupIndex].isExpanded.value =
!controller.groups[index].isExpanded.value; !controller.groups[groupIndex].isExpanded.value;
}, },
child: Row( child: Row(
children: [ children: [
Obx(() => controller.groups[index].isExpanded.value Obx(() => controller.groups[groupIndex].isExpanded.value
? IconButton( ? IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
controller.groups[index].isExpanded.value = false; controller.groups[groupIndex].isExpanded.value =
false;
}, },
icon: const Icon( icon: const Icon(
Icons.expand_more, Icons.expand_more,
@ -162,7 +163,8 @@ class SaleQuotationPage extends StatelessWidget {
: IconButton( : IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
controller.groups[index].isExpanded.value = true; controller.groups[groupIndex].isExpanded.value =
true;
}, },
icon: const Icon( icon: const Icon(
Icons.chevron_right, Icons.chevron_right,
@ -179,7 +181,7 @@ class SaleQuotationPage extends StatelessWidget {
ModalUtil.confirm( ModalUtil.confirm(
title: '确定要删除此组吗?', title: '确定要删除此组吗?',
onConfirm: () { onConfirm: () {
controller.removeGroup(index); controller.removeGroup(groupIndex);
}); });
}, },
icon: const Icon( icon: const Icon(
@ -188,7 +190,7 @@ class SaleQuotationPage extends StatelessWidget {
)), )),
IconButton( IconButton(
onPressed: () { onPressed: () {
controller.addItems(); controller.addItems(groupIndex);
}, },
icon: const Icon( icon: const Icon(
Icons.add_circle_outline, Icons.add_circle_outline,
@ -196,7 +198,7 @@ class SaleQuotationPage extends StatelessWidget {
)), )),
], ],
))), ))),
sliver: Obx(() => !controller.groups[index].isExpanded.value sliver: Obx(() => !controller.groups[groupIndex].isExpanded.value
? SliverList( ? SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, i) => SizedBox(), (context, i) => SizedBox(),
@ -212,11 +214,13 @@ class SaleQuotationPage extends StatelessWidget {
children: [ children: [
SlidableAction( SlidableAction(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: (_) {}, onPressed: (_) {
controller.groups[groupIndex].items.removeAt(i);
},
backgroundColor: AppTheme.dangerColor, backgroundColor: AppTheme.dangerColor,
foregroundColor: Colors.white, foregroundColor: Colors.white,
icon: Icons.delete, icon: Icons.delete,
label: 'Delete', label: '删除',
), ),
], ],
), ),
@ -304,51 +308,53 @@ class SaleQuotationPage extends StatelessWidget {
alignment: Alignment.center, alignment: Alignment.center,
width: quantityWidth, width: quantityWidth,
child: Text( child: Text(
'${controller.groups[index].items[i].quantity}', '${controller.groups[groupIndex].items[i].quantity}',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(25)), fontSize: ScreenAdaper.height(25)),
), ),
), ),
groupIndex: index, groupIndex: groupIndex,
rowIndex: i, rowIndex: i,
field: 'quantity', field: 'quantity',
inputWidth: quantityWidth, inputWidth: quantityWidth,
value: controller.groups[index].items[i].quantity), value: controller
.groups[groupIndex].items[i].quantity),
buildEditCell( buildEditCell(
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,
width: unitPriceWidth, width: unitPriceWidth,
child: Text( child: Text(
'${controller.groups[index].items[i].cost}', '${controller.groups[groupIndex].items[i].cost}',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(25)), fontSize: ScreenAdaper.height(25)),
), ),
), ),
groupIndex: index, groupIndex: groupIndex,
rowIndex: i, rowIndex: i,
field: 'cost', field: 'cost',
inputWidth: unitPriceWidth, inputWidth: unitPriceWidth,
value: controller.groups[index].items[i].cost), value: controller.groups[groupIndex].items[i].cost),
buildEditCell( buildEditCell(
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,
width: amountWidth, width: amountWidth,
child: Text( child: Text(
'${controller.groups[index].items[i].amount}', '${controller.groups[groupIndex].items[i].amount}',
style: TextStyle( style: TextStyle(
fontSize: ScreenAdaper.height(25)), fontSize: ScreenAdaper.height(25)),
), ),
), ),
groupIndex: index, groupIndex: groupIndex,
rowIndex: i, rowIndex: i,
field: 'amount', field: 'amount',
inputWidth: amountWidth, inputWidth: amountWidth,
value: controller.groups[index].items[i].amount), value:
controller.groups[groupIndex].items[i].amount),
], ],
), ),
), ),
), ),
childCount: !controller.groups[index].isExpanded.value childCount: !controller.groups[groupIndex].isExpanded.value
? 0 ? 0
: group.items.length, : group.items.length,
), ),

View File

@ -48,7 +48,7 @@ class _SkNumberInputState extends State<SkNumberInput> {
return TextFormField( return TextFormField(
focusNode: focusNode, focusNode: focusNode,
onTap: () { onTap: () {
if (widget.onTap == null) { if (widget.onTap != null) {
widget.onTap!(focusNode); widget.onTap!(focusNode);
} }
}, },

View File

@ -37,25 +37,9 @@ class SkSingleSearchMore<T> extends StatelessWidget {
vertical: ScreenAdaper.height(20)), vertical: ScreenAdaper.height(20)),
child: Column( child: Column(
children: [ children: [
Container( buildDialogHeader(),
height: ScreenAdaper.height(60), SizedBox(
padding: EdgeInsets.only(bottom: ScreenAdaper.height(15)), height: ScreenAdaper.height(defaultPadding) / 2,
child: Stack(
children: [
Center(
child: Text(
'请选择',
style: TextStyle(
fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w600),
),
),
Positioned(
right: 0,
child:
GestureDetector(onTap: () {}, child: Icon(Icons.close)))
],
),
), ),
buildSearchBar(), buildSearchBar(),
SizedBox( SizedBox(
@ -67,6 +51,34 @@ class SkSingleSearchMore<T> extends StatelessWidget {
); );
} }
Widget buildDialogHeader() {
return Container(
height: ScreenAdaper.height(60),
child: Stack(
children: [
Center(
child: Text(
'请选择',
style: TextStyle(
fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w600),
),
),
Positioned(
right: 0,
child: GestureDetector(
onTap: () {
Get.back();
},
child: Icon(
Icons.close,
size: ScreenAdaper.height(40),
)))
],
),
);
}
Widget buildSearchBar() { Widget buildSearchBar() {
final doSearch = debouncer((String value) { final doSearch = debouncer((String value) {
controller.searchKey.value = value; controller.searchKey.value = value;

View File

@ -736,6 +736,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.14.0" version: "0.14.0"
pinyin:
dependency: "direct main"
description:
name: pinyin
sha256: "509a51abec754d8b69cc94074b2bdb9f4a407bc4daf5723ec6d995b7682a048a"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:

View File

@ -64,6 +64,7 @@ dependencies:
flutter_svg: ^2.0.10+1 flutter_svg: ^2.0.10+1
flutter_sticky_header: ^0.6.5 flutter_sticky_header: ^0.6.5
flutter_slidable: ^3.1.0 flutter_slidable: ^3.1.0
pinyin: ^3.2.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter