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') } } 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() } }) socketTask.onError(() => { console.log(pageInfo + ' error') }) socket.sockTask = socketTask } await createSocket() if (socket) { socket.onMessage = (fn) => { socket.sockTask.onMessage((res) => { let data = JSON.parse(res.data) console.log(pageInfo + '接收到消息:', data) if (data.type != 'heartbeat') { fn(data) } }) } } 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 === undefined || value === null) { isValid = false msg = rule.message break } if (isArray(value) && value.length === 0) { isValid = false msg = rule.message break } if (isString(value)) { if (value.trim() === '') { 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 } }