index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <template>
  2. <view class="page-content mx-bg-shared-gradient">
  3. <view class="px-40 fx-row fx-bet-cen gap-20" :class="largeScreen?'mt-80':'mt-50'">
  4. <uv-avatar shape="circle" :size="64" :src="avatar" @click="uploadAvatar"/>
  5. <view class="flex-1 fx-col fx-bet-base">
  6. <view class="fx-row items-center gap-20">
  7. <text class="text-main text-2xl font-bold">{{ currentUser.nickName }}</text>
  8. <uv-image width="auto" height="18" mode="heightFix" :src="vipTagImg"/>
  9. </view>
  10. <text class="text-content text-lg items-end">{{ encryptMobile }}</text>
  11. </view>
  12. <uv-image :src="iconSetting" width="24" height="24" @click="goSettingPage"/>
  13. </view>
  14. <view class="mt-30 grid grid-cols-3">
  15. <view class="fx-col items-center" :class="largeScreen?'gap-15':'gap-5'">
  16. <text class="text-main text-lg font-bold">{{ userStat.numExercise || '0' }}</text>
  17. <text class="text-content text-sm">做题数量</text>
  18. </view>
  19. <view class="fx-col items-center" :class="largeScreen?'gap-15':'gap-5'">
  20. <view class="text-main text-lg font-bold">
  21. {{ userStat.timeVideo || '0' }}
  22. <text v-if="userStat.timeVideo && userStat.timeVideoUnit" class="text-xs font-normal">
  23. {{ userStat.timeVideoUnit }}
  24. </text>
  25. </view>
  26. <text class="text-content text-sm">视频观看时长</text>
  27. </view>
  28. <view class="fx-col items-center" :class="largeScreen?'gap-15':'gap-5'">
  29. <text class="text-main text-lg font-bold">{{ userStat.numLogin || '0' }}</text>
  30. <text class="text-content text-sm">登陆次数</text>
  31. </view>
  32. </view>
  33. <view class="p-40">
  34. <view class="buy-vip">
  35. <view class="fx-row fx-bet-cen h-full text-xs">
  36. <template v-if="currentUser.isBind">
  37. <text>已开通会员,享受权益中</text>
  38. <text class="font-thin">{{ currentUser.outDate }} 到期</text>
  39. </template>
  40. <template v-else>
  41. <text>开通会员,享受全部权益</text>
  42. <view @click="handleVipClick">
  43. <uv-text text="去开通" suffix-icon="arrow-right"/>
  44. </view>
  45. </template>
  46. </view>
  47. </view>
  48. </view>
  49. <index-title-wrap title="常用功能" disable-line bold class="px-40">
  50. <mx-index-menus :data="usualMenus" title-class="text-sm font-normal text-content" class="!mx-0"
  51. container-wrap-class="p-30" :gap-class="largeScreen?undefined:'gap-0'"/>
  52. </index-title-wrap>
  53. <index-title-wrap title="其它功能" disable-line bold class="mx-40 mt-40" :class="{'!gap-0': !largeScreen}">
  54. <uv-cell v-for="m in otherMenus" :key="m.name" is-link :icon="m.icon" :title="m.name"
  55. @click="handleSettingClick(m)"/>
  56. </index-title-wrap>
  57. <view class="flex-1 min-h-180 fx-row fx-cen-cen">
  58. <uv-button type="error" size="large" shape="circle" text="退出登陆" plain
  59. :custom-style="{ width: '50vw', height: '44px' }" @click="handleLogout"/>
  60. </view>
  61. </view>
  62. </template>
  63. <script setup>
  64. import {computed} from "vue";
  65. import {onShow} from "@dcloudio/uni-app";
  66. import mxConfig from "@/common/mxConfig";
  67. import mxConst from "@/common/mxConst.js";
  68. import {useUserStore} from "@/hooks/useUserStore";
  69. import {useEnvStore} from "@/hooks/useEnvStore";
  70. import {useTransfer} from "@/hooks/useTransfer";
  71. import {useChooseImage} from "@/hooks/useChooseImage";
  72. import {useUserStorePageFilter} from "@/hooks/useUserStorePageFilter";
  73. import {mobile} from "@/uni_modules/uv-ui-tools/libs/function/test";
  74. import _ from "lodash";
  75. import IndexTitleWrap from "@/pages/index/components/index-title-wrap.vue";
  76. import iconVip from "@/static/personal/vip_tag.png";
  77. import iconVipNone from "@/static/personal/vip_none_tag.png";
  78. import iconSetting from "@/static/personal/setting.png";
  79. import {sys} from "@/uni_modules/uv-ui-tools/libs/function";
  80. import {useSingletonBuyVip} from "@/hooks/useSingletonComponent";
  81. const {isLogin, currentUser, avatar, GetInfo, Logout} = useUserStore();
  82. const {transferTo, transferToFAQ} = useTransfer();
  83. const {isDisplayedPermission} = useEnvStore();
  84. const {chooseAvatar} = useChooseImage()
  85. const vipTagImg = computed(() => currentUser.value.isBind ? iconVip : iconVipNone);
  86. const userStat = computed(() => currentUser.value.userStat || {});
  87. const encryptMobile = computed(() =>
  88. mobile(currentUser.value.phonenumber)
  89. ? currentUser.value.phonenumber.replace(/^(\d{3})\d{4}(\d+)/, "$1****$2")
  90. : currentUser.value.phonenumber
  91. );
  92. const {menus} = useUserStorePageFilter("PersonalCenter");
  93. const groupedMenus = computed(() => _.partition(menus.value, (m) => m.category == "usual"))
  94. const usualMenus = computed(() => groupedMenus.value[0])
  95. const otherMenus = computed(() => groupedMenus.value[1])
  96. const largeScreen = computed(() => sys().windowHeight > 740)
  97. onShow(async () => {
  98. if (!isLogin.value) transferTo(mxConst.routes.login)
  99. });
  100. function goSettingPage() {
  101. transferTo(mxConst.routes.setting)
  102. }
  103. async function handleLogout() {
  104. await Logout()
  105. transferTo(mxConst.routes.login)
  106. }
  107. function handleVipClick() {
  108. const buyVipPopup = useSingletonBuyVip()
  109. buyVipPopup.open()
  110. }
  111. function handleSettingClick(setting) {
  112. if (setting.type === "FAQ") return transferToFAQ()
  113. if (!setting.path) return
  114. let nextData = setting.nextData || {}
  115. nextData.settingName = ""
  116. transferTo(setting.path, nextData, [currentUser, {settingName: setting.name}])
  117. }
  118. function uploadAvatar() {
  119. // 简单判断一下,不能保证已经真正获取权限
  120. if (!isDisplayedPermission.value) {
  121. uni.showModal({
  122. title: "权限说明",
  123. content: mxConfig.cameraAuthTips,
  124. showCancel: false,
  125. success: (res) => {
  126. if (res.confirm) {
  127. isDisplayedPermission.value = true;
  128. chooseAvatarCore()
  129. }
  130. },
  131. });
  132. } else {
  133. chooseAvatarCore()
  134. }
  135. }
  136. function chooseAvatarCore() {
  137. chooseAvatar((data) => {
  138. currentUser.avatar = data.imgUrl
  139. GetInfo()
  140. })
  141. }
  142. </script>
  143. <style scoped>
  144. .buy-vip {
  145. background-image: url("~@/static/personal/buy_vip.png");
  146. background-repeat: no-repeat;
  147. background-position: center;
  148. background-size: cover;
  149. height: 44px;
  150. border-radius: 6px;
  151. overflow: hidden;
  152. padding: 0 12px 0 48px;
  153. }
  154. ::v-deep .uv-cell .uv-cell__body {
  155. padding: 10px 0;
  156. }
  157. </style>