account_view.dart 22 KB

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