view.dart 18 KB

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