Skip to content
本页目录

一些方法

图片压缩

图片压缩
ts
const fileToDataURL = (file: Blob): Promise<any> => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = (e) => resolve((e.target as FileReader).result);
    reader.readAsDataURL(file);
  });
};
const dataURLToImage = (dataURL: string): Promise<HTMLImageElement> => {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.src = dataURL;
  });
};
const canvastoFile = (canvas: HTMLCanvasElement, type: string, quality: number): Promise<Blob | null> => {
  return new Promise((resolve) => canvas.toBlob((blob) => resolve(blob), type, quality));
};
/**
 * 图片压缩方法
 * @param {Object}  file 图片文件
 * @param {String} type 想压缩成的文件类型
 * @param {Nubmber} quality 压缩质量参数
 * @returns 压缩后的新图片
 */
export const compressionFile = async(file, type = "image/jpeg", quality = 0.5) => {
  const fileName = file.name;
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d") as CanvasRenderingContext2D;
  const base64 = await fileToDataURL(file);
  const img = await dataURLToImage(base64);
  canvas.width = img.width;
  canvas.height = img.height;
  context.clearRect(0, 0, img.width, img.height);
  context.drawImage(img, 0, 0, img.width, img.height);
  const blob = (await canvastoFile(canvas, type, quality)) as Blob; // quality:0.5可根据实际情况计算
  const newFile = await new File([blob], fileName, {
    type: type
  });
  return newFile;
};
js
/**
   * 压缩图片方法
   * @param {file} file 文件
   * @param {Number} quality 图片质量(取值0-1之间默认0.92)
   */
  compressImg(file, quality) {
    var qualitys = 0.52
    console.log(parseInt((file.size / 1024).toFixed(2)))
    if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
      qualitys = 0.85
    }
    if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
      qualitys = 0.92
    }
    if (quality) {
      qualitys = quality
    }
    if (file[0]) {
      return Promise.all(Array.from(file).map(e => this.compressImg(e,
        qualitys))) // 如果是 file 数组返回 Promise 数组
    } else {
      return new Promise((resolve) => {
        console.log(file)
        if ((file.size / 1024).toFixed(2) < 300) {
          resolve({
            file: file
          })
        } else {
          const reader = new FileReader() // 创建 FileReader
          reader.onload = ({
            target: {
              result: src
            }
          }) => {
            const image = new Image() // 创建 img 元素
            image.onload = async() => {
              const canvas = document.createElement('canvas') // 创建 canvas 元素
              const context = canvas.getContext('2d')
              var targetWidth = image.width
              var targetHeight = image.height
              var originWidth = image.width
              var originHeight = image.height
              if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
                var maxWidth = 1600
                var maxHeight = 1600
                targetWidth = originWidth
                targetHeight = originHeight
                // 图片尺寸超过的限制
                if (originWidth > maxWidth || originHeight > maxHeight) {
                  if (originWidth / originHeight > maxWidth / maxHeight) {
                    // 更宽,按照宽度限定尺寸
                    targetWidth = maxWidth
                    targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                  } else {
                    targetHeight = maxHeight
                    targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                  }
                }
              }
              if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
                maxWidth = 1400
                maxHeight = 1400
                targetWidth = originWidth
                targetHeight = originHeight
                // 图片尺寸超过的限制
                if (originWidth > maxWidth || originHeight > maxHeight) {
                  if (originWidth / originHeight > maxWidth / maxHeight) {
                    // 更宽,按照宽度限定尺寸
                    targetWidth = maxWidth
                    targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                  } else {
                    targetHeight = maxHeight
                    targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                  }
                }
              }
              canvas.width = targetWidth
              canvas.height = targetHeight
              context.clearRect(0, 0, targetWidth, targetHeight)
              context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
              const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
              const buffer = atob(canvasURL.split(',')[1])
              let length = buffer.length
              const bufferArray = new Uint8Array(new ArrayBuffer(length))
              while (length--) {
                bufferArray[length] = buffer.charCodeAt(length)
              }
              const miniFile = new File([bufferArray], file.name, {
                type: 'image/jpeg'
              })
              console.log({
                file: miniFile,
                origin: file,
                beforeSrc: src,
                afterSrc: canvasURL,
                beforeKB: Number((file.size / 1024).toFixed(2)),
                afterKB: Number((miniFile.size / 1024).toFixed(2)),
                qualitys: qualitys
              })
              resolve({
                file: miniFile,
                origin: file,
                beforeSrc: src,
                afterSrc: canvasURL,
                beforeKB: Number((file.size / 1024).toFixed(2)),
                afterKB: Number((miniFile.size / 1024).toFixed(2))
              })
            }
            image.src = src
          }
          reader.readAsDataURL(file)
        }
      })
    }
  },

