123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- // 题目
- class QuestionService extends CrudService {
- constructor(ctx) {
- super(ctx, 'question');
- this.model = this.ctx.model.Question;
- this.excelService = this.ctx.service.excel;
- this.typeModel = this.ctx.model.QuestionType;
- }
- async import({ url }) {
- const data = await this.excelService.importExcel(url);
- const head = _.head(data);
- let meta = this.getMeta();
- // 将meta整理下,把对应的列加上,key为index
- meta = meta.map(i => {
- if (!i.children) {
- const rIndex = head.findIndex(f => f === i.label);
- if (rIndex >= 0) i.index = rIndex;
- } else {
- for (const c of i.children) {
- const rcIndex = head.findIndex(f => f === c.label);
- if (rcIndex >= 0) c.index = rcIndex;
- }
- }
- return i;
- });
- // 表头干掉,处理数据不需要它
- data.shift();
- const midData = [];
- for (const row of data) {
- // row:每行数据
- const questData = {};
- for (const m of meta) {
- // 检查有没有index;如果是直接m.index,需要排除 值=0的情况(不明白的话,let x = 0,然后if(x)走下就知道了)
- // 所以换了个写法,只检查有没有该key
- const keys = Object.keys(m);
- if (!keys.includes('index') && !keys.includes('children')) continue;
- const { key, index, type, format } = m;
- if (!m.children) {
- const val = row[index];
- if (format && _.isFunction(format)) questData[key] = format(val);
- else questData[key] = val;
- } else {
- // 根据meta创建类型
- questData[key] = type === 'Array' ? [] : {};
- // 添加数据的方法
- const addToObject = type === 'Array' ? data => questData[key].push(data) : data => (questData[key] = { ...questData[key], ...data });
- const midObject = {};
- for (const c of m.children) {
- const { key: ckey, index: cIndex, format } = c;
- const val = row[cIndex];
- if (format && _.isFunction(format)) midObject[ckey] = format(val);
- else midObject[ckey] = val;
- }
- addToObject(midObject);
- }
- }
- midData.push(questData);
- }
- // 处理题
- let list = this.dealImportData(midData);
- // 将type换成系统中有的题型的id
- list = await this.changeType(list);
- const res = await this.model.insertMany(list);
- return res;
- }
- /**
- * 处理type换成系统中有的题型的id
- * @param {Array} array 数据数组,除type外所有数据已经处理完
- */
- async changeType(array) {
- const typeList = await this.typeModel.find();
- for (const i of array) {
- // 此处需要检验.该题型的答案是单选/多选
- const r = typeList.find(f => i.type === f.title);
- if (r)i.type = r._id;
- }
- return array;
- }
- /**
- * 将数据整理成数据库格式
- * @param {Array} array 数据数组,title和type为题目分界,只是选项的话,没有
- */
- dealImportData(array) {
- const list = [];
- let operaData = {};
- for (const i of array) {
- if (_.get(i, 'title') && _.get(i, 'type')) {
- if (_.get(operaData, 'title') && _.get(operaData, 'type')) {
- // 之前的题合并完了.该下一题了
- list.push(_.cloneDeep(operaData));
- // 新题
- operaData = i;
- } else {
- // 新题合并
- operaData = i;
- }
- } else {
- // 合并选项
- if (_.isArray(operaData.selects) && _.isArray(i.selects)) {
- operaData.selects = [ ...operaData.selects, ...i.selects ];
- }
- }
- }
- // 循环结束后,最后一个题扔保留在operaData中,放进list里
- if (operaData.title) {
- list.push(operaData);
- }
- return list;
- }
- getMeta() {
- return [
- { label: '题目', key: 'title' },
- { label: '题型', key: 'type', remark: '需要用字符串找到question_type的title一致的数据,将id拿来' },
- {
- key: 'selects',
- type: 'Array',
- children: [
- { label: '答案内容', key: 'title' },
- {
- label: '是否正确',
- key: 'isRight',
- format: i => {
- if (i === '是') return true;
- },
- },
- ],
- },
- ];
- }
- }
- module.exports = QuestionService;
|