'use strict'; const assert = require('assert'); const _ = require('lodash'); const { ObjectId } = require('mongoose').Types; const { CrudService } = require('naf-framework-mongoose/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const moment = require('moment'); class TaskService extends CrudService { constructor(ctx) { super(ctx, 'task'); this.model = this.ctx.model.Task; const { baseUrl } = _.get(this.ctx.app.config, 'mission'); if (baseUrl) this.missionBase = baseUrl; } async update({ id }, data) { assert(id, '缺少要修改的数据信息'); const question = _.get(data, 'question', []); if (question.length <= 0) delete data.question; await this.model.findByIdAndUpdate(id, data); return await this.model.findById(id); } // 建立任务 async toExport(body) { const { range } = body; const { fn } = await this.getFnDir(range); const data = { title: fn, params: { project: 'center', service: 'task', method: 'export', body, }, }; if (this.missionBase) { const url = `${this.missionBase}/api/mission`; const res = await this.ctx.curl(url, { method: 'post', headers: { 'content-type': 'application/json', }, data, dataType: 'json', }); if (res.status !== 200 || res.data.errcode !== 0) { throw new BusinessError(ErrorCode.SERVICE_FAULT, '创建任务失败'); } } else { throw new BusinessError(ErrorCode.SERVICE_FAULT, '未找到任务项目设置'); } } async export({ range, subid, missionid }) { assert(missionid, '缺少任务信息,无法执行任务'); try { // 找到学生 // 修改条件,termid变成数组了,需要一个一个查出来 const { planid, termid, batchid, classid } = range; const queryObject = {}; if (planid) queryObject.planid = planid; if (batchid) queryObject.batchid = batchid; if (classid) queryObject.classid = classid; let studentList = []; for (const t of termid) { queryObject.termid = t; const stuList = await this.ctx.service.student.query(queryObject); studentList.push(...stuList); } if (studentList.length <= 0) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到任何学生信息'); } studentList = JSON.parse(JSON.stringify(studentList)); this.ctx.service.util.updateProcess(missionid, '25'); console.log('作业导出=>25%'); // 找到作业 const taskList = await this.getTaskInfo(range, subid); this.ctx.service.util.updateProcess(missionid, '50'); console.log('作业导出=>50%'); // prefix 最少 科目名称/人 可能出现 选择到期:期/班/科目/人; 选择到批:期/批/班/科目/人; 选择到班:科目/人 ;选择计划:期/批/班/科目/人 // 找到应该是哪种模式的文件夹,同时可以获得压缩包的名称 const { fn, prefix: pn } = await this.getFnDir(range); // 循环作业,之后匹配所需要的信息 const arr = []; for (const task of taskList) { const { lessonname, studentid, picurl } = task; const stu = studentList.find(f => f._id === studentid); if (!stu) continue; const { name: studentname, termname, batchname, classname } = stu; let picarr = []; if (_.isString(picurl)) { picarr = [ picurl ]; } else { picarr = picurl; } for (const uri of picarr) { const obj = { uri }; const keys = Object.keys(pn); let prefix = `${lessonname}/${studentname}/`; if (keys.includes('class')) { prefix = `${classname}/${prefix}`; } if (keys.includes('batchid')) { prefix = `${batchname}/${prefix}`; } if (keys.includes('term')) { prefix = `${termname}/${prefix}`; } obj.prefix = prefix; arr.push(obj); } } this.ctx.service.util.updateProcess(missionid, '75'); console.log('作业导出=>75%'); const res = await this.ctx.service.util.toZip(arr, fn); if (!res) { console.error(`${moment().format('YYYY-MM-DD HH:SS:mm')} ${fn} 导出失败`); throw new BusinessError(ErrorCode.SERVICE_FAULT, `${fn}导出失败`); } this.ctx.service.util.updateProcess(missionid, '100', '2', { uri: res, }); console.log('作业导出=>100%'); } catch (error) { this.ctx.service.util.updateProcess(missionid, undefined, '3'); } } async getTaskInfo(range, subid) { const { planid, termid, batchid, classid } = range; let lessonList = []; // 找到指定范围的课表 if (classid) { lessonList = await this.ctx.model.Lesson.find({ classid }); } else if (batchid) { lessonList = await this.ctx.model.Lesson.find({ batchid }); } else if (termid) { lessonList = await this.ctx.model.Lesson.find({ termid: { $in: termid } }); } else if (planid) { const trainPlan = await this.ctx.model.Trainplan.findById(planid); if (!trainPlan) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到年度计划信息'); } let { termnum } = trainPlan; if (!termnum) { throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到年度计划下的期信息'); } termnum = JSON.parse(JSON.stringify(termnum)); const termids = termnum.map(i => i._id); lessonList = await this.ctx.model.Lesson.find({ termid: { $in: termids } }); } lessonList = JSON.parse(JSON.stringify(lessonList)); // 不需要其他属性,只要课表安排 lessonList = lessonList.map(i => i.lessons); lessonList = lessonList.flat(); // 过滤出有subid且 !==''的课程 lessonList = lessonList.filter(f => f.subid && f.subid !== ''); // 如果指定某科,就把这科过滤出来 if (subid) lessonList = lessonList.filter(f => f.subid === subid); // 找作业 const lessonids = lessonList.map(i => i._id); let taskList = await this.ctx.model.Uploadtask.find({ lessonid: { $in: lessonids }, }); taskList = JSON.parse(JSON.stringify(taskList)); const arr = []; for (const task of taskList) { const r = arr.find(f => f.studentid === task.studentid && f.lessonid === task.lessonid); if (!r) arr.push(task); } return JSON.parse(JSON.stringify(arr)); } async getFnDir(range) { const { planid, termid, batchid, classid } = range; let fn = '作业'; const prefix = { class: true }; // 只有班级 if (classid) { const cla = await this.ctx.service.class.fetch({ id: classid }); if (cla) { const { name, term } = cla; if (name) fn = `${name.includes('班') ? name : `${name}班`}${fn}`; if (term) fn = `第${term}期${fn}`; } } else if (batchid) { const tid = _.head(termid); const obj = await this.toGetFn(tid, batchid); if (obj) { const { term, batch } = obj; if (batch) fn = `第${batch}批${fn}`; if (term) fn = `第${term}期${fn}`; } prefix.term = true; prefix.batch = true; } else if (termid) { if (termid.length === 1) { const obj = await this.toGetFn(_.head(termid)); if (obj) { const { term } = obj; if (term) fn = `第${term}期${fn}`; } } else { let tStr = ''; for (let i = 0; i < termid.length; i++) { const tid = termid[i]; const obj = await this.toGetFn(tid); if (obj) { const { term } = obj; if (term) { if (i === 0) { tStr += `${term}期`; } else { tStr += `,${term}期`; } } } } fn = `${tStr}${fn}`; } prefix.term = true; } else { const trainPlan = await this.ctx.model.Trainplan.findById(planid); if (trainPlan) { const { title } = trainPlan; if (title) fn = `${title}${fn}`; } prefix.term = true; prefix.batch = true; } return { fn, prefix }; } async toGetFn(termid, batchid) { const trainPlan = await this.ctx.model.Trainplan.findOne({ 'termnum._id': ObjectId(termid) }); if (!trainPlan) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到年度计划信息'); const { termnum } = trainPlan; if (!termnum) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到年度计划的期信息'); const obj = {}; if (termid) { const term = termnum.id(termid); if (term) obj.term = term.term; if (batchid) { const { batchnum } = term; const batch = batchnum.id(batchid); if (batch) obj.batch = batch.batch; } } return obj; } } module.exports = TaskService;