拼板印
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

480 lines
12 KiB

import env from '@/env/index.js'
import store from '@/store/index.js'
import { isDate, isString, isArray } from './is.js'
/**
* 日期格式化,样例 yyyy-mm-dd hh:MM:ss
* @param date Date 需要转换的日期
* @param fmt string 转化的格式 yyyy-mm-dd hh:MM:ss
*/
export const dateTimeFormat = (date, fmt) => {
if (isString(date)) {
date = date.replace(/-/g, '/')
}
if (!isDate(date)) {
date = new Date(date)
}
if (!date || isNaN(date.getTime())) {
throw new Error('日期不正确')
}
let ret
const opt = {
'y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月
'd+': date.getDate().toString(), // 日
'h+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
's+': date.getSeconds().toString() // 秒
}
for (let k in opt) {
ret = new RegExp('(' + k + ')').exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'))
}
}
return fmt
}
/**
* 日期格式化文字描述,样例 yyyy-mm-dd hh:MM:ss
* @param stringTime 需要转换的日期
*/
export const getTimer = (stringTime) => {
let minute = 1000 * 60
let hour = minute * 60
let day = hour * 24
let week = day * 7
let month = day * 30
let time1 = new Date().getTime() //当前的时间戳
let time2 = Date.parse(new Date(stringTime)) //指定时间的时间戳
let time = time1 - time2
let result = null
if (time / month >= 1) {
result = parseInt(time / month) + '月前'
} else if (time / week >= 1) {
result = parseInt(time / week) + '周前'
} else if (time / day >= 1) {
result = parseInt(time / day) + '天前'
} else if (time / hour >= 1) {
result = parseInt(time / hour) + '小时前'
} else if (time / minute >= 1) {
result = parseInt(time / minute) + '分钟前'
} else {
result = '刚刚'
}
return result
}
/**
* 创建websocket
* @param {*} data
* @value {string} pageInfo 页面信息
* @value {true} retry 是否重连,默认false
* @returns 一个websocket实例
*/
export const makeSocket = async ({ pageInfo = '', retry = false }) => {
const socket = {
sockTask: null,
close: function () {
this.sockTask.close({
code: 1000
})
closeFlag = true
},
onMessage: function () {
console.log('onMessage')
},
onError: function () {
console.log('onError')
},
onRetry: function () {
console.log('onRetry')
}
}
let limitedNum = 0
let closeFlag = false
let timer = null
async function createSocket() {
let url = ''
if (env == 'production') {
url = 'wss://api-client-yyt.qniao.cn/qn-websocket-service/wechatwebsock?token='
} else if (env == 'test') {
url = 'wss://api-client-yyt-test.qniao.cn/qn-websocket-service/wechatwebsock?token='
}
const token = store.state.qnToken
const socketTask = await uni.connectSocket({
url: `${url}${token}`,
header: {
'content-type': 'application/json'
},
success: () => {
console.log('websocket连接成功')
},
fail: () => {
console.log('websocket连接失败')
}
})
socketTask.onOpen(() => {
console.log(pageInfo + ' onOpen')
timer = setInterval(() => {
socketTask.send({
data: 'ping'
})
}, 10000)
})
socketTask.onClose(() => {
console.log(pageInfo + ' onClose')
clearInterval(timer)
timer = null
if (!closeFlag && retry && limitedNum < 20) {
limitedNum++
console.log('重连次数:' + limitedNum)
createSocket().then(() => {
installSocket()
socket.onRetry()
})
}
})
socket.sockTask = socketTask
}
await createSocket()
function installSocket() {
if (socket.sockTask) {
socket.onMessage = (fn) => {
socket.sockTask.onMessage((res) => {
let data = JSON.parse(res.data)
console.log(pageInfo + '接收到消息:', data)
if (data.type != 'heartbeat') {
fn(data)
}
})
}
socket.onError = (fn) => {
socket.sockTask.onError((err) => {
fn(err)
})
}
}
}
installSocket()
return socket
}
let _boundaryCheckingState = true
/**
* {beyond:是否超出目标时间,day:天,hours:小时,minutes:分钟,seconds:秒钟}
* @param time 计算时间
* @param target 对照时间
* @returns 时间差对象
*/
export const difTime = (time, target) => {
if (isString(time)) {
time = time.replace(/-/g, '/')
}
if (isString(target)) {
target = target.replace(/-/g, '/')
}
let begin = new Date(time).getTime()
// 兼容ios时间
let end = new Date(target).getTime()
let beyond = begin < end ? false : true
let diff = Math.abs(begin - end)
// 计算天数
let day = Math.floor(diff / (24 * 3600 * 1000))
day != day ? (day = 0) : ''
diff = diff % (24 * 3600 * 1000)
// 计算小时数
let hours = Math.floor(diff / (3600 * 1000))
hours != hours ? (hours = 0) : ''
diff = diff % (3600 * 1000)
// 计算分钟数
let minutes = Math.floor(diff / (60 * 1000))
minutes != minutes ? (minutes = 0) : ''
diff = diff % (60 * 1000)
// 计算秒数
let seconds = Math.floor(diff / 1000)
seconds != seconds ? (seconds = 0) : ''
return {
beyond,
day,
hours,
minutes,
seconds
}
}
/**
* 迭代操作
*/
function iteratorOperation(arr, operation) {
const [num1, num2, ...others] = arr
let res = operation(num1, num2)
others.forEach((num) => {
res = operation(res, num)
})
return res
}
/**
* Return digits length of a number
* @param {*number} num Input number
*/
function digitLength(num) {
// Get digit length of e
const eSplit = num.toString().split(/[eE]/)
const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0)
return len > 0 ? len : 0
}
/**
* 把错误的数据转正
* strip(0.09999999999999998)=0.1
*/
function strip(num, precision = 15) {
return +parseFloat(Number(num).toPrecision(precision))
}
/**
* 把小数转成整数,支持科学计数法。如果是小数则放大成整数
* @param {*number} num 输入数
*/
function float2Fixed(num) {
if (num.toString().indexOf('e') === -1) {
return Number(num.toString().replace('.', ''))
}
const dLen = digitLength(num)
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num)
}
/**
* 检测数字是否越界,如果越界给出提示
* @param {*number} num 输入数
*/
function checkBoundary(num) {
if (_boundaryCheckingState) {
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`)
}
}
}
/**
* 精确乘法
*/
function times(...nums) {
if (nums.length > 2) {
return iteratorOperation(nums, times)
}
const [num1, num2] = nums
const num1Changed = float2Fixed(num1)
const num2Changed = float2Fixed(num2)
const baseNum = digitLength(num1) + digitLength(num2)
const leftValue = num1Changed * num2Changed
checkBoundary(leftValue)
return leftValue / Math.pow(10, baseNum)
}
/**
* 精确除法
*/
function divide(...nums) {
if (nums.length > 2) {
return iteratorOperation(nums, divide)
}
const [num1, num2] = nums
const num1Changed = float2Fixed(num1)
const num2Changed = float2Fixed(num2)
checkBoundary(num1Changed)
checkBoundary(num2Changed)
// fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))))
}
/**
* 精确四舍五入
*/
export const round = (num, ratio) => {
const base = Math.pow(10, ratio)
let result = divide(Math.round(Math.abs(times(num, base))), base)
if (num < 0 && result !== 0) {
result = times(result, -1)
}
return result
}
/**
* 根据规则校验字段
* @param {*} value 输入值
* @param {array} rules 规则集 {type,required,message}
* @value {boolean} required 是否必填
* @value {string} type 字段类型校验,目前支持 phone
* @returns {object} {isValid,msg}
*/
export const validateField = (value, rules) => {
let isValid = true
let msg = ''
for (let rule of rules) {
if (rule.required) {
if (value === '' || value === undefined || value === null) {
isValid = false
msg = rule.message
break
}
if (isArray(value) && value.length === 0) {
isValid = false
msg = rule.message
break
}
}
if (rule.type === 'phone' && value !== '' && !/^1[3456789]\d{9}$/.test(value)) {
isValid = false
msg = rule.message
break
}
}
return {
isValid,
msg
}
}
/**
* 正确数字保留几位小数显示
* @param {(number | string)} value 要修正的对象
* @param {number} precision 保留位数
* @returns {string}
*/
export const numToString = function (value, precision = 2) {
const zeros = '00000000000000'
let temp = ''
try {
temp = round(value, precision) + ''
let dot = temp.indexOf('.')
if (dot == -1) {
temp = temp + '.' + zeros.substring(0, 0 + precision)
} else {
// 计算差几个0,精度 - 现有位数
let digits = precision - (temp.length - dot - 1)
digits > 0 ? (temp = temp + zeros.substring(0, digits)) : ''
}
} catch (error) {
console.log('数字格式错误')
return value
}
return temp
}
/**
* 简易版防抖函数
* @param {Function} fn 函数
* @param {number} delay 延迟时间
* @returns {Function}
*/
export function debounce(fn, delay) {
let timer = null
return function (...args) {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
timer = null
fn.apply(this, args)
}, delay)
}
}
/**
* 简易版节流函数,可以带异步数据返回
* @param {Function} fn 函数,如果需要返回内容则需要返回Promise,并在then中return内容
* @param {number} delay 延迟时间单位毫秒
*/
export function throttle(fn, delay) {
let timer = null,
first = true,
result = null,
lastInvokeTime = 0,
remainingTime = null
return function (...args) {
if (first) {
result = fn.apply(this, args)
first = false
lastInvokeTime = Date.now()
return result
}
// 如果上次调用时间与当前时间差大于等于delay,则直接执行
if (Date.now() - lastInvokeTime >= delay) {
result = fn.apply(this, args)
lastInvokeTime = Date.now()
return result
} else {
remainingTime = delay - (Date.now() - lastInvokeTime)
if (timer) {
clearTimeout(timer)
createTimer.call(this, remainingTime, args)
} else {
createTimer.call(this, remainingTime, args)
}
}
return result
}
function createTimer(time, args) {
timer = null
timer = setTimeout(() => {
result = fn.apply(this, args)
timer = null
lastInvokeTime = Date.now()
}, time)
}
}
/**
* 简易的解析地址的函数
* @param {string} url 需要解析的url地址
* @returns {object} {host,query}
*/
export function parseUrl(url) {
let query = {}
let host = url
if (url.indexOf('?') > -1) {
host = url.substring(0, url.indexOf('?'))
let str = url.split('?')[1]
let arr2 = str.split('&')
arr2.forEach((item) => {
let arr3 = item.split('=')
query[arr3[0]] = arr3[1]
})
}
return { host, query }
}
/**
* 获取数组的所有子集
* @param {Array} arr 数组
* @returns Array<Array<any>>
*/
export function getAllSubsets(arr) {
let res = [[]]
for (let item of arr) {
const tempRes = res.map((subset) => {
const one = subset.concat([])
one.push(item)
return one
})
res = res.concat(tempRes)
}
return res
}