user.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <view class="user-page">
  3. <tui-skeleton v-if="isRequest" :loadingType="3" :isLoading="true"></tui-skeleton>
  4. <!-- 用户信息 -->
  5. <view class="info">
  6. <image class="avatar" :src="avatar" mode="widthFix"></image>
  7. <view class="name" v-if="nickName" v-text="nickName"></view>
  8. <view class="login" hover-class="hover-class" hover-stay-time="100" v-else @click="onLogin">登录</view>
  9. </view>
  10. <!-- 订单信息 -->
  11. <view class="order">
  12. <view class="title">
  13. <text>我的订单</text>
  14. <view @click="handleOrderClick(0)">
  15. <text class="all">全部订单</text>
  16. <tui-icon name="arrowright" size="20rpx"></tui-icon>
  17. </view>
  18. </view>
  19. <view class="navbar">
  20. <view class="item" v-for="nav in navbar" :key="nav.id" @click="handleOrderClick(nav.id)">
  21. <view class="name">
  22. <image class="icon" :src="staticUrl + nav.icon" mode="widthFix"></image>
  23. <text v-text="nav.name"></text>
  24. </view>
  25. <tui-badge
  26. type="danger"
  27. absolute
  28. :scaleRatio="0.8"
  29. translateX="-20%"
  30. top="-6rpx"
  31. v-text="nav.badge"
  32. v-if="nav.badge"
  33. ></tui-badge>
  34. </view>
  35. </view>
  36. </view>
  37. <!-- 菜单选项 -->
  38. <view class="menus">
  39. <tui-list-view>
  40. <template v-for="menu in menus">
  41. <tui-list-cell
  42. :arrow="true"
  43. :key="menu.id"
  44. :size="26"
  45. v-if="!menu.hidden"
  46. padding="36rpx 24rpx"
  47. @click="handleMenuClick(menu.id)"
  48. >
  49. <view class="menu-item">
  50. <button class="menu-item contact" v-if="menu.id === 4" open-type="contact">客服</button>
  51. <view class="name">
  52. <image class="menu-icon" :src="staticUrl + menu.icon"></image>
  53. <text v-text="menu.name"></text>
  54. </view>
  55. <text v-text="menu.count" class="count" v-if="menu.count"></text>
  56. </view>
  57. </tui-list-cell>
  58. </template>
  59. </tui-list-view>
  60. </view>
  61. <!-- 技术支持 -->
  62. <view class="copyright">
  63. <image class="image" :src="staticUrl + 'icon-logo@1x.png'"></image>
  64. <view class="text">由采美365网提供技术服务</view>
  65. </view>
  66. </view>
  67. </template>
  68. <script>
  69. // 引入订单导航和操作菜单轮播
  70. import { navbarList as navbar, menusList as menus } from './config.js'
  71. import { fetchUserOrderTotal } from '@/services/api/user.js'
  72. import { mapGetters, mapActions } from 'vuex'
  73. export default {
  74. data() {
  75. return {
  76. isRequest: true,
  77. navbar: [],
  78. menus: [],
  79. paymentCount: 0,
  80. waitShipmentsCount: 0,
  81. shipmentsCount: 0,
  82. salesReturnCount: 0
  83. }
  84. },
  85. computed: {
  86. ...mapGetters(['headImgUrl', 'nickName', 'userIdentity', 'userId', 'unusedNum']),
  87. avatar() {
  88. return this.headImgUrl || `${this.staticUrl}icon-default-avatar.png`
  89. }
  90. },
  91. onPullDownRefresh() {
  92. this.initCenter()
  93. },
  94. onShow() {
  95. this.initCenter()
  96. },
  97. methods: {
  98. ...mapActions('cart', ['fetchCartKindCount']),
  99. ...mapActions('coupon', ['initCouponCount']),
  100. // 订单跳转
  101. handleOrderClick(id = 0) {
  102. if (!this.userId) {
  103. return this.onLogin()
  104. }
  105. this.$router.navigateTo(`order/order-list?current=${id}`)
  106. },
  107. // 菜单跳转
  108. handleMenuClick(id) {
  109. switch (id) {
  110. case 1:
  111. this.$router.navigateTo('coupon/coupon-user')
  112. break
  113. case 2:
  114. this.$router.navigateTo('activity/activity-area')
  115. break
  116. case 3:
  117. if (!this.userId) return this.onLogin()
  118. this.$router.navigateTo('address/address-list')
  119. break
  120. default:
  121. console.log('other click')
  122. break
  123. }
  124. },
  125. // 初始化个人中心
  126. async initCenter() {
  127. try {
  128. this.fetchCartKindCount()
  129. const res = await fetchUserOrderTotal({ userId: this.userId })
  130. await this.initCouponCount()
  131. this.initTabs(res.data)
  132. this.initMenus()
  133. } catch (e) {
  134. console.log(e)
  135. } finally {
  136. this.isRequest = false
  137. uni.stopPullDownRefresh()
  138. }
  139. },
  140. // 初始化tabs
  141. initTabs(badgeObj) {
  142. function formatBadge(num) {
  143. if (!num) return ''
  144. return num > 99 ? '99+' : num
  145. }
  146. this.navbar = navbar.map((item, index) => {
  147. if (index === 0) {
  148. item.badge = formatBadge(badgeObj.paymentCount)
  149. } else if (index === 1) {
  150. item.badge = formatBadge(badgeObj.waitShipmentsCount)
  151. } else if (index === 2) {
  152. item.badge = formatBadge(badgeObj.shipmentsCount)
  153. } else if (index === 3) {
  154. item.badge = formatBadge(badgeObj.salesReturnCount)
  155. }
  156. return item
  157. })
  158. },
  159. // 初始化菜单
  160. initMenus() {
  161. this.menus = menus.filter(item => {
  162. if (item.id === 1) item.count = this.unusedNum
  163. return item.userIdentity.indexOf(this.userIdentity) > -1
  164. })
  165. },
  166. // 去登录
  167. onLogin() {
  168. const pages = getCurrentPages()
  169. const page = pages[pages.length - 1]
  170. uni.setStorageSync('LOGIN_REDIRECT_URL', page.$page.fullPath)
  171. uni.redirectTo({ url: '/pages/authorize/login-custom' })
  172. }
  173. }
  174. }
  175. </script>
  176. <style scoped>
  177. .navbar >>> .tui-danger {
  178. background-color: #f83c6c !important;
  179. }
  180. </style>
  181. <style lang="scss" scoped>
  182. .user-page {
  183. min-height: 100vh;
  184. position: relative;
  185. }
  186. .info {
  187. @extend .cm-flex-center;
  188. height: 280rpx;
  189. background: url('https://static.caimei365.com/app/mini-hehe/icon/icon-user-bg@2x.png') no-repeat center;
  190. flex-direction: column;
  191. background-size: 750rpx 280rpx;
  192. .avatar {
  193. width: 120rpx;
  194. height: 120rpx;
  195. border-radius: 50%;
  196. }
  197. .name {
  198. margin-top: 24rpx;
  199. font-size: 28rpx;
  200. color: #fff;
  201. }
  202. .login {
  203. width: 184rpx;
  204. height: 56rpx;
  205. margin-top: 24rpx;
  206. border-radius: 28rpx;
  207. background: #ffffff;
  208. line-height: 56rpx;
  209. text-align: center;
  210. color: #f83c6c;
  211. font-size: 28rpx;
  212. }
  213. }
  214. .order {
  215. background: #fff;
  216. .title {
  217. @extend .cm-flex-between;
  218. padding: 24rpx;
  219. border-bottom: 1px solid #eaeef1;
  220. font-size: 32rpx;
  221. .all {
  222. font-size: 26rpx;
  223. }
  224. }
  225. .navbar {
  226. @extend .cm-flex-around;
  227. padding: 24rpx;
  228. .item {
  229. position: relative;
  230. width: 120rpx;
  231. }
  232. .name {
  233. @extend .cm-flex-center;
  234. flex-direction: column;
  235. .icon {
  236. width: 64rpx;
  237. height: 64rpx;
  238. }
  239. text {
  240. font-size: 26rpx;
  241. margin-top: 8rpx;
  242. }
  243. }
  244. }
  245. }
  246. .menus {
  247. margin-top: 24rpx;
  248. .menu-item {
  249. position: relative;
  250. @extend .cm-flex-between;
  251. .contact {
  252. position: absolute;
  253. top: -18rpxrpx;
  254. left: -24rpx;
  255. width: 100%;
  256. background: #000;
  257. opacity: 0;
  258. &::after {
  259. border: 0 !important;
  260. }
  261. }
  262. .name {
  263. display: flex;
  264. align-items: center;
  265. }
  266. .menu-icon {
  267. width: 36rpx;
  268. height: 36rpx;
  269. margin-right: 12rpx;
  270. }
  271. .count {
  272. margin-right: 32rpx;
  273. font-size: 24rpx;
  274. color: #f83c6c;
  275. }
  276. }
  277. }
  278. .copyright {
  279. @extend .cm-flex-center;
  280. position: absolute;
  281. bottom: 24rpx;
  282. width: 100%;
  283. .image {
  284. width: 54rpx;
  285. height: 46rpx;
  286. margin-right: 16rpx;
  287. }
  288. .text {
  289. font-size: 20rpx;
  290. color: #cccccc;
  291. }
  292. }
  293. </style>