common-util.ts

本文介绍了一个Node.js项目中的实用工具类,包括字符串处理、日期操作、文件下载等功能。涉及的技术点包括NestJS框架使用、Moment.js日期处理、文件系统操作等。
import { Injectable } from '@nestjs/common';
import * as moment from 'moment';
import * as fs from 'fs';
import xlsx from 'node-xlsx';
import * as uuid from 'uuid';
import * as pinyin from 'pinyin';
import { RpcException } from '@nestjs/microservices';
import * as crypto from 'crypto';

@Injectable()
export class ToStr {

  /**
   * 去除字符串中的指定字符
   * @param str   指定字符串
   * @param split 指定字符
   * @param join  填充字符
   */
  public static splitJoinStr(str: string, split: string, join?: string): string {
    join = join || '';
    return str.split(split).join(join);
  }

  /** 对象深拷贝 */
  public static clone<T>(origin: T): T {
    return JSON.parse(JSON.stringify(origin));
  }

  /**
   * 格式化数字 补零
   * @param num
   * @param length
   */
  public static numberFormat(num, length) {
    return (Array(length).join('0') + num).slice(-length);
  }

  /**
   * 解决js中数字运算丢失精度问题
   * @param num   数字
   * @param digit 精度
   * @return 计算结果
   */
  public static computationalAccuracy(num, digit: number): number {
    const m = Math.pow(10, digit);
    return Math.round(num * m) / m;
  }

  /** md5加密 */
  public static md5(data) {
    const hash = crypto.createHash('md5');
    return hash.update(data).digest('hex');
  }

  // /** 检查是否数字 */
  // public static checkInputNumber(drugIds) {
  //   const re = /^[0-9]+$/;
  //   for (const key in drugIds) {
  //     if (!re.test(drugIds[key].amount)) {
  //       return false;
  //     }
  //   }
  //   return drugIds;
  // }

  /** date to str 20181125 */
  public static getDateForNumber(date?: Date): string {
    return moment(date || new Date()).format('YYYYMMDDHHmmssSSS');
  }

  /** 获得当前日期:YYYY-MM-DD */
  public static dateOfToday(): string {
    return moment(new Date()).format('YYYY-MM-DD');
  }

  /** 下载文件 @param:名称类型,@param:文件格式,@param:buffer,@param:Response */
  public static downloadXLSX(
    typeName: string,
    fileType: string,
    sheet: any,
    res: any,
  ) {
    const buffer = xlsx.build([{ data: sheet }]);
    const fileName = `${typeName}${this.getDateForNumber()}${fileType}`;
    // 生成文件
    fs.writeFile(`./${fileName}`, buffer, e => {
      if (e) {
        return console.log(e);
      }
      // 下载
      res.download(`./${fileName}`, fileName, e1 => {
        if (e1) {
          return console.log(e1);
        }
        console.log(`下载 ${fileName} 成功`);
        // 最后记得删除文件
        fs.unlink(`./${fileName}`, e2 => {
          if (e2) {
            return console.log(e);
          }
          console.log(`删除 ${fileName} 成功`);
        });
      });
    });
  }

  /** UUID:uuid */
  public static UUID(): string {
    return uuid.v1().replace(/-/g, '');
  }

  /** is empty string */
  public static isEmptyString(opts): boolean {
    if (!opts) return true;
    if (typeof opts === 'string') {
      return opts === '';
    }
  }

  /** is empty Object */
  public static isEmptyObject(opts): boolean {
    if (!opts) return true;
    if (typeof opts.rows === 'object' && !(opts.rows instanceof Array)) {
      let hasProp = false;
      for (const prop in opts.rows) {
        hasProp = true;
        break;
      }
      if (hasProp) {
        opts.rows = [opts.rows];
      } else {
        return false;
      }
    }
  }

  /** 获得当前年月日流水格式 */
  public static streamDateOfNow(date?: Date): string {
    return moment(date || new Date()).format('YYYYMMDD');
  }

  /** 获得当前具体时间流水格式 */
  public static streamTimeOfNow(date?: Date): string {
    return moment(date || new Date()).format('YYYYMMDDHHmmssSSS');
  }

  /** 获得具体时间:YYYY-MM-DD HH:mm:ss */
  public static datetimeOfNow(date?: Date): string {
    return moment(date || new Date()).format('YYYY-MM-DD HH:mm:ss');
  }

  /** 比较时间,前者大返回true */
  public static compTime(datetime1: string, datetime2?: string): boolean {
    let date1, date2;
    try {
      date1 = new Date(datetime1);
    } catch (e) {
      date1 = new Date();
    }
    try {
      date2 = !datetime2 ? new Date() : new Date(datetime2);
    } catch (e) {
      date2 = new Date();
    }
    return date1 > date2;
  }