常用表单校验

常用表单校验
ts
// 身份证号码验证
export const validateCardId = (rule: any, value: any, callback: any) => {
  if (!value) callback(new Error('请填写身份证号码'))
  else if (cnid(value)) callback()
  else callback('请填写正确的身份证号码')
}

// 手机号码验证
export const validatePhone = (rule: any, value: string, callback: any) => {
  const phone = getItem<string>(TEMP_STORAGE_ENUM.PHONE, sessionStorage)
  const reg
    = /^(0|86|17951)?(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
  if (!value) callback(new Error('请填写手机号'))
  else if (phone === value) callback()
  else if (value.includes('*') && value.length === 11) callback()
  else if (reg.test(value)) callback()
  else callback(new Error('请填写正确的手机号'))
}

// 手机号码验证(非必填)
export const validatePhoneNotRequire = (
  rule: any,
  value: any,
  callback: any,
) => {
  if (!value) {
    callback()
  }
  else {
    const reg
      = /^(0|86|17951)?(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
    if (reg.test(value)) callback()
    else callback(new Error('请填写正确的手机号'))
  }
}

// 身份证号码验证(非必填)
export const validateCardIdNotRequire = (
  rule: any,
  value: any,
  callback: any,
) => {
  if (!value) callback()
  else if (cnid(value)) callback()
  else callback('请填写正确的身份证号码')
}

// 密码验证
export const validatePassword = (rule: any, value: string, callback: any) => {
  const passWord = getItem<string>(TEMP_STORAGE_ENUM.PWS, sessionStorage)
  const reg = /^(?=.*\d)(?=.*[A-Z])[\da-zA-Z]{8,16}$/
  if (passWord === value) {
    callback()
  }
  else if (value?.length) {
    if (reg.test(value)) callback()
    else callback(new Error('长度8-16位字符, 必须包含数字及大小写英文'))
  }
  else {
    callback()
  }
}

// IP地址验证
export const validateIP = (rule: any, value: any, callback: any) => {
  if (!value) {
    callback(new Error('请输入IP地址'))
  }
  else {
    const reg
      = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
    if (reg.test(value)) callback()
    else callback(new Error('输入正确的IP地址'))
  }
}

// 端口号验证
export const validatePort = (rule: any, value: any, callback: any) => {
  const reg = /^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5]))$/
  if (!value) callback(new Error('请输入端口号'))
  else if (reg.test(value)) callback()
  else callback(new Error('请输入正确的端口号'))
}

// 判断是否是链接
export function isLink(str: string) {
  // 创建一个正则表达式来匹配链接
  const regexp = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[:?\d]*)\S*$/
  return regexp.test(str)
}

// 判断字符串数组是否为空数组
export function isNullArray(rule: any, value: [], callback: any) {
  if (!value) {
    callback(new Error('请输入'))
  }
  else if (value.length > 0) {
    value.forEach((item) => {
      if (item === '') callback(new Error('不能为空'))
      else callback()
    })
  }
  else {
    callback()
  }
}

// 施工许可证校验
export const validateConstruction = (rule: any, value: any, callback: any) => {
  const reg = /^\d{18}$/
  if (reg.test(value)) callback()
  else callback(new Error('施工许可证号长度为 18 位数字'))
}
// 统一社会信用代码由18位数字或大写拉丁字母组成
export const validateCorpCode = (rule: any, value: any, callback: any) => {
  const reg = /^(\d|[A-Z]){18}$/
  if (reg.test(value)) callback()
  else callback(new Error('统一社会信用代码为 18 位数字或大写拉丁字母'))
}

