'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; class StudentService extends CrudService { constructor(ctx) { super(ctx, 'student'); this.model = this.ctx.model.Student; this.umodel = this.ctx.model.User; this.tmodel = this.ctx.model.Trainplan; this.clamodel = this.ctx.model.Class; this.upmodel = this.ctx.model.Uploadtask; this.gmodel = this.ctx.model.Group; this.psmodel = this.ctx.model.Personalscore; this.gsmodel = this.ctx.model.Groupscore; } async create(data) { const { name, phone: mobile, gender } = data; const res = await this.model.create(data); if (res) { const obj = { name, mobile, gender, type: '4', passwd: '12345678', uid: res._id }; const user = await this.ctx.service.user.create(obj); } return res; } // 查询 async query({ skip, limit, ...info }) { const total = await this.model.count(info); const res = await this.model .find(info) .skip(Number(skip)) .limit(Number(limit)); const data = []; for (const elm of res) { const plan = await this.tmodel.findOne({ 'termnum._id': ObjectId(elm.termid), }); const newdata = { ...JSON.parse(JSON.stringify(elm)) }; if (plan) { const term = await plan.termnum.id(elm.termid); newdata.termname = term.term; if (elm.batchid) { const _batch = await term.batchnum.id(elm.batchid); newdata.batchname = _batch.batch; } } if (elm.classid) { const classs = await this.clamodel.findById(elm.classid); if (classs) { newdata.classname = classs.name; } } data.push(newdata); } const result = { total, data }; return result; } // 查询 async seek({ termid, type, batchid, skip, limit }) { const total = await this.model.count({ termid, type, batchid, $or: [{ classid: null }, { classid: '' }], }); const data = await this.model .find({ termid, type, batchid, $or: [{ classid: null }, { classid: '' }] }) .skip(Number(skip)) .limit(Number(limit)); const result = { total, data }; return result; } async findbedroom(data) { const { batchid, classid } = data; const result = []; // 如果传的是批次id if (batchid) { // 查询该批次下的所有学生 const students = await this.model.find({ batchid }); const bedroomList = new Set(); // 查询该批次的所有寝室号 for (const student of students) { bedroomList.add(student.bedroom); } let studentList = []; // 查询该批次所有寝室下的学生名单 for (const bedroom of bedroomList) { const newstudents = await this.model.find({ bedroom }); for (const newstudent of newstudents) { studentList.push(newstudent.name); } result.push({ bedroom, studentList }); studentList = []; } } // 如果传的是班级id if (classid) { // 查询该班级所有学生 const students = await this.model.find({ classid }); const bedroomList = new Set(); // 查询该班级所有寝室号 for (const student of students) { bedroomList.add(student.bedroom); } let studentList = []; // 查询该班级所有寝室的学生名单 for (const bedroom of bedroomList) { const newstudents = await this.model.find({ bedroom }); for (const newstudent of newstudents) { // 如果寝室中有非本班级学生(混寝),则过滤掉不予显示 if (newstudent.classid === classid) { studentList.push(newstudent.name); } } result.push({ bedroom, studentList }); studentList = []; } } return result; } async upjob(data) { const { stuid, job } = data; const student = await this.model.findById(stuid); student.job = job; if (job === '班长' || job === '学委') { const user = await this.umodel.findOne({ uid: stuid, type: '4' }); const date = await this.ctx.service.util.updatedate(); const openid = user.openid; const detail = '你已被班主任设置为' + job + ',请及时登录查看'; const remark = '感谢您的使用'; if (openid) { this.ctx.service.weixin.sendTemplateMsg( this.ctx.app.config.REVIEW_TEMPLATE_ID, openid, '您有一个新的通知', detail, date, remark ); } } return await student.save(); } // 根据学生id删除班级 async deleteclass(data) { for (const el of data) { const student = await this.model.findById(el); if (student) { student.classid = ''; await student.save(); } } } // 根据班级id查出班级各个学生的分数 async findscore({ skip, limit, ...info }) { const { classid } = info; const total = await this.model.count(info); const students = await this.model .find(info) .skip(Number(skip)) .limit(Number(limit)); const data = []; const groups = await this.gmodel.find({ classid }); for (const student of students) { const _student = JSON.parse(JSON.stringify(student)); const group = groups.find(item => item.students.find(stuinfo => stuinfo.stuid === _student.id) ); console.log(group); if (group) { _student.groupscore = group.score; } const tasks = await this.upmodel.find({ studentid: _student.id }); _student.tasks = tasks; data.push(_student); } return { total, data }; } async findbystuids({ data }) { const res = []; for (const stuid of data) { const stu = await this.model.findById(stuid); if (stu)res.push(stu); } return res; } // 根据学生id删除学生 async deletestus(data) { for (const el of data) { await this.model.deleteOne({ _id: ObjectId(el) }); } } // 批量更新寝室号 async updatabedroom(data) { for (const el of data) { const student = await this.model.findById(el.id); if (student) { student.bedroom = el.bedroom; await student.save(); } } } /** * 计算班级的优秀学生 * 规则:班级干部(学生的job!=='普通学生'),检查是否有评优资格(is_fine_status==='0'可以评优),全部评优; * 普通学生取总成绩前10的人评优(非10位并列时,名额该占用就占用;第10名若有并列,就全都要) * @param {String} param0 {id=>班级id} */ async getFineStudent({ id: classid }) { // 获取班级学生列表 let studentList = await this.model.find({ classid }); // 重置评优,干部全优秀 studentList = studentList.map(i => { if (i.job.includes('普通')) i.is_fine = '1'; else i.is_fine = '0'; return i; }); // 初始化后取出不需要算的人,他们就这样,没必要算 const reverseList = studentList.filter(f => !(f.is_fine !== '2' && f.job.includes('普通'))); // 过滤出取消评优资格的学生和干部;干部就是优秀;被取消资格就别凑热闹了 studentList = studentList.filter(f => f.is_fine !== '2' && f.job.includes('普通')); // 获取平时分 const dailyScoreList = await this.psmodel.find({ classid }); studentList = this.dealScoreList(dailyScoreList, studentList); // 获取作业分 const taskScoreList = await this.upmodel.find({ classid }); studentList = this.dealScoreList(taskScoreList, studentList); // 获取小组分,小组 const groupList = await this.gmodel.find({ classid }); const groupScoreList = await this.gsmodel.find({ classid }); studentList = this.dealGroupScoreList(groupList, groupScoreList, studentList); studentList = studentList.sort((a, b) => (b.score * 1 || 0) - (a.score * 1 || 0)); // 排名 // eslint-disable-next-line no-unused-vars let num = 0; for (const student of studentList) { // 先判断是否超过第10位,超过就跳出 if (num > 10) break; const { score, is_fine } = student; // 最开始初始化过所有人的状态,并且将干部和不能评优的人都过滤出去,所以正常学生应该都是没有评优,如果此处已经是优秀,那么就是和前人同分改的,直接跳过就好 if (is_fine === '1') continue; // 没有分凑什么热闹 if (!score) continue; let plus = 1; // 这轮有多少人,到这了,这个人肯定是要改了,所以默认1 // 评优 student.is_fine = '1'; const rlist = studentList.filter(f => f.score === score); // 处理同分的人也都变成is_fine for (const stud of rlist) { stud.is_fine = '1'; const sindex = studentList.findIndex(f => ObjectId(stud._id).equals(f._id)); if (sindex >= 0) { studentList[sindex] = stud; plus++; } } // num+plus,算下num num = num + plus; } // 算完的和不用算的合并,提交 const lastList = [ ...studentList, ...reverseList ]; for (const student of lastList) { const res = await student.save(); // const { meta, ...data } = student; // const r = await this.model.findByIdAndUpdate( // { _id: ObjectId(student._id) }, // data // ); console.log(res); } } /** * 将分数放到学生身上 * @param {Array} scoreList 班级的分数列表 * @param {Array} studentList 学生列表 */ dealScoreList(scoreList, studentList) { scoreList = _.groupBy(scoreList, 'studentid'); studentList = studentList.map(i => { const slist = scoreList[i._id]; if (slist)i.score = (i.score * 1 || 0) + slist.reduce((p, n) => p + (n.score * 1 || 0), 0); return i; }); return studentList; } /** * 将 学生所在 组的 团队平均分 + 到学生身上 * @param {Array} groupList 班级的小组的列表 * @param {Array} scoreList 所有小组的分数列表 * @param {Array} studentList 学生列表 */ dealGroupScoreList(groupList, scoreList, studentList) { // console.log(groupList); scoreList = _.groupBy(scoreList, 'groupid'); // 算出每组的平均分,之后加给学生 groupList = groupList.map(i => { const { students } = i; if (students.length > 0) { const slist = scoreList[i._id]; if (slist) { i.score = slist.reduce((p, n) => p + (n.score * 1 || 0), 0); i.score = _.floor(_.divide(i.score, students.length), 2); } } return i; }); // 每个学生加自己的组的平均分 studentList = studentList.map(i => { const r = groupList.find(f => f.students.find(sf => ObjectId(sf.stuid).equals(i._id))); if (r) i.score = (i.score * 1 || 0) + (r.score * 1 || 0); return i; }); return studentList; } } module.exports = StudentService;