utils.js
/*
* 对Date的扩展,将 Date 转化为指定格式的String
* 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
* 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
* @param {String} fmt 目标时间格式
*/
Date.prototype.Format = function (fmt) {
let o = {
'M+': this.getMonth() + 1, // 月份
'd+': this.getDate(), // 日
'h+': this.getHours(), // 小时
'm+': this.getMinutes(), // 分
's+': this.getSeconds(), // 秒
'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
'S': this.getMilliseconds() // 毫秒
}
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
}
return fmt
}
/**
* 随机码 对指定的字符串中随机取参数位
*/
export const randomString = function (len) {
len = len || 32
var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
var maxPos = chars.length
var pwd = ''
for (var i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
}
/**
* 获取文件后缀
*/
export const getSuffix = function (filename) {
let pos = filename.lastIndexOf('.')
let suffix = ''
if (pos != -1) {
suffix = filename.substring(pos)
}
return suffix
}
/**
* 定义全局函数,或者单独引用
* */
/**
* 浮点数加法
* */
export const addition = (arg1, arg2) => {
let r1, r2, m
if (parseInt(arg1) === arg1) {
r1 = 0
} else {
r1 = arg1.toString().split('.')[1].length
}
if (parseInt(arg2) === arg2) {
r2 = 0
} else {
r2 = arg2.toString().split('.')[1].length
}
m = Math.pow(10, Math.max(r1, r2))
return (arg1 * m + arg2 * m) / m
}
/**
* 浮点数减法
* */
export const subtraction = (arg1, arg2) => {
let c = 0
let d = arg1.toString()
let e = arg2.toString()
try {
c += d.split('.')[1].length
} catch (f) {}
try {
c += e.split('.')[1].length
} catch (f) {}
return Number(d.replace('.', '')) * Number(e.replace('.', '')) / Math.pow(10, c)
}
/**
* 浮点数乘法
* */
export const multiplication = (arg1, arg2) => {
let m = 0
let s1 = arg1.toString()
let s2 = arg2.toString()
try {
m += s1.split('.')[1].length
} catch (e) {
}
try {
m += s2.split('.')[1].length
} catch (e) {
}
return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m)
}
/**
* 对象的深拷贝
* @param source 需要深拷贝的对象
* @returns {object}
*/
export const objDeepCopy = (source) => {
let sourceCopy = {}
for (let item in source) sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item]
return sourceCopy
}
/**
* 对象数组的深拷贝
* @param source 需要深拷贝的对象
* @returns {object}
*/
export const objArryDeepCopy = (source) => {
let sourceCopy = source instanceof Array ? [] : {}
for (let item in source) {
sourceCopy[item] = typeof source[item] === 'object' ? objArryDeepCopy(source[item]) : source[item]
}
return sourceCopy
}
/**
* 判断是否是微信浏览器
* */
export const isWxBrowser = () => {
let ua = window.navigator.userAgent.toLowerCase()
if (ua.match(/MicroMessenger/i) === 'micromessenger') {
return true
} else {
return false
}
}
/**
* 判断是否是支付宝浏览器
* */
export const isAliBrowser = () => {
let ua = window.navigator.userAgent.toLowerCase()
if (ua.match(/alipaydefined/i) === 'alipaydefined') {
return true
} else {
return false
}
}
/**
* 判断手机是android 还是 ios
* */
export const mobileVersion = () => {
let u = navigator.userAgent
let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 // android终端
let isIos = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
if (isAndroid) {
return 'android'
} else if (isIos) {
return 'ios'
} else {
return 'windows'
}
}
/**
* 将更新后的信息,存储到sessionStorage中
* 及需要暂时保存在本地的数据 关闭浏览器后及清除
* */
export const setSessionStorage = (key, value) => {
window.sessionStorage.setItem(key, JSON.stringify(value))
}
/**
* 删除到sessionStorage中
* 及需要暂时保存在本地的数据 关闭浏览器后及清除
* */
export const removeSessionStorage = (key) => {
window.sessionStorage.removeItem(key)
}
/**
* 保存id
* @param key
* @param value
*/
export const setIdSessionStorage = (key, value) => {
window.sessionStorage.setItem(key, JSON.stringify(value))
// window.sessionStorage.removeItem(key);
}
/**
* 将更新后的信息,存储到localStorage中
* 及需要永久保存在本地的数据 关闭浏览器后也还存在的
* */
export const setLocalStorage = (key, value) => {
window.localStorage.setItem(key, JSON.stringify(value))
}
/**
* 获取存储在sessionStorage中的数据
* */
export const getSessionData = key => window.sessionStorage.getItem(key)
/**
* 获取存储在localStorage中的数据
* */
export const getLocalStorage = key => window.localStorage.getItem(key)
// 设置sessionStorage
export const setSessionStorages = (key, value) => {
if (typeof value === 'object') {
window.sessionStorage.setItem(key, JSON.stringify(value))
} else {
window.sessionStorage.setItem(key, value)
}
}
// 获取sessionStorage
export const getSessionStorage = key => {
let storage = window.sessionStorage.getItem(key)
try {
return JSON.parse(storage)
} catch (err) {
return storage
}
}
window.setSessionStorage = setSessionStorages
window.getSessionStorage = getSessionStorage
axios.js
import Vue from 'vue'
import axios from 'axios'
// import qs from 'qs'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { storageGet } from './storage'
const axiosX = axios.create({
baseURL: process.env.API,
timeout: 80000
})
NProgress.configure({ showSpinner: false })
/**
* 判断请求是否成功,如果失败则给出对应提示
* @param response 请求数据
*/
function checkStatus (response) {
// 如果http状态码正常,则直接返回数据
if (response && (Number(response.status) === 200 || Number(response.status) === 304)) {
return response.data
}
}
/**
* 当请求成功时候,对于业务逻辑做判断
* @param res 请求成功后返回的接口数据
* @returns {*}
*/
function checkCode (res) {
if (res.code === 200) {
return true
}
// 请求成功,但是业务逻辑出错情况下,给出对应提示
codeErrorHandle(res.msg)
}
/**
* 当请求成功,但是出现了业务层面错误时候,给出对应的错误处理
* @param res 返回的信息
*/
function codeErrorHandle (msg) {
Message({
showClose: true,
message: msg,
type: 'error'
})
}
axiosX.interceptors.request.use(function (config) {
config.headers['Content-Type'] = 'application/json; charset=UTF-8'
// 在发送请求之前做些什么
return config
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error)
})
axiosX.interceptors.response.use(function (response) {
let res = checkStatus(response)
if (res) {
if (checkCode(res)) {
return res
}
}
}, function (err) {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '错误请求'
break
case 401:
err.message = '未授权,请重新登录'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = '请求错误,未找到该资源'
break
case 405:
err.message = '请求方法未允许'
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器端出错'
break
case 501:
err.message = '网络未实现'
break
case 502:
err.message = '网络错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网络超时'
break
case 505:
err.message = 'http版本不支持该请求'
break
default:
err.message = `连接错误${err.response.status}`
}
} else {
err.message = '登录超时,请重新登录'
window.sessionStorage.clear()
setTimeout(function () {
window.location.reload()
}, 1000)
}
Message({
showClose: true,
message: err.message,
type: 'error'
})
return Promise.reject(err)
})
const XHR = ({
method = 'post',
qs = true,
loading = false,
loginRequire = true,
reqComplex = false,
reqContentType = 'urlencoded'
}) => {
// 用户登陆信息
const user = storageGet('userInfo')
// 带请求进度条成功方法
const sucFunX = res => {
NProgress.done()
return res
}
// 成功执行方法
const sucFunC = res => {
return res
}
// 带请求进度条失败方法
const errFunX = err => {
NProgress.done()
console.log(err)
}
// 失败执行访求
const errFunC = err => {
console.log(err)
}
// 判断是否需要Longing
const sucFun = loading ? sucFunX : sucFunC
// 判断是否需要Longing
const errFun = loading ? errFunX : errFunC
return { user, sucFun, errFun }
}
// 简单带请求带状态POST
// Posting('/fsddf', {id: 111, page: 1})
const Posting = function (url = '', data = {}) {
NProgress.start()
let { user, sucFun, errFun } = XHR({ loading: true })
// let reqData = qs.stringify({ ...user, ...data })
let reqData = { ...user, ...data }
return axiosX.post(url, reqData).then(sucFun).catch(errFun)
}
// 简单带请求POST
// Post('/fsddf', {id: 111, page: 1})
const Post = function (url = '', data = {}) {
let { user, sucFun, errFun } = XHR({ loading: false })
// let reqData = qs.stringify({ ...user, ...data })
let reqData = { ...user, ...data }
return axiosX.post(url, reqData).then(sucFun).catch(errFun)
}
// 简单带请求带状态Get
// Geting('/fsddf', {id: 111, page: 1})
const Geting = function (url = '', data = {}) {
NProgress.start()
let { user, sucFun, errFun } = XHR({ loading: true })
let params = {
params: { ...user, ...data }
}
return axiosX.get(url, params).then(sucFun).catch(errFun)
}
// 简单带请求GET
// Get('/fsddf', {id: 111, page: 1})
const Get = function (url = '', data = {}) {
let { user, sucFun, errFun } = XHR({ loading: false })
let params = {
params: { ...user, ...data }
}
return axiosX.get(url, params).then(sucFun).catch(errFun)
}
// 默认请求
Vue.prototype.$axios = axios
Vue.axios = axios
// 带等待状态POST请求
Vue.prototype.$Posting = Posting
Vue.Posting = Posting
// 带等待状态GET请求
Vue.prototype.$Geting = Geting
Vue.Geting = Geting
// 无等待状态POST请求
Vue.prototype.$Post = Post
Vue.Post = Post
// 无等待状态GET请求
Vue.prototype.$Get = Get
Vue.Get = Get
export { axios, Posting, Geting, Post, Get }
validation.js
/*
* validation 1.x
* 正则表达式
*/
import Vue from 'vue'
/* eslint-disable */
const Validation = {
checkPhone, // 检测是否为电话号码
isEmpty, // 是否为空
isNumber, // 是否为数字
checkLength, // 检测字符串长度
isEqual, // 是否相同
replaceStr, // *替换str
checkPwd, // 检测密码格式 6-16位数字或字母
checkPwd2, // 检测密码格式 6-16位数字和字母
checkArrLen, // 检测数组长度是否存在
isIdcard, // 检测身份证是否合法
isTel, // 检测电话号码(包括座机号和手机号)
isChina, // 检测是否为中文
filterEmoji, // 替换ios中的emoji表情
isSpecial, // 判断是否包含特殊字符
isRate, // 判断是否在0-1之间,用于费率的计算
isFeePoint, // 判断最多小数点后6位
isFeeCheck,
isInteger, // 是否是正整数
checkRuleMoney, // 风控判断单笔单日钱数
isBasicInteger
}
function checkPhone (num) {
// 表示以1开头,第二位可能是3/4/5/7/8等的任意一个,在加上后面的\d表示数字[0-9]的9位,总共加起来11位结束。
if ((/^1[3|4|5|7|8]\d{9}$/.test(num))) { // 判断条件:不是正确的手机号码
return false
} else {
return true
}
};
/**
* 是否是正整数
* @param str
* @returns {boolean}
*/
function isInteger (str) {
str = str || ''
if (/^\+?[1-9]\d*$/.test(str)) { // 为空,返回true
return true
} else {
return false
}
}
/**
* 渠道方基础信息是否是整数
* @param str
* @returns {boolean}
*/
function isBasicInteger (str) {
if (/^\+?[0-9]\d*$/.test(str)) { // 为空,返回true
return true
} else {
return false
}
}
function isEmpty (str) {
str = str || ''
console.log('str:',str)
if (/^\s*$/.test(str)) { // 为空,返回true
return true
} else {
return false
}
}
function isNumber (str) { // 是数字 为true
str = str || 0
if (/^\d+(\.\d+)?$/.test(str)) {
return true
} else {
return false
}
}
/**
* 验证费率
* @param str
* @returns {boolean}
*/
function isFeeCheck (str) {
str = str || 0
if (/^-?(0(\.\d*)?)$/.test(str)) {
return true
} else {
return false
}
}
function isTel (str) { // 是电话号码 为true(数字和——)
str = str || ''
if (/^(((\d{3,4}-?)?\d{7,8})|(1\d{10}))$/.test(str)) {
return true
} else {
return false
}
}
function isChina (str) {
str = str.replace(/[\u4e00-\u9fa5]+/g, '')
return str
}
function filterEmoji (name) {
let newName = '',
is4Byte = function (str) {
return str.codePointAt(0) > 65535
}
for (let item of name) {
if (is4Byte(item)) {
item = ''
}
newName += item
}
return newName
}
function isSpecial (val) {
val = val.trim() || ''
var regEn = /[`~!@#$%^&*()_+<>?"{}.\/;'[\]·!#¥(——);|《》?、【】[\]️ ♂️♀️]/im
if (regEn.test(val)) {
return false
} else {
return true
}
}
function isRate(val) {
val = +val
if(val > -0.99999999999 && val <1) {
return true
}else {
return false
}
}
/**
* 小数点后最多6位
* @param val
* @returns {boolean}
*/
function isFeePoint(val) {
var reg = /^[+-]?\d+(\.\d{1,6})?$/
if(reg.test(val)) {
return true
}else {
return false
}
}
function checkLength (str, len) { // 超出了,返回true
str = str.trim() || ''
if (str.length > len) {
return true
} else {
return false
}
};
function isEqual (str1, str2) { // 不相同,返回true
str1 = str1 || ''
str2 = str2 || ''
if (str1 === str2) {
return false
} else {
return true
}
};
function repeatStr (str, count) {
var text = ''
for (var i = 0; i < count; i++) {
text += str
}
return text
};
function replaceStr (str, regArr, type, ARepText) { // demo:replaceStr('18819322663',[3,5,3],0)
var regtext = '',
Reg = null,
replaceText = ARepText || '*'
if (regArr.length === 3 && type === 0) {
regtext = '(\\w{' + regArr[0] + '})\\w{' + regArr[1] + '}(\\w{' + regArr[2] + '})'
Reg = new RegExp(regtext)
var replaceCount = repeatStr(replaceText, regArr[1])
return str.replace(Reg, '$1' + replaceCount + '$2')
}
};
function checkPwd (str) {
str = str || ''
if (/^[a-zA-Z0-9]{6,16}$/.test(str)) {
return false
} else {
return true
}
};
/**
* 风控判断单笔单日钱
* @param str
* @returns {boolean}
*/
function checkRuleMoney(str) {
str = str || ''
if (/^\d+(\.\d{0,2})?$/.test(str)){
return false
} else {
return true
}
}
function checkPwd2 (str) {
str = str || ''
if (/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,20}$/.test(str)) {
return false
} else {
return true
}
};
function checkArrLen (arr) {
arr = arr || []
if (arr.length < 1) { return false } else { return true }
};
function isIdcard (ID) {
if (typeof ID !== 'string') return '非法字符串'
var city = { 11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江 ', 31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北 ', 43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏 ', 61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外' }
var birthday = ID.substr(6, 4) + '/' + Number(ID.substr(10, 2)) + '/' + Number(ID.substr(12, 2))
var d = new Date(birthday)
var newBirthday = d.getFullYear() + '/' + Number(d.getMonth() + 1) + '/' + Number(d.getDate())
var currentTime = new Date().getTime()
var time = d.getTime()
var arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
var arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
var sum = 0
var i
var residue
if (!/^\d{17}(\d|x)$/i.test(ID)) return false
if (city[ID.substr(0, 2)] === undefined) return false
if (time >= currentTime || birthday !== newBirthday) return false
for (i = 0; i < 17; i++) {
sum += ID.substr(i, 1) * arrInt[i]
}
residue = arrCh[sum % 11]
if (residue !== ID.substr(17, 1).toUpperCase()) return false
return true
}
// export default validation
Vue.prototype.$Validation = Validation