From 8337c34fcc761d07acaad796d10f3e12e9bbe2d1 Mon Sep 17 00:00:00 2001 From: lrj <owen.stl@gmail.com> Date: 星期日, 05 十月 2025 08:56:04 +0800 Subject: [PATCH] feat: 微信项目详情支持阶段评分时间轴 --- wx/pages/project/detail.js | 330 +++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 236 insertions(+), 94 deletions(-) diff --git a/wx/pages/project/detail.js b/wx/pages/project/detail.js index 9e95a97..6ce3629 100644 --- a/wx/pages/project/detail.js +++ b/wx/pages/project/detail.js @@ -5,12 +5,18 @@ data: { projectId: '', projectDetail: null, - ratingStats: null, + timeline: [], loading: true, error: '', statusText: '', genderText: '', - educationText: '' + educationText: '', + timelineLoading: false, + timelineError: '', + showRatingDetail: false, + ratingDetail: null, + ratingDetailLoading: false, + ratingDetailError: '' }, onLoad(options) { @@ -30,51 +36,38 @@ // 鍔犺浇椤圭洰璇︽儏 async loadProjectDetail() { try { - this.setData({ - loading: true, - error: '' + this.setData({ + loading: true, + error: '' }) - // 璋冪敤API鑾峰彇椤圭洰璇︽儏 const projectDetail = await this.getProjectDetailFromAPI(this.data.projectId) - - if (projectDetail) { - // 澶勭悊鏂囦欢澶у皬鏄剧ず - if (projectDetail.submissionFiles) { - projectDetail.submissionFiles.forEach(file => { - file.fileSizeText = this.formatFileSize(file.fileSize) - }) - } - // 鑾峰彇璇勫垎缁熻 - const ratingStats = await this.getRatingStatsFromAPI(this.data.projectId) - - // 澶勭悊璇勫垎鏃堕棿鏄剧ず - if (ratingStats && ratingStats.judgeRatings) { - ratingStats.judgeRatings.forEach(rating => { - if (rating.ratingTime) { - rating.ratingTimeText = this.formatDateTime(rating.ratingTime) - } - }) - } - - this.setData({ - projectDetail, - ratingStats, - statusText: this.getStatusText(projectDetail.state), - genderText: this.getGenderText(projectDetail.playerInfo?.gender), - educationText: this.getEducationText(projectDetail.playerInfo?.education), - loading: false - }) - } else { + if (!projectDetail) { throw new Error('椤圭洰璇︽儏鑾峰彇澶辫触') } + + if (projectDetail.submissionFiles) { + projectDetail.submissionFiles.forEach(file => { + file.fileSizeText = this.formatFileSize(file.fileSize) + }) + } + + this.setData({ + projectDetail, + statusText: this.getStatusText(projectDetail.state), + genderText: this.getGenderText(projectDetail.playerInfo?.gender), + educationText: this.getEducationText(projectDetail.playerInfo?.education) + }) + + await this.loadProjectTimeline(this.data.projectId) } catch (error) { console.error('鍔犺浇椤圭洰璇︽儏澶辫触:', error) this.setData({ - error: error.message || '鍔犺浇澶辫触锛岃閲嶈瘯', - loading: false + error: error.message || '鍔犺浇澶辫触锛岃閲嶈瘯' }) + } finally { + this.setData({ loading: false }) } }, @@ -85,42 +78,62 @@ query GetProjectDetail($id: ID!) { activityPlayerDetail(id: $id) { id - activityId - playerId - playerName - playerGender - playerPhone - playerEducation - playerBirthDate - playerIdCard - playerAddress + playerInfo { + id + name + phone + gender + birthday + education + introduction + description + avatarUrl + avatar { + id + fullUrl + fullThumbUrl + name + fileSize + fileExt + } + userInfo { + userId + name + phone + avatarUrl + } + } + regionInfo { + id + name + fullPath + } + activityName projectName - projectDescription - projectCategory - projectTags - projectFiles { - id - fileName - fileUrl - fileSize - fileType - uploadTime - } - submitTime - reviewTime - reviewerId - reviewerName - score - rating { - id - judgeId - judgeName - score - feedback - ratingTime - } - state + description feedback + state + stageId + submissionFiles { + id + fullUrl + fullThumbUrl + name + fileSize + fileExt + mediaType + } + ratingForm { + schemeId + schemeName + items { + id + name + maxScore + orderNo + } + totalMaxScore + } } } ` @@ -133,45 +146,174 @@ } }, - // 鑾峰彇璇勫垎缁熻 - async getRatingStatsFromAPI(projectId) { + async loadProjectTimeline(activityPlayerId) { + if (!activityPlayerId) { + return + } + + const idNumber = Number(activityPlayerId) + const variables = { + activityPlayerId: Number.isNaN(idNumber) ? activityPlayerId : idNumber + } + + this.setData({ + timelineLoading: true, + timelineError: '' + }) + const query = ` - query GetRatingStats($activityPlayerId: ID!) { - ratingStats(activityPlayerId: $activityPlayerId) { - averageScore - totalRatings - scoreDistribution { - score - count + query ProjectStageTimeline($activityPlayerId: ID!) { + projectStageTimeline(activityPlayerId: $activityPlayerId) { + activityId + activityName + stages { + stageId + stageName + matchTime + sortOrder + participated + activityPlayerId + averageScore + ratingCount + hasRating + latestRatingTime } } } ` try { - const result = await app.graphqlRequest(query, { activityPlayerId: projectId }) - return result.ratingStats + const result = await app.graphqlRequest(query, variables) + const projectStageTimeline = result && result.projectStageTimeline ? result.projectStageTimeline : null + const stages = projectStageTimeline && projectStageTimeline.stages ? projectStageTimeline.stages : [] + + const timeline = stages.map(stage => { + const hasScore = stage.hasRating && stage.averageScore !== null && stage.averageScore !== undefined + let scoreText = '鏈弬璧�' + if (stage.participated) { + scoreText = hasScore ? `骞冲潎鍒嗭細${Number(stage.averageScore).toFixed(2)}` : '鏈瘎鍒�' + } + + return { + ...stage, + matchTimeText: stage.matchTime ? this.formatDateTime(stage.matchTime) : '', + scoreText, + displayAverageScore: hasScore ? Number(stage.averageScore).toFixed(2) : null, + isClickable: stage.participated && hasScore && !!stage.activityPlayerId + } + }) + + this.setData({ + timeline, + timelineLoading: false + }) } catch (error) { - throw error + console.error('鍔犺浇闃舵鏃堕棿杞村け璐�:', error) + this.setData({ + timelineError: error.message || '鏃堕棿杞村姞杞藉け璐�', + timelineLoading: false + }) } }, - // 鑾峰彇璇勫璇勫垎璇︽儏 - async getJudgeRatingDetail(activityPlayerId, judgeId) { + async fetchStageRatingDetail(activityPlayerId) { + const idNumber = Number(activityPlayerId) + const variables = { + activityPlayerId: Number.isNaN(idNumber) ? activityPlayerId : idNumber + } + const query = ` - query GetJudgeRatingDetail($activityPlayerId: ID!, $judgeId: ID!) { - judgeRatingDetail(activityPlayerId: $activityPlayerId, judgeId: $judgeId) { - remark + query StageJudgeRatings($activityPlayerId: ID!) { + stageJudgeRatings(activityPlayerId: $activityPlayerId) { + activityPlayerId + stageId + stageName + matchTime + ratingCount + averageScore + judgeRatings { + judgeId + judgeName + totalScore + feedback + ratingTime + } } } ` - try { - const result = await app.graphqlRequest(query, { activityPlayerId, judgeId }) - return result.judgeRatingDetail - } catch (error) { - throw error + const result = await app.graphqlRequest(query, variables) + const detail = result && result.stageJudgeRatings ? result.stageJudgeRatings : null + + const sourceJudgeRatings = detail && detail.judgeRatings ? detail.judgeRatings : [] + const judgeRatings = sourceJudgeRatings.map(item => ({ + ...item, + totalScoreText: item.totalScore !== null && item.totalScore !== undefined ? `${Number(item.totalScore).toFixed(2)}鍒哷 : '鏈瘎鍒�', + ratingTimeText: item.ratingTime ? this.formatDateTime(item.ratingTime) : '' + })) + + const averageScoreValue = detail && detail.averageScore !== undefined && detail.averageScore !== null + ? detail.averageScore + : null + + return { + activityPlayerId: detail && detail.activityPlayerId ? detail.activityPlayerId : variables.activityPlayerId, + stageId: detail && detail.stageId ? detail.stageId : null, + stageName: detail && detail.stageName ? detail.stageName : '闃舵淇℃伅', + matchTime: detail && detail.matchTime ? detail.matchTime : null, + matchTimeText: detail && detail.matchTime ? this.formatDateTime(detail.matchTime) : '', + ratingCount: detail && detail.ratingCount ? detail.ratingCount : 0, + averageScore: averageScoreValue, + averageScoreText: averageScoreValue !== null ? Number(averageScoreValue).toFixed(2) : '鏆傛棤璇勫垎', + judgeRatings } + }, + + async openStageDetail(e) { + const { playerId } = e.currentTarget.dataset + const clickable = e.currentTarget.dataset.clickable === true || e.currentTarget.dataset.clickable === 'true' + const participated = e.currentTarget.dataset.participated === true || e.currentTarget.dataset.participated === 'true' + + if (!playerId || !participated) { + return + } + + if (!clickable) { + wx.showToast({ + title: '鏆傛棤璇勫垎', + icon: 'none' + }) + return + } + + this.setData({ + showRatingDetail: true, + ratingDetailLoading: true, + ratingDetailError: '', + ratingDetail: { judgeRatings: [] } + }) + + try { + const detail = await this.fetchStageRatingDetail(playerId) + this.setData({ + ratingDetail: detail, + ratingDetailLoading: false + }) + } catch (error) { + console.error('鍔犺浇闃舵璇勫垎璇︽儏澶辫触:', error) + this.setData({ + ratingDetailError: error.message || '鍔犺浇澶辫触', + ratingDetailLoading: false + }) + } + }, + + closeStageDetail() { + this.setData({ + showRatingDetail: false, + ratingDetail: null, + ratingDetailError: '' + }) }, // 棰勮鏂囦欢 @@ -455,4 +597,4 @@ path: `/pages/project/detail?id=${this.data.projectId}` } } -}) \ No newline at end of file +}) -- Gitblit v1.8.0