personalCenter.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. <template>
  2. <view class="pc">
  3. <view class="pc-header">
  4. <uv-navbar
  5. title="个人中心"
  6. fixed
  7. placeholder
  8. leftIconSize="0"
  9. bgColor="transparent"
  10. :border="false"
  11. titleStyle="font-weight: 700;color: #1a1a1a;"
  12. >
  13. </uv-navbar>
  14. <view
  15. class="pc-user u-flex-center-sb"
  16. @tap.stop="goJump('/pages/set/edit', true)"
  17. >
  18. <view class="pc-user-left u-flex-center">
  19. <image
  20. v-if="userInformation && userInformation.headPhoto"
  21. :src="userInformation.headPhoto"
  22. class="pc-avatar"
  23. mode="aspectFill"
  24. />
  25. <image
  26. v-else
  27. :src="$defaultAvatar"
  28. class="pc-avatar"
  29. mode="aspectFill"
  30. />
  31. <view class="pc-user-info">
  32. <view class="pc-user-name">{{
  33. userInformation.id ? userInformation.nickname : "登录/注册"
  34. }}</view>
  35. <view class="pc-user-phone u-flex-center" v-if="userInformation.id">
  36. <image
  37. class="pc-user-phone-icon"
  38. src="/static/image/personalCenter/icon_phone.png"
  39. mode="aspectFill"
  40. />
  41. <text class="pc-user-phone-text">{{
  42. userInformation.mobile
  43. }}</text>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="pc-nav-right">
  48. <view
  49. class="pc-nav-icon"
  50. @tap.stop="goJump('/pages/user/myMsg', true)"
  51. >
  52. <uv-icon name="chat" color="#1a1a1a" size="44rpx"></uv-icon>
  53. <view class="pc-nav-badge" v-if="myMsgText">{{ myMsgText }}</view>
  54. </view>
  55. <view
  56. class="pc-nav-icon"
  57. @tap.stop="goJump('/pages/set/index', true)"
  58. >
  59. <uv-icon name="setting" color="#1a1a1a" size="44rpx"></uv-icon>
  60. </view>
  61. <!-- <uv-icon name="arrow-right" color="#1a1a1a" size="44rpx"></uv-icon> -->
  62. </view>
  63. </view>
  64. <view class="pc-assets u-flex-center-sb">
  65. <view
  66. class="pc-assets-card"
  67. style="
  68. background-image: url('/static/image/personalCenter/icon_points.png');
  69. "
  70. @tap.stop="goMypoints"
  71. >
  72. <view class="pc-assets-value">{{ integralAble || 0 }} <text class="unit">积分</text></view>
  73. <view class="pc-assets-label">我的积分</view>
  74. </view>
  75. <view
  76. class="pc-assets-card"
  77. style="
  78. background-image: url('/static/image/personalCenter/icon_amount.png');
  79. "
  80. @tap.stop="goToMyWallet"
  81. >
  82. <view class="pc-assets-value">{{
  83. $addDecimals(userInformation.balance || 0, 2)
  84. }} <text class="unit">元</text></view>
  85. <view class="pc-assets-label">我的钱包</view>
  86. </view>
  87. </view>
  88. </view>
  89. <view class="pc-body">
  90. <view class="pc-card">
  91. <view class="pc-card-head u-flex-center-sb">
  92. <view class="pc-card-title">商城订单</view>
  93. <view class="pc-card-more u-flex-center" @tap.stop="goOrderList(-1)">
  94. <text>查看更多</text>
  95. <uv-icon name="arrow-right" size="24rpx" color="#999999"></uv-icon>
  96. </view>
  97. </view>
  98. <view class="pc-order-grid">
  99. <view
  100. class="pc-order-item"
  101. v-for="item in orderStatusList"
  102. :key="item.keys"
  103. @tap.stop="goOrderList(item.keys)"
  104. >
  105. <image class="pc-order-icon" :src="item.icon" mode="aspectFill" />
  106. <view class="pc-order-text">{{ item.label }}</view>
  107. </view>
  108. </view>
  109. </view>
  110. <view class="pc-card">
  111. <view class="pc-card-head">
  112. <view class="pc-card-title">其他工具</view>
  113. </view>
  114. <view class="pc-tool-grid">
  115. <view
  116. class="pc-tool-item"
  117. v-for="(item, index) in toolsList"
  118. :key="index"
  119. >
  120. <template v-if="item.key === 'kf'">
  121. <!-- #ifdef MP-WEIXIN -->
  122. <button open-type="contact" class="pc-tool-btn">
  123. <image
  124. class="pc-tool-icon"
  125. :src="item.icon"
  126. mode="aspectFill"
  127. />
  128. <view class="pc-tool-text">{{ item.label }}</view>
  129. </button>
  130. <!-- #endif -->
  131. <!-- #ifndef MP-WEIXIN -->
  132. <view class="pc-tool-btn" @tap.stop="customerService">
  133. <image
  134. class="pc-tool-icon"
  135. :src="item.icon"
  136. mode="aspectFill"
  137. />
  138. <view class="pc-tool-text">{{ item.label }}</view>
  139. </view>
  140. <!-- #endif -->
  141. </template>
  142. <template v-else>
  143. <view class="pc-tool-btn" @tap.stop="goSublevelPage(item)">
  144. <image
  145. class="pc-tool-icon"
  146. :src="item.icon"
  147. mode="aspectFill"
  148. />
  149. <view class="pc-tool-text">{{ item.label }}</view>
  150. </view>
  151. </template>
  152. </view>
  153. </view>
  154. </view>
  155. </view>
  156. </view>
  157. </template>
  158. <script setup>
  159. import { computed, ref } from "vue";
  160. import { onShow, onPullDownRefresh } from "@dcloudio/uni-app";
  161. import { userInfo } from "@/api/login.js";
  162. import { messageUnreadNum_Api, totalIntegral_Api } from "@/api/userInfo.js";
  163. import utils from "@/util/index.js";
  164. const userInformation = ref({});
  165. const myMsg = ref(0);
  166. const integralAble = ref(0); // 用户积分数据
  167. const myMsgText = computed(() => {
  168. if (!myMsg.value) return "";
  169. if (myMsg.value > 99) return "99+";
  170. return String(myMsg.value);
  171. });
  172. const orderStatusList = [
  173. { label: "待付款", icon: "/static/image/order/order-icon1.png", keys: 0 },
  174. { label: "待发货", icon: "/static/image/order/order-icon2.png", keys: 1 },
  175. { label: "待收货", icon: "/static/image/order/order-icon3.png", keys: 3 },
  176. { label: "待评价", icon: "/static/image/order/order-icon4.png", keys: 5 },
  177. { label: "退款/售后", icon: "/static/image/order/order-icon5.png", keys: 6 },
  178. ];
  179. const toolsList = ref([
  180. {
  181. label: "我的拼团",
  182. icon: "/static/image/personalCenter/tool2.png",
  183. url: "/pages/groupBuying/myGbOrder/list",
  184. idNeedLogin: true,
  185. isPage: true,
  186. },
  187. {
  188. label: "收货地址",
  189. icon: "/static/image/personalCenter/tool3.png",
  190. url: "/pages/user/address/addressList?formType=mine",
  191. idNeedLogin: true,
  192. isPage: true,
  193. },
  194. {
  195. label: "分销中心",
  196. icon: "/static/image/personalCenter/tool1.png",
  197. url: "/pages/distribution/index",
  198. idNeedLogin: true,
  199. isPage: true,
  200. },
  201. {
  202. label: "我的收藏",
  203. icon: "/static/image/personalCenter/tool5.png",
  204. url: "/pages/user/collection",
  205. idNeedLogin: true,
  206. isPage: true,
  207. },
  208. {
  209. label: "商家入驻",
  210. icon: "/static/image/personalCenter/tool4.png",
  211. url: "/pages/user/merchant/settleIn?type=tenants_agreement",
  212. idNeedLogin: true,
  213. isPage: true,
  214. },
  215. {
  216. label: "官方客服",
  217. icon: "/static/image/personalCenter/tool9.png",
  218. url: "",
  219. key: "kf",
  220. idNeedLogin: false,
  221. isPage: false,
  222. },
  223. {
  224. label: "常见问题",
  225. icon: "/static/image/personalCenter/tool8.png",
  226. url: "/pages/user/faq",
  227. idNeedLogin: false,
  228. isPage: true,
  229. },
  230. {
  231. label: "领券中心",
  232. icon: "/static/image/personalCenter/tool6.png",
  233. url: "/pages/couponCenter/index",
  234. idNeedLogin: false,
  235. isPage: true,
  236. },
  237. {
  238. label: "优惠券",
  239. icon: "/static/image/personalCenter/tool7.png",
  240. url: "/pages/couponCenter/index?isMyCoupon=true",
  241. idNeedLogin: true,
  242. isPage: true,
  243. },
  244. ]);
  245. const goOrderList = (keys) => {
  246. goJump(`/pages/order/mallOrder/orderList?keys=${keys}`, true);
  247. };
  248. // 跳转我的积分
  249. function goMypoints() {
  250. if (utils.isLoginTo(true)) return;
  251. uni.navigateTo({ url: "/pages/user/pointsList" });
  252. }
  253. //获取未读消息
  254. function getUnreadNum() {
  255. return messageUnreadNum_Api()
  256. .then((res) => {
  257. uni.stopPullDownRefresh();
  258. if (res && res.code == 200) {
  259. myMsg.value = res.data || 0;
  260. } else {
  261. myMsg.value = 0;
  262. }
  263. })
  264. .catch(() => {
  265. myMsg.value = 0;
  266. });
  267. }
  268. //前往我的钱包
  269. function goToMyWallet() {
  270. if (utils.isLoginTo(true)) return;
  271. uni.navigateTo({
  272. url: "/pages/user/wallet/index",
  273. });
  274. }
  275. //判断是否登录
  276. function judgeLogin() {
  277. return userInfo().then((res) => {
  278. uni.stopPullDownRefresh();
  279. if (res && res.code == 200) {
  280. userInformation.value = res.data;
  281. uni.setStorageSync("personal", res.data);
  282. }
  283. });
  284. }
  285. // 跳转子级页面
  286. const goSublevelPage = (item) => {
  287. if (item.key === "kf") return;
  288. if (item.idNeedLogin) {
  289. let url = item.url;
  290. if (utils.isLoginTo(true)) return;
  291. uni.navigateTo({ url });
  292. return;
  293. }
  294. uni.navigateTo({ url: item.url });
  295. };
  296. // 跳转页面
  297. const goJump = (url = "", isLogin = false) => {
  298. if (!url) return;
  299. if (isLogin && utils.isLoginTo(isLogin)) return;
  300. uni.navigateTo({
  301. url,
  302. });
  303. };
  304. // 查询总积分
  305. const getTotalIntegral = () => {
  306. return totalIntegral_Api().then((res) => {
  307. if (res.code == 200) {
  308. integralAble.value = res.data || 0;
  309. }
  310. });
  311. };
  312. // 客服
  313. const customerService = () => {
  314. // #ifdef APP-PLUS
  315. let sweixin;
  316. plus.share.getServices(
  317. (res) => {
  318. sweixin = res.find((i) => i.id === "weixin");
  319. if (sweixin) {
  320. sweixin.openCustomerServiceChat(
  321. {
  322. corpid: "wxf4cb2367022f4941",
  323. url: "https://work.weixin.qq.com/kfid/kfcfa748e7c99d682b8",
  324. },
  325. (suc) => {
  326. console.log("success", JSON.stringify(suc));
  327. },
  328. (err) => {
  329. console.log("error", JSON.stringify(err));
  330. }
  331. );
  332. } else {
  333. plus.nativeUI.alert("当前环境不支持微信操作!");
  334. }
  335. },
  336. function (e) {
  337. uni.showToast({
  338. title: "获取服务失败,不支持该操作。" + JSON.stringify(e),
  339. icon: "error",
  340. });
  341. }
  342. );
  343. // #endif
  344. };
  345. onShow(async () => {
  346. let token = uni.getStorageSync("apiToken");
  347. if (token) {
  348. await Promise.allSettled([
  349. getTotalIntegral(),
  350. judgeLogin(),
  351. getUnreadNum(),
  352. ]);
  353. } else {
  354. integralAble.value = 0;
  355. myMsg.value = 0;
  356. userInformation.value = {};
  357. }
  358. });
  359. onPullDownRefresh(() => {
  360. let token = uni.getStorageSync("apiToken");
  361. if (!token) {
  362. uni.stopPullDownRefresh();
  363. } else {
  364. Promise.allSettled([
  365. getTotalIntegral(),
  366. judgeLogin(),
  367. getUnreadNum(),
  368. ]).finally(() => {
  369. uni.stopPullDownRefresh();
  370. });
  371. }
  372. });
  373. </script>
  374. <style scoped lang="scss">
  375. .pc {
  376. min-height: 100vh;
  377. // background-color: #f7f7f7;
  378. background: linear-gradient(0deg, #f4f4f4 55%, #ffb700) no-repeat;
  379. }
  380. .pc-header {
  381. padding: 0 24rpx 24rpx;
  382. box-sizing: border-box;
  383. }
  384. .pc-nav-right {
  385. display: flex;
  386. align-items: center;
  387. // gap: 22rpx;
  388. }
  389. .pc-nav-icon {
  390. position: relative;
  391. // width: 56rpx;
  392. // height: 56rpx;
  393. display: flex;
  394. align-items: center;
  395. justify-content: center;
  396. margin-right: 20rpx;
  397. }
  398. .pc-nav-badge {
  399. position: absolute;
  400. right: -6rpx;
  401. top: -6rpx;
  402. min-width: 28rpx;
  403. height: 28rpx;
  404. padding: 0 8rpx;
  405. box-sizing: border-box;
  406. background: #ff3b30;
  407. border-radius: 999rpx;
  408. color: #ffffff;
  409. font-size: 20rpx;
  410. font-weight: 700;
  411. line-height: 28rpx;
  412. text-align: center;
  413. border: 2rpx solid rgba(255, 255, 255, 0.85);
  414. }
  415. .pc-user {
  416. // margin-top: 24rpx;
  417. // padding: 10rpx 0;
  418. }
  419. .pc-user-left {
  420. flex: 1;
  421. min-width: 0;
  422. }
  423. .pc-avatar {
  424. width: 120rpx;
  425. height: 120rpx;
  426. border-radius: 50%;
  427. border: 4rpx solid rgba(255, 255, 255, 0.95);
  428. flex-shrink: 0;
  429. }
  430. .pc-user-info {
  431. margin-left: 20rpx;
  432. flex: 1;
  433. min-width: 0;
  434. }
  435. .pc-user-name {
  436. font-size: 44rpx;
  437. font-weight: 800;
  438. color: #1a1a1a;
  439. line-height: 1.2;
  440. }
  441. .pc-user-phone {
  442. margin-top: 14rpx;
  443. display: inline-flex;
  444. align-items: center;
  445. padding: 6rpx 18rpx;
  446. background: rgba(255, 255, 255, 0.7);
  447. border-radius: 999rpx;
  448. }
  449. .pc-user-phone-icon {
  450. width: 26rpx;
  451. height: 26rpx;
  452. flex-shrink: 0;
  453. }
  454. .pc-user-phone-text {
  455. margin-left: 10rpx;
  456. font-size: 26rpx;
  457. color: #1a1a1a;
  458. }
  459. .pc-assets {
  460. margin-top: 26rpx;
  461. }
  462. .pc-assets-card {
  463. width: 329rpx;
  464. min-height: 176rpx;
  465. // background: rgba(255, 255, 255, 0.88);
  466. border-radius: 10rpx;
  467. padding: 24rpx 26rpx;
  468. box-sizing: border-box;
  469. display: flex;
  470. flex-direction: column;
  471. // justify-content: center;
  472. background-size: 100% 100%;
  473. // background-position: center;
  474. background-repeat: no-repeat;
  475. }
  476. .pc-assets-card + .pc-assets-card {
  477. margin-left: 18rpx;
  478. }
  479. .pc-assets-value {
  480. font-size: 43rpx;
  481. font-weight: 700;
  482. color: #ff6a00;
  483. line-height: 1.1;
  484. .unit{
  485. font-size: 26rpx;
  486. font-weight: 400;
  487. }
  488. }
  489. .pc-assets-label {
  490. margin-top: 12rpx;
  491. font-size: 26rpx;
  492. color: #1a1a1a;
  493. }
  494. .pc-body {
  495. padding: 24rpx;
  496. box-sizing: border-box;
  497. }
  498. .pc-card {
  499. background: #ffffff;
  500. border-radius: 20rpx;
  501. padding: 28rpx 24rpx;
  502. box-sizing: border-box;
  503. }
  504. .pc-card + .pc-card {
  505. margin-top: 24rpx;
  506. }
  507. .pc-card-head {
  508. display: flex;
  509. align-items: center;
  510. justify-content: space-between;
  511. }
  512. .pc-card-title {
  513. font-size: 30rpx;
  514. font-weight: 700;
  515. color: #1a1a1a;
  516. }
  517. .pc-card-more {
  518. font-size: 26rpx;
  519. color: #999999;
  520. }
  521. .pc-order-grid {
  522. margin-top: 22rpx;
  523. display: grid;
  524. grid-template-columns: repeat(5, 1fr);
  525. gap: 10rpx;
  526. }
  527. .pc-order-item {
  528. text-align: center;
  529. }
  530. .pc-order-icon {
  531. width: 56rpx;
  532. height: 56rpx;
  533. }
  534. .pc-order-text {
  535. margin-top: 14rpx;
  536. font-size: 24rpx;
  537. color: #1a1a1a;
  538. }
  539. .pc-tool-grid {
  540. margin-top: 26rpx;
  541. display: grid;
  542. grid-template-columns: repeat(4, 1fr);
  543. gap: 10rpx;
  544. }
  545. .pc-tool-item {
  546. text-align: center;
  547. }
  548. .pc-tool-btn {
  549. display: inline-flex;
  550. flex-direction: column;
  551. align-items: center;
  552. justify-content: center;
  553. background: transparent;
  554. padding: 0;
  555. border: 0;
  556. line-height: initial;
  557. }
  558. .pc-tool-btn:after {
  559. border: none;
  560. }
  561. .pc-tool-icon {
  562. width: 56rpx;
  563. height: 56rpx;
  564. }
  565. .pc-tool-text {
  566. margin-top: 14rpx;
  567. margin-bottom: 22rpx;
  568. font-size: 26rpx;
  569. color: #1a1a1a;
  570. }
  571. </style>