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.
This commit is contained in:
parent
21c5bb9b57
commit
e871eed0e8
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
<view wx:elif="{{!loading}}" class="empty-state">
|
||||
<image class="empty-icon" src="/images/empty-ranking.svg" mode="aspectFit"></image>
|
||||
<text class="empty-title">暂无排名数据</text>
|
||||
<text class="empty-desc">每月完成3场比赛即可上榜</text>
|
||||
<text class="empty-desc">暂无排名数据</text>
|
||||
</view>
|
||||
<!-- 加载更多 -->
|
||||
<view wx:if="{{loading}}" class="loading-state">
|
||||
|
||||
@ -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 })
|
||||
|
||||
@ -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,13 +80,19 @@ class LadderController {
|
||||
|
||||
// 添加排名
|
||||
const startRank = offset + 1;
|
||||
const list = rows.map((lu, index) => ({
|
||||
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: lu.user?.avatar,
|
||||
avatar: avatar || null,
|
||||
gender: lu.gender,
|
||||
level: lu.level,
|
||||
levelName: LADDER_LEVEL_NAMES[lu.level],
|
||||
@ -104,7 +103,8 @@ class LadderController {
|
||||
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,
|
||||
|
||||
@ -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,用于前端判断
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user