teacher.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = require('lodash');
  4. const moment = require('moment');
  5. const XLSX = require('xlsx');
  6. const { CrudService } = require('naf-framework-mongoose/lib/service');
  7. const { BusinessError, ErrorCode } = require('naf-core').Error;
  8. const stringRandom = require('string-random');
  9. class TeacherService extends CrudService {
  10. constructor(ctx) {
  11. super(ctx, 'teacher');
  12. this.model = this.ctx.model.Teacher;
  13. this.umodel = this.ctx.model.User;
  14. const { baseUrl } = _.get(this.ctx.app.config, 'mission');
  15. if (baseUrl) this.missionBase = baseUrl;
  16. }
  17. async query({ name, ...info } = {}, { skip = 0, limit = 0 } = {}) {
  18. const query = { ...info };
  19. if (name) {
  20. query.name = { $regex: name };
  21. }
  22. let res = await this.model
  23. .find(query)
  24. .skip(Number(skip))
  25. .limit(Number(limit));
  26. res = JSON.parse(JSON.stringify(res));
  27. for (const tea of res) {
  28. const r = await this.umodel.findOne({ uid: tea._id }, '+passwd');
  29. if (r) {
  30. const { passwd } = r;
  31. tea.secret = passwd.secret;
  32. tea.openid = _.get(r, 'openid');
  33. }
  34. }
  35. return res;
  36. }
  37. async count({ name, ...info } = {}) {
  38. const query = { ...info };
  39. if (name) {
  40. query.name = { $regex: name };
  41. }
  42. const res = await this.model.count(query);
  43. return res;
  44. }
  45. // 根据状态删除教师信息
  46. async deleteByStatus({ status }) {
  47. await this.model.deleteMany({ status });
  48. return 'deleted';
  49. }
  50. // 查询详情
  51. async fetchTeacher({ id }) {
  52. // 将文件拼到查询到的数据后
  53. return await this.model.findById(id, '+file');
  54. }
  55. // 批量查询教师
  56. async fetchteachers({ ids }) {
  57. return await this.model.find({ _id: { $in: ids } });
  58. }
  59. // 检查教师
  60. async checkarrange({ id, date }) {}
  61. async status(data) {
  62. const { teachersid, zlscore, msscore, status, remark } = data;
  63. for (const teacherid of teachersid) {
  64. const teacher = await this.model.findById(teacherid);
  65. teacher.status = status;
  66. if (zlscore) {
  67. teacher.zlscore = zlscore;
  68. }
  69. if (msscore) {
  70. teacher.msscore = msscore;
  71. }
  72. await teacher.save();
  73. let detail = '';
  74. if (status === '1') {
  75. const passwd = stringRandom();
  76. detail =
  77. '您的账号身份已确认,密码为:' +
  78. passwd +
  79. '请尽快登录账号上传课件资料附件';
  80. // 状态更新后创建教师用户
  81. const newdata = {
  82. name: teacher.name,
  83. mobile: teacher.phone,
  84. type: '3',
  85. uid: teacher.id,
  86. gender: teacher.gender,
  87. passwd,
  88. };
  89. await this.ctx.service.user.create(newdata);
  90. } else if (status === '4') {
  91. detail = '您已通过审核被正式录入教师库';
  92. }
  93. const date = await this.ctx.service.util.updatedate();
  94. const user = await this.umodel.findOne({ uid: teacher.id, type: '3' });
  95. if (user && user.openid) {
  96. await this.ctx.service.weixin.sendTemplateMsg(
  97. this.ctx.app.config.REVIEW_TEMPLATE_ID,
  98. user.openid,
  99. '您有一个新的通知',
  100. detail,
  101. date,
  102. remark
  103. );
  104. } else {
  105. await this.ctx.service.util.sendMail(
  106. teacher.email,
  107. '账号审核',
  108. detail,
  109. ''
  110. );
  111. }
  112. }
  113. }
  114. // 教室分数上传
  115. async teaimport(data) {
  116. const { filepath } = data;
  117. assert(filepath, 'filepath不能为空');
  118. // 取得excle中数据
  119. const _filepath = this.ctx.app.config.baseUrl + filepath;
  120. const teadatas = await this.getImportXLSXData(_filepath);
  121. // 将得到的数据校验
  122. const datacheck = await this.datacheck(teadatas);
  123. if (datacheck.errorcode === '1') {
  124. return datacheck;
  125. }
  126. // 将数据存入数据库中
  127. for (const tea of teadatas) {
  128. const res = await this.model.findOne({
  129. idnumber: tea.idnumber,
  130. name: tea.name,
  131. });
  132. if (res) {
  133. res.beforescore = tea.xsscore;
  134. await res.save();
  135. }
  136. }
  137. return datacheck;
  138. }
  139. // 获取导入的XLSX文件中的数据
  140. async getImportXLSXData(filepath) {
  141. const file = await this.ctx.curl(filepath);
  142. const workbook = XLSX.read(file.data);
  143. // 读取内容
  144. let exceldata = [];
  145. const sheetNames = workbook.SheetNames; // 获取表名
  146. const sheet = workbook.Sheets[sheetNames[0]]; // 通过表名得到表对象
  147. // 遍历26个字母
  148. const theadRule = [];
  149. const range = XLSX.utils.decode_range(sheet['!ref']);
  150. const col_start = range.s.c;
  151. const col_end = range.e.c;
  152. for (let i = col_start; i <= col_end; i++) {
  153. const addr = XLSX.utils.encode_col(i) + XLSX.utils.encode_row(0);
  154. theadRule.push(sheet[addr].v);
  155. }
  156. const params = XLSX.utils.sheet_to_json(sheet); // 通过工具将表对象的数据读出来并转成json
  157. if (!params) return [];
  158. const length = params.length;
  159. const _datas = [];
  160. let data = {};
  161. for (let i = 0; i < length; i++) {
  162. data = params[i];
  163. _datas.push({
  164. idnumber: data[theadRule[1]],
  165. name: data[theadRule[2]],
  166. xsscore: data[theadRule[3]],
  167. });
  168. }
  169. exceldata = [ ...exceldata, ..._datas ];
  170. return exceldata;
  171. }
  172. // 获取导入的XLSX文件中的数据
  173. async datacheck(studatas) {
  174. let errorcode = '0';
  175. const errormsg = [];
  176. for (const data of studatas) {
  177. // 判断是否为空
  178. if (!data.idnumber) {
  179. errorcode = '1';
  180. data.msg = data.msg + '身份证号不允许为空,';
  181. }
  182. if (!data.name) {
  183. errorcode = '1';
  184. data.msg = data.msg + '姓名不允许为空,';
  185. }
  186. if (!data.xsscore) {
  187. errorcode = '1';
  188. data.msg = data.msg + '评分不允许为空,';
  189. }
  190. if (errorcode === '1') {
  191. errormsg.push(data);
  192. }
  193. }
  194. return { errorcode, errormsg };
  195. }
  196. // 建立任务
  197. async toExport(body) {
  198. const fn = `教师导出 ${moment().format('YYYY-MM-DD HH:SS:mm')}`;
  199. const data = {
  200. title: fn,
  201. params: {
  202. project: 'center',
  203. service: 'teacher',
  204. method: 'export',
  205. body,
  206. },
  207. };
  208. if (this.missionBase) {
  209. const url = `${this.missionBase}/api/mission`;
  210. const res = await this.ctx.curl(url, {
  211. method: 'post',
  212. headers: {
  213. 'content-type': 'application/json',
  214. },
  215. data,
  216. dataType: 'json',
  217. });
  218. if (res.status !== 200 || res.data.errcode !== 0) {
  219. throw new BusinessError(ErrorCode.SERVICE_FAULT, '创建任务失败');
  220. }
  221. } else {
  222. throw new BusinessError(ErrorCode.SERVICE_FAULT, '未找到任务项目设置');
  223. }
  224. }
  225. // 导出
  226. async export({ missionid, model }) {
  227. assert(missionid, '缺少任务信息,无法执行任务');
  228. try {
  229. const head = model.map(i => {
  230. const { zh, model } = i;
  231. const headObj = { header: zh };
  232. if (model) headObj.key = model;
  233. headObj.width = 20;
  234. return headObj;
  235. });
  236. const fn = '教师导出';
  237. const data = await this.query();
  238. console.log(data.length);
  239. if (data.length <= 0) {
  240. throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到教师信息');
  241. }
  242. this.ctx.service.util.updateProcess(missionid, '50');
  243. const res = await this.ctx.service.util.toExcel(data, head, fn);
  244. console.log(res);
  245. if (!res) {
  246. console.error(
  247. `${moment().format('YYYY-MM-DD HH:mm:ss')} ${fn} 导出失败`
  248. );
  249. throw new BusinessError(ErrorCode.SERVICE_FAULT, `${fn}导出失败`);
  250. }
  251. this.ctx.service.util.updateProcess(missionid, '100', '2', {
  252. uri: res,
  253. });
  254. } catch (error) {
  255. console.log('in function:error');
  256. this.ctx.service.util.updateProcess(missionid, undefined, '3');
  257. }
  258. }
  259. }
  260. module.exports = TeacherService;