feat: product searcher
This commit is contained in:
parent
9e39aa8c41
commit
7986fde5d3
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:dio/dio.dart';
|
||||
import 'package:sk_base_mobile/constants/global_url.dart';
|
||||
import 'package:sk_base_mobile/models/base_response.dart';
|
||||
import 'package:sk_base_mobile/models/dict_type.model.dart';
|
||||
import 'package:sk_base_mobile/services/dio.service.dart';
|
||||
import '../constants/constants.dart';
|
||||
|
||||
|
@ -39,6 +40,11 @@ Future<Response<PaginationData>> getInventoryInout(Map params) {
|
|||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||
}
|
||||
|
||||
// 一次性获取所有的字典类型(不分页)
|
||||
Future<Response> getDictTypeAll(Map params) {
|
||||
return DioService.dio.post(Urls.getDictType, data: params);
|
||||
}
|
||||
|
||||
Future<Response> logout() {
|
||||
return DioService.dio.post(
|
||||
Urls.logout,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class DictTypeEnum {
|
||||
static const String InventoryRoom = "inventory_room";
|
||||
static const String InventoryLine = 'inventory_line';
|
||||
static const String InventoryLineLevel = 'inventory_line_level';
|
||||
}
|
|
@ -10,4 +10,5 @@ class Urls {
|
|||
static String getProducts = 'product';
|
||||
static String getInventoryInout = 'materials-in-out';
|
||||
static String updateAvatar = 'user/updateAvatar';
|
||||
static String getDictType = 'system/dict-type/all';
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/store/dict.store.dart';
|
||||
import 'package:sk_base_mobile/util/loading_util.dart';
|
||||
import 'package:timeago/timeago.dart' as timeago;
|
||||
import 'package:sk_base_mobile/constants/cache_key.dart';
|
||||
|
@ -42,6 +43,9 @@ class Global {
|
|||
/// 依赖注入用户信息
|
||||
await Get.putAsync<AuthStore>(() => AuthStore().init());
|
||||
|
||||
/// 依赖注入字典信息
|
||||
await Get.putAsync<DictService>(() => DictService().init());
|
||||
|
||||
if (StorageService.to.getString(CacheKeys.token, isWithUser: false) !=
|
||||
null) {
|
||||
/// 这里做一些缓存初始化后的操作
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:sk_base_mobile/config.dart';
|
|||
import 'package:sk_base_mobile/services/storage.service.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/widgets/refresh-footer.dart';
|
||||
import 'package:sk_base_mobile/widgets/refresh_footer.dart';
|
||||
import 'package:sk_base_mobile/widgets/refresh_header.dart';
|
||||
|
||||
import 'constants/constants.dart';
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
class DictItemModel {
|
||||
DictItemModel({
|
||||
required this.id,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.creator,
|
||||
required this.updater,
|
||||
this.id,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.creator,
|
||||
this.updater,
|
||||
required this.label,
|
||||
required this.value,
|
||||
required this.orderNo,
|
||||
required this.status,
|
||||
required this.remark,
|
||||
this.value,
|
||||
this.orderNo,
|
||||
this.status,
|
||||
this.remark,
|
||||
});
|
||||
|
||||
final int? id;
|
||||
|
@ -17,7 +17,7 @@ class DictItemModel {
|
|||
final DateTime? updatedAt;
|
||||
final String? creator;
|
||||
final String? updater;
|
||||
final String? label;
|
||||
final String label;
|
||||
final String? value;
|
||||
final int? orderNo;
|
||||
final int? status;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import 'dict_item.model.dart';
|
||||
|
||||
class DictTypeModel {
|
||||
DictTypeModel({
|
||||
required this.id,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.creator,
|
||||
required this.updater,
|
||||
required this.name,
|
||||
required this.code,
|
||||
required this.status,
|
||||
required this.remark,
|
||||
required this.dictItems,
|
||||
});
|
||||
|
||||
final int? id;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final String? creator;
|
||||
final String? updater;
|
||||
final String? name;
|
||||
final String? code;
|
||||
final int? status;
|
||||
final String? remark;
|
||||
final List<DictItemModel> dictItems;
|
||||
|
||||
factory DictTypeModel.fromJson(Map<String, dynamic> json) {
|
||||
return DictTypeModel(
|
||||
id: json["id"],
|
||||
createdAt: DateTime.tryParse(json["createdAt"] ?? ""),
|
||||
updatedAt: DateTime.tryParse(json["updatedAt"] ?? ""),
|
||||
creator: json["creator"],
|
||||
updater: json["updater"],
|
||||
name: json["name"],
|
||||
code: json["code"],
|
||||
status: json["status"],
|
||||
remark: json["remark"],
|
||||
dictItems: json["dictItems"] == null
|
||||
? []
|
||||
: List<DictItemModel>.from(
|
||||
json["dictItems"]!.map((x) => DictItemModel.fromJson(x))),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"createdAt": createdAt?.toIso8601String(),
|
||||
"updatedAt": updatedAt?.toIso8601String(),
|
||||
"creator": creator,
|
||||
"updater": updater,
|
||||
"name": name,
|
||||
"code": code,
|
||||
"status": status,
|
||||
"remark": remark,
|
||||
"dictItems": dictItems.map((x) => x.toJson()).toList(),
|
||||
};
|
||||
}
|
|
@ -4,8 +4,8 @@ import 'package:sk_base_mobile/models/file.model.dart';
|
|||
import 'company.model.dart';
|
||||
|
||||
class ProductModel {
|
||||
ProductModel({
|
||||
required this.id,
|
||||
ProductModel(
|
||||
{required this.id,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.name,
|
||||
|
@ -17,9 +17,12 @@ class ProductModel {
|
|||
required this.files,
|
||||
required this.company,
|
||||
required this.unit,
|
||||
});
|
||||
this.productNumber,
|
||||
this.productSpecification});
|
||||
|
||||
final int? id;
|
||||
final String? productNumber;
|
||||
final String? productSpecification;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final String? name;
|
||||
|
@ -41,6 +44,8 @@ class ProductModel {
|
|||
remark: json["remark"],
|
||||
isDelete: json["isDelete"],
|
||||
companyId: json["companyId"],
|
||||
productNumber: json['productNumber'],
|
||||
productSpecification: json['productSpecification'],
|
||||
unitId: json["unitId"],
|
||||
namePinyin: json["namePinyin"],
|
||||
files: json["files"] == null
|
||||
|
@ -63,6 +68,8 @@ class ProductModel {
|
|||
"isDelete": isDelete,
|
||||
"companyId": companyId,
|
||||
"unitId": unitId,
|
||||
'productNumber': productNumber,
|
||||
'productSpecification': productSpecification,
|
||||
"namePinyin": namePinyin,
|
||||
"files": files.map((x) => x?.toJson()).toList(),
|
||||
"company": company?.toJson(),
|
||||
|
|
|
@ -3,14 +3,17 @@ import 'package:get/get.dart';
|
|||
import 'package:sk_base_mobile/screens/inventory_inout/components/task_list.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout_controller.dart';
|
||||
|
||||
class TaskPageView extends StatelessWidget {
|
||||
TaskPageView({super.key});
|
||||
class InventoryInoutView extends StatelessWidget {
|
||||
InventoryInoutView({super.key});
|
||||
final controller = Get.put(InventoryInoutController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PageView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
reverse: true,
|
||||
onPageChanged: (index) {
|
||||
controller.changePage(index);
|
||||
},
|
||||
controller: controller.pageController,
|
||||
children: List.generate(
|
||||
controller.daysNum,
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/components/change_button_roe.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/components/task_page_View.dart';
|
||||
import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_page_View.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class TaskPageBody extends StatelessWidget {
|
||||
|
@ -38,7 +38,7 @@ class TaskPageBody extends StatelessWidget {
|
|||
Colors.white.withOpacity(.0),
|
||||
Colors.white.withOpacity(.0),
|
||||
])),
|
||||
child: TaskPageView(),
|
||||
child: InventoryInoutView(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:sk_base_mobile/app_theme.dart';
|
|||
import 'package:sk_base_mobile/db_helper/dbHelper.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart';
|
||||
import 'package:sk_base_mobile/util/date.util.dart';
|
||||
import 'package:sk_base_mobile/util/logger_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/apis/api.dart' as Api;
|
||||
|
@ -36,6 +37,12 @@ class InventoryInoutController extends GetxController {
|
|||
// getInoutHistory();
|
||||
}
|
||||
|
||||
Future<void> changePage(int index) async {
|
||||
LoggerUtil()
|
||||
.info(DateUtil.format(DateTime.now().add(Duration(days: -index))));
|
||||
|
||||
}
|
||||
|
||||
/// 打开出库还是入库选择框
|
||||
Future<void> showInOrOutPickerDialog() async {
|
||||
showDialog(
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
|
||||
class ProductSearch extends StatelessWidget {
|
||||
ProductSearch({super.key});
|
||||
final controller = Get.put(ProductSearchController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: ScreenAdaper.width(20),
|
||||
vertical: ScreenAdaper.height(20)),
|
||||
child: Column(
|
||||
children: [buildSearchBar(), Expanded(child: buildProductList())],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSearchBar() {
|
||||
final doSearch = debouncer((_) {
|
||||
controller.onRefresh();
|
||||
}, delayTime: 500);
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: controller.searchBarController,
|
||||
onChanged: (value) => doSearch(value),
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: ScreenAdaper.height(10),
|
||||
horizontal: ScreenAdaper.width(10)),
|
||||
hintText: '名称,编号',
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
))),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildProductList() {
|
||||
return Obx(
|
||||
() => SmartRefresher(
|
||||
enablePullDown: true,
|
||||
enablePullUp: true,
|
||||
controller: controller.refreshController,
|
||||
onLoading: controller.onLoading,
|
||||
onRefresh: controller.onRefresh,
|
||||
child: ListView.separated(
|
||||
itemCount: controller.products.length,
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
height: 1,
|
||||
color: AppTheme.dividerColor,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final itemData = controller.products[index];
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: ScreenAdaper.height(10)),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
itemData.productNumber!,
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
),
|
||||
SizedBox(
|
||||
width: ScreenAdaper.width(10),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${itemData.name}',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
),
|
||||
Text(
|
||||
'${itemData.company?.name}',
|
||||
style: TextStyle(
|
||||
fontSize: ScreenAdaper.sp(15),
|
||||
color: AppTheme.grey),
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ProductSearchController extends GetxController {
|
||||
RxList<ProductModel> products = RxList([]);
|
||||
TextEditingController searchBarController = TextEditingController(text: '');
|
||||
RefreshController refreshController = RefreshController(initialRefresh: true);
|
||||
int page = 1;
|
||||
int limit = 15;
|
||||
int total = 0;
|
||||
Future<List<ProductModel>> getData({bool isRefresh = false}) async {
|
||||
if (isRefresh == true) {
|
||||
page = 1;
|
||||
} else {
|
||||
page++;
|
||||
}
|
||||
final res = await Api.getProducts(
|
||||
{'page': page, 'pageSize': 30, 'keyword': searchBarController.text});
|
||||
List<ProductModel> newList =
|
||||
res.data!.items.map((e) => ProductModel.fromJson(e)).toList();
|
||||
isRefresh == true ? products.assignAll(newList) : products.addAll(newList);
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
await getData(isRefresh: true).then((_) {
|
||||
refreshController.refreshCompleted(resetFooterState: true);
|
||||
}).catchError((_) {
|
||||
refreshController.refreshFailed();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> onLoading() async {
|
||||
await getData().then((_) {
|
||||
if (_.isEmpty) {
|
||||
refreshController.loadNoData();
|
||||
} else {
|
||||
refreshController.loadComplete();
|
||||
}
|
||||
}).catchError((_) {
|
||||
refreshController.loadFailed();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,17 +1,24 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/constants/constants.dart';
|
||||
import 'package:sk_base_mobile/constants/dict_enum.dart';
|
||||
import 'package:sk_base_mobile/models/index.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/date_time.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/product_search.dart';
|
||||
import 'package:sk_base_mobile/store/dict.store.dart';
|
||||
import 'package:sk_base_mobile/util/date.util.dart';
|
||||
import 'package:sk_base_mobile/util/modal.util.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zt_bottomsheet_picker.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zt_number_input.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zt_search_select.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zk_date_picker.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zt_text_input.dart';
|
||||
import 'package:sk_base_mobile/widgets/empty.dart';
|
||||
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
||||
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout_controller.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
@ -21,7 +28,7 @@ class NewInventoryInout extends StatelessWidget {
|
|||
NewInventoryInout({super.key, this.inOrOut = 'in'});
|
||||
|
||||
final controller = Get.put(NewInventoryInoutController());
|
||||
|
||||
final dictService = Get.find<DictService>();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
|
@ -88,12 +95,13 @@ class NewInventoryInout extends StatelessWidget {
|
|||
SizedBox(
|
||||
height: ScreenAdaper.height(formVerticalGap),
|
||||
),
|
||||
Row(
|
||||
children: [Expanded(child: buildRemark())],
|
||||
),
|
||||
buildPositionBottomPicker(),
|
||||
SizedBox(
|
||||
height: ScreenAdaper.height(formVerticalGap),
|
||||
),
|
||||
Row(
|
||||
children: [Expanded(child: buildRemark())],
|
||||
),
|
||||
buildImageUploadQueue()
|
||||
];
|
||||
|
||||
|
@ -116,16 +124,16 @@ class NewInventoryInout extends StatelessWidget {
|
|||
|
||||
/// 项目
|
||||
Widget buildProjectPicker() {
|
||||
return ZtSearchSelect(
|
||||
return ZtSearchSelect<ProjectModel>(
|
||||
isRequired: true,
|
||||
textController: controller.projectTextController,
|
||||
labelText: '项目',
|
||||
itemBuilder: (itemData) => Container(
|
||||
itemBuilder: (_, itemData) => Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: ScreenAdaper.height(15),
|
||||
horizontal: ScreenAdaper.width(20)),
|
||||
child: Text(
|
||||
'${itemData?.name}',
|
||||
'${itemData.name}',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
)),
|
||||
suggestionsCallback: (String keyword) {
|
||||
|
@ -142,24 +150,168 @@ class NewInventoryInout extends StatelessWidget {
|
|||
|
||||
/// 产品
|
||||
Widget buildProductPicker() {
|
||||
return ZtSearchSelect(
|
||||
isRequired: true,
|
||||
textController: controller.productTextController,
|
||||
return TextFormField(
|
||||
controller: controller.positionTextController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '产品',
|
||||
itemBuilder: (itemData) => ListTile(
|
||||
title: Text('${itemData?.name}'),
|
||||
subtitle: Text('${itemData?.company?.name ?? ''}'),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always),
|
||||
readOnly: true,
|
||||
onTap: () {
|
||||
Get.generalDialog(
|
||||
barrierLabel: "productPicker",
|
||||
barrierDismissible: true,
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
pageBuilder: (_, __, ___) {
|
||||
return Center(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
child: Material(
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(
|
||||
30,
|
||||
),
|
||||
suggestionsCallback: (String keyword) {
|
||||
return controller.getProducts(keyword: keyword);
|
||||
topRight: Radius.circular(30)),
|
||||
child: Container(
|
||||
height: Get.height - ScreenAdaper.height(200),
|
||||
width: Get.width - ScreenAdaper.width(200),
|
||||
child: ProductSearch(),
|
||||
),
|
||||
))));
|
||||
},
|
||||
onClear: () {
|
||||
controller.payload.remove('productId');
|
||||
transitionBuilder: (_, anim, __, child) {
|
||||
Tween<Offset> tween;
|
||||
tween = Tween(begin: const Offset(0, 1), end: Offset.zero);
|
||||
return SlideTransition(
|
||||
position: tween.animate(
|
||||
CurvedAnimation(parent: anim, curve: Curves.easeInOut),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
onSelected: (ProductModel product) {
|
||||
controller.productTextController.text = product.name ?? '';
|
||||
controller.payload['productId'] = product.id;
|
||||
);
|
||||
});
|
||||
// return DropdownSearch<ProductModel>(
|
||||
// asyncItems: (String filter) async {
|
||||
// return controller.getProducts(keyword: filter);
|
||||
// },
|
||||
|
||||
// dropdownDecoratorProps: const DropDownDecoratorProps(
|
||||
// dropdownSearchDecoration: InputDecoration(
|
||||
// labelText: "产品",
|
||||
// hintText: "请选择",
|
||||
// floatingLabelBehavior: FloatingLabelBehavior.always),
|
||||
// ),
|
||||
// popupProps: PopupProps.menu(
|
||||
// isFilterOnline: true,
|
||||
// searchFieldProps: TextFieldProps(
|
||||
// cursorColor: AppTheme.primaryColorLight,
|
||||
// decoration: InputDecoration(
|
||||
// contentPadding: EdgeInsets.symmetric(
|
||||
// vertical: ScreenAdaper.height(15),
|
||||
// horizontal: ScreenAdaper.width(10)))),
|
||||
// searchDelay: const Duration(milliseconds: 500),
|
||||
// emptyBuilder: (context, searchEntry) => const Empty(
|
||||
// text: '未找到',
|
||||
// ),
|
||||
// itemBuilder: (_, itemData, _1) => Container(
|
||||
// decoration: const BoxDecoration(
|
||||
// border: Border(top: BorderSide(color: AppTheme.dividerColor))),
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// vertical: ScreenAdaper.height(5),
|
||||
// horizontal: ScreenAdaper.width(10)),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// itemData.productNumber!,
|
||||
// style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: ScreenAdaper.width(10),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// '${itemData.name}',
|
||||
// style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// ),
|
||||
// Text(
|
||||
// '${itemData.company?.name}',
|
||||
// style: TextStyle(
|
||||
// fontSize: ScreenAdaper.sp(15), color: AppTheme.grey),
|
||||
// )
|
||||
// ],
|
||||
// )),
|
||||
// // SizedBox(
|
||||
// // width: ScreenAdaper.width(10),
|
||||
// // ),
|
||||
// // Text(
|
||||
// // itemData.productNumber!,
|
||||
// // style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// // ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// showSearchBox: true,
|
||||
// ),
|
||||
// onChanged: print,
|
||||
// // selectedItem: "Brazil",
|
||||
// );
|
||||
// return ZtSearchSelect<ProductModel>(
|
||||
// isRequired: true,
|
||||
// textController: controller.productTextController,
|
||||
// labelText: '产品',
|
||||
// itemBuilder: (_, itemData) => Container(
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// vertical: ScreenAdaper.height(5),
|
||||
// horizontal: ScreenAdaper.width(10)),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// itemData.productNumber!,
|
||||
// style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: ScreenAdaper.width(10),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// '${itemData.name}',
|
||||
// style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// ),
|
||||
// Text(
|
||||
// '${itemData.company?.name}',
|
||||
// style: TextStyle(
|
||||
// fontSize: ScreenAdaper.sp(15),
|
||||
// color: AppTheme.grey),
|
||||
// )
|
||||
// ],
|
||||
// )),
|
||||
// // SizedBox(
|
||||
// // width: ScreenAdaper.width(10),
|
||||
// // ),
|
||||
// // Text(
|
||||
// // itemData.productNumber!,
|
||||
// // style: TextStyle(fontSize: ScreenAdaper.sp(20)),
|
||||
// // ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// suggestionsCallback: (String keyword) {
|
||||
// return controller.getProducts(keyword: keyword);
|
||||
// },
|
||||
// onClear: () {
|
||||
// controller.payload.remove('productId');
|
||||
// },
|
||||
// onSelected: (ProductModel product) {
|
||||
// controller.productTextController.text = product.name ?? '';
|
||||
// controller.payload['productId'] = product.id;
|
||||
// });
|
||||
}
|
||||
|
||||
/// 时间
|
||||
|
@ -205,6 +357,73 @@ class NewInventoryInout extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
/// 库存位置选择
|
||||
Widget buildPositionBottomPicker() {
|
||||
final firstLevelData = [
|
||||
...dictService.getDictItemsByCode(DictTypeEnum.InventoryRoom)
|
||||
];
|
||||
final secondLevelData = [
|
||||
DictItemModel(label: '未知', value: '未知'),
|
||||
...dictService.getDictItemsByCode(DictTypeEnum.InventoryLine)
|
||||
];
|
||||
final thirdDatas =
|
||||
dictService.getDictItemsByCode(DictTypeEnum.InventoryLineLevel);
|
||||
final thirdtLevelData = [
|
||||
if (thirdDatas.isNotEmpty) DictItemModel(label: '未知', value: '未知'),
|
||||
...thirdDatas
|
||||
];
|
||||
return TextFormField(
|
||||
controller: controller.positionTextController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '库存位置',
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always),
|
||||
readOnly: true,
|
||||
onTap: () {
|
||||
printInfo(
|
||||
info: firstLevelData
|
||||
.map((e) => Center(child: (Text(e.label))))
|
||||
.toList()
|
||||
.toString());
|
||||
ModalUtil.showBottomSheetPicker(
|
||||
title: '库存位置',
|
||||
firstLevel: firstLevelData
|
||||
.map((e) => Center(child: (Text(e.label))))
|
||||
.toList(),
|
||||
secondLevel: secondLevelData
|
||||
.map((e) => Center(child: (Text(e.label))))
|
||||
.toList(),
|
||||
thirdLevel: thirdtLevelData
|
||||
.map((e) => Center(child: (Text(e.label))))
|
||||
.toList(),
|
||||
onChanged: (_0, _1, _2) {
|
||||
String position = firstLevelData[_0].label;
|
||||
if (_1 >= 1) {
|
||||
position += ', ${secondLevelData[_1].label}';
|
||||
}
|
||||
if (_2 >= 1) {
|
||||
position += ', ${thirdtLevelData[_2].label}';
|
||||
}
|
||||
// , ${secondLevelData[_1].label}, ${thirdtLevelData[_2].label}
|
||||
controller.positionTextController.text = position;
|
||||
});
|
||||
},
|
||||
onChanged: (_) {
|
||||
printInfo(info: _);
|
||||
});
|
||||
// return ZtTextInput(
|
||||
// textController: controller.agentTextController,
|
||||
// labelText: '库存位置',
|
||||
// isRequired: true,
|
||||
// onTap: () => ModalUtil.showBottomSheetPicker(
|
||||
// title: '库存位置',
|
||||
// firstLevel: dictService
|
||||
// .getDictItemsByCode(DictTypeEnum.InventoryRoom)
|
||||
// .map((e) => Text(e.label))
|
||||
// .toList(),
|
||||
// onChanged: () {}),
|
||||
// );
|
||||
}
|
||||
|
||||
/// 照片上传
|
||||
Widget buildImageUploadQueue() {
|
||||
return Container(
|
||||
|
@ -217,7 +436,7 @@ class NewInventoryInout extends StatelessWidget {
|
|||
Text(
|
||||
'*请拍照上传产品照片',
|
||||
style: TextStyle(
|
||||
fontSize: ScreenAdaper.sp(30),
|
||||
fontSize: ScreenAdaper.sp(25),
|
||||
color: AppTheme.secondPrimaryColor),
|
||||
),
|
||||
SizedBox(
|
||||
|
@ -247,8 +466,8 @@ class NewInventoryInout extends StatelessWidget {
|
|||
children: [
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: ScreenAdaper.width(5)),
|
||||
width: ScreenAdaper.width(200),
|
||||
height: ScreenAdaper.width(200),
|
||||
width: ScreenAdaper.width(180),
|
||||
height: ScreenAdaper.width(180),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(width: 1.0, color: AppTheme.dividerColor),
|
||||
|
@ -303,8 +522,8 @@ class NewInventoryInout extends StatelessWidget {
|
|||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: ScreenAdaper.width(5)),
|
||||
width: ScreenAdaper.width(200),
|
||||
height: ScreenAdaper.width(200),
|
||||
width: ScreenAdaper.width(180),
|
||||
height: ScreenAdaper.width(180),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(width: 1.0, color: AppTheme.dividerColor),
|
||||
|
|
|
@ -44,6 +44,7 @@ class NewInventoryInoutController extends GetxController {
|
|||
final quantityTextController = TextEditingController();
|
||||
final agentTextController = TextEditingController();
|
||||
final remarkTextController = TextEditingController();
|
||||
final positionTextController = TextEditingController();
|
||||
final uploadImgFilesPath = <String>[].obs;
|
||||
final uploadScrollController = ScrollController();
|
||||
Map<String, dynamic> payload = {};
|
||||
|
@ -60,7 +61,7 @@ class NewInventoryInoutController extends GetxController {
|
|||
|
||||
Future<List<ProductModel>> getProducts({String? keyword}) async {
|
||||
final res =
|
||||
await Api.getProducts({'page': 1, 'pageSize': 10, 'name': keyword});
|
||||
await Api.getProducts({'page': 1, 'pageSize': 10, 'keyword': keyword});
|
||||
if (res.data != null) {
|
||||
products.assignAll(
|
||||
res.data!.items.map((e) => ProductModel.fromJson(e)).toList());
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:get/get.dart';
|
|||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/tap_to_dismiss_keyboard.dart';
|
||||
import 'package:sk_base_mobile/config.dart';
|
||||
import 'package:sk_base_mobile/models/auth.dart';
|
||||
import 'package:sk_base_mobile/models/user_info.model.dart';
|
||||
import 'package:sk_base_mobile/services/service.dart';
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:get/get_state_manager/get_state_manager.dart';
|
||||
import 'package:sk_base_mobile/constants/dict_enum.dart';
|
||||
import 'package:sk_base_mobile/models/dict_item.model.dart';
|
||||
import 'package:sk_base_mobile/models/dict_type.model.dart';
|
||||
import 'package:sk_base_mobile/apis/api.dart' as Api;
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
|
||||
const needCachedKey = [
|
||||
DictTypeEnum.InventoryRoom,
|
||||
DictTypeEnum.InventoryLine,
|
||||
DictTypeEnum.InventoryLineLevel
|
||||
];
|
||||
|
||||
class DictService extends GetxService {
|
||||
Future<DictService> init() async {
|
||||
await getDictTypes();
|
||||
return this;
|
||||
}
|
||||
|
||||
RxList<DictTypeModel> dictTypes = RxList([]);
|
||||
Future<void> getDictTypes() async {
|
||||
try {
|
||||
final response = await Api.getDictTypeAll({
|
||||
'storeCodes': needCachedKey,
|
||||
'withItems': true,
|
||||
});
|
||||
dictTypes.value = (response.data as List)
|
||||
.map((item) => DictTypeModel.fromJson(item))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
LoggerUtil().error('getDictTypes error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
List<DictItemModel> getDictItemsByCode(String code) {
|
||||
return dictTypes.firstWhereOrNull((item) => item.code == code)?.dictItems ??
|
||||
[];
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/widgets/core/zt_bottomsheet_picker.dart';
|
||||
|
||||
class ModalUtil {
|
||||
static Future<bool> showWarningDialog(
|
||||
|
@ -40,4 +42,27 @@ class ModalUtil {
|
|||
);
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
/// 底部选择器,支持3级
|
||||
static Future<void> showBottomSheetPicker(
|
||||
{title = '请选择',
|
||||
required onChanged,
|
||||
required firstLevel,
|
||||
secondLevel,
|
||||
thirdLevel,
|
||||
itemHeight,
|
||||
popupHeight}) async =>
|
||||
showCupertinoModalPopup(
|
||||
context: Get.overlayContext!,
|
||||
builder: (BuildContext context) {
|
||||
return ZtBottomSheetPicker(
|
||||
title: title,
|
||||
onChanged: onChanged,
|
||||
firstLevel: firstLevel,
|
||||
secondLevel: secondLevel,
|
||||
thirdLevel: thirdLevel,
|
||||
itemHeight: itemHeight ?? 80.0,
|
||||
popupHeight: popupHeight ?? 400);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class ZtBaseDatePicker extends StatelessWidget {
|
||||
final Function? onDateTimeChanged;
|
||||
final yearController =
|
||||
FixedExtentScrollController(initialItem: DateTime.now().year - 2000);
|
||||
final monthController =
|
||||
FixedExtentScrollController(initialItem: DateTime.now().month - 1);
|
||||
final dayController =
|
||||
FixedExtentScrollController(initialItem: DateTime.now().day - 1);
|
||||
ZtBaseDatePicker({super.key, this.onDateTimeChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: ScreenAdaper.height(250),
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25)),
|
||||
)),
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
final year = 2000 + yearController.selectedItem;
|
||||
String month = '${monthController.selectedItem + 1}';
|
||||
if (int.parse(month) < 10) {
|
||||
month = '0$month';
|
||||
}
|
||||
final day = dayController.selectedItem + 1;
|
||||
if (onDateTimeChanged != null) {
|
||||
onDateTimeChanged!('$year-$month-$day');
|
||||
}
|
||||
LoggerUtil().info('$year-$month-$day');
|
||||
},
|
||||
child: Text(
|
||||
'确定',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25)),
|
||||
))
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: yearController,
|
||||
itemExtent: ScreenAdaper.height(60),
|
||||
onSelectedItemChanged: (int index) {
|
||||
// 处理用户选择的年份
|
||||
},
|
||||
children: List<Widget>.generate(DateTime.now().year - 1999,
|
||||
(int index) {
|
||||
return Center(child: Text('${2000 + index}年'));
|
||||
}),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: monthController,
|
||||
itemExtent: ScreenAdaper.height(60),
|
||||
onSelectedItemChanged: (int index) {
|
||||
// 处理用户选择的月份
|
||||
},
|
||||
children: List<Widget>.generate(12, (int index) {
|
||||
return Center(child: Text('${index + 1}月'));
|
||||
}),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: dayController,
|
||||
itemExtent: ScreenAdaper.height(60),
|
||||
onSelectedItemChanged: (int index) {
|
||||
// 处理用户选择的日期
|
||||
},
|
||||
children: List<Widget>.generate(31, (int index) {
|
||||
return Center(child: Text('${index + 1}日'));
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class ZtBottomSheetPicker extends StatelessWidget {
|
||||
final Function? onChanged;
|
||||
FixedExtentScrollController firstLevelControlller =
|
||||
FixedExtentScrollController();
|
||||
FixedExtentScrollController secondLevelController =
|
||||
FixedExtentScrollController();
|
||||
FixedExtentScrollController thirdLevelController =
|
||||
FixedExtentScrollController();
|
||||
final List<Widget> firstLevel;
|
||||
final List<Widget>? secondLevel;
|
||||
final List<Widget>? thirdLevel;
|
||||
double? itemHeight;
|
||||
double? popupHeight;
|
||||
final String title;
|
||||
ZtBottomSheetPicker(
|
||||
{super.key,
|
||||
this.title = '请选择',
|
||||
required this.onChanged,
|
||||
required this.firstLevel,
|
||||
this.secondLevel,
|
||||
this.thirdLevel,
|
||||
this.itemHeight = 80.0,
|
||||
this.popupHeight = 400.0});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: ScreenAdaper.height(popupHeight!),
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25)),
|
||||
)),
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: AppTheme.nearlyBlack,
|
||||
fontSize: ScreenAdaper.sp(25),
|
||||
decoration: TextDecoration.none),
|
||||
),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
onChanged!(
|
||||
firstLevelControlller.selectedItem,
|
||||
(secondLevel ?? []).isNotEmpty
|
||||
? secondLevelController.selectedItem
|
||||
: -1,
|
||||
(thirdLevel ?? []).isNotEmpty
|
||||
? thirdLevelController.selectedItem
|
||||
: -1,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'确定',
|
||||
style: TextStyle(fontSize: ScreenAdaper.sp(25)),
|
||||
))
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: firstLevelControlller,
|
||||
itemExtent: ScreenAdaper.height(itemHeight!),
|
||||
onSelectedItemChanged: (int index) {},
|
||||
children: firstLevel,
|
||||
),
|
||||
),
|
||||
if ((secondLevel ?? []).isNotEmpty)
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: secondLevelController,
|
||||
itemExtent: ScreenAdaper.height(itemHeight!),
|
||||
onSelectedItemChanged: (int index) {},
|
||||
children: secondLevel!,
|
||||
),
|
||||
),
|
||||
if ((thirdLevel ?? []).isNotEmpty)
|
||||
Expanded(
|
||||
child: CupertinoPicker(
|
||||
scrollController: thirdLevelController,
|
||||
itemExtent: ScreenAdaper.height(itemHeight!),
|
||||
onSelectedItemChanged: (int index) {},
|
||||
children: thirdLevel!,
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,14 +4,14 @@ import 'package:get/get.dart';
|
|||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class ZtSearchSelect extends StatelessWidget {
|
||||
class ZtSearchSelect<T> extends StatelessWidget {
|
||||
final TextEditingController textController;
|
||||
final Function? suggestionsCallback;
|
||||
final Function? onSelected;
|
||||
final void Function(T)? onSelected;
|
||||
final VoidCallback? onClear;
|
||||
final String labelText;
|
||||
final bool isRequired;
|
||||
final Widget Function(dynamic itemData)? itemBuilder;
|
||||
final Widget Function(BuildContext, T) itemBuilder;
|
||||
const ZtSearchSelect(
|
||||
{super.key,
|
||||
required this.textController,
|
||||
|
@ -89,13 +89,13 @@ class ZtSearchSelect extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
itemBuilder: (context, itemData) {
|
||||
return itemBuilder!(itemData);
|
||||
return itemBuilder(context, itemData as T);
|
||||
},
|
||||
onSelected: (selectedItemData) {
|
||||
// 键盘关闭
|
||||
FocusScope.of(context).unfocus();
|
||||
if (onSelected != null) {
|
||||
onSelected!(selectedItemData);
|
||||
onSelected!(selectedItemData as T);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,14 +12,15 @@ class ZtTextInput extends StatelessWidget {
|
|||
final String labelText;
|
||||
final String? hint;
|
||||
final bool isTextArea;
|
||||
const ZtTextInput(
|
||||
{super.key,
|
||||
const ZtTextInput({
|
||||
super.key,
|
||||
required this.textController,
|
||||
this.onTap,
|
||||
this.hint,
|
||||
this.isRequired = false,
|
||||
this.labelText = '',
|
||||
this.isTextArea = false});
|
||||
this.isTextArea = false,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFormField(
|
||||
|
@ -27,7 +28,7 @@ class ZtTextInput extends StatelessWidget {
|
|||
onTapOutside: (event) {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
maxLines: isTextArea ? 3 : 1, // 添加这行代码
|
||||
maxLines: isTextArea ? 2 : 1, // 添加这行代码
|
||||
onTap: onTap ?? () {},
|
||||
decoration: InputDecoration(
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
|
|
|
@ -10,10 +10,10 @@ class Empty extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Center(
|
||||
child: Image(
|
||||
height: ScreenAdaper.height(130),
|
||||
image: const AssetImage('assets/images/empty_icon.png'))),
|
||||
// Center(
|
||||
// child: Image(
|
||||
// height: ScreenAdaper.height(130),
|
||||
// image: const AssetImage('assets/images/empty_icon.png'))),
|
||||
Text(
|
||||
text ?? '',
|
||||
textAlign: TextAlign.center,
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
|
||||
class LoadingIndicator extends StatelessWidget {
|
||||
final bool animating;
|
||||
const LoadingIndicator({super.key, this.animating = true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoActivityIndicator(
|
||||
animating: animating,
|
||||
color: AppTheme.primaryColor,
|
||||
radius: ScreenAdaper.sp(20),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||
|
||||
class RefreshFooter extends StatefulWidget {
|
||||
const RefreshFooter({Key? key}) : super(key: key);
|
||||
|
@ -32,16 +35,16 @@ class _RefreshFooterState extends State<RefreshFooter>
|
|||
builder: (BuildContext context, LoadStatus? status) {
|
||||
Widget body;
|
||||
if (status == LoadStatus.idle) {
|
||||
body = const Text("Pull up to get latest messages");
|
||||
body = const Text("上拉获取更多");
|
||||
} else if (status == LoadStatus.loading) {
|
||||
body = const SizedBox(child: const CupertinoActivityIndicator());
|
||||
body = const LoadingIndicator();
|
||||
} else if (status == LoadStatus.failed) {
|
||||
body = Text(
|
||||
"Load failed, please try again",
|
||||
"获取失败,请重试",
|
||||
style: style,
|
||||
);
|
||||
} else if (status == LoadStatus.canLoading) {
|
||||
body = const CupertinoActivityIndicator(
|
||||
body = const LoadingIndicator(
|
||||
animating: false,
|
||||
);
|
||||
} else {
|
|
@ -1,6 +1,9 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:sk_base_mobile/app_theme.dart';
|
||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||
|
||||
class RefreshHeader extends RefreshIndicator {
|
||||
RefreshHeader()
|
||||
|
@ -39,15 +42,17 @@ class RefreshHeaderState extends RefreshIndicatorState<RefreshHeader>
|
|||
TextStyle style = TextStyle(fontSize: ScreenAdaper.sp(18));
|
||||
Widget body;
|
||||
if (mode == RefreshStatus.refreshing) {
|
||||
body = const CupertinoActivityIndicator();
|
||||
body = const LoadingIndicator();
|
||||
} else if (mode == RefreshStatus.canRefresh) {
|
||||
body = const CupertinoActivityIndicator(animating: false);
|
||||
body = const LoadingIndicator(
|
||||
animating: false,
|
||||
);
|
||||
} else if (mode == RefreshStatus.completed) {
|
||||
body = const SizedBox();
|
||||
} else if (mode == RefreshStatus.failed) {
|
||||
body = Text("No more Data)", style: style);
|
||||
body = Text("没有更多数据了", style: style);
|
||||
} else {
|
||||
body = const CupertinoActivityIndicator();
|
||||
body = const LoadingIndicator();
|
||||
}
|
||||
return SizedBox(
|
||||
height: ScreenAdaper.height(40),
|
||||
|
|
|
@ -177,6 +177,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.1"
|
||||
dropdown_search:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dropdown_search
|
||||
sha256: "55106e8290acaa97ed15bea1fdad82c3cf0c248dd410e651f5a8ac6870f783ab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.6"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -57,6 +57,7 @@ dependencies:
|
|||
path: ^1.8.3
|
||||
path_provider: ^2.1.2
|
||||
flutter_typeahead: ^5.2.0
|
||||
dropdown_search: ^5.0.6
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
|
Loading…
Reference in New Issue