visitService.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. 'use strict';
  2. const Service = require('../service/baseService');
  3. const request = require('request');
  4. const fs = require('fs');
  5. const path = require('path');
  6. const sm4 = require('../util/sm4').sma4;
  7. class VisitService extends Service {
  8. tag() {
  9. return this.ctx.model.VisitModel;
  10. }
  11. // baidu-base64编码
  12. async getResult(data) {
  13. if (data.photoPath && data.visitPhotoPath && data.accessToken) {
  14. // 读取待识别图像并base64编码
  15. const infoPicName = path.basename('' + data.photoPath);// 该用户的采集图片的文件名 xxx.jpg
  16. const visitPicName = path.basename('' + data.visitPhotoPath);// 该用户的探访图片的文件名 xxx.jpg
  17. // const infoPicPath = this.app.config.defaultUploadPath + infoPicName; // 采集文件路径;
  18. const infoPicPath = infoPicName; // 采集文件路径;
  19. // const visitPicPath = this.app.config.defaultUploadPath + visitPicName; // 探访文件路径
  20. const visitPicPath = visitPicName; // 探访文件路径
  21. const infoData = fs.readFileSync(infoPicPath); // 例:fileUrl="D:\\test\\test.bmp"
  22. const visitData = fs.readFileSync(visitPicPath); // 例:fileUrl="D:\\test\\test.bmp"
  23. const infoBase64 = infoData.toString('base64');
  24. const visitBase64 = visitData.toString('base64');
  25. const jsonData = [
  26. {
  27. image: infoBase64,
  28. image_type: 'BASE64',
  29. },
  30. {
  31. image: visitBase64,
  32. image_type: 'BASE64',
  33. },
  34. ];
  35. const url = 'https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=' + data.accessToken; // 正式
  36. const res = await this.ctx.curl(url, {
  37. method: 'POST',
  38. headers: {
  39. accept: 'application/json',
  40. 'Content-Type': 'application/x-www-form-urlencoded' },
  41. contentType: 'json',
  42. data: JSON.stringify(jsonData),
  43. dataType: 'json',
  44. });
  45. this.ctx.logger.info('对比结果==========>', res);
  46. if (res.status == '200') {
  47. return res.data;
  48. }
  49. return '';
  50. }
  51. }
  52. // baidu-url
  53. async getResult2(data) {
  54. // this.ctx.logger.info('Service==data=======================>' + JSON.stringify(data));
  55. if (data.photoPath && data.visitPhotoPath && data.accessToken) {
  56. const infoPicUrl = this.app.config.defaultUrlDoFace + data.photoPath.replaceAll('/', '$'); // 采集文件路径;
  57. const visitPicUrl = this.app.config.defaultUrlDoFace + data.visitPhotoPath.replaceAll('/', '$'); // 采集文件路径;
  58. const jsonData = [
  59. {
  60. // image: 'https://bucketnj1-1254259530.cos.ap-nanjing.myqcloud.com/face/tmp_0c7c2dcde7374488f97228d2134d48950d150d9f6d5d492c.jpg',
  61. image: infoPicUrl,
  62. image_type: 'URL',
  63. liveness_control: 'NORMAL',
  64. },
  65. {
  66. // image: 'https://bucketnj1-1254259530.cos.ap-nanjing.myqcloud.com/face/tmp_0c7c2dcde7374488f97228d2134d48950d150d9f6d5d492c.jpg',
  67. image: visitPicUrl,
  68. image_type: 'URL',
  69. liveness_control: 'NORMAL',
  70. },
  71. ];
  72. const options1 = {
  73. url: 'https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=' + data.accessToken,
  74. method: 'POST',
  75. body: JSON.stringify(jsonData),
  76. headers: {
  77. accept: 'application/json',
  78. 'content-type': 'application/x-www-form-urlencoded',
  79. },
  80. };
  81. const result = await this.getFace(options1);
  82. return JSON.parse(result);
  83. }
  84. }
  85. async getPeopleFace(data) {
  86. // this.ctx.logger.info('Service==data=======================>' + JSON.stringify(data));
  87. if (data.photoPath && data.accessToken) {
  88. const photoPath = this.app.config.defaultUrl + data.photoPath; // 采集文件路径;
  89. const jsonData =
  90. {
  91. // image: 'https://bucketnj1-1254259530.cos.ap-nanjing.myqcloud.com/face/tmp_0c7c2dcde7374488f97228d2134d48950d150d9f6d5d492c.jpg',
  92. image: photoPath,
  93. image_type: 'URL',
  94. // liveness_control: 'HIGH',
  95. liveness_control: 'NORMAL',
  96. // liveness_control: 'LOW',
  97. };
  98. const options1 = {
  99. url: 'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=' + data.accessToken,
  100. method: 'POST',
  101. body: JSON.stringify(jsonData),
  102. headers: {
  103. accept: 'application/json',
  104. 'content-type': 'application/x-www-form-urlencoded',
  105. },
  106. };
  107. const result = await this.getFace(options1);
  108. return JSON.parse(result);
  109. }
  110. }
  111. async getPeopleFaceByBase64(data) {
  112. if (data.photoBase64 && data.accessToken) {
  113. // const photoBase64 = this.app.config.defaultUrl + data.photoPath; // 采集文件路径;
  114. // const infoPicUrl = this.app.config.defaultUrlDoFace + data.photoPath.replaceAll('/', '$'); // 采集文件路径;
  115. const jsonData =
  116. {
  117. image: data.photoBase64,
  118. image_type: 'BASE64',
  119. liveness_control: 'NORMAL',
  120. };
  121. const options1 = {
  122. url: 'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=' + data.accessToken,
  123. method: 'POST',
  124. body: JSON.stringify(jsonData),
  125. headers: {
  126. accept: 'application/json',
  127. 'content-type': 'application/x-www-form-urlencoded',
  128. },
  129. };
  130. const result = await this.getFace(options1);
  131. return JSON.parse(result);
  132. }
  133. }
  134. async getFace(option) {
  135. return new Promise((resolve, reject) => {
  136. request(option, function(error, response, body) {
  137. if (!error) {
  138. if (response.statusCode == 200) {
  139. resolve(body);
  140. } else {
  141. resolve(body);
  142. }
  143. } else {
  144. reject(error);
  145. }
  146. });
  147. });
  148. }
  149. async bing(query) {
  150. const { ctx, service } = this;
  151. const { fid, openId } = query;
  152. const result = await service.familyService.oneData({ _id: this.app.mongoose.Types.ObjectId(fid) });
  153. // ctx.logger.error('service==========', result);
  154. if (result) {
  155. let openIdArray = [];
  156. if (result.openId) {
  157. openIdArray = result.openId;
  158. // openId已绑定
  159. if (openIdArray.indexOf(openId) == -1) {
  160. openIdArray.push(openId);
  161. } else {
  162. ctx.error('openId已绑定');
  163. }
  164. } else {
  165. openIdArray.push(openId);
  166. }
  167. await service.familyService.update(result._id, { openId: openIdArray });
  168. return null;
  169. }
  170. return '该户不存在,请联系管理员!';
  171. }
  172. // 根据身份证查询
  173. async visitByNumber(data) {
  174. const { model } = this.ctx;
  175. return await model.VisitModel.find(data).sort({ visitTime: -1 }).limit(15);
  176. }
  177. // 导出探访数据
  178. async visitExportData(data) {
  179. const { model } = this.ctx;
  180. const where = {};
  181. if (data.dept1) {
  182. where.dept1 = data.dept1;// 省
  183. }
  184. if (data.dept2) {
  185. where.dept2 = data.dept2; // 市
  186. }
  187. if (data.dept3) {
  188. where.dept3 = data.dept3; // 区
  189. }
  190. if (data.dept4) {
  191. where.dept4 = data.dept4; // 乡
  192. }
  193. if (data.dept5) {
  194. where.dept5 = data.dept5; // 社区
  195. }
  196. const queryName = data.queryName;
  197. delete data.queryName;
  198. if (queryName) {
  199. const userInfo = await this.ctx.model.SysUserModel.find({ loginName: { $regex: queryName } });
  200. if (userInfo.length > 0) {
  201. where.userid = userInfo[0]._id;
  202. }
  203. }
  204. // 老人姓名
  205. if (data.oldName) {
  206. // where.oldInfo = { $regex: data.oldName };
  207. where.oldInfo = sm4.encrypt_ECB(data.oldName); // TODO 数据加密处理-CH
  208. }
  209. // 时间
  210. if (data.startTime && data.endTime) {
  211. where.visitTime = { $gte: new Date(data.startTime + ' 00:00:00'), $lt: new Date(data.endTime + ' 23:59:59') };
  212. }
  213. if (data.eightType && data.eightType != '') {
  214. if (data.eightType === '1') {
  215. where.$or = [
  216. {
  217. infoOldType: '空巢老年人',
  218. },
  219. {
  220. infoOldType: '重残老人',
  221. },
  222. {
  223. infoOldType: '独居老年人',
  224. },
  225. {
  226. infoOldType: '计划生育特殊家庭老人',
  227. },
  228. {
  229. infoOldType: '重残老年人',
  230. },
  231. {
  232. infoOldType: '失能',
  233. },
  234. {
  235. infoOldType: '农村留守老年人',
  236. },
  237. {
  238. infoOldType: '分散供养特困老年人',
  239. },
  240. {
  241. infoOldType: '高龄老人',
  242. },
  243. {
  244. infoOldAbility: '失能',
  245. },
  246. ];
  247. } else if (data.eightType === '0') {
  248. where.$and = [{ infoOldType: '居家老年人' }, { infoOldType: { $size: 1 } }];
  249. where.$or = [
  250. {
  251. infoOldAbility: '完全自理',
  252. },
  253. {
  254. infoOldAbility: '半失能(部分自理)',
  255. },
  256. {
  257. infoOldAbility: '半失能(部分自理)',
  258. },
  259. ];
  260. }
  261. }
  262. this.ctx.logger.info('条件', where);
  263. const pop = [
  264. {
  265. path: 'userid',
  266. select: 'loginName',
  267. },
  268. ];
  269. const result = await model.VisitModel.find(where, { dept1: 1, dept2: 1, dept3: 1, dept4: 1, dept5: 1, visitTime: 1, visitLocation: 1, oldInfo: 1, oldIdNumber: 1,
  270. health: 1, mind: 1, security: 1, hygiene: 1, live: 1, urgency: 1,
  271. demand: 1, visitMessage: 1, userid: 1 }).populate(pop);
  272. return result;
  273. }
  274. // pc端首页近七天探访数据统计
  275. async sevendayNum(data, user) {
  276. const { model } = this.ctx;
  277. const level = user.dept.level;
  278. const match = {};
  279. match.time = { $gte: data.startday };
  280. // admin的dept 存在冲突,所以它不需要结合
  281. if (user.role._id != this.app.config.defaultAdminRoleId) {
  282. match['dept' + level] = user.dept._id;
  283. }
  284. const res = await model.VisitModel.aggregate([
  285. { $project: { time: { $dateToString: { format: '%Y-%m-%d', date: '$visitTime' } }, _id: 1, dept1: 1, dept2: 1, dept3: 1, dept4: 1, dept5: 1 } },
  286. { $match: match },
  287. { $group: { _id: '$time', value: { $sum: 1 } } },
  288. { $project: { label: '$_id', value: 1, _id: 0 } },
  289. { $sort: { label: 1 } },
  290. ]);
  291. this.ctx.logger.info(data);
  292. const morenArr = [];
  293. for (let i = 0; i < 7; i++) {
  294. const yestday = new Date();
  295. yestday.setTime(yestday.getTime() - 24 * 60 * 60 * 1000 * (6 - i));
  296. let month = yestday.getMonth() + 1;
  297. if (month < 10) month = '0' + month;
  298. let day = yestday.getDate();
  299. if (day < 10) day = '0' + day;
  300. const ysday = yestday.getFullYear() + '-' + month + '-' + day;
  301. const vote = {};
  302. vote.label = ysday;
  303. vote.value = 0;
  304. morenArr.push(vote);
  305. }
  306. if (res.length > 0) {
  307. for (let j = 0; j < morenArr.length; j++) {
  308. const mlabel = morenArr[j].label;
  309. for (let k = 0; k < res.length; k++) {
  310. const clabel = res[k].label;
  311. if (mlabel == clabel) {
  312. morenArr[j].value = res[k].value;
  313. }
  314. }
  315. }
  316. }
  317. return morenArr;
  318. }
  319. async listForPageWithDept(data, pop) {
  320. const page = data.page || 1;
  321. const rows = Number.parseInt(data.rows)
  322. || this.app.config.defaultPageSize;
  323. const sort = data.sort;
  324. delete data.page;
  325. delete data.rows;
  326. delete data.sort;
  327. const eightType = data.eightType;
  328. if (eightType !== '') {
  329. if (eightType === '1') {
  330. data.$or = [
  331. {
  332. infoOldType: '空巢老年人',
  333. },
  334. {
  335. infoOldType: '重残老人',
  336. },
  337. {
  338. infoOldType: '独居老年人',
  339. },
  340. {
  341. infoOldType: '计划生育特殊家庭老人',
  342. },
  343. {
  344. infoOldType: '重残老年人',
  345. },
  346. {
  347. infoOldType: '失能',
  348. },
  349. {
  350. infoOldType: '农村留守老年人',
  351. },
  352. {
  353. infoOldType: '分散供养特困老年人',
  354. },
  355. {
  356. infoOldType: '高龄老人',
  357. },
  358. {
  359. infoOldAbility: '失能',
  360. },
  361. ];
  362. } else if (eightType === '0') {
  363. data.$and = [{ infoOldType: '居家老年人' }, { infoOldType: { $size: 1 } }];
  364. data.$or = [
  365. {
  366. infoOldAbility: '完全自理',
  367. },
  368. {
  369. infoOldAbility: '半失能(部分自理)',
  370. },
  371. {
  372. infoOldAbility: '半失能(部分自理)',
  373. },
  374. ];
  375. }
  376. }
  377. delete data.eightType;
  378. // 老人类别
  379. if (data.infoOldType) {
  380. const ts = data.infoOldType.split(',');
  381. data.infoOldType = { $in: ts };
  382. } else {
  383. delete data.infoOldType;
  384. }
  385. if (pop) {
  386. const total = await this.tag().find(data).countDocuments();
  387. let userTotal = await this.tag().aggregate([
  388. { $match: data },
  389. { $group: { _id: { userid: '$userid' } } }, { $count: 'total' },
  390. ]);
  391. let oldPersonTotal = await this.tag().aggregate([
  392. { $match: data },
  393. { $group: { _id: { infoId: '$infoId' } } }, { $count: 'total' }]);
  394. const result = (sort ? await this.tag().find(data).populate(pop)
  395. .sort(sort)
  396. .skip((page - 1) * rows)
  397. .limit(rows)
  398. : await this.tag().find(data).populate(pop)
  399. .skip((page - 1) * rows)
  400. .limit(rows));
  401. result.forEach(item => {
  402. let str = '';
  403. if (item.fwxq_rzylyxq === '1') str += '入住养老院需求 ';
  404. if (item.fwxq_zyfw === '1') str += '助医服务 ';
  405. if (item.fwxq_zxfw === '1') str += '助行服务 ';
  406. if (item.fwxq_zjfw === '1') str += '助洁服务 ';
  407. if (item.fwxq_zcfw === '1') str += '助餐服务 ';
  408. if (item.fwxq_xzfw === '1') str += '洗澡服务 ';
  409. if (item.fwxq_kffw === '1') str += '康复服务 ';
  410. if (item.fwxq_jtcw === '1') str += '家庭床位 ';
  411. if (item.fwxq_rzsqyljgxq === '1') str += '入住社区养老院需求 ';
  412. if (item.fwxq_jkjcxq === '1') str += '健康检查需求 ';
  413. if (item.fwxq_qtfwxq === '1') str += '其他服务需求 ';
  414. if (item.demand == null) {
  415. if (str.length === 0) {
  416. str = '无';
  417. }
  418. item.demand = str;
  419. }
  420. });
  421. if (userTotal[0] !== undefined) {
  422. userTotal = userTotal[0].total;
  423. } else {
  424. userTotal = 0;
  425. }
  426. if (oldPersonTotal[0] !== undefined) {
  427. oldPersonTotal = oldPersonTotal[0].total;
  428. } else {
  429. oldPersonTotal = 0;
  430. }
  431. return {
  432. count: total, // 共计X次
  433. // 这俩有问题,带地区显示为0
  434. userCount: userTotal, // 位巡访员
  435. oldPersonCount: oldPersonTotal, // 巡访X位老年人
  436. list: result, // 数据列表
  437. };
  438. }
  439. }
  440. }
  441. module.exports = VisitService;