import * as QS from 'qs'; import { requestInstance } from 'common/request'; import { App } from 'utils/types'; const NOSCONFIG = { DOMAIN: window.location.host, FROM: 'szcp', MAX_SIZE: 10000000, UPLOAD_TYPE: 'cms', }; const PIC_UPLOAD_URL = '//upfile.m.163.com/nos/upload/pub'; const PIC_BATCH_UPLOAD_URL = '//upload.ws.126.net/batchUploadImgUrl'; const PIC_SUFFIX_REG = /(gif|png|jpe?g)$/; const DEFAULT_TARGET_SIZE = { targetWidth: 0, targetHeight: 0, }; const DEFAULT_MAX_SIZE = { maxWidth: 0, maxHeight: 0, }; /** * 图片类 * @param {string} url * @param {string} id * @returns */ const Img = (url: string, id: string) => ({ id, src: url, status: 0, // 0: 失败, 1: 成功, 2: 上传中 }); /** * 生成图片ID * @param {number} index * @returns */ const genImageId = (index = 0) => `dingyue_${index}_${new Date().valueOf()}`; /** * 图片预加载 * @param {String} url * @returns */ const loadImageAsync = (url: string) => new Promise((resolve, reject) => { const image = new Image(); image.onload = () => { resolve(image); }; image.onerror = () => { reject(new Error(`Could not load image at ${url}`)); }; image.src = url; }); /** * 图片转Canvas * @param {Image} image * @returns */ const imageToCanvas = (image: any, targetSize = DEFAULT_TARGET_SIZE) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const { targetWidth, targetHeight } = targetSize; const { width, height } = image; if (targetWidth && targetHeight) { canvas.width = targetWidth; canvas.height = targetHeight; } else { canvas.width = width; canvas.height = height; } (ctx as CanvasRenderingContext2D).drawImage(image, 0, 0, width, height); return canvas; }; /** * 图片转Blob Promise * @param {Image} image */ const imageToBlobAsync = ( image: any, quality: number, targetSize = DEFAULT_TARGET_SIZE, ) => new Promise((resolve) => { imageToCanvas(image, targetSize).toBlob((blob) => resolve(blob), `${quality}`, 'image/jpg'); }); /** * 图片转base64 Promise * @param {Image} image * @returns */ const imageToBase64 = ( image: any, targetSize = DEFAULT_TARGET_SIZE, ) => imageToCanvas(image, targetSize).toDataURL(); /** * 图片校验 * @param {File} file * @param {String} type file, base64 * @returns {String} 错误 */ const verifyImage = (file: File, type?: string) => { let result = ''; if (!file || (type === 'file' && !file.size)) { result = '文件不存在'; } if (!PIC_SUFFIX_REG.test(file.type)) { result = `${file.name}文件类型错误`; } if (type === 'file' && file.size >= NOSCONFIG.MAX_SIZE) { result = `文件大小不可以超过${(NOSCONFIG.MAX_SIZE / 1) * 1000 * 1000}M`; } return result; }; /** * 前端压缩图片 * @param {Image} image * @param {{ targetWidth: Number, targetHeight: Number }} maxSize * @returns targetWidth 压缩后宽度 targetHeight 压缩后高度 */ const compressImage = (image: { width: number; height: number; }, maxSize = DEFAULT_MAX_SIZE) => { const { width, height } = image; const { maxWidth, maxHeight } = maxSize; let targetWidth = width; let targetHeight = height; if (maxWidth) { if (width > maxWidth) { targetWidth = maxWidth; targetHeight = height / (width / maxWidth); } } else if (maxHeight) { if (height > maxHeight) { targetHeight = maxHeight; targetWidth = width / (height / maxHeight); } } return { targetWidth, targetHeight, }; }; /** * 图片上传 * @param {File} file * @param {Function} onSuccess 上传成功回调 * @param {Function} onFail 上传失败回调 * @param {Object} config 配置 * @returns {Promise} */ const uploadImg = ( file: string | Blob, config: App.ImageUploadConfig = { type: App.ImageType.FILE, id: '', logotext: '', name: '', }, ): Promise => new Promise((resolve, reject) => { const { type, id, logotext, } = config; // 构建请求参数 const data = new FormData(); if (type === App.ImageType.BASE64) { data.append('uploadtype', 'base64'); data.append('body', file); } else { const verifyImageResult = verifyImage(file as File); if (verifyImageResult) { reject(new Error(verifyImageResult)); } data.append('file', file); } data.append('from', NOSCONFIG.FROM); if (logotext) data.append('logotext', logotext); requestInstance.request({ url: PIC_UPLOAD_URL, data, method: 'POST', headers: { 'Content-Type': 'multipart/form-data', }, }).then((rs: any) => { resolve({ url: rs.url, id }); }); }); interface BatchUploadImgUrlRes { data: App.Dict, errmsg: App.Dict, } const batchUploadImgUrl = (urls: string[], other = {}) => { const params = { uploadtype: NOSCONFIG.UPLOAD_TYPE, from: NOSCONFIG.FROM, bucketName: 'dingyue', urls, ...other, }; return requestInstance.request({ url: PIC_BATCH_UPLOAD_URL, data: QS.stringify(params, { arrayFormat: 'repeat' }), method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded;', }, }).then((rs: BatchUploadImgUrlRes) => { const { data, errmsg } = rs; const srcMap = data || {}; urls.forEach((url: string) => { if (errmsg[url]) { srcMap[url] = null; } }); return Promise.resolve(srcMap); }); }; export { Img, genImageId, loadImageAsync, verifyImage, imageToBlobAsync, imageToCanvas, imageToBase64, compressImage, uploadImg, batchUploadImgUrl, };