From e871eed0e86b4a584a40319b6245db448de4138c Mon Sep 17 00:00:00 2001 From: ethanfly Date: Tue, 10 Feb 2026 01:27:52 +0800 Subject: [PATCH] refactor: Improve data validation and avatar normalization - Simplified data validation logic in the index.js file to handle cases where data is missing or incomplete. - Updated the index.wxml file to provide a clearer message when no ranking data is available. - Added a new method to normalize avatar URLs in the helper.js file, ensuring that default avatars are handled correctly across user and match controllers. - Refactored user and match controllers to utilize the new avatar normalization method, enhancing consistency in avatar display. --- miniprogram/pages/index/index.js | 12 +-- miniprogram/pages/index/index.wxml | 2 +- .../pages/match/challenge-detail/index.js | 13 +++ server/src/controllers/ladderController.js | 88 ++++++++----------- server/src/controllers/matchController.js | 16 ++-- server/src/controllers/userController.js | 11 +-- server/src/utils/helper.js | 22 ++++- 7 files changed, 89 insertions(+), 75 deletions(-) diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js index 43d35a43..dd5c8346 100644 --- a/miniprogram/pages/index/index.js +++ b/miniprogram/pages/index/index.js @@ -156,17 +156,7 @@ Page({ }); const data = res && res.data ? res.data : null; - if (!data) return; - - if (data.qualified === false) { - wx.showToast({ - title: `本月场次不足(${data.monthlyMatchCount}/${data.minMonthlyMatches})`, - icon: "none", - }); - return; - } - - if (!data.ladderUserId || !data.page) { + if (!data || !data.ladderUserId || !data.page) { return; } diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml index 49668f91..f9f45e56 100644 --- a/miniprogram/pages/index/index.wxml +++ b/miniprogram/pages/index/index.wxml @@ -71,7 +71,7 @@ 暂无排名数据 - 每月完成3场比赛即可上榜 + 暂无排名数据 diff --git a/miniprogram/pages/match/challenge-detail/index.js b/miniprogram/pages/match/challenge-detail/index.js index 7a600d27..43f4d180 100644 --- a/miniprogram/pages/match/challenge-detail/index.js +++ b/miniprogram/pages/match/challenge-detail/index.js @@ -31,6 +31,19 @@ Page({ } }, + onPullDownRefresh() { + // 下拉刷新时重新加载比赛详情 + if (this.data.matchId) { + this.loadMatchDetail().then(() => { + wx.stopPullDownRefresh() + }).catch(() => { + wx.stopPullDownRefresh() + }) + } else { + wx.stopPullDownRefresh() + } + }, + // 加载比赛详情 async loadMatchDetail() { this.setData({ loading: true }) diff --git a/server/src/controllers/ladderController.js b/server/src/controllers/ladderController.js index 1444c53d..2201586c 100644 --- a/server/src/controllers/ladderController.js +++ b/server/src/controllers/ladderController.js @@ -37,13 +37,6 @@ class LadderController { status: 1, }; - // 如果不是大屏显示,则需要满足每月最低参赛场次限制 - if (!is_display) { - where.monthly_match_count = { - [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES, - }; - } - if (gender) { where.gender = gender; } @@ -87,24 +80,31 @@ class LadderController { // 添加排名 const startRank = offset + 1; - const list = rows.map((lu, index) => ({ - rank: startRank + index, - id: lu.id, - userId: lu.user_id, - realName: lu.real_name, - nickname: lu.user?.nickname, - avatar: lu.user?.avatar, - gender: lu.gender, - level: lu.level, - levelName: LADDER_LEVEL_NAMES[lu.level], - powerScore: lu.power_score, - matchCount: lu.match_count, - winCount: lu.win_count, - winRate: - lu.match_count > 0 - ? Math.round((lu.win_count / lu.match_count) * 100) - : 0, - })); + const list = rows.map((lu, index) => { + // 如果头像是服务端的默认头像URL,返回null让前端使用本地默认头像 + let avatar = lu.user?.avatar; + if (avatar && (avatar.includes('/images/avatar-default.svg') || avatar.includes('avatar-default'))) { + avatar = null; + } + return { + rank: startRank + index, + id: lu.id, + userId: lu.user_id, + realName: lu.real_name, + nickname: lu.user?.nickname, + avatar: avatar || null, + gender: lu.gender, + level: lu.level, + levelName: LADDER_LEVEL_NAMES[lu.level], + powerScore: lu.power_score, + matchCount: lu.match_count, + winCount: lu.win_count, + winRate: + lu.match_count > 0 + ? Math.round((lu.win_count / lu.match_count) * 100) + : 0, + }; + }); res.json(pageResult(list, count, page, pageSize)); } catch (err) { @@ -149,31 +149,11 @@ class LadderController { return res.status(404).json(error("未加入该门店天梯", 404)); } - if ( - !is_display && - (ladderUser.monthly_match_count || 0) < POWER_CALC.MIN_MONTHLY_MATCHES - ) { - return res.json( - success({ - qualified: false, - ladderUserId: ladderUser.id, - monthlyMatchCount: ladderUser.monthly_match_count || 0, - minMonthlyMatches: POWER_CALC.MIN_MONTHLY_MATCHES, - }), - ); - } - const where = { store_id, status: 1, }; - if (!is_display) { - where.monthly_match_count = { - [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES, - }; - } - if (normalizedGender) { where.gender = normalizedGender; } @@ -233,17 +213,22 @@ class LadderController { gender: ladderUser.gender, status: 1, power_score: { [Op.gt]: ladderUser.power_score }, - monthly_match_count: { [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES }, }, }); + // 如果头像是服务端的默认头像URL,返回null让前端使用本地默认头像 + let avatar = ladderUser.user?.avatar; + if (avatar && (avatar.includes('/images/avatar-default.svg') || avatar.includes('avatar-default'))) { + avatar = null; + } + res.json( success({ id: ladderUser.id, userId: ladderUser.user_id, realName: ladderUser.real_name, nickname: ladderUser.user?.nickname, - avatar: ladderUser.user?.avatar, + avatar: avatar || null, memberCode: ladderUser.user?.member_code, gender: ladderUser.gender, level: ladderUser.level, @@ -300,20 +285,25 @@ class LadderController { gender: ladderUser.gender, status: 1, power_score: { [Op.gt]: ladderUser.power_score }, - monthly_match_count: { [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES }, }, }); const matchCount = ladderUser.match_count || 0; const winCount = ladderUser.win_count || 0; + // 如果头像是服务端的默认头像URL,返回null让前端使用本地默认头像 + let avatar = ladderUser.user && ladderUser.user.avatar; + if (avatar && (avatar.includes('/images/avatar-default.svg') || avatar.includes('avatar-default'))) { + avatar = null; + } + res.json( success({ id: ladderUser.id, userId: ladderUser.user_id, realName: ladderUser.real_name, nickname: ladderUser.user && ladderUser.user.nickname, - avatar: ladderUser.user && ladderUser.user.avatar, + avatar: avatar || null, memberCode: ladderUser.user && ladderUser.user.member_code, gender: ladderUser.gender, level: ladderUser.level, diff --git a/server/src/controllers/matchController.js b/server/src/controllers/matchController.js index b2c1a9d8..5af131d0 100644 --- a/server/src/controllers/matchController.js +++ b/server/src/controllers/matchController.js @@ -1,6 +1,6 @@ const { Match, MatchGame, MatchPlayer, MatchRound, LadderUser, User, Store, sequelize } = require('../models'); const { MATCH_TYPES, MATCH_STATUS, CONFIRM_STATUS, RANKING_STAGE, MATCH_WEIGHTS, POWER_CALC } = require('../config/constants'); -const { generateMatchCode, success, error, getPagination, pageResult } = require('../utils/helper'); +const { generateMatchCode, success, error, getPagination, pageResult, normalizeAvatarForClient } = require('../utils/helper'); const PowerCalculator = require('../services/powerCalculator'); const { sendChallengeNotification, sendScoreConfirmNotification, sendMatchNotification, broadcastToUsers } = require('../websocket'); const matchAdminController = require('./matchAdminController'); @@ -949,7 +949,7 @@ class MatchController { ladderUserId: p.ladder_user_id, realName: p.ladderUser?.real_name || `选手${p.ladder_user_id}`, nickname: p.ladderUser?.user?.nickname, - avatar: p.ladderUser?.user?.avatar, + avatar: normalizeAvatarForClient(p.ladderUser?.user?.avatar, req), level: p.ladderUser?.level }); } @@ -1005,7 +1005,7 @@ class MatchController { ladderUserId: p.ladder_user_id, realName: p.ladderUser?.real_name, nickname: p.ladderUser?.user?.nickname, - avatar: p.ladderUser?.user?.avatar, + avatar: normalizeAvatarForClient(p.ladderUser?.user?.avatar, req), level: p.ladderUser?.level, initialPower: p.initial_power, winCount: p.win_count, @@ -1140,7 +1140,7 @@ class MatchController { id: opponent.id, realName: opponent.real_name, nickname: opponent.user?.nickname, - avatar: opponent.user?.avatar, + avatar: normalizeAvatarForClient(opponent.user?.avatar, req), level: opponent.level, powerScore: opponent.power_score }, @@ -1433,7 +1433,7 @@ class MatchController { id: opponent.id, realName: opponent.real_name, nickname: opponent.user && opponent.user.nickname, - avatar: opponent.user && opponent.user.avatar, + avatar: normalizeAvatarForClient(opponent.user && opponent.user.avatar, req), level: opponent.level, powerScore: opponent.power_score } @@ -1544,7 +1544,7 @@ class MatchController { id: opponentLadder.id, realName: opponentLadder.real_name, nickname: opponentLadder.user?.nickname, - avatar: opponentLadder.user?.avatar, + avatar: normalizeAvatarForClient(opponentLadder.user?.avatar, req), level: opponentLadder.level, powerScore: opponentLadder.power_score }; @@ -1823,7 +1823,7 @@ class MatchController { id: challengerLadder.id, realName: challengerLadder.real_name, nickname: challengerLadder.user?.nickname, - avatar: challengerLadder.user?.avatar, + avatar: normalizeAvatarForClient(challengerLadder.user?.avatar, req), level: challengerLadder.level, powerScore: challengerLadder.power_score, userId: challengerLadder.user_id, // 添加 user_id,用于前端判断 @@ -1836,7 +1836,7 @@ class MatchController { id: defenderLadder.id, realName: defenderLadder.real_name, nickname: defenderLadder.user?.nickname, - avatar: defenderLadder.user?.avatar, + avatar: normalizeAvatarForClient(defenderLadder.user?.avatar, req), level: defenderLadder.level, powerScore: defenderLadder.power_score, userId: defenderLadder.user_id, // 添加 user_id,用于前端判断 diff --git a/server/src/controllers/userController.js b/server/src/controllers/userController.js index db27eb1c..4c1ba8c9 100644 --- a/server/src/controllers/userController.js +++ b/server/src/controllers/userController.js @@ -10,6 +10,7 @@ const { calculateDistance, getFullUrl, normalizeAvatarUrl, + normalizeAvatarForClient, } = require("../utils/helper"); const { LADDER_LEVEL_NAMES } = require("../config/constants"); const { Op } = require("sequelize"); @@ -76,7 +77,7 @@ class UserController { responseData.userInfo = { id: user.id, nickname: user.nickname, - avatar: getFullUrl(user.avatar, req), + avatar: normalizeAvatarForClient(user.avatar, req), phone: user.phone, gender: user.gender, memberCode: user.member_code, @@ -96,7 +97,7 @@ class UserController { ? { id: user.id, nickname: user.nickname, - avatar: user.avatar, + avatar: normalizeAvatarForClient(user.avatar, req), phone: user.phone, gender: user.gender, memberCode: user.member_code, @@ -281,7 +282,7 @@ class UserController { userInfo: { id: user.id, nickname: user.nickname, - avatar: getFullUrl(user.avatar, req), + avatar: normalizeAvatarForClient(user.avatar, req), phone: user.phone, gender: user.gender, memberCode: user.member_code, @@ -373,7 +374,7 @@ class UserController { success( { nickname: user.nickname, - avatar: getFullUrl(user.avatar, req), + avatar: normalizeAvatarForClient(user.avatar, req), gender: user.gender, }, "更新成功", @@ -412,7 +413,7 @@ class UserController { const result = { id: user.id, nickname: user.nickname, - avatar: getFullUrl(user.avatar, req), + avatar: normalizeAvatarForClient(user.avatar, req), phone: user.phone, gender: user.gender, memberCode: user.member_code, diff --git a/server/src/utils/helper.js b/server/src/utils/helper.js index 810a50d5..de6314d7 100644 --- a/server/src/utils/helper.js +++ b/server/src/utils/helper.js @@ -204,6 +204,25 @@ function getFullUrl(path, req) { return `${protocol}://${host}${path}`; } +/** + * 规范化返回给客户端的头像URL + * 如果头像是服务端的默认头像URL,返回null让前端使用本地默认头像 + * @param {string} avatar - 头像URL(可能是完整URL或相对路径) + * @param {object} req - Express request对象(用于获取host) + * @returns {string|null} 规范化后的头像URL,如果是默认头像则返回null + */ +function normalizeAvatarForClient(avatar, req) { + if (!avatar) return null; + + // 检查是否是默认头像(相对路径或完整URL) + if (avatar.includes('/images/avatar-default.svg') || avatar.includes('avatar-default')) { + return null; + } + + // 使用 getFullUrl 处理其他头像URL + return getFullUrl(avatar, req) || null; +} + module.exports = { generateMemberCode, generateMatchCode, @@ -215,5 +234,6 @@ module.exports = { error, pageResult, getFullUrl, - normalizeAvatarUrl + normalizeAvatarUrl, + normalizeAvatarForClient };