infoController.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. 'use strict';
  2. const Controller = require('egg').Controller;
  3. const ARCHIVER = require('archiver');
  4. const FS = require('fs');
  5. const path = require('path');
  6. const excelUtils = require('../util/excelUtils');
  7. class InfoController extends Controller {
  8. // 单查询
  9. async one() {
  10. const { ctx, service } = this;
  11. const query = ctx.query;
  12. const { id } = query;
  13. const result = await service.infoService.one(id);
  14. ctx.logic(result, '查询失败');
  15. }
  16. // 添加采集记录
  17. async add() {
  18. const { ctx, service } = this;
  19. const query = ctx.request.body;
  20. const user = ctx.user;
  21. query.userid = user._id;
  22. // query.userName = user.loginName;
  23. query.dept1 = user.dept1;
  24. query.dept2 = user.dept2;
  25. query.dept3 = user.dept3;
  26. query.dept4 = user.dept4;
  27. query.dept5 = user.dept5;
  28. if (!query.fid) {
  29. const familyResult = await service.familyService.add(query);
  30. query.fid = familyResult._id;
  31. }
  32. const infoResult = await service.infoService.add(query);
  33. ctx.success(infoResult);
  34. }
  35. // 修改采集记录
  36. async update() {
  37. const { ctx, service } = this;
  38. const query = ctx.request.body;
  39. const { id } = query;
  40. delete query.id;
  41. delete query.fid;
  42. const oneInfo = await this.ctx.service.infoService.one(id);
  43. // status == '2' 审核中 不允许进行修改
  44. // status == '3' 审核成功 状态不变,不允许修改为空
  45. if (oneInfo) {
  46. if (oneInfo.status !== '2') {
  47. if (oneInfo.status == '3') {
  48. const flag = await this.ctx.service.infoService.checkInfoUpdate(query);
  49. if (flag) {
  50. const result = await service.infoService.update(id, query);
  51. ctx.success(result);
  52. } else {
  53. ctx.error('审核成功,不允许修改为空', 333);
  54. }
  55. } else {
  56. const result = await service.infoService.update(id, query);
  57. ctx.success(result);
  58. }
  59. } else {
  60. ctx.error('审核中,不允许进行修改', 222);
  61. }
  62. } else {
  63. ctx.error('请求参数有误', 3333);
  64. }
  65. }
  66. // 删除采集记录,同时删除所在的户
  67. async delete() {
  68. const { ctx, service } = this;
  69. const query = ctx.query;
  70. const { id } = query;
  71. const info = await service.infoService.one(id);
  72. const fid = info.fid;
  73. const result = await service.infoService.dele(id);
  74. const family = await service.infoService.list({ fid });
  75. if (family.length === 0) {
  76. await service.familyService.delete(fid);
  77. }
  78. ctx.success(result);
  79. }
  80. // 不分页查询
  81. async list() {
  82. const { ctx, service } = this;
  83. const query = ctx.query;
  84. const result = await service.infoService.list(query);
  85. ctx.success(result);
  86. }
  87. // 分页查询
  88. async listForPage() {
  89. const { ctx, service } = this;
  90. const user = ctx.user;
  91. const level = user.dept.level;
  92. // 判断当前的dept权限 和传入的5级权限 不能超过当前人dept
  93. if (!ctx.query.dept1) {
  94. delete ctx.query.dept1;
  95. }
  96. if (!ctx.query.dept2) {
  97. delete ctx.query.dept2;
  98. }
  99. if (!ctx.query.dept3) {
  100. delete ctx.query.dept3;
  101. }
  102. if (!ctx.query.dept4) {
  103. delete ctx.query.dept4;
  104. }
  105. if (!ctx.query.dept5) {
  106. delete ctx.query.dept5;
  107. }
  108. delete ctx.query.deptId;
  109. // admin的dept 存在冲突,所以它不需要结合
  110. if (user.role._id != this.app.config.defaultAdminRoleId) {
  111. ctx.query['dept' + level] = user.dept._id;
  112. }
  113. // 判断如果当前是采集员看数据的话 只能看他自己
  114. if (user.role._id + '' == this.app.config.defaultUserRoleId) {
  115. ctx.query.cjname = user.loginName;
  116. }
  117. const result = await service.infoService.listForPage(ctx.query);
  118. ctx.success(result);
  119. }
  120. // 根据openId查询采集记录
  121. async listByOpenid() {
  122. const { ctx, service } = this;
  123. const query = ctx.query;
  124. const user = ctx.user;
  125. query.userid = user._id;
  126. const result = await this.ctx.service.infoService.list(query);
  127. ctx.success(result);
  128. }
  129. // 根据户Id查询采集记录
  130. async listByFid() {
  131. const { ctx, service } = this;
  132. const query = ctx.query;
  133. const result = await service.infoService.listByFid(query);
  134. ctx.success(result);
  135. }
  136. // 审批流程
  137. async approval() {
  138. const { ctx, service } = this;
  139. const { id } = ctx.query;
  140. delete ctx.query.id;
  141. const result = await service.infoService.approval(id, ctx.query);
  142. // ctx.logic(result, '没有审批权限');
  143. ctx.success(result);
  144. }
  145. // 二维码压缩包下载
  146. async allImage() {
  147. // console.log('allImage');
  148. const { ctx, service } = this;
  149. const query = ctx.query;
  150. const user = ctx.user;
  151. delete query.sessionId;
  152. if (user.dept5) {
  153. query.dept5 = user.dept5;
  154. } else if (user.dept4) {
  155. query.dept4 = user.dept4;
  156. }
  157. // 采集已完成并且审核成功才可以下载二维码
  158. query.status = '3';
  159. query.$or = [{ online: { $exists: false } }, { online: 'true' }];
  160. const result = await service.infoService.list(query);
  161. ctx.logger.info(query);
  162. // archiver可压缩为zip或tar格式,这里选择zip格式,注意这里新定义了一个变量archive,而不是原有的archiver包引用
  163. const archive = ARCHIVER('zip', {
  164. store: true,
  165. });
  166. archive.on('warning', function(err) {
  167. if (err.code === 'ENOENT') {
  168. ctx.logger.info(err.message);
  169. ctx.logger.info('stat故障和其他非阻塞错误');
  170. } else {
  171. ctx.logger.info(err.message);
  172. throw err;
  173. }
  174. });
  175. archive.on('error', function(err) {
  176. ctx.logger.info(err.message);
  177. throw err;
  178. });
  179. // 生成压缩包文件
  180. const zipName = Date.now() + '.zip';
  181. const zipPath = this.app.config.defaultUploadPath + zipName;
  182. const output = FS.createWriteStream(zipPath);
  183. // 文件输出流结束
  184. output.on('close', function() {
  185. ctx.logger.info(`总共 ${archive.pointer()} 字节`);
  186. ctx.logger.info('archiver完成文件的归档,文件输出流描述符已关闭');
  187. });
  188. // 数据源是否耗尽
  189. output.on('end', function() {
  190. ctx.logger.info('数据源已耗尽');
  191. });
  192. // 将压缩路径、包名与压缩格式连接
  193. archive.pipe(output);
  194. if (result.length <= 1000) {
  195. for (let index = 0; index < result.length; index++) {
  196. const element = result[index];
  197. const picName = path.basename('' + element.pic);
  198. // FS读取文件流,将读取的文件流append到压缩包中
  199. archive.append(FS.createReadStream(this.app.config.defaultUploadPath + picName), { name: 'scan' + picName });
  200. }
  201. }
  202. // 压缩结束
  203. await archive.finalize();
  204. // 下载文件
  205. ctx.set({
  206. 'Content-type': 'application/octet-stream',
  207. 'Content-Disposition': 'attachment;filename=' + encodeURI(zipName), // 定义文件名
  208. });
  209. ctx.body = FS.createReadStream(zipPath);
  210. }
  211. // 根据身份证号码查询采集记录
  212. async listByNumber() {
  213. const { ctx, service } = this;
  214. const query = ctx.query;
  215. const { number } = query;
  216. const result = await service.infoService.oneData({ idNumber: number });
  217. if (result) {
  218. ctx.error('身份证号码已存在');
  219. } else {
  220. ctx.success();
  221. }
  222. }
  223. // 修改离线状态
  224. // async updateOffLine() {
  225. // const { ctx, service } = this;
  226. // const query = ctx.query;
  227. // const { id, offLine } = query;
  228. // delete query.id;
  229. // if (id) {
  230. // const result = await service.infoService.updateOffLine(id, offLine);
  231. // ctx.success(result);
  232. // }
  233. // }
  234. // * 筛选----身份证重复录入
  235. async groupByNumber() {
  236. const { ctx, service } = this;
  237. const user = ctx.user;
  238. const level = user.dept.level;
  239. // 判断当前的dept权限 和传入的5级权限 不能超过当前人dept
  240. if (!ctx.query.dept1) {
  241. delete ctx.query.dept1;
  242. }
  243. if (!ctx.query.dept2) {
  244. delete ctx.query.dept2;
  245. }
  246. if (!ctx.query.dept3) {
  247. delete ctx.query.dept3;
  248. }
  249. if (!ctx.query.dept4) {
  250. delete ctx.query.dept4;
  251. }
  252. if (!ctx.query.dept5) {
  253. delete ctx.query.dept5;
  254. }
  255. delete ctx.query.deptId;
  256. // admin的dept 存在冲突,所以它不需要结合
  257. if (user.role._id != this.app.config.defaultAdminRoleId) {
  258. ctx.query['dept' + level] = user.dept._id;
  259. }
  260. const result = await service.infoService.groupByNumber(ctx.query);
  261. ctx.success(result);
  262. }
  263. // 导出Excel
  264. async exportExcelByInfo() {
  265. const { ctx, service } = this;
  266. const query = ctx.query;
  267. const user = ctx.user;
  268. const level = user.dept.level;
  269. delete query.sessionId;
  270. // // 判断当前的dept权限 和传入的5级权限 不能超过当前人dept
  271. // if (!ctx.query.dept1) {
  272. // delete ctx.query.dept1;
  273. // }
  274. // if (!ctx.query.dept2) {
  275. // delete ctx.query.dept2;
  276. // }
  277. // if (!ctx.query.dept3) {
  278. // delete ctx.query.dept3;
  279. // }
  280. // if (!ctx.query.dept4) {
  281. // delete ctx.query.dept4;
  282. // }
  283. // if (!ctx.query.dept5) {
  284. // delete ctx.query.dept5;
  285. // }
  286. // delete ctx.query.deptId;
  287. // 乡镇村级以上管理员
  288. if (level == '1' || level == '2' ) {
  289. ctx.logger.info('区及以上');
  290. if (!ctx.query.dept1 || !ctx.query.dept2 || !ctx.query.dept3 ) {
  291. delete ctx.query.dept1;
  292. delete ctx.query.dept2;
  293. delete ctx.query.dept3;
  294. this.ctx.error('请选择要导出的市、区乡镇村级地区');
  295. return;
  296. }
  297. } else {
  298. ctx.logger.info('区以下管理员');
  299. // 登录人的地区
  300. if (user.dept5) {
  301. query.dept5 = user.dept5;
  302. } else if (user.dept4) {
  303. query.dept4 = user.dept4;
  304. }else if (user.dept3) {
  305. query.dept3 = user.dept3;
  306. }
  307. }
  308. const begintime = new Date().getTime();
  309. ctx.logger.info("开始时间"+begintime);
  310. const result = await service.infoService.exportData(ctx.query);
  311. const endtime = new Date().getTime();
  312. ctx.logger.info("结束时间"+endtime);
  313. // if (result.length == 0) {
  314. // this.ctx.error('暂无数据', 200);
  315. // return;
  316. // }
  317. // if (result.length > 6 * 1000) {
  318. // this.ctx.error('数据量过大,请联系管理员导出', 500);
  319. // return;
  320. // }
  321. const config = [{
  322. sheetOptions: { pageSetup: { orientation: 'landscape', fitToHeight: true } },
  323. sheetHeader: [
  324. {
  325. headerName:
  326. '吉林省民政厅居家老年人巡视关爱探访系统采集信息',
  327. headerConfig: { height: 40 },
  328. },
  329. ],
  330. sheetKey: [
  331. { label: '序号', key: 'num', letter: 'A', width: 6 },
  332. { label: '姓名', key: 'name', letter: 'B', width: 10 },
  333. { label: '性别', key: 'sex', letter: 'C', width: 10 },
  334. { label: '民族', key: 'nation', letter: 'D', width: 10 },
  335. { label: '身份证号', key: 'idNumber', letter: 'E', width: 20 },
  336. { label: '户籍地址', key: 'nativePlace', letter: 'F', width: 40 },
  337. { label: '现居地址', key: 'address', letter: 'G', width: 40 },
  338. // { label: '年龄', key: 'birthday', letter: 'H', width: 20 },
  339. ],
  340. sheetData: result,
  341. }];
  342. const workbook = excelUtils.getExcel(config);
  343. if (!workbook) {
  344. this.ctx.error();
  345. return;
  346. }
  347. this.ctx.set('Content-Type', 'application/vnd.openxmlformats');
  348. this.ctx.set('Content-Disposition', "attachment;filename*=UTF-8' '" + encodeURIComponent(new Date().getTime()) + '.xlsx');
  349. this.ctx.body = await workbook.xlsx.writeBuffer();
  350. // const finalfilename = encodeURIComponent(new Date().getTime());
  351. // const path = this.app.config.defaultUploadPath + finalfilename + '.xlsx';
  352. // await workbook.xlsx.writeFile(path);
  353. // this.ctx.body = this.app.config.defaultUrl+this.app.config.defaultWritePathPre + finalfilename + '.xlsx'+new Date().getTime()+"生成文件时间"+
  354. // ";开始时间="+begintime+";结束时间="+endtime;
  355. }
  356. async exportExcelForPage() {
  357. const { ctx, service } = this;
  358. const query = ctx.query;
  359. const user = ctx.user;
  360. const level = user.dept.level;
  361. delete query.sessionId;
  362. // 判断当前的dept权限 和传入的5级权限 不能超过当前人dept
  363. if (!ctx.query.dept1) {
  364. delete ctx.query.dept1;
  365. }
  366. if (!ctx.query.dept2) {
  367. delete ctx.query.dept2;
  368. }
  369. if (!ctx.query.dept3) {
  370. delete ctx.query.dept3;
  371. }
  372. if (!ctx.query.dept4) {
  373. delete ctx.query.dept4;
  374. }
  375. if (!ctx.query.dept5) {
  376. delete ctx.query.dept5;
  377. }
  378. delete ctx.query.deptId;
  379. // admin的dept 存在冲突,所以它不需要结合
  380. if (user.role._id != this.app.config.defaultAdminRoleId) {
  381. ctx.query['dept' + level] = user.dept._id;
  382. }
  383. // 判断如果当前是采集员看数据的话 只能看他自己
  384. if (user.role._id + '' == this.app.config.defaultUserRoleId) {
  385. ctx.query.cjname = user.loginName;
  386. }
  387. // 登录人的地区
  388. // if (user.dept5) {
  389. // query.dept5 = user.dept5;
  390. // } else if (user.dept4) {
  391. // query.dept4 = user.dept4;
  392. // } else if (user.dept3) {
  393. // query.dept3 = user.dept3;
  394. // }
  395. const result = await service.infoService.exportData(ctx.query);
  396. if (result.length > 4 * 10000) {
  397. this.ctx.error('数据量过大,请联系管理员导出', 500);
  398. return;
  399. }
  400. // const config = [{
  401. // sheetOptions: { pageSetup: { orientation: 'landscape', fitToHeight: true } },
  402. // sheetHeader: [
  403. // {
  404. // headerName:
  405. // '吉林省民政厅居家老年人巡视关爱探访系统',
  406. // headerConfig: { height: 40 },
  407. // },
  408. // ],
  409. // sheetKey: [
  410. // { label: '序号', key: 'num', letter: 'A', width: 6 },
  411. // { label: '姓名', key: 'name', letter: 'B', width: 10 },
  412. // { label: '性别', key: 'sex', letter: 'C', width: 20 },
  413. // { label: '民族', key: 'nation', letter: 'D', width: 20 },
  414. // { label: '身份证号', key: 'idNumber', letter: 'E', width: 20 },
  415. // { label: '户籍地址', key: 'nativePlace', letter: 'F', width: 30 },
  416. // { label: '现居地址', key: 'address', letter: 'G', width: 30 },
  417. // // { label: '年龄', key: 'birthday', letter: 'H', width: 20 },
  418. // ],
  419. // sheetData: result,
  420. // }];
  421. // const workbook = excelUtils.getExcel(config);
  422. // if (!workbook) {
  423. // this.ctx.error();
  424. // return;
  425. // }
  426. // this.ctx.set('Content-Type', 'application/vnd.openxmlformats');
  427. // this.ctx.set('Content-Disposition', "attachment;filename*=UTF-8' '" + encodeURIComponent(new Date().getTime()) + '.xlsx');
  428. // this.ctx.body = await workbook.xlsx.writeBuffer();
  429. const archive = ARCHIVER('zip', {
  430. store: true,
  431. });
  432. archive.on('warning', function(err) {
  433. if (err.code === 'ENOENT') {
  434. ctx.logger.info(err.message);
  435. ctx.logger.info('stat故障和其他非阻塞错误');
  436. } else {
  437. ctx.logger.info(err.message);
  438. throw err;
  439. }
  440. });
  441. archive.on('error', function(err) {
  442. ctx.logger.info(err.message);
  443. throw err;
  444. });
  445. // 生成压缩包文件
  446. const zipName = Date.now() + '.zip';
  447. const zipPath = this.app.config.defaultUploadPath + zipName;
  448. const output = FS.createWriteStream(zipPath);
  449. // 文件输出流结束
  450. output.on('close', function() {
  451. ctx.logger.info(`总共 ${archive.pointer()} 字节`);
  452. ctx.logger.info('archiver完成文件的归档,文件输出流描述符已关闭');
  453. });
  454. // 数据源是否耗尽
  455. output.on('end', function() {
  456. ctx.logger.info('数据源已耗尽');
  457. });
  458. // 将压缩路径、包名与压缩格式连接
  459. archive.pipe(output);
  460. if (result.length > 1000) {
  461. const n = result.length / 1000 + 1;
  462. for (let i = 1; i < n; i++) {
  463. // const result = await model.InfoModel.find(where).populate(pop).skip((page - 1) * rows)
  464. // .limit(rows)
  465. // .sort({ time: -1 });
  466. ctx.query.page = i;
  467. ctx.query.row = 1000;
  468. const resultForPage = await service.infoService.listForPage(ctx.query);
  469. // const config = [{
  470. // sheetOptions: { pageSetup: { orientation: 'landscape', fitToHeight: true } },
  471. // sheetHeader: [
  472. // {
  473. // headerName:
  474. // '吉林省民政厅居家老年人巡视关爱探访系统',
  475. // headerConfig: { height: 40 },
  476. // },
  477. // ],
  478. // sheetKey: [
  479. // { label: '序号', key: 'num', letter: 'A', width: 6 },
  480. // { label: '姓名', key: 'name', letter: 'B', width: 10 },
  481. // { label: '性别', key: 'sex', letter: 'C', width: 20 },
  482. // { label: '民族', key: 'nation', letter: 'D', width: 20 },
  483. // { label: '身份证号', key: 'idNumber', letter: 'E', width: 20 },
  484. // { label: '户籍地址', key: 'nativePlace', letter: 'F', width: 30 },
  485. // { label: '现居地址', key: 'address', letter: 'G', width: 30 },
  486. // // { label: '年龄', key: 'birthday', letter: 'H', width: 20 },
  487. // ],
  488. // sheetData: result,
  489. // }];
  490. // const workbook = excelUtils.getExcel(config);
  491. // if (!workbook) {
  492. // this.ctx.error();
  493. // return;
  494. // }
  495. // archive.append('', { name: i });
  496. }
  497. // for (let index = 0; index < result.length; index++) {
  498. // const element = result[index];
  499. // const picName = path.basename('' + element.pic);
  500. // // FS读取文件流,将读取的文件流append到压缩包中
  501. // archive.append(FS.createReadStream(this.app.config.defaultUploadPath + picName), { name: 'scan' + picName });
  502. // }
  503. }
  504. // 压缩结束
  505. await archive.finalize();
  506. // 下载文件
  507. ctx.set({
  508. 'Content-type': 'application/octet-stream',
  509. 'Content-Disposition': 'attachment;filename=' + encodeURI(zipName), // 定义文件名
  510. });
  511. ctx.body = FS.createReadStream(zipPath);
  512. }
  513. // 根据户ID查询老人
  514. async visitByFid() {
  515. const { ctx, service } = this;
  516. const query = ctx.query;
  517. const { fid } = query;
  518. // delete query.fid;
  519. if (fid) {
  520. const result = await service.infoService.listByFid(query);
  521. // ctx.logger.error('visitIsExist', result);
  522. ctx.logic(result, ' ');
  523. } else {
  524. ctx.error('fid不存在');
  525. }
  526. }
  527. }
  528. module.exports = InfoController;