date_range_picker_dialog.dart 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import 'package:cs_resources/constants/color_constants.dart';
  2. import 'package:cs_resources/generated/assets.dart';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:plugin_basic/basic_export.dart';
  6. import 'package:plugin_platform/engine/toast/toast_engine.dart';
  7. import 'package:shared/utils/date_time_utils.dart';
  8. import 'package:widgets/ext/ex_widget.dart';
  9. import 'package:widgets/my_load_image.dart';
  10. import 'package:widgets/my_text_view.dart';
  11. import 'package:widgets/picker/date_picker_util.dart';
  12. import 'package:widgets/widget_export.dart';
  13. class DateRangePickerDialog extends StatefulWidget {
  14. final void Function(String) confirmAction; // 回调确认的时间区间
  15. final VoidCallback? cancelAction;
  16. final String? dateRange; // 时间区间参数
  17. DateRangePickerDialog({
  18. required this.confirmAction,
  19. this.cancelAction,
  20. this.dateRange, // 接收时间区间
  21. });
  22. @override
  23. _DateRangePickerDialogState createState() => _DateRangePickerDialogState();
  24. }
  25. class _DateRangePickerDialogState extends State<DateRangePickerDialog> {
  26. DateTime? startDate;
  27. DateTime? endDate;
  28. @override
  29. void initState() {
  30. super.initState();
  31. // 如果 dateRange 不为空,则解析并设置开始和结束日期
  32. if (widget.dateRange != null && widget.dateRange!.isNotEmpty) {
  33. List<String> dates = widget.dateRange!.split(',');
  34. if (dates.length >= 2) {
  35. startDate = DateTime.parse(dates[0]);
  36. endDate = DateTime.parse(dates[dates.length - 1]);
  37. }
  38. }
  39. }
  40. @override
  41. Widget build(BuildContext context) {
  42. return Column(
  43. crossAxisAlignment: CrossAxisAlignment.center,
  44. mainAxisAlignment: MainAxisAlignment.center,
  45. children: [
  46. Container(
  47. width: double.infinity,
  48. decoration: const BoxDecoration(
  49. color: Colors.white,
  50. borderRadius: BorderRadius.all(Radius.circular(15)),
  51. ),
  52. child: Column(
  53. children: [
  54. MyTextView(
  55. "Select Date Range".tr,
  56. fontSize: 19,
  57. isFontMedium: true,
  58. textColor: ColorConstants.black,
  59. marginTop: 15,
  60. marginBottom: 15,
  61. ),
  62. InkWell(
  63. onTap: () {
  64. DatePickerUtil.showCupertinoDatePicker(
  65. selectedDateTime: startDate ?? DateTime.now(),
  66. mode: CupertinoDatePickerMode.date,
  67. onDateTimeChanged: (date) {
  68. setState(() {
  69. startDate = date;
  70. });
  71. },
  72. title: "Start Time".tr,
  73. );
  74. },
  75. child: Container(
  76. decoration: const BoxDecoration(
  77. color: ColorConstants.grayECECEC,
  78. borderRadius: BorderRadius.all(Radius.circular(5)),
  79. ),
  80. margin: const EdgeInsets.symmetric(horizontal: 15),
  81. padding: const EdgeInsets.all(15.0),
  82. child: Row(
  83. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  84. children: [
  85. MyTextView(
  86. startDate != null ? DateTimeUtils.formatDate(startDate, format: 'yyyy-MM-dd') : "Select Start Time",
  87. fontSize: 15,
  88. isFontRegular: true,
  89. textColor: ColorConstants.black33,
  90. ),
  91. const MyAssetImage(
  92. Assets.cptJobPickDateIcon,
  93. width: 20,
  94. height: 20,
  95. color: ColorConstants.secondaryAppColor,
  96. ),
  97. ],
  98. ),
  99. ),
  100. ),
  101. InkWell(
  102. onTap: () {
  103. DatePickerUtil.showCupertinoDatePicker(
  104. selectedDateTime: endDate ?? DateTime.now(),
  105. mode: CupertinoDatePickerMode.date,
  106. onDateTimeChanged: (date) {
  107. setState(() {
  108. endDate = date;
  109. });
  110. },
  111. title: "End Time".tr,
  112. );
  113. },
  114. child: Container(
  115. decoration: const BoxDecoration(
  116. color: ColorConstants.grayECECEC,
  117. borderRadius: BorderRadius.all(Radius.circular(5)),
  118. ),
  119. margin: const EdgeInsets.only(left: 15, right: 15, top: 15),
  120. padding: const EdgeInsets.all(15.0),
  121. child: Row(
  122. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  123. children: [
  124. MyTextView(
  125. endDate != null ? DateTimeUtils.formatDate(endDate, format: 'yyyy-MM-dd') : "Select End Time",
  126. fontSize: 15,
  127. isFontRegular: true,
  128. textColor: ColorConstants.black33,
  129. ),
  130. const MyAssetImage(
  131. Assets.cptJobPickDateIcon,
  132. width: 20,
  133. height: 20,
  134. color: ColorConstants.secondaryAppColor,
  135. ),
  136. ],
  137. ),
  138. ),
  139. ),
  140. Container(
  141. margin: const EdgeInsets.only(top: 25),
  142. color: const Color(0XFFCECECE),
  143. height: 0.5,
  144. ),
  145. Row(
  146. children: [
  147. Expanded(
  148. flex: 1,
  149. child: InkWell(
  150. onTap: () {
  151. onCancel();
  152. widget.cancelAction?.call();
  153. },
  154. child: MyTextView(
  155. "Cancel".tr,
  156. fontSize: 17.5,
  157. isFontMedium: true,
  158. textAlign: TextAlign.center,
  159. textColor: const Color(0XFF0085C4),
  160. cornerRadius: 3,
  161. borderWidth: 1,
  162. ),
  163. )),
  164. Container(
  165. color: const Color(0xff09141F).withOpacity(0.13),
  166. width: 0.5,
  167. ),
  168. Expanded(
  169. flex: 1,
  170. child: InkWell(
  171. onTap: () async {
  172. if (startDate != null && endDate != null) {
  173. if (endDate!.isBefore(startDate!.add(const Duration(hours: 6)))) {
  174. ToastEngine.show("End date must be greater than start date");
  175. } else {
  176. onCancel();
  177. // 确保开始日期和结束日期都已选择
  178. String dateRange = _getDateRange(startDate!, endDate!);
  179. widget.confirmAction(dateRange);
  180. }
  181. } else {
  182. ToastEngine.show("Select Date");
  183. }
  184. },
  185. child: MyTextView(
  186. "Confirm".tr,
  187. marginLeft: 10,
  188. fontSize: 17.5,
  189. isFontMedium: true,
  190. textAlign: TextAlign.center,
  191. textColor: const Color(0XFF0085C4),
  192. cornerRadius: 3,
  193. ),
  194. )),
  195. ],
  196. ).constrained(height: 46),
  197. ],
  198. ),
  199. ),
  200. ],
  201. ).constrained(width: 295);
  202. }
  203. String _getDateRange(DateTime start, DateTime end) {
  204. List<String> dateList = [];
  205. DateTime current = start;
  206. String endFormat = DateTimeUtils.formatDate(end, format: 'yyyy-MM-dd');
  207. // 逐日增加,直到达到结束日期,包括结束日期
  208. while (current.isBefore(end) || current.isAtSameMomentAs(end)) {
  209. dateList.add(DateTimeUtils.formatDate(current, format: 'yyyy-MM-dd'));
  210. current = current.add(const Duration(days: 1));
  211. }
  212. if (!dateList.contains(endFormat)) {
  213. dateList.add(endFormat);
  214. }
  215. return dateList.join(','); // 使用逗号连接日期
  216. }
  217. void onCancel() async {
  218. SmartDialog.dismiss();
  219. }
  220. }