  /** 根据时间差得到具体时间:YYYY-MM-DD HH:mm:ss */
  public static datetimeByTimeDifference(timeDifference: {
    year?: number;
    month?: number;
    date?: number;
    hours?: number;
    minutes?: number;
    seconds?: number;
    milliseconds?: number;
    beforeTime?: Date | string;
  }): string {
    let laterTime: Date;
    try {
      laterTime = !timeDifference.beforeTime
        ? new Date()
        : typeof timeDifference.beforeTime === 'string'
        ? new Date(timeDifference.beforeTime)
        : timeDifference.beforeTime;
    } catch (e) {
      console.log(`日期格式化错误,${e}`);
      laterTime = new Date();
    }
    if (!this.isEmptyValue(timeDifference.year)) {
      laterTime.setFullYear(laterTime.getFullYear() + timeDifference.year);
    }
    if (!this.isEmptyValue(timeDifference.month)) {
      laterTime.setMonth(laterTime.getMonth() + timeDifference.month);
    }
    if (!this.isEmptyValue(timeDifference.date)) {
      laterTime.setDate(laterTime.getDate() + timeDifference.date);
    }
    if (!this.isEmptyValue(timeDifference.hours)) {
      laterTime.setHours(laterTime.getHours() + timeDifference.hours);
    }
    if (!this.isEmptyValue(timeDifference.minutes)) {
      laterTime.setMinutes(laterTime.getMinutes() + timeDifference.minutes);
    }
    if (!this.isEmptyValue(timeDifference.seconds)) {
      laterTime.setSeconds(laterTime.getSeconds() + timeDifference.seconds);
    }
    if (!this.isEmptyValue(timeDifference.milliseconds)) {
      laterTime.setMilliseconds(
        laterTime.getMilliseconds() + timeDifference.milliseconds,
      );
    }
    return moment(laterTime).format('YYYY-MM-DD HH:mm:ss');
  }

  /**
   * SQL:在列中查找
   */
  public static findInSetForSQL(
    fieldList: string[],
    fieldName: string,
    andOr: 'and' | 'or',
    keyName: string,
  ): { sql: string; condition: [] } {
    let sql = `(`;
    const condition: any = {};
    for (const key in fieldList) {
      if (+key !== 0) {
        sql += ` ${andOr === 'and' ? 'AND' : 'OR'} `;
      }
      if (fieldList[key].toUpperCase() === 'NULL') {
        sql += `${fieldName} IS NULL`;
      } else if (fieldList[key] === '') {
        sql += `${fieldName} = ''`;
      } else {
        sql += `FIND_IN_SET(:${keyName}${key},${fieldName})`;
      }
      condition[`${keyName}${key}`] = fieldList[key];
    }
    sql += `)`;
    return { sql, condition };
  }

  /**
   * 多个查询
   */
  public static findMoreForSQL(data: {
    valueList: string[];
    fieldName: string;
    andOr: 'and' | 'or';
    like?: boolean;
    unique?: number;
  }): { sql: string; condition: [] } {
    let sql = `(`;
    const condition: any = {};
    for (const key in data.valueList) {
      // 生成一个keyName
      const keyName = `${data.fieldName}${key}${
        !this.isEmptyValue(data.unique) ? data.unique : ''
      }`;
      if (+key === 0) {
        sql += `${data.fieldName} ${
          data.like === true ? 'like' : '='
        } :${keyName}`;
      } else {
        sql += ` ${data.andOr === 'and' ? 'AND' : 'OR'} ${data.fieldName} ${
          data.like === true ? 'like' : '='
        } :${keyName}`;
      }
      condition[keyName] =
        data.like === true ? `%${data.valueList[key]}%` : data.valueList[key];
    }
    sql += `)`;
    return { sql, condition };
  }

  /**
   * 对象拷贝
   */
  public static copyProperties(requestData: {
    oldObj: object;
    returnObj: any;
    copyFieldNameArray?: string[];
    passFieldNameArray?: string[];
  }): any {
    try {
      if (
        requestData.copyFieldNameArray === undefined ||
        requestData.copyFieldNameArray.length === 0
      ) {
        for (const key in requestData.oldObj) {
          // 判断是否有要跳过的参数
          if (
            requestData.passFieldNameArray === undefined ||
            !requestData.passFieldNameArray.includes(key)
          ) {
            requestData.returnObj[key] = this.copyField(
              requestData.oldObj[key],
            );
          }
        }
      } else {
        for (const key in requestData.copyFieldNameArray) {
          const fieldName: string = requestData.copyFieldNameArray[key];
          if (!this.isEmptyValue(requestData.oldObj[fieldName])) {
            requestData.returnObj[fieldName] = this.copyField(
              requestData.oldObj[fieldName],
            );
          }
        }
      }
    } catch (e) {
      console.log(e);
      this.throwExceptionOfRpc(500, e);
    }
    return requestData.returnObj;
  }

  /** 深拷贝字段 */
  private static copyField(fieldValue: any): any {
    if (typeof fieldValue === 'object') {
      const tmp = JSON.stringify(fieldValue);
      return JSON.parse(tmp);
    }
    return fieldValue;
  }

  /** 获取汉语拼音首字母,https://www.npmjs.com/package/pinyin */
  public static getFirstWordByChinese(word: string): string {
    let firstWord = '';
    try {
      const alias = pinyin(word, {
        // 首字母风格,只返回拼音的首字母部分
        style: pinyin.STYLE_FIRST_LETTER,
      });
      for (const key in alias) {
        firstWord +=
          alias[key] && alias[key].length > 0
            ? alias[key][0].substring(0, 1)
            : '';
      }
    } catch (e) {
      console.log(`获取首字母失败,${e}`);
    }
    return firstWord.toUpperCase();
  }

