Selaa lähdekoodia

sdk更新,月卡更新

Rockz-Home 1 kuukausi sitten
vanhempi
commit
2f65323465

+ 92 - 53
card/newCards/top1/api.js

@@ -1,3 +1,9 @@
+/**
+ * 请任何自动化工具每次更新本文档,要再下面的版本号自动加1,并更新日期
+ * 
+ * 版本号:1
+ * 日期:2025-12-4 16:14:00
+*/
 (function (window) {
     'use strict';
 
@@ -60,6 +66,7 @@
         'CardDetailQuery': {
             mcId: 101,
             mcName: '[Mock]线上马拉松',
+            nickName: '[Mock]用户昵称', // Added as per user request
             mcType: 1,
             beginSecond: Date.now() / 1000 - 86400 * 2,
             endSecond: Date.now() / 1000 + 86400 * 5,
@@ -68,21 +75,40 @@
             coiName: '个人组',
             ocaId: 201 // Mocked ocaId
         },
-        'MatchRsDetailQuery': [
-            { id: 1, name: '[Mock]活动1', status: 1 },
-            { id: 2, name: '[Mock]活动2', status: 0 }
-        ],
+        'MatchRsDetailQuery': { 
+            id: 1, 
+            name: '[Mock]活动1', 
+            status: 1, 
+            totalSysPoint: 100,
+            mcType: 1,
+            mcId: 101,
+            mcName: '[Mock]线上马拉松',
+            beginSecond: Date.now() / 1000 - 86400 * 2,
+            endSecond: Date.now() / 1000 + 86400 * 5,
+            nickName: '[Mock]用户昵称',
+            totalNum: 10,
+            totalDistanct: 5000,
+            totalDistanctRankNum: 5,
+            totalCp: 20,
+            totalCpRankNum: 3,
+            totalSysPointRankNum: 10,
+            fastPace: 300,
+            fastPaceRankNum: 8
+        },
         'CardRankDetailQuery': {
             totalRankRs: [
-                { nickName: 'Mock张三', score: 10000, headUrl: 'https://picsum.photos/40/40?random=1', rankNum: 1 },
-                { nickName: 'Mock李四', score: 9500, headUrl: 'https://picsum.photos/40/40?random=2', rankNum: 2 },
-                { nickName: 'Mock王五', score: 8800, headUrl: 'https://picsum.photos/40/40?random=3', rankNum: 3 },
-                { nickName: 'Mock赵六', score: 7200, headUrl: 'https://picsum.photos/40/40?random=4', rankNum: 4 },
-                { nickName: 'Mock小明', score: 6500, headUrl: 'https://picsum.photos/40/40?random=5', rankNum: 5 }
+                { userName: 'Mock张三', score: 10000, headUrl: 'https://picsum.photos/40/40?random=1', rankNum: 1, isSelf: 0, inRankNum: 1, isInGame: 0, additionalName: '计算机学院', isDispAdditionalName: 1, inGameUserNum: 0, isDispInGameUserNum: 0, isTodayFinishGame: 0 },
+                { userName: 'Mock李四', score: 9500, headUrl: 'https://picsum.photos/40/40?random=2', rankNum: 2, isSelf: 0, inRankNum: 2, isInGame: 0, additionalName: '土木建筑', isDispAdditionalName: 1, inGameUserNum: 0, isDispInGameUserNum: 0, isTodayFinishGame: 0 },
+                { userName: 'Mock王五', score: 8800, headUrl: 'https://picsum.photos/40/40?random=3', rankNum: 3, isSelf: 0, inRankNum: 3, isInGame: 0, additionalName: '艺术设计', isDispAdditionalName: 1, inGameUserNum: 0, isDispInGameUserNum: 0, isTodayFinishGame: 0 },
+                { userName: 'Mock赵六', score: 7200, headUrl: 'https://picsum.photos/40/40?random=4', rankNum: 4, isSelf: 0, inRankNum: 4, isInGame: 0, additionalName: '交通运输', isDispAdditionalName: 1, inGameUserNum: 0, isDispInGameUserNum: 0, isTodayFinishGame: 0 },
+                { userName: 'Mock小明', score: 6500, headUrl: 'https://picsum.photos/40/40?random=5', rankNum: 5, isSelf: 1, inRankNum: 5, isInGame: 0, additionalName: '信息工程', isDispAdditionalName: 1, inGameUserNum: 0, isDispInGameUserNum: 0, isTodayFinishGame: 0 }
             ],
             teamRankRs: [],
             inTeamRs: [],
-            otherRs: []
+            otherRs: [],
+            regionPaceRs: null,
+            regionTodayPaceRs: null,
+            regionSpeedRs: null
         },
         'UserCurrentRankNumQuery': { rankNum: 5 },
         'UserJoinCardQuery': { isJoin: false }, // 默认未报名
@@ -159,7 +185,7 @@
         'MapListQuery': [
             { mapId: 1, mapName: '[Mock]公园地图', latitude: 36.6, longitude: 117.0, activityList: [] }
         ],
-        'CompStatisticQuery': { totalDistance: 123.45, totalPeople: 1000 },
+        'CompStatisticQuery': { totalDistance: 5024, totalPeople: 1000, totalAnswerNum: 1500, totalCp: 8900 },
         'WarnMessageQuery': [
             { warnType: 1, warnTitle: '[Mock]黄牌警告', warnMessage: '您的成绩异常', iconUrl: 'https://picsum.photos/50/50?random=10' }
         ],
@@ -192,9 +218,9 @@
                 { orderNum: 2, isComplete: 0, showName: '未完2', relationType: 1, ocaId: 11, longitude: 117.2, latitude: 36.7, popupImg: 'https://picsum.photos/100/100?random=20' }
             ]
         },
