// pages/judge/review.js
|
const app = getApp()
|
const { graphqlRequest, formatDate } = require('../../lib/utils')
|
|
Page({
|
data: {
|
loading: false,
|
submitting: false,
|
|
// 提交作品信息
|
submission: null,
|
activityPlayerId: '',
|
|
// 活动信息
|
activity: null,
|
|
// 评审标准
|
criteria: [],
|
|
// 评分数据
|
scores: {},
|
|
// 评审意见
|
comment: '',
|
|
// 总分
|
totalScore: 0,
|
maxScore: 0,
|
|
// 评审状态
|
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分 - 优秀' }
|
]
|
},
|
|
onLoad(options) {
|
if (options.id) {
|
this.setData({ activityPlayerId: options.id })
|
this.loadSubmissionDetail()
|
}
|
},
|
|
onShow() {
|
// 页面显示时检查评审状态
|
if (this.data.submissionId) {
|
this.checkReviewStatus()
|
}
|
},
|
|
// 加载提交作品详情
|
async loadSubmissionDetail() {
|
try {
|
this.setData({ loading: true })
|
|
const query = `
|
query GetActivityPlayerDetail($id: ID!) {
|
activityPlayerDetail(id: $id) {
|
id
|
projectName
|
description
|
activityName
|
stageId
|
state
|
playerInfo {
|
id
|
name
|
phone
|
gender
|
birthday
|
education
|
introduction
|
userInfo {
|
userId
|
name
|
phone
|
avatarUrl
|
}
|
}
|
regionInfo {
|
id
|
name
|
fullPath
|
}
|
submissionFiles {
|
id
|
name
|
url
|
fullUrl
|
fileExt
|
fileSize
|
mediaType
|
thumbUrl
|
fullThumbUrl
|
}
|
ratingForm {
|
schemeId
|
schemeName
|
totalMaxScore
|
items {
|
id
|
name
|
description
|
maxScore
|
weight
|
sortOrder
|
}
|
}
|
}
|
}
|
`
|
|
const result = await graphqlRequest(query, { id: this.data.activityPlayerId })
|
|
if (result && result.activityPlayerDetail) {
|
const detail = result.activityPlayerDetail
|
|
// 构建submission对象以兼容现有的WXML模板
|
const submission = {
|
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) : [],
|
participant: {
|
id: detail.playerInfo.id,
|
name: detail.playerInfo.name,
|
school: detail.regionInfo ? detail.regionInfo.name : '',
|
major: detail.playerInfo.education || '',
|
avatar: detail.playerInfo.userInfo?.avatarUrl || '/images/default-avatar.svg'
|
},
|
status: detail.state === 1 ? 'APPROVED' : detail.state === 2 ? 'REJECTED' : 'PENDING'
|
}
|
|
// 构建activity对象
|
const activity = {
|
id: detail.stageId,
|
title: detail.activityName,
|
description: detail.description,
|
judgeCriteria: detail.ratingForm ? detail.ratingForm.items || [] : []
|
}
|
|
// 初始化评分数据
|
const scores = {}
|
let maxScore = 0
|
|
if (activity.judgeCriteria) {
|
activity.judgeCriteria.forEach(criterion => {
|
scores[criterion.id] = 0 // 暂时设为0,后续需要查询已有评分
|
maxScore += criterion.maxScore
|
})
|
}
|
|
this.setData({
|
submission,
|
activity,
|
criteria: activity.judgeCriteria || [],
|
scores,
|
maxScore,
|
existingReview: null, // 暂时设为null,后续需要查询已有评分
|
reviewStatus: 'PENDING',
|
comment: ''
|
})
|
|
this.calculateTotalScore()
|
|
// 检查是否已有评分
|
this.checkReviewStatus()
|
}
|
} catch (error) {
|
console.error('加载作品详情失败:', error)
|
wx.showToast({
|
title: '加载失败',
|
icon: 'error'
|
})
|
} finally {
|
this.setData({ loading: false })
|
}
|
},
|
|
// 检查评审状态
|
async checkReviewStatus() {
|
try {
|
const query = `
|
query GetCurrentJudgeRating($activityPlayerId: ID!) {
|
currentJudgeRating(activityPlayerId: $activityPlayerId) {
|
id
|
totalScore
|
comment
|
status
|
ratedAt
|
items {
|
ratingItemId
|
ratingItemName
|
score
|
maxScore
|
}
|
}
|
}
|
`
|
|
const result = await graphqlRequest(query, { activityPlayerId: this.data.activityPlayerId })
|
|
if (result && result.currentJudgeRating) {
|
const rating = result.currentJudgeRating
|
|
// 如果已有评分,填充数据
|
const scores = {}
|
let totalScore = 0
|
|
if (rating.items) {
|
rating.items.forEach(item => {
|
scores[item.ratingItemId] = item.score
|
totalScore += item.score
|
})
|
}
|
|
this.setData({
|
scores,
|
totalScore,
|
comment: rating.comment || '',
|
existingReview: rating,
|
reviewStatus: rating.status || 'COMPLETED'
|
})
|
|
console.log('已加载现有评分:', rating)
|
} else {
|
console.log('当前评委尚未评分')
|
}
|
} catch (error) {
|
console.error('检查评审状态失败:', error)
|
}
|
},
|
|
// 评分改变
|
onScoreChange(e) {
|
const { criterionId } = e.currentTarget.dataset
|
const { value } = e.detail
|
|
this.setData({
|
[`scores.${criterionId}`]: parseInt(value)
|
})
|
|
this.calculateTotalScore()
|
},
|
|
// 计算总分
|
calculateTotalScore() {
|
const { scores, criteria } = this.data
|
let totalScore = 0
|
|
criteria.forEach(criterion => {
|
const score = scores[criterion.id] || 0
|
totalScore += score * (criterion.weight || 1)
|
})
|
|
this.setData({ totalScore })
|
},
|
|
// 评审意见输入
|
onCommentInput(e) {
|
this.setData({
|
comment: e.detail.value
|
})
|
},
|
|
// 媒体点击
|
onMediaTap(e) {
|
const { url, type } = e.currentTarget.dataset
|
|
if (type === 'image') {
|
wx.previewImage({
|
current: url,
|
urls: this.data.submission.images || []
|
})
|
} else if (type === 'video') {
|
this.setData({
|
showMediaPreview: true,
|
currentMedia: url,
|
mediaType: 'video'
|
})
|
}
|
},
|
|
// 关闭媒体预览
|
onCloseMediaPreview() {
|
this.setData({
|
showMediaPreview: false,
|
currentMedia: null
|
})
|
},
|
|
// 下载文件
|
async onDownloadFile(e) {
|
const { fileId, fileName, fileUrl } = e.currentTarget.dataset
|
|
try {
|
// 添加到下载中列表
|
const downloadingFiles = [...this.data.downloadingFiles, fileId]
|
|
// 同时更新文件的isDownloading字段
|
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 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)
|
wx.showToast({
|
title: '下载失败',
|
icon: 'error'
|
})
|
} finally {
|
// 从下载中列表移除
|
const downloadingFiles = this.data.downloadingFiles.filter(id => id !== fileId)
|
|
// 同时更新文件的isDownloading字段
|
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()
|
}
|
},
|
|
// 验证评审数据
|
validateReview() {
|
const { scores, criteria, comment } = this.data
|
|
// 检查是否所有标准都已评分
|
for (let criterion of criteria) {
|
if (!scores[criterion.id] || scores[criterion.id] === 0) {
|
wx.showToast({
|
title: `请为"${criterion.name}"评分`,
|
icon: 'error'
|
})
|
return false
|
}
|
}
|
|
// 检查评审意见
|
if (!comment.trim()) {
|
wx.showToast({
|
title: '请填写评审意见',
|
icon: 'error'
|
})
|
return false
|
}
|
|
if (comment.trim().length < 10) {
|
wx.showToast({
|
title: '评审意见至少10个字符',
|
icon: 'error'
|
})
|
return false
|
}
|
|
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()
|
}
|
},
|
|
// 提交评审
|
async onSubmitReview() {
|
if (!this.validateReview()) {
|
return
|
}
|
|
wx.showModal({
|
title: '确认提交',
|
content: '评审提交后将无法修改,确定要提交吗?',
|
success: async (res) => {
|
if (res.confirm) {
|
await this.submitReview()
|
}
|
}
|
})
|
},
|
|
// 执行提交评审
|
async submitReview() {
|
try {
|
this.setData({ submitting: true })
|
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'
|
})
|
|
// 更新状态
|
this.setData({
|
reviewStatus: 'COMPLETED'
|
})
|
|
// 重新加载评分状态
|
await this.checkReviewStatus()
|
|
// 延迟返回上一页
|
setTimeout(() => {
|
wx.navigateBack()
|
}, 1500)
|
}
|
} catch (error) {
|
console.error('提交评分失败:', error)
|
wx.showToast({
|
title: '提交失败',
|
icon: 'error'
|
})
|
} finally {
|
this.setData({ submitting: false })
|
wx.hideLoading()
|
}
|
},
|
|
// 查看其他评审
|
onViewOtherReviews() {
|
wx.navigateTo({
|
url: `/pages/judge/reviews?activityPlayerId=${this.data.activityPlayerId}`
|
})
|
},
|
|
// 联系参赛者
|
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
|
}
|
}
|
})
|
}
|
},
|
|
// 获取评分等级文本
|
getScoreLabel(score) {
|
const option = this.data.scoreOptions.find(opt => opt.value === score)
|
return option ? option.label : `${score}分`
|
},
|
|
// 获取文件大小文本
|
getFileSizeText(size) {
|
if (size < 1024) {
|
return `${size}B`
|
} else if (size < 1024 * 1024) {
|
return `${(size / 1024).toFixed(1)}KB`
|
} else {
|
return `${(size / (1024 * 1024)).toFixed(1)}MB`
|
}
|
},
|
|
// 格式化日期
|
formatDate(dateString) {
|
return formatDate(dateString, 'YYYY-MM-DD HH:mm')
|
},
|
|
// 分享页面
|
onShareAppMessage() {
|
return {
|
title: '蓉易创 - 评审作品',
|
path: '/pages/index/index'
|
}
|
}
|
})
|