From 530d6b2feb904bfcbd9f6690517174ebd5db66d8 Mon Sep 17 00:00:00 2001 From: ltx <1006158920@qq.com> Date: Sat, 9 May 2026 16:19:37 +0800 Subject: [PATCH] =?UTF-8?q?update:=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96&?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/mine/mine.js | 38 ++++++++++------ pages/mine/mine.wxml | 7 ++- pages/mine/mine.wxss | 24 ++++++++--- subpackages/mine/auth/auth.js | 7 ++- subpackages/mine/auth/auth.wxml | 39 +++++++++++++++-- subpackages/mine/auth/auth.wxss | 67 ++++++++++++++++++++++++++++- subpackages/mine/cert/cert.js | 12 +++--- subpackages/mine/cert/cert.wxss | 1 + subpackages/mine/order/order.js | 7 ++- subpackages/mine/order/order.wxml | 29 +++++++++---- subpackages/mine/order/order.wxss | 44 +++++++++++++++++++ subpackages/mine/points/points.js | 1 + subpackages/mine/records/records.js | 4 +- utils/auth.js | 11 +++++ utils/constants.js | 1 + 15 files changed, 245 insertions(+), 47 deletions(-) diff --git a/pages/mine/mine.js b/pages/mine/mine.js index e347253..94cbbf6 100644 --- a/pages/mine/mine.js +++ b/pages/mine/mine.js @@ -105,19 +105,31 @@ Page({ }); }, - onChooseAvatar() { - wx.chooseMedia({ - count: 1, - mediaType: ['image'], - sourceType: ['album', 'camera'], - success: (res) => { - const tempFilePath = res.tempFiles[0].tempFilePath; - this.setData({ - 'profile.avatar': tempFilePath - }); - // TODO: 上传头像到服务器 - } - }); + onChooseAvatar(e) { + const tempFilePath = e.detail.avatarUrl; + if (!tempFilePath) return; + + // 先展示本地预览 + // this.setData({ 'profile.avatar': tempFilePath }); + + wx.showLoading({ title: '上传中...', mask: true }); + auth + .uploadFile(tempFilePath) + .then((url) => { + return auth.updateProfile({ "avatarUrl": url }).then(() => url); + }) + .then((url) => { + this.setData({ 'profile.avatar': url }); + wx.showToast({ title: '头像更新成功', icon: 'success' }); + }) + .catch((err) => { + wx.showToast({ title: (err && err.message) || '头像更新失败', icon: 'none' }); + // 回滚预览,重新加载 profile + this.loadProfile(); + }) + .finally(() => { + wx.hideLoading(); + }); }, onFetchOpenId() { diff --git a/pages/mine/mine.wxml b/pages/mine/mine.wxml index e598a93..c9bc5e3 100644 --- a/pages/mine/mine.wxml +++ b/pages/mine/mine.wxml @@ -15,13 +15,12 @@ - - - + {{maskedPhone}} diff --git a/pages/mine/mine.wxss b/pages/mine/mine.wxss index 6b88a67..67e9038 100644 --- a/pages/mine/mine.wxss +++ b/pages/mine/mine.wxss @@ -40,7 +40,7 @@ /* ====== 已登录页面 ====== */ .mine-page { min-height: 100vh; - background: #f0f2f8; + background: #f5f6f8; } /* ====== 蓝色头部 ====== */ @@ -78,10 +78,22 @@ margin-bottom: 32rpx; } -.avatar-wrap { +.avatar-wrap, +.avatar-wrapper { position: relative; width: 168rpx; height: 168rpx; + padding: 0; + margin: 0; + background: transparent; + border: none; + border-radius: 50%; + line-height: 1; + overflow: visible; +} + +.avatar-wrapper::after { + border: none; } .avatar { @@ -94,8 +106,8 @@ .camera-icon { position: absolute; - right: 0rpx; - bottom: 0rpx; + right: -4rpx; + bottom: -4rpx; width: 48rpx; height: 48rpx; background: linear-gradient(135deg, #1a57b2 0%, #3a7bd5 100%); @@ -291,6 +303,8 @@ color: #1a1a1a; font-weight: 500; letter-spacing: 0.5rpx; + font-size: 26rpx; + margin-left: 10rpx; } .func-menu-arrow { @@ -310,7 +324,7 @@ line-height: 96rpx; background: #fff; color: #e53935; - font-size: 30rpx; + font-size: 28rpx; font-weight: 500; border-radius: 20rpx; border: none; diff --git a/subpackages/mine/auth/auth.js b/subpackages/mine/auth/auth.js index b603c8b..2f66cbb 100644 --- a/subpackages/mine/auth/auth.js +++ b/subpackages/mine/auth/auth.js @@ -83,7 +83,8 @@ Page({ authStatus: 0, authStatusText: '未认证', canSubmit: true, - submitBtnText: '提交认证' + submitBtnText: '提交认证', + loading: true }, _timer: null, @@ -130,6 +131,7 @@ Page({ }, loadAuth() { + this.setData({ loading: true }); return Promise.all([ auth.fetchMyAuth().catch(() => ({})), auth.fetchMyProfile().catch(() => ({})) @@ -162,10 +164,13 @@ Page({ canSubmit, submitBtnText }); + }).finally(() => { + this.setData({ loading: false }); }); }, onChooseImage(e) { + if (this.data.authStatus === 2) return; const kind = e.currentTarget.dataset.kind; wx.chooseMedia({ count: 1, diff --git a/subpackages/mine/auth/auth.wxml b/subpackages/mine/auth/auth.wxml index b96a6e6..39f275b 100644 --- a/subpackages/mine/auth/auth.wxml +++ b/subpackages/mine/auth/auth.wxml @@ -9,7 +9,38 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -81,21 +112,21 @@ 性别 - + 联系电话 {{countdown>0 ? countdown + 's' : '发送验证码'}} - + 验证码 - + diff --git a/subpackages/mine/auth/auth.wxss b/subpackages/mine/auth/auth.wxss index 3dca407..aa46f8c 100644 --- a/subpackages/mine/auth/auth.wxss +++ b/subpackages/mine/auth/auth.wxss @@ -1,5 +1,5 @@ page { - background: #f5f7fa; + background: #f5f6f8; } view{ @@ -299,6 +299,71 @@ view{ border: 1rpx solid #e5e7eb; } +/* ===== 骨架屏 ===== */ +.skeleton-wrap { + padding: 0 20rpx; +} + +.skeleton-upload-card { + background: #ffffff; + border-radius: 16rpx; + padding: 22rpx; + margin-bottom: 18rpx; +} + +.skeleton-upload-row { + display: flex; + gap: 18rpx; +} + +.skeleton-upload-box { + flex: 1; + height: 240rpx; + border-radius: 16rpx; +} + +.skeleton-form-card { + background: #ffffff; + border-radius: 16rpx; + overflow: hidden; +} + +.skeleton-form-row { + display: flex; + align-items: center; + padding: 26rpx 22rpx; + border-bottom: 1rpx solid #f3f4f6; + gap: 20rpx; +} + +.skeleton-form-row:last-child { + border-bottom: none; +} + +.skeleton-label { + width: 140rpx; + height: 32rpx; + border-radius: 8rpx; + flex-shrink: 0; +} + +.skeleton-value { + flex: 1; + height: 32rpx; + border-radius: 8rpx; +} + +@keyframes skeleton-shimmer { + 0% { background-position: -750rpx 0; } + 100% { background-position: 750rpx 0; } +} + +.skeleton-anim { + background: linear-gradient(90deg, #ebebeb 25%, #f5f5f5 50%, #ebebeb 75%); + background-size: 750rpx 100%; + animation: skeleton-shimmer 1.4s infinite linear; +} + /* ===== OCR 识别中提示 ===== */ .ocr-tip { display: flex; diff --git a/subpackages/mine/cert/cert.js b/subpackages/mine/cert/cert.js index b2bb12d..73cc00d 100644 --- a/subpackages/mine/cert/cert.js +++ b/subpackages/mine/cert/cert.js @@ -54,7 +54,6 @@ Page({ loadProfile() { if (this.data.loading) return; - this.setData({ loading: true }); auth .fetchMyProfile() @@ -66,14 +65,14 @@ Page({ certificateCount: p.certificateCount != null ? p.certificateCount : '-' }); }) - .catch(() => {}) - .finally(() => this.setData({ loading: false })); - } - , + .catch(() => {}); + }, + /** 重置并加载 */ resetAndLoad() { this.setData({ records: [], pageNo: 1, noMore: false }); + this.loadProfile(); return this.loadRecords(); }, @@ -125,8 +124,7 @@ Page({ this.setData({ records: newRecords, pageNo: pageNo + 1, - noMore: currentTotal >= total, - certificateCount: total + noMore: currentTotal >= total }); }) .catch(() => { diff --git a/subpackages/mine/cert/cert.wxss b/subpackages/mine/cert/cert.wxss index 22f168c..740d15a 100644 --- a/subpackages/mine/cert/cert.wxss +++ b/subpackages/mine/cert/cert.wxss @@ -196,6 +196,7 @@ align-items: center; justify-content: center; padding-top: 240rpx; + padding-bottom: 240rpx; } .empty-icon { diff --git a/subpackages/mine/order/order.js b/subpackages/mine/order/order.js index a682e07..9952113 100644 --- a/subpackages/mine/order/order.js +++ b/subpackages/mine/order/order.js @@ -28,6 +28,7 @@ function formatOrder(item) { Page({ data: { loading: false, + skeleton: true, noMore: false, pageNo: 1, total: 0, @@ -47,7 +48,7 @@ Page({ const pageNo = refresh ? 1 : this.data.pageNo; if (!refresh && this.data.noMore) return; - this.setData({ loading: true }); + this.setData({ loading: true, skeleton: refresh }); try { const res = await auth.fetchMyOrders({ pageNo, pageSize: PAGE_SIZE }); const rows = (res && res.rows) || []; @@ -59,10 +60,12 @@ Page({ orders: newOrders, pageNo: pageNo + 1, total, - noMore + noMore, + skeleton: false }); } catch (err) { wx.showToast({ title: err?.message || '加载失败', icon: 'none' }); + this.setData({ skeleton: false }); } finally { this.setData({ loading: false }); } diff --git a/subpackages/mine/order/order.wxml b/subpackages/mine/order/order.wxml index 49cc3ab..cd1ad95 100644 --- a/subpackages/mine/order/order.wxml +++ b/subpackages/mine/order/order.wxml @@ -1,13 +1,21 @@ - + + + + + + + + + + + + + + + - + 没有更多了 - 加载中... + + + 加载中... + diff --git a/subpackages/mine/order/order.wxss b/subpackages/mine/order/order.wxss index 1e22b31..59ab860 100644 --- a/subpackages/mine/order/order.wxss +++ b/subpackages/mine/order/order.wxss @@ -117,3 +117,47 @@ font-size: 24rpx; color: #c0c4cc; } + +/* ===== 底部加载动画 ===== */ +.loading-more { + display: flex; + align-items: center; + justify-content: center; + gap: 12rpx; +} + +.loading-spinner { + width: 32rpx; + height: 32rpx; + border: 4rpx solid #e0e0e0; + border-top-color: #07c160; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* ===== 骨架屏 ===== */ +.skeleton-card { + overflow: hidden; +} + +.skeleton-line { + height: 28rpx; + border-radius: 8rpx; + background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%); + background-size: 400% 100%; + animation: skeleton-shimmer 1.4s ease infinite; +} + +@keyframes skeleton-shimmer { + 0% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} + +.skeleton-title { width: 62%; } +.skeleton-status { width: 16%; height: 24rpx; } +.skeleton-time { width: 52%; height: 24rpx; } +.skeleton-amount { width: 38%; height: 24rpx; align-self: flex-end; } diff --git a/subpackages/mine/points/points.js b/subpackages/mine/points/points.js index 8413a80..4332ee8 100644 --- a/subpackages/mine/points/points.js +++ b/subpackages/mine/points/points.js @@ -24,6 +24,7 @@ Page({ }, onPullDownRefresh() { + if(this.data.loading) return; this.loadProfile(); this.resetAndLoad().finally(() => wx.stopPullDownRefresh()); }, diff --git a/subpackages/mine/records/records.js b/subpackages/mine/records/records.js index 81884d0..ddae8b5 100644 --- a/subpackages/mine/records/records.js +++ b/subpackages/mine/records/records.js @@ -31,6 +31,7 @@ Page({ }, onPullDownRefresh() { + this.initData(true).finally(() => wx.stopPullDownRefresh()); }, @@ -39,7 +40,8 @@ Page({ this.setData({ registrations: [], pageNo: 1, - hasMore: true + hasMore: true, + registrationsLoadingText: '加载中...' }); } return this.loadRegistrations(reset ? 1 : this.data.pageNo, reset); diff --git a/utils/auth.js b/utils/auth.js index 57a7c6c..2e262e9 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -266,6 +266,16 @@ async function fetchMyProfile() { }); } +async function updateProfile(data) { + return request({ + path: API.updateProfile, + method: 'POST', + needAuth: true, + data: data, + contentType: 'application/json' + }); +} + async function fetchMyAuth() { return request({ path: API.myAuth, @@ -394,6 +404,7 @@ module.exports = { registerWithVerification, resetPassword, fetchMyProfile, + updateProfile, fetchMyAuth, submitMyAuth, fetchMyRegistrations, diff --git a/utils/constants.js b/utils/constants.js index a24ecac..6b73fa2 100644 --- a/utils/constants.js +++ b/utils/constants.js @@ -25,6 +25,7 @@ const API = { /** 小程序 wx.login 的 code 换 openid(按后端实际路径修改) */ wechatOpenidByJsCode: '/api/wechat/jscode2session', myProfile: '/api/my/profile', + updateProfile: '/api/my/avatar/url', myAuth: '/api/my/auth', myRegistrations: '/api/my/registrations', myPoints: '/api/my/points',