wangrong
2026-07-25 c2c8841967d9ab95e1bda8c65c2e37c8f0511005
修改萤石云任务
3个文件已删除
2个文件已添加
6个文件已修改
317 ■■■■■ 已修改文件
src/modules/base/controller/admin/sys/param.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/base/service/sys/param.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/basicdata/controller/admin/iot.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/basicdata/entity/iot.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/basicdata/service/iot.ts 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/config.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/monitor/controller/admin/ys7.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | 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/monitor/service/ys7.ts 76 ●●●●● 补丁 | 查看 | 原始文档 | 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,45 +28,52 @@
  @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
                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;
    (
      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
      ${isAdmin ? 'WHERE 1=1' : 'WHERE a.id IN (?)'}
    )
    UNION ALL
    (
      SELECT
        b.businessId   AS a_id,
        a.tenantId     AS a_tenantId,
        b.businessName AS a_name,
        b.departmentId AS a_parentId,
        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
  `;
    // 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;
  }
}