lrf vor 4 Monaten
Ursprung
Commit
798363c194
2 geänderte Dateien mit 127 neuen und 15 gelöschten Zeilen
  1. 115 15
      src/controller/match/matchRegistration.controller.ts
  2. 12 0
      src/service/util.service.ts

+ 115 - 15
src/controller/match/matchRegistration.controller.ts

@@ -2,15 +2,19 @@ import { CVO_match, FVO_match, QVO_match, UVAO_match } from '../../interface/pla
 import { ApiResponse, ApiTags, ApiQuery } from '@midwayjs/swagger';
 import { Validate } from '@midwayjs/validate';
 import { Controller, Inject, Get, Param, Post, Body, Del, Query, Config } from '@midwayjs/core';
-import { cloneDeep, get, omit, pick } from 'lodash';
+import { cloneDeep, get, head, isArray, omit, pick } from 'lodash';
 import { ServiceError, ErrorCode } from '../../error/service.error';
 import { BaseController } from '../../frame/BaseController';
 import { MatchRegistrationService } from '../../service/match/matchRegistration.service';
 import { UserService } from '../../service/system/user.service';
 import * as bcrypt from 'bcryptjs';
+import * as Path from 'path'
 import dayjs = require('dayjs');
 import { MatchService } from '../../service/platform/match.service';
 import { ServiceUtilService } from '../../service/serviceUtil.service';
+import * as Excel from 'exceljs';
+import { UtilService } from '../../service/util.service';
+import { AliyunSmsService } from '../../service/thirdParty/aliyunSms.service';
 const namePrefix = '创新大赛-赛事报名';
 @ApiTags(['创新大赛-赛事报名'])
 @Controller('/matchReg', { tagName: namePrefix })