  /** 检查布尔类型数据是否错误或空 */
  public static isCheckBooleanEmpty(value: string): boolean {
    return (
      !this.isEmptyValue(value) &&
      (value.toString() === '0' || value.toString() === '1')
    );
  }

  /** 检查布尔类型数据是否错误 */
  public static isCheckBooleanValue(validate: {}, failedMsg: string) {
    for (const fieldName in validate) {
      if (+validate[fieldName] !== 1 && +validate[fieldName] !== 0) {
        this.throwExceptionOfRpc(
          500,
          `${failedMsg}${fieldName}字段的值${validate[fieldName]}不正确`,
        );
      }
    }
  }

  /** 检查布尔类型数据是否为空 */
  public static isEmptyBooleanValue(value: string) {
    return (
      this.isEmptyValue(value) ||
      !(value.toString() === '0' || value.toString() === '1')
    );
  }

  /** 统一抛出异常 */
  public static throwExceptionOfRpc(code: number, message: any): never {
    throw new RpcException({ code, message });
  }

  /** 对象比对,返回数据不一样的字段名称,略过新对象是undefined的字段 */
  public static diffFieldList(
    obj1: any,
    obj2: any,
    passFieldList?: string[],
  ): string[] {
    const diffFieldList: string[] = [];
    for (const key in obj2) {
      if (passFieldList !== undefined && passFieldList.indexOf(key) !== -1) {
        continue;
      }
      if (obj2[key] !== undefined && obj2[key] !== obj1[key]) {
        diffFieldList.push(key);
      }
    }
    return diffFieldList;
  }

  /** 驼峰转下划线 */
  public static toHump(str: string): string {
    return str.replace(/([A-Z])/g, '_$1').toLowerCase();
  }

  /** 匹配字符串 */
  public static equals(
    targetStr: string,
    equalsStrList: string[],
    failedMsg: string,
  ) {
    let result = false;
    for (const key in equalsStrList) {
      const equalsStr = equalsStrList[key];
      if (targetStr === equalsStr) {
        result = true;
        break;
      }
    }
    if (!result) {
      this.throwExceptionOfRpc(500, failedMsg);
    }
  }

  /**
   * 匹配YYYY-MM
   * @param param
   */
  public static isYeahMonth(param: string): boolean {
    return /^\d{4}-((0([1-9]))|(1(0|1|2)))$/.test(param);
  }

  /**
   * 匹配YYYY-mm-dd
   * @param param
   */
  public static isDate(param: string): boolean {
    return /(\d{4}-(((0(1|3|5|7|8))|(1(0|2)))(-((0[1-9])|([1-2][0-9])|(3[0-1])))?)|(((0(2|4|6|9))|(11))(-((0[1-9])|([1-2][0-9])|(30)))?)|((02)(-((0[1-9])|(1[0-9])|(2[0-8])))?))|(((([0-9]{2})((0[48])|([2468][048])|([13579][26]))|(((0[48])|([2468][048])|([3579][26]))00)))-02-29)/.test(
      param,
    );
  }

  /** date to str */
  public static getDateStr(date?: Date): string {
    return moment(date || new Date()).format('llll');
  }

  /** current_time */
  public static getCurrentTimestamp(date?): number {
    const time = (date ? new Date(date) : new Date()).getTime();
    return `${time}`.length > 10 ? +`${time}`.substr(0, 10) : time;
  }

  /** current_time */
  public static getCurrentTimes(date?): number {
    return (date ? new Date(date) : new Date()).getTime();
  }

  /** get day startTimes */
  public static getDateStartTimes(date?): number {
    date = date ? new Date(date) : new Date();
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    return date.getTime();
  }

  /** get day endTimes */
  public static getDateEndTimes(date?): number {
    date = date ? new Date(date) : new Date();
    date.setHours(23);
    date.setMinutes(59);
    date.setSeconds(59);
    date.setMilliseconds(999);
    return date.getTime();
  }

  /**
   * 对请求字符串进行拼接
   * @param parm
   */
  public static getSign(param: object) {
    const keys = [];
    for (const i in param) {
      if (param[i] !== undefined && param[i] !== '') {
        keys.push(i);
      }
    }
    // 对参数键进行ASCII 码从小到大排序
    keys.sort();
    let sign = '';
    keys.forEach((value, index) => {
      sign += value;
      sign += '=';
      sign += param[value];
      sign += '&';
    });
    return sign.substring(0, sign.length - 1);
  }

  /**
   * 获取指定字符在当前字符串中出现的所有索引
   * @param str1 目标字符串
   * @param str2 指定字符(比str1短)
   */
  public static getAllIndex(str1: string, str2: string) {
    const arrLen = str1.length > str2.length ? str1.length % str2.length : 0;
    const indexList = [];
    for (let i = 0; i++; i < arrLen) {
      const index = str1.indexOf(str2);
      if (index !== -1) {
        str1 = str1.substring(index + str2.length);
        indexList.push(
          (indexList.length > 0 ? indexList[indexList.length - 1] : 0) + index,
        );
      }
    }
    return indexList;
  }

  /** 生成随机字符串 (5K8264ILTKCH16CQ2502SI8ZNMTM67VS) */
  genRandomString(len): string {
    const text = 'abcdefghijklmnopqrstuvwxyz0123456789';
    const rdmIndex = text => (Math.random() * text.length) | 0;
    let rdmString = '';
    for (; rdmString.length < len; rdmString += text.charAt(rdmIndex(text)));
    return rdmString;
  }

