初次提交
This commit is contained in:
37
src/utils/auth.js
Normal file
37
src/utils/auth.js
Normal file
@ -0,0 +1,37 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const TokenKey = 'token'
|
||||
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey)
|
||||
}
|
||||
|
||||
export function getScreenToken() {
|
||||
return Cookies.get('ScreenTokenKey') || localStorage.getItem('SCREEN_TOKEN')
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
localStorage.setItem('USER_TOKEN', token)
|
||||
return Cookies.set(TokenKey, token)
|
||||
}
|
||||
|
||||
export function setScreenToken(token) {
|
||||
localStorage.setItem('SCREEN_TOKEN', token)
|
||||
return Cookies.set('ScreenTokenKey', token)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey)
|
||||
}
|
||||
export function setAseKey(key) {
|
||||
return Cookies.set('aseKey', key)
|
||||
}
|
||||
export function getAseKey() {
|
||||
return Cookies.get('aseKey')
|
||||
}
|
||||
export function setIV(iv) {
|
||||
return Cookies.set('iv', iv)
|
||||
}
|
||||
export function getIV() {
|
||||
return Cookies.get('iv')
|
||||
}
|
||||
32
src/utils/clipboard.js
Normal file
32
src/utils/clipboard.js
Normal file
@ -0,0 +1,32 @@
|
||||
import Vue from 'vue'
|
||||
import Clipboard from 'clipboard'
|
||||
|
||||
function clipboardSuccess() {
|
||||
Vue.prototype.$message({
|
||||
message: 'Copy successfully',
|
||||
type: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
}
|
||||
|
||||
function clipboardError() {
|
||||
Vue.prototype.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
|
||||
export default function handleClipboard(text, event) {
|
||||
const clipboard = new Clipboard(event.target, {
|
||||
text: () => text
|
||||
})
|
||||
clipboard.on('success', () => {
|
||||
clipboardSuccess()
|
||||
clipboard.destroy()
|
||||
})
|
||||
clipboard.on('error', () => {
|
||||
clipboardError()
|
||||
clipboard.destroy()
|
||||
})
|
||||
clipboard.onClick(event)
|
||||
}
|
||||
36
src/utils/error-log.js
Normal file
36
src/utils/error-log.js
Normal file
@ -0,0 +1,36 @@
|
||||
import Vue from 'vue'
|
||||
import store from '@/store'
|
||||
import { isString, isArray } from '@/utils/validate'
|
||||
import settings from '@/settings'
|
||||
|
||||
// you can set in settings.js
|
||||
// errorLog:'production' | ['production', 'development']
|
||||
const { errorLog: needErrorLog } = settings
|
||||
|
||||
function checkNeed() {
|
||||
const env = process.env.NODE_ENV
|
||||
if (isString(needErrorLog)) {
|
||||
return env === needErrorLog
|
||||
}
|
||||
if (isArray(needErrorLog)) {
|
||||
return needErrorLog.includes(env)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (checkNeed()) {
|
||||
Vue.config.errorHandler = function(err, vm, info, a) {
|
||||
// Don't ask me why I use Vue.nextTick, it just a hack.
|
||||
// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
|
||||
Vue.nextTick(() => {
|
||||
store.dispatch('errorLog/addErrorLog', {
|
||||
err,
|
||||
vm,
|
||||
info,
|
||||
url: window.location.href
|
||||
})
|
||||
console.error(err, info)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
13
src/utils/get-page-title.js
Normal file
13
src/utils/get-page-title.js
Normal file
@ -0,0 +1,13 @@
|
||||
import defaultSettings from '@/settings'
|
||||
import i18n from '@/lang'
|
||||
|
||||
const title = defaultSettings.title || 'Vue Element Admin'
|
||||
|
||||
export default function getPageTitle(key) {
|
||||
const hasKey = i18n.te(`route.${key}`)
|
||||
if (hasKey) {
|
||||
const pageName = i18n.t(`route.${key}`)
|
||||
return `${pageName} - ${title}`
|
||||
}
|
||||
return `${title}`
|
||||
}
|
||||
12
src/utils/i18n.js
Normal file
12
src/utils/i18n.js
Normal file
@ -0,0 +1,12 @@
|
||||
// translate router.meta.title, be used in breadcrumb sidebar tagsview
|
||||
export function generateTitle(title) {
|
||||
const hasKey = this.$te('route.' + title)
|
||||
|
||||
if (hasKey) {
|
||||
// $t :this method from vue-i18n, inject in @/lang/index.js
|
||||
const translatedTitle = this.$t('route.' + title)
|
||||
|
||||
return translatedTitle
|
||||
}
|
||||
return title
|
||||
}
|
||||
1057
src/utils/index.js
Normal file
1057
src/utils/index.js
Normal file
File diff suppressed because it is too large
Load Diff
25
src/utils/open-window.js
Normal file
25
src/utils/open-window.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
*Created by PanJiaChen on 16/11/29.
|
||||
* @param {Sting} url
|
||||
* @param {Sting} title
|
||||
* @param {Number} w
|
||||
* @param {Number} h
|
||||
*/
|
||||
export default function openWindow(url, title, w, h) {
|
||||
// Fixes dual-screen position Most browsers Firefox
|
||||
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
|
||||
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
|
||||
|
||||
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
|
||||
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
|
||||
|
||||
const left = ((width / 2) - (w / 2)) + dualScreenLeft
|
||||
const top = ((height / 2) - (h / 2)) + dualScreenTop
|
||||
const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
|
||||
|
||||
// Puts focus on the newWindow
|
||||
if (window.focus) {
|
||||
newWindow.focus()
|
||||
}
|
||||
}
|
||||
|
||||
21
src/utils/permission.js
Normal file
21
src/utils/permission.js
Normal file
@ -0,0 +1,21 @@
|
||||
import store from '@/store'
|
||||
|
||||
/**
|
||||
* @param {Array} value
|
||||
* @returns {Boolean}
|
||||
* @example see @/views/permission/directive.vue
|
||||
*/
|
||||
export default function checkPermission(value) {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const roles = store.getters && store.getters.roles
|
||||
const permissionRoles = value
|
||||
|
||||
const hasPermission = roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
})
|
||||
return hasPermission
|
||||
} else {
|
||||
console.error(`need roles! Like v-permission="['admin','editor']"`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
117
src/utils/request.js
Normal file
117
src/utils/request.js
Normal file
@ -0,0 +1,117 @@
|
||||
import axios from 'axios'
|
||||
import { Message } from 'element-ui'
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
import { getToken, getScreenToken } from '@/utils/auth'
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
|
||||
// withCredentials: true, // send cookies when cross-domain requests
|
||||
timeout: 10000 // request timeout
|
||||
})
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
config.headers['lang'] = sessionStorage.getItem('language') === 'en' ? 'en_US' : 'zh_CN'
|
||||
// do something before request is sent
|
||||
if (config.headers.isScreen) {
|
||||
config.headers['authorization'] = getScreenToken()
|
||||
} else {
|
||||
if (store.getters.token) {
|
||||
config.headers['authorization'] = getToken()
|
||||
|
||||
// let each request carry token
|
||||
// ['X-Token'] is a custom headers key
|
||||
// please modify it according to the actual situation
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// do something with request error
|
||||
// for debug
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
/**
|
||||
* If you want to get http information such as headers or status
|
||||
* Please return response => response
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine the request status by custom code
|
||||
* Here is just an example
|
||||
* You can also judge the status by HTTP Status Code
|
||||
*/
|
||||
response => {
|
||||
const res = response.data
|
||||
// if the custom code is not 20000, it is judged as an error.
|
||||
if (res.code !== 200) {
|
||||
console.log(123, res)
|
||||
|
||||
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
|
||||
if (res.code === 401001 || res.code === 401002) {
|
||||
Message({
|
||||
message: '登录凭证已过期,请重新登录' || 'Error',
|
||||
type: 'warning',
|
||||
duration: 2 * 1000
|
||||
})
|
||||
// to re-login
|
||||
store.dispatch('user/resetToken').then(() => {
|
||||
// location.reload()
|
||||
router.push(localStorage.getItem('loginPage'))
|
||||
})
|
||||
} else if (res.code === 60000) {
|
||||
Message({
|
||||
message: res.msg || 'Error',
|
||||
type: 'warning',
|
||||
duration: 2 * 1000
|
||||
})
|
||||
} else {
|
||||
Message({
|
||||
message: res.msg || 'Error',
|
||||
type: 'error',
|
||||
duration: 2 * 1000
|
||||
})
|
||||
}
|
||||
// debugger
|
||||
return Promise.reject(new Error(res.message || 'Error'))
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (error.code === 'ECONNABORTED' || error.message === 'Network Error' || error.message.includes('timeout')) {
|
||||
// Message({
|
||||
// message: '服务器繁忙,请稍后重试',
|
||||
// type: 'warning',
|
||||
// duration: 2 * 1000
|
||||
// })
|
||||
// 判断licence校验
|
||||
} else if (error.response.data.code === 401) {
|
||||
Message({
|
||||
message: error.response.data.message,
|
||||
type: 'warning',
|
||||
duration: 2 * 1000
|
||||
})
|
||||
} else {
|
||||
console.log(error.response.status)
|
||||
if (error.response.status !== 503 && error.response.status !== 500) {
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 2 * 1000
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
||||
58
src/utils/scroll-to.js
Normal file
58
src/utils/scroll-to.js
Normal file
@ -0,0 +1,58 @@
|
||||
Math.easeInOutQuad = function(t, b, c, d) {
|
||||
t /= d / 2
|
||||
if (t < 1) {
|
||||
return c / 2 * t * t + b
|
||||
}
|
||||
t--
|
||||
return -c / 2 * (t * (t - 2) - 1) + b
|
||||
}
|
||||
|
||||
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
|
||||
var requestAnimFrame = (function() {
|
||||
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
|
||||
})()
|
||||
|
||||
/**
|
||||
* Because it's so fucking difficult to detect the scrolling element, just move them all
|
||||
* @param {number} amount
|
||||
*/
|
||||
function move(amount) {
|
||||
document.documentElement.scrollTop = amount
|
||||
document.body.parentNode.scrollTop = amount
|
||||
document.body.scrollTop = amount
|
||||
}
|
||||
|
||||
function position() {
|
||||
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} to
|
||||
* @param {number} duration
|
||||
* @param {Function} callback
|
||||
*/
|
||||
export function scrollTo(to, duration, callback) {
|
||||
const start = position()
|
||||
const change = to - start
|
||||
const increment = 20
|
||||
let currentTime = 0
|
||||
duration = (typeof (duration) === 'undefined') ? 500 : duration
|
||||
var animateScroll = function() {
|
||||
// increment the time
|
||||
currentTime += increment
|
||||
// find the value with the quadratic in-out easing function
|
||||
var val = Math.easeInOutQuad(currentTime, start, change, duration)
|
||||
// move the document.body
|
||||
move(val)
|
||||
// do the animation unless its over
|
||||
if (currentTime < duration) {
|
||||
requestAnimFrame(animateScroll)
|
||||
} else {
|
||||
if (callback && typeof (callback) === 'function') {
|
||||
// the animation is done so lets callback
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
animateScroll()
|
||||
}
|
||||
165
src/utils/validate.js
Normal file
165
src/utils/validate.js
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Created by PanJiaChen on 16/11/18.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isExternal(path) {
|
||||
return /^(https?:|mailto:|tel:)/.test(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validUsername(str) {
|
||||
const valid_map = ['admin', 'editor']
|
||||
return valid_map.indexOf(str.trim()) >= 0
|
||||
}
|
||||
/**
|
||||
* @param {string} phone
|
||||
* @returns {}
|
||||
*/
|
||||
export function isvalidatemobile(phone) {
|
||||
const list = []
|
||||
let result = true
|
||||
let msg = ''
|
||||
var isPhone = /^0\d{2,3}-?\d{7,8}$/
|
||||
// 增加134 减少|1349[0-9]{7},增加181,增加145,增加17[678]]ss
|
||||
if (!validatenull(phone)) {
|
||||
if (phone.length === 11) {
|
||||
if (isPhone.test(phone)) {
|
||||
msg = '手机号码格式不正确'
|
||||
} else {
|
||||
result = false
|
||||
}
|
||||
} else {
|
||||
msg = '手机号码长度不为11位'
|
||||
}
|
||||
} else {
|
||||
msg = '手机号码不能为空'
|
||||
}
|
||||
list.push(result)
|
||||
list.push(msg)
|
||||
return list
|
||||
}
|
||||
/**
|
||||
* 判断是否为空
|
||||
*/
|
||||
export function validatenull(val) {
|
||||
if (typeof val === 'boolean') {
|
||||
return false
|
||||
}
|
||||
if (typeof val === 'number') {
|
||||
return false
|
||||
}
|
||||
if (val instanceof Array) {
|
||||
if (val.length === 0) return true
|
||||
} else if (val instanceof Object) {
|
||||
if (JSON.stringify(val) === '{}') return true
|
||||
} else {
|
||||
if (val === 'null' || val == null || val === 'undefined' || val === undefined || val === '') return true
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validURL(url) {
|
||||
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
||||
return reg.test(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validLowerCase(str) {
|
||||
const reg = /^[a-z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validUpperCase(str) {
|
||||
const reg = /^[A-Z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validAlphabets(str) {
|
||||
const reg = /^[A-Za-z]+$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} email
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validEmail(email) {
|
||||
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return reg.test(email)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isString(str) {
|
||||
if (typeof str === 'string' || str instanceof String) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} arg
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isArray(arg) {
|
||||
if (typeof Array.isArray === 'undefined') {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]'
|
||||
}
|
||||
return Array.isArray(arg)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param value 关键字
|
||||
* @param arr 要过滤的数组
|
||||
* @param key 过滤的key
|
||||
* @returns []过滤的数组
|
||||
*/
|
||||
export function searchTree(value, arr, key) {
|
||||
const newArr = []
|
||||
|
||||
arr.forEach((element, index) => {
|
||||
if (element[key].indexOf(value) > -1) {
|
||||
// 判断条件
|
||||
newArr.push(element)
|
||||
} else {
|
||||
if (element.children && element.children.length > 0) {
|
||||
const redata = searchTree(value, element.children, key)
|
||||
if (redata && redata.length > 0) {
|
||||
const obj = {
|
||||
...element,
|
||||
children: redata
|
||||
}
|
||||
newArr.push(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return newArr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user