view.dart 18 KB

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