@@ -23,6 +27,12 @@ export class MatchRegistrationController implements BaseController {
   matchService: MatchService
   @Inject()
   serviceUtil: ServiceUtilService
+  @Inject()
+  utilService: UtilService;
+  @Inject()
+  smsService: AliyunSmsService
+
+
   @Config('PathConfig.path')
   path;
   @Get('/')
@@ -64,6 +74,7 @@ export class MatchRegistrationController implements BaseController {
   async create(@Body() data: object) {
     const userColumns = ['user', 'user_id'];
     let regData = omit(data, userColumns);
+    let returnUser = {};
     if (get(data, 'user_id')) {
       regData = { user_id: get(data, 'user_id'), ...regData };
     } else {
@@ -74,12 +85,18 @@ export class MatchRegistrationController implements BaseController {
       await this.userService.checkPhone(user);
       await this.userService.checkEmail(user);
       // 处理密码, TODO:可能会要自动生成
-      const passowrd = get(user, 'password');
-      if (passowrd) {
+      const password = get(user, 'password');
+      if (password) {
         const salt = bcrypt.genSaltSync(10);
-        const hash = bcrypt.hashSync(passowrd, salt);
+        const hash = bcrypt.hashSync(password, salt);
         Object.assign(user, { password: hash });
       }
+      returnUser = { password, account: get(user, 'account') }
+      // 发送短信
+      const phone = get(user, 'phone')
+      const msg = { "账号": get(user, 'account'), "密码": password }
+      await this.smsService.send(phone, msg)
+
       const dbData = await this.userService.create(user);
       regData = { user_id: dbData.id, ...regData };
     }
@@ -92,7 +109,8 @@ export class MatchRegistrationController implements BaseController {
     const no = `${get(data, 'match_id')}-${get(regData, 'user_id')}-${matchRegTotal + 1}`;
     regData = { ...regData, no, time: dayjs().format('YYYY-MM-DD HH:mm:ss') };
     const result = await this.service.create(regData);
-    return result;
+    if (Object.keys(returnUser).length > 0) return returnUser
+    else return result;
   }
 
   @Post('/:id', { routerName: `修改${namePrefix}` })
@@ -121,7 +139,7 @@ export class MatchRegistrationController implements BaseController {
     return data;
   }
 
-  @Get('/detail/:match_id')
+  @Get('/export/:match_id')
   @ApiTags('导出初赛名单')
   async exportList(@Param('match_id') match_id: string) {
     // 查询所有未被退回的报名信息
@@ -133,32 +151,114 @@ export class MatchRegistrationController implements BaseController {
     if (!match) throw new ServiceError(ErrorCode.MATCH_NOT_FOUND)
     // 获取赛事名称, 赛事名称放首行
     const match_name = get(match, 'name')
+    const fir = ['赛事名称', match_name]
     // 第二行是表头: 项目编号,用户名称,报名时间, ...报名信息,分数
-    const header = ['项目编号', '用户名称', '报名时间']
-    // TODO: 将报名信息的问题塞进来
-
+    const sec = ['项目编号', '用户名称', '报名时间']
+    // 将报名信息的问题塞进来, 并整理出文件列,计算出文件列的字母
+    const firstData = head(data);
+    const info = get(firstData, 'info', [])
+    const fileColumns = []
+    for (const i of info) {
+      const problem = get(i, 'problem')
+      sec.push(problem)
+      const type = get(i, 'type')
+      if (type === '5' || type === '7') {
+        const length = sec.length
+        const col = this.utilService.ToExcelColumn(length - 1)
+        const sid = get(i, 'sid')
+        fileColumns.push({ sid, col })
+      }
+    }
     // 填充分数列
-    header.push('分数')
-    const list = [];
+    sec.push('分数')
+    const workbook = new Excel.Workbook();
+    const sheet = workbook.addWorksheet('sheet1');
+    sheet.addRow(fir)
+    sheet.addRow(sec);
     // 整理数据
-    for (const i of data) {
+    for (let index = 0; index < data.length; index++) {
+      const i = data[index];
       const item = [];
       // 项目编号
       const no = get(i, 'no', "")
       item.push(no)
       // 用户信息
       const user = await this.userService.fetch({ id: get(i, 'user_id') });
-      if (user) item.push(get(user, 'nick_nake'))
+      if (user) item.push(get(user, 'nick_name'))
       else item.push("")
       // 报名时间
       const time = get(i, 'time', "")
       item.push(time)
-      // TODO:处理报名信息
+      // 处理报名信息
+      const info = get(i, 'info', [])
+      for (const is of info) {
+        const type = get(is, 'type')
+        const val = get(is, 'reply', '')
+        // 0:单选;2:下拉;3:单行文本;4:多行文本
+        if (type === '0' || type === '2' || type === '3' || type === '4') {
+          item.push(val)
+        } else if (type === '1') {
+          // 1:多选
+          item.push(val.join(';'))
+        } else if (type === '5' || type === '7') {
+          // 5:图片/文件;7:附件模板
+          // 1.需要确定单元格位置,生成超链接格式,1个单元格只能有一个超链接
+          const sid = get(is, 'sid')
+          const headFile = head(val)
+          const link = {
+            text: get(headFile, 'name'),
+            hyperlink: get(headFile, 'uri'),
+            toolTip: get(headFile, 'uri'),
+          }
+          const posObj = fileColumns.find(f => f.sid === sid)
+          if (!posObj) continue;
+          posObj.value = link;
+          posObj.line = index + 1 + 2; // +1 是索引加1为行数; +2 是表格从第三行开始的
+          // for (const valI of val) {
+          //   const fileName = get(valI, 'name')
+          //   // TODO:需要加上域名
+          //   const uri = get(valI, 'uri')
+          //   const link = {
+          //     text: fileName,
+          //     hyperlink: uri,
+          //     tooltip: uri
+          //   }
+          // }
+
+
+        } else if (type === '6') {
+          // 6:数组,将sid外的 key,value拼成字符串作为内容
+          if (!isArray(val)) continue;
+          const midArr = []
+          for (const valI of val) {
+            const obj = omit(valI, ['sid'])
+            for (const key in obj) {
+              midArr.push(`${key}: ${obj[key]}`)
+            }
+          }
+          // 将键值对拼成字符串
+          item.push(midArr.join(';'))
+        }
+      }
+      sheet.addRow(item)
+    }
+    // 处理超链接
+    for (const i of fileColumns) {
+      const col = get(i, 'col')
+      const line = get(i, 'line')
+      const pos = `${col}${line}`
+      const value = get(i, 'value')
+      if (!value) continue;
+      sheet.getCell(pos).value = value
     }
-    const filename = `${match_name}初赛名单.xlsx`
+    const nowDate = new Date().getTime();
+    const filename = `${match_name}初赛名单-${nowDate}.xlsx`
     const path = this.path;
     if (!path) {
       throw new ServiceError('服务端没有设置存储路径');
     }
+    const filepath = Path.resolve(path, filename);
+    await workbook.xlsx.writeFile(filepath);
+    return `/files/cxyy/export/${filename}`;
   }
 }

+ 12 - 0
src/service/util.service.ts

@@ -1322,4 +1322,16 @@ export class UtilService {
     };
     return get(obj, name);
   }
+
+  ToExcelColumn(n) {
+    var ordA = 'A'.charCodeAt(0);
+    var ordZ = 'Z'.charCodeAt(0);
+    var len = ordZ - ordA + 1;
+    var s = "";
+    while (n >= 0) {
+      s = String.fromCharCode(n % len + ordA) + s;
+      n = Math.floor(n / len) - 1;
+    }
+    return s;
+}
 }