|
|
@@ -1,569 +0,0 @@
|
|
|
-/** 公共方法类 */
|
|
|
-import CryptoJs from 'crypto-js'
|
|
|
-import encHex from 'crypto-js/enc-hex'
|
|
|
-
|
|
|
-/**
|
|
|
- * 人性化时间显示
|
|
|
- *
|
|
|
- * @param {Object} datetime
|
|
|
- */
|
|
|
-export function formateTime(datetime) {
|
|
|
- if (datetime === null) return ''
|
|
|
-
|
|
|
- datetime = datetime.replace(/-/g, '/')
|
|
|
-
|
|
|
- const time = new Date()
|
|
|
- let outTime = new Date(datetime)
|
|
|
- if (/^[1-9]\d*$/.test(datetime)) {
|
|
|
- outTime = new Date(parseInt(datetime) * 1000)
|
|
|
- }
|
|
|
-
|
|
|
- if (
|
|
|
- time.getTime() < outTime.getTime() ||
|
|
|
- time.getFullYear() === outTime.getFullYear()
|
|
|
- ) {
|
|
|
- return parseTime(outTime, '{y}-{m}-{d} {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getMonth() !== outTime.getMonth()) {
|
|
|
- return parseTime(outTime, '{m}-{d} {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getDate() !== outTime.getDate()) {
|
|
|
- const day = outTime.getDate() - time.getDate()
|
|
|
- if (day === -1) {
|
|
|
- return parseTime(outTime, '昨天 {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- if (day === -2) {
|
|
|
- return parseTime(outTime, '前天 {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- return parseTime(outTime, '{m}-{d} {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- const diff = time.getTime() - outTime.getTime()
|
|
|
-
|
|
|
- if (time.getHours() !== outTime.getHours() || diff > 30 * 60 * 1000) {
|
|
|
- return parseTime(outTime, '{h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- let minutes = outTime.getMinutes() - time.getMinutes()
|
|
|
- if (minutes === 0) {
|
|
|
- return '刚刚'
|
|
|
- }
|
|
|
-
|
|
|
- minutes = Math.abs(minutes)
|
|
|
- return `${minutes}分钟前`
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 格式化文件大小
|
|
|
- *
|
|
|
- * @param {String} value 文件大小(字节)
|
|
|
- */
|
|
|
-export function formateSize(value) {
|
|
|
- if (value === null || value === '') {
|
|
|
- return '0'
|
|
|
- }
|
|
|
- const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
|
- let index = 0
|
|
|
- const srcsize = parseFloat(value)
|
|
|
- index = Math.floor(Math.log(srcsize) / Math.log(1000))
|
|
|
- let size = srcsize / Math.pow(1000, index)
|
|
|
- size = size.toFixed(2) // 保留的小数位数
|
|
|
- return size + unitArr[index]
|
|
|
-}
|
|
|
-/**
|
|
|
- * 获取文件后缀名
|
|
|
- *
|
|
|
- * @param {String} fileName
|
|
|
- */
|
|
|
-export function getFileExt(fileName) {
|
|
|
- let ext = fileName.split('.')
|
|
|
- ext = ext[ext.length - 1] // 获取文件后缀名
|
|
|
- return ext
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 根据图片url下载图片
|
|
|
- * @param {String} imgsrc
|
|
|
- * @param {String} name
|
|
|
- */
|
|
|
-export function downloadIamge(imgsrc, name) {
|
|
|
- // 下载图片地址和图片名
|
|
|
- const image = new Image()
|
|
|
- // 解决跨域 Canvas 污染问题
|
|
|
- image.setAttribute('crossOrigin', 'anonymous')
|
|
|
- image.onload = function() {
|
|
|
- const canvas = document.createElement('canvas')
|
|
|
- canvas.width = image.width
|
|
|
- canvas.height = image.height
|
|
|
- const context = canvas.getContext('2d')
|
|
|
- context.drawImage(image, 0, 0, image.width, image.height)
|
|
|
- const url = canvas.toDataURL('image/png') // 得到图片的base64编码数据
|
|
|
- const a = document.createElement('a') // 生成一个a元素
|
|
|
- const event = new MouseEvent('click') // 创建一个单击事件
|
|
|
- a.download = name || 'photo' // 设置图片名称
|
|
|
- a.href = url // 将生成的URL设置为a.href属性
|
|
|
- a.dispatchEvent(event) // 触发a的单击事件
|
|
|
- }
|
|
|
- image.src = imgsrc
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 通过图片url获取图片大小
|
|
|
- *
|
|
|
- * @param {String} imgsrc 例如图片名: D8x5f13a53dbc4b9_350x345.png
|
|
|
- */
|
|
|
-export function getImageInfo(imgsrc) {
|
|
|
- const data = {
|
|
|
- width: 0,
|
|
|
- height: 0
|
|
|
- }
|
|
|
-
|
|
|
- const arr = imgsrc.split('_')
|
|
|
- if (arr.length === 1) return data
|
|
|
-
|
|
|
- let info = arr[arr.length - 1].match(/\d+x\d+/g)
|
|
|
- if (info === null) return data
|
|
|
-
|
|
|
- info = info[0].split('x')
|
|
|
- return {
|
|
|
- width: parseInt(info[0]),
|
|
|
- height: parseInt(info[1])
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 时间格式化方法
|
|
|
- *
|
|
|
- * @param {(Object|string|number)} time
|
|
|
- * @param {String} cFormat
|
|
|
- * @returns {String | null}
|
|
|
- */
|
|
|
-export function parseTime(time, cFormat) {
|
|
|
- if (arguments.length === 0) {
|
|
|
- return null
|
|
|
- }
|
|
|
-
|
|
|
- let date
|
|
|
- const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
|
|
|
-
|
|
|
- if (typeof time === 'object') {
|
|
|
- date = time
|
|
|
- } else {
|
|
|
- if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
|
|
|
- time = parseInt(time)
|
|
|
- }
|
|
|
- if (typeof time === 'number' && time.toString().length === 10) {
|
|
|
- time = time * 1000
|
|
|
- }
|
|
|
-
|
|
|
- date = new Date(time.replace(/-/g, '/'))
|
|
|
- }
|
|
|
-
|
|
|
- const formatObj = {
|
|
|
- y: date.getFullYear(),
|
|
|
- m: date.getMonth() + 1,
|
|
|
- d: date.getDate(),
|
|
|
- h: date.getHours(),
|
|
|
- i: date.getMinutes(),
|
|
|
- s: date.getSeconds(),
|
|
|
- a: date.getDay()
|
|
|
- }
|
|
|
-
|
|
|
- const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
|
|
|
- const value = formatObj[key]
|
|
|
- // Note: getDay() returns 0 on Sunday
|
|
|
- if (key === 'a') {
|
|
|
- return ['日', '一', '二', '三', '四', '五', '六'][value]
|
|
|
- }
|
|
|
-
|
|
|
- return value.toString().padStart(2, '0')
|
|
|
- })
|
|
|
-
|
|
|
- return time_str
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 去除字符串控制
|
|
|
- *
|
|
|
- * @param {String} str
|
|
|
- */
|
|
|
-export function trim(str, type = null) {
|
|
|
- if (type) {
|
|
|
- return str.replace(/(^\s*)|(\s*$)/g, '')
|
|
|
- } else if (type === 'l') {
|
|
|
- return str.replace(/(^\s*)/g, '')
|
|
|
- } else {
|
|
|
- return str.replace(/(\s*$)/g, '')
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 解析url中参数
|
|
|
- *
|
|
|
- * @param {String} url
|
|
|
- * @returns {Object}
|
|
|
- */
|
|
|
-export function param2Obj(url) {
|
|
|
- const search = url.split('?')[1]
|
|
|
-
|
|
|
- if (!search) return {}
|
|
|
-
|
|
|
- return JSON.parse(
|
|
|
- '{"' +
|
|
|
- decodeURIComponent(search)
|
|
|
- .replace(/"/g, '\\"')
|
|
|
- .replace(/&/g, '","')
|
|
|
- .replace(/=/g, '":"')
|
|
|
- .replace(/\+/g, ' ') +
|
|
|
- '"}'
|
|
|
- )
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * @param {Object} json
|
|
|
- * @returns {Array}
|
|
|
- */
|
|
|
-export function param(json) {
|
|
|
- if (!json) return ''
|
|
|
- return cleanArray(
|
|
|
- Object.keys(json).map(key => {
|
|
|
- if (json[key] === undefined) return ''
|
|
|
-
|
|
|
- return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
|
|
|
- })
|
|
|
- ).join('&')
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * @param {Array} actual
|
|
|
- * @returns {Array}
|
|
|
- */
|
|
|
-export function cleanArray(actual) {
|
|
|
- const newArray = []
|
|
|
- for (let i = 0; i < actual.length; i++) {
|
|
|
- if (actual[i]) {
|
|
|
- newArray.push(actual[i])
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return newArray
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * @param {HTMLElement} element
|
|
|
- * @param {String} className
|
|
|
- */
|
|
|
-export function toggleClass(element, className) {
|
|
|
- if (!element || !className) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let classString = element.className
|
|
|
- const nameIndex = classString.indexOf(className)
|
|
|
- if (nameIndex === -1) {
|
|
|
- classString += '' + className
|
|
|
- } else {
|
|
|
- classString =
|
|
|
- classString.substr(0, nameIndex) +
|
|
|
- classString.substr(nameIndex + className.length)
|
|
|
- }
|
|
|
- element.className = classString
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Check if an element has a class
|
|
|
- *
|
|
|
- * @param {HTMLElement} elm
|
|
|
- * @param {String} cls
|
|
|
- * @returns {Boolean}
|
|
|
- */
|
|
|
-export function hasClass(ele, cls) {
|
|
|
- return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Add class to element
|
|
|
- *
|
|
|
- * @param {HTMLElement} elm
|
|
|
- * @param {String} cls
|
|
|
- */
|
|
|
-export function addClass(ele, cls) {
|
|
|
- if (!hasClass(ele, cls)) ele.className += ' ' + cls
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Remove class from element
|
|
|
- *
|
|
|
- * @param {HTMLElement} elm
|
|
|
- * @param {String} cls
|
|
|
- */
|
|
|
-export function removeClass(ele, cls) {
|
|
|
- if (hasClass(ele, cls)) {
|
|
|
- const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
|
|
|
- ele.className = ele.className.replace(reg, ' ')
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 通过图片Url获取图片等比例缩放的宽度和高度信息
|
|
|
- *
|
|
|
- * @param {String} src
|
|
|
- * @param {Number} width
|
|
|
- */
|
|
|
-export function imgZoom(src, width = 200) {
|
|
|
- const info = getImageInfo(src)
|
|
|
-
|
|
|
- if (info.width < width) {
|
|
|
- return {
|
|
|
- width: `${info.width}px`,
|
|
|
- height: `${info.height}px`
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- width: width + 'px',
|
|
|
- height: parseInt(info.height / (info.width / width)) + 'px'
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 获取浏览器光标选中内容
|
|
|
- *
|
|
|
- * @export
|
|
|
- * @returns
|
|
|
- */
|
|
|
-export function getSelection() {
|
|
|
- return window.getSelection
|
|
|
- ? window.getSelection().toString()
|
|
|
- : document.selection.createRange().text
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 剪贴板复制功能
|
|
|
- *
|
|
|
- * @param {String} value 复制内容
|
|
|
- * @param {Function} callback 复制成功回调方法
|
|
|
- */
|
|
|
-export const copyTextToClipboard = (value, callback) => {
|
|
|
- const textArea = document.createElement('textarea')
|
|
|
- textArea.style.background = 'transparent'
|
|
|
- textArea.value = value
|
|
|
-
|
|
|
- document.body.appendChild(textArea)
|
|
|
-
|
|
|
- textArea.select()
|
|
|
-
|
|
|
- try {
|
|
|
- document.execCommand('copy')
|
|
|
- if (callback) callback()
|
|
|
- } catch (err) {
|
|
|
- alert('Oops, unable to copy')
|
|
|
- }
|
|
|
-
|
|
|
- document.body.removeChild(textArea)
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 隐藏用户手机号中间四位
|
|
|
- *
|
|
|
- * @param {String} phone 手机号
|
|
|
- */
|
|
|
-export function hidePhone(phone) {
|
|
|
- return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 人性化显示时间
|
|
|
- *
|
|
|
- * @param {Object} datetime
|
|
|
- */
|
|
|
-export function beautifyTime(datetime = '') {
|
|
|
- if (datetime === null) {
|
|
|
- return ''
|
|
|
- }
|
|
|
-
|
|
|
- datetime = datetime.replace(/-/g, '/')
|
|
|
-
|
|
|
- const time = new Date()
|
|
|
- let outTime = new Date(datetime)
|
|
|
- if (/^[1-9]\d*$/.test(datetime)) {
|
|
|
- outTime = new Date(parseInt(datetime) * 1000)
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getTime() < outTime.getTime()) {
|
|
|
- return parseTime(outTime, '{y}/{m}/{d}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getFullYear() !== outTime.getFullYear()) {
|
|
|
- return parseTime(outTime, '{y}/{m}/{d}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getMonth() !== outTime.getMonth()) {
|
|
|
- return parseTime(outTime, '{m}/{d}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getDate() !== outTime.getDate()) {
|
|
|
- const day = outTime.getDate() - time.getDate()
|
|
|
- if (day === -1) {
|
|
|
- return parseTime(outTime, '昨天 {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- if (day === -2) {
|
|
|
- return parseTime(outTime, '前天 {h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- return parseTime(outTime, '{m}-{d}')
|
|
|
- }
|
|
|
-
|
|
|
- if (time.getHours() !== outTime.getHours()) {
|
|
|
- return parseTime(outTime, '{h}:{i}')
|
|
|
- }
|
|
|
-
|
|
|
- let minutes = outTime.getMinutes() - time.getMinutes()
|
|
|
- if (minutes === 0) {
|
|
|
- return '刚刚'
|
|
|
- }
|
|
|
-
|
|
|
- minutes = Math.abs(minutes)
|
|
|
- return `${minutes}分钟前`
|
|
|
-}
|
|
|
-
|
|
|
-export function getSort(fn) {
|
|
|
- return function(a, b) {
|
|
|
- let ret = 0
|
|
|
-
|
|
|
- if (fn.call(this, a, b)) {
|
|
|
- ret = -1
|
|
|
- } else if (fn.call(this, b, a)) {
|
|
|
- ret = 1
|
|
|
- }
|
|
|
-
|
|
|
- return ret
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 批量排序
|
|
|
- *
|
|
|
- * @param {*} arr
|
|
|
- */
|
|
|
-export function getMutipSort(arr) {
|
|
|
- return function(a, b) {
|
|
|
- let tmp
|
|
|
- let i = 0
|
|
|
-
|
|
|
- do {
|
|
|
- tmp = arr[i++](a, b)
|
|
|
- } while (tmp === 0 && i < arr.length)
|
|
|
-
|
|
|
- return tmp
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Url 替换超链接
|
|
|
- *
|
|
|
- * @param {String} text 文本
|
|
|
- * @param {String} color 超链接颜色
|
|
|
- */
|
|
|
-export function textReplaceLink(text, color = '#409eff') {
|
|
|
- const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi
|
|
|
- return text.replace(
|
|
|
- exp,
|
|
|
- `<a href='$1' target="_blank" style="color:${color};text-decoration: revert;">$1</a >`
|
|
|
- )
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 防抖
|
|
|
- *
|
|
|
- * @param {*} func
|
|
|
- * @param {*} wait
|
|
|
- * @param {*} immediate
|
|
|
- * @returns
|
|
|
- */
|
|
|
-export function debounce(func, wait, immediate) {
|
|
|
- let timeout
|
|
|
-
|
|
|
- return function() {
|
|
|
- const context = this
|
|
|
- const args = arguments
|
|
|
-
|
|
|
- if (timeout) clearTimeout(timeout) // timeout 不为null
|
|
|
- if (immediate) {
|
|
|
- const callNow = !timeout // 第一次会立即执行,以后只有事件执行后才会再次触发
|
|
|
- timeout = setTimeout(function() {
|
|
|
- timeout = null
|
|
|
- }, wait)
|
|
|
- if (callNow) func.apply(context, args)
|
|
|
- } else {
|
|
|
- timeout = setTimeout(function() {
|
|
|
- func.apply(context, args)
|
|
|
- }, wait)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-export function sha256sum(file) {
|
|
|
- const sha256 = CryptoJs.algo.SHA256.create()
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- const reader = new FileReader()
|
|
|
- reader.onload = ({ target }) => {
|
|
|
- const wordArray = CryptoJs.lib.WordArray.create(target.result)
|
|
|
- sha256.update(wordArray)
|
|
|
- resolve()
|
|
|
- }
|
|
|
- reader.readAsArrayBuffer(file)
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-export function hashFile(file) {
|
|
|
- /**
|
|
|
- * 使用指定的算法计算hash值
|
|
|
- */
|
|
|
- function hashFileInternal(file, alog) {
|
|
|
- // 指定块的大小,这里设置为10MB,可以根据实际情况进行配置
|
|
|
- const chunkSize = 10 * 1024 * 1024
|
|
|
- let promise = Promise.resolve()
|
|
|
- // 使用promise来串联hash计算的顺序。因为FileReader是在事件中处理文件内容的,必须要通过某种机制来保证update的顺序是文件正确的顺序
|
|
|
- for (let index = 0; index < file.size; index += chunkSize) {
|
|
|
- promise = promise.then(() => hashBlob(file.slice(index, index + chunkSize)))
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 更新文件块的hash值
|
|
|
- */
|
|
|
- function hashBlob(blob) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- const reader = new FileReader()
|
|
|
- reader.onload = ({ target }) => {
|
|
|
- const wordArray = CryptoJs.lib.WordArray.create(target.result)
|
|
|
- // 增量更新计算结果
|
|
|
- alog.update(wordArray)
|
|
|
- resolve()
|
|
|
- }
|
|
|
- reader.readAsArrayBuffer(blob)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 使用promise返回最终的计算结果
|
|
|
- return promise.then(() => encHex.stringify(alog.finalize()))
|
|
|
- }
|
|
|
-
|
|
|
- // 同时计算文件的sha256和md5,并使用promise返回
|
|
|
- /* return Promise.all([hashFileInternal(file, CryptoJs.algo.SHA256.create()),
|
|
|
- hashFileInternal(file, CryptoJs.algo.MD5.create())])
|
|
|
- .then(([sha256sum, md5sum]) => ({
|
|
|
- sha256sum,
|
|
|
- md5sum
|
|
|
- }))*/
|
|
|
- return Promise.all([hashFileInternal(file, CryptoJs.algo.SHA256.create()),
|
|
|
- hashFileInternal(file, CryptoJs.algo.MD5.create())])
|
|
|
- .then(([sha256sum]) => ({
|
|
|
- sha256sum
|
|
|
- }))
|
|
|
-}
|