  /**
   * 20191012111215 ---> 2019-10-12 11-12-15
   * @param date
   */
  getStringToDte(date: string): Date {
    const timeStr =
      date.substring(0, 4) +
      '-' +
      date.substring(4, 6) +
      '-' +
      date.substring(6, 8) +
      ' ' +
      date.substring(8, 10) +
      ':' +
      date.substring(10, 12) +
      ':' +
      date.substring(12, 14);
    const nyrArr = timeStr.split(' ')[0].split('-');
    const sfmArr = timeStr.split(' ')[1].split(':');
    const resDate = new Date(
      +nyrArr[0],
      +nyrArr[1] - 1,
      +nyrArr[2],
      +sfmArr[0],
      +sfmArr[1],
      0,
      0,
    );
    return resDate;
  }

  /** date to str 20181125 */
  getDateForNumber(date?: Date): string {
    return moment(date || new Date()).format('YYYYMMDDHHmmssSSS');
  }

  /** 下载文件 @param:名称类型,@param:文件格式,@param:buffer,@param:Response */
  async download(typeName: string, fileType: string, sheet: any, res: any) {
    const buffer = await xlsx.build([{ data: sheet }]);
    const fileName = `${typeName}${this.getDateForNumber()}${fileType}`;
    // 生成文件
    fs.writeFile(`./${fileName}`, buffer, e => {
      if (!e) {
        res.download(`./${fileName}`, fileName, e1 => {
          if (!e1) {
            console.log(`download ${fileName} successful`);
            fs.unlink(`./${fileName}`, e => {
              if (!e) {
                console.log(`deleted ${fileName} successful`);
              } else {
                return console.log(e);
              }
            });
          } else {
            return console.log(e1);
          }
        });
      } else {
        return console.log(e);
      }
      // 下载
    });
  }

  /** 判断值是否为空 */
  public static isEmptyValue(opts, trim?: boolean): boolean {
    if (
      (opts === undefined || opts === 'undefined' || opts === undefined) &&
      typeof opts !== 'number'
    ) {
      return true;
    }
    return (trim ? `${opts}`.trim() : `${opts}`) === '';
  }

  /** 得到昨天的时间 */
  getYesterdaysTime(): string {
    const day1 = new Date();
    day1.setTime(day1.getTime() - 24 * 60 * 60 * 1000);
    return moment(day1).format('YYYYMMDD');
  }

  /** 得到昨天的时间 YYYY-MM-DD */
  getYesterdaysTimeYMD(): string {
    const day1 = new Date();
    day1.setTime(day1.getTime() - 24 * 60 * 60 * 1000);
    return moment(day1).format('YYYY-MM-DD');
  }

  /** 得到今天时间 YYYY-MM-DD */
  public static getDateYMD(date?: Date): string {
    return moment(date || new Date()).format('YYYY-MM-DD');
  }

  public static prefixInteger(num: number, length: number) {
    return (Array(length).join('0') + num).slice(-length);
  }
}

