view.dart 18 KB

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