// 邮政编码校验
export const validatePostalCode = (rule: any, value: any, callback: any) => {
  if (String(value).length === 6) callback()
  else callback(new Error('邮政编码长度为6位数'))
}
身份证号码校验规则
ts
class CheckCardId {
  private _normalize(id: string) {
    id = id.toUpperCase().replace(/\[-\/\s]/g, '')
    if (/\([A-Z0-9]\)$/.test(id)) {
      id = id.replace(/\[\(\)]/g, '')
    }

    return id
  }

  private _isDateValid(idDate: string, minDate?: string | number | Date, maxDate?: string | number | Date) {
    const isFormatValid = (date: string) => {
      return typeof date === 'string' && /^[0-9]{8}$/.test(date)
    }

    const parseDate = (input: string) => {
      let startIndex = 0
      const year = +input.substring(startIndex, (startIndex += 4))
      const month = input.substring(startIndex, (startIndex += 2))
      const day = +input.substring(startIndex, (startIndex += 2))
      const date = new Date(year, +month - 1, day)

      let maxDay: number
      if ('01,03,05,07,08,10,12'.includes(month)) {
        maxDay = 31
      }
      else if ('04,06,09,11'.includes(month)) {
        maxDay = 30
      }
      else if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
        maxDay = 29
      }
      else {
        maxDay = 28
      }

      const isDayValid = day > 0 && day <= maxDay
      const isMonthValid = +month > 0 && +month <= 12
      const isFutureDate = new Date() < date

      if (!isDayValid) {
        return false
      }
      if (!isMonthValid) {
        return false
      }
      if (isFutureDate) {
        return false
      }

      return date
    }

    const formatData = (input: string | number | Date) => {
      const date = new Date(input)
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      return year + month + day
    }

    minDate = formatData(minDate || '1800/01/01')
    maxDate = formatData(maxDate || Date.now())

    if (!isFormatValid(idDate)) {
      return false
    }
    if (!isFormatValid(minDate)) {
      return false
    }
    if (!isFormatValid(maxDate)) {
      return false
    }
    if (!parseDate(idDate)) {
      return false
    }
    if (!parseDate(minDate)) {
      return false
    }
    if (!parseDate(maxDate)) {
      return false
    }

    return idDate >= minDate && idDate <= maxDate
  }

  public cnid(id: string) {
    const isLengthValid = (id: string) => id.length === 18
    const isFormatValid = (id: string) => /^[0-9]{17}[0-9X]$/.test(id)
    const isChecksumValid = (id: string) => {
      const identifier = id.slice(0, -1)
      const checkDigit = id.slice(-1) === 'X' ? 10 : +id.slice(-1)
      const getWeight = (n: number) => 2 ** (n - 1) % 11
      let weightedSum = 0
      let index = id.length
      for (let i = 0; i < identifier.length; i++) {
        const char = identifier[i]
        weightedSum += +char * getWeight(index)
        index--
      }
      const remainder = ((12 - (weightedSum % 11)) % 11) - checkDigit
      return remainder === 0
    }
    id = this._normalize(id)
    return isLengthValid(id) && isFormatValid(id) && this._isDateValid(id.substring(6, 14)) && isChecksumValid(id)
  }

  public twid(id: string) {
    const isLengthValid = (id: string) => id.length === 10
    const isFormatValid = (id: string) => /^[A-Z][12][0-9]{8}$/.test(id)
    const isChecksumValid = (id: string) => {
      const idLen = id.length
      const letters = 'ABCDEFGHJKLMNPQRSTUVXYWZIO'
      const letterIndex = letters.indexOf(id[0]) + 10
      const letterValue = Math.floor(letterIndex / 10) + (letterIndex % 10) * (idLen - 1)
      const idTail = id.slice(1)
      let weight = idLen - 2
      let weightedSum = 0
      for (let i = 0, len = idTail.length; i < len; i++) {
        const char = idTail[i]
        weightedSum += +char * weight
        weight--
      }
      const remainder = (letterValue + weightedSum + +id.slice(-1)) % 10
      return remainder === 0
    }
    id = this._normalize(id)
    return isLengthValid(id) && isFormatValid(id) && isChecksumValid(id)
  }

  public hkid(id: string) {
    const isLengthValid = (id: string) => id.length === 8 || id.length === 9
    const isFormatValid = (id: string) => /^[A-MP-Z]{1,2}[0-9]{6}[0-9A]$/.test(id)
    const getLetterValue = (letter: string) => letter.charCodeAt(0) - 64
    const isLetter = (char: string) => /[a-zA-Z]/.test(char)
    const isChecksumValid = (id: string) => {
      let weight = id.length
      let weightedSum = 0
      const identifier = id.slice(0, -1)
      const checkDigit = id.slice(-1) === 'A' ? 10 : +id.slice(-1)
      for (let i = 0, len = identifier.length; i < len; i++) {
        const char = identifier[i]
        const charValue = isLetter(char) ? getLetterValue(char) : +char
        weightedSum += charValue * weight
        weight--
      }
      const remainder = (weightedSum + checkDigit) % 11
      return remainder === 0
    }
    id = this._normalize(id)
    return isLengthValid(id) && isFormatValid(id) && isChecksumValid(id)
  }
}