-        'CardUriQuery': {}, // 暂无 Mock 结构
-        'MatchFinishInfoQuery': {}, // 暂无 Mock 结构
-        'RedisRebuild': {} // 暂无 Mock 结构
+        'CardUrlQuery': { url: 'https://mock-uri.colormaprun.com/card/nanning1/index.html'}, // 暂无 Mock 结构  
+        'MatchFininshInfoQuery': {}, // 暂无 Mock 结构
+        'RedisRebulid': {} // 暂无 Mock 结构
     };
 
     var API = {
@@ -214,10 +240,12 @@
             Config.token = token;
         },
 
-        request: function(endpoint, data) {
+        request: function(endpoint, data, method) {
+            var reqMethod = (method || 'POST').toUpperCase();
+            
             if (Config.useMock) {
                 return new Promise(function(resolve, reject) {
-                    Logger.log('[API-Mock] Request:', endpoint, data);
+                    Logger.log('[API-Mock] Request (' + reqMethod + '):', endpoint, data);
                     setTimeout(function() {
                         var mockData = MOCK_DB[endpoint];
                         if (endpoint === 'OnlineMcSignUp') MOCK_DB['UserJoinCardQuery'].isJoin = true;
@@ -230,30 +258,41 @@
             }
 
             var url = Config.baseUrl + endpoint;
-            var headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'token': Config.token };
-            var formData = new URLSearchParams();
-            for (var key in data) { if (data.hasOwnProperty(key)) formData.append(key, data[key]); }
 
-            Logger.log('[API] Request:', endpoint, data);
+            var body = null;
+            if (reqMethod === 'GET') {
+                var headers = { 'Content-Type': 'application/x-www-form-urlencoded','Authorization': 'Bearer ' + Config.token };
+                var params = new URLSearchParams();
+                for (var key in data) { if (data.hasOwnProperty(key)) params.append(key, data[key]); }
+                var queryString = params.toString();
+                if (queryString) url += '?' + queryString;
+            } else {
+                var headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'token': Config.token};
+                var formData = new URLSearchParams();
+                for (var key in data) { if (data.hasOwnProperty(key)) formData.append(key, data[key]); }
+                body = formData;
+            }
+
+            Logger.log('[API] Request (' + reqMethod + '):', endpoint, data);
 
-            return fetch(url, { method: 'POST', headers: headers, body: formData, mode: 'cors', credentials: 'omit' })
+            return fetch(url, { method: reqMethod, headers: headers, body: body, mode: 'cors', credentials: 'omit' })
             .then(function(response) { return response.json(); })
             .then(function(res) {
                 Logger.log('[API] Response:', endpoint, res);
                 if (res.code === 0) return res.data;
-                if (res.code === 401 || res.statusCode === 401) {
-                    Logger.warn('[API] Token invalid');
-                    if (window.Bridge && window.Bridge._post) window.Bridge._post('toLogin');
-                    else alert('登录已过期');
-                    throw new Error('Unauthorized');
-                }
-                var msg = res.message || '请求失败';
-                if (window.Bridge && window.Bridge.showToast) {
-                    window.Bridge.showToast(msg, 'none');
-                } else {
-                    alert(msg);
-                }
-                throw new Error(msg);
+                // if (res.code === 401 || res.statusCode === 401) {
+                //     Logger.warn('[API] Token invalid');
+                //     if (window.Bridge && window.Bridge._post) window.Bridge._post('toLogin');
+                //     else alert('登录已过期');
+                //     throw new Error('Unauthorized');
+                // }
+                // var msg = res.message || '请求失败';
+                // if (window.Bridge && window.Bridge.showToast) {
+                //     window.Bridge.showToast(msg, 'none');
+                // } else {
+                //     alert(msg);
+                // }
+                // throw new Error(msg);
             })
             .catch(function(err) { Logger.error('[API] Error:', err); throw err; });
         },
@@ -263,16 +302,16 @@
         // ==============================
 
         // 1. 卡片基本信息查询
-        getCardBase: function(ecId, pageName) { return this.request('CardBaseQuery', { ecId: ecId, pageName: pageName }); },
+        getCardBase: function(ecId) { return this.request('CardBaseQuery', { ecId: ecId }); },
 
         // 2. 卡片对应活动或赛事详情查询
         getCardDetail: function(ecId) { return this.request('CardDetailQuery', { ecId: ecId }); },
 
         // 3. 卡片对应线上赛多个活动查询
-        getMatchRsDetail: function(ecId) { return this.request('MatchRsDetailQuery', { ecId: ecId }); },
+        getMatchRsDetail: function(ecId, ocaId) { return this.request('MatchRsDetailQuery', { ecId: ecId, ocaId: ocaId }); },
 
         // 4. 排名查询
-        getRankDetail: function(mcIdListStr, mcType, dispArrStr) { return this.request('CardRankDetailQuery', { mcIdListStr: mcIdListStr, mcType: mcType, dispArrStr: dispArrStr }); },
+        getRankDetail: function(mcIdListStr, mcType, ocaId, dispArrStr) { return this.request('CardRankDetailQuery', { mcIdListStr: mcIdListStr, mcType: mcType, ocaId: ocaId, dispArrStr: dispArrStr }); },
 
         // 5. 卡片用户当前排名查询
         getUserCurrentRank: function(ecId) { return this.request('UserCurrentRankNumQuery', { ecId: ecId }); },
@@ -284,7 +323,7 @@
         isNewUserInCardComp: function(ecId) { return this.request('IsNewUserInCardComp', { ecId: ecId }); },
 
         // 8. 线上赛报名页面信息详情
-        getOnlineMcSignUpDetail: function(ecId) { return this.request('OnlineMcSignUpDetail', { ecId: ecId }); },
+        getOnlineMcSignUpDetail: function(ecId, mcId) { return this.request('OnlineMcSignUpDetail', { ecId: ecId, mcId: mcId }); },
 
         // 9. 线上赛报名(重新分组)
         signUpOnline: function(mcId, coiId, selectTeam, nickName) { 
@@ -295,7 +334,7 @@
         isAllowMcSignUp: function(ecId) { return this.request('IsAllowMcSignUp', { ecId: ecId }); },
 
         // 11. 玩家当前月挑战记录查询
-        getCurrentMonthlyChallenge: function() { return this.request('CurrentMonthlyChallengeQuery', {}); },
+        getCurrentMonthlyChallenge: function(year, month) { return this.request('CurrentMonthlyChallengeQuery', {year: year, month: month}); },
 
         // 12. 卡片配置信息查询
         getCardConfig: function(ecId, pageName) { return this.request('CardConfigQuery', { ecId: ecId, pageName: pageName }); },
@@ -307,16 +346,16 @@
         getMonthlyChallenge: function() { return this.request('MonthlyChallengeQuery', {}); },
 
         // 15. 月挑战排名查询
-        getMonthRankDetail: function() { return this.request('MonthRankDetailQuery', {}); },
+        getMonthRankDetail: function(year, month, dispArrStr) { return this.request('MonthRankDetailQuery', {year: year, month: month, dispArrStr: dispArrStr}); },
 
         // 16. 玩家活动成就查询
         getAchievement: function() { return this.request('AchievementQuery', {}); },
 
         // 17. 玩家兑换记录查询
-        getExchangeList: function(ecId) { return this.request('ExchangeListQuery', { ecId: ecId }); },
+        getExchangeList: function() { return this.request('ExchangeListQuery', {}); },
 
         // 18. 玩家兑换详情查询
-        getExchangeDetail: function(ecId, exchangeId) { return this.request('ExchangeDetailQuery', { ecId: ecId, exchangeId: exchangeId }); },
+        getExchangeDetail: function(oarId) { return this.request('ExchangeDetailQuery', { oarId: oarId}); },
 
         // 19. 未读消息列表查询
         getUnReadMessages: function(relationId, relationType) { return this.request('UnReadMessageQuery', { relationId: relationId, relationType: relationType || 2 }); },
@@ -325,22 +364,22 @@
         readMessage: function(mqIdListStr) { return this.request('ReadMessage', { mqIdListStr: mqIdListStr }); },
 
         // 21. 卡片对应地图列表详情查询
-        getMapList: function(ecId) { return this.request('MapListQuery', { ecId: ecId }); },
+        getMapList: function(mcId) { return this.request('MapListQuery', { mcId: mcId }); },
 
         // 22. 赛事总成绩统计查询
-        getCompStatistic: function(ecId) { return this.request('CompStatisticQuery', { ecId: ecId }); },
+        getCompStatistic: function(mcId) { return this.request('CompStatisticQuery', { mcId: mcId }); },
 
         // 23. 警告列表查询
         getWarnMessage: function(ecId) { return this.request('WarnMessageQuery', { ecId: ecId }); },
 
         // 24. 查询电子证书样式
-        getCertStyle: function(ecId) { return this.request('CertStyleQuery', { ecId: ecId }); },
+        getCertStyle: function(certStyleType) { return this.request('CertStyleQuery', { certStyleType: certStyleType }); },
 
         // 25. 查询电子证书成就对应用户基本信息
-        getUserBaseInCertificate: function(ecId) { return this.request('UserBaseQueryInCertificate', { ecId: ecId }); },
+        getUserBaseInCertificate: function(oarId) { return this.request('UserBaseQueryInCertificate', { oarId: oarId }); },
 
         // 26. 根据成就信息确认生成电子证书
-        createCertificate: function(data) { return this.request('CertificateCreateByUserAi', data); },
+        createCertificate: function(nickName,oarId) { return this.request('CertificateCreateByUserAi', {nickName: nickName, oarId: oarId}); },
 
         // 27. 卡片内可用积分查询
         getScore: function(ecId) { return this.request('OnlineScoreQuery', { ecId: ecId }); },
@@ -349,25 +388,25 @@
         getGoodsList: function(ecId) { return this.request('CanExchangeGoodsList', { ecId: ecId }); },
 
         // 29. 积分可兑换商品详情
-        getGoodsDetail: function(goodsId) { return this.request('CanExchangeGoodsDetail', { goodsId: goodsId }); },
+        getGoodsDetail: function(ecId, goodsId) { return this.request('CanExchangeGoodsDetail', {ecid: ecId, goodsId: goodsId }); },
 
         // 30. 积分兑换商品
-        exchangeGoods: function(ecId, goodsId) { return this.request('ScoreExchangeGoods', { ecId: ecId, goodsId: goodsId }); },
+        exchangeGoods: function(ecId, goodsId, exchNum) { return this.request('ScoreExchangeGoods', { ecId: ecId, goodsId: goodsId, exchNum: exchNum }); },
 
         // 31. 用户基本信息查询
-        getUserInfo: function() { return this.request('UserBasicInformationQuery', {}); },
+        getUserInfo: function() { return this.request('UserBasicInformationQuery', {}, 'GET'); },
 
         // 32. 网格卡片信息查询
         getGrids: function(ecId) { return this.request('GridsQuery', { ecId: ecId }); },
 
         // 33. 卡片URI查询
-        getCardUri: function(ecId) { return this.request('CardUriQuery', { ecId: ecId }); },
+        getCardUrl: function(actId, matchType) { return this.request('CardUrlQuery', { actId: actId, matchType: matchType }); },
 
         // 34. 赛事完赛信息查询
-        getMatchFinishInfo: function(ecId) { return this.request('MatchFinishInfoQuery', { ecId: ecId }); },
+        getMatchFininshInfo: function(actId, matchType) { return this.request('MatchFininshInfoQuery', { actId, matchType }); },
 
         // 35. Redis 重建 (管理接口)
-        redisRebuild: function(ecId) { return this.request('RedisRebuild', { ecId: ecId }); }
+        redisRebulid: function(compId) { return this.request('RedisRebulid', { compId: compId }); }
     };
 
     window.API = API;

+ 26 - 24
card/newCards/top1/detail-christmas.html

@@ -622,7 +622,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -665,7 +665,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -676,7 +676,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -684,12 +684,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -850,8 +858,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -887,21 +895,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 27 - 24
card/newCards/top1/detail-cloud.html

@@ -589,7 +589,7 @@
                 
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 const isActualFirst = (person === p1 && p1 !== null); 
 
@@ -630,7 +630,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -641,7 +641,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -649,13 +649,22 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
             
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
+            
+            // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
         }
 
@@ -803,8 +812,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -838,21 +847,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 26 - 24
card/newCards/top1/detail-newyear-fireworks.html

@@ -622,7 +622,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -665,7 +665,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -676,7 +676,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -684,12 +684,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -850,8 +858,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -887,21 +895,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 26 - 24
card/newCards/top1/detail-newyear.html

@@ -622,7 +622,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -665,7 +665,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -676,7 +676,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -684,12 +684,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -850,8 +858,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -887,21 +895,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 26 - 24
card/newCards/top1/detail-rain.html

@@ -585,7 +585,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -628,7 +628,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -639,7 +639,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -647,12 +647,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -813,8 +821,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -850,21 +858,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 64 - 36
card/newCards/top1/detail-snow.html

@@ -621,7 +621,7 @@
                 
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 const isActualFirst = (person === p1 && p1 !== null); 
 
@@ -662,7 +662,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -673,23 +673,57 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
-            const rankNumEl = document.getElementById('myRankNum');
-            const myScoreEl = document.getElementById('myScoreValue');
-            const myNameEl = document.getElementById('myName');
-            const myTeamEl = document.getElementById('myTeam');
-            const myAvatarEl = document.getElementById('myAvatar');
-            const rankVal = myRank && Number(myRank.rankNum);
-            const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
-            const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
-            myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
-            
-            document.querySelector('.my-rank-bar').onclick = null;
-        }
+                function renderMyInfo(myRank, myScore, userInfo, statusText) {
+
+                    const rankNumEl = document.getElementById('myRankNum');
+
+                    const myScoreEl = document.getElementById('myScoreValue');
+
+                    const myNameEl = document.getElementById('myName');
+
+                    const myTeamEl = document.getElementById('myTeam');
+
+                    const myAvatarEl = document.getElementById('myAvatar');
+
+                    const rankVal = myRank && Number(myRank.rankNum);
+
+                    const hasRank = rankVal > 0;
+
+                    
+
+                    rankNumEl.innerText = hasRank ? rankVal : '';
+
+                    myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+
+                    
+
+                    const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
+
+                    myNameEl.innerText = name;
+
+                    
+
+                    if (statusText !== undefined) {
+
+                        myTeamEl.innerText = statusText;
+
+                    } else {
+
+                        myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+
+                    }
+
+                    
+
+                    myAvatarEl.innerHTML = buildAvatar(name, name);
+
+                    
+
+                    // Remove click listener if exists (clean slate)
+
+                    document.querySelector('.my-rank-bar').onclick = null;
+
+                }
 
         function renderGuestState() {
             const rankNumEl = document.getElementById('myRankNum');
@@ -835,8 +869,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -870,21 +904,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 26 - 24
card/newCards/top1/detail-sun.html

@@ -587,7 +587,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -630,7 +630,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -641,7 +641,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -649,12 +649,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -815,8 +823,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -852,21 +860,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 26 - 24
card/newCards/top1/detail-windy.html

@@ -586,7 +586,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -629,7 +629,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -640,7 +640,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -648,12 +648,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -814,8 +822,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -851,21 +859,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 27 - 25
card/newCards/top1/detail.html

@@ -584,7 +584,7 @@
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
                 // Placeholder avatar for empty slots or Multiavatar for actual people
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#ddd;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;font-weight:bold;">?</div>';
 
                 // Only the actual first place gets the crown, and only if that person exists
                 const isActualFirst = (person === p1 && p1 !== null); 
@@ -627,7 +627,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '个人'}</div>
@@ -638,7 +638,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -646,12 +646,20 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '--';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续加油' : '';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续加油' : '继续加油';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
             
             // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
@@ -812,8 +820,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -846,24 +854,18 @@
                 renderPodium(state.scoreList, 'score');
                 switchTab(state.activeTab, document.querySelector('.tab.active'));
                 
-                if (!token && !useMock) {
+                if ((!token && !useMock) || !myRank) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
 

+ 28 - 24
card/newCards/top1/detail3.html

@@ -574,7 +574,7 @@
                 
                 const name = person ? (person.nickName || person.name || person.userName) : '虚位以待';
                 const score = person ? (person.score != null ? person.score : (person.inRankNum != null ? person.inRankNum : '')) : '';
-                const avatarContent = person ? buildAvatar(name, person.rankNum) : '<div style="width:100%;height:100%;background:#eee;color:#aaa;display:flex;align-items:center;justify-content:center;font-weight:bold;font-size:20px;">?</div>';
+                const avatarContent = person ? buildAvatar(name, name) : '<div style="width:100%;height:100%;background:#eee;color:#aaa;display:flex;align-items:center;justify-content:center;font-weight:bold;font-size:20px;">?</div>';
 
                 const isActualFirst = (person === p1 && p1 !== null); 
 
@@ -615,7 +615,7 @@
                 row.className = 'list-item';
                 row.innerHTML = `
                     <div class="rank">${rankNum}</div>
-                    <div class="avatar">${buildAvatar(name, rankNum)}</div>
+                    <div class="avatar">${buildAvatar(name, name)}</div>
                     <div class="info">
                         <div class="name">${name}</div>
                         <div class="team">${teamIcon}${team || '小小探险家'}</div>
@@ -626,7 +626,7 @@
             });
         }
 
-        function renderMyInfo(myRank, myScore, userInfo) {
+        function renderMyInfo(myRank, myScore, userInfo, statusText) {
             const rankNumEl = document.getElementById('myRankNum');
             const myScoreEl = document.getElementById('myScoreValue');
             const myNameEl = document.getElementById('myName');
@@ -634,12 +634,22 @@
             const myAvatarEl = document.getElementById('myAvatar');
             const rankVal = myRank && Number(myRank.rankNum);
             const hasRank = rankVal > 0;
-            rankNumEl.innerText = hasRank ? rankVal : '-';
-            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '--';
+            
+            rankNumEl.innerText = hasRank ? rankVal : '';
+            myScoreEl.innerText = hasRank && myScore && myScore.score != null ? myScore.score : '';
+            
             const name = (userInfo && (userInfo.nickName || userInfo.userName)) || '我';
             myNameEl.innerText = name;
-            myTeamEl.innerText = hasRank ? '继续冲刺!' : '加油!';
-            myAvatarEl.innerHTML = buildAvatar(name, 'me');
+            
+            if (statusText !== undefined) {
+                myTeamEl.innerText = statusText;
+            } else {
+                myTeamEl.innerText = hasRank ? '继续冲刺!' : '加油!';
+            }
+            
+            myAvatarEl.innerHTML = buildAvatar(name, name);
+            
+            // Remove click listener if exists (clean slate)
             document.querySelector('.my-rank-bar').onclick = null;
         }
 
@@ -787,8 +797,8 @@
                 let base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig;
                 if (useMock || allowLogin) {
                     [base, currentMonth, allMonths, myRank, myScore, userInfo, cardConfig] = await Promise.all([
-                        safeCall(() => API.getCardBase(ecId, 'rank')),
-                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { ecId: ecId })),
+                        safeCall(() => API.getCardBase(ecId)),
+                        safeCall(() => API.request('CurrentMonthlyChallengeQuery', { year: targetYM.year, month: targetYM.month })),
                         safeCall(() => API.getMonthlyChallenge()),
                         safeCall(() => API.getUserCurrentRank(ecId)),
                         safeCall(() => API.getScore(ecId)),
@@ -821,21 +831,15 @@
                 if (!token && !useMock) {
                     renderGuestState();
                 } else {
-                    let hasRenderedMyInfo = false;
-                    if (allowLogin && myRank) {
-                        const rankVal = Number(myRank.rankNum);
-                        if (rankVal > 0) {
-                            renderMyInfo({ rankNum: rankVal }, myScore, userInfo);
-                        } else {
-                            renderMyInfo({ rankNum: null }, null, userInfo);
-                        }
-                        hasRenderedMyInfo = true;
-                    } else if (selfRow) {
-                        renderMyInfo({ rankNum: selfRow.rankNum }, { score: selfRow.inRankNum || selfRow.score }, { nickName: selfRow.userName });
-                        hasRenderedMyInfo = true;
-                    }
-                    if (!hasRenderedMyInfo) {
-                        renderMyInfo(myRank, myScore, userInfo);
+                    const selfItem = monthGrad && monthGrad.find(item => item.isSelf === 1);
+                    if (selfItem) {
+                        renderMyInfo(
+                            { rankNum: selfItem.rankNum }, 
+                            { score: selfItem.score != null ? selfItem.score : selfItem.inRankNum }, 
+                            userInfo
+                        );
+                    } else {
+                        renderMyInfo(null, null, userInfo, '继续加油');
                     }
                 }
                 renderRules(cardConfig);

+ 36 - 23
card/sdk/api.js

@@ -240,10 +240,12 @@
             Config.token = token;
         },
 
-        request: function(endpoint, data) {
+        request: function(endpoint, data, method) {
+            var reqMethod = (method || 'POST').toUpperCase();
+            
             if (Config.useMock) {
                 return new Promise(function(resolve, reject) {
-                    Logger.log('[API-Mock] Request:', endpoint, data);
+                    Logger.log('[API-Mock] Request (' + reqMethod + '):', endpoint, data);
                     setTimeout(function() {
                         var mockData = MOCK_DB[endpoint];
                         if (endpoint === 'OnlineMcSignUp') MOCK_DB['UserJoinCardQuery'].isJoin = true;
@@ -256,30 +258,41 @@
             }
 
             var url = Config.baseUrl + endpoint;
-            var headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'token': Config.token };
-            var formData = new URLSearchParams();
-            for (var key in data) { if (data.hasOwnProperty(key)) formData.append(key, data[key]); }
 
-            Logger.log('[API] Request:', endpoint, data);
+            var body = null;
+            if (reqMethod === 'GET') {
+                var headers = { 'Content-Type': 'application/x-www-form-urlencoded','Authorization': 'Bearer ' + Config.token };
+                var params = new URLSearchParams();
+                for (var key in data) { if (data.hasOwnProperty(key)) params.append(key, data[key]); }
+                var queryString = params.toString();
+                if (queryString) url += '?' + queryString;
+            } else {
+                var headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'token': Config.token};
+                var formData = new URLSearchParams();
+                for (var key in data) { if (data.hasOwnProperty(key)) formData.append(key, data[key]); }
+                body = formData;
+            }
+
+            Logger.log('[API] Request (' + reqMethod + '):', endpoint, data);
 
-            return fetch(url, { method: 'POST', headers: headers, body: formData, mode: 'cors', credentials: 'omit' })
+            return fetch(url, { method: reqMethod, headers: headers, body: body, mode: 'cors', credentials: 'omit' })
             .then(function(response) { return response.json(); })
             .then(function(res) {
                 Logger.log('[API] Response:', endpoint, res);
                 if (res.code === 0) return res.data;
-                if (res.code === 401 || res.statusCode === 401) {
-                    Logger.warn('[API] Token invalid');
-                    if (window.Bridge && window.Bridge._post) window.Bridge._post('toLogin');
-                    else alert('登录已过期');
-                    throw new Error('Unauthorized');
-                }
-                var msg = res.message || '请求失败';
-                if (window.Bridge && window.Bridge.showToast) {
-                    window.Bridge.showToast(msg, 'none');
-                } else {
-                    alert(msg);
-                }
-                throw new Error(msg);
+                // if (res.code === 401 || res.statusCode === 401) {
+                //     Logger.warn('[API] Token invalid');
+                //     if (window.Bridge && window.Bridge._post) window.Bridge._post('toLogin');
+                //     else alert('登录已过期');
+                //     throw new Error('Unauthorized');
+                // }
+                // var msg = res.message || '请求失败';
+                // if (window.Bridge && window.Bridge.showToast) {
+                //     window.Bridge.showToast(msg, 'none');
+                // } else {
+                //     alert(msg);
+                // }
+                // throw new Error(msg);
             })
             .catch(function(err) { Logger.error('[API] Error:', err); throw err; });
         },
@@ -381,7 +394,7 @@
         exchangeGoods: function(ecId, goodsId, exchNum) { return this.request('ScoreExchangeGoods', { ecId: ecId, goodsId: goodsId, exchNum: exchNum }); },
 
         // 31. 用户基本信息查询
-        getUserInfo: function() { return this.request('UserBasicInformationQuery', {}); },
+        getUserInfo: function() { return this.request('UserBasicInformationQuery', {}, 'GET'); },
 
         // 32. 网格卡片信息查询
         getGrids: function(ecId) { return this.request('GridsQuery', { ecId: ecId }); },
@@ -390,10 +403,10 @@
         getCardUrl: function(actId, matchType) { return this.request('CardUrlQuery', { actId: actId, matchType: matchType }); },
 
         // 34. 赛事完赛信息查询
-        getMatchFinishInfo: function(actId, matchType) { return this.request('MatchFininshInfoQuery', { actId, matchType }); },
+        getMatchFininshInfo: function(actId, matchType) { return this.request('MatchFininshInfoQuery', { actId, matchType }); },
 
         // 35. Redis 重建 (管理接口)
-        redisRebuild: function(compId) { return this.request('RedisRebulid', { compId: compId }); }
+        redisRebulid: function(compId) { return this.request('RedisRebulid', { compId: compId }); }
     };
 
     window.API = API;