matchExt.controller.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. import { ApiTags, ApiQuery } from '@midwayjs/swagger';
  2. import { Validate } from '@midwayjs/validate';
  3. import { Controller, Inject, Get, Param, Post, Body, Del, Query } from '@midwayjs/core';
  4. import { cloneDeep, get, omit, pick } from 'lodash';
  5. import { ServiceError, ErrorCode } from '../../error/service.error';
  6. import { BaseController } from '../../frame/BaseController';
  7. import { MatchExtService } from '../../service/match/matchExt.service';
  8. import { MatchRegistrationService } from '../../service/match/matchRegistration.service';
  9. import { UserService } from '../../service/system/user.service';
  10. import { AliyunSmsService } from '../../service/thirdParty/aliyunSms.service';
  11. import { MatchService } from '../../service/platform/match.service';
  12. import dayjs = require('dayjs');
  13. const namePrefix = '创新大赛拓展';
  14. @ApiTags(['创新大赛拓展'])
  15. @Controller('/matchExt', { tagName: namePrefix })
  16. export class MatchExtController implements BaseController {
  17. @Inject()
  18. service: MatchExtService;
  19. @Inject()
  20. matchRegService: MatchRegistrationService;
  21. @Inject()
  22. userService: UserService;
  23. @Inject()
  24. smsService: AliyunSmsService;
  25. @Inject()
  26. matchService: MatchService;
  27. @Get('/')
  28. @ApiTags('列表查询')
  29. @ApiQuery({ name: 'query' })
  30. async index(@Query() query: object) {
  31. const qobj = omit(query, ['skip', 'limit']);
  32. const others: any = pick(query, ['skip', 'limit']);
  33. const result = await this.service.query(qobj, others);
  34. return result;
  35. }
  36. @Get('/:id')
  37. @ApiTags('单查询')
  38. async fetch(@Param('id') id: number) {
  39. const data = await this.service.fetch({ id });
  40. return data;
  41. }
  42. @Post('/', { routerName: `创建${namePrefix}` })
  43. @ApiTags('创建数据')
  44. @Validate()
  45. async create(@Body() data: object) {
  46. // 跟随赛事信息创建,不能直接创建
  47. return false;
  48. }
  49. @Post('/:id', { routerName: `修改${namePrefix}` })
  50. @ApiTags('修改数据')
  51. @Validate()
  52. async update(@Param('id') id: number, @Body() data: object) {
  53. if (!id) throw new ServiceError(ErrorCode.ID_NOT_FOUND);
  54. // 所有的修改,是不允许修改状态的
  55. const newData = omit(data, ['status']);
  56. const result = await this.service.update({ id }, newData);
  57. return result;
  58. }
  59. @Del('/:id', { routerName: `删除${namePrefix}` })
  60. @ApiTags('删除数据')
  61. @Validate()
  62. async delete(@Param('id') id: number) {
  63. if (!id) throw new ServiceError(ErrorCode.ID_NOT_FOUND);
  64. // 不允许删除非报名中的赛事
  65. const data = await this.service.fetch({ id });
  66. if (!data) return;
  67. const status = get(data, 'status');
  68. if (status !== '0') {
  69. // 抛出异常:赛事不处于报名中的状态,无法删除.
  70. throw new ServiceError(ErrorCode.MATCH_EXT_IS_BEGINNING);
  71. }
  72. const result = await this.service.delete({ id });
  73. return result;
  74. }
  75. @Get('/detail/:id')
  76. async detail(@Param('id') id: string) {
  77. const data = await this.service.fetch({ id });
  78. return data;
  79. }
  80. /**
  81. * 进入:报名阶段-已结束
  82. * @param data body
  83. * @property match_id 赛事id
  84. */
  85. @Post('/step1', { routerName: '报名阶段-已结束' })
  86. async step1(@Body() data: object) {
  87. //报名结束,需要检查 报名的创建接口是否允许创建信息----不允许再添加报名信息了
  88. /**
  89. * 检查内容:
  90. * 赛事拓展表:
  91. * ext.status = "0"
  92. * 赛事表:
  93. * match.status = "1"
  94. * 修改内容:
  95. * 赛事拓展表:
  96. * ext.status => "1" 变为 报名阶段-已结束
  97. * 赛事表:
  98. * match.status =>"2" 变为 进行中
  99. * 赛事报名表:
  100. * 处于 报名阶段(ext_status='0') 且 已通过审核的报名信息(status='1') 变为 初审阶段(ext_status='1')且未通过审核(status='0')的报名信息
  101. * reg.ext_status: "0" => "1"
  102. * reg.status: "1" => "0"
  103. */
  104. const match_id = get(data, 'match_id');
  105. await this.service.checkMatchStatus(match_id, '1');
  106. await this.service.checkMatchExtStatus(match_id, '0');
  107. await this.matchService.update({ id: match_id }, { match_status: '2' });
  108. await this.service.update({ match_id }, { status: '1' });
  109. await this.matchRegService.update({ match_id, ext_status: '0', status: '1' }, { ext_status: '1', status: '0' });
  110. return 'ok';
  111. }
  112. // 报名阶段-已结束 到 初审阶段-组织初审 过程只是变化状态码,不需要处理其他内容
  113. /**
  114. * 进入: 初审阶段-组织初审
  115. * @param data body
  116. * @property match_id 赛事id
  117. */
  118. @Post('/step2', { routerName: '初审阶段-组织初审' })
  119. async regBack(@Body() data: object) {
  120. // 只修改状态,不做时间修改,时间修改用另一个接口
  121. /**
  122. * 检查内容:
  123. * 赛事拓展表:
  124. * ext.status = "1"
  125. * 修改内容:
  126. * 赛事拓展表:
  127. * ext.status => "2" 变为 初审阶段-组织初审
  128. * 赛事报名表:
  129. * reg.ext_status: "1" => '2'
  130. */
  131. const match_id = get(data, 'match_id');
  132. await this.service.checkMatchExtStatus(match_id, '1');
  133. await this.service.update({ match_id }, { status: '2' });
  134. await this.matchRegService.update({ match_id, ext_status: '1' }, { ext_status: '2' });
  135. }
  136. /**
  137. * 初审阶段-组织初审 到 初审阶段-公示名单 需要修改 参加初审人员信息的 初审开始时间
  138. * @param data body
  139. * @property match_id 赛事id
  140. * @property start_time 初审时间
  141. * @property ids 报名数据id
  142. */
  143. @Post('/step2/fill', { routerName: '初审阶段-组织初审-补充初审时间信息' })
  144. async step2Fill(@Body() data: object) {
  145. /**
  146. * 检查内容:
  147. * 赛事拓展表:
  148. * ext.status = "2"
  149. * 修改内容:
  150. * 赛事报名表:
  151. * reg.ext_status: '2'
  152. * reg.start_time: => ${start_time}
  153. */
  154. const match_id = get(data, 'match_id');
  155. await this.service.checkMatchExtStatus(match_id, '2');
  156. const start_time = get(data, 'start_time');
  157. // 验证是否是正确的时间格式
  158. const is_time = dayjs(start_time).isValid();
  159. if (!is_time) {
  160. // 抛出异常: 时间格式错误
  161. throw new ServiceError(ErrorCode.TIME_FORMAT_ERROR);
  162. }
  163. // 获取报名信息数据id
  164. const ids = get(data, 'ids', []);
  165. for (const id of ids) {
  166. await this.matchRegService.update({ id: id, ext_status: '2', status: '0' }, { start_time });
  167. }
  168. }
  169. /**
  170. * 进入: 初审阶段-公示名单, 只修改状态即可
  171. * @param data body
  172. * @property match_id 赛事id
  173. */
  174. @Post('/step3', { routerName: '初审阶段-公示名单' })
  175. async step3(@Body() data: object) {
  176. /**
  177. * 检查内容:
  178. * 赛事拓展表:
  179. * ext.status = "2"
  180. * 修改内容:
  181. * 赛事拓展表:
  182. * ext.status => "3" 变为 初审阶段-公示名单
  183. * 赛事报名表:
  184. * reg.ext_status: "2" => '3'
  185. */
  186. const match_id = get(data, 'match_id');
  187. await this.service.checkMatchExtStatus(match_id, '2');
  188. await this.service.update({ match_id }, { status: '3' });
  189. await this.matchRegService.update({ match_id, ext_status: '2' }, { ext_status: '3' });
  190. }
  191. /**
  192. * 查询初审名单
  193. * @param match_id 赛事id
  194. */
  195. @Get('/step3/nameList/:match_id', { routerName: '初审阶段-公示名单-名单查询' })
  196. async step3NameList(@Param('match_id') match_id: string) {
  197. /**
  198. * 检查内容:
  199. * 赛事拓展表:
  200. * ext.status = "3"
  201. * 查询内容:
  202. * 赛事报名表:
  203. * reg.ext_status: "3";
  204. */
  205. await this.service.checkMatchExtStatus(match_id, '3');
  206. const { data } = await this.matchRegService.query({ match_id, ext_status: '3', status: '0' });
  207. const fillList = [];
  208. for (const i of data) {
  209. const newItem = cloneDeep(i);
  210. const user_id = get(i, 'user_id');
  211. const user = await this.userService.fetch({ id: user_id });
  212. if (user) newItem.user_name = get(user, 'nick_name');
  213. const match_id = get(i, 'match_id');
  214. const match = await this.matchService.fetch({ id: match_id });
  215. if (match) newItem.match_name = get(match, 'name');
  216. fillList.push(newItem);
  217. }
  218. return fillList;
  219. }
  220. /**
  221. * 进入: 初审阶段-赛事进行, 只修改状态即可
  222. * @param data body
  223. * @property match_id 赛事id
  224. */
  225. @Post('/step4', { routerName: '初审阶段-赛事进行' })
  226. async step4(@Body() data: object) {
  227. /**
  228. * 检查内容:
  229. * 赛事拓展表:
  230. * ext.status = "3"
  231. * 修改内容:
  232. * 赛事拓展表:
  233. * ext.status => "4" 变为 初审阶段-赛事进行
  234. * 赛事报名表:
  235. * reg.ext_status: "3" => '4'
  236. */
  237. const match_id = get(data, 'match_id');
  238. await this.service.checkMatchExtStatus(match_id, '3');
  239. await this.service.update({ match_id }, { status: '4' });
  240. await this.matchRegService.update({ match_id, ext_status: '3' }, { ext_status: '4' });
  241. }
  242. /**
  243. * 初审阶段-赛事进行-上传成绩, 只上传分数
  244. * @param match_id 赛事id
  245. * @property reg_id 选手id
  246. * @property status 是否通过; 1:通过初审;2未通过初审
  247. * @property score 分数
  248. */
  249. @Post('/step4/score/:match_id', { routerName: '初审阶段-赛事进行-上传成绩' })
  250. async step4Score(@Param('match_id') match_id: string, @Body() data: object) {
  251. /**
  252. * 检查内容:
  253. * 赛事拓展表:
  254. * ext.status = "4"
  255. * 修改内容:
  256. * 赛事报名表:
  257. * reg.ext_status: "4"
  258. * reg.status: '0'
  259. * reg.score = ${score}
  260. */
  261. await this.service.checkMatchExtStatus(match_id, '4');
  262. const reg_id = get(data, 'reg_id');
  263. // const status = get(data, 'status')
  264. const score = get(data, 'score');
  265. const query = { id: reg_id, ext_status: '4', status: '0' };
  266. const regData = await this.matchRegService.fetch(query);
  267. if (!regData) {
  268. // 抛出异常: 该选手不符合上传成绩的要求,请检查选手信息
  269. throw new ServiceError(ErrorCode.MATCH_REG_USER_ERROR);
  270. }
  271. await this.matchRegService.update({ id: reg_id }, { score });
  272. }
  273. /**
  274. * 决定决赛名单
  275. * @param match_id 赛事id
  276. * @param data body
  277. * @property ids 报名信息id
  278. */
  279. @Post('/step4/to5/:match_id', { routerName: '初审阶段-赛事进行-选择决赛名单' })
  280. async step4To5(@Param('match_id') match_id: string, @Body() data: object) {
  281. /**
  282. * 检查内容:
  283. * 赛事拓展表:
  284. * ext.status = "4"
  285. * 修改内容:
  286. * 赛事报名表:
  287. * reg.ext_status: "4"
  288. * reg.status: '0'
  289. * reg.status: '0' => '1'
  290. */
  291. await this.service.checkMatchExtStatus(match_id, '4');
  292. const ids = get(data, 'ids', []);
  293. for (const id of ids) {
  294. await this.matchRegService.update({ id: id, ext_status: '4', status: '0' }, { status: '1' });
  295. }
  296. }
  297. @Post('/step5', { routerName: '决赛阶段-组织决赛' })
  298. async step5(@Body() data: object) {
  299. /**
  300. * 检查内容:
  301. * 赛事拓展表:
  302. * ext.status = "4"
  303. * 修改内容:
  304. * 赛事拓展表:
  305. * ext.status => "5"
  306. * 赛事报名表:
  307. * reg.ext_status: "4"
  308. * reg.status: '1'
  309. * reg.status: '1' => '0'
  310. * reg.ext_status: '4' => '5'
  311. */
  312. const match_id = get(data, 'match_id');
  313. await this.service.checkMatchExtStatus(match_id, '4');
  314. await this.service.update({ match_id }, { status: '5' });
  315. await this.matchRegService.update({ match_id, ext_status: '4', status: '1' }, { status: '0', ext_status: '5' });
  316. }
  317. /**
  318. * 设置某些人决赛时间
  319. * @param match_id 赛事id
  320. * @param data body
  321. * @property ids 报名数据id列表
  322. * @property start_time 决赛开始时间
  323. */
  324. @Post('/step5/time/:match_id', { routerName: '决赛阶段-组织决赛-设置决赛时间' })
  325. async step5SetTime(@Param('match_id') match_id: string, @Body() data: object) {
  326. /**
  327. * 检查内容:
  328. * 赛事拓展表:
  329. * ext.status = "5"
  330. * 修改内容:
  331. * 赛事报名表:
  332. * reg.ext_status: "5"
  333. * reg.status: '0'
  334. * reg.final_start_time => ${start_time}
  335. */
  336. await this.service.checkMatchExtStatus(match_id, '5');
  337. const ids = get(data, 'ids', []);
  338. const start_time = get(data, 'start_time');
  339. for (const id of ids) {
  340. await this.matchRegService.update({ id, ext_status: '5', status: '0' }, { final_start_time: start_time });
  341. }
  342. return 'ok';
  343. }
  344. @Get('/step5/sms/:match_id', { routerName: '决赛阶段-组织决赛-短信通知' })
  345. async step5Sms(@Param('match_id') match_id: string, @Body() data: object) {
  346. /**
  347. * 检查内容:
  348. * 赛事拓展表:
  349. * ext.status = "5"
  350. * 组织内容:
  351. * 赛事报名表:
  352. * reg.ext_status:'5'
  353. * reg.status: '0'
  354. * reg.final_confirm:'1'
  355. * 1.获取赛事信息----标题
  356. * 2.获取赛事报名信息----每个人的决赛时间
  357. * 3.获取用户信息----昵称,电话
  358. * 4.组织短信: ${昵称} 您参加的赛事: ${标题} 将于 ${决赛时间} 开始,
  359. * 请您在网站或小程序中进行确认,以避免主办方将您误认为拒赛而采用其他选手代替
  360. */
  361. await this.service.checkMatchExtStatus(match_id, '5');
  362. const matchInfo = await this.matchService.fetch({ id: match_id });
  363. const match_name = get(matchInfo, 'name');
  364. const { data: extList } = await this.service.query({ match_id, ext_status: '5', status: '0', final_confirm: '1' });
  365. for (const i of extList) {
  366. const user_id = get(i, 'user_id');
  367. if (!user_id) continue;
  368. const userInfo = this.userService.fetch({ id: user_id });
  369. if (!userInfo) continue;
  370. const phone = get(userInfo, 'phone');
  371. if (!phone) continue;
  372. const nick_name = get(userInfo, 'nick_name');
  373. if (!nick_name) continue;
  374. const start_time = get(i, 'start_time');
  375. if (!start_time) continue;
  376. const smsMsg = `${nick_name} 您参加的赛事: ${match_name} 将于 ${start_time} 开始, 请您在网站或小程序中进行确认,以避免主办方将您误认为拒赛而采用其他选手代替`;
  377. // TODO: 发短信
  378. }
  379. }
  380. /**
  381. * 用户确认参加决赛
  382. * @param match_id 赛事id
  383. * @param data body
  384. * @property user_id 用户id
  385. */
  386. @Post('/step5/confirm/:match_id', { routerName: '决赛阶段-组织决赛-参加决赛确认' })
  387. async step5Confirm(@Param('match_id') match_id: string, @Body() data: object) {
  388. /**
  389. * 检查内容:
  390. * 赛事拓展表:
  391. * ext.status = "5"
  392. * 修改内容:
  393. * 赛事报名表:
  394. * reg.ext_status:'5'
  395. * reg.status: '0'
  396. * final_confirm => '0'
  397. */
  398. await this.service.checkMatchExtStatus(match_id, '5');
  399. const user_id = get(data, 'user_id');
  400. // 默认规定顺序,先来后到
  401. const { data: list } = await this.matchRegService.query({ match_id, ext_status: '5', status: '0', final_confirm: '0' });
  402. // 做默认序号,将已经确认的人查出来,然后排查序号,如果中间有缺少的序号,就先补充到缺少的序号中;如果没有缺少,那就往后默认排
  403. let lastOrderNum = 1;
  404. for (const i of list) {
  405. const thisOrderNum = get(i, 'final_order_no');
  406. // 按理说,不应该出现没有排序的情况
  407. if (!thisOrderNum) continue;
  408. // 顺序不一致,说明少了
  409. if (lastOrderNum !== thisOrderNum) {
  410. // 少了就需要把当前的补上.会出现2种情况, 正常顺序<当前顺序: 按正常顺序进行补充;
  411. // 正常顺序>当前顺序:说明从此开始,后面的序号都是乱的,是不应该出现的情况.如果出现了,就需要人为调整了.所以只考虑第一个情况
  412. break;
  413. }
  414. // 下一个,如果不循环了,那就直接给新数据用
  415. lastOrderNum = lastOrderNum + 1;
  416. }
  417. await this.matchRegService.update({ match_id, user_id, ext_status: '5', status: '0' }, { final_confirm: '0', final_order_no: lastOrderNum });
  418. }
  419. @Post('/step5/refuse/:match_id', { routerName: '决赛阶段-组织决赛-拒绝参加决赛' })
  420. async step5Refuse(@Param('match_id') match_id: string, @Body() data: object) {
  421. /**
  422. * 检查内容:
  423. * 赛事拓展表:
  424. * ext.status = "5"
  425. * 修改内容:
  426. * 赛事报名表:
  427. * reg.ext_status:'5'
  428. * reg.status: '0'
  429. * reg.status => '2'
  430. */
  431. await this.service.checkMatchExtStatus(match_id, '5');
  432. const user_id = get(data, 'user_id');
  433. await this.matchRegService.update({ match_id, user_id, ext_status: '5', status: '0' }, { status: '2' });
  434. }
  435. /**
  436. * 选择初赛中的选手 补充到决赛中
  437. * @param match_id 赛事id
  438. * @param data body
  439. * @property user_id 用户id
  440. */
  441. @Post('/step5/supplement/:match_id', { routerName: '决赛阶段-组织决赛-补充决赛人员' })
  442. async step5Supplement(@Param('match_id') match_id: string, @Body() data: object) {
  443. /**
  444. * 检查内容:
  445. * 赛事拓展表:
  446. * ext.status = "5"
  447. * 修改内容:
  448. * 赛事报名表:
  449. * reg.ext_status:'4'=>'5'
  450. * reg.status =>'0'
  451. */
  452. await this.service.checkMatchExtStatus(match_id, '5');
  453. const user_id = get(data, 'user_id');
  454. await this.matchRegService.update({ match_id, user_id, ext_status: '4' }, { ext_status: '5', status: '0' });
  455. }
  456. @Get('/step5/list/:match_id', { routerName: '决赛阶段-组织决赛-决赛人员名单' })
  457. async step5NameList(@Param('match_id') match_id: string) {
  458. /**
  459. * 检查内容:
  460. * 赛事拓展表:
  461. * ext.status = "5"
  462. * 组织内容:
  463. * 赛事报名表:
  464. * reg.ext_status:'5'
  465. * reg.final_confirm =>'0'
  466. */
  467. await this.service.checkMatchExtStatus(match_id, '5');
  468. // 决赛名单,根据顺序升序
  469. const { data: list } = await this.matchRegService.query({ match_id, ext_status: '5', final_confirm: '0' }, { order: { final_order_no: 'ASC' } });
  470. return list;
  471. }
  472. /**
  473. * 决赛人员排序
  474. * @param match_id 赛事id
  475. * @param data body
  476. * @property id 报名数据id
  477. * @property num 排名位置
  478. */
  479. @Post('/step5/order/:match_id', { routerName: '决赛阶段-组织决赛-人员排序' })
  480. async step5Order(@Param('match_id') match_id: string, @Body() data: object) {
  481. /**
  482. * 检查内容:
  483. * 赛事拓展表:
  484. * ext.status = "5"
  485. * 组织内容:
  486. * 赛事报名表:
  487. * reg.final_order_no =>'0'
  488. */
  489. await this.service.checkMatchExtStatus(match_id, '5');
  490. const { data: list } = await this.matchRegService.query({ match_id, ext_status: '5', final_confirm: '0' }, { order: { final_order_no: 'ASC' } });
  491. const id = get(data, 'id');
  492. if (!id) {
  493. // 抛出异常:缺少报名信息
  494. throw new ServiceError(ErrorCode.MATCH_EXT_DATA_NOT_FOUND);
  495. }
  496. const order_no = get(data, 'order_no');
  497. // 没写,直接不该
  498. if (!order_no) return 'ok';
  499. /**数据原索引 */
  500. const oldIndex = list.findIndex(f => f.id === id);
  501. // 没数据,不改
  502. if (oldIndex < 0) {
  503. throw new ServiceError(ErrorCode.MATCH_REG_NOT_FOUND);
  504. }
  505. const oldData = list[oldIndex];
  506. /**目标索引 */
  507. let targetIndex = order_no - 1;
  508. if (oldIndex === targetIndex) {
  509. throw new ServiceError(ErrorCode.MATCH_REG_ORDER_NOT_CHANGE);
  510. }
  511. let removeIndex = oldIndex;
  512. if (targetIndex < oldIndex) {
  513. // 如果要移动到的索引 小于 原数据索引: 是在原数据前添加的,影响删除,需要原索引+1才能删除原数据
  514. removeIndex = removeIndex + 1;
  515. } else {
  516. // 移动的索引要+1
  517. targetIndex = targetIndex + 1;
  518. }
  519. list.splice(targetIndex, 0, oldData);
  520. list.splice(removeIndex, 1);
  521. // 重新排列
  522. for (let index = 0; index < list.length; index++) {
  523. const e = list[index];
  524. const id = get(e, 'id');
  525. await this.matchRegService.update({ id }, { final_order_no: index + 1 });
  526. }
  527. }
  528. @Post('/step6', { routerName: '决赛阶段-名单公示' })
  529. async step6(@Body() data: object) {
  530. /**
  531. * 检查内容:
  532. * 赛事拓展表:
  533. * ext.status = "5"
  534. * 修改内容:
  535. * 赛事拓展表:
  536. * ext.status => "6" 变为 决赛阶段-名单公示
  537. * 赛事报名表:
  538. * reg.final_confirm:'0'
  539. * reg.ext_status: "5" => '6'
  540. */
  541. const match_id = get(data, 'match_id');
  542. await this.service.checkMatchExtStatus(match_id, '5');
  543. await this.service.update({ match_id }, { status: '6' });
  544. await this.matchRegService.update({ match_id, ext_status: '5', final_confirm: '0' }, { ext_status: '6' });
  545. }
  546. @Post('/step7', { routerName: '决赛阶段-赛事进行' })
  547. async step7(@Body() data: object) {
  548. /**
  549. * 检查内容:
  550. * 赛事拓展表:
  551. * ext.status = "6"
  552. * 修改内容:
  553. * 赛事拓展表:
  554. * ext.status => "7" 变为 决赛阶段-赛事进行
  555. * 赛事报名表:
  556. * reg.final_confirm:'0'
  557. * reg.ext_status: "6" => '7'
  558. */
  559. const match_id = get(data, 'match_id');
  560. await this.service.checkMatchExtStatus(match_id, '6');
  561. await this.service.update({ match_id }, { status: '7' });
  562. await this.matchRegService.update({ match_id, ext_status: '6', final_confirm: '0' }, { ext_status: '7' });
  563. }
  564. // TODO:决赛大屏,评委打分
  565. @Post('/step8', { routerName: '决赛阶段-赛事结束' })
  566. async step8(@Body() data: object) {
  567. /**
  568. * 检查内容:
  569. * 赛事拓展表:
  570. * ext.status = "7"
  571. * 修改内容:
  572. * 赛事拓展表:
  573. * ext.status => "8" 变为 决赛阶段-赛事进行
  574. * 赛事报名表:
  575. * reg.ext_status: "7" => '8'
  576. */
  577. const match_id = get(data, 'match_id')
  578. await this.service.checkMatchExtStatus(match_id, "7")
  579. await this.service.update({ match_id }, { status: '8' })
  580. await this.matchRegService.update({ match_id, ext_status: '7', final_confirm: '0' }, { ext_status: '8' })
  581. }
  582. @Get('/firstStep/:match_id', { routerName: '进入初审阶段' })
  583. async toFirstStep(@Param('match_id') match_id: string, @Body() data: object) {
  584. // 进入初审阶段,查询选手名单(未被退回的),根据选手名单的报名顺序,排列名单,并赋予开始时间
  585. /**赛事拓展数据 */
  586. const extData = await this.service.fetch({ match_id });
  587. if (extData) {
  588. const nowStatus = get(extData, 'status');
  589. // 如果状态不是 '0', 说明状态不对,
  590. // if (nowStatus !== '0') throw new ServiceError(ErrorCode.MATCH_EXT_STATUS_ERROR)
  591. // 修改流程进度为下一步----初审
  592. await this.service.update({ match_id }, { status: '1' });
  593. }
  594. const start_time = get(data, 'start_time');
  595. const regQuery = { match_id, status: '0' };
  596. await this.matchRegService.update(regQuery, { start_time });
  597. /**赛事报名数据 */
  598. const { data: list } = await this.matchRegService.query(regQuery);
  599. // 获取赛事名称
  600. const matchData = await this.matchService.fetch({ id: match_id });
  601. // 发送短信通知
  602. const msg = `您参加的赛事: ${get(matchData, 'name')} 将于 ${start_time}开始初审,具体安排请通过网页或小程序查看.请您提前做好准备.`;
  603. for (const i of list) {
  604. const user_id = get(i, 'user_id');
  605. if (!user_id) continue;
  606. const ups = await this.service.getUserProps(user_id, ['phone']);
  607. const phone = get(ups, 'phone');
  608. try {
  609. await this.smsService.send(phone, msg);
  610. } catch (error) {
  611. console.error('matchExt - toFirstStep:发送短信发生错误');
  612. }
  613. }
  614. }
  615. @Post('/secondStep/:match_id', { routerName: '进入决赛准备阶段' })
  616. async toSecondStep(@Param('match_id') match_id: string, @Body() data: object) {
  617. // 进入决赛准备阶段,获取前端传来的人数,保存在拓展表里.
  618. const extData = await this.service.fetch({ match_id });
  619. const final_persons = get(data, 'final_persons');
  620. // TODO: 抛出异常,缺少进入决赛人数设置
  621. // if (!final_persons) throw new ServiceError(ErrorCode.MATCH_EXT_NO_FINAL_PERSON)
  622. if (extData) {
  623. const nowStatus = get(extData, 'status');
  624. // 如果状态不是 '1', 说明状态不对,
  625. // TODO:抛出异常 赛事状态错误
  626. // if (nowStatus !== '1') throw new ServiceError(ErrorCode.MATCH_EXT_STATUS_ERROR)
  627. // 修改流程进度为下一步----决赛准备阶段
  628. await this.service.update({ match_id }, { status: '2', final_persons });
  629. }
  630. // 根据进入决赛的人数,查询列表; 初审分数在走这个接口前就需要上完.
  631. const query = { match_id };
  632. const others = { skip: 0, limit: final_persons, others: { score: 'DESC' } };
  633. const { data: list } = await this.matchRegService.query(query, others);
  634. // 获取赛事名称
  635. const matchData = await this.matchService.fetch({ id: match_id });
  636. const match_name = get(matchData, 'name');
  637. const msg = `您在赛事: ${match_name}中已进入决赛,请通过网站或小程序进入平台进行信息确认.`;
  638. const lastList = [];
  639. for (const i of list) {
  640. const user_id = get(i, 'user_id');
  641. if (!user_id) continue;
  642. // 发短信通知去确认
  643. const ups = await this.service.getUserProps(user_id, ['phone']);
  644. const phone = get(ups, 'phone');
  645. try {
  646. await this.smsService.send(phone, msg);
  647. } catch (error) {
  648. console.error('matchExt - toSecondStep:发送短信发生错误');
  649. }
  650. }
  651. }
  652. }