const checkCardId = new CheckCardId()

export { CheckCardId as default, checkCardId }

文件下载

文件下载
ts
import { ElMessage } from "element-plus";

export async function exportFile(
  fun: (...args: any) => Promise<any>,
  params = {},
  name = String(Date.now()),
  suffix = ".xls"
) {
  try {
    const res = await fun({ ...params });
    const type =
      res?.type ||
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    const blob = new Blob([res], { type });
    const fileName = name + suffix;
    const url = window.URL.createObjectURL(blob);
    if ("download" in document.createElement("a")) {
      const a = document.createElement("a");
      a.href = url;
      a.download = fileName;
      a.style.display = "none";
      document.body.appendChild(a);
      a.click();
      URL.revokeObjectURL(a.href);
      document.body.removeChild(a);
    } else {
      const nav = window.navigator as any;
      nav.msSaveBlob(blob, fileName);
    }
    ElMessage({ type: "success", message: "导出成功" });
  } catch (error: any) {
    ElMessage({ type: "error", message: error });
  }
}

/** 下载文件 */
export function downLoadFile(url: string, fileName = "") {
  if ("download" in document.createElement("a")) {
    // 支持a标签download的浏览器
    const link = document.createElement("a"); // 创建a标签
    if (fileName) link.download = fileName; // a标签添加属性

    link.style.display = "none";
    link.href = url;
    // console.log(link)
    document.body.appendChild(link);
    link.click(); // 执行下载
    URL.revokeObjectURL(link.href); // 释放url
    document.body.removeChild(link); // 释放标签
  } else {
    fileName
      ? (navigator as any)?.msSaveBlob(url, fileName)
      : (navigator as any)?.msSaveBlob(url);
  }
}

export async function dowloadFile(
  fun: any,
  params = {},
  name = String(Date.now()),
  fix = ".xls"
) {
  try {
    const res = await fun({ ...params });
    const blob = new Blob([res], { type: res?.type });
    const fileName = name + fix;
    const url = window.URL.createObjectURL(blob);
    if ("download" in document.createElement("a")) {
      const a = document.createElement("a");
      a.href = url;
      if (fileName) a.download = fileName;
      a.style.display = "none";
      document.body.appendChild(a);
      a.click();
      URL.revokeObjectURL(a.href);
      document.body.removeChild(a);
    } else {
      fileName
        ? (navigator as any).msSaveBlob(blob, fileName)
        : (navigator as any).msSaveBlob(blob);
    }
    return Promise.resolve(res);
  } catch (error) {
    return Promise.reject(error);
  }
}

/**
 * 下载base64图片
 * @param base 
 * @param name 
 * @param fix 
 * @returns 
 */
export async function DowloadFile(
  base: any,
  name = String(Date.now()),
  fix = ".png"
) {
  try {
    const parts = base.split(";base64,");
    const contentType = parts[0].split(":")[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    const blob = new Blob([uInt8Array], { type: contentType });
    console.log(blob);
    const fileName = name + fix;
    const url = window.URL.createObjectURL(blob);
    if ("download" in document.createElement("a")) {
      const a = document.createElement("a");
      a.href = url;
      if (fileName) a.download = fileName;
      a.style.display = "none";
      document.body.appendChild(a);
      a.click();
      URL.revokeObjectURL(a.href);
      document.body.removeChild(a);
    } else {
      fileName
        ? (navigator as any).msSaveBlob(blob, fileName)
        : (navigator as any).msSaveBlob(blob);
    }
    return Promise.resolve(base);
  } catch (error) {
    return Promise.reject(error);
  }
}