| src/modules/base/controller/admin/sys/param.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/base/service/sys/param.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/basicdata/controller/admin/iot.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/basicdata/entity/iot.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/basicdata/service/iot.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/config.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/controller/admin/ys7.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/controller/ys7.controller.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/dto/ys7.dto.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/service/ys7.service.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/monitor/service/ys7.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/modules/base/controller/admin/sys/param.ts
@@ -31,4 +31,9 @@ async htmlByKey(@Query('key') key: string) { this.ctx.body = await this.baseSysParamService.htmlByKey(key); } @Get('/stringbykey', { summary: '获得网页内容的参数值' }) async stringByKey(@Query('key') key: string) { this.ctx.body = await this.baseSysParamService.getByKey(key); } } src/modules/base/service/sys/param.ts
@@ -45,6 +45,30 @@ } /** * 根据key获得对应的参数 * @param key */ async getByKey(key) { const result = await this.baseSysParamEntity.findOneBy({ keyName: key }); if (result) { if (result.dataType == 0) { try { return JSON.parse(result.data); } catch (error) { return result.data; } } if (result.dataType == 1) { return result.data; } if (result.dataType == 2) { return result.data.split(','); } } return; } /** * 信息 * @param id * @param infoIgnoreProperty src/modules/basicdata/controller/admin/iot.ts
@@ -43,4 +43,9 @@ return this.ok(devices); } @Post('/getSitelist', { summary: '获取站点列表' }) async getSitelist() { const sitelist = await this.basicdataIotService.sitelist(); return this.ok(sitelist); } } src/modules/basicdata/entity/iot.ts
@@ -6,7 +6,7 @@ */ @Entity('t_basicdata_iot') export class BasicdataIotEntity extends BaseEntity { @Index({ unique: true }) @Index({ unique: false }) @Column({ comment: '终端编码' }) iotCode: string; src/modules/basicdata/service/iot.ts
@@ -5,7 +5,7 @@ import { BaseSysDepartmentEntity } from '../../base/entity/sys/department'; import { BasicdataIotEntity } from '../entity/iot'; import { BaseSysPermsService } from '../../base/service/sys/perms'; import { BaseSysParamService } from '../../base/service/sys/param'; import { BaseSysParamEntity } from '../../base/entity/sys/param'; import * as _ from 'lodash'; /** @@ -19,8 +19,8 @@ @InjectEntityModel(BaseSysDepartmentEntity) baseSysDepartmentEntity: Repository<BaseSysDepartmentEntity>; @Inject() baseSysParamService: BaseSysParamService; @InjectEntityModel(BaseSysParamEntity) baseSysParamEntity: Repository<BaseSysParamEntity>; @Inject() baseSysPermsService: BaseSysPermsService; @@ -28,15 +28,22 @@ @Inject() ctx; /** * 获得部门菜单 * 获得部门+站点合并树(遵循 Cool 数据权限规范) */ async list() { const permsDepartmentArr = await this.baseSysPermsService.departmentIds( this.ctx.admin.userId ); // 过滤部门权限 async sitelist() { const { userId, username } = this.ctx.admin; // 超管不受限 const isAdmin = username === 'admin'; let deptIds: any[] = []; if (!isAdmin) { deptIds = await this.baseSysPermsService.departmentIds(userId); // 没配部门权限时给个必定为空的值,防止查出全库 if (_.isEmpty(deptIds)) deptIds = [null]; } const sql = ` ( SELECT @@ -46,12 +53,7 @@ a.parentId AS a_parentId, a.orderNum AS a_orderNum FROM base_sys_department a WHERE 1=1 ${this.setSql( this.ctx.admin.username !== 'admin', `and (a.departmentId in (?) `, [!_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null]] )} ${isAdmin ? 'WHERE 1=1' : 'WHERE a.id IN (?)'} ) UNION ALL ( @@ -60,13 +62,18 @@ a.tenantId AS a_tenantId, b.businessName AS a_name, b.departmentId AS a_parentId, a.orderNum AS a_orderNum COALESCE(a.orderNum, 999) AS a_orderNum FROM t_basicdata_site b LEFT JOIN base_sys_department a ON b.departmentId = a.id ${!isAdmin ? 'WHERE b.departmentId IN (?)' : ''} ) ORDER BY a_orderNum ASC`; const result = await this.nativeQuery(sql); return result; ORDER BY a_orderNum ASC `; // nativeQuery 第二个参数必须显式传参数组 const params = isAdmin ? [] : [deptIds, deptIds]; return this.nativeQuery(sql, params); } /** @@ -74,7 +81,7 @@ */ async getYsDevices(businessId: string) { // 修复原先key、secret取值颠倒bug + 增加await const ys7_appKey: string = await this.baseSysParamService.dataByKey('ys7.appKey'); // const appKey_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appKey' }); // departmentId 是数字,尝试转换;转换失败赋值 null const deptId = /^\d+$/.test(businessId) ? Number(businessId) : null; const qb = this.basicdataIotEntity.createQueryBuilder('a') @@ -104,13 +111,7 @@ qb.andWhere('a.businessId = :businessId', { businessId }); } const result = await qb.orderBy('a.iotName', 'ASC').getMany(); const deviceList = result.map(item => { return { ...item, iotKey: ys7_appKey }; }); return deviceList; return result; } src/modules/monitor/config.ts
@@ -6,10 +6,6 @@ description: '萤石云视频监控模块', enable: true, middleware: [], // globalGuard: [], // globalFilter: [], // globalPipe: [], // 静态资源配置(萤石不需要,预留) // static: {}, globalMiddlewares: [], } as ModuleConfig; }; src/modules/monitor/controller/admin/ys7.ts
New file @@ -0,0 +1,19 @@ import {CoolController, BaseController } from '@cool-midway/core'; import { Post, Inject } from '@midwayjs/core'; import { Ys7Service } from '../../service/ys7'; @CoolController() export class Ys7Controller extends BaseController { @Inject() ys7Service: Ys7Service; /** * 获取萤石云 AccessToken * 前端 POST /admin/monitor/ys7/getToken */ @Post('/getToken') async getToken() { const tokenInfo = await this.ys7Service.getAccessToken(); return this.ok(tokenInfo); } } src/modules/monitor/controller/ys7.controller.ts
File was deleted src/modules/monitor/dto/ys7.dto.ts
File was deleted src/modules/monitor/service/ys7.service.ts
File was deleted src/modules/monitor/service/ys7.ts
New file @@ -0,0 +1,76 @@ import { Provide, Inject } from '@midwayjs/core'; import { BaseService } from '@cool-midway/core'; import axios from 'axios'; import { BaseSysParamEntity } from '../../base/entity/sys/param'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; interface Ys7TokenData { accessToken: string; /** 萤石返回的毫秒级过期时间戳 */ expireTime: number; } @Provide() export class Ys7Service extends BaseService { @InjectEntityModel(BaseSysParamEntity) baseSysParamEntity: Repository<BaseSysParamEntity>; /** 内存并发锁 */ private refreshing: Promise<Ys7TokenData> | null = null; /** * 对外暴露:拿 token(自动读缓存 / 续签) */ async getAccessToken() { const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' }); if ( !token || !token.updateTime || Date.now() - new Date(token.updateTime).getTime() > 6 * 24 * 60 * 60 * 1000 ) { await this.fetchAndSaveRemote(); } } /** 真正调萤石 */ private async fetchAndSaveRemote(): Promise<Ys7TokenData> { const appKey_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appKey' }); const appSecret_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appSecret' }); if (!appKey_result || !appSecret_result) { throw new Error( '萤石云 appKey/appSecret 未配置,请在【系统参数】中维护 ys7.appKey / ys7.appSecret' ); } const { data: res } = await axios.post( 'https://open.ys7.com/api/lapp/token/get', new URLSearchParams({ appKey: appKey_result.data, appSecret: appSecret_result.data }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, timeout: 8000, } ); if (String(res.code) !== '200') { throw new Error(`萤石云获取 Token 失败:${res.msg}(code: ${res.code})`); } const tokenData: Ys7TokenData = { accessToken: res.data.accessToken, expireTime: res.data.expireTime, }; // 写回系统参数表(Cool-Admin 自带 upsert) const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' }); this.baseSysParamEntity.save({ ...token, data: tokenData.accessToken, updateTime: new Date(), }).catch(() => { // 忽略写回失败 }); return tokenData; } }