一些方法
图片压缩
图片压缩
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);
}
}