discount_ticket_dialog.dart 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
  4. import 'package:get/get.dart';
  5. import 'package:lottie/lottie.dart';
  6. import '../../../data/consts/constants.dart';
  7. import '../../../data/consts/event_report.dart';
  8. import '../../../handler/event_handler.dart';
  9. import '../../../resource/assets.gen.dart';
  10. import '../../../resource/colors.gen.dart';
  11. import '../../../utils/styles.dart';
  12. import '../suprise/goods_surprise_controller.dart';
  13. // 折扣券一杯奶茶弹窗
  14. class DiscountTicketDialog {
  15. static const String tag = 'DiscountTicketDialog';
  16. static void show({VoidCallback? clickConfirm, VoidCallback? clickCancel}) {
  17. EventHandler.report(EventId.event_02006);
  18. if (SmartDialog.checkExist(tag: tag)) return;
  19. SmartDialog.show(
  20. tag: tag,
  21. backType: SmartBackType.block,
  22. clickMaskDismiss: false,
  23. maskColor: ColorName.black70,
  24. animationType: SmartAnimationType.centerScale_otherSlide,
  25. onDismiss: () => Get.delete<GoodsSurpriseController>(),
  26. builder: (_) {
  27. final controller = Get.find<GoodsSurpriseController>();
  28. return Stack(
  29. children: [
  30. Positioned(
  31. top: 0,
  32. left: 0,
  33. right: 0,
  34. bottom: 0,
  35. child: Column(
  36. crossAxisAlignment: CrossAxisAlignment.center,
  37. mainAxisAlignment: MainAxisAlignment.center,
  38. children: [
  39. Stack(
  40. clipBehavior: Clip.none,
  41. children: [
  42. Column(
  43. mainAxisAlignment: MainAxisAlignment.center,
  44. crossAxisAlignment: CrossAxisAlignment.center,
  45. children: [
  46. SizedBox(
  47. width: 360.h,
  48. height: 110.h,
  49. child: IgnorePointer(
  50. child: Lottie.asset(
  51. Assets.anim.animDiscountTicketDialogData,
  52. repeat: false,
  53. fit: BoxFit.contain,
  54. ),
  55. ),
  56. ),
  57. Container(
  58. margin: EdgeInsets.only(left: 31.h, right: 14.h),
  59. width: 317.w,
  60. height: 364.h,
  61. decoration: BoxDecoration(
  62. image: DecorationImage(
  63. image: Assets.images.bgTicketDialog.provider(),
  64. fit: BoxFit.contain,
  65. ),
  66. boxShadow: [
  67. BoxShadow(
  68. color: Colors.black.withAlpha(4), // 阴影颜色
  69. blurRadius: 10, // 模糊程度
  70. spreadRadius: 2, // 扩散程度
  71. offset: Offset(4, 4), // 偏移量 (x, y)
  72. ),
  73. ],
  74. ),
  75. child: Stack(
  76. children: [
  77. Column(
  78. mainAxisAlignment: MainAxisAlignment.start,
  79. crossAxisAlignment: CrossAxisAlignment.center,
  80. children: [
  81. SizedBox(height: 160.h),
  82. Container(
  83. margin: EdgeInsets.only(right: 16.h),
  84. decoration: BoxDecoration(
  85. image: DecorationImage(
  86. image:
  87. Assets.images.bgTicketDialogPrices
  88. .provider(),
  89. fit: BoxFit.cover,
  90. alignment: Alignment.center,
  91. ),
  92. ),
  93. width: 260.w,
  94. height: 100.h,
  95. child: Column(
  96. children: [
  97. Container(
  98. margin: EdgeInsets.only(top: 10.h),
  99. child: Obx(() {
  100. return Text(
  101. controller.secondAmount?.name ??
  102. "",
  103. style: TextStyle(
  104. color: const Color(
  105. 0xFFC39858,
  106. ),
  107. fontSize: 14.sp,
  108. fontWeight: FontWeight.w400,
  109. ),
  110. );
  111. }),
  112. ),
  113. Obx(() {
  114. return Text.rich(
  115. TextSpan(
  116. children: [
  117. TextSpan(
  118. text: '¥',
  119. style: TextStyle(
  120. color: const Color(
  121. 0xFFF55208,
  122. ),
  123. fontSize: 27.sp,
  124. fontWeight:
  125. FontWeight.w700,
  126. height: 0,
  127. ),
  128. ),
  129. TextSpan(
  130. text:
  131. controller
  132. .secondAmount
  133. ?.amountText,
  134. style: TextStyle(
  135. color: const Color(
  136. 0xFFF55208,
  137. ),
  138. height: 0,
  139. fontSize: 36.sp,
  140. fontWeight:
  141. FontWeight.w700,
  142. ),
  143. ),
  144. ],
  145. ),
  146. );
  147. }),
  148. Obx(() {
  149. return Text(
  150. controller
  151. .secondAmount
  152. ?.description ??
  153. "",
  154. style: TextStyle(
  155. color: Colors.black.withAlpha(
  156. 66,
  157. ),
  158. fontSize: 10.sp,
  159. fontWeight: FontWeight.w400,
  160. ),
  161. );
  162. }),
  163. ],
  164. ),
  165. ),
  166. Container(
  167. margin: EdgeInsets.only(right: 25.h),
  168. width: 317.w,
  169. height: 16.h,
  170. decoration: BoxDecoration(
  171. image: DecorationImage(
  172. image:
  173. Assets
  174. .images
  175. .bgTicketDialogPrices2
  176. .provider(),
  177. fit: BoxFit.contain,
  178. ),
  179. ),
  180. ),
  181. SizedBox(height: 9.h),
  182. GestureDetector(
  183. onTap: () {
  184. EventHandler.report(
  185. EventId.event_02007,
  186. );
  187. clickConfirm?.call();
  188. SmartDialog.dismiss(tag: tag);
  189. },
  190. child: Container(
  191. margin: EdgeInsets.only(right: 20.h),
  192. width: 200.w,
  193. height: 54.h,
  194. child: Assets
  195. .images
  196. .iconTicketDialogButton
  197. .image(width: 200.w, height: 54.h),
  198. ),
  199. ),
  200. ],
  201. ),
  202. // 倒计时
  203. Visibility(
  204. visible: isNotHWChannel(),
  205. child: Positioned(
  206. right: 40.w,
  207. child: Container(
  208. height: 24.h,
  209. width: 107.w,
  210. alignment: Alignment.center,
  211. decoration: ShapeDecoration(
  212. gradient: LinearGradient(
  213. begin: Alignment.centerLeft,
  214. end: Alignment.centerRight,
  215. colors: [
  216. const Color(0xFFFF68F4),
  217. const Color(0xFFF96432),
  218. ],
  219. ),
  220. shape: RoundedRectangleBorder(
  221. side: BorderSide(
  222. width: 1,
  223. color: Colors.white,
  224. ),
  225. borderRadius: BorderRadius.only(
  226. topLeft: Radius.circular(15.r),
  227. topRight: Radius.circular(16.r),
  228. bottomRight: Radius.circular(16.r),
  229. ),
  230. ),
  231. ),
  232. margin: EdgeInsets.only(top: 140.h),
  233. child: Obx(() {
  234. int totalMilliseconds =
  235. controller.timeLeft.value;
  236. int minutes =
  237. (totalMilliseconds ~/ 6000);
  238. int seconds =
  239. (totalMilliseconds ~/ 100) % 60;
  240. int milliseconds =
  241. (totalMilliseconds % 100); // 毫秒
  242. return Row(
  243. children: [
  244. Container(
  245. margin: EdgeInsets.only(left: 4.w),
  246. width: 57.w,
  247. child: Text(
  248. "${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}:${milliseconds.toString().padLeft(2, '0')}",
  249. style: TextStyle(
  250. color: Colors.white,
  251. fontSize: 12.sp,
  252. fontWeight: FontWeight.w500,
  253. ),
  254. ),
  255. ),
  256. Text(
  257. "后过期",
  258. style: TextStyle(
  259. color: Colors.white,
  260. fontSize: 12.sp,
  261. fontWeight: FontWeight.w500,
  262. ),
  263. ),
  264. ],
  265. );
  266. }),
  267. ),
  268. ),
  269. ),
  270. ],
  271. ),
  272. ),
  273. ],
  274. ),
  275. ],
  276. ),
  277. Container(
  278. margin: EdgeInsets.only(top: 24.h),
  279. child: GestureDetector(
  280. onTap: () {
  281. EventHandler.report(EventId.event_02008);
  282. SmartDialog.dismiss(tag: tag);
  283. clickCancel?.call();
  284. },
  285. child: Assets.images.iconCharacterDialogClose.image(
  286. width: 40.r,
  287. height: 40.r,
  288. ),
  289. ),
  290. ),
  291. ],
  292. ),
  293. ),
  294. ],
  295. );
  296. },
  297. );
  298. }
  299. }
  300. class VerticalDots extends StatelessWidget {
  301. final double dotSize;
  302. final double height;
  303. final Color? color;
  304. const VerticalDots({
  305. super.key,
  306. required this.dotSize,
  307. required this.height,
  308. this.color = Colors.white,
  309. });
  310. @override
  311. Widget build(BuildContext context) {
  312. return SizedBox(
  313. width: 2.w,
  314. height: 8.h,
  315. child: Column(
  316. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  317. children: List.generate(2, (index) {
  318. return Container(
  319. width: dotSize,
  320. height: dotSize,
  321. decoration: BoxDecoration(color: color, shape: BoxShape.circle),
  322. );
  323. }),
  324. ),
  325. );
  326. }
  327. }