From 0a48616045ddce1562584543a0e89e5144051fde Mon Sep 17 00:00:00 2001 From: Codex Assistant <codex@example.com> Date: 星期日, 05 十月 2025 14:52:44 +0800 Subject: [PATCH] 报名审核 --- wx/pages/judge/review.js | 522 +++++++++++++++++++++++++++++---------------------------- 1 files changed, 264 insertions(+), 258 deletions(-) diff --git a/wx/pages/judge/review.js b/wx/pages/judge/review.js index 27afd37..e317235 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 } = require('../../lib/utils') +const { graphqlRequest, formatDate: formatDateUtil } = require('../../lib/utils') Page({ data: { @@ -10,13 +10,15 @@ // 鎻愪氦浣滃搧淇℃伅 submission: null, activityPlayerId: '', - + stageId: null, + submissionId: null, + // 娲诲姩淇℃伅 activity: null, - + // 璇勫鏍囧噯 criteria: [], - + // 璇勫垎鏁版嵁 scores: {}, @@ -31,24 +33,7 @@ reviewStatus: 'PENDING', // PENDING, COMPLETED // 宸叉湁璇勫璁板綍 - 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鍒� - 浼樼' } - ] + existingReview: null }, onLoad(options) { @@ -62,6 +47,32 @@ // 椤甸潰鏄剧ず鏃舵鏌ヨ瘎瀹$姸鎬� 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 } }, @@ -102,13 +113,11 @@ submissionFiles { id name - url fullUrl + fullThumbUrl fileExt fileSize mediaType - thumbUrl - fullThumbUrl } ratingForm { schemeId @@ -117,10 +126,8 @@ items { id name - description maxScore - weight - sortOrder + orderNo } } } @@ -137,62 +144,64 @@ id: detail.id, title: detail.projectName, description: detail.description, - 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) : [], + submittedAt: detail.submitTime || null, + team: detail.team || null, participant: { - id: detail.playerInfo.id, - name: detail.playerInfo.name, + 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 || '', - avatar: detail.playerInfo.userInfo?.avatarUrl || '/images/default-avatar.svg' + major: detail.playerInfo?.education || '' }, - status: detail.state === 1 ? 'APPROVED' : detail.state === 2 ? 'REJECTED' : 'PENDING' + status: detail.state === 1 ? 'APPROVED' : detail.state === 2 ? 'REJECTED' : 'PENDING', + mediaList: (detail.submissionFiles || []).map(file => this.transformMediaFile(file)) } - - // 鏋勫缓activity瀵硅薄 - const activity = { - id: detail.stageId, - title: detail.activityName, - description: detail.description, - judgeCriteria: detail.ratingForm ? detail.ratingForm.items || [] : [] - } - - // 鍒濆鍖栬瘎鍒嗘暟鎹� + + 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 + } + }) + const scores = {} - let maxScore = 0 - - if (activity.judgeCriteria) { - activity.judgeCriteria.forEach(criterion => { - scores[criterion.id] = 0 // 鏆傛椂璁句负0锛屽悗缁渶瑕佹煡璇㈠凡鏈夎瘎鍒� - maxScore += criterion.maxScore - }) - } - + criteria.forEach(criterion => { + scores[criterion.id] = 0 + }) + + const maxScore = detail.ratingForm?.totalMaxScore || criteria.reduce((sum, item) => sum + (item.maxScore || 0), 0) + this.setData({ submission, - activity, - criteria: activity.judgeCriteria || [], + activity: { + id: detail.id, + stageId: detail.stageId, + ratingSchemeId: detail.ratingForm?.schemeId || null, + totalMaxScore: maxScore + }, + stageId: detail.stageId || null, + submissionId: detail.id, + criteria, scores, maxScore, - existingReview: null, // 鏆傛椂璁句负null锛屽悗缁渶瑕佹煡璇㈠凡鏈夎瘎鍒� + totalScore: 0, + existingReview: null, reviewStatus: 'PENDING', comment: '' }) - + this.calculateTotalScore() - + // 妫�鏌ユ槸鍚﹀凡鏈夎瘎鍒� this.checkReviewStatus() } @@ -215,7 +224,7 @@ currentJudgeRating(activityPlayerId: $activityPlayerId) { id totalScore - comment + remark status ratedAt items { @@ -239,38 +248,98 @@ if (rating.items) { rating.items.forEach(item => { - scores[item.ratingItemId] = item.score - totalScore += item.score + const numericScore = item.score !== undefined && item.score !== null ? Number(item.score) : 0 + scores[item.ratingItemId] = numericScore + totalScore += numericScore }) } - + + 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, - totalScore, - comment: rating.comment || '', - existingReview: rating, - reviewStatus: rating.status || 'COMPLETED' + 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' }) 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 } = e.currentTarget.dataset - const { value } = e.detail - - this.setData({ - [`scores.${criterionId}`]: parseInt(value) - }) - - this.calculateTotalScore() + 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) }, // 璁$畻鎬诲垎 @@ -279,11 +348,11 @@ let totalScore = 0 criteria.forEach(criterion => { - const score = scores[criterion.id] || 0 - totalScore += score * (criterion.weight || 1) + const score = Number(scores[criterion.id] || 0) + totalScore += score }) - this.setData({ totalScore }) + this.setData({ totalScore: Number(totalScore.toFixed(2)) }) }, // 璇勫鎰忚杈撳叆 @@ -295,106 +364,58 @@ // 濯掍綋鐐瑰嚮 onMediaTap(e) { - const { url, type } = e.currentTarget.dataset - - if (type === 'image') { + 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) wx.previewImage({ - current: url, - urls: this.data.submission.images || [] + current: media.url, + urls: imageUrls }) - } else if (type === 'video') { - this.setData({ - showMediaPreview: true, - currentMedia: url, - mediaType: 'video' + } else if (media.mediaType === 'video') { + wx.navigateTo({ + url: `/pages/video/video?url=${encodeURIComponent(media.url)}&title=${encodeURIComponent(media.name)}` }) + } else { + this.openDocumentMedia(media) } }, - // 鍏抽棴濯掍綋棰勮 - onCloseMediaPreview() { - this.setData({ - showMediaPreview: false, - currentMedia: null - }) - }, - - // 涓嬭浇鏂囦欢 - async onDownloadFile(e) { - const { fileId, fileName, fileUrl } = e.currentTarget.dataset - + async openDocumentMedia(media) { try { - // 娣诲姞鍒颁笅杞戒腑鍒楄〃 - 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 - })) - } - - this.setData({ - downloadingFiles, - submission + wx.showLoading({ title: '鎵撳紑涓�...' }) + const downloadRes = await new Promise((resolve, reject) => { + wx.downloadFile({ + url: media.url, + success: resolve, + fail: reject + }) }) - - 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' - }) - } + + if (downloadRes.statusCode !== 200) { + throw new Error('鏂囦欢涓嬭浇澶辫触') + } + + await new Promise((resolve, reject) => { + wx.openDocument({ + filePath: downloadRes.tempFilePath, + showMenu: true, + success: resolve, + fail: reject + }) }) } 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() } }, @@ -402,6 +423,7 @@ // 楠岃瘉璇勫鏁版嵁 validateReview() { const { scores, criteria, comment } = this.data + const commentText = (comment || '').trim() // 妫�鏌ユ槸鍚︽墍鏈夋爣鍑嗛兘宸茶瘎鍒� for (let criterion of criteria) { @@ -415,7 +437,7 @@ } // 妫�鏌ヨ瘎瀹℃剰瑙� - if (!comment.trim()) { + if (!commentText) { wx.showToast({ title: '璇峰~鍐欒瘎瀹℃剰瑙�', icon: 'error' @@ -423,7 +445,7 @@ return false } - if (comment.trim().length < 10) { + if (commentText.length < 10) { wx.showToast({ title: '璇勫鎰忚鑷冲皯10涓瓧绗�', icon: 'error' @@ -432,54 +454,6 @@ } return true - }, - - // 淇濆瓨鑽夌 - async onSaveDraft() { - try { - wx.showLoading({ title: '淇濆瓨涓�...' }) - - const { activityPlayerId, scores, comment, criteria, activity } = this.data - - // 鏋勫缓璇勫垎椤规暟缁� - const ratings = criteria.map(criterion => ({ - itemId: criterion.id, - score: scores[criterion.id] || 0 - })) - - const mutation = ` - mutation SaveActivityPlayerRating($input: ActivityPlayerRatingInput!) { - saveActivityPlayerRating(input: $input) - } - ` - - const input = { - activityPlayerId, - stageId: activity.stageId, - 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: '淇濆瓨澶辫触', - icon: 'error' - }) - } finally { - wx.hideLoading() - } }, // 鎻愪氦璇勫 @@ -505,12 +479,23 @@ this.setData({ submitting: true }) wx.showLoading({ title: '鎻愪氦涓�...' }) - const { activityPlayerId, scores, comment, criteria, activity } = this.data + 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 ratings = criteria.map(criterion => ({ itemId: criterion.id, - score: scores[criterion.id] || 0 + score: Number(scores[criterion.id] || 0) })) const mutation = ` @@ -521,9 +506,9 @@ const input = { activityPlayerId, - stageId: activity.stageId, + stageId, ratings, - comment: comment.trim() + comment: commentText } const result = await graphqlRequest(mutation, { input }) @@ -569,34 +554,17 @@ // 鑱旂郴鍙傝禌鑰� onContactParticipant() { const { submission } = this.data - - 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 - } - } + const phone = submission?.participant?.phone + if (phone) { + wx.makePhoneCall({ + phoneNumber: phone + }) + } else { + wx.showToast({ + title: '鏆傛棤鑱旂郴鏂瑰紡', + icon: 'none' }) } - }, - - // 鑾峰彇璇勫垎绛夌骇鏂囨湰 - getScoreLabel(score) { - const option = this.data.scoreOptions.find(opt => opt.value === score) - return option ? option.label : `${score}鍒哷 }, // 鑾峰彇鏂囦欢澶у皬鏂囨湰 @@ -610,9 +578,47 @@ } }, + // 缁熶竴澶勭悊鎬у埆鏄剧ず鏂囨湰 + 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 || '鏈~鍐�' + }, + // 鏍煎紡鍖栨棩鏈� formatDate(dateString) { - return formatDate(dateString, 'YYYY-MM-DD HH:mm') + return formatDateUtil(dateString, 'YYYY-MM-DD HH:mm') }, // 鍒嗕韩椤甸潰 @@ -622,4 +628,4 @@ path: '/pages/index/index' } } -}) \ No newline at end of file +}) -- Gitblit v1.8.0