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
};