这种情况下可以合并了吗? git status On branch lqn/feat/aio-v1.0-device All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: ../../../../../.env modified: ../../../../../omada-central-env.config.js modified: ../../../../../package.json modified: ../../../../../pnpm-lock.yaml modified: ../../../../../rsbuild.config.ts modified: ../../../../api/auth.ts modified: ../../../../api/video.ts modified: ../../../../assets/icons/package-near-expire.svg modified: ../../../../components/AppAiFreeTrial.vue modified: ../../../../components/eptz/Index.vue modified: ../../../../components/live/PreviewPlayer.vue modified: ../../../../components/live/use-live-tool.ts modified: ../../../../components/navigator/Index.vue new file: ../../../../config-env/common-util.ts modified: ../../../../config-env/index.ts new file: ../../../../config-env/log/index.ts new file: ../../../../config-env/nav/index.ts modified: ../../../../config-env/system-settings/index.ts modified: ../../../../config-env/user/index.ts modified: ../../../../config-env/video/index.ts modified: ../../../../constants/custom-role.ts new file: ../../../../constants/errors/device.ts new file: ../../../../constants/errors/index.ts new file: ../../../../constants/errors/player.ts modified: ../../../../constants/navigator.ts modified: ../../../../hooks/use-preview.ts modified: ../../../../i18n/locales/en_US.json modified: ../../../../index.ts modified: ../../../../player/interface.ts modified: ../../../../player/media-player.ts modified: ../../../../player/plugins/instances/timeline/TimeSpanSlider.vue modified: ../../../../player/preview/preview-player.ts new file: ../../../../player/stream/base.ts new file: ../../../../player/stream/direct-stream.ts new file: ../../../../player/stream/https-relay-stream.ts new file: ../../../../player/stream/index.ts new file: ../../../../player/stream/local-media-stream.ts new file: ../../../../player/stream/multipart-conversion.ts new file: ../../../../player/stream/p2p-stream.ts new file: ../../../../player/stream/racing-stream.ts new file: ../../../../player/stream/relay-stream-base.ts new file: ../../../../player/stream/relay-stream.ts modified: ../../../../store/modules/auth.ts modified: ../../../../styles/application/var.less modified: ../../../../utils/device-pre-connect.ts modified: ../../../../utils/rsa-encode.ts modified: ../../../../utils/video.ts modified: ../../../account-settings/uid-account/Index.vue modified: ../../../auth/login-redirect/uid-cloud-redirect/Index.vue modified: ../../Index.vue modified: ../../ai-search/face/hooks/use-face.ts modified: ../../ai-search/hooks/use-first-empty-guide.ts modified: ../../ai-search/hooks/utils.ts modified: ../../ai-search/human/const.ts modified: ../../ai-search/human/hooks/use-human.ts modified: ../../ai-search/vehicle/hooks/use-vehicle.ts modified: ../../alarm/events/components/event-menu/Recipients.vue modified: ../../alarm/events/custom-alerts/custom-alerts-content/Index.vue modified: ../../alarm/events/device-event/Index.vue modified: ../../billing-account/order-history/Index.vue modified: ../../billing-account/order-history/hooks/use-order.ts modified: ../../components/video-batch-select/Index.vue modified: ../../dashboard/line-chart/hooks/use-line.ts modified: ../components/delete-device-modal/delete-aio-device/Index.vue modified: ../components/delete-device-modal/delete-device-ability.ts modified: ../components/device.less modified: ../components/edit-device-nvr/Index.vue modified: ../components/edit-device-nvr/alarm-info/hotzone-detection/use-device.ts modified: ../components/edit-device-nvr/alarm-info/pet-detection/Index.vue modified: ../components/edit-device-nvr/alarm-info/pet-detection/use-pet-detection.ts modified: ../components/edit-device-nvr/camera-info/device-access/use-table.ts modified: ../components/edit-device-nvr/storage-info/array-management/AddHarddriveModal.vue modified: ../components/edit-device-nvr/storage-info/array-management/CreateRAIDModal.vue modified: ../components/edit-device-nvr/storage-info/array-management/CreateRAIDOnceModal.vue modified: ../components/edit-device-nvr/storage-info/array-management/EditRAIDModal.vue modified: ../components/edit-device-nvr/storage-info/array-management/Index.vue modified: ../components/edit-device-nvr/storage-info/recording-manager/hooks/constants.ts modified: ../components/edit-device-nvr/storage-info/recording-manager/hooks/use-columns.tsx modified: ../components/edit-device-nvr/storage-info/storage-manager/components/storage-status/Index.vue modified: ../components/edit-device-nvr/storage-info/storage-manager/components/storage-status/hooks/use-storage-status.ts modified: ../components/edit-device/Index.vue modified: ../components/edit-device/cloud-storage/Index.vue modified: ../components/edit-device/network-settings/ddns/Index.vue modified: ../components/edit-device/network-settings/ddns/hooks/useAction.ts modified: ../components/edit-device/smart-analysis/people-counting/use-device.ts modified: ../components/edit-device/smart-event/pet-detection/Index.vue modified: ../components/edit-device/smart-event/pet-detection/use-pet-detection.ts modified: ../components/edit-device/smart-event/queue-detection/use-queue-detection.ts modified: ../components/edit-device/system-manager/capture-management/Index.vue modified: ../components/edit-device/system-manager/certificate-management/Index.vue modified: ../components/edit-solar-drawer/Index.vue modified: ../components/information-display/components/IpcInformation.vue modified: ../components/local-upgrade/Index.vue modified: Index.vue modified: components/TableFilter.vue modified: ../hooks/use-columns-cloud.tsx modified: ../hooks/use-columns-local.tsx modified: ../../license/license-manage/Index.vue modified: ../../log/components/SystemTable.vue modified: ../../log/hooks/system-table/use-log.ts modified: ../../map/device-map/components/LiveViewList.vue modified: ../../organization/hooks/index.ts deleted: ../../organization/hooks/use-actions.ts modified: ../../passenger-flow/components/passenger-flow-quick-settings/components/SingleLiveView.vue modified: ../../plan/Index.vue modified: ../../rules/event-rules/Index.vue modified: ../../rules/event-rules/hooks/use-actions.tsx modified: ../../rules/event-rules/hooks/use-event-rule.tsx modified: ../../system-setting/Index.vue modified: ../../user/ReinviteIcon.vue modified: ../../video/video-common/VideoToolTip.vue modified: ../../video/video-common/use-get-videoInfo.ts modified: ../../video/video-surveillance/component/time-span/Index.vue modified: ../../video/video-surveillance/hooks/utils.ts modified: ../../video/video-surveillance/live-view/Index.vue modified: ../../video/video-surveillance/live-view/hooks/preview-port.ts modified: ../../video/video-surveillance/live-view/plugins/ratio.vue modified: ../../video/video-surveillance/playback/Playback.vue modified: ../../video/video-surveillance/playback/event/hook/use-image-cloud.ts modified: ../../video/video-surveillance/playback/main/const/playback-player.ts new file: ../../video/video-surveillance/playback/main/const/retry-white-list.ts modified: ../../video/video-surveillance/playback/main/error-hander/use-playback-error.ts modified: ../../video/video-surveillance/playback/main/playback-manage.ts modified: ../../video/video-surveillance/playback/main/playback-player/device-player.ts modified: ../../video/video-surveillance/playback/main/playback-player/hooks/use-decryption.ts Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: ../components/add-device-modal/transfer/transfer.d.ts Untracked files: (use "git add <file>..." to include in what will be committed) ../../../../../dist.7z
最新发布
11-29
我想我們先整合一下,先給我擴充後的整個完整目錄結構:my-app/ ├── README.md ├── Makefile ├── .gitignore ├── .editorconfig ├── .prettierrc ├── .eslintrc.cjs ├── .golangci.yml ├── .dockerignore ├── .vscode/ │ ├── extensions.json │ └── settings.json │ ├── contracts/ # 契約單一真相(SSOT) │ ├── common.yaml # 全域元資料(servers、security、RBAC、components 共用) │ ├── domains/ │ │ ├── users.yaml # 使用者領域 schema/paths 片段 │ │ └── auth.yaml # 認證授權相關 schema/paths 片段 │ ├── endpoints/ │ │ ├── users.list.yaml # 端點片段(可拆分便於維護) │ │ └── users.detail.yaml │ └── openapi.base.yaml # OpenAPI 合成基底(版本/聯絡/License 等) │ ├── api/ # 由 contracts 合成的 OpenAPI(生成物) │ ├── openapi.yaml # 最終合成 OpenAPI │ └── snapshot/ │ └── openapi.2025-10-27.yaml # 每次 CI 產生快照(便於 diff 與回滾) │ ├── scripts/ # 生成/驗證/工具腳本 │ ├── contracts-to-openapi.mjs # 合併 contracts → api/openapi.yaml │ ├── gen-openapi.sh # 調用 oapi-codegen / openapi-typescript / zod wrap │ ├── gen-zod-from-openapi.mjs # 將 TS types 轉 zod schema(或直接嵌入) │ ├── validate-openapi.mjs # 基於 spectral 或 openapi-diff 驗證 │ ├── validate-artifact.mjs # 驗證 repo/data 與 schema(CI 用) │ ├── bump-version.mjs # 語義化版本管理 │ └── release-notes.mjs # 變更日誌生成 │ ├── repo/ # Artifact 倉庫(可被 Gateway/mock/e2e 使用) │ ├── api/ │ │ ├── index.json # 路由索引(method/path → flow 與 data 映射) │ │ └── flows/ │ │ ├── users.list.flow.yaml │ │ └── users.detail.flow.yaml │ ├── data/ # 假資料(E2E 與 Mock 使用) │ │ ├── users.list.v1.json │ │ ├── users.detail.u_1.v1.json │ │ └── seed/ │ │ └── users.seed.json │ ├── plugins/ # JS 外掛(goja) │ │ ├── search.js │ │ └── helpers.js │ └── validators/ # 前後端共用 schema 定義(可選) │ ├── zod.ts │ └── ajv.ts │ ├── gateway/ # Artifact Gateway(Golang) │ ├── cmd/ │ │ └── artifact-gateway/ │ │ └── main.go # 啟動 HTTP、讀取 REPO_BASE、註冊路由 /mock /repo │ ├── internal/ │ │ ├── gateway/ │ │ │ ├── server.go # 路由、middleware(RBAC、logging、recover) │ │ │ └── match.go # 依 repo/api/index.json 匹配端點 │ │ └── flows/ │ │ ├── engine.go # Context、Step、OperatorRegistry、RespondStep │ │ ├── dataset.go # DataSource 介面、MemoryDataSource │ │ ├── ops.go # 運算子:filterAndPaginate、findById、checkEmailUnique、assignId、js 代理 │ │ ├── plugins.go # goja VM、外掛搜尋路徑、函式執行 │ │ ├── validator.go # request/response schema 驗證(可接 gojsonschema) │ │ ├── rbac.go # x-role / JWT claims 驗證(開發期) │ │ └── ops_test.go # 單元測試(涵蓋四個運算子與 JS 外掛) │ ├── testdata/ │ │ ├── repo/ # 測試專用 repo 拷貝 │ │ │ ├── api/index.json │ │ │ ├── data/users.list.v1.json │ │ │ └── plugins/search.js │ │ └── requests/ │ │ └── users.create.json │ ├── Dockerfile │ └── go.mod │ ├── backend/ # 真實後端服務(Golang) │ ├── cmd/ │ │ └── api/ │ │ └── main.go # 真實 API 入口(生產使用) │ ├── pkg/ │ │ ├── gen/ # oapi-codegen 生成 │ │ │ └── openapi.gen.go │ │ ├── handlers/ │ │ │ ├── users.go │ │ │ └── health.go │ │ ├── middlewares/ │ │ │ ├── logger.go │ │ │ └── auth.go │ │ ├── models/ │ │ │ └── user.go │ │ ├── storage/ │ │ │ └── memory.go │ │ └── server/ │ │ └── router.go │ ├── api/ │ │ └── openapi.yaml # 從 /api 同步或軟鏈接,供 oapi-codegen │ ├── Dockerfile │ ├── go.mod │ └── go.sum │ ├── frontend/ # Angular 前端 │ ├── src/ │ │ ├── app/ │ │ │ ├── core/ │ │ │ │ ├── api/ │ │ │ │ │ ├── types.gen.ts # openapi-typescript 生成 │ │ │ │ │ └── zod.gen.ts # zod schema(由腳本生成或手寫) │ │ │ │ ├── artifact/ │ │ │ │ │ ├── artifact.service.ts # 以 /mock 或 /repo 讀取資料 │ │ │ │ │ └── artifact.spec.ts # 與 repo/data 一致性測試 │ │ │ │ ├── datasource/ │ │ │ │ │ ├── datasource.service.ts # 資料來源狀態管理(Mock/Repo/API) │ │ │ │ │ ├── datasource.interceptor.ts# 附加 header 與監測請求 │ │ │ │ │ └── datasource.model.ts │ │ │ │ ├── config/config.service.ts │ │ │ │ └── utils/http-error.util.ts │ │ │ ├── features/ │ │ │ │ └── users/ │ │ │ │ ├── users-list/ │ │ │ │ │ ├── users-list.component.ts │ │ │ │ │ └── users-list.component.html │ │ │ │ └── users-detail/ │ │ │ │ ├── users-detail.component.ts │ │ │ │ └── users-detail.component.html │ │ │ ├── shared/ │ │ │ │ ├── components/ │ │ │ │ └── pipes/ │ │ │ └── devtools/ │ │ │ ├── datasource-switcher/ │ │ │ │ ├── datasource-switcher.component.ts │ │ │ │ ├── datasource-switcher.component.html │ │ │ │ └── datasource-switcher.component.scss │ │ │ └── request-log-panel/ │ │ │ ├── request-log-panel.component.ts │ │ │ └── request-log-panel.component.html │ │ ├── environments/ │ │ │ ├── environment.ts # dev:預設 /mock │ │ │ └── environment.prod.ts # prod:預設 /api │ │ ├── main.ts │ │ └── styles.scss │ ├── cypress/ # e2e 測試 │ │ ├── e2e/ │ │ │ ├── datasource-switch.cy.ts │ │ │ └── users-flow.cy.ts │ │ └── support/ │ │ └── e2e.ts │ ├── Dockerfile │ ├── angular.json │ ├── package.json │ └── tsconfig.json │ ├── config/ │ ├── cloudbuild.yaml # GCP Cloud Build(或 GitHub Actions 對等) │ └── k8s/ │ ├── namespace.yaml │ ├── gateway.deployment.yaml │ ├── gateway.service.yaml │ ├── backend.deployment.yaml │ ├── backend.service.yaml │ └── ingress.yaml │ ├── artifacts/ │ ├── template.yaml # Artifact 模板與鏡像標籤參數 │ ├── docker-compose.dev.yaml # 本地整包開發(含 repo 暴露與 /mock 代理) │ └── helm/ │ └── my-app/ │ ├── Chart.yaml │ ├── values.yaml │ └── templates/ │ ├── deployment.yaml │ ├── service.yaml │ └── ingress.yaml │ └── .github/ └── workflows/ └── ci.yml # GitHub Actions(或與 Cloud Build 並存)
10-28
Caused by: org.apache.flink.util.SerializedThrowable: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.data.load.stream.DefaultStreamLoader.send(DefaultStreamLoader.java:289) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.data.load.stream.DefaultStreamLoader.lambda$send$2(DefaultStreamLoader.java:120) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_362] ... 1 more 2025-06-10 01:14:52,776 INFO com.starrocks.connector.flink.manager.StarRocksSinkManagerV2 [] - Stream load manager flush 2025-06-10 01:14:52,776 ERROR com.starrocks.connector.flink.manager.StarRocksSinkManagerV2 [] - catch exception, wait rollback com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.data.load.stream.DefaultStreamLoader.send(DefaultStreamLoader.java:289) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.data.load.stream.DefaultStreamLoader.lambda$send$2(DefaultStreamLoader.java:120) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_362] at java.lang.Thread.run(Thread.java:750) [?:1.8.0_362] 2025-06-10 01:14:52,776 ERROR com.starrocks.connector.flink.table.sink.StarRocksDynamicSinkFunctionV2 [] - Failed to flush when closing java.lang.RuntimeException: com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.connector.flink.manager.StarRocksSinkManagerV2.AssertNotException(StarRocksSinkManagerV2.java:367) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.connector.flink.manager.StarRocksSinkManagerV2.flush(StarRocksSinkManagerV2.java:299) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.connector.flink.table.sink.StarRocksDynamicSinkFunctionV2.close(StarRocksDynamicSinkFunctionV2.java:184) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at org.apache.flink.api.common.functions.util.FunctionUtils.closeFunction(FunctionUtils.java:41) ~[roi-flinksql-custom-1.0-SNAPSHOT.jar:?] at org.apache.flink.streaming.api.operators.AbstractUdfStreamOperator.dispose(AbstractUdfStreamOperator.java:117) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.disposeAllOperators(StreamTask.java:791) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.runAndSuppressThrowable(StreamTask.java:770) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.cleanUpInvoke(StreamTask.java:689) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:593) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:755) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.run(Task.java:570) [flink-dist_2.11-1.12.3.jar:1.12.3] at java.lang.Thread.run(Thread.java:750) [?:1.8.0_362] Caused by: com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.data.load.stream.DefaultStreamLoader.send(DefaultStreamLoader.java:289) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.data.load.stream.DefaultStreamLoader.lambda$send$2(DefaultStreamLoader.java:120) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_362] ... 1 more 2025-06-10 01:14:52,778 WARN org.apache.flink.runtime.taskmanager.Task [] - Sink: Sink(table=[default_catalog.default_database.sink_rt_dau_pvreport2sr], fields=[day, EXPR$1, client_act_time, is_client_act, ts, EXPR$5]) (1/1)#0 (6b68924ad80786daa5913d36d18c04f2) switched from RUNNING to FAILED. java.io.IOException: Could not perform checkpoint 1 for operator Sink: Sink(table=[default_catalog.default_database.sink_rt_dau_pvreport2sr], fields=[day, EXPR$1, client_act_time, is_client_act, ts, EXPR$5]) (1/1)#0. at org.apache.flink.streaming.runtime.tasks.StreamTask.triggerCheckpointOnBarrier(StreamTask.java:963) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.CheckpointBarrierHandler.notifyCheckpoint(CheckpointBarrierHandler.java:115) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.SingleCheckpointBarrierHandler.processBarrier(SingleCheckpointBarrierHandler.java:156) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.CheckpointedInputGate.handleEvent(CheckpointedInputGate.java:180) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.CheckpointedInputGate.pollNext(CheckpointedInputGate.java:157) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.StreamTaskNetworkInput.emitNext(StreamTaskNetworkInput.java:179) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.io.StreamOneInputProcessor.processInput(StreamOneInputProcessor.java:65) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.processInput(StreamTask.java:396) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMailboxLoop(MailboxProcessor.java:191) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.runMailboxLoop(StreamTask.java:617) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:581) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:755) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.run(Task.java:570) [flink-dist_2.11-1.12.3.jar:1.12.3] at java.lang.Thread.run(Thread.java:750) [?:1.8.0_362] Suppressed: java.lang.RuntimeException: com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.connector.flink.manager.StarRocksSinkManagerV2.AssertNotException(StarRocksSinkManagerV2.java:367) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.connector.flink.manager.StarRocksSinkManagerV2.flush(StarRocksSinkManagerV2.java:299) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.connector.flink.table.sink.StarRocksDynamicSinkFunctionV2.close(StarRocksDynamicSinkFunctionV2.java:184) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at org.apache.flink.api.common.functions.util.FunctionUtils.closeFunction(FunctionUtils.java:41) ~[roi-flinksql-custom-1.0-SNAPSHOT.jar:?] at org.apache.flink.streaming.api.operators.AbstractUdfStreamOperator.dispose(AbstractUdfStreamOperator.java:117) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.disposeAllOperators(StreamTask.java:791) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.runAndSuppressThrowable(StreamTask.java:770) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.cleanUpInvoke(StreamTask.java:689) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:593) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:755) [flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.runtime.taskmanager.Task.run(Task.java:570) [flink-dist_2.11-1.12.3.jar:1.12.3] at java.lang.Thread.run(Thread.java:750) [?:1.8.0_362] Caused by: com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." } errorLog: null at com.starrocks.data.load.stream.DefaultStreamLoader.send(DefaultStreamLoader.java:289) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at com.starrocks.data.load.stream.DefaultStreamLoader.lambda$send$2(DefaultStreamLoader.java:120) ~[flink-connector-starrocks-1.2.7_flink-1.12_2.11.jar:?] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_362] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_362] ... 1 more Caused by: org.apache.flink.runtime.checkpoint.CheckpointException: Could not complete snapshot 1 for operator Sink: Sink(table=[default_catalog.default_database.sink_rt_dau_pvreport2sr], fields=[day, EXPR$1, client_act_time, is_client_act, ts, EXPR$5]) (1/1)#0. Failure reason: Checkpoint was declined. at org.apache.flink.streaming.api.operators.StreamOperatorStateHandler.snapshotState(StreamOperatorStateHandler.java:241) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.api.operators.StreamOperatorStateHandler.snapshotState(StreamOperatorStateHandler.java:162) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.api.operators.AbstractStreamOperator.snapshotState(AbstractStreamOperator.java:371) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.SubtaskCheckpointCoordinatorImpl.checkpointStreamOperator(SubtaskCheckpointCoordinatorImpl.java:686) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.SubtaskCheckpointCoordinatorImpl.buildOperatorSnapshotFutures(SubtaskCheckpointCoordinatorImpl.java:607) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.SubtaskCheckpointCoordinatorImpl.takeSnapshotSync(SubtaskCheckpointCoordinatorImpl.java:572) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.SubtaskCheckpointCoordinatorImpl.checkpointState(SubtaskCheckpointCoordinatorImpl.java:298) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.lambda$performCheckpoint$9(StreamTask.java:1004) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTaskActionExecutor$1.runThrowing(StreamTaskActionExecutor.java:50) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.performCheckpoint(StreamTask.java:988) ~[flink-dist_2.11-1.12.3.jar:1.12.3] at org.apache.flink.streaming.runtime.tasks.StreamTask.triggerCheckpointOnBarrier(StreamTask.java:947) ~[flink-dist_2.11-1.12.3.jar:1.12.3] ... 13 more Caused by: org.apache.flink.util.SerializedThrowable: com.starrocks.data.load.stream.exception.StreamLoadFailException: Stream load failed because of error, db: s_rpt, table: rpt_rt_dau_dim, label: 26639e7c-856e-477f-896f-d2ba3bb37f66, responseBody: { "Status": "INTERNAL_ERROR", "Message": "The size of this batch exceed the max size [104857600] of json type data data [ 106097396 ]. Set ignore_json_size to skip the check, although it may lead huge memory consuming." }
06-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值