student.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = require('lodash');
  4. const { ObjectId } = require('mongoose').Types;
  5. const { CrudService } = require('naf-framework-mongoose/lib/service');
  6. const { BusinessError, ErrorCode } = require('naf-core').Error;
  7. class StudentService extends CrudService {
  8. constructor(ctx) {
  9. super(ctx, 'student');
  10. this.model = this.ctx.model.Student;
  11. this.umodel = this.ctx.model.User;
  12. this.tmodel = this.ctx.model.Trainplan;
  13. this.clamodel = this.ctx.model.Class;
  14. this.upmodel = this.ctx.model.Uploadtask;
  15. this.gmodel = this.ctx.model.Group;
  16. this.psmodel = this.ctx.model.Personalscore;
  17. this.gsmodel = this.ctx.model.Groupscore;
  18. }
  19. async create(data) {
  20. const { name, phone: mobile, gender } = data;
  21. const res = await this.model.create(data);
  22. if (res) {
  23. const obj = { name, mobile, gender, type: '4', passwd: '12345678', uid: res._id };
  24. const user = await this.ctx.service.user.create(obj);
  25. }
  26. return res;
  27. }
  28. // 查询
  29. async query({ skip, limit, ...info }) {
  30. const { termid, classid } = info;
  31. if (!classid) {
  32. const classes = await this.clamodel.find({ termid });
  33. for (const cla of classes) {
  34. await this.arrangeNumber(cla._id);
  35. }
  36. } else { await this.arrangeNumber(classid); }
  37. const total = await this.model.count(info);
  38. const res = await this.model
  39. .find(info)
  40. .skip(Number(skip))
  41. .limit(Number(limit));
  42. const data = [];
  43. for (const elm of res) {
  44. const plan = await this.tmodel.findOne({
  45. 'termnum._id': ObjectId(elm.termid),
  46. });
  47. const newdata = { ...JSON.parse(JSON.stringify(elm)) };
  48. if (plan) {
  49. const term = await plan.termnum.id(elm.termid);
  50. newdata.termname = term.term;
  51. if (elm.batchid) {
  52. const _batch = await term.batchnum.id(elm.batchid);
  53. newdata.batchname = _batch.batch;
  54. }
  55. }
  56. if (elm.classid) {
  57. const classs = await this.clamodel.findById(elm.classid);
  58. if (classs) {
  59. newdata.classname = classs.name;
  60. }
  61. }
  62. data.push(newdata);
  63. }
  64. const result = { total, data };
  65. return result;
  66. }
  67. // 查询
  68. async seek({ termid, type, batchid, skip, limit }) {
  69. const total = await this.model.count({
  70. termid,
  71. type,
  72. batchid,
  73. $or: [{ classid: null }, { classid: '' }],
  74. });
  75. const data = await this.model
  76. .find({ termid, type, batchid, $or: [{ classid: null }, { classid: '' }] })
  77. .skip(Number(skip))
  78. .limit(Number(limit));
  79. const result = { total, data };
  80. return result;
  81. }
  82. async findbedroom(data) {
  83. const { batchid, classid } = data;
  84. const result = [];
  85. // 如果传的是批次id
  86. if (batchid) {
  87. // 查询该批次下的所有学生
  88. const students = await this.model.find({ batchid });
  89. const bedroomList = new Set();
  90. // 查询该批次的所有寝室号
  91. for (const student of students) {
  92. bedroomList.add(student.bedroom);
  93. }
  94. let studentList = [];
  95. // 查询该批次所有寝室下的学生名单
  96. for (const bedroom of bedroomList) {
  97. const newstudents = await this.model.find({ bedroom });
  98. for (const newstudent of newstudents) {
  99. studentList.push(newstudent.name);
  100. }
  101. result.push({ bedroom, studentList });
  102. studentList = [];
  103. }
  104. }
  105. // 如果传的是班级id
  106. if (classid) {
  107. // 查询该班级所有学生
  108. const students = await this.model.find({ classid });
  109. const bedroomList = new Set();
  110. // 查询该班级所有寝室号
  111. for (const student of students) {
  112. bedroomList.add(student.bedroom);
  113. }
  114. let studentList = [];
  115. // 查询该班级所有寝室的学生名单
  116. for (const bedroom of bedroomList) {
  117. const newstudents = await this.model.find({ bedroom });
  118. for (const newstudent of newstudents) {
  119. // 如果寝室中有非本班级学生(混寝),则过滤掉不予显示
  120. if (newstudent.classid === classid) {
  121. studentList.push(newstudent.name);
  122. }
  123. }
  124. result.push({ bedroom, studentList });
  125. studentList = [];
  126. }
  127. }
  128. return result;
  129. }
  130. async upjob(data) {
  131. const { stuid, job } = data;
  132. const student = await this.model.findById(stuid);
  133. student.job = job;
  134. if (job === '班长' || job === '学委') {
  135. const user = await this.umodel.findOne({ uid: stuid, type: '4' });
  136. const date = await this.ctx.service.util.updatedate();
  137. const openid = user.openid;
  138. const detail = '你已被班主任设置为' + job + ',请及时登录查看';
  139. const remark = '感谢您的使用';
  140. if (openid) {
  141. this.ctx.service.weixin.sendTemplateMsg(
  142. this.ctx.app.config.REVIEW_TEMPLATE_ID,
  143. openid,
  144. '您有一个新的通知',
  145. detail,
  146. date,
  147. remark
  148. );
  149. }
  150. }
  151. return await student.save();
  152. }
  153. // 根据学生id删除班级
  154. async deleteclass(data) {
  155. for (const el of data) {
  156. const student = await this.model.findById(el);
  157. if (student) {
  158. student.classid = '';
  159. await student.save();
  160. }
  161. }
  162. }
  163. // 根据班级id查出班级各个学生的分数
  164. async findscore({ skip, limit, ...info }) {
  165. const { classid } = info;
  166. const total = await this.model.count(info);
  167. const students = await this.model
  168. .find(info)
  169. .skip(Number(skip))
  170. .limit(Number(limit));
  171. const data = [];
  172. const groups = await this.gmodel.find({ classid });
  173. for (const student of students) {
  174. const _student = JSON.parse(JSON.stringify(student));
  175. const group = groups.find(item =>
  176. item.students.find(stuinfo => stuinfo.stuid === _student.id)
  177. );
  178. console.log(group);
  179. if (group) {
  180. _student.groupscore = group.score;
  181. }
  182. const tasks = await this.upmodel.find({ studentid: _student.id });
  183. _student.tasks = tasks;
  184. data.push(_student);
  185. }
  186. return { total, data };
  187. }
  188. async findbystuids({ data }) {
  189. const res = [];
  190. for (const stuid of data) {
  191. const stu = await this.model.findById(stuid);
  192. if (stu)res.push(stu);
  193. }
  194. return res;
  195. }
  196. // 根据学生id删除学生
  197. async deletestus(data) {
  198. for (const el of data) {
  199. await this.model.deleteOne({ _id: ObjectId(el) });
  200. }
  201. }
  202. // 批量更新寝室号
  203. async updatabedroom(data) {
  204. for (const el of data) {
  205. const student = await this.model.findById(el.id);
  206. if (student) {
  207. student.bedroom = el.bedroom;
  208. await student.save();
  209. }
  210. }
  211. }
  212. /**
  213. * 计算班级的优秀学生
  214. * 规则:班级干部(学生的job!=='普通学生'),检查是否有评优资格(is_fine_status==='0'可以评优),全部评优;
  215. * 普通学生取总成绩前10的人评优(非10位并列时,名额该占用就占用;第10名若有并列,就全都要)
  216. * @param {String} param0 {id=>班级id}
  217. */
  218. async getFineStudent({ id: classid }) {
  219. // 获取班级学生列表
  220. let studentList = await this.model.find({ classid });
  221. // 重置评优,干部全优秀
  222. studentList = studentList.map(i => {
  223. if (i.job.includes('普通')) i.is_fine = '0';
  224. else i.is_fine = '1';
  225. return i;
  226. });
  227. // 初始化后取出不需要算的人,他们就这样,没必要算
  228. const reverseList = studentList.filter(f => !(f.is_fine !== '2' && f.job.includes('普通')));
  229. // 过滤出取消评优资格的学生和干部;干部就是优秀;被取消资格就别凑热闹了
  230. studentList = studentList.filter(f => f.is_fine !== '2' && f.job.includes('普通'));
  231. // 获取平时分
  232. const dailyScoreList = await this.psmodel.find({ classid });
  233. studentList = this.dealScoreList(dailyScoreList, studentList);
  234. // 获取作业分
  235. const taskScoreList = await this.upmodel.find({ classid });
  236. studentList = this.dealScoreList(taskScoreList, studentList);
  237. // 获取小组分,小组
  238. const groupList = await this.gmodel.find({ classid });
  239. const groupScoreList = await this.gsmodel.find({ classid });
  240. studentList = this.dealGroupScoreList(groupList, groupScoreList, studentList);
  241. studentList = studentList.sort((a, b) => (b.score * 1 || 0) - (a.score * 1 || 0));
  242. // 排名
  243. // eslint-disable-next-line no-unused-vars
  244. let num = 0;
  245. for (const student of studentList) {
  246. // 先判断是否超过第10位,超过就跳出
  247. if (num > 10) break;
  248. const { score, is_fine } = student;
  249. // 最开始初始化过所有人的状态,并且将干部和不能评优的人都过滤出去,所以正常学生应该都是没有评优,如果此处已经是优秀,那么就是和前人同分改的,直接跳过就好
  250. if (is_fine === '1') continue;
  251. // 没有分凑什么热闹
  252. if (!score) continue;
  253. let plus = 1; // 这轮有多少人,到这了,这个人肯定是要改了,所以默认1
  254. // 评优
  255. student.is_fine = '1';
  256. const rlist = studentList.filter(f => f.score === score);
  257. // 处理同分的人也都变成is_fine
  258. for (const stud of rlist) {
  259. stud.is_fine = '1';
  260. const sindex = studentList.findIndex(f => ObjectId(stud._id).equals(f._id));
  261. if (sindex >= 0) {
  262. studentList[sindex] = stud;
  263. plus++;
  264. }
  265. }
  266. // num+plus,算下num
  267. num = num + plus;
  268. }
  269. // 算完的和不用算的合并,提交
  270. const lastList = [ ...studentList, ...reverseList ];
  271. for (const student of lastList) {
  272. const res = await student.save();
  273. // const { meta, ...data } = student;
  274. // const r = await this.model.findByIdAndUpdate(
  275. // { _id: ObjectId(student._id) },
  276. // data
  277. // );
  278. console.log(res);
  279. }
  280. }
  281. /**
  282. * 将分数放到学生身上
  283. * @param {Array} scoreList 班级的分数列表
  284. * @param {Array} studentList 学生列表
  285. */
  286. dealScoreList(scoreList, studentList) {
  287. scoreList = _.groupBy(scoreList, 'studentid');
  288. studentList = studentList.map(i => {
  289. const slist = scoreList[i._id];
  290. if (slist)i.score = (i.score * 1 || 0) + slist.reduce((p, n) => p + (n.score * 1 || 0), 0);
  291. return i;
  292. });
  293. return studentList;
  294. }
  295. /**
  296. * 将 学生所在 组的 团队平均分 + 到学生身上
  297. * @param {Array} groupList 班级的小组的列表
  298. * @param {Array} scoreList 所有小组的分数列表
  299. * @param {Array} studentList 学生列表
  300. */
  301. dealGroupScoreList(groupList, scoreList, studentList) {
  302. // console.log(groupList);
  303. scoreList = _.groupBy(scoreList, 'groupid');
  304. // 算出每组的平均分,之后加给学生
  305. groupList = groupList.map(i => {
  306. const { students } = i;
  307. if (students.length > 0) {
  308. const slist = scoreList[i._id];
  309. if (slist) {
  310. i.score = slist.reduce((p, n) => p + (n.score * 1 || 0), 0);
  311. i.score = _.floor(_.divide(i.score, students.length), 2);
  312. }
  313. }
  314. return i;
  315. });
  316. // 每个学生加自己的组的平均分
  317. studentList = studentList.map(i => {
  318. const r = groupList.find(f => f.students.find(sf => ObjectId(sf.stuid).equals(i._id)));
  319. if (r) i.score = (i.score * 1 || 0) + (r.score * 1 || 0);
  320. return i;
  321. });
  322. return studentList;
  323. }
  324. // 将学生排号
  325. async arrangeNumber(classid) {
  326. const studList = await this.model.find({ classid });
  327. console.log(`in function:arrangeNumber classid=>${classid}`);
  328. let number = 1;
  329. // 查每个学生的编号,如果没有,就给赋上值;有,就给number赋上值,然后继续下一位
  330. for (const stu of studList) {
  331. if (!stu.number) {
  332. if (number * 1 < 10)stu.number = `0${number}`;
  333. else stu.number = number;
  334. await stu.save();
  335. } else {
  336. number = stu.number * 1;
  337. }
  338. number = number * 1 + 1;
  339. }
  340. console.log(`last number => ${number}`);
  341. }
  342. }
  343. module.exports = StudentService;