'use strict'; const assert = require('assert'); const _ = require('lodash'); const moment = require('moment'); const XLSX = require('xlsx'); const { CrudService } = require('naf-framework-mongoose/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const stringRandom = require('string-random'); const { ObjectId } = require('mongoose').Types; class TeacherService extends CrudService { constructor(ctx) { super(ctx, 'teacher'); this.model = this.ctx.model.Teacher; this.umodel = this.ctx.model.User; const { baseUrl } = _.get(this.ctx.app.config, 'mission'); if (baseUrl) this.missionBase = baseUrl; this.yjy = this.ctx.model.Yjyconnect; this.export_limit = 50; } async query({ name, ...info } = {}, { skip = 0, limit = 0 } = {}) { const query = { ...info }; if (name) { query.name = { $regex: name }; } let rs = await this.model.find(query, null, { skip, limit }).exec(); if (rs.length > 0) rs = JSON.parse(JSON.stringify(rs)); const ids = rs.map((i) => ObjectId(i._id).toString()); const users = await this.umodel.find({ uid: ids }).lean(); const uids = users.map((i) => ObjectId(i._id).toString()); const yjyUsers = await this.yjy.find({ suid: uids }).lean(); for (const i of rs) { const { _id: did } = i; const user = users.find((f) => ObjectId(did).equals(f.uid)); if (!user) { i.is_bind = false; continue; } const yjyUser = yjyUsers.find((f) => ObjectId(user._id).equals(f.suid)); if (yjyUser) i.is_bind = true; else i.is_bind = false; } return rs; } async count({ name, ...info } = {}) { const query = { ...info }; if (name) { query.name = { $regex: name }; } const res = await this.model.count(query); return res; } // 根据状态删除教师信息 async deleteByStatus({ status }) { await this.model.deleteMany({ status }); return 'deleted'; } // 查询详情 async fetchTeacher({ id }) { // 将文件拼到查询到的数据后 return await this.model.findById(id, '+file'); } async create(data) { const { name, phone: mobile } = data; const user = await this.umodel.findOne({ mobile }); if (user) { throw new BusinessError(ErrorCode.DATA_EXIST, '电话已经存在'); } // 创建教师信息 const res = await this.model.create(data); // 再创建教师用户 const passwd = stringRandom(); const newdata = { name, mobile, type: '3', uid: ObjectId(res.id || res._id).toString(), passwd: { secret: passwd }, }; await this.umodel.create(newdata); // 返回教师信息 return this.model.findById(res._id || res.id); } async delete({ id }) { await this.model.findByIdAndDelete(id); await this.umodel.deleteOne({ uid: id, type: '3' }); return 'deleted'; } // 批量查询教师 async fetchteachers({ ids }) { return await this.model.find({ _id: { $in: ids } }); } // 检查教师 async checkarrange({ id, date }) {} async status(data) { const { teachersid, zlscore, msscore, status, remark } = data; for (const teacherid of teachersid) { const teacher = await this.model.findById(teacherid); console.log(status); teacher.status = status; if (zlscore) { teacher.zlscore = zlscore; } if (msscore) { teacher.msscore = msscore; } await teacher.save(); let detail = ''; if (status === '1') { const userInfo = await this.umodel.findOne({ uid: teacherid }, '+passwd'); if (!userInfo) continue; const passwd = _.get(userInfo, 'passwd.secret'); detail = '您的账号身份已确认,密码为:' + passwd + '请尽快登录账号上传课件资料附件'; } else if (status === '4') { detail = '您已通过审核被正式录入教师库'; } const date = await this.ctx.service.util.updatedate(); const user = await this.umodel.findOne({ uid: teacher.id, type: '3' }); if (user && user.openid) { await this.ctx.service.weixin.sendTemplateMsg(this.ctx.app.config.REVIEW_TEMPLATE_ID, user.openid, '您有一个新的通知', detail, date, remark); } else { await this.ctx.service.util.sendMail(teacher.email, '账号审核', detail, ''); } } } // 教室分数上传 async teaimport(data) { const { filepath } = data; assert(filepath, 'filepath不能为空'); // 取得excle中数据 const _filepath = this.ctx.app.config.baseUrl + filepath; const teadatas = await this.getImportXLSXData(_filepath); // 将得到的数据校验 const datacheck = await this.datacheck(teadatas); if (datacheck.errorcode === '1') { return datacheck; } // 将数据存入数据库中 for (const tea of teadatas) { const res = await this.model.findOne({ idnumber: tea.idnumber, name: tea.name, }); if (res) { res.beforescore = tea.xsscore; await res.save(); } } return datacheck; } // 获取导入的XLSX文件中的数据 async getImportXLSXData(filepath) { const file = await this.ctx.curl(filepath); const workbook = XLSX.read(file.data); // 读取内容 let exceldata = []; const sheetNames = workbook.SheetNames; // 获取表名 const sheet = workbook.Sheets[sheetNames[0]]; // 通过表名得到表对象 // 遍历26个字母 const theadRule = []; const range = XLSX.utils.decode_range(sheet['!ref']); const col_start = range.s.c; const col_end = range.e.c; for (let i = col_start; i <= col_end; i++) { const addr = XLSX.utils.encode_col(i) + XLSX.utils.encode_row(0); theadRule.push(sheet[addr].v); } const params = XLSX.utils.sheet_to_json(sheet); // 通过工具将表对象的数据读出来并转成json if (!params) return []; const length = params.length; const _datas = []; let data = {}; for (let i = 0; i < length; i++) { data = params[i]; _datas.push({ idnumber: data[theadRule[1]], name: data[theadRule[2]], xsscore: data[theadRule[3]], }); } exceldata = [...exceldata, ..._datas]; return exceldata; } // 获取导入的XLSX文件中的数据 async datacheck(studatas) { let errorcode = '0'; const errormsg = []; for (const data of studatas) { // 判断是否为空 if (!data.idnumber) { errorcode = '1'; data.msg = data.msg + '身份证号不允许为空,'; } if (!data.name) { errorcode = '1'; data.msg = data.msg + '姓名不允许为空,'; } if (!data.xsscore) { errorcode = '1'; data.msg = data.msg + '评分不允许为空,'; } if (errorcode === '1') { errormsg.push(data); } } return { errorcode, errormsg }; } // 建立任务 async toExport(body) { const fn = `教师导出 ${moment().format('YYYY-MM-DD HH:SS:mm')}`; const data = { title: fn, params: { project: 'center', service: 'teacher', 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({ missionid, model }) { assert(missionid, '缺少任务信息,无法执行任务'); try { const head = model.map((i) => { // const { zh, model } = i; // const headObj = { header: zh }; // if (model) headObj.key = model; // headObj.width = 20; // return headObj; return i.zh; }); let fn = '教师导出'; let skip = 0; const total = await this.count({}); const times = Math.ceil(total / this.export_limit); let dp = null; const { downloadPath, fn: nfn } = await this.ctx.service.util.toAsyncExcel([head], fn, dp); dp = downloadPath; fn = nfn; for (let i = 0; i < times; i++) { const data = await this.query({}, { skip, limit: this.export_limit }); if (data.length <= 0) break; const dataList = data.map((i) => { const obj = []; for (const m of model) { obj.push(i[m.model]); } return obj; }); await this.ctx.service.util.toAsyncExcel(dataList, fn, dp); skip = skip + this.export_limit; const per = Math.ceil(((i + 1) / times) * 100); this.ctx.service.util.updateProcess(missionid, per); } this.ctx.service.util.updateProcess(missionid, '100', '2', { uri: dp, }); } catch (error) { console.log('in function:error'); this.ctx.service.util.updateProcess(missionid, undefined, '3'); } } } module.exports = TeacherService;