From 58d9f460b2f8c34430285115e2557d18333c5cab Mon Sep 17 00:00:00 2001 From: Codex Assistant <codex@example.com> Date: 星期三, 08 十月 2025 14:16:55 +0800 Subject: [PATCH] feat: 修复Player实体phone字段数据冗余问题并优化小程序报名逻辑 --- wx/pages/judge/review.js | 529 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 262 insertions(+), 267 deletions(-) diff --git a/wx/pages/judge/review.js b/wx/pages/judge/review.js index e317235..c8d16d2 100644 --- a/wx/pages/judge/review.js +++ b/wx/pages/judge/review.js @@ -1,6 +1,6 @@ // pages/judge/review.js const app = getApp() -const { graphqlRequest, formatDate: formatDateUtil } = require('../../lib/utils') +const { graphqlRequest, formatDate } = require('../../lib/utils') Page({ data: { @@ -10,15 +10,13 @@ // 鎻愪氦浣滃搧淇℃伅 submission: null, activityPlayerId: '', - stageId: null, - submissionId: null, - + // 娲诲姩淇℃伅 activity: null, - + // 璇勫鏍囧噯 criteria: [], - + // 璇勫垎鏁版嵁 scores: {}, @@ -33,7 +31,24 @@ reviewStatus: 'PENDING', // PENDING, COMPLETED // 宸叉湁璇勫璁板綍 - existingReview: null + existingReview: null, + + // 濯掍綋棰勮 + showMediaPreview: false, + currentMedia: null, + mediaType: 'image', + + // 鏂囦欢涓嬭浇 + downloadingFiles: [], + + // 璇勫垎绛夌骇 + scoreOptions: [ + { value: 1, label: '1鍒� - 寰堝樊' }, + { value: 2, label: '2鍒� - 杈冨樊' }, + { value: 3, label: '3鍒� - 涓�鑸�' }, + { value: 4, label: '4鍒� - 鑹ソ' }, + { value: 5, label: '5鍒� - 浼樼' } + ] }, onLoad(options) { @@ -47,32 +62,6 @@ // 椤甸潰鏄剧ず鏃舵鏌ヨ瘎瀹$姸鎬� if (this.data.submissionId) { this.checkReviewStatus() - } - }, - - transformMediaFile(file) { - const url = file.fullUrl || file.url - const thumbUrl = file.fullThumbUrl || url - const ext = (file.fileExt || '').toLowerCase() - let mediaType = 'file' - - if (file.mediaType === 1 || ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'heic'].includes(ext)) { - mediaType = 'image' - } else if (file.mediaType === 2 || ['mp4', 'mov', 'avi', 'wmv', 'mkv', 'webm', 'flv'].includes(ext)) { - mediaType = 'video' - } else if (ext === 'pdf') { - mediaType = 'pdf' - } else if (['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'wps', 'txt', 'rtf'].includes(ext)) { - mediaType = 'word' - } - - return { - id: file.id, - name: file.name, - url, - thumbUrl, - mediaType, - size: file.fileSize || 0 } }, @@ -113,11 +102,13 @@ submissionFiles { id name + url fullUrl - fullThumbUrl fileExt fileSize mediaType + thumbUrl + fullThumbUrl } ratingForm { schemeId @@ -144,64 +135,64 @@ id: detail.id, title: detail.projectName, description: detail.description, - submittedAt: detail.submitTime || null, - team: detail.team || null, + files: detail.submissionFiles ? detail.submissionFiles.map(file => ({ + id: file.id, + name: file.name, + url: file.fullUrl || file.url, + type: file.fileExt, + size: file.fileSize, + isDownloading: this.data.downloadingFiles.indexOf(file.id) > -1 + })) : [], + images: detail.submissionFiles ? detail.submissionFiles + .filter(file => file.mediaType === 1) + .map(file => file.fullUrl || file.url) : [], + videos: detail.submissionFiles ? detail.submissionFiles + .filter(file => file.mediaType === 2) + .map(file => file.fullUrl || file.url) : [], participant: { - id: detail.playerInfo?.id, - name: detail.playerInfo?.name, - phone: detail.playerInfo?.phone || detail.playerInfo?.userInfo?.phone || '', - avatar: detail.playerInfo?.userInfo?.avatarUrl || '/images/default-avatar.svg', - gender: this.getGenderLabel(detail.playerInfo?.gender), - birthday: this.getBirthdayText(detail.playerInfo?.birthday), - region: detail.regionInfo?.fullPath || detail.regionInfo?.name || '', - education: detail.playerInfo?.education || '', - school: detail.regionInfo ? detail.regionInfo.name : '', - major: detail.playerInfo?.education || '' + id: detail.playerInfo.id, + name: detail.playerInfo.name, + gender: this.getGenderText(detail.playerInfo.gender), + birthday: detail.playerInfo.birthday || '', + region: detail.regionInfo ? detail.regionInfo.name : '', + education: detail.playerInfo.education || '', + avatar: detail.playerInfo.userInfo?.avatarUrl || '/images/default-avatar.svg' }, - status: detail.state === 1 ? 'APPROVED' : detail.state === 2 ? 'REJECTED' : 'PENDING', - mediaList: (detail.submissionFiles || []).map(file => this.transformMediaFile(file)) + status: detail.state === 1 ? 'APPROVED' : detail.state === 2 ? 'REJECTED' : 'PENDING' } - - const criteria = (detail.ratingForm?.items || []).map(item => { - const maxScore = item.maxScore || 0 - return { - id: item.id, - name: item.name, - maxScore, - description: item.description || '鏆傛棤鎻忚堪', - step: maxScore > 20 ? 1 : 0.5, - currentScore: 0 - } - }) - + + // 鏋勫缓activity瀵硅薄 + const activity = { + id: detail.stageId, + title: detail.activityName, + description: detail.description, + judgeCriteria: detail.ratingForm ? detail.ratingForm.items || [] : [] + } + + // 鍒濆鍖栬瘎鍒嗘暟鎹� const scores = {} - criteria.forEach(criterion => { - scores[criterion.id] = 0 - }) - - const maxScore = detail.ratingForm?.totalMaxScore || criteria.reduce((sum, item) => sum + (item.maxScore || 0), 0) - + let maxScore = 0 + + if (activity.judgeCriteria) { + activity.judgeCriteria.forEach(criterion => { + scores[criterion.id] = 0 // 鏆傛椂璁句负0锛屽悗缁渶瑕佹煡璇㈠凡鏈夎瘎鍒� + maxScore += criterion.maxScore + }) + } + this.setData({ submission, - activity: { - id: detail.id, - stageId: detail.stageId, - ratingSchemeId: detail.ratingForm?.schemeId || null, - totalMaxScore: maxScore - }, - stageId: detail.stageId || null, - submissionId: detail.id, - criteria, + activity, + criteria: activity.judgeCriteria || [], scores, maxScore, - totalScore: 0, - existingReview: null, + existingReview: null, // 鏆傛椂璁句负null锛屽悗缁渶瑕佹煡璇㈠凡鏈夎瘎鍒� reviewStatus: 'PENDING', comment: '' }) - + this.calculateTotalScore() - + // 妫�鏌ユ槸鍚﹀凡鏈夎瘎鍒� this.checkReviewStatus() } @@ -231,7 +222,7 @@ ratingItemId ratingItemName score - maxScore + weightedScore } } } @@ -248,98 +239,38 @@ if (rating.items) { rating.items.forEach(item => { - const numericScore = item.score !== undefined && item.score !== null ? Number(item.score) : 0 - scores[item.ratingItemId] = numericScore - totalScore += numericScore + scores[item.ratingItemId] = item.score + totalScore += item.score }) } - - const updatedCriteria = this.data.criteria.map(criterion => { - const value = scores[criterion.id] !== undefined ? scores[criterion.id] : 0 - return { - ...criterion, - currentScore: value - } - }) - - const normalizedTotal = Number(totalScore.toFixed(2)) - + this.setData({ scores, - criteria: updatedCriteria, - totalScore: normalizedTotal, - comment: rating.remark || rating.comment || '', - existingReview: { - ...rating, - totalScore: rating.totalScore ? Number(rating.totalScore) : normalizedTotal, - reviewedAt: rating.ratedAt || rating.reviewedAt || rating.updateTime || null - }, - reviewStatus: 'COMPLETED' + totalScore, + comment: rating.remark || '', + existingReview: rating, + reviewStatus: rating.status || 'COMPLETED' }) console.log('宸插姞杞界幇鏈夎瘎鍒�:', rating) } else { console.log('褰撳墠璇勫灏氭湭璇勫垎') } - - this.calculateTotalScore() } catch (error) { console.error('妫�鏌ヨ瘎瀹$姸鎬佸け璐�:', error) } }, - normalizeScore(value, criterion) { - const maxScore = Number(criterion.maxScore || 0) - const step = Number(criterion.step || (maxScore > 20 ? 1 : 0.5)) - if (Number.isNaN(value)) { - value = 0 - } - let normalized = Math.round(value / step) * step - if (normalized < 0) normalized = 0 - if (normalized > maxScore) normalized = maxScore - return Number(normalized.toFixed(2)) - }, - - updateCriterionScore(criterionId, index, value) { - const criterion = this.data.criteria[index] - if (!criterion) return - const normalized = this.normalizeScore(value, criterion) - - this.setData({ - [`scores.${criterionId}`]: normalized, - [`criteria[${index}].currentScore`]: normalized - }) - - this.calculateTotalScore() - }, - // 璇勫垎鏀瑰彉 onScoreChange(e) { - const { criterionId, index } = e.currentTarget.dataset - const criterion = this.data.criteria[index] - if (!criterion) return - - const inputValue = Number(e.detail.value) - const newScore = this.normalizeScore(inputValue, criterion) - this.updateCriterionScore(criterionId, index, newScore) - }, - - increaseScore(e) { - const { criterionId, index } = e.currentTarget.dataset - const criterion = this.data.criteria[index] - if (!criterion) return - const current = Number(this.data.scores[criterionId] || criterion.currentScore || 0) - const step = criterion.step || (criterion.maxScore > 20 ? 1 : 0.5) - this.updateCriterionScore(criterionId, index, current + step) - }, - - decreaseScore(e) { - const { criterionId, index } = e.currentTarget.dataset - const criterion = this.data.criteria[index] - if (!criterion) return - const current = Number(this.data.scores[criterionId] || criterion.currentScore || 0) - const step = criterion.step || (criterion.maxScore > 20 ? 1 : 0.5) - this.updateCriterionScore(criterionId, index, current - step) + const { criterionId } = e.currentTarget.dataset + const { value } = e.detail + + this.setData({ + [`scores.${criterionId}`]: parseInt(value) + }) + + this.calculateTotalScore() }, // 璁$畻鎬诲垎 @@ -348,11 +279,11 @@ let totalScore = 0 criteria.forEach(criterion => { - const score = Number(scores[criterion.id] || 0) + const score = scores[criterion.id] || 0 totalScore += score }) - this.setData({ totalScore: Number(totalScore.toFixed(2)) }) + this.setData({ totalScore }) }, // 璇勫鎰忚杈撳叆 @@ -364,58 +295,106 @@ // 濯掍綋鐐瑰嚮 onMediaTap(e) { - const index = Number(e.currentTarget.dataset.index) - const mediaList = this.data.submission?.mediaList || [] - const media = mediaList[index] - if (!media) return - - if (media.mediaType === 'image') { - const imageUrls = mediaList - .filter(item => item.mediaType === 'image') - .map(item => item.url) + const { url, type } = e.currentTarget.dataset + + if (type === 'image') { wx.previewImage({ - current: media.url, - urls: imageUrls + current: url, + urls: this.data.submission.images || [] }) - } else if (media.mediaType === 'video') { - wx.navigateTo({ - url: `/pages/video/video?url=${encodeURIComponent(media.url)}&title=${encodeURIComponent(media.name)}` + } else if (type === 'video') { + this.setData({ + showMediaPreview: true, + currentMedia: url, + mediaType: 'video' }) - } else { - this.openDocumentMedia(media) } }, - async openDocumentMedia(media) { + // 鍏抽棴濯掍綋棰勮 + onCloseMediaPreview() { + this.setData({ + showMediaPreview: false, + currentMedia: null + }) + }, + + // 涓嬭浇鏂囦欢 + async onDownloadFile(e) { + const { fileId, fileName, fileUrl } = e.currentTarget.dataset + try { - wx.showLoading({ title: '鎵撳紑涓�...' }) - const downloadRes = await new Promise((resolve, reject) => { - wx.downloadFile({ - url: media.url, - success: resolve, - fail: reject - }) - }) - - if (downloadRes.statusCode !== 200) { - throw new Error('鏂囦欢涓嬭浇澶辫触') + // 娣诲姞鍒颁笅杞戒腑鍒楄〃 + const downloadingFiles = [...this.data.downloadingFiles, fileId] + + // 鍚屾椂鏇存柊鏂囦欢鐨刬sDownloading瀛楁 + const submission = { ...this.data.submission } + if (submission.files) { + submission.files = submission.files.map(file => ({ + ...file, + isDownloading: file.id === fileId ? true : file.isDownloading + })) } - - await new Promise((resolve, reject) => { - wx.openDocument({ - filePath: downloadRes.tempFilePath, - showMenu: true, - success: resolve, - fail: reject - }) + + this.setData({ + downloadingFiles, + submission + }) + + wx.showLoading({ title: '涓嬭浇涓�...' }) + + const result = await wx.downloadFile({ + url: fileUrl, + success: (res) => { + if (res.statusCode === 200) { + // 淇濆瓨鍒扮浉鍐屾垨鏂囦欢 + wx.saveFile({ + tempFilePath: res.tempFilePath, + success: () => { + wx.showToast({ + title: '涓嬭浇鎴愬姛', + icon: 'success' + }) + }, + fail: () => { + wx.showToast({ + title: '淇濆瓨澶辫触', + icon: 'error' + }) + } + }) + } + }, + fail: () => { + wx.showToast({ + title: '涓嬭浇澶辫触', + icon: 'error' + }) + } }) } catch (error) { - console.error('鎵撳紑鏂囦欢澶辫触:', error) + console.error('涓嬭浇鏂囦欢澶辫触:', error) wx.showToast({ - title: '鏃犳硶鎵撳紑鏂囦欢', + title: '涓嬭浇澶辫触', icon: 'error' }) } finally { + // 浠庝笅杞戒腑鍒楄〃绉婚櫎 + const downloadingFiles = this.data.downloadingFiles.filter(id => id !== fileId) + + // 鍚屾椂鏇存柊鏂囦欢鐨刬sDownloading瀛楁 + const submission = { ...this.data.submission } + if (submission.files) { + submission.files = submission.files.map(file => ({ + ...file, + isDownloading: file.id === fileId ? false : file.isDownloading + })) + } + + this.setData({ + downloadingFiles, + submission + }) wx.hideLoading() } }, @@ -423,7 +402,6 @@ // 楠岃瘉璇勫鏁版嵁 validateReview() { const { scores, criteria, comment } = this.data - const commentText = (comment || '').trim() // 妫�鏌ユ槸鍚︽墍鏈夋爣鍑嗛兘宸茶瘎鍒� for (let criterion of criteria) { @@ -437,23 +415,63 @@ } // 妫�鏌ヨ瘎瀹℃剰瑙� - if (!commentText) { + if (!comment.trim()) { wx.showToast({ title: '璇峰~鍐欒瘎瀹℃剰瑙�', icon: 'error' }) return false } - - if (commentText.length < 10) { + + return true + }, + + // 淇濆瓨鑽夌 + async onSaveDraft() { + try { + wx.showLoading({ title: '淇濆瓨涓�...' }) + + const { activityPlayerId, scores, comment, criteria, activity } = this.data + + // 鏋勫缓璇勫垎椤规暟缁� + const ratings = criteria.map(criterion => ({ + itemId: parseInt(criterion.id), + score: parseFloat(scores[criterion.id] || 0) + })) + + const mutation = ` + mutation SaveActivityPlayerRating($input: ActivityPlayerRatingInput!) { + saveActivityPlayerRating(input: $input) + } + ` + + const input = { + activityPlayerId: parseInt(activityPlayerId), + stageId: parseInt(activity.id), + ratings, + comment: comment.trim() + } + + const result = await graphqlRequest(mutation, { input }) + + if (result && result.saveActivityPlayerRating) { + wx.showToast({ + title: '鑽夌宸蹭繚瀛�', + icon: 'success' + }) + + // 閲嶆柊鍔犺浇璇勫垎鐘舵�� + await this.checkReviewStatus() + } + } catch (error) { + console.error('淇濆瓨鑽夌澶辫触:', error) wx.showToast({ - title: '璇勫鎰忚鑷冲皯10涓瓧绗�', + title: '淇濆瓨澶辫触', icon: 'error' }) - return false + } finally { + wx.hideLoading() } - - return true }, // 鎻愪氦璇勫 @@ -479,23 +497,12 @@ this.setData({ submitting: true }) wx.showLoading({ title: '鎻愪氦涓�...' }) - const { activityPlayerId, scores, comment, criteria, stageId } = this.data - const commentText = (comment || '').trim() - - if (!stageId) { - wx.showToast({ - title: '缂哄皯闃舵淇℃伅锛屾棤娉曟彁浜�', - icon: 'none' - }) - this.setData({ submitting: false }) - wx.hideLoading() - return - } + const { activityPlayerId, scores, comment, criteria, activity } = this.data // 鏋勫缓璇勫垎椤规暟缁� const ratings = criteria.map(criterion => ({ itemId: criterion.id, - score: Number(scores[criterion.id] || 0) + score: scores[criterion.id] || 0 })) const mutation = ` @@ -506,9 +513,9 @@ const input = { activityPlayerId, - stageId, + stageId: activity.id, ratings, - comment: commentText + comment: comment.trim() } const result = await graphqlRequest(mutation, { input }) @@ -544,27 +551,46 @@ } }, - // 鏌ョ湅鍏朵粬璇勫 + // 鏌ョ湅鍏朵粬璇勫 - 宸查殣钘忓姛鑳� + /* onViewOtherReviews() { wx.navigateTo({ url: `/pages/judge/reviews?activityPlayerId=${this.data.activityPlayerId}` }) }, + */ // 鑱旂郴鍙傝禌鑰� onContactParticipant() { const { submission } = this.data - const phone = submission?.participant?.phone - if (phone) { - wx.makePhoneCall({ - phoneNumber: phone - }) - } else { - wx.showToast({ - title: '鏆傛棤鑱旂郴鏂瑰紡', - icon: 'none' + + if (submission.participant) { + wx.showActionSheet({ + itemList: ['鍙戦�佹秷鎭�', '鏌ョ湅璇︽儏'], + success: (res) => { + switch (res.tapIndex) { + case 0: + // 鍙戦�佹秷鎭姛鑳� + wx.navigateTo({ + url: `/pages/chat/chat?userId=${submission.participant.id}` + }) + break + case 1: + // 鏌ョ湅鐢ㄦ埛璇︽儏 + wx.navigateTo({ + url: `/pages/user/profile?userId=${submission.participant.id}` + }) + break + } + } }) } + }, + + // 鑾峰彇璇勫垎绛夌骇鏂囨湰 + getScoreLabel(score) { + const option = this.data.scoreOptions.find(opt => opt.value === score) + return option ? option.label : `${score}鍒哷 }, // 鑾峰彇鏂囦欢澶у皬鏂囨湰 @@ -578,47 +604,16 @@ } }, - // 缁熶竴澶勭悊鎬у埆鏄剧ず鏂囨湰 - getGenderLabel(gender) { - if (gender === null || gender === undefined || gender === '') { - return '鏈~鍐�' - } - - const normalized = String(gender).trim().toLowerCase() - - if (normalized === '') { - return '鏈~鍐�' - } - - if (normalized === 'male' || normalized === 'm') { - return '鐢�' - } - if (normalized === 'female' || normalized === 'f') { - return '濂�' - } - - if (/^-?\d+$/.test(normalized)) { - const numeric = Number(normalized) - if (numeric === 1) return '鐢�' - if (numeric === 0) return '濂�' - if (numeric === 2) return '濂�' - } - - return gender === undefined || gender === null ? '鏈~鍐�' : String(gender) - }, - - // 缁熶竴澶勭悊鍑虹敓鏃ユ湡鏄剧ず鏂囨湰 - getBirthdayText(dateString) { - if (!dateString) { - return '鏈~鍐�' - } - const formatted = formatDateUtil(dateString, 'YYYY-MM-DD') - return formatted || '鏈~鍐�' + // 鎬у埆杞崲鍑芥暟 + getGenderText(gender) { + if (gender === 0) return '鐢�' + if (gender === 1) return '濂�' + return '鏈~鍐�' }, // 鏍煎紡鍖栨棩鏈� formatDate(dateString) { - return formatDateUtil(dateString, 'YYYY-MM-DD HH:mm') + return formatDate(dateString, 'YYYY-MM-DD HH:mm') }, // 鍒嗕韩椤甸潰 @@ -628,4 +623,4 @@ path: '/pages/index/index' } } -}) +}) \ No newline at end of file -- Gitblit v1.8.0