'use strict'; const assert = require('assert'); const _ = require('lodash'); const fs = require('fs'); const Excel = require('exceljs'); const { ObjectId } = require('mongoose').Types; const { CrudService } = require('naf-framework-mongoose/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const moment = require('moment'); const nodemailer = require('nodemailer'); const { template } = require('lodash'); const docx = require('docx'); const archiver = require('archiver'); class UtilService extends CrudService { async updatedate() { let date = new Date(); date = moment(date).format('YYYY-MM-DD HH:mm:ss'); return date; } async sendMail(email, subject, text, html) { const setting = await this.ctx.model.Setting.findOne(); let user_email = this.ctx.app.config.user_email; let auth_code = this.ctx.app.config.auth_code; if (setting) { user_email = setting.user_email; auth_code = setting.auth_code; } const transporter = nodemailer.createTransport({ host: 'smtp.exmail.qq.com', secureConnection: true, port: 465, auth: { user: user_email, // 账号 pass: auth_code, // 授权码 }, }); const mailOptions = { from: user_email, // 发送者,与上面的user一致 to: email, // 接收者,可以同时发送多个,以逗号隔开 subject, // 标题 text, // 文本 html, }; try { await transporter.sendMail(mailOptions); return true; } catch (err) { return false; } } async findone({ modelname }, data) { // 查询单条 const _model = _.capitalize(modelname); const res = await this.ctx.model[_model].findOne({ ...data }); return res; } async findbyids({ modelname }, { data }) { // 共通批量查询方法 const _model = _.capitalize(modelname); const res = []; for (const elm of data) { const result = await this.ctx.model[_model].findById(elm); res.push(result); } return res; } async findmodel({ modelname }) { const _model = _.capitalize(modelname); const data = this.ctx.model[_model].prototype.schema.obj; return data; } async utilMethod(data, body) { // 将指定计划,期数的教师状态解除确认 let trainPlan = await this.ctx.model.Trainplan.findById('5f5adb337ceb003386c9b0d4'); trainPlan = JSON.parse(JSON.stringify(trainPlan)); let terms = {}; for (const term of trainPlan.termnum) { if (ObjectId('5f5aed5e69b4221aedaa5005').equals(term._id)) { for (const batch of term.batchnum) { for (const c of batch.class) { for (const l of c.lessons) { l.status = '0'; } } } terms = term; } } const i = trainPlan.termnum.findIndex(f => ObjectId('5f5aed5e69b4221aedaa5005').equals(f._id)); trainPlan.termnum[i] = terms; delete trainPlan.meta; const r = await this.ctx.model.Trainplan.update( { _id: ObjectId('5f5adb337ceb003386c9b0d4') }, { ...trainPlan } ); console.log(r); // const output = fs.createWriteStream('E:\\exportFile\\test.zip'); // const archive = archiver('zip', { // zlib: { level: 9 }, // }); // archive.pipe(output); // const res = await this.ctx.curl('http://jytz.jilinjobs.cn/files/task/20200914174650.jpg'); // if (res && res.data) { // archive.append(res.data, { name: 'test.jpg', prefix: 'test/test2/test3' }); // } // archive.finalize(); } async teacherImport() { // const filepath = './teacherlist.xlsx'; // const workbook = new Excel.Workbook(); // await workbook.xlsx.readFile(filepath); // const worksheet = workbook.getWorksheet(1); // if (!worksheet) return; // let arr = []; // worksheet.eachRow((row, ri) => { // if (ri !== 1) { // const obj = {}; // obj.name = row.getCell(3).value || undefined; // obj.department = row.getCell(4).value || undefined; // if (row.getCell(5).value) obj.job = row.getCell(5).value; // obj.phone = row.getCell(6).value || undefined; // obj.status = '4'; // arr.push(obj); // } // }); // // 检查谁生成过了, user表和teacher表 // let ur = await this.ctx.model.User.find({ mobile: { $in: arr.map(i => i.phone) }, type: '3' }); // let tr = await this.ctx.model.Teacher.find({ phone: { $in: arr.map(i => i.phone) } }); // // 将有的老师过滤出去 // if (ur) { // ur = JSON.parse(JSON.stringify(ur)); // arr = arr.filter(f => !ur.find(uf => `${uf.mobile}` === `${f.phone}`)); // } // if (tr) { // tr = JSON.parse(JSON.stringify(tr)); // arr = arr.filter(f => !(tr.find(tf => `${tf.phone}` === `${f.phone}`))); // } // for (const tea of arr) { // const ctr = await this.ctx.model.Teacher.create(tea); // if (ctr) { // const obj = { name: tea.name, mobile: tea.phone, type: '3', uid: ctr._id }; // const cur = await this.ctx.model.User.create(obj); // } // } // const user = await this.ctx.model.User.find({ passwd: { $exists: false } }); // console.log(user.length); // for (const u of user) { // u.passwd = { secret: '12345678' }; // u.save(); // } } async toExcel(dataList, meta, fn = '导出结果') { console.log(meta); // 导出excel const { app } = this; const nowDate = new Date().getTime(); const filename = `${fn}-${nowDate}.xlsx`; // 取出预设存储地址 const rootPath = `${app.config.cdn.repos_root_path}`; const rooturl = `${app.config.cdn.repos_root_url_excel}`; let path = `${rootPath}${rooturl}`; if (!path) { throw new BusinessError(ErrorCode.BUSINESS, '服务端没有设置存储路径'); } if (process.env.NODE_ENV === 'development') path = 'E:\\exportFile\\'; if (!fs.existsSync(path)) { // 如果不存在文件夹,就创建 fs.mkdirSync(path); } // 生成文件 const filepath = `${path}${filename}`; fs.createWriteStream(filepath); const workbook = new Excel.Workbook(); const sheet = workbook.addWorksheet('sheet'); sheet.columns = meta; sheet.addRows(dataList); await workbook.xlsx.writeFile(filepath); return `/files/excel/${filename}`; } /** * 导出docx * @param {Array} data 数据[{title,content([]),author}] * @param {String} fn 文件名 */ async toDocx(data, fn = '培训心得') { const { Document, Packer, Paragraph, TextRun, HeadingLevel, AlignmentType, } = docx; const doc = new Document(); const children = []; // 整理数据 for (let i = 0; i < data.length; i++) { const obj = data[i]; const { title, content, author } = obj; const c = []; if (title) { const tit = new Paragraph({ children: [ new TextRun({ text: title, bold: true }) ], heading: HeadingLevel.TITLE, alignment: AlignmentType.CENTER, }); c.push(tit); } if (author) { const auth = new Paragraph({ children: [ new TextRun({ color: '#000000', text: author }) ], heading: HeadingLevel.HEADING_2, alignment: AlignmentType.RIGHT, }); c.push(auth); } if (content && _.isArray(content) && content.length > 0) { for (const cont of content) { const p = new Paragraph({ children: [ new TextRun({ text: cont, bold: true }) ], }); c.push(p); } } if (i !== data.length - 1) { // 换页 const last = new Paragraph({ pageBreakBefore: true, }); c.push(last); } if (c.length > 0) children.push(...c); } doc.addSection({ properties: {}, children, }); const { app } = this; const rootPath = `${app.config.cdn.repos_root_path}`; const rooturl = `${app.config.cdn.repos_root_url_experience}`; let path = `${rootPath}${rooturl}`; // 如果不存在文件夹,就创建 if (process.env.NODE_ENV === 'development') path = 'E:\\exportFile\\'; if (!fs.existsSync(path)) { fs.mkdirSync(path); } const num = new Date().getTime(); const buffer = await Packer.toBuffer(doc); fs.writeFileSync(`${path}${fn}-${num}.docx`, buffer); // Packer.toBuffer(doc).then(buffer => { // fs.writeFileSync(`${path}${fn}-${num}.docx`, buffer); // }); return `/files${rooturl}${fn}-${num}.docx`; } /** * 将选择的文件导出到zip压缩包中,提供下载 * @param {*} fileList 需要导入到zip中的列表,格式有2中: [{url:""}]或[String] * @param {*} fn 文件名,默认为 "导出结果" */ async toZip(fileList, fn = '导出结果') { if (!_.isArray(fileList)) { throw new BusinessError(ErrorCode.DATA_INVALID, '需要压缩的文件数据格式错误'); } fn = `${fn}.zip`; // zip文件夹创建 const { app } = this; const rootPath = `${app.config.cdn.repos_root_path}`; const zipPath = `${app.config.cdn.repos_root_url_zip}`; let path = `${rootPath}${zipPath}`; if (process.env.NODE_ENV === 'development') path = 'E:\\exportFile\\'; if (!fs.existsSync(path)) { fs.mkdirSync(path); } // 文件请求后将数据整理到这里 const resetFileList = []; for (const file of fileList) { let uri = ''; let filename = ''; let prefixs; if (_.isString(file)) { uri = file; const arr = file.split('/'); const last = _.last(arr); if (last) filename = last; } else if (_.isObject(file)) { const { uri: furi, url: furl, name, prefix } = file; if (furi) uri = furi; else if (furl) uri = furl; if (name) filename = name; else { const arr = uri.split('/'); const last = _.last(arr); if (last) filename = last; } if (prefix) prefixs = prefix; } const obj = {}; if (uri) obj.uri = uri; if (filename)obj.filename = filename; if (prefixs) obj.prefix = prefixs; resetFileList.push(obj); } // 导出 const output = fs.createWriteStream(`${path}${fn}`); const archive = archiver('zip', { zlib: { level: 9 }, }); archive.pipe(output); // 请求文件,追加进压缩包 for (const file of resetFileList) { const { uri, filename, prefix } = file; const res = await this.ctx.curl(`http://127.0.0.1${uri}`); if (res && res.data) { const options = {}; if (filename)options.name = filename; if (prefix) options.prefix = prefix; if (filename) { archive.append(res.data, options); } } } await archive.finalize(); return `/files${zipPath}${fn}`; } } module.exports = UtilService;