558 lines
27 KiB
JavaScript
558 lines
27 KiB
JavaScript
import * as taskService from './modules/task-service.js';
|
||
import * as imageHandler from './modules/image-handler.js';
|
||
import { campApi } from '../../config/camp_api.js';
|
||
|
||
// 兼容:formatDateTime 可能不存在,提供安全封装
|
||
function safeFormatDateTime(v) {
|
||
try {
|
||
if (typeof formatDateTime === 'function') return formatDateTime(v);
|
||
} catch (_) { }
|
||
return v || '';
|
||
}
|
||
|
||
// 格式化日期为 YYYY-MM-DD HH:mm:ss 格式
|
||
function formatDateTimeString(date) {
|
||
var d = date || new Date();
|
||
var year = d.getFullYear();
|
||
var month = String(d.getMonth() + 1).padStart(2, '0');
|
||
var day = String(d.getDate()).padStart(2, '0');
|
||
var hours = String(d.getHours()).padStart(2, '0');
|
||
var minutes = String(d.getMinutes()).padStart(2, '0');
|
||
var seconds = String(d.getSeconds()).padStart(2, '0');
|
||
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
|
||
}
|
||
|
||
import { formatDateTime } from '../../utils/util';
|
||
|
||
var app = getApp();
|
||
Page({
|
||
data: {
|
||
pdfUrl: '',
|
||
description: '',
|
||
fileName: '主观题试卷.pdf',
|
||
loading: true,
|
||
needReview: false,
|
||
reviewStatus: 'NOT_STARTED',
|
||
reviewTime: '',
|
||
reviewComment: '',
|
||
reviewImages: [],
|
||
submittedImages: [],
|
||
hasSubmitted: false,
|
||
allowResubmit: false,
|
||
tempImages: [],
|
||
taskId: null,
|
||
showPdfActionSheet: false,
|
||
statusText: '', // 状态文本:任务已完成、需要审核、等待审核、审核通过、已驳回
|
||
statusClass: '' // 状态样式类名
|
||
},
|
||
|
||
onLoad: function (options) {
|
||
var that = this;
|
||
|
||
// 从 URL 参数中获取数据
|
||
var campId = options.campId || '';
|
||
var courseId = options.courseId || '';
|
||
var taskId = options.taskId || '';
|
||
var taskTitle = options.taskTitle ? decodeURIComponent(options.taskTitle) : '主观题';
|
||
|
||
if (!taskId) {
|
||
wx.showToast({
|
||
title: '任务ID不存在',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
wx.setNavigationBarTitle({
|
||
title: taskTitle
|
||
});
|
||
|
||
that.setData({
|
||
campId: String(campId),
|
||
courseId: String(courseId),
|
||
taskId: String(taskId)
|
||
});
|
||
|
||
that.getTaskDetail();
|
||
},
|
||
|
||
getTaskDetail: function () {
|
||
var that = this;
|
||
var taskId = this.data.taskId;
|
||
|
||
taskService.getTaskDetail(taskId).then(function (taskData) {
|
||
console.log('taskData', taskData,taskId);
|
||
if (taskData) {
|
||
var needReview = taskData.needReview || false;
|
||
// 初始状态:还没有进度信息,根据 needReview 计算状态文本
|
||
var statusInfo = that.computeStatusText(needReview, 'NOT_STARTED', false);
|
||
that.setData({
|
||
pdfUrl: taskData.pdfUrl,
|
||
description: taskData.description || '',
|
||
needReview: needReview,
|
||
reviewStatus: taskData.reviewStatus,
|
||
loading: false,
|
||
statusText: statusInfo.text,
|
||
statusClass: statusInfo.class
|
||
});
|
||
}
|
||
}).finally(function () {
|
||
var userId = wx.getStorageSync('wxuserid');
|
||
if (userId && taskId) {
|
||
taskService.fetchProgressSilent(userId, taskId)
|
||
.then(function (progressRes) {
|
||
var progress = null;
|
||
if (progressRes && progressRes.success === true && progressRes.progress) {
|
||
progress = progressRes.progress;
|
||
} else if (progressRes && progressRes.code === 200 && progressRes.data) {
|
||
progress = progressRes.data;
|
||
}
|
||
if (progress) {
|
||
var hasImgs = Array.isArray(progress.answer_images) && progress.answer_images.length > 0;
|
||
var done = hasImgs || progress.is_completed === true || progress.is_completed === 1;
|
||
if (done) {
|
||
that.setData({ hasSubmitted: true });
|
||
}
|
||
that.handleTaskDetail(progress);
|
||
} else {
|
||
// 没有进度信息,根据 needReview 计算状态文本
|
||
var needReview = that.data.needReview;
|
||
var statusInfo = that.computeStatusText(needReview, 'NOT_STARTED', false);
|
||
that.setData({
|
||
hasSubmitted: false,
|
||
submittedImages: [],
|
||
reviewImages: [],
|
||
reviewStatus: 'NOT_STARTED',
|
||
reviewTime: '',
|
||
statusText: statusInfo.text,
|
||
statusClass: statusInfo.class
|
||
});
|
||
}
|
||
})
|
||
.catch(function () {
|
||
// 获取进度失败,根据 needReview 计算状态文本
|
||
var needReview = that.data.needReview;
|
||
var statusInfo = that.computeStatusText(needReview, 'NOT_STARTED', false);
|
||
that.setData({
|
||
hasSubmitted: false,
|
||
submittedImages: [],
|
||
reviewImages: [],
|
||
reviewStatus: 'NOT_STARTED',
|
||
reviewTime: '',
|
||
statusText: statusInfo.text,
|
||
statusClass: statusInfo.class
|
||
});
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 计算状态文本和样式类
|
||
* @param {Boolean} needReview - 是否需要审核
|
||
* @param {String} reviewStatus - 审核状态
|
||
* @param {Boolean} hasProgress - 是否有进度信息
|
||
* @returns {Object} {text: String, class: String}
|
||
*/
|
||
computeStatusText: function (needReview, reviewStatus, hasProgress) {
|
||
var statusText = '';
|
||
var statusClass = '';
|
||
|
||
if (!needReview) {
|
||
// 不需要审核
|
||
if (hasProgress) {
|
||
statusText = '任务已完成';
|
||
statusClass = 'no-audit';
|
||
} else {
|
||
statusText = '不需要审核';
|
||
statusClass = 'no-audit';
|
||
}
|
||
} else {
|
||
// 需要审核
|
||
if (!hasProgress) {
|
||
// 没有进度信息
|
||
statusText = '需要审核';
|
||
statusClass = 'need-audit';
|
||
} else {
|
||
// 有进度信息,根据审核状态判断
|
||
var normalizedStatus = String(reviewStatus || '').toLowerCase();
|
||
if (normalizedStatus === 'approved' || normalizedStatus === 'review_status_approved') {
|
||
statusText = '审核通过';
|
||
statusClass = 'approved';
|
||
} else if (normalizedStatus === 'rejected' || normalizedStatus === 'review_status_rejected') {
|
||
statusText = '已驳回';
|
||
statusClass = 'need-audit';
|
||
} else if (normalizedStatus === 'pending' || normalizedStatus === 'review_status_pending') {
|
||
statusText = '等待审核';
|
||
statusClass = 'need-audit';
|
||
} else {
|
||
statusText = '需要审核';
|
||
statusClass = 'need-audit';
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
text: statusText,
|
||
class: statusClass
|
||
};
|
||
},
|
||
|
||
handleTaskDetail: function (data) {
|
||
var that = this;
|
||
try {
|
||
// 解析已提交的图片(优先使用 answer_images 数组)
|
||
var submittedImages = [];
|
||
if (Array.isArray(data.answer_images)) {
|
||
submittedImages = data.answer_images;
|
||
} else if (typeof data.images === 'string') {
|
||
try { submittedImages = JSON.parse(data.images) || []; } catch (_) { submittedImages = []; }
|
||
}
|
||
|
||
// 解析批复图片:可能是数组、JSON 字符串或空对象
|
||
var reviewImages = [];
|
||
if (Array.isArray(data.review_images)) {
|
||
reviewImages = data.review_images;
|
||
} else if (typeof data.review_images === 'string') {
|
||
try { reviewImages = JSON.parse(data.review_images) || []; } catch (_) { reviewImages = []; }
|
||
}
|
||
|
||
// 格式化时间(安全封装)
|
||
var reviewTime = safeFormatDateTime(data.review_time)
|
||
|
||
// 更新 needReview(如果后端返回了该字段,优先使用后端返回的值)
|
||
var currentNeedReview = that.data.needReview;
|
||
if (data.need_review !== undefined) {
|
||
currentNeedReview = !!data.need_review;
|
||
}
|
||
|
||
var hasProgress = true; // 有进度数据
|
||
var reviewStatus = data.review_status || 'NOT_STARTED';
|
||
|
||
// 计算状态文本
|
||
var statusInfo = that.computeStatusText(currentNeedReview, reviewStatus, hasProgress);
|
||
|
||
var updateData = {
|
||
submittedImages: submittedImages,
|
||
hasSubmitted: (submittedImages.length > 0) || (data.is_completed === true || data.is_completed === 1),
|
||
reviewStatus: reviewStatus,
|
||
reviewTime: reviewTime,
|
||
reviewComment: data.review_comment || '',
|
||
reviewImages: reviewImages,
|
||
tempImages: [],
|
||
statusText: statusInfo.text,
|
||
statusClass: statusInfo.class
|
||
};
|
||
|
||
// 如果后端返回了 need_review 字段,使用后端返回的值(更准确)
|
||
if (data.need_review !== undefined) {
|
||
updateData.needReview = !!data.need_review;
|
||
}
|
||
|
||
this.setData(updateData);
|
||
|
||
console.log("reviewStatus", this.data.reviewStatus);
|
||
console.log("needReview", this.data.needReview);
|
||
console.log("statusText", this.data.statusText);
|
||
} catch (error) {
|
||
console.error('处理数据失败:', error);
|
||
}
|
||
},
|
||
|
||
chooseImage: function () {
|
||
var that = this;
|
||
var currentCount = this.data.tempImages.length;
|
||
|
||
imageHandler.chooseImage(6, currentCount).then(function (newImages) {
|
||
var tempImages = that.data.tempImages.concat(newImages);
|
||
that.setData({ tempImages: tempImages });
|
||
}).catch(function (err) {
|
||
console.error('选择图片失败:', err);
|
||
});
|
||
},
|
||
|
||
deleteImage: function (e) {
|
||
var index = e.currentTarget.dataset.index;
|
||
var tempImages = this.data.tempImages.slice();
|
||
tempImages.splice(index, 1);
|
||
this.setData({ tempImages: tempImages });
|
||
},
|
||
|
||
previewImage: function (e) {
|
||
var url = e.currentTarget.dataset.url;
|
||
var images = this.data.tempImages.length > 0 ?
|
||
this.data.tempImages :
|
||
this.data.submittedImages;
|
||
imageHandler.previewImage(url, images);
|
||
},
|
||
|
||
previewFeedbackImage: function (e) {
|
||
var current = e.currentTarget.dataset.url;
|
||
wx.previewImage({
|
||
current: current,
|
||
urls: this.data.feedbackImages
|
||
});
|
||
},
|
||
|
||
uploadImage: function (tempFilePath) {
|
||
return imageHandler.uploadImage(tempFilePath, this.data.taskId, 'subjective');
|
||
},
|
||
|
||
submitAnswer: function () {
|
||
var that = this;
|
||
if (this.data.tempImages.length === 0) {
|
||
wx.showToast({
|
||
title: '请上传答案图片',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
wx.showLoading({
|
||
title: '提交中...',
|
||
mask: true
|
||
});
|
||
|
||
var uploadedUrls = [];
|
||
var uploadPromises = this.data.tempImages.map(function (tempPath) {
|
||
return that.uploadImage(tempPath).then(function (imageUrl) {
|
||
uploadedUrls.push(imageUrl);
|
||
});
|
||
});
|
||
|
||
Promise.all(uploadPromises)
|
||
.then(function () {
|
||
var userId = String(wx.getStorageSync('wxuserid') || '');
|
||
var taskIdStr = String(that.data.taskId);
|
||
return taskService.submitAnswer(userId, taskIdStr, uploadedUrls);
|
||
})
|
||
.then(function (result) {
|
||
if ((result && result.code === 200) || (result && result.success === true)) {
|
||
wx.showToast({
|
||
title: '提交成功',
|
||
icon: 'success'
|
||
});
|
||
|
||
// 如果不需要审核,直接标记为完成(审核通过)
|
||
// 需要审核:设置为 pending(等待审核)
|
||
// 不需要审核:设置为 approved(审核通过,任务完成)
|
||
// 注意:后端返回的格式是小写(pending, approved, rejected)
|
||
var newReviewStatus = that.data.needReview ? 'pending' : 'approved';
|
||
|
||
// 计算状态文本(提交后有进度信息)
|
||
var statusInfo = that.computeStatusText(that.data.needReview, newReviewStatus, true);
|
||
|
||
that.setData({
|
||
hasSubmitted: true,
|
||
submittedImages: uploadedUrls,
|
||
tempImages: [],
|
||
reviewStatus: newReviewStatus,
|
||
statusText: statusInfo.text,
|
||
statusClass: statusInfo.class
|
||
});
|
||
|
||
// 如果不需要审核,重新获取进度信息以确保状态同步
|
||
// 后端应该已经将任务标记为完成,重新获取以确认
|
||
if (!that.data.needReview) {
|
||
var userId = wx.getStorageSync('wxuserid');
|
||
if (userId && that.data.taskId) {
|
||
// 延迟一小段时间,确保后端已更新
|
||
setTimeout(function () {
|
||
taskService.fetchProgressSilent(userId, that.data.taskId)
|
||
.then(function (progressRes) {
|
||
var progress = null;
|
||
if (progressRes && progressRes.success === true && progressRes.progress) {
|
||
progress = progressRes.progress;
|
||
} else if (progressRes && progressRes.code === 200 && progressRes.data) {
|
||
progress = progressRes.data;
|
||
}
|
||
if (progress) {
|
||
// 更新状态,确保与后端同步
|
||
that.handleTaskDetail(progress);
|
||
// 如果后端返回的状态是已完成且不需要审核,确保 reviewStatus 为 approved
|
||
if ((progress.is_completed === true || progress.is_completed === 1) && !that.data.needReview) {
|
||
that.setData({
|
||
reviewStatus: 'approved'
|
||
});
|
||
}
|
||
}
|
||
})
|
||
.catch(function (err) {
|
||
console.log('获取进度信息失败:', err);
|
||
});
|
||
}, 500);
|
||
}
|
||
}
|
||
} else {
|
||
throw new Error((result && (result.message || result.msg)) || '提交失败');
|
||
}
|
||
})
|
||
.catch(function (error) {
|
||
console.error('提交失败:', error);
|
||
wx.showToast({
|
||
title: error.message || '提交失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
})
|
||
.finally(function () {
|
||
wx.hideLoading();
|
||
});
|
||
},
|
||
|
||
handlePdfTap: function () {
|
||
if (!this.data.pdfUrl) {
|
||
wx.showToast({
|
||
title: 'PDF文件不存在',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
wx.showActionSheet({
|
||
itemList: ['预览文件', '直接下载', '分享文件'],
|
||
success: (res) => {
|
||
var that = this;
|
||
if (res.tapIndex === 0) {
|
||
// 预览文件
|
||
wx.downloadFile({
|
||
url: that.data.pdfUrl,
|
||
success: function (res) {
|
||
if (res.statusCode === 200) {
|
||
wx.openDocument({
|
||
filePath: res.tempFilePath,
|
||
success: function () {
|
||
console.log('打开文档成功');
|
||
},
|
||
fail: function (error) {
|
||
console.error('打开文档失败:', error);
|
||
wx.showToast({
|
||
title: '打开文档失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
fail: function (error) {
|
||
console.error('下载文件失败:', error);
|
||
wx.showToast({
|
||
title: '下载文件失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
} else if (res.tapIndex === 1) {
|
||
// 直接下载
|
||
wx.downloadFile({
|
||
url: that.data.pdfUrl,
|
||
success: function (res) {
|
||
if (res.statusCode === 200) {
|
||
var fs = wx.getFileSystemManager();
|
||
fs.saveFile({
|
||
tempFilePath: res.tempFilePath,
|
||
success: function () {
|
||
wx.showToast({
|
||
title: '已保存到本地',
|
||
icon: 'success'
|
||
});
|
||
},
|
||
fail: function (err) {
|
||
console.error('保存失败:', err);
|
||
wx.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
fail: function (error) {
|
||
console.error('下载文件失败:', error);
|
||
wx.showToast({
|
||
title: '下载文件失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
} else if (res.tapIndex === 2) {
|
||
// 分享文件
|
||
wx.downloadFile({
|
||
url: that.data.pdfUrl,
|
||
success: function (res) {
|
||
if (res.statusCode === 200) {
|
||
wx.shareFileMessage({
|
||
fileName: that.data.fileName,
|
||
filePath: res.tempFilePath,
|
||
success: () => {
|
||
console.log('分享文件成功');
|
||
},
|
||
fail: (error) => {
|
||
console.error('分享文件失败:', error);
|
||
wx.showToast({
|
||
title: '分享文件失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
fail: (error) => {
|
||
console.error('下载文件失败:', error);
|
||
wx.showToast({
|
||
title: '下载文件失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
handleResubmit() {
|
||
console.log('handleResubmit')
|
||
this.setData({
|
||
tempImages: [],
|
||
allowResubmit: true,
|
||
hasSubmitted: false,
|
||
submittedImages: []
|
||
});
|
||
},
|
||
|
||
previewReviewImage: function (e) {
|
||
const { url } = e.currentTarget.dataset;
|
||
const reviewImages = this.data.reviewImages;
|
||
if (!reviewImages || reviewImages.length === 0) {
|
||
console.error('找不到老师批复的图片');
|
||
return;
|
||
}
|
||
wx.previewImage({
|
||
urls: reviewImages,
|
||
current: url,
|
||
success: () => {
|
||
console.log('预览成功');
|
||
},
|
||
fail: (err) => {
|
||
console.error('预览失败:', err);
|
||
}
|
||
});
|
||
},
|
||
|
||
onShareAppMessage: function () {
|
||
const fileName = this.data.fileName || '主观题试卷.pdf';
|
||
return {
|
||
title: fileName,
|
||
path: `/pages/camp_task_subjective_question/index?campId=${this.data.campId}&courseId=${this.data.courseId}&taskId=${this.data.taskId}`,
|
||
imageUrl: this.data.pdfUrl
|
||
}
|
||
},
|
||
|
||
onShareTimeline: function () {
|
||
const fileName = this.data.fileName || '主观题试卷.pdf';
|
||
return {
|
||
title: fileName,
|
||
query: `campId=${this.data.campId}&courseId=${this.data.courseId}&taskId=${this.data.taskId}`,
|
||
imageUrl: this.data.pdfUrl
|
||
}
|
||
}
|
||
}); |