setting_view.dart 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. import 'dart:io';
  2. import 'package:date_format/date_format.dart';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter/services.dart';
  6. import 'package:flutter_screenutil/flutter_screenutil.dart';
  7. import 'package:flutter_svg/flutter_svg.dart';
  8. import 'package:get/get.dart';
  9. import 'package:nomo/app/base/base_view.dart';
  10. import 'package:nomo/app/constants/assets.dart';
  11. import 'package:nomo/app/dialog/all_dialog.dart';
  12. import 'package:nomo/app/widgets/click_opacity.dart';
  13. import 'package:nomo/app/widgets/ix_image.dart';
  14. import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
  15. import 'package:nomo/utils/device_manager.dart';
  16. import '../../../constants/enums.dart';
  17. import '../../../data/sp/ix_sp.dart';
  18. import '../../../../config/theme/dark_theme_colors.dart';
  19. import '../../../../config/translations/localization_service.dart';
  20. import '../../../../config/translations/strings_enum.dart';
  21. import '../../../../utils/system_helper.dart';
  22. import '../../../components/ix_snackbar.dart';
  23. import '../../../constants/iconfont/iconfont.dart';
  24. import '../../../routes/app_pages.dart';
  25. import '../../../widgets/ix_app_bar.dart';
  26. import '../controllers/setting_controller.dart';
  27. class SettingView extends BaseView<SettingController> {
  28. const SettingView({super.key});
  29. @override
  30. PreferredSizeWidget? get appBar => IXAppBar(title: Strings.settings.tr);
  31. @override
  32. Widget buildContent(BuildContext context) {
  33. return CustomScrollView(
  34. slivers: [
  35. // Account Section
  36. _buildSectionHeader(Strings.account.tr),
  37. _buildLoginSection(),
  38. _buildAccountSection(),
  39. // Network Section
  40. _buildSectionHeader(Strings.networkSection.tr),
  41. _buildNetworkSection(),
  42. // APP Section
  43. _buildSectionHeader('APP'),
  44. _buildAppSection(),
  45. // Security Section
  46. // _buildSectionHeader(Strings.securitySection.tr),
  47. // _buildSecuritySection(),
  48. // 底部间距
  49. SliverSafeArea(sliver: SliverToBoxAdapter(child: 0.verticalSpace)),
  50. ],
  51. );
  52. }
  53. /// 构建分组标题
  54. Widget _buildSectionHeader(String title) {
  55. return SliverToBoxAdapter(
  56. child: Padding(
  57. padding: EdgeInsets.fromLTRB(14.w, 10.w, 14.w, 10.w),
  58. child: Text(
  59. title,
  60. style: TextStyle(
  61. fontSize: 16.sp,
  62. color: Get.reactiveTheme.hintColor,
  63. fontWeight: FontWeight.w500,
  64. ),
  65. ),
  66. ),
  67. );
  68. }
  69. /// 构建登录分组
  70. Widget _buildLoginSection() {
  71. return SliverToBoxAdapter(
  72. child: Obx(() {
  73. if (!controller.apiController.isGuest) {
  74. return SizedBox.shrink();
  75. }
  76. return Container(
  77. margin: EdgeInsets.only(left: 14.w, right: 14.w, bottom: 10.w),
  78. decoration: BoxDecoration(
  79. color: Get.reactiveTheme.highlightColor,
  80. borderRadius: BorderRadius.circular(12.r),
  81. ),
  82. child: _buildSettingItem(
  83. icon: IconFont.icon37,
  84. iconColor: Get.reactiveTheme.shadowColor,
  85. title: Strings.login.tr,
  86. trailing: Icon(
  87. IconFont.icon02,
  88. size: 20.w,
  89. color: Get.reactiveTheme.hintColor,
  90. ),
  91. onTap: () {
  92. Get.toNamed(Routes.LOGIN);
  93. },
  94. ),
  95. );
  96. }),
  97. );
  98. }
  99. /// Account 分组
  100. Widget _buildAccountSection() {
  101. return SliverToBoxAdapter(
  102. child: Obx(() {
  103. return Container(
  104. margin: EdgeInsets.symmetric(horizontal: 14.w),
  105. decoration: BoxDecoration(
  106. color: Get.reactiveTheme.highlightColor,
  107. borderRadius: BorderRadius.circular(12.r),
  108. ),
  109. child: Column(
  110. children: [
  111. _buildSettingItem(
  112. icon: IconFont.icon29,
  113. iconColor: Get.reactiveTheme.shadowColor,
  114. title: _getUserAccount().isNotEmpty
  115. ? _getUserAccount()
  116. : Strings.account.tr,
  117. trailing: Row(
  118. children: [
  119. IXImage(
  120. source: controller.apiController.userLevel == 3
  121. ? Assets.premium
  122. : controller.apiController.userLevel == 9999
  123. ? Assets.test
  124. : Assets.free,
  125. width: controller.apiController.userLevel == 3
  126. ? 92.w
  127. : 64.w,
  128. height: 28.w,
  129. sourceType: ImageSourceType.asset,
  130. ),
  131. 4.horizontalSpace,
  132. Icon(
  133. IconFont.icon02,
  134. size: 20.w,
  135. color: Get.reactiveTheme.hintColor,
  136. ),
  137. ],
  138. ),
  139. onTap: () {
  140. Get.toNamed(Routes.ACCOUNT);
  141. },
  142. ),
  143. _buildDivider(),
  144. _buildSettingItem(
  145. icon: IconFont.icon14,
  146. iconColor: Get.reactiveTheme.shadowColor,
  147. title:
  148. 'UID ${DeviceManager.getCacheDeviceId().length > 12 ? '${DeviceManager.getCacheDeviceId().substring(0, 6)}***${DeviceManager.getCacheDeviceId().substring(DeviceManager.getCacheDeviceId().length - 6)}' : DeviceManager.getCacheDeviceId()}',
  149. showInfo: true,
  150. trailing: ClickOpacity(
  151. onTap: () {
  152. Clipboard.setData(
  153. ClipboardData(text: DeviceManager.getCacheDeviceId()),
  154. );
  155. IXSnackBar.showIXSnackBar(
  156. title: Strings.copied.tr,
  157. message: Strings.copied.tr,
  158. );
  159. },
  160. child: Icon(
  161. IconFont.icon57,
  162. size: 20.w,
  163. color: Get.reactiveTheme.hintColor,
  164. ),
  165. ),
  166. onTap: () {},
  167. onInfoTap: () {
  168. AllDialog.showUidInfo();
  169. },
  170. ),
  171. _buildDivider(),
  172. // 根据用户类型显示不同的时间信息
  173. if (controller.apiController.isPremium) ...[
  174. // _buildSettingItem(
  175. // icon: IconFont.icon23,
  176. // iconColor: Get.reactiveTheme.shadowColor,
  177. // title: Strings.myPreCode.tr,
  178. // trailing: Row(
  179. // mainAxisSize: MainAxisSize.min,
  180. // children: [
  181. // Text(
  182. // '123***ADZ',
  183. // style: TextStyle(
  184. // fontSize: 13.sp,
  185. // color: Get.reactiveTheme.hintColor,
  186. // ),
  187. // ),
  188. // SizedBox(width: 4.w),
  189. // Icon(
  190. // IconFont.icon02,
  191. // size: 20.w,
  192. // color: Get.reactiveTheme.hintColor,
  193. // ),
  194. // ],
  195. // ),
  196. // onTap: () {
  197. // // TODO: 跳转到Pre Code页面
  198. // Get.toNamed(Routes.PRECODE);
  199. // },
  200. // ),
  201. // _buildDivider(),
  202. _buildSettingItem(
  203. icon: IconFont.icon30,
  204. iconColor: Get.reactiveTheme.shadowColor,
  205. title: Strings.validTerm.tr,
  206. trailing: Text(
  207. controller.apiController.validTermText,
  208. style: TextStyle(
  209. fontSize: 13.sp,
  210. color: Get.reactiveTheme.primaryColor,
  211. fontWeight: FontWeight.w500,
  212. ),
  213. ),
  214. onTap: () {
  215. // TODO: 跳转到有效期详情页面
  216. },
  217. ),
  218. ] else ...[
  219. _buildSettingItem(
  220. icon: IconFont.icon30,
  221. iconColor: Get.reactiveTheme.shadowColor,
  222. title: Strings.freeTime.tr,
  223. trailing: Text(
  224. '${controller.apiController.remainTimeFormatted} / Days',
  225. style: TextStyle(
  226. fontSize: 14.sp,
  227. color: const Color(0xFFFFCC00),
  228. fontWeight: FontWeight.w500,
  229. ),
  230. ),
  231. ),
  232. ],
  233. // _buildDivider(),
  234. // _buildSettingItem(
  235. // icon: IconFont.icon31,
  236. // iconColor: Get.reactiveTheme.shadowColor,
  237. // title: Strings.deviceAuthorization.tr,
  238. // trailing: Row(
  239. // mainAxisSize: MainAxisSize.min,
  240. // children: [
  241. // Text(
  242. // isPremium ? '1/4' : '0/1',
  243. // style: TextStyle(
  244. // fontSize: 13.sp,
  245. // color: Get.reactiveTheme.hintColor,
  246. // ),
  247. // ),
  248. // SizedBox(width: 4.w),
  249. // Icon(
  250. // IconFont.icon02,
  251. // size: 20.w,
  252. // color: Get.reactiveTheme.hintColor,
  253. // ),
  254. // ],
  255. // ),
  256. // onTap: () {
  257. // Get.toNamed(Routes.DEVICEAUTH);
  258. // },
  259. // ),
  260. ],
  261. ),
  262. );
  263. }),
  264. );
  265. }
  266. /// Network 分组
  267. Widget _buildNetworkSection() {
  268. return SliverToBoxAdapter(
  269. child: Container(
  270. margin: EdgeInsets.symmetric(horizontal: 14.w),
  271. decoration: BoxDecoration(
  272. color: Get.reactiveTheme.highlightColor,
  273. borderRadius: BorderRadius.circular(12.r),
  274. ),
  275. child: Column(
  276. children: [
  277. _buildSettingItem(
  278. icon: IconFont.icon34,
  279. iconColor: Get.reactiveTheme.primaryColor,
  280. title: Strings.routingMode.tr,
  281. trailing: Icon(
  282. IconFont.icon02,
  283. size: 20.w,
  284. color: Get.reactiveTheme.hintColor,
  285. ),
  286. onTap: () {
  287. // TODO: 跳转到路由模式页面
  288. Get.toNamed(Routes.ROUTINGMODE);
  289. },
  290. ),
  291. _buildDivider(),
  292. if (Platform.isAndroid) ...[
  293. _buildSettingItem(
  294. icon: IconFont.icon32,
  295. iconColor: Get.reactiveTheme.primaryColor,
  296. title: Strings.splitTunneling.tr,
  297. trailing: Icon(
  298. IconFont.icon02,
  299. size: 20.w,
  300. color: Get.reactiveTheme.hintColor,
  301. ),
  302. onTap: () {
  303. // TODO: 跳转到分流隧道页面
  304. Get.toNamed(Routes.SPLITTUNNELING);
  305. },
  306. ),
  307. _buildDivider(),
  308. ],
  309. // _buildSettingItem(
  310. // icon: IconFont.icon33,
  311. // iconColor: Get.reactiveTheme.primaryColor,
  312. // title: Strings.autoReconnect.tr,
  313. // trailing: Obx(
  314. // () => CupertinoSwitch(
  315. // value: controller.autoReconnect,
  316. // onChanged: (value) {
  317. // controller.autoReconnect = value;
  318. // },
  319. // activeTrackColor: Get.reactiveTheme.shadowColor,
  320. // thumbColor: Colors.white,
  321. // inactiveThumbColor: Colors.white,
  322. // inactiveTrackColor: Colors.grey,
  323. // ),
  324. // ),
  325. // ),
  326. _buildDivider(),
  327. _buildSettingItem(
  328. icon: IconFont.icon35,
  329. iconColor: Get.reactiveTheme.primaryColor,
  330. title: Strings.restoreDefault.tr,
  331. trailing: Icon(
  332. IconFont.icon02,
  333. size: 20.w,
  334. color: Get.reactiveTheme.hintColor,
  335. ),
  336. onTap: () {
  337. // TODO: 恢复默认设置
  338. },
  339. ),
  340. ],
  341. ),
  342. ),
  343. );
  344. }
  345. /// APP 分组
  346. Widget _buildAppSection() {
  347. return SliverToBoxAdapter(
  348. child: Container(
  349. margin: EdgeInsets.symmetric(horizontal: 14.w),
  350. decoration: BoxDecoration(
  351. color: Get.reactiveTheme.highlightColor,
  352. borderRadius: BorderRadius.circular(12.r),
  353. ),
  354. child: Column(
  355. children: [
  356. _buildSettingItem(
  357. icon: IconFont.icon36,
  358. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  359. iconGradient: LinearGradient(
  360. colors: [
  361. DarkThemeColors.settingAppLinearGradientStartColor,
  362. DarkThemeColors.settingAppLinearGradientEndColor,
  363. ],
  364. begin: Alignment.topCenter,
  365. end: Alignment.bottomCenter,
  366. ),
  367. title: Strings.language.tr,
  368. trailing: Row(
  369. mainAxisSize: MainAxisSize.min,
  370. children: [
  371. Text(
  372. LocalizationService.getGlobalLanguageTitle(),
  373. style: TextStyle(
  374. fontSize: 13.sp,
  375. color: Get.reactiveTheme.hintColor,
  376. ),
  377. ),
  378. 8.horizontalSpace,
  379. Icon(
  380. IconFont.icon02,
  381. size: 20.w,
  382. color: Get.reactiveTheme.hintColor,
  383. ),
  384. ],
  385. ),
  386. onTap: () {
  387. // TODO: 跳转到语言选择页面
  388. Get.toNamed(Routes.LANGUAGE);
  389. },
  390. ),
  391. _buildDivider(),
  392. _buildSettingItem(
  393. icon: IconFont.icon37,
  394. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  395. iconGradient: LinearGradient(
  396. colors: [
  397. DarkThemeColors.settingAppLinearGradientStartColor,
  398. DarkThemeColors.settingAppLinearGradientEndColor,
  399. ],
  400. begin: Alignment.topCenter,
  401. end: Alignment.bottomCenter,
  402. ),
  403. title: Strings.feedback.tr,
  404. trailing: Icon(
  405. IconFont.icon02,
  406. size: 20.w,
  407. color: Get.reactiveTheme.hintColor,
  408. ),
  409. onTap: () {
  410. // TODO: 跳转到反馈页面
  411. Get.toNamed(Routes.FEEDBACK);
  412. },
  413. ),
  414. _buildDivider(),
  415. _buildSettingItem(
  416. icon: IconFont.icon38,
  417. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  418. iconGradient: LinearGradient(
  419. colors: [
  420. DarkThemeColors.settingAppLinearGradientStartColor,
  421. DarkThemeColors.settingAppLinearGradientEndColor,
  422. ],
  423. begin: Alignment.topCenter,
  424. end: Alignment.bottomCenter,
  425. ),
  426. title: Strings.privacyPolicy.tr,
  427. trailing: Icon(
  428. IconFont.icon02,
  429. size: 20.w,
  430. color: Get.reactiveTheme.hintColor,
  431. ),
  432. onTap: () {
  433. // TODO: 跳转到隐私政策页面
  434. SystemHelper.openPrivacyTerms();
  435. },
  436. ),
  437. _buildDivider(),
  438. _buildSettingItem(
  439. icon: IconFont.icon38,
  440. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  441. iconGradient: LinearGradient(
  442. colors: [
  443. DarkThemeColors.settingAppLinearGradientStartColor,
  444. DarkThemeColors.settingAppLinearGradientEndColor,
  445. ],
  446. begin: Alignment.topCenter,
  447. end: Alignment.bottomCenter,
  448. ),
  449. title: Strings.termsOfService.tr,
  450. trailing: Icon(
  451. IconFont.icon02,
  452. size: 20.w,
  453. color: Get.reactiveTheme.hintColor,
  454. ),
  455. onTap: () {
  456. // TODO: 跳转到服务条款页面
  457. SystemHelper.openTermsOfService();
  458. },
  459. ),
  460. _buildDivider(),
  461. _buildSettingItem(
  462. svgPath: Assets.pushNotifications,
  463. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  464. iconGradient: LinearGradient(
  465. colors: [
  466. DarkThemeColors.settingAppLinearGradientStartColor,
  467. DarkThemeColors.settingAppLinearGradientEndColor,
  468. ],
  469. begin: Alignment.topCenter,
  470. end: Alignment.bottomCenter,
  471. ),
  472. title: Strings.pushNotifications.tr,
  473. trailing: Obx(
  474. () => CupertinoSwitch(
  475. value: controller.pushNotifications,
  476. onChanged: (value) {
  477. controller.showNotificationConfigPage();
  478. },
  479. activeTrackColor: Get.reactiveTheme.shadowColor,
  480. thumbColor: Colors.white,
  481. inactiveThumbColor: Colors.white,
  482. inactiveTrackColor: Colors.grey,
  483. ),
  484. ),
  485. onTap: () {
  486. controller.showNotificationConfigPage();
  487. },
  488. ),
  489. _buildDivider(),
  490. _buildSettingItem(
  491. icon: IconFont.icon39,
  492. iconColor: DarkThemeColors.settingAppLinearGradientStartColor,
  493. iconGradient: LinearGradient(
  494. colors: [
  495. DarkThemeColors.settingAppLinearGradientStartColor,
  496. DarkThemeColors.settingAppLinearGradientEndColor,
  497. ],
  498. begin: Alignment.topCenter,
  499. end: Alignment.bottomCenter,
  500. ),
  501. title: Strings.version.tr,
  502. trailing: Text(
  503. 'V1.0.0',
  504. style: TextStyle(
  505. fontSize: 13.sp,
  506. color: Get.reactiveTheme.hintColor,
  507. ),
  508. ),
  509. ),
  510. ],
  511. ),
  512. ),
  513. );
  514. }
  515. /// Security 分组
  516. Widget _buildSecuritySection() {
  517. return SliverToBoxAdapter(
  518. child: Container(
  519. margin: EdgeInsets.symmetric(horizontal: 14.w),
  520. decoration: BoxDecoration(
  521. color: Get.reactiveTheme.highlightColor,
  522. borderRadius: BorderRadius.circular(12.r),
  523. ),
  524. child: Column(
  525. children: [
  526. _buildSettingItem(
  527. icon: IconFont.icon11,
  528. iconColor:
  529. DarkThemeColors.settingSecurityLinearGradientStartColor,
  530. iconGradient: LinearGradient(
  531. colors: [
  532. DarkThemeColors.settingSecurityLinearGradientStartColor,
  533. DarkThemeColors.settingSecurityLinearGradientEndColor,
  534. ],
  535. begin: Alignment.topCenter,
  536. end: Alignment.bottomCenter,
  537. ),
  538. title: Strings.changePassword.tr,
  539. onTap: () {
  540. // TODO: 跳转到忘记密码页面
  541. Get.toNamed(Routes.FORGOTPWD);
  542. },
  543. ),
  544. _buildDivider(),
  545. _buildSettingItem(
  546. icon: IconFont.icon40,
  547. iconColor:
  548. DarkThemeColors.settingSecurityLinearGradientStartColor,
  549. iconGradient: LinearGradient(
  550. colors: [
  551. DarkThemeColors.settingSecurityLinearGradientStartColor,
  552. DarkThemeColors.settingSecurityLinearGradientEndColor,
  553. ],
  554. begin: Alignment.topCenter,
  555. end: Alignment.bottomCenter,
  556. ),
  557. title: Strings.deleteAccount.tr,
  558. onTap: () {
  559. AllDialog.showDeleteAccountConfirm(() {
  560. // 退出登录
  561. controller.handleDeleteAccount();
  562. });
  563. },
  564. ),
  565. _buildDivider(),
  566. _buildSettingItem(
  567. icon: IconFont.icon66,
  568. iconColor:
  569. DarkThemeColors.settingSecurityLinearGradientStartColor,
  570. iconGradient: LinearGradient(
  571. colors: [
  572. DarkThemeColors.settingSecurityLinearGradientStartColor,
  573. DarkThemeColors.settingSecurityLinearGradientEndColor,
  574. ],
  575. begin: Alignment.topCenter,
  576. end: Alignment.bottomCenter,
  577. ),
  578. title: Strings.logout.tr,
  579. titleColor: const Color(0xFFEF0000),
  580. onTap: () {
  581. AllDialog.showLogoutConfirm(() {
  582. // 退出登录
  583. controller.handleLogout();
  584. });
  585. },
  586. ),
  587. ],
  588. ),
  589. ),
  590. );
  591. }
  592. /// 构建设置项
  593. Widget _buildSettingItem({
  594. IconData? icon,
  595. String? svgPath,
  596. required Color iconColor,
  597. Gradient? iconGradient,
  598. required String title,
  599. Color? titleColor,
  600. bool showInfo = false,
  601. Widget? trailing,
  602. VoidCallback? onTap,
  603. VoidCallback? onInfoTap,
  604. }) {
  605. // 确保至少提供了 icon 或 svgPath 之一
  606. assert(
  607. icon != null || svgPath != null,
  608. 'Must provide either icon or svgPath',
  609. );
  610. return ClickOpacity(
  611. onTap: onTap,
  612. child: Container(
  613. height: 56.w,
  614. padding: EdgeInsets.symmetric(horizontal: 14.w),
  615. child: Row(
  616. children: [
  617. // 图标
  618. Container(
  619. width: 30.w,
  620. height: 30.w,
  621. decoration: BoxDecoration(
  622. gradient: iconGradient,
  623. color: iconGradient == null ? iconColor : null,
  624. borderRadius: BorderRadius.circular(8.r),
  625. ),
  626. child: svgPath != null
  627. ? Padding(
  628. padding: EdgeInsets.all(5.w),
  629. child: SvgPicture.asset(
  630. svgPath,
  631. width: 20.w,
  632. height: 20.w,
  633. colorFilter: const ColorFilter.mode(
  634. Colors.white,
  635. BlendMode.srcIn,
  636. ),
  637. ),
  638. )
  639. : Icon(icon!, size: 20.w, color: Colors.white),
  640. ),
  641. 10.horizontalSpace,
  642. // 标题
  643. Expanded(
  644. child: Row(
  645. children: [
  646. Text(
  647. title,
  648. style: TextStyle(
  649. fontSize: 14.sp,
  650. color:
  651. titleColor ??
  652. Get.reactiveTheme.textTheme.bodyLarge!.color,
  653. fontWeight: FontWeight.w500,
  654. ),
  655. ),
  656. 4.horizontalSpace,
  657. if (showInfo)
  658. ClickOpacity(
  659. onTap: onInfoTap,
  660. child: Icon(
  661. IconFont.icon59,
  662. size: 20.w,
  663. color: Colors.white,
  664. ),
  665. ),
  666. ],
  667. ),
  668. ),
  669. // 右侧内容
  670. if (trailing != null) trailing,
  671. ],
  672. ),
  673. ),
  674. );
  675. }
  676. /// 构建分割线
  677. Widget _buildDivider() {
  678. return Padding(
  679. padding: EdgeInsets.only(left: 60.w),
  680. child: Divider(
  681. height: 1,
  682. color: Get.reactiveTheme.dividerColor.withOpacity(0.3),
  683. ),
  684. );
  685. }
  686. /// 获取用户账号显示文本
  687. String _getUserAccount() {
  688. final user = IXSP.getUser();
  689. if (user == null) return '';
  690. if (user.memberLevel == MemberLevel.normal.level) {
  691. return user.account?.username ?? '';
  692. }
  693. return '';
  694. }
  695. }