view.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. import 'package:electronic_assistant/base/base_page.dart';
  2. import 'package:electronic_assistant/data/bean/payment_way.dart';
  3. import 'package:electronic_assistant/resource/assets.gen.dart';
  4. import 'package:electronic_assistant/resource/colors.gen.dart';
  5. import 'package:electronic_assistant/router/app_pages.dart';
  6. import 'package:electronic_assistant/utils/expand.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:flutter_screenutil/flutter_screenutil.dart';
  9. import 'package:get/get.dart';
  10. import '../../data/bean/store_item.dart';
  11. import '../../data/consts/Constants.dart';
  12. import '../../widget/shimmer_effect.dart';
  13. import 'controller.dart';
  14. enum StoreFromType { home, mine, analyse }
  15. class StorePage extends BasePage<StoreController> {
  16. const StorePage({super.key});
  17. static start({StoreFromType? fromType}) {
  18. Get.toNamed(RoutePath.store, arguments: {'fromType': fromType});
  19. }
  20. @override
  21. Color backgroundColor() {
  22. return "#071935".color;
  23. }
  24. @override
  25. Color navigationBarColor() {
  26. return "#283B58".color;
  27. }
  28. @override
  29. bool statusBarDarkFont() {
  30. return false;
  31. }
  32. @override
  33. bool immersive() {
  34. return true;
  35. }
  36. //47.67
  37. @override
  38. Widget buildBody(BuildContext context) {
  39. return Stack(
  40. children: [
  41. SingleChildScrollView(
  42. child: _buildStoreContent(),
  43. ),
  44. Align(
  45. alignment: Alignment.bottomCenter,
  46. child: _buildBottomButton(),
  47. ),
  48. Positioned(
  49. left: 0,
  50. right: 0,
  51. child: AppBar(
  52. backgroundColor: Colors.transparent,
  53. scrolledUnderElevation: 0,
  54. leading: IconButton(
  55. color: Colors.white,
  56. icon: const Icon(Icons.arrow_back_ios_new_rounded),
  57. onPressed: () {
  58. Get.back();
  59. },
  60. ),
  61. actions: [_buildElectricBalance()],
  62. ),
  63. ),
  64. ],
  65. );
  66. }
  67. _buildElectricBalance() {
  68. return Container(
  69. padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.w),
  70. margin: EdgeInsets.only(right: 12.w),
  71. decoration: BoxDecoration(
  72. borderRadius: BorderRadius.circular(100.w),
  73. border: Border.all(
  74. color: "#7688B1".toColor(),
  75. width: 1.w,
  76. )),
  77. child: Row(
  78. children: [
  79. Assets.images.iconStoreLogo.image(width: 20.w, height: 20.w),
  80. Container(
  81. margin: EdgeInsets.symmetric(horizontal: 3.w),
  82. child: Text("电量",
  83. style: TextStyle(color: Colors.white, fontSize: 12.w)),
  84. ),
  85. Obx(() {
  86. return Text('${controller.userInfo?.memberInfo?.electric ?? '0'}',
  87. style: TextStyle(color: Colors.white, fontSize: 12.w));
  88. }),
  89. ],
  90. ),
  91. );
  92. }
  93. _buildStoreContent() {
  94. return Stack(
  95. children: [
  96. _buildTopBanner(),
  97. Column(
  98. children: [
  99. Container(
  100. margin: EdgeInsets.only(top: 315.w),
  101. height: 154.w,
  102. child: Obx(() => ListView.builder(
  103. itemBuilder: _buildStoreItem,
  104. itemCount: controller.storeItems.length,
  105. scrollDirection: Axis.horizontal,
  106. )),
  107. ),
  108. Container(
  109. margin: EdgeInsets.only(left: 12.w, right: 12.w, top: 18.w),
  110. alignment: Alignment.centerLeft,
  111. child: Obx(() => Text(
  112. " · ${controller.currentSelectedStoreItem.value?.itemDesc}",
  113. style: TextStyle(
  114. fontSize: 10.sp,
  115. color: "#AFAFAF".color,
  116. fontWeight: FontWeight.bold))),
  117. ),
  118. Visibility(
  119. visible: GetPlatform.isAndroid,
  120. child: _buildPaymentWays(),
  121. ),
  122. _buildService(),
  123. _buildRule(),
  124. SizedBox(height: 80.w)
  125. ],
  126. ),
  127. ],
  128. );
  129. }
  130. _buildTopBanner() {
  131. return Stack(alignment: AlignmentDirectional.bottomStart, children: [
  132. Assets.images.bgStoreTop.image(),
  133. Container(
  134. margin: EdgeInsets.only(left: 12.w, bottom: 73.33.w),
  135. child: Assets.images.iconStoreDescripe.image(width: 268.w))
  136. ]);
  137. }
  138. Widget _buildStoreItem(BuildContext context, int index) {
  139. StoreItem storeItem = controller.storeItems[index];
  140. return GestureDetector(
  141. onTap: () => controller.onStoreItemClick(storeItem),
  142. child: Container(
  143. margin: EdgeInsets.only(
  144. left: index == 0 ? 12.w : 10.w,
  145. right: index == controller.storeItems.length - 1 ? 12.w : 0),
  146. child: Stack(
  147. children: [
  148. Obx(() =>
  149. controller.currentSelectedStoreItem.value?.id == storeItem.id
  150. ? _buildSelectedItemContent(storeItem)
  151. : _buildUnselectedItemContent(storeItem)),
  152. Visibility(
  153. visible: storeItem.popular,
  154. child: Container(
  155. padding: EdgeInsets.only(
  156. left: 8.w, right: 8.w, top: 2.w, bottom: 10.w),
  157. decoration: BoxDecoration(
  158. image: DecorationImage(
  159. image: Assets.images.iconStoreGoodTag.provider(),
  160. fit: BoxFit.fill,
  161. ),
  162. ),
  163. child: Text("最多人购买",
  164. style: TextStyle(
  165. color: "#703D27".color,
  166. fontSize: 12.sp,
  167. fontWeight: FontWeight.bold)),
  168. ),
  169. ),
  170. ],
  171. ),
  172. ),
  173. );
  174. }
  175. Widget _buildSelectedItemContent(StoreItem storeItem) {
  176. return Container(
  177. width: 132.w,
  178. margin: EdgeInsets.only(top: 9.w),
  179. decoration: BoxDecoration(
  180. borderRadius: BorderRadius.circular(12.w),
  181. gradient: LinearGradient(
  182. colors: ['#9075FF'.color, '#4366FF'.color],
  183. begin: Alignment.centerLeft,
  184. end: Alignment.centerRight,
  185. stops: const [0.0, 1.0],
  186. ),
  187. ),
  188. child: Container(
  189. margin: EdgeInsets.all(2.w),
  190. decoration: BoxDecoration(
  191. gradient: LinearGradient(
  192. colors: ['#DADBFF'.color, '#FFF3F6'.color],
  193. begin: Alignment.centerLeft,
  194. end: Alignment.centerRight,
  195. stops: const [0.0, 1.0],
  196. ),
  197. borderRadius: BorderRadius.circular(12.w),
  198. ),
  199. child: _buildItemContent(storeItem, true),
  200. ),
  201. );
  202. }
  203. Widget _buildUnselectedItemContent(StoreItem storeItem) {
  204. return Container(
  205. width: 132.w,
  206. margin: EdgeInsets.only(top: 9.w),
  207. padding: EdgeInsets.all(2.w),
  208. decoration: BoxDecoration(
  209. borderRadius: BorderRadius.circular(12.w), color: "#40567D".color),
  210. child: _buildItemContent(storeItem, false),
  211. );
  212. }
  213. Widget _buildItemContent(StoreItem storeItem, bool isSelect) {
  214. return Column(
  215. children: [
  216. Container(
  217. margin: EdgeInsets.only(top: 14.w),
  218. child: Text(storeItem.name,
  219. style: TextStyle(
  220. color: isSelect ? "#6177F2".color : Colors.white,
  221. fontSize: 13.sp,
  222. fontWeight: FontWeight.bold)),
  223. ),
  224. Container(
  225. margin: EdgeInsets.only(top: 10.w),
  226. child: RichText(
  227. text: TextSpan(
  228. children: [
  229. TextSpan(
  230. text: "¥",
  231. style: TextStyle(
  232. color: isSelect ? "#6177F2".color : Colors.white,
  233. fontSize: 16.sp,
  234. ),
  235. ),
  236. TextSpan(
  237. text: storeItem.amountText,
  238. style: TextStyle(
  239. color: isSelect ? "#6177F2".color : Colors.white,
  240. fontSize: 39.sp,
  241. fontWeight: FontWeight.bold,
  242. ),
  243. ),
  244. ],
  245. )),
  246. ),
  247. Text("¥${storeItem.originalAmountText}",
  248. style: TextStyle(
  249. color: "#AFAFAF".color,
  250. fontSize: 14.sp,
  251. decoration: TextDecoration.lineThrough,
  252. decorationColor: "#AFAFAF".color)),
  253. Container(
  254. padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.w),
  255. decoration: isSelect
  256. ? BoxDecoration(
  257. gradient: LinearGradient(
  258. colors: ['#9075FF'.color, '#4366FF'.color],
  259. begin: Alignment.topCenter,
  260. end: Alignment.bottomCenter,
  261. stops: const [0.0, 1.0],
  262. ),
  263. borderRadius: BorderRadius.circular(12.w),
  264. )
  265. : BoxDecoration(
  266. color: "#7688B1".toColor(),
  267. borderRadius: BorderRadius.circular(12.w),
  268. ),
  269. child: Row(
  270. mainAxisSize: MainAxisSize.min,
  271. children: [
  272. SizedBox(
  273. width: 16.w,
  274. height: 16.w,
  275. child: Assets.images.iconStoreGoodFlash.image(),
  276. ),
  277. Text(
  278. "${storeItem.authValue}电量",
  279. style: TextStyle(
  280. color: Colors.white,
  281. fontSize: 13.sp,
  282. fontWeight: FontWeight.bold,
  283. ),
  284. ),
  285. ],
  286. ),
  287. ),
  288. ],
  289. );
  290. }
  291. Widget _buildPaymentWays() {
  292. return Container(
  293. margin: EdgeInsets.only(top: 10.w),
  294. child: ExpansionTile(
  295. initiallyExpanded: true,
  296. onExpansionChanged: (value) {
  297. controller.isPaymentWayExpanded.value = value;
  298. },
  299. title: Padding(
  300. padding: EdgeInsets.symmetric(horizontal: 12.w),
  301. child: Row(
  302. children: [
  303. Text("支付方式",
  304. style: TextStyle(color: Colors.white, fontSize: 14.sp)),
  305. const Spacer(),
  306. Obx(() =>
  307. controller.currentSelectedPaymentWay.value?._icon ??
  308. Container()),
  309. Container(
  310. margin: EdgeInsets.only(left: 6.w, right: 4.w),
  311. child: Obx(() => Text(
  312. controller.currentSelectedPaymentWay.value?.title ?? "",
  313. style: TextStyle(color: Colors.white, fontSize: 14.sp))),
  314. ),
  315. Obx(() => controller.isPaymentWayExpanded.value
  316. ? Assets.images.iconArrowUpWhite
  317. .image(width: 16.w, height: 16.w)
  318. : Assets.images.iconArrowDownWhite
  319. .image(width: 16.w, height: 16.w)),
  320. ],
  321. ),
  322. ),
  323. showTrailingIcon: false,
  324. shape: const RoundedRectangleBorder(
  325. side: BorderSide(color: Colors.transparent),
  326. ),
  327. collapsedShape: const RoundedRectangleBorder(
  328. side: BorderSide(color: Colors.transparent),
  329. ),
  330. minTileHeight: 15.w,
  331. tilePadding: EdgeInsets.zero,
  332. children: [
  333. Obx(() => ListView.builder(
  334. shrinkWrap: true,
  335. physics: const NeverScrollableScrollPhysics(),
  336. padding: EdgeInsets.symmetric(horizontal: 12.w),
  337. itemBuilder: _buildPaymentWayItem,
  338. itemCount: controller.paymentWays.length,
  339. scrollDirection: Axis.vertical,
  340. )),
  341. ],
  342. ),
  343. );
  344. }
  345. Widget _buildPaymentWayItem(BuildContext context, int index) {
  346. PaymentWay paymentWay = controller.paymentWays[index];
  347. return GestureDetector(
  348. onTap: () => controller.onPaymentWayItemClick(paymentWay),
  349. child: Padding(
  350. padding: EdgeInsets.symmetric(vertical: 6.w),
  351. child: Row(
  352. children: [
  353. paymentWay._icon,
  354. Expanded(
  355. child: Container(
  356. margin: EdgeInsets.only(left: 8.w),
  357. child: Text(controller.paymentWays[index].title,
  358. style: TextStyle(color: Colors.white, fontSize: 14.sp)),
  359. ),
  360. ),
  361. Obx(() => SizedBox(
  362. width: 20.w,
  363. height: 20.w,
  364. child: controller.currentSelectedPaymentWay.value?.id ==
  365. paymentWay.id
  366. ? Assets.images.iconSelectTrue.image()
  367. : Assets.images.iconSelectFalse.image())),
  368. ],
  369. ),
  370. ),
  371. );
  372. }
  373. Widget _buildService() {
  374. return Container(
  375. margin: EdgeInsets.only(left: 12.w, right: 12.w, top: 30.w),
  376. child: Column(
  377. children: [
  378. Row(
  379. children: [
  380. Container(
  381. width: 4.w,
  382. height: 16.h,
  383. decoration: BoxDecoration(
  384. color: Colors.white,
  385. borderRadius: BorderRadius.circular(2),
  386. gradient: LinearGradient(
  387. colors: [
  388. '#357AFF'.toColor(),
  389. '#E389FF'.toColor(),
  390. '#ffffff'.toColor()
  391. ],
  392. begin: Alignment.topCenter,
  393. end: Alignment.bottomCenter,
  394. stops: const [0.0, 0.5, 1.0],
  395. ),
  396. ),
  397. ),
  398. SizedBox(
  399. width: 6.w,
  400. ),
  401. Text(
  402. "多种专属服务·高效辅助办公",
  403. style: TextStyle(
  404. fontSize: 15.sp,
  405. color: Colors.white,
  406. fontWeight: FontWeight.w500,
  407. ),
  408. ),
  409. ],
  410. ),
  411. Container(
  412. margin: EdgeInsets.only(top: 16.w),
  413. child: Row(
  414. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  415. children: [
  416. _buildServiceItem(
  417. Assets.images.iconStoreServiceSum.image(),
  418. "智能谈话总结",
  419. ),
  420. _buildServiceItem(
  421. Assets.images.iconStoreServiceRemain.image(),
  422. "待办任务处理",
  423. ),
  424. _buildServiceItem(
  425. Assets.images.iconStoreServiceAdvice.image(),
  426. "专业工作建议",
  427. ),
  428. _buildServiceItem(
  429. Assets.images.iconStoreServiceDeal.image(),
  430. "处理交代事宜",
  431. ),
  432. ],
  433. ),
  434. )
  435. ],
  436. ),
  437. );
  438. }
  439. Widget _buildServiceItem(Image icon, String title) {
  440. return Column(
  441. children: [
  442. SizedBox(
  443. width: 32.w,
  444. child: icon,
  445. ),
  446. SizedBox(
  447. height: 2.h,
  448. ),
  449. Text(
  450. title,
  451. style: TextStyle(
  452. color: ColorName.white.withOpacity(0.8),
  453. fontSize: 11.sp,
  454. ),
  455. ),
  456. ],
  457. );
  458. }
  459. Container _buildRule() {
  460. return Container(
  461. margin: EdgeInsets.only(top: 26.w, left: 12.w, right: 12.w),
  462. width: double.infinity,
  463. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
  464. decoration: BoxDecoration(
  465. color: "#40567D".toColor().withOpacity(0.2),
  466. borderRadius: BorderRadius.circular(8),
  467. ),
  468. child: Column(
  469. crossAxisAlignment: CrossAxisAlignment.start,
  470. children: [
  471. Text(
  472. "扣电规则",
  473. style: TextStyle(
  474. fontSize: 12,
  475. fontWeight: FontWeight.w500,
  476. color: Colors.white.withOpacity(0.6),
  477. ),
  478. ),
  479. SizedBox(
  480. height: 6.h,
  481. ),
  482. Text(
  483. "1、小听每听5分钟扣1电量,不满5分钟按5分钟算。",
  484. style: TextStyle(
  485. fontSize: 12,
  486. color: Colors.white.withOpacity(0.6),
  487. ),
  488. ),
  489. Text(
  490. "2、大文件、超大文件生成新的总结,每次扣1电量。",
  491. style: TextStyle(
  492. fontSize: 12,
  493. fontWeight: FontWeight.w500,
  494. color: Colors.white.withOpacity(0.6),
  495. ),
  496. ),
  497. Text(
  498. "3、用大文件和小听对话,每次对话扣1电量。",
  499. style: TextStyle(
  500. fontSize: 12,
  501. fontWeight: FontWeight.w500,
  502. color: Colors.white.withOpacity(0.6),
  503. ),
  504. ),
  505. ],
  506. ),
  507. );
  508. }
  509. Widget _buildBottomButton() {
  510. return Container(
  511. width: double.infinity,
  512. padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.w),
  513. decoration: BoxDecoration(
  514. color: "#283B58".color,
  515. borderRadius: BorderRadius.only(
  516. topLeft: Radius.circular(12.w),
  517. topRight: Radius.circular(12.w),
  518. ),
  519. ),
  520. child: GestureDetector(
  521. onTap: () => controller.onBuyClick(),
  522. child: ShimmerEffect(
  523. child: Container(
  524. height: 48.w,
  525. alignment: Alignment.center,
  526. decoration: BoxDecoration(
  527. gradient: LinearGradient(
  528. colors: ['#9075FF'.color, '#4366FF'.color],
  529. begin: Alignment.centerLeft,
  530. end: Alignment.centerRight,
  531. stops: const [0.0, 1.0],
  532. ),
  533. borderRadius: BorderRadius.circular(8.w),
  534. ),
  535. child: _buildBuyButton(),
  536. ),
  537. ),
  538. ),
  539. );
  540. }
  541. Widget _buildBuyButton() {
  542. return Obx(() => Text(
  543. "立即购买 ¥${controller.currentSelectedStoreItem.value?.amountText ?? ''}",
  544. style: TextStyle(
  545. fontWeight: FontWeight.bold,
  546. fontSize: 16.sp,
  547. color: Colors.white),
  548. ));
  549. }
  550. }
  551. extension on PaymentWay {
  552. get _icon {
  553. switch (payMethod) {
  554. // case PayMethod.alipay:
  555. // return Assets.images.iconStoreAlipay.image(width: 20.w, height: 20.w);
  556. // case PayMethod.wechat:
  557. // return Assets.images.iconStoreWechatPay
  558. // .image(width: 20.w, height: 20.w);
  559. default:
  560. return Container();
  561. }
  562. }
  563. }