diff --git a/achievements/achievements.js b/achievements/achievements.js
index c9db8df..d4c63a4 100644
--- a/achievements/achievements.js
+++ b/achievements/achievements.js
@@ -85,6 +85,7 @@ Page({
sections: [],
loading: false,
error: '',
+ heroBadgeIcon: HERO_BADGE_ICON,
},
onShow() {
this.loadData()
diff --git a/achievements/achievements.wxml b/achievements/achievements.wxml
index 0efa6a9..930164f 100644
--- a/achievements/achievements.wxml
+++ b/achievements/achievements.wxml
@@ -13,7 +13,7 @@
已点亮勋章 / {{total}}
-
+
diff --git a/me/me.js b/me/me.js
index d3928c5..26cd27f 100644
--- a/me/me.js
+++ b/me/me.js
@@ -1,5 +1,20 @@
const app = getApp()
+const DEFAULT_AVATAR = 'data:image/svg+xml;utf8,' + encodeURIComponent(`
+
+`)
+
Page({
data: {
name: '',
@@ -8,6 +23,7 @@ Page({
badges: 0,
openid: '',
avatarUrl: '',
+ defaultAvatarUrl: DEFAULT_AVATAR,
loading: false,
error: '',
showNicknameModal: false,
@@ -20,17 +36,16 @@ Page({
this.setData({ loading: true, error: '' })
await app.ensureLogin()
if (!app.globalData.openid) {
- this.setData({ loading: false, error: '????????' })
+ this.setData({ loading: false, error: '登录失败,请稍后重试' })
return
}
wx.request({
- url: `${app.globalData.baseUrl}/api/v1/auth/profile`,
+ url: `${app.globalData.baseUrl}/api/v1/auth/profile?openid=${encodeURIComponent(app.globalData.openid)}`,
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 nickname = profile.nickname || '考研战士'
const normalizedAvatar = avatarUrl.startsWith('http') ? avatarUrl : avatarUrl ? `${app.globalData.baseUrl}${avatarUrl}` : ''
this.setData({
openid: app.globalData.openid,
@@ -38,12 +53,21 @@ Page({
nickname,
avatarUrl: normalizedAvatar,
nicknameDraft: nickname,
+ days: Number(profile.days || 0),
+ error: '',
})
},
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: '????' })
+ this.setData({
+ openid: app.globalData.openid,
+ name: '考研战士',
+ nickname: '考研战士',
+ avatarUrl: normalizedAvatar,
+ nicknameDraft: '考研战士',
+ error: '个人信息加载失败,请稍后重试',
+ })
},
complete: () => {
this.loadAchievements()
@@ -52,13 +76,13 @@ Page({
})
},
openNicknameModal() {
- this.setData({ showNicknameModal: true, nicknameDraft: this.data.nickname || this.data.name || '????' })
+ 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 || '????' })
+ this.setData({ showNicknameModal: false, nicknameDraft: this.data.nickname || this.data.name || '考研战士' })
},
onNicknameInput(e) {
this.setData({ nicknameDraft: e.detail.value })
@@ -67,7 +91,7 @@ Page({
if (!app.globalData.openid) return
const nickname = (this.data.nicknameDraft || '').trim()
if (!nickname) {
- wx.showToast({ title: '??????', icon: 'none' })
+ wx.showToast({ title: '请输入昵称', icon: 'none' })
return
}
wx.request({
@@ -79,14 +103,14 @@ Page({
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' })
+ wx.showToast({ title: '保存成功', icon: 'success' })
},
- fail: () => wx.showToast({ title: '????', icon: 'none' }),
+ fail: () => wx.showToast({ title: '保存失败', icon: 'none' }),
})
},
chooseAvatar() {
if (!app.globalData.openid) {
- wx.showToast({ title: '????', icon: 'none' })
+ wx.showToast({ title: '请先登录', icon: 'none' })
return
}
wx.chooseImage({
@@ -133,35 +157,34 @@ Page({
wx.setStorageSync(`avatarUrl:${app.globalData.openid}`, fullUrl)
this.setData({ avatarUrl: fullUrl })
wx.request({
- url: `${app.globalData.baseUrl}/api/v1/auth/profile`,
+ url: `${app.globalData.baseUrl}/api/v1/auth/profile?openid=${encodeURIComponent(app.globalData.openid)}`,
method: 'GET',
- data: { openid: app.globalData.openid },
success: (profileRes) => {
const profile = profileRes.data?.data || {}
- const nextNickname = profile.nickname || '????'
- this.setData({ name: nextNickname, avatarUrl: fullUrl })
+ const nextNickname = profile.nickname || '考研战士'
+ this.setData({ name: nextNickname, nickname: nextNickname, avatarUrl: fullUrl })
},
})
- wx.showToast({ title: '?????', icon: 'success' })
+ wx.showToast({ title: '头像已更新', icon: 'success' })
} catch (err) {
- wx.showToast({ title: '??????', icon: 'none' })
+ wx.showToast({ title: '头像更新失败', icon: 'none' })
}
},
- fail: () => wx.showToast({ title: '??????', icon: 'none' }),
+ fail: () => wx.showToast({ title: '头像上传失败', icon: 'none' }),
})
},
- fail: () => wx.showToast({ title: '??????', icon: 'none' }),
+ fail: () => wx.showToast({ title: '头像处理失败', icon: 'none' }),
}, this)
})
},
- fail: () => wx.showToast({ title: '??????', icon: 'none' }),
+ fail: () => wx.showToast({ title: '读取图片失败', icon: 'none' }),
})
},
})
},
loadAchievements() {
if (!app.globalData.openid) {
- this.setData({ error: '???????' })
+ this.setData({ error: '登录状态已失效,请重新进入页面' })
return
}
wx.request({
@@ -172,13 +195,13 @@ Page({
const badges = Array.isArray(list) ? list.filter((i) => i.is_unlocked).length : 0
this.setData({ badges })
},
- fail: () => this.setData({ error: '????????' }),
+ fail: () => this.setData({ error: '成就数据加载失败,请稍后重试' }),
})
},
goTo(e) {
const { url } = e.currentTarget.dataset
if (!app.globalData.openid) {
- wx.showToast({ title: '????', icon: 'none' })
+ wx.showToast({ title: '请先登录', icon: 'none' })
return
}
wx.navigateTo({ url })
diff --git a/me/me.wxml b/me/me.wxml
index f6edc78..ecef783 100644
--- a/me/me.wxml
+++ b/me/me.wxml
@@ -14,7 +14,7 @@
-
+
更换头像
diff --git a/progress/achievements/achievements.js b/progress/achievements/achievements.js
index f6ca52d..02174a0 100644
--- a/progress/achievements/achievements.js
+++ b/progress/achievements/achievements.js
@@ -1,32 +1,41 @@
const app = getApp()
+function staticIcon(path) {
+ const base = app.globalData.staticBaseUrl || ''
+ const cleanBase = base.replace(/\/$/, '')
+ const cleanPath = path.replace(/^\/+/, '')
+ return `${cleanBase}/${cleanPath}`
+}
+
+const HERO_BADGE_ICON = staticIcon('/icons/achievements/state/achievement-unlocked.svg')
+
const ACHIEVEMENT_ICON_MAP = {
- MASTERED_100: '/assets/icons/achievements/core/100.svg',
- MASTERED_1000: '/assets/icons/achievements/core/1000.svg',
- MASTERED_3000: '/assets/icons/achievements/core/3000.svg',
- MASTERED_5000: '/assets/icons/achievements/core/5000.svg',
- MASTERED_7000: '/assets/icons/achievements/core/7000.svg',
- MASTERED_10000: '/assets/icons/achievements/core/10000.svg',
- TOTAL_100: '/assets/icons/achievements/core/total-100.svg',
- CHECKIN_7: '/assets/icons/achievements/core/checkin-30.svg',
- CHECKIN_30: '/assets/icons/achievements/core/checkin-30.svg',
- CHECKIN_100: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_180: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_360: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_STREAK_7: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_STREAK_30: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_STREAK_100: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_STREAK_180: '/assets/icons/achievements/core/streak.svg',
- CHECKIN_STREAK_360: '/assets/icons/achievements/core/streak.svg',
- ACCURACY_80: '/assets/icons/achievements/core/accuracy.svg',
- ACCURACY_90: '/assets/icons/achievements/core/accuracy.svg',
- DAILY_REVIEW_20: '/assets/icons/achievements/core/review-volume.svg',
- DAILY_REVIEW_50: '/assets/icons/achievements/core/review-volume.svg',
+ MASTERED_100: staticIcon('/icons/achievements/core/100.svg'),
+ MASTERED_1000: staticIcon('/icons/achievements/core/1000.svg'),
+ MASTERED_3000: staticIcon('/icons/achievements/core/3000.svg'),
+ MASTERED_5000: staticIcon('/icons/achievements/core/5000.svg'),
+ MASTERED_7000: staticIcon('/icons/achievements/core/7000.svg'),
+ MASTERED_10000: staticIcon('/icons/achievements/core/10000.svg'),
+ TOTAL_100: staticIcon('/icons/achievements/core/total-100.svg'),
+ CHECKIN_7: staticIcon('/icons/achievements/core/checkin-30.svg'),
+ CHECKIN_30: staticIcon('/icons/achievements/core/checkin-30.svg'),
+ CHECKIN_100: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_180: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_360: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_STREAK_7: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_STREAK_30: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_STREAK_100: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_STREAK_180: staticIcon('/icons/achievements/core/streak.svg'),
+ CHECKIN_STREAK_360: staticIcon('/icons/achievements/core/streak.svg'),
+ ACCURACY_80: staticIcon('/icons/achievements/core/accuracy.svg'),
+ ACCURACY_90: staticIcon('/icons/achievements/core/accuracy.svg'),
+ DAILY_REVIEW_20: staticIcon('/icons/achievements/core/review-volume.svg'),
+ DAILY_REVIEW_50: staticIcon('/icons/achievements/core/review-volume.svg'),
}
const STATUS_ICON_MAP = {
- 1: '/assets/icons/achievements/state/achievement-unlocked.svg',
- 0: '/assets/icons/achievements/state/achievement-locked.svg',
+ 1: staticIcon('/icons/achievements/state/achievement-unlocked.svg'),
+ 0: staticIcon('/icons/achievements/state/achievement-locked.svg'),
}
const GROUP_ORDER = {
@@ -39,12 +48,12 @@ const GROUP_ORDER = {
}
const GROUP_META = {
- mastery: { title: '掌握进阶', subtitle: '从入门到精通', icon: '/assets/icons/achievements/core/mastery-advanced.svg' },
- checkin: { title: '打卡里程', subtitle: '记录坚持的脚步', icon: '/assets/icons/achievements/core/checkin-30.svg' },
- streak: { title: '连续坚持', subtitle: '不断线的努力', icon: '/assets/icons/achievements/core/streak.svg' },
- accuracy: { title: '准确率', subtitle: '复习质量提升', icon: '/assets/icons/achievements/core/accuracy.svg' },
- review: { title: '复习数量', subtitle: '积累复习量', icon: '/assets/icons/achievements/core/review-volume.svg' },
- other: { title: '其他', subtitle: '更多成就', icon: '/assets/icons/achievements/core/total-100.svg' },
+ mastery: { title: '掌握进阶', subtitle: '从入门到精通', icon: staticIcon('/icons/achievements/core/mastery-advanced.svg') },
+ checkin: { title: '打卡里程', subtitle: '记录坚持的脚步', icon: staticIcon('/icons/achievements/core/checkin-30.svg') },
+ streak: { title: '连续坚持', subtitle: '不断线的努力', icon: staticIcon('/icons/achievements/core/streak.svg') },
+ accuracy: { title: '准确率', subtitle: '复习质量提升', icon: staticIcon('/icons/achievements/core/accuracy.svg') },
+ review: { title: '复习数量', subtitle: '积累复习量', icon: staticIcon('/icons/achievements/core/review-volume.svg') },
+ other: { title: '其他', subtitle: '更多成就', icon: staticIcon('/icons/achievements/core/total-100.svg') },
}
const GROUP_PROGRESS = {
@@ -81,6 +90,7 @@ Page({
sections: [],
loading: false,
error: '',
+ heroBadgeIcon: HERO_BADGE_ICON,
},
onShow() {
this.loadData()
@@ -97,8 +107,8 @@ Page({
return (list || []).map((item) => ({
...item,
group: this.getGroup(item.achievement_code),
- icon: ACHIEVEMENT_ICON_MAP[item.achievement_code] || GROUP_META[this.getGroup(item.achievement_code)].icon,
- stateIcon: STATUS_ICON_MAP[item.is_unlocked] || STATUS_ICON_MAP[0],
+ icon: item.icon_url || ACHIEVEMENT_ICON_MAP[item.achievement_code] || GROUP_META[this.getGroup(item.achievement_code)].icon,
+ stateIcon: item.state_icon_url || STATUS_ICON_MAP[item.is_unlocked] || STATUS_ICON_MAP[0],
}))
},
buildSections(list) {
diff --git a/progress/achievements/achievements.wxml b/progress/achievements/achievements.wxml
index 0efa6a9..930164f 100644
--- a/progress/achievements/achievements.wxml
+++ b/progress/achievements/achievements.wxml
@@ -13,7 +13,7 @@
已点亮勋章 / {{total}}
-
+