wangrong
2026-07-25 a97d3b4a19c0fc7586bd02f5b51f609904d5cf15
萤石云设备对接
4个文件已添加
4个文件已修改
230 ■■■■■ 已修改文件
src/configuration.ts 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/basicdata/controller/admin/iot.ts 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/basicdata/service/iot.ts 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/config.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/controller/ys7.controller.ts 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/dto/ys7.dto.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/service/ys7.service.ts 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/push/controller/app/open.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/configuration.ts
@@ -8,7 +8,7 @@
  MidwayWebRouterService,
} from '@midwayjs/core';
import * as koa from '@midwayjs/koa';
// import * as crossDomain from '@midwayjs/cross-domain';
import * as crossDomain from '@midwayjs/cross-domain';
import * as validate from '@midwayjs/validate';
import * as info from '@midwayjs/info';
import * as staticFile from '@midwayjs/static-file';
@@ -18,15 +18,15 @@
import * as ProdConfig from './config/config.prod';
import * as cool from '@cool-midway/core';
import * as upload from '@midwayjs/upload';
// import * as task from '@cool-midway/task';
// import * as rpc from '@cool-midway/rpc';
//import * as task from '@cool-midway/task';
//import * as rpc from '@cool-midway/rpc';
@Configuration({
  imports: [
    // https://koajs.com/
    koa,
    // 是否开启跨域(注:顺序不能乱放!!!) http://www.midwayjs.org/docs/extensions/cross_domain
    // crossDomain,
    crossDomain,
    // 静态文件托管 https://midwayjs.org/docs/extensions/static_file
    staticFile,
    // orm https://midwayjs.org/docs/extensions/orm
@@ -40,9 +40,9 @@
    // cool-admin 官方组件 https://cool-js.com
    cool,
    // rpc 微服务 远程调用
    // rpc,
    //rpc,
    // 任务与队列
    // task,
    //task,
    {
      component: info,
      enabledEnvironment: ['local', 'prod'],
src/modules/basicdata/controller/admin/iot.ts
@@ -1,4 +1,4 @@
import { Inject } from '@midwayjs/core';
import { Body, Inject, Post, Query } from '@midwayjs/core';
import { CoolController, BaseController } from '@cool-midway/core';
import { BasicdataIotEntity } from '../../entity/iot';
import { BasicdataIotService } from '../../service/iot';
@@ -27,10 +27,8 @@
    where: async ctx => {
      const conditions: any[][] = [];
      conditions.push(...(await WithDeptFilterWhere(ctx, { alias: 'a', field: 'departmentId' })));
      // 其他关联表(举例)
      // conditions.push(...(await deptFilterWhere(ctx, 'd', 'id')));
      return conditions;
    },
  },
@@ -38,4 +36,11 @@
export class AdminBasicdataIotController extends BaseController {
  @Inject()
  basicdataIotService: BasicdataIotService;
  @Post('/getYsDevices', { summary: '获取萤石云监控设备' })
  async getYsDevices(@Body('businessId') businessId: string) {
    const devices = await this.basicdataIotService.getYsDevices(businessId);
    return this.ok(devices);
  }
}
src/modules/basicdata/service/iot.ts
@@ -1,8 +1,12 @@
import { Provide } from '@midwayjs/core';
import { Inject, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
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 * as _ from 'lodash';
/**
 * 数据源定义信息服务
@@ -11,4 +15,103 @@
export class BasicdataIotService extends BaseService {
  @InjectEntityModel(BasicdataIotEntity)
  basicdataIotEntity: Repository<BasicdataIotEntity>;
  @InjectEntityModel(BaseSysDepartmentEntity)
  baseSysDepartmentEntity: Repository<BaseSysDepartmentEntity>;
  @Inject()
  baseSysParamService: BaseSysParamService;
  @Inject()
  baseSysPermsService: BaseSysPermsService;
  @Inject()
  ctx;
  /**
   * 获得部门菜单
   */
  async list() {
    const permsDepartmentArr = await this.baseSysPermsService.departmentIds(
      this.ctx.admin.userId
    );
    // 过滤部门权限
    const sql = `
        (
            SELECT
                a.id AS a_id,
                a.tenantId AS a_tenantId,
                a.name AS a_name,
                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]]
                )}
        )
        UNION ALL
        (
            SELECT
                b.businessId AS a_id,
                a.tenantId AS a_tenantId,
                b.businessName AS a_name,
                b.departmentId AS a_parentId,
                a.orderNum AS a_orderNum
            FROM t_basicdata_site b
            LEFT JOIN base_sys_department a ON b.departmentId = a.id
        )
        ORDER BY a_orderNum ASC`;
    const result = await this.nativeQuery(sql);
    return result;
  }
  /**
   * 监控设备查询
   */
  async getYsDevices(businessId: string) {
    // 修复原先key、secret取值颠倒bug + 增加await
    const ys7_appKey: string = await this.baseSysParamService.dataByKey('ys7.appKey');
    // departmentId 是数字,尝试转换;转换失败赋值 null
    const deptId = /^\d+$/.test(businessId) ? Number(businessId) : null;
    const qb = this.basicdataIotEntity.createQueryBuilder('a')
      .select([
        'a.id',
        'a.iotCode',
        'a.iotName',
        'a.iotTypeCode',
        'a.businessType',
        'a.businessId',
        'a.departmentId',
        'a.iotKey',
        'a.iotSecret',
        'a.iotChanel',
        'a.installLocation',
        'a.protocol'
      ])
      .where('a.iotTypeCode IN (:...typeIds)', {
        typeIds: ['萤石云固定监控', '萤石云车载监控'],
      });
    if (deptId !== null) {
      qb.andWhere('(a.businessId = :businessId OR a.departmentId = :deptId)', {
        businessId,
        deptId
      });
    } else {
      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;
  }
}
src/modules/monitor/config.ts
New file
@@ -0,0 +1,15 @@
import { ModuleConfig } from '@cool-midway/core';
export default () => {
    return {
        name: 'monitor',
        description: '萤石云视频监控模块',
        enable: true,
        middleware: [],
        // globalGuard: [],
        // globalFilter: [],
        // globalPipe: [],
        // 静态资源配置(萤石不需要,预留)
        // static: {},
    } as ModuleConfig;
};
src/modules/monitor/controller/ys7.controller.ts
New file
@@ -0,0 +1,20 @@
import { Controller, Post } from '@midwayjs/core';
import { Inject } from '@midwayjs/core';
import { BaseController } from '@cool-midway/core';
import { Ys7Service } from '../service/ys7.service';
@Controller('/admin/monitor/ys7')
export class Ys7Controller extends BaseController {
  @Inject()
  ys7Service: Ys7Service;
  /**
   * 获取萤石云 AccessToken
   * GET/POST 均可,前端 POST 调
   */
  @Post('/getToken')
  async getToken() {
    const token = await this.ys7Service.getAccessToken();
    return this.ok(token);
  }
}
src/modules/monitor/dto/ys7.dto.ts
New file
@@ -0,0 +1,9 @@
import { Rule, RuleType } from '@midwayjs/validate';
export class GetYs7TokenDTO {
    @Rule(RuleType.string().required())
    appKey: string;
    @Rule(RuleType.string().required())
    appSecret: string;
}
src/modules/monitor/service/ys7.service.ts
New file
@@ -0,0 +1,56 @@
import { Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import axios from 'axios';
import { BaseSysParamService } from '../../base/service/sys/param';
@Provide()
export class Ys7Service extends BaseService {
    @Inject()
    baseSysParamService: BaseSysParamService;
    /**
     * 获取萤石云 AccessToken
     * 内部自动读系统参数,不走缓存建议上层包一层 Redis
     */
    async getAccessToken(): Promise<{
        accessToken: string;
        expireTime: number;
    }> {
        // 从 Cool-Admin 系统参数表读取
        const appKey = await this.baseSysParamService.dataByKey('ys7.appKey');
        const appSecret = await this.baseSysParamService.dataByKey('ys7.appSecret');
        if (!appKey || !appSecret) {
            throw new Error('萤石云 appKey/appSecret 未配置,请在系统参数中维护 ys7.appKey / ys7.appSecret');
        }
        try {
            const res = await axios.post(
                'https://open.ys7.com/api/lapp/token/get',
                new URLSearchParams({
                    appKey,
                    appSecret,
                }),
                {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded',
                    },
                    timeout: 8000,
                }
            );
            const { code, msg, data } = res.data;
            if (String(code) !== '200') {
                throw new Error(`萤石云获取 Token 失败:${msg}(code: ${code})`);
            }
            return {
                accessToken: data.accessToken,
                expireTime: data.expireTime,
            };
        } catch (err) {
            throw err;
        }
    }
}
src/modules/push/controller/app/open.ts
@@ -28,7 +28,7 @@
  ) {
    const CLIENT_ID = String(await this.baseSysParamService.dataByKey('YAOHUA.WEIGHT.CLIENTID')); //'10001';
    const SECRET = String(await this.baseSysParamService.dataByKey('YAOHUA.WEIGHT.SECRET')); '9001ac9676b8';
    const SECRET = String(await this.baseSysParamService.dataByKey('YAOHUA.WEIGHT.SECRET')); //'9001ac9676b8';
    const clientId = headers['clientid'];