|
@@ -7,6 +7,7 @@ const assert = require('assert');
|
|
|
const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
|
const XLSX = require('xlsx');
|
|
|
const utils = require('../utils/utils.js');
|
|
|
+const moment = require('moment');
|
|
|
class TrainplanService extends CrudService {
|
|
|
constructor(ctx) {
|
|
|
super(ctx, 'trainplan');
|
|
@@ -356,27 +357,32 @@ class TrainplanService extends CrudService {
|
|
|
];
|
|
|
// 需要打出的列表
|
|
|
const _data = studentList;
|
|
|
- const headers = _headers.map(({ title }) =>
|
|
|
- title).map((v, i) =>
|
|
|
- Object.assign({}, { v, position: String.fromCharCode(65 + i) + 1 })
|
|
|
- ).reduce((prev, next) =>
|
|
|
- Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
- {}
|
|
|
- );
|
|
|
-
|
|
|
- const data = _data.map((v, i) =>
|
|
|
- _headers.map(({ key }, j) =>
|
|
|
- Object.assign(
|
|
|
- {},
|
|
|
- { v: v[key], position: String.fromCharCode(65 + j) + (i + 2) }
|
|
|
+ const headers = _headers
|
|
|
+ .map(({ title }) => title)
|
|
|
+ .map((v, i) =>
|
|
|
+ Object.assign({}, { v, position: String.fromCharCode(65 + i) + 1 })
|
|
|
+ )
|
|
|
+ .reduce(
|
|
|
+ (prev, next) =>
|
|
|
+ Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
+ {}
|
|
|
+ );
|
|
|
+
|
|
|
+ const data = _data
|
|
|
+ .map((v, i) =>
|
|
|
+ _headers.map(({ key }, j) =>
|
|
|
+ Object.assign(
|
|
|
+ {},
|
|
|
+ { v: v[key], position: String.fromCharCode(65 + j) + (i + 2) }
|
|
|
+ )
|
|
|
)
|
|
|
)
|
|
|
- ).reduce((prev, next) =>
|
|
|
- prev.concat(next)).reduce(
|
|
|
- (prev, next) =>
|
|
|
- Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
- {}
|
|
|
- );
|
|
|
+ .reduce((prev, next) => prev.concat(next))
|
|
|
+ .reduce(
|
|
|
+ (prev, next) =>
|
|
|
+ Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
+ {}
|
|
|
+ );
|
|
|
|
|
|
// 合并 headers 和 data
|
|
|
const output = Object.assign({}, headers, data);
|
|
@@ -534,15 +540,12 @@ class TrainplanService extends CrudService {
|
|
|
/** 头部-行列信息*/
|
|
|
const ws = XLSX.utils.aoa_to_sheet(data);
|
|
|
|
|
|
-
|
|
|
// 构建 workbook 对象
|
|
|
const nowDate = new Date().getTime();
|
|
|
const path =
|
|
|
- 'D:\\wwwroot\\service\\service-file\\upload\\train\\' +
|
|
|
- nowDate +
|
|
|
- '.xlsx';
|
|
|
+ 'D:\\wwwroot\\service\\service-file\\upload\\train\\' + nowDate + '.xlsx';
|
|
|
const respath =
|
|
|
- 'http://free.liaoningdoupo.com:80/files/train/' + nowDate + '.xlsx';
|
|
|
+ 'http://free.liaoningdoupo.com:80/files/train/' + nowDate + '.xlsx';
|
|
|
// 导出
|
|
|
const wb = XLSX.utils.book_new();
|
|
|
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
|
@@ -552,68 +555,218 @@ class TrainplanService extends CrudService {
|
|
|
// console.log(xuhao);
|
|
|
XLSX.writeFile(wb, path);
|
|
|
return respath;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 导出学校大表
|
|
|
+ async exportPlan({ trainplanId }) {
|
|
|
+ const wscols = [
|
|
|
+ { wpx: 50 }, // 第一列宽度设置单位px
|
|
|
+ ];
|
|
|
+ const monthList = [];
|
|
|
+ // 月份合并单元格
|
|
|
+ const colzb = 0;
|
|
|
+ const rowzb = 1;
|
|
|
+ // 头部合并单元格
|
|
|
+ const coltb = 0;
|
|
|
+ const rowtb = 0;
|
|
|
+ // 人数合并单元格
|
|
|
+ const colrs = 0;
|
|
|
+ const rowrs = 1;
|
|
|
+ // 人数数量合并单元格
|
|
|
+ const colrssl = 0;
|
|
|
+ const rowrssl = 3;
|
|
|
+
|
|
|
+ // 班级数合并单元格
|
|
|
+ const colbjs = 0;
|
|
|
+ const rowbjs = 1;
|
|
|
+ // 班级数数量合并单元格
|
|
|
+ const colbjssl = 0;
|
|
|
+ const rowbjssl = 3;
|
|
|
+ // 数据
|
|
|
+ const data = [];
|
|
|
+ // 计划表
|
|
|
+ const trainplan = await this.model.findOne({ _id: trainplanId });
|
|
|
+ const termnum = trainplan.termnum;
|
|
|
+ let classNum = 0;
|
|
|
+ // 获取最大的班级数,也就是月份的高
|
|
|
+ for (const term of termnum) {
|
|
|
+ if (term.classnum > classNum) {
|
|
|
+ classNum = parseInt(term.classnum);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 得到所有的节日日期的数组,然后循环时注意得到一个删除一个
|
|
|
+ const festivals = trainplan.festivals;
|
|
|
+ const festivalList = this.getfestivalList(festivals);
|
|
|
+ const termnumList = this.gettermnumList(termnum);
|
|
|
+ console.log(termnumList);
|
|
|
+ // 得到所有班级的数组,然后循环时注意得到一个删除一个
|
|
|
+
|
|
|
+ // 循环12个月,得到12个月以及每个月的数据
|
|
|
+ // for (let index = 1; index < 13; index++) {
|
|
|
+ // // 添加月份坐标
|
|
|
+ // const colRow = {
|
|
|
+ // s: { c: colzb, r: rowzb },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: colzb, r: rowzb + classNum + 1 },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,这里加3,代表头部+月份+星期,所以+3
|
|
|
+ // rowzb = rowzb + classNum + 3;
|
|
|
+ // monthList.push(colRow);
|
|
|
+
|
|
|
+ // // 添加头部坐标
|
|
|
+ // const colRowTB = {
|
|
|
+ // s: { c: coltb, r: rowtb },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: coltb + 33, r: rowtb },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,
|
|
|
+ // rowtb = rowtb + classNum + 3;
|
|
|
+ // monthList.push(colRowTB);
|
|
|
+
|
|
|
+ // // 添加人数坐标
|
|
|
+ // const colRowRS = {
|
|
|
+ // s: { c: colrs + 32, r: rowrs },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: colrs + 32, r: rowrs + 1 },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,
|
|
|
+ // rowrs = rowrs + classNum + 3;
|
|
|
+ // monthList.push(colRowRS);
|
|
|
+
|
|
|
+ // // 添加人数数量坐标
|
|
|
+ // const colRowRSSL = {
|
|
|
+ // s: { c: colrssl + 32, r: rowrssl },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: colrssl + 32, r: rowrssl + classNum - 1 },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,
|
|
|
+ // rowrssl = rowrssl + classNum + 3;
|
|
|
+ // monthList.push(colRowRSSL);
|
|
|
+
|
|
|
+ // // 添加班级数坐标
|
|
|
+ // const colRowBJS = {
|
|
|
+ // s: { c: colbjs + 33, r: rowbjs },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: colbjs + 33, r: rowbjs + 1 },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,
|
|
|
+ // rowbjs = rowbjs + classNum + 3;
|
|
|
+ // monthList.push(colRowBJS);
|
|
|
+
|
|
|
+ // // 添加班级数数量坐标
|
|
|
+ // const colRowBJSSL = {
|
|
|
+ // s: { c: colbjssl + 33, r: rowbjssl },
|
|
|
+ // // 保证留下7个空行,如果需要在上面加值,直接在下面加入即可第几空行加入就行
|
|
|
+ // e: { c: colbjssl + 33, r: rowbjssl + classNum - 1 },
|
|
|
+ // };
|
|
|
+ // // rowzb为上一次终止,那么起始需+1,
|
|
|
+ // rowbjssl = rowbjssl + classNum + 3;
|
|
|
+ // monthList.push(colRowBJSSL);
|
|
|
+
|
|
|
+ // const resDate = this.makeCalendar(trainplan.year, index);
|
|
|
+ // data.push([ '' ]);
|
|
|
+ // data.push([ this.getBigMonth(index) + '月' ].concat(resDate.dlist).concat([ '人数' ].concat([ '班级数' ])));
|
|
|
+ // data.push([ '' ].concat(resDate.tlist));
|
|
|
+
|
|
|
+ // // 加列数组
|
|
|
+ // for (let i = 0; i < classNum; i++) {
|
|
|
+ // data.push('');
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // // console.log(data);
|
|
|
+
|
|
|
+ // // ...以此类推即可
|
|
|
+ // /** 头部-行列信息*/
|
|
|
+ // const ws = XLSX.utils.aoa_to_sheet(data);
|
|
|
|
|
|
- // // 批次期次都在这里面
|
|
|
- // const trainplan = await this.model.find({ _id: trainplanId });
|
|
|
- // const _headers = [
|
|
|
- // { key: 'title', title: '计划标题' },
|
|
|
- // { key: 'year', title: '年度' },
|
|
|
- // ];
|
|
|
- // // 需要打出的列表
|
|
|
- // const _data = trainplan;
|
|
|
- // const headers = _headers.map(({ title }) =>
|
|
|
- // title).map((v, i) =>
|
|
|
- // Object.assign({}, { v, position: String.fromCharCode(65 + i) + 1 })
|
|
|
- // ).reduce((prev, next) =>
|
|
|
- // Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
- // {}
|
|
|
- // );
|
|
|
- // console.log('--------------------headers');
|
|
|
- // console.log(headers);
|
|
|
- // const data = _data.map((v, i) =>
|
|
|
- // _headers.map(({ key }, j) =>
|
|
|
- // Object.assign(
|
|
|
- // {},
|
|
|
- // { v: v[key], position: String.fromCharCode(65 + j) + (i + 2) }
|
|
|
- // )
|
|
|
- // )
|
|
|
- // ).reduce((prev, next) =>
|
|
|
- // prev.concat(next)).reduce((prev, next) =>
|
|
|
- // Object.assign({}, prev, { [next.position]: { v: next.v } }),
|
|
|
- // {}
|
|
|
- // );
|
|
|
- // console.log('--------------------data');
|
|
|
- // console.log(data);
|
|
|
- // // 合并 headers 和 data
|
|
|
- // const output = Object.assign({}, headers, data);
|
|
|
- // console.log('----------output');
|
|
|
- // console.log(output);
|
|
|
- // // 获取所有单元格的位置
|
|
|
- // const outputPos = Object.keys(output);
|
|
|
- // console.log('--------------------outputPos');
|
|
|
- // console.log(outputPos);
|
|
|
- // // 计算出范围
|
|
|
- // const ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];
|
|
|
- // console.log('--------------------ref');
|
|
|
- // console.log(ref);
|
|
|
// // 构建 workbook 对象
|
|
|
// const nowDate = new Date().getTime();
|
|
|
// const path =
|
|
|
- // 'D:\\wwwroot\\service\\service-file\\upload\\train\\' +
|
|
|
- // nowDate +
|
|
|
- // '.xlsx';
|
|
|
+ // 'D:\\wwwroot\\service\\service-file\\upload\\train\\' + nowDate + '.xlsx';
|
|
|
// const respath =
|
|
|
- // 'http://free.liaoningdoupo.com:80/files/train/' + nowDate + '.xlsx';
|
|
|
- // const wb = {
|
|
|
- // SheetNames: [ 'sheet0' ],
|
|
|
- // Sheets: { sheet0: Object.assign({}, output, { '!ref': ref }) },
|
|
|
- // // 导出 Excel
|
|
|
- // };
|
|
|
- // console.log('----------wb');
|
|
|
- // console.log(wb);
|
|
|
+ // 'http://free.liaoningdoupo.com:80/files/train/' + nowDate + '.xlsx';
|
|
|
+ // // 导出
|
|
|
+ // const wb = XLSX.utils.book_new();
|
|
|
+ // XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
|
|
+ // ws['!cols'] = wscols;
|
|
|
+ // ws['!merges'] = monthList;
|
|
|
+ // // console.log(xuhao);
|
|
|
// XLSX.writeFile(wb, path);
|
|
|
// return respath;
|
|
|
}
|
|
|
+ // 获取批次日期列表
|
|
|
+ gettermnumList(termnums) {
|
|
|
+ const termnumList = [];
|
|
|
+ for (const termnum of termnums) {
|
|
|
+ termnum.term;
|
|
|
+ termnum.classnum;
|
|
|
+ for (const batchnum of termnum.batchnum) {
|
|
|
+ batchnum.batch;
|
|
|
+ batchnum.class.length;
|
|
|
+ batchnum.startdate;
|
|
|
+ batchnum.enddate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return termnumList;
|
|
|
+ }
|
|
|
+ // 获取节假日集合
|
|
|
+ getfestivalList(festivals) {
|
|
|
+ let dateList = [];
|
|
|
+ for (let index = 0; index < festivals.length; index++) {
|
|
|
+ dateList = [
|
|
|
+ ...dateList,
|
|
|
+ ...utils.begindateEnddateSum(
|
|
|
+ festivals[index].begindate,
|
|
|
+ festivals[index].finishdate
|
|
|
+ ),
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ return dateList;
|
|
|
+ }
|
|
|
+ // 获取大月份传过来的值是以1月份开始的
|
|
|
+ getBigMonth(index) {
|
|
|
+ const monthBig = [ '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二' ];
|
|
|
+ return monthBig[index - 1];
|
|
|
+ }
|
|
|
+ // 获取这个月份的所有日期1~30号或者31或者28,或者29
|
|
|
+ makeCalendar(year, month = 1, month0) {
|
|
|
+ month0 = month;
|
|
|
+ if (month * 1 < 10) month = '0' + month;
|
|
|
+ // 获取这个月份的最大值
|
|
|
+ const days = moment(year + '-' + month).daysInMonth();
|
|
|
+ const dlist = this.getDayList(year, month, days, month0);
|
|
|
+ while (dlist.dlist.length < 31) {
|
|
|
+ dlist.dlist.push('');
|
|
|
+ }
|
|
|
+ return dlist;
|
|
|
+ }
|
|
|
+ // 获取这个月份的1-30号经过加工的
|
|
|
+ getDayList(year, month, days, month0) {
|
|
|
+ const dlist = [];
|
|
|
+ const tlist = [];
|
|
|
+ const all = {};
|
|
|
+ for (let index = 0; index < days; index++) {
|
|
|
+ dlist.push(month0 + '月' + moment(year + '-' + month).add(index, 'days').format('D') + '日');
|
|
|
+ let dayy = parseInt(index + 1);
|
|
|
+ if (dayy * 1 < 10) dayy = '0' + dayy;
|
|
|
+ tlist.push(this.getWeekDay(year + '-' + month + '-' + dayy));
|
|
|
+ }
|
|
|
+ all.dlist = dlist;
|
|
|
+ all.tlist = tlist;
|
|
|
+ return all;
|
|
|
+ }
|
|
|
+ // 获取星期几
|
|
|
+ getWeekDay(datestr) {
|
|
|
+ const weekday = moment(datestr).weekday();
|
|
|
+ if (weekday || weekday === 0) {
|
|
|
+ // console.log(weekday);
|
|
|
+ const arr = [ '日', '一', '二', '三', '四', '五', '六' ];
|
|
|
+ return '星期' + arr[weekday];
|
|
|
+ }
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ // async updateclass({ trainplanid, classid, rightHeader }) {
|
|
|
+ // assert(trainplanid && classid && rightHeader, '缺少参数项');
|
|
|
|
|
|
async updateclass({ trainplanid, termid, batchid, classid, rightHeader }) {
|
|
|
assert(trainplanid && termid && batchid && classid && rightHeader, '缺少参数项');
|