account_view.dart 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import 'package:flutter_screenutil/flutter_screenutil.dart';
  4. import 'package:flutter_svg/flutter_svg.dart';
  5. import 'package:get/get.dart';
  6. import 'package:nomo/app/base/base_view.dart';
  7. import 'package:nomo/app/widgets/click_opacity.dart';
  8. import 'package:nomo/app/widgets/ix_app_bar.dart';
  9. import 'package:nomo/app/widgets/submit_btn.dart';
  10. import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
  11. import '../../../../config/theme/dark_theme_colors.dart';
  12. import '../../../../config/translations/strings_enum.dart';
  13. import '../../../../utils/device_manager.dart';
  14. import '../../../components/ix_snackbar.dart';
  15. import '../../../constants/assets.dart';
  16. import '../../../constants/iconfont/iconfont.dart';
  17. import '../../../dialog/all_dialog.dart';
  18. import '../../../routes/app_pages.dart';
  19. import '../../../widgets/ix_image.dart';
  20. import '../controllers/account_controller.dart';
  21. class AccountView extends BaseView<AccountController> {
  22. const AccountView({super.key});
  23. @override
  24. PreferredSizeWidget? get appBar => IXAppBar(title: Strings.account.tr);
  25. @override
  26. Widget buildContent(BuildContext context) {
  27. return Obx(() {
  28. final isPremium = controller.isPremium;
  29. return SingleChildScrollView(
  30. padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 10.w),
  31. child: Column(
  32. crossAxisAlignment: CrossAxisAlignment.start,
  33. children: [
  34. // Account 信息卡片
  35. // _buildAccountCard(isPremium),
  36. _buildAccountSection(),
  37. // Security Section
  38. _buildSectionHeader(Strings.securitySection.tr),
  39. _buildSecuritySection(),
  40. 20.verticalSpaceFromWidth,
  41. // 底部按钮
  42. _buildBottomButtons(isPremium),
  43. 20.verticalSpaceFromWidth,
  44. ],
  45. ),
  46. );
  47. });
  48. }
  49. /// 构建账户信息卡片
  50. Widget _buildAccountCard(bool isPremium) {
  51. return Container(
  52. decoration: BoxDecoration(
  53. color: Get.reactiveTheme.highlightColor,
  54. borderRadius: BorderRadius.circular(12.r),
  55. ),
  56. child: Column(
  57. children: [
  58. // Account 条目
  59. _buildAccountItem(isPremium),
  60. _buildDivider(),
  61. // UID 条目
  62. _buildUIDItem(),
  63. _buildDivider(),
  64. // Time/Term 条目
  65. if (isPremium) _buildValidTermItem() else _buildFreeTimeItem(),
  66. _buildDivider(),
  67. // Premium 功能列表
  68. _buildPremiumFeatures(isPremium),
  69. ],
  70. ),
  71. );
  72. }
  73. /// Account 条目
  74. Widget _buildAccountItem(bool isPremium) {
  75. return Container(
  76. height: 56.w,
  77. padding: EdgeInsets.symmetric(horizontal: 16.w),
  78. child: Row(
  79. children: [
  80. // 图标
  81. Container(
  82. width: 30.w,
  83. height: 30.w,
  84. decoration: BoxDecoration(
  85. color: Get.reactiveTheme.shadowColor,
  86. borderRadius: BorderRadius.circular(8.r),
  87. ),
  88. child: Icon(IconFont.icon29, size: 20.w, color: Colors.white),
  89. ),
  90. 10.horizontalSpace,
  91. // 标题
  92. Expanded(
  93. child: Text(
  94. Strings.account.tr,
  95. style: TextStyle(
  96. fontSize: 14.sp,
  97. color: Get.reactiveTheme.textTheme.bodyLarge!.color,
  98. fontWeight: FontWeight.w400,
  99. ),
  100. ),
  101. ),
  102. // 徽章
  103. IXImage(
  104. source: isPremium ? Assets.premium : Assets.free,
  105. width: isPremium ? 92.w : 64.w,
  106. height: 28.w,
  107. sourceType: ImageSourceType.asset,
  108. ),
  109. ],
  110. ),
  111. );
  112. }
  113. /// UID 条目
  114. Widget _buildUIDItem() {
  115. return ClickOpacity(
  116. onTap: () {
  117. Clipboard.setData(ClipboardData(text: controller.uid));
  118. Get.snackbar(Strings.copied.tr, 'UID ${Strings.copied.tr}');
  119. },
  120. child: Container(
  121. height: 56.w,
  122. padding: EdgeInsets.symmetric(horizontal: 16.w),
  123. child: Row(
  124. children: [
  125. // 图标
  126. Container(
  127. width: 30.w,
  128. height: 30.w,
  129. decoration: BoxDecoration(
  130. color: Get.reactiveTheme.shadowColor,
  131. borderRadius: BorderRadius.circular(8.r),
  132. ),
  133. child: Icon(IconFont.icon14, size: 20.w, color: Colors.white),
  134. ),
  135. 10.horizontalSpace,
  136. // UID
  137. Expanded(
  138. child: Text(
  139. controller.uid,
  140. style: TextStyle(
  141. fontSize: 14.sp,
  142. color: Get.reactiveTheme.textTheme.bodyLarge!.color,
  143. fontWeight: FontWeight.w400,
  144. ),
  145. ),
  146. ),
  147. // 复制图标
  148. Icon(
  149. IconFont.icon57,
  150. size: 20.w,
  151. color: Get.reactiveTheme.hintColor,
  152. ),
  153. ],
  154. ),
  155. ),
  156. );
  157. }
  158. /// Free Time 条目
  159. Widget _buildFreeTimeItem() {
  160. return Container(
  161. height: 56.w,
  162. padding: EdgeInsets.symmetric(horizontal: 16.w),
  163. child: Row(
  164. children: [
  165. // 图标
  166. Container(
  167. width: 30.w,
  168. height: 30.w,
  169. decoration: BoxDecoration(
  170. color: Get.reactiveTheme.shadowColor,
  171. borderRadius: BorderRadius.circular(8.r),
  172. ),
  173. child: Icon(IconFont.icon30, size: 20.w, color: Colors.white),
  174. ),
  175. 10.horizontalSpace,
  176. // 标题
  177. Expanded(
  178. child: Text(
  179. Strings.freeTime.tr,
  180. style: TextStyle(
  181. fontSize: 14.sp,
  182. color: Get.reactiveTheme.textTheme.bodyLarge!.color,
  183. fontWeight: FontWeight.w400,
  184. ),
  185. ),
  186. ),
  187. // 时间
  188. Text(
  189. controller.freeTime,
  190. style: TextStyle(
  191. fontSize: 13.sp,
  192. color: DarkThemeColors.validTermColor,
  193. fontWeight: FontWeight.w400,
  194. ),
  195. ),
  196. ],
  197. ),
  198. );
  199. }
  200. /// Valid Term 条目
  201. Widget _buildValidTermItem() {
  202. return Container(
  203. height: 56.w,
  204. padding: EdgeInsets.symmetric(horizontal: 16.w),
  205. child: Row(
  206. children: [
  207. // 图标
  208. Container(
  209. width: 30.w,
  210. height: 30.w,
  211. decoration: BoxDecoration(
  212. color: Get.reactiveTheme.shadowColor,
  213. borderRadius: BorderRadius.circular(8.r),
  214. ),
  215. child: Icon(IconFont.icon30, size: 20.w, color: Colors.white),
  216. ),
  217. 10.horizontalSpace,
  218. // 标题
  219. Expanded(
  220. child: Text(
  221. Strings.validTerm.tr,
  222. style: TextStyle(
  223. fontSize: 14.sp,
  224. color: Get.reactiveTheme.textTheme.bodyLarge!.color,
  225. fontWeight: FontWeight.w400,
  226. ),
  227. ),
  228. ),
  229. // 有效期
  230. Text(
  231. controller.validTerm,
  232. style: TextStyle(
  233. fontSize: 13.sp,
  234. color: Get.reactiveTheme.primaryColor,
  235. fontWeight: FontWeight.w400,
  236. ),
  237. ),
  238. ],
  239. ),
  240. );
  241. }
  242. Widget _buildPremiumFeatures(bool isPremium) {
  243. return Padding(
  244. padding: EdgeInsets.symmetric(horizontal: 14.w),
  245. child: Column(
  246. children: [
  247. _buildFeatureItem(IconFont.icon60, Strings.unlockAllFreeLocations.tr),
  248. _buildFeatureItem(IconFont.icon61, Strings.unlockSmartMode.tr),
  249. _buildFeatureItem(IconFont.icon62, Strings.unlockMultiHopMode.tr),
  250. _buildFeatureItem(
  251. IconFont.icon63,
  252. Strings.premiumCanShareXDevices.tr,
  253. ),
  254. _buildFeatureItem(
  255. IconFont.icon64,
  256. Strings.ownYourOwnPrivateServer.tr,
  257. ),
  258. _buildFeatureItem(IconFont.icon65, Strings.closeAds.tr),
  259. ],
  260. ),
  261. );
  262. }
  263. Widget _buildFeatureItem(IconData icon, String title) {
  264. return SizedBox(
  265. height: 44.w,
  266. child: Row(
  267. children: [
  268. Icon(icon, color: DarkThemeColors.subscriptionColor, size: 24.w),
  269. 12.horizontalSpace,
  270. Expanded(
  271. child: Text(
  272. title,
  273. style: TextStyle(
  274. fontSize: 13.sp,
  275. color: Get.reactiveTheme.hintColor,
  276. ),
  277. ),
  278. ),
  279. Container(
  280. width: 20.w,
  281. height: 20.w,
  282. decoration: BoxDecoration(
  283. shape: BoxShape.circle,
  284. color: DarkThemeColors.subscriptionSelectColor,
  285. ),
  286. child: Icon(Icons.check, color: Colors.white, size: 12.w),
  287. ),
  288. ],
  289. ),
  290. );
  291. }
  292. /// 底部按钮
  293. Widget _buildBottomButtons(bool isPremium) {
  294. if (isPremium) {
  295. return Column(
  296. children: [
  297. SubmitButton(
  298. text: Strings.changeSubscription.tr,
  299. bgColor: Get.reactiveTheme.highlightColor,
  300. textColor: DarkThemeColors.subscriptionColor,
  301. onPressed: () {
  302. // TODO: 修改订阅
  303. },
  304. ),
  305. 20.verticalSpaceFromWidth,
  306. // Device Authorization 按钮
  307. _buildSecondaryButton(
  308. text:
  309. '${Strings.deviceAuthorization.tr} (${controller.deviceCount}/${controller.maxDeviceCount})',
  310. icon: IconFont.icon11,
  311. onTap: () {
  312. // TODO: 设备授权
  313. },
  314. ),
  315. 10.verticalSpaceFromWidth,
  316. // 提示文字
  317. Text(
  318. Strings.youCanAuthorizeOtherDevices.trParams({
  319. 'current': controller.deviceCount.toString(),
  320. 'max': controller.maxDeviceCount.toString(),
  321. }),
  322. textAlign: TextAlign.center,
  323. style: TextStyle(
  324. fontSize: 12.sp,
  325. color: Get.reactiveTheme.hintColor,
  326. height: 1.5,
  327. ),
  328. ),
  329. ],
  330. );
  331. } else {
  332. return Column(
  333. children: [
  334. // Upgrade to Premium 按钮
  335. SubmitButton(
  336. text: Strings.upgradeToPremium.tr,
  337. bgColor: Get.reactiveTheme.highlightColor,
  338. textColor: DarkThemeColors.subscriptionColor,
  339. onPressed: () {
  340. // TODO: 修改订阅
  341. },
  342. ),
  343. 20.verticalSpaceFromWidth,
  344. // Activate Pre Code 按钮
  345. _buildSecondaryButton(
  346. text: Strings.bindEmailMemberBenefits.tr,
  347. icon: IconFont.icon23,
  348. onTap: () {
  349. // TODO: 绑定邮箱
  350. AllDialog.showBindEmailMemberBenefits();
  351. },
  352. ),
  353. 10.verticalSpaceFromWidth,
  354. // 提示文字
  355. Text(
  356. Strings.bindingAccountEmailProtectsPreRights.tr,
  357. textAlign: TextAlign.center,
  358. style: TextStyle(
  359. fontSize: 12.sp,
  360. color: Get.reactiveTheme.hintColor,
  361. ),
  362. ),
  363. ],
  364. );
  365. }
  366. }
  367. /// 次要按钮(黑色边框)
  368. Widget _buildSecondaryButton({
  369. required String text,
  370. required IconData icon,
  371. required VoidCallback onTap,
  372. }) {
  373. return ClickOpacity(
  374. onTap: onTap,
  375. child: Container(
  376. height: 52.w,
  377. decoration: BoxDecoration(
  378. border: Border.all(color: Get.reactiveTheme.dividerColor, width: 1.w),
  379. borderRadius: BorderRadius.circular(12.r),
  380. ),
  381. child: Row(
  382. mainAxisAlignment: MainAxisAlignment.center,
  383. children: [
  384. Text(
  385. text,
  386. style: TextStyle(
  387. fontSize: 16.sp,
  388. color: DarkThemeColors.subscriptionColor,
  389. fontWeight: FontWeight.w400,
  390. ),
  391. ),
  392. SizedBox(width: 8.w),
  393. Icon(icon, size: 20.w, color: DarkThemeColors.subscriptionColor),
  394. ],
  395. ),
  396. ),
  397. );
  398. }
  399. /// 构建分割线
  400. Widget _buildDivider() {
  401. return Divider(height: 1.w, color: Get.reactiveTheme.dividerColor);
  402. }
  403. /// 构建分组标题
  404. Widget _buildSectionHeader(String title) {
  405. return Padding(
  406. padding: EdgeInsets.symmetric(vertical: 10.w),
  407. child: Text(
  408. title,
  409. style: TextStyle(
  410. fontSize: 16.sp,
  411. color: Get.reactiveTheme.hintColor,
  412. fontWeight: FontWeight.w500,
  413. ),
  414. ),
  415. );
  416. }
  417. /// Account 分组
  418. Widget _buildAccountSection() {
  419. return Obx(() {
  420. final isPremium = controller.isPremium;
  421. final isGuest = controller.isGuest;
  422. return Container(
  423. decoration: BoxDecoration(
  424. color: Get.reactiveTheme.highlightColor,
  425. borderRadius: BorderRadius.circular(12.r),
  426. ),
  427. child: Column(
  428. children: [
  429. if (!isGuest)
  430. _buildSettingItem(
  431. icon: IconFont.icon29,
  432. iconColor: Get.reactiveTheme.shadowColor,
  433. title: Strings.account.tr,
  434. trailing: IXImage(
  435. source: isPremium ? Assets.premium : Assets.free,
  436. width: isPremium ? 92.w : 64.w,
  437. height: 28.w,
  438. sourceType: ImageSourceType.asset,
  439. ),
  440. onTap: () {
  441. Get.toNamed(Routes.ACCOUNT);
  442. },
  443. ),
  444. if (!isGuest) _buildDivider(),
  445. _buildSettingItem(
  446. icon: IconFont.icon14,
  447. iconColor: Get.reactiveTheme.shadowColor,
  448. title:
  449. 'UID ${DeviceManager.getCacheDeviceId().length > 12 ? '${DeviceManager.getCacheDeviceId().substring(0, 6)}***${DeviceManager.getCacheDeviceId().substring(DeviceManager.getCacheDeviceId().length - 6)}' : DeviceManager.getCacheDeviceId()}',
  450. showInfo: true,
  451. trailing: ClickOpacity(
  452. onTap: () {
  453. Clipboard.setData(
  454. ClipboardData(text: DeviceManager.getCacheDeviceId()),
  455. );
  456. IXSnackBar.showIXSnackBar(
  457. title: Strings.copied.tr,
  458. message: Strings.copied.tr,
  459. );
  460. },
  461. child: Icon(
  462. IconFont.icon57,
  463. size: 20.w,
  464. color: Get.reactiveTheme.hintColor,
  465. ),
  466. ),
  467. onTap: () {},
  468. onInfoTap: () {
  469. AllDialog.showUidInfo();
  470. },
  471. ),
  472. _buildDivider(),
  473. // 根据用户类型显示不同的时间信息
  474. if (isPremium) ...[
  475. // _buildSettingItem(
  476. // icon: IconFont.icon23,
  477. // iconColor: Get.reactiveTheme.shadowColor,
  478. // title: Strings.myPreCode.tr,
  479. // trailing: Row(
  480. // mainAxisSize: MainAxisSize.min,
  481. // children: [
  482. // Text(
  483. // '123***ADZ',
  484. // style: TextStyle(
  485. // fontSize: 13.sp,
  486. // color: Get.reactiveTheme.hintColor,
  487. // ),
  488. // ),
  489. // SizedBox(width: 4.w),
  490. // Icon(
  491. // IconFont.icon02,
  492. // size: 20.w,
  493. // color: Get.reactiveTheme.hintColor,
  494. // ),
  495. // ],
  496. // ),
  497. // onTap: () {
  498. // // TODO: 跳转到Pre Code页面
  499. // Get.toNamed(Routes.PRECODE);
  500. // },
  501. // ),
  502. // _buildDivider(),
  503. _buildSettingItem(
  504. icon: IconFont.icon30,
  505. iconColor: Get.reactiveTheme.shadowColor,
  506. title: Strings.validTerm.tr,
  507. trailing: Text(
  508. 'Year / 2026-12-12',
  509. style: TextStyle(
  510. fontSize: 13.sp,
  511. color: Get.reactiveTheme.primaryColor,
  512. fontWeight: FontWeight.w500,
  513. ),
  514. ),
  515. onTap: () {
  516. // TODO: 跳转到有效期详情页面
  517. },
  518. ),
  519. ] else ...[
  520. _buildSettingItem(
  521. icon: IconFont.icon30,
  522. iconColor: Get.reactiveTheme.shadowColor,
  523. title: Strings.freeTime.tr,
  524. trailing: Text(
  525. '01:60:59 / Days',
  526. style: TextStyle(
  527. fontSize: 14.sp,
  528. color: const Color(0xFFFFCC00),
  529. fontWeight: FontWeight.w500,
  530. ),
  531. ),
  532. ),
  533. ],
  534. // _buildDivider(),
  535. // _buildSettingItem(
  536. // icon: IconFont.icon31,
  537. // iconColor: Get.reactiveTheme.shadowColor,
  538. // title: Strings.deviceAuthorization.tr,
  539. // trailing: Row(
  540. // mainAxisSize: MainAxisSize.min,
  541. // children: [
  542. // Text(
  543. // isPremium ? '1/4' : '0/1',
  544. // style: TextStyle(
  545. // fontSize: 13.sp,
  546. // color: Get.reactiveTheme.hintColor,
  547. // ),
  548. // ),
  549. // SizedBox(width: 4.w),
  550. // Icon(
  551. // IconFont.icon02,
  552. // size: 20.w,
  553. // color: Get.reactiveTheme.hintColor,
  554. // ),
  555. // ],
  556. // ),
  557. // onTap: () {
  558. // Get.toNamed(Routes.DEVICEAUTH);
  559. // },
  560. // ),
  561. ],
  562. ),
  563. );
  564. });
  565. }
  566. /// Security 分组
  567. Widget _buildSecuritySection() {
  568. return Container(
  569. decoration: BoxDecoration(
  570. color: Get.reactiveTheme.highlightColor,
  571. borderRadius: BorderRadius.circular(12.r),
  572. ),
  573. child: Column(
  574. children: [
  575. _buildSettingItem(
  576. icon: IconFont.icon11,
  577. iconColor: DarkThemeColors.settingSecurityLinearGradientStartColor,
  578. iconGradient: LinearGradient(
  579. colors: [
  580. DarkThemeColors.settingSecurityLinearGradientStartColor,
  581. DarkThemeColors.settingSecurityLinearGradientEndColor,
  582. ],
  583. begin: Alignment.topCenter,
  584. end: Alignment.bottomCenter,
  585. ),
  586. title: Strings.changePassword.tr,
  587. onTap: () {
  588. // TODO: 跳转到忘记密码页面
  589. Get.toNamed(Routes.FORGOTPWD);
  590. },
  591. ),
  592. _buildDivider(),
  593. _buildSettingItem(
  594. icon: IconFont.icon40,
  595. iconColor: DarkThemeColors.settingSecurityLinearGradientStartColor,
  596. iconGradient: LinearGradient(
  597. colors: [
  598. DarkThemeColors.settingSecurityLinearGradientStartColor,
  599. DarkThemeColors.settingSecurityLinearGradientEndColor,
  600. ],
  601. begin: Alignment.topCenter,
  602. end: Alignment.bottomCenter,
  603. ),
  604. title: Strings.deleteAccount.tr,
  605. onTap: () {
  606. AllDialog.showDeleteAccountConfirm(() {
  607. // 退出登录
  608. controller.handleDeleteAccount();
  609. });
  610. },
  611. ),
  612. _buildDivider(),
  613. _buildSettingItem(
  614. icon: IconFont.icon66,
  615. iconColor: DarkThemeColors.settingSecurityLinearGradientStartColor,
  616. iconGradient: LinearGradient(
  617. colors: [
  618. DarkThemeColors.settingSecurityLinearGradientStartColor,
  619. DarkThemeColors.settingSecurityLinearGradientEndColor,
  620. ],
  621. begin: Alignment.topCenter,
  622. end: Alignment.bottomCenter,
  623. ),
  624. title: Strings.logout.tr,
  625. titleColor: const Color(0xFFEF0000),
  626. onTap: () {
  627. AllDialog.showLogoutConfirm(() {
  628. // 退出登录
  629. controller.handleLogout();
  630. });
  631. },
  632. ),
  633. ],
  634. ),
  635. );
  636. }
  637. /// 构建设置项
  638. Widget _buildSettingItem({
  639. IconData? icon,
  640. String? svgPath,
  641. required Color iconColor,
  642. Gradient? iconGradient,
  643. required String title,
  644. Color? titleColor,
  645. bool showInfo = false,
  646. Widget? trailing,
  647. VoidCallback? onTap,
  648. VoidCallback? onInfoTap,
  649. }) {
  650. // 确保至少提供了 icon 或 svgPath 之一
  651. assert(
  652. icon != null || svgPath != null,
  653. 'Must provide either icon or svgPath',
  654. );
  655. return ClickOpacity(
  656. onTap: onTap,
  657. child: Container(
  658. height: 56.w,
  659. padding: EdgeInsets.symmetric(horizontal: 14.w),
  660. child: Row(
  661. children: [
  662. // 图标
  663. Container(
  664. width: 30.w,
  665. height: 30.w,
  666. decoration: BoxDecoration(
  667. gradient: iconGradient,
  668. color: iconGradient == null ? iconColor : null,
  669. borderRadius: BorderRadius.circular(8.r),
  670. ),
  671. child: svgPath != null
  672. ? Padding(
  673. padding: EdgeInsets.all(5.w),
  674. child: SvgPicture.asset(
  675. svgPath,
  676. width: 20.w,
  677. height: 20.w,
  678. colorFilter: const ColorFilter.mode(
  679. Colors.white,
  680. BlendMode.srcIn,
  681. ),
  682. ),
  683. )
  684. : Icon(icon!, size: 20.w, color: Colors.white),
  685. ),
  686. 10.horizontalSpace,
  687. // 标题
  688. Expanded(
  689. child: Row(
  690. children: [
  691. Text(
  692. title,
  693. style: TextStyle(
  694. fontSize: 14.sp,
  695. color:
  696. titleColor ??
  697. Get.reactiveTheme.textTheme.bodyLarge!.color,
  698. fontWeight: FontWeight.w500,
  699. ),
  700. ),
  701. 4.horizontalSpace,
  702. if (showInfo)
  703. ClickOpacity(
  704. onTap: onInfoTap,
  705. child: Icon(
  706. IconFont.icon59,
  707. size: 20.w,
  708. color: Colors.white,
  709. ),
  710. ),
  711. ],
  712. ),
  713. ),
  714. // 右侧内容
  715. if (trailing != null) trailing,
  716. ],
  717. ),
  718. ),
  719. );
  720. }
  721. }