195 lines
7.2 KiB
JavaScript
195 lines
7.2 KiB
JavaScript
const app = getApp()
|
|
|
|
Page({
|
|
data: {
|
|
name: '',
|
|
nickname: '',
|
|
days: 0,
|
|
badges: 0,
|
|
openid: '',
|
|
avatarUrl: '',
|
|
loading: false,
|
|
error: '',
|
|
showNicknameModal: false,
|
|
nicknameDraft: '',
|
|
},
|
|
onShow() {
|
|
this.loadProfile()
|
|
},
|
|
async loadProfile() {
|
|
this.setData({ loading: true, error: '' })
|
|
await app.ensureLogin()
|
|
if (!app.globalData.openid) {
|
|
this.setData({ loading: false, error: '登录失败,请重试' })
|
|
return
|
|
}
|
|
wx.request({
|
|
url: `${app.globalData.baseUrl}/api/v1/auth/profile`,
|
|
method: 'GET',
|
|
data: { openid: app.globalData.openid },
|
|
success: (res) => {
|
|
const profile = res.data?.data || {}
|
|
const avatarUrl = profile.avatar_url || wx.getStorageSync(`avatarUrl:${app.globalData.openid}`) || ''
|
|
const nickname = profile.nickname || '考研搭子'
|
|
const normalizedAvatar = avatarUrl.startsWith('http') ? avatarUrl : avatarUrl ? `${app.globalData.baseUrl}${avatarUrl}` : ''
|
|
this.setData({
|
|
openid: app.globalData.openid,
|
|
name: nickname,
|
|
nickname,
|
|
avatarUrl: normalizedAvatar,
|
|
nicknameDraft: nickname,
|
|
})
|
|
},
|
|
fail: () => {
|
|
const storedAvatarUrl = wx.getStorageSync(`avatarUrl:${app.globalData.openid}`) || ''
|
|
const normalizedAvatar = storedAvatarUrl.startsWith('http') ? storedAvatarUrl : storedAvatarUrl ? `${app.globalData.baseUrl}${storedAvatarUrl}` : ''
|
|
this.setData({ openid: app.globalData.openid, name: '考研搭子', nickname: '考研搭子', avatarUrl: normalizedAvatar, nicknameDraft: '考研搭子' })
|
|
},
|
|
complete: () => {
|
|
this.loadAchievements()
|
|
this.setData({ loading: false })
|
|
},
|
|
})
|
|
},
|
|
openNicknameModal() {
|
|
this.setData({ showNicknameModal: true, nicknameDraft: this.data.nickname || this.data.name || '考研搭子' })
|
|
},
|
|
onAvatarError() {
|
|
this.setData({ avatarUrl: '' })
|
|
},
|
|
closeNicknameModal() {
|
|
this.setData({ showNicknameModal: false, nicknameDraft: this.data.nickname || this.data.name || '考研搭子' })
|
|
},
|
|
onNicknameInput(e) {
|
|
this.setData({ nicknameDraft: e.detail.value })
|
|
},
|
|
saveNickname() {
|
|
if (!app.globalData.openid) return
|
|
const nickname = (this.data.nicknameDraft || '').trim()
|
|
if (!nickname) {
|
|
wx.showToast({ title: '昵称不能为空', icon: 'none' })
|
|
return
|
|
}
|
|
wx.request({
|
|
url: `${app.globalData.baseUrl}/api/v1/auth/profile`,
|
|
method: 'PUT',
|
|
header: { 'Content-Type': 'application/json' },
|
|
data: { openid: app.globalData.openid, nickname },
|
|
success: (res) => {
|
|
const profile = res.data?.data || {}
|
|
const nextNickname = profile.nickname || nickname
|
|
this.setData({ nickname: nextNickname, name: nextNickname, nicknameDraft: nextNickname, showNicknameModal: false })
|
|
wx.showToast({ title: '昵称已保存', icon: 'success' })
|
|
},
|
|
fail: () => wx.showToast({ title: '保存失败', icon: 'none' }),
|
|
})
|
|
},
|
|
chooseAvatar() {
|
|
if (!app.globalData.openid) {
|
|
wx.showToast({ title: '请先登录', icon: 'none' })
|
|
return
|
|
}
|
|
wx.chooseImage({
|
|
count: 1,
|
|
sizeType: ['compressed'],
|
|
sourceType: ['album', 'camera'],
|
|
success: (res) => {
|
|
const localPath = res.tempFilePaths?.[0] || ''
|
|
if (!localPath) return
|
|
wx.getImageInfo({
|
|
src: localPath,
|
|
success: (info) => {
|
|
const size = 320
|
|
const side = Math.min(info.width, info.height)
|
|
const x = Math.max(0, Math.floor((info.width - side) / 2))
|
|
const y = Math.max(0, Math.floor((info.height - side) / 2))
|
|
const ctx = wx.createCanvasContext('avatar-canvas', this)
|
|
ctx.clearRect(0, 0, size, size)
|
|
ctx.save()
|
|
ctx.beginPath()
|
|
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI)
|
|
ctx.clip()
|
|
ctx.drawImage(localPath, x, y, side, side, 0, 0, size, size)
|
|
ctx.draw(false, () => {
|
|
wx.canvasToTempFilePath({
|
|
canvasId: 'avatar-canvas',
|
|
width: size,
|
|
height: size,
|
|
destWidth: size,
|
|
destHeight: size,
|
|
quality: 0.85,
|
|
success: (canvasRes) => {
|
|
const uploadPath = canvasRes.tempFilePath || localPath
|
|
wx.uploadFile({
|
|
url: `${app.globalData.baseUrl}/api/v1/auth/avatar?openid=${encodeURIComponent(app.globalData.openid)}`,
|
|
filePath: uploadPath,
|
|
name: 'file',
|
|
success: (uploadRes) => {
|
|
try {
|
|
const payload = JSON.parse(uploadRes.data)
|
|
const avatarUrl = payload?.data?.avatar_url || ''
|
|
if (!avatarUrl) throw new Error('missing avatar_url')
|
|
const fullUrl = avatarUrl.startsWith('http') ? avatarUrl : `${app.globalData.baseUrl}${avatarUrl}`
|
|
wx.setStorageSync(`avatarUrl:${app.globalData.openid}`, fullUrl)
|
|
this.setData({ avatarUrl: fullUrl })
|
|
wx.request({
|
|
url: `${app.globalData.baseUrl}/api/v1/auth/profile`,
|
|
method: 'GET',
|
|
data: { openid: app.globalData.openid },
|
|
success: (profileRes) => {
|
|
const profile = profileRes.data?.data || {}
|
|
const nextNickname = profile.nickname || '考研搭子'
|
|
this.setData({ name: nextNickname, avatarUrl: fullUrl })
|
|
},
|
|
})
|
|
wx.showToast({ title: '头像已上传', icon: 'success' })
|
|
} catch (err) {
|
|
wx.showToast({ title: '头像上传失败', icon: 'none' })
|
|
}
|
|
},
|
|
fail: () => wx.showToast({ title: '头像上传失败', icon: 'none' }),
|
|
})
|
|
},
|
|
fail: () => wx.showToast({ title: '头像处理失败', icon: 'none' }),
|
|
}, this)
|
|
})
|
|
},
|
|
fail: () => wx.showToast({ title: '头像处理失败', icon: 'none' }),
|
|
})
|
|
},
|
|
})
|
|
},
|
|
loadAchievements() {
|
|
if (!app.globalData.openid) {
|
|
this.setData({ error: '未获取到登录态' })
|
|
return
|
|
}
|
|
wx.request({
|
|
url: `${app.globalData.baseUrl}/api/v1/achievements`,
|
|
header: { 'X-OpenID': app.globalData.openid },
|
|
success: (res) => {
|
|
const list = res.data?.data || []
|
|
const badges = Array.isArray(list) ? list.filter((i) => i.is_unlocked).length : 0
|
|
this.setData({ badges })
|
|
},
|
|
fail: () => this.setData({ error: '成就数据加载失败' }),
|
|
})
|
|
},
|
|
goTo(e) {
|
|
const { url } = e.currentTarget.dataset
|
|
if (!app.globalData.openid) {
|
|
wx.showToast({ title: '请先登录', icon: 'none' })
|
|
return
|
|
}
|
|
wx.navigateTo({ url })
|
|
},
|
|
goHome() {
|
|
wx.reLaunch({ url: '/pages/index/index' })
|
|
},
|
|
goToReview() {
|
|
wx.navigateTo({ url: '/pages/review-config/review-config' })
|
|
},
|
|
goToMe() {},
|
|
noop() {},
|
|
})
|