|
@@ -0,0 +1,292 @@
|
|
|
+'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');
|
|
|
+const axios = require('axios');
|
|
|
+const crypto = require('crypto');
|
|
|
+
|
|
|
+class CardService extends CrudService {
|
|
|
+ constructor(ctx) {
|
|
|
+ super(ctx, 'card');
|
|
|
+ this.model = this.ctx.model.Position;
|
|
|
+ this.cardCacheModel = this.ctx.model.CardCache;
|
|
|
+ this.cardAdminModel = this.ctx.model.CardAdmin;
|
|
|
+ this.tp = this.ctx.service.transformPosition;
|
|
|
+ this.dbConfig = this.app.config.dbServer;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 定时任务执行函数,login是在应用加载完成时开始的.
|
|
|
+ * 登陆过期时间是12h,请求更新token时间,所以应该不用担心会有token过期问题
|
|
|
+ */
|
|
|
+ async loop() {
|
|
|
+
|
|
|
+ const { ip, port } = this.dbConfig;
|
|
|
+ const query = [
|
|
|
+ { key: 'is_class', value: '在岗', type: 'like' },
|
|
|
+ { key: 'work_card', type: 'exists' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const res = await axios({
|
|
|
+ method: 'post',
|
|
|
+ url: `http://${ip}:${port}/db/query?table=security_guard_base`,
|
|
|
+ data: query,
|
|
|
+ responseType: 'json',
|
|
|
+ });
|
|
|
+ const data = this.selfRequestDeal(res);
|
|
|
+
|
|
|
+ const isWorkingList = data.list;
|
|
|
+
|
|
|
+ for (const worker of isWorkingList) {
|
|
|
+ this.dealPosition(worker);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 组织每个保安员的定位信息 及 信息保存
|
|
|
+ * @param {Object} worker 符合条件的保安员基础信息(security_guard_base)
|
|
|
+ */
|
|
|
+ async dealPosition(worker) {
|
|
|
+ if (!worker) return;
|
|
|
+ let positionData = {};
|
|
|
+ const { id, work_card } = worker;
|
|
|
+ positionData = _.pick(worker, [ 'name', 'card', 'is_class' ]);
|
|
|
+ positionData.user_id = id;
|
|
|
+
|
|
|
+ const cbw = await this.getBaoanWork(id);
|
|
|
+ if (cbw) {
|
|
|
+ positionData.company_name = _.get(cbw, 'company_name');
|
|
|
+ positionData.company_id = _.get(cbw, 'company_id');
|
|
|
+ }
|
|
|
+
|
|
|
+ const dispatch = await this.getBaoanDispatch(id);
|
|
|
+ if (dispatch) {
|
|
|
+ positionData.company_service_object_id = _.get(dispatch, 'service_target_id');
|
|
|
+ positionData.company_service_object_name = _.get(dispatch, 'service_target');
|
|
|
+ }
|
|
|
+
|
|
|
+ const position = await this.getPosition(work_card);
|
|
|
+ if (position) {
|
|
|
+ const { latitude, longitude, ...info } = position;
|
|
|
+ positionData = { ...positionData, latitude, longitude, info };
|
|
|
+ this.model.create(positionData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取该工牌实时定位信息
|
|
|
+ * @param {String} vid 工牌id
|
|
|
+ */
|
|
|
+ async getPosition(vid) {
|
|
|
+ if (!vid) return;
|
|
|
+ let vObj = await this.getAuthorizeCode(vid);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (vObj) {
|
|
|
+ const position = await this.toGetPosition(vObj.vKey, vObj.vid);
|
|
|
+ if (position) return position;
|
|
|
+ }
|
|
|
+ vObj = null;
|
|
|
+
|
|
|
+ vObj = await this.getAuthorizeCode(vid, false);
|
|
|
+ if (vObj) {
|
|
|
+ const position = await this.toGetPosition(vObj.vKey, vObj.vid);
|
|
|
+ if (position) return position;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 请求车辆最新信息并处理
|
|
|
+ * @param {String} vKey 工牌授权码
|
|
|
+ * @param {String} vid 工牌id
|
|
|
+ */
|
|
|
+ async toGetPosition(vKey, vid) {
|
|
|
+
|
|
|
+ const method = 'loadLocation';
|
|
|
+ const data = await this.toRequest(method, { vid, vKey });
|
|
|
+ const position = this.getPositionFromData(data);
|
|
|
+ if (position) {
|
|
|
+ const obj = { info: {} };
|
|
|
+ if (_.get(position, 'lat')) obj.latitude = _.get(position, 'lat');
|
|
|
+ if (_.get(position, 'lng')) obj.longitude = _.get(position, 'lng');
|
|
|
+ if (obj.latitude && obj.longitude) {
|
|
|
+ const [ latitude, longitude ] = this.tp.transform(obj.latitude, obj.longitude);
|
|
|
+ if (latitude && longitude) {
|
|
|
+ obj.latitude = latitude;
|
|
|
+ obj.longitude = longitude;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_.get(position, 'info')) obj.info = _.get(position, 'info');
|
|
|
+ if (_.get(position, 'state')) obj.state = _.get(position, 'state');
|
|
|
+ if (_.get(position, 'speed')) obj.speed = _.get(position, 'speed');
|
|
|
+ if (_.get(position, 'direct')) obj.direct = _.get(position, 'direct');
|
|
|
+ if (_.get(position, 'vhcofflinemin')) obj.vhcofflinemin = _.get(position, 'vhcofflinemin');
|
|
|
+ if (Object.keys(obj).length > 0) return obj;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 处理最新定位信息接口返回结果
|
|
|
+ * @param {Object} data 请求最新定位信息接口返回结果
|
|
|
+ */
|
|
|
+ getPositionFromData(data) {
|
|
|
+ if (data) {
|
|
|
+ const { locs } = data;
|
|
|
+ if (locs && _.isArray(locs)) {
|
|
|
+ const l = _.head(locs);
|
|
|
+ if (l) return l;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取工牌授权码
|
|
|
+ * @param {String} work_card 工牌id
|
|
|
+ * @param {Boolean} useCache 是否使用缓存
|
|
|
+ */
|
|
|
+ async getAuthorizeCode(work_card, useCache = true) {
|
|
|
+ if (!work_card) return;
|
|
|
+ let data;
|
|
|
+
|
|
|
+ if (useCache) {
|
|
|
+ data = await this.cardCacheModel.findOne({ work_card });
|
|
|
+ if (data) return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ const list = await this.toCacheCardGroup();
|
|
|
+ const r = list.find(f => `${f.work_card}` === `${work_card}`);
|
|
|
+
|
|
|
+ if (r) return r;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 缓存并返回获取的车辆数据
|
|
|
+ */
|
|
|
+ async toCacheCardGroup() {
|
|
|
+ const users = await this.cardAdminModel.find({}).limit(1);
|
|
|
+ if (users.length <= 0) return;
|
|
|
+ const user = _.head(users);
|
|
|
+ const data = await this.toRequest('loadVehicles', { uid: user.uid, uKey: user.uKey });
|
|
|
+ let list = _.get(data, 'groups', []);
|
|
|
+ list = _.flattenDeep(list.map(i => i.vehicles));
|
|
|
+ list = list.map(i => ({ vid: i.id, vKey: i.vKey, work_card: i.name }));
|
|
|
+
|
|
|
+ await this.cardCacheModel.deleteMany();
|
|
|
+ await this.cardCacheModel.insertMany(list);
|
|
|
+
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取保安员入职信息
|
|
|
+ * @param {String} security_guard_id 保安员id
|
|
|
+ */
|
|
|
+ async getBaoanWork(security_guard_id) {
|
|
|
+ const { ip, port } = this.dbConfig;
|
|
|
+ const res = await axios({
|
|
|
+ method: 'post',
|
|
|
+ url: `http://${ip}:${port}/db/fetch?table=company_baoan_work`,
|
|
|
+ data: { security_guard_id, is_quit: '0' },
|
|
|
+ });
|
|
|
+ const data = this.selfRequestDeal(res);
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取保安员派遣信息
|
|
|
+ * @param {String} security_guard_id 保安员id
|
|
|
+ */
|
|
|
+ async getBaoanDispatch(security_guard_id) {
|
|
|
+ const { ip, port } = this.dbConfig;
|
|
|
+ const res = await axios({
|
|
|
+ method: 'post',
|
|
|
+ url: `http://${ip}:${port}/db/fetch?table=company_baoan_dispatch`,
|
|
|
+ data: { security_guard_id, status: '0' },
|
|
|
+ });
|
|
|
+ const data = this.selfRequestDeal(res);
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 登陆;用户放在session中
|
|
|
+ */
|
|
|
+ async login() {
|
|
|
+ console.log('初始化----------工牌接口登陆');
|
|
|
+ const name = 'fwedz';
|
|
|
+ const pwd = '000000';
|
|
|
+ const method = 'loginSystem';
|
|
|
+ const res = await this.toRequest(method, { name, pwd });
|
|
|
+ if (res.success) {
|
|
|
+ await this.cardAdminModel.deleteMany();
|
|
|
+ await this.cardAdminModel.create(_.pick(res, [ 'uid', 'uKey' ]));
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 请求接口
|
|
|
+ * @param {String} method 函数
|
|
|
+ * @param {Object} params 参数
|
|
|
+ */
|
|
|
+ async toRequest(method, params = {}) {
|
|
|
+ if (!method) return;
|
|
|
+ let url = `http://47.104.0.190:89/gpsonline/GPSAPI?version=1&method=${method}`;
|
|
|
+ for (const key in params) {
|
|
|
+ url += `&${key}=${params[key]}`;
|
|
|
+ }
|
|
|
+ const req = await axios.get(url);
|
|
|
+ const data = this.requestReturnDeal(req);
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 错误码文案
|
|
|
+ * @param {Number} code 错误码
|
|
|
+ */
|
|
|
+ errorType(code) {
|
|
|
+ const object = {
|
|
|
+ 0: '系统出错',
|
|
|
+ 1: '方法名不存在',
|
|
|
+ 2: '版本号不存在',
|
|
|
+ 3: '参数不能为空',
|
|
|
+ 4: '参数值格式有误',
|
|
|
+ 5: '用户名或密码错误',
|
|
|
+ 6: '授权码无效',
|
|
|
+ 7: '超过一小时最大访问次数',
|
|
|
+ };
|
|
|
+
|
|
|
+ return object[code];
|
|
|
+ }
|
|
|
+
|
|
|
+ * 请求结果处理
|
|
|
+ * @param {Object} req 统一处理请求
|
|
|
+ */
|
|
|
+ requestReturnDeal(req) {
|
|
|
+ if (req.status !== 200) {
|
|
|
+ console.error('接口请求失败----http失败');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (req.data) return req.data;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 保安系统接口处理
|
|
|
+ * @param {Object} req 统一处理请求
|
|
|
+ */
|
|
|
+ selfRequestDeal(req) {
|
|
|
+ if (req.status !== 200) {
|
|
|
+ console.error('接口请求失败----http失败');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const { data } = req.data;
|
|
|
+ if (data) return data;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+module.exports = CardService;
|