feat: enhance profile editing and image upload functionality

- Introduced a utility function to ensure absolute media URLs for user profile images.
- Updated the user cache synchronization method to handle profile data more effectively, including avatar, nickname, phone, and MBTI.
- Refactored the avatar upload process to utilize the new URL handling function, improving reliability.
- Modified the super article editor to focus on image uploads instead of file uploads, enhancing user experience with clearer labeling and prompts.

This update aims to streamline user profile management and improve the image upload experience in the application.
This commit is contained in:
乘风
2026-05-09 16:23:59 +08:00
parent 2645212d47
commit b1db1efeb8
7 changed files with 73 additions and 117 deletions

View File

@@ -14,6 +14,15 @@ const { uploadByApi } = require('../../utils/miniprogramUpload.js')
const MBTI_OPTIONS = ['INTJ', 'INFP', 'INTP', 'ENTP', 'ENFP', 'ENTJ', 'ENFJ', 'INFJ', 'ISTJ', 'ISFJ', 'ESTJ', 'ESFJ', 'ISTP', 'ISFP', 'ESTP', 'ESFP']
/** 补齐小程序可用的绝对 URL本地/OSS 相对路径拼 baseUrl */
function ensureAbsMediaUrl(u, base) {
const s = String(u || '').trim()
if (!s) return ''
if (/^https?:\/\//i.test(s)) return s
const b = String(base || '').replace(/\/$/, '')
return b ? b + (s.startsWith('/') ? s : '/' + s) : s
}
/** 首次分步完善完成后写入;与手机号+昵称齐全时自动写入,老用户免向导 */
const PROFILE_WIZARD_DONE_KEY = 'profile_wizard_v1_done'
@@ -409,6 +418,49 @@ Page({
}
},
/** 将接口返回的 profile data 写入 globalData.userInfo、storage可选同步本页展示字段头像上传时用 */
_syncUserCacheFromProfileData(d, patchPage) {
if (!d || typeof d !== 'object') return
const base = app.globalData.baseUrl || ''
const ensureAbs = (u) => ensureAbsMediaUrl(u, base)
if (patchPage) {
const patch = {}
if (d.avatar != null && String(d.avatar).trim() !== '') patch.avatar = ensureAbs(d.avatar)
if (d.nickname != null) patch.nickname = String(d.nickname)
if (d.phone != null) patch.phone = String(d.phone)
if (d.wechatId != null) patch.wechatId = String(d.wechatId)
if (d.mbti != null) {
patch.mbti = String(d.mbti)
const idx = MBTI_OPTIONS.indexOf(patch.mbti)
if (idx >= 0) patch.mbtiIndex = idx
}
if (Object.keys(patch).length) {
this.setData(patch, () => this._syncAvatarPreview())
} else {
this._syncAvatarPreview()
}
}
const u = app.globalData.userInfo
if (!u) return
if (d.nickname != null && String(d.nickname).trim() !== '') u.nickname = String(d.nickname).trim()
if (d.avatar != null && String(d.avatar).trim() !== '') u.avatar = ensureAbs(d.avatar)
if (d.phone != null && String(d.phone).trim() !== '') {
u.phone = String(d.phone).trim()
wx.setStorageSync('user_phone', u.phone)
}
if (d.wechatId != null) {
const w = String(d.wechatId).trim()
u.wechatId = w
u.wechat = w
u.wechat_id = w
if (w) wx.setStorageSync('user_wechat', w)
}
if (d.mbti != null && String(d.mbti).trim() !== '') u.mbti = String(d.mbti).trim()
wx.setStorageSync('userInfo', u)
},
/** 点击头像:相册/相机选图(不使用 open-type=chooseAvatar避免 Windows 开发者工具 http://tmp 渲染报错) */
onTapPickAvatar() {
const run = () => {
@@ -437,20 +489,20 @@ Page({
const uploadRes = await uploadByApi({ filePath, folder: 'avatars' })
let avatarUrl = uploadRes.data?.url || uploadRes.url
if (avatarUrl && !avatarUrl.startsWith('http')) {
avatarUrl = app.globalData.baseUrl + avatarUrl
if (avatarUrl && !/^https?:\/\//i.test(avatarUrl)) {
avatarUrl = ensureAbsMediaUrl(avatarUrl, app.globalData.baseUrl)
}
this.setData({ avatar: avatarUrl }, () => this._syncAvatarPreview())
const avatarToSave = toAvatarPath(avatarUrl)
await app.request({
const profileRes = await app.request({
url: '/api/miniprogram/user/profile',
method: 'POST',
data: { userId: app.globalData.userInfo?.id, avatar: avatarToSave },
})
if (app.globalData.userInfo) {
app.globalData.userInfo.avatar = avatarUrl
wx.setStorageSync('userInfo', app.globalData.userInfo)
if (!profileRes?.success) {
throw new Error(profileRes?.error || profileRes?.message || '保存头像失败')
}
this._syncUserCacheFromProfileData(profileRes.data, true)
wx.hideLoading()
wx.showToast({ title: '头像已更新', icon: 'success' })
setTimeout(() => this.generateShareCard(), 200)
@@ -523,12 +575,7 @@ Page({
data: payload,
})
wx.showToast({ title: '保存成功', icon: 'success' })
if (app.globalData.userInfo) {
if (payload.nickname) app.globalData.userInfo.nickname = payload.nickname
if (res?.data?.avatar) app.globalData.userInfo.avatar = res.data.avatar
if (payload.phone) app.globalData.userInfo.phone = payload.phone
wx.setStorageSync('userInfo', app.globalData.userInfo)
}
if (res?.data) this._syncUserCacheFromProfileData(res.data, false)
if (wizardComplete) {
wx.setStorageSync(PROFILE_WIZARD_DONE_KEY, '1')
this.setData({ wizardMode: false, saving: false })