- Updated the API base URLs in app.js to point to local development server for testing. - Enhanced SVG icons with gradient fills for improved visual appeal across various components. - Refactored the avatar upload functionality in avatar-nickname.js and profile-edit.js to utilize a new upload utility for better code maintainability. - Improved the layout and styling of the my page and super article editor for a more user-friendly interface. This update aims to streamline development processes and enhance the overall user experience in the application.
254 lines
8.0 KiB
JavaScript
254 lines
8.0 KiB
JavaScript
/**
|
||
* 卡若创业派对 - 头像与昵称设置页
|
||
* 每次进入页面头像、昵称表单均为空,不回显服务端/本地资料;提交后再写入。
|
||
* 新用户(from=new_user)须上传头像 + 自填昵称后才能「完成」。
|
||
*/
|
||
const app = getApp()
|
||
const { trackClick } = require('../../utils/trackClick')
|
||
const { resolveChooseAvatarFilePath, pickLocalAvatarImagePath } = require('../../utils/util.js')
|
||
const { uploadByApi } = require('../../utils/miniprogramUpload.js')
|
||
|
||
function isPlaceholderNickname(n) {
|
||
const s = (n || '').trim()
|
||
if (!s) return true
|
||
return s === '微信用户' || s.indexOf('微信用户') === 0
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 44,
|
||
avatar: '',
|
||
nickname: '',
|
||
saving: false,
|
||
nicknameInputFocus: false,
|
||
/** 规则引擎传入:avatar | nickname,用于高亮对应区块 */
|
||
uiFocus: '',
|
||
fromNewUser: false,
|
||
/** 新用户:头像+真实昵称都齐才可提交 */
|
||
canSubmit: true,
|
||
/** 延后挂载昵称 input,避免微信原生层缓存/自动填充造成「假回显」 */
|
||
nickInputReady: false,
|
||
},
|
||
|
||
onLoad(options) {
|
||
const fromNewUser = String(options.from || '').toLowerCase() === 'new_user'
|
||
const focus = String(options.focus || '').toLowerCase()
|
||
this.setData({
|
||
statusBarHeight: app.globalData.statusBarHeight || 44,
|
||
fromNewUser,
|
||
nickInputReady: false,
|
||
})
|
||
if (focus === 'avatar' || focus === 'nickname') {
|
||
this.setData({ uiFocus: focus })
|
||
}
|
||
this.loadFromUser()
|
||
// 下一帧再挂载 input + 再清一次,打断原生昵称缓存(测试工程师等)
|
||
setTimeout(() => {
|
||
this.setData({
|
||
nickname: '',
|
||
avatar: '',
|
||
nickInputReady: true,
|
||
})
|
||
this._updateCanSubmit()
|
||
if (focus === 'nickname') {
|
||
setTimeout(() => {
|
||
if (typeof wx.requirePrivacyAuthorize === 'function') {
|
||
wx.requirePrivacyAuthorize({
|
||
success: () => this.setData({ nicknameInputFocus: true }),
|
||
fail: () => {},
|
||
})
|
||
} else {
|
||
this.setData({ nicknameInputFocus: true })
|
||
}
|
||
}, 400)
|
||
}
|
||
}, 50)
|
||
if (fromNewUser) {
|
||
trackClick('avatar_nickname', 'page_view', '新注册引导页')
|
||
}
|
||
},
|
||
|
||
loadFromUser() {
|
||
const user = app.globalData.userInfo
|
||
if (!app.globalData.isLoggedIn || !user?.id) {
|
||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||
setTimeout(() => getApp().goBackOrToHome(), 1500)
|
||
return
|
||
}
|
||
// 任意用户进入本页均不回显已有头像/昵称,由用户在本页重新选择、填写后再保存
|
||
this.setData({
|
||
nickname: '',
|
||
avatar: '',
|
||
})
|
||
this._updateCanSubmit()
|
||
},
|
||
|
||
_updateCanSubmit() {
|
||
const { avatar, nickname, fromNewUser } = this.data
|
||
const nick = (nickname || '').trim()
|
||
if (!fromNewUser) {
|
||
this.setData({ canSubmit: true })
|
||
return
|
||
}
|
||
const ok = !!(avatar && nick && !isPlaceholderNickname(nick))
|
||
this.setData({ canSubmit: ok })
|
||
},
|
||
|
||
goBack() {
|
||
if (this.data.fromNewUser && this._isProfileIncomplete()) {
|
||
wx.showModal({
|
||
title: '提示',
|
||
content: '请先设置头像并填写昵称后再离开',
|
||
showCancel: false,
|
||
confirmText: '我知道了',
|
||
})
|
||
return
|
||
}
|
||
getApp().goBackOrToHome()
|
||
},
|
||
|
||
_isProfileIncomplete() {
|
||
const { avatar, nickname, fromNewUser } = this.data
|
||
if (!fromNewUser) return false
|
||
const nick = (nickname || '').trim()
|
||
const av = (avatar || '').trim()
|
||
return !av || !nick || isPlaceholderNickname(nick)
|
||
},
|
||
|
||
onNicknameInput(e) {
|
||
this.setData({ nickname: e.detail.value })
|
||
this._updateCanSubmit()
|
||
},
|
||
onNicknameChange(e) {
|
||
this.setData({ nickname: e.detail.value })
|
||
this._updateCanSubmit()
|
||
},
|
||
onNicknameBlur() {
|
||
this.setData({ nicknameInputFocus: false })
|
||
},
|
||
onNicknameAreaTouch() {
|
||
if (typeof wx.requirePrivacyAuthorize !== 'function') return
|
||
wx.requirePrivacyAuthorize({
|
||
success: () => {
|
||
this.setData({ nicknameInputFocus: true })
|
||
},
|
||
fail: () => {},
|
||
})
|
||
},
|
||
onTapPickAvatar() {
|
||
trackClick('avatar_nickname', 'btn_click', '选择头像')
|
||
const run = () => {
|
||
pickLocalAvatarImagePath()
|
||
.then((p) => this.uploadAndSaveAvatar(p))
|
||
.catch((err) => {
|
||
if (err && err.cancelled) return
|
||
wx.showToast({ title: (err && err.message) || '选择图片失败', icon: 'none' })
|
||
})
|
||
}
|
||
if (typeof wx.requirePrivacyAuthorize === 'function') {
|
||
wx.requirePrivacyAuthorize({
|
||
success: run,
|
||
fail: () => wx.showToast({ title: '需同意隐私指引后再换头像', icon: 'none' }),
|
||
})
|
||
} else {
|
||
run()
|
||
}
|
||
},
|
||
|
||
async uploadAndSaveAvatar(tempUrl) {
|
||
wx.showLoading({ title: '上传中...', mask: true })
|
||
try {
|
||
let filePath
|
||
try {
|
||
filePath = await resolveChooseAvatarFilePath(tempUrl)
|
||
} catch (readErr) {
|
||
wx.hideLoading()
|
||
wx.showToast({ title: readErr.message || '无法读取所选图片', icon: 'none' })
|
||
return
|
||
}
|
||
const uploadRes = await uploadByApi({ filePath, folder: 'avatars' })
|
||
let avatarUrl = uploadRes.data?.url || uploadRes.url
|
||
if (avatarUrl && !avatarUrl.startsWith('http')) {
|
||
avatarUrl = app.globalData.baseUrl + avatarUrl
|
||
}
|
||
this.setData({ avatar: avatarUrl })
|
||
await app.request({
|
||
url: '/api/miniprogram/user/profile',
|
||
method: 'POST',
|
||
data: { userId: app.globalData.userInfo?.id, avatar: avatarUrl },
|
||
})
|
||
if (app.globalData.userInfo) {
|
||
app.globalData.userInfo.avatar = avatarUrl
|
||
wx.setStorageSync('userInfo', app.globalData.userInfo)
|
||
}
|
||
wx.hideLoading()
|
||
wx.showToast({ title: '头像已更新', icon: 'success' })
|
||
this._updateCanSubmit()
|
||
if (this.data.fromNewUser) {
|
||
trackClick('avatar_nickname', 'form_step_done', '头像更新完成')
|
||
}
|
||
} catch (e) {
|
||
wx.hideLoading()
|
||
wx.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||
}
|
||
},
|
||
|
||
async saveProfile() {
|
||
const userId = app.globalData.userInfo?.id
|
||
if (!userId) {
|
||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||
return
|
||
}
|
||
if (this.data.fromNewUser && !this.data.canSubmit) {
|
||
wx.showToast({ title: '请先设置头像并填写昵称', icon: 'none' })
|
||
return
|
||
}
|
||
const nickname = (this.data.nickname || '').trim()
|
||
const avatar = (this.data.avatar || '').trim()
|
||
if (!nickname) {
|
||
wx.showToast({ title: '请输入昵称', icon: 'none' })
|
||
return
|
||
}
|
||
if (this.data.fromNewUser) {
|
||
if (!avatar) {
|
||
wx.showToast({ title: '请先选择头像', icon: 'none' })
|
||
return
|
||
}
|
||
if (isPlaceholderNickname(nickname)) {
|
||
wx.showToast({ title: '请修改昵称,不能使用系统默认占位词', icon: 'none' })
|
||
return
|
||
}
|
||
}
|
||
trackClick('avatar_nickname', 'btn_click', '完成保存')
|
||
this.setData({ saving: true })
|
||
try {
|
||
await app.request({
|
||
url: '/api/miniprogram/user/profile',
|
||
method: 'POST',
|
||
data: { userId, avatar: avatar || undefined, nickname },
|
||
})
|
||
if (app.globalData.userInfo) {
|
||
if (nickname) app.globalData.userInfo.nickname = nickname
|
||
if (avatar) app.globalData.userInfo.avatar = avatar
|
||
wx.setStorageSync('userInfo', app.globalData.userInfo)
|
||
}
|
||
if (this.data.fromNewUser) {
|
||
try {
|
||
wx.removeStorageSync('profile_guide_required')
|
||
} catch (_) {}
|
||
wx.setStorageSync('new_user_guide_done_at', Date.now())
|
||
trackClick('avatar_nickname', 'form_submit', '新注册引导完成', {
|
||
hasAvatar: !!avatar,
|
||
nicknameLen: nickname.length,
|
||
})
|
||
}
|
||
wx.showToast({ title: '保存成功', icon: 'success' })
|
||
setTimeout(() => getApp().goBackOrToHome(), 800)
|
||
} catch (e) {
|
||
wx.showToast({ title: e.message || '保存失败', icon: 'none' })
|
||
}
|
||
this.setData({ saving: false })
|
||
},
|
||
|
||
})
|