This commit is contained in:
2022-10-19 17:01:55 +08:00
commit 4f131cda36
466 changed files with 60382 additions and 0 deletions

16
src/utils/auth.js Normal file
View File

@@ -0,0 +1,16 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
console.log('setToken=' + token)
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}

20
src/utils/blobToBase64.js Normal file
View File

@@ -0,0 +1,20 @@
/*
* @Author: gtz
* @Date: 2021-03-01 16:54:38
* @LastEditors: gtz
* @LastEditTime: 2021-03-01 16:57:00
* @Description: file content
*/
export function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader()
fileReader.onload = (e) => {
resolve(e.target.result)
}
fileReader.readAsDataURL(blob)
fileReader.onerror = () => {
reject(new Error('blobToBase64 error'))
}
})
}

4
src/utils/bus.js Normal file
View File

@@ -0,0 +1,4 @@
import Vue from 'vue'
import VueBus from 'vue-bus'
Vue.use(VueBus)

15
src/utils/cache.js Normal file
View File

@@ -0,0 +1,15 @@
/*
* @Date: 2021-01-23 16:19:01
* @LastEditors: guo
* @LastEditTime: 2021-01-23 16:54:29
* @FilePath: \basic-admin\src\utils\cache.js
* @Description: 带缓存的接口请求
*/
// import request from './request'
export default function(reqPromise) {
return new Promise((resolve, reject) => {
resolve()
})
}

32
src/utils/clipboard.js Normal file
View 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)
}

35
src/utils/error-log.js Normal file
View File

@@ -0,0 +1,35 @@
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)
})
}
}

View File

@@ -0,0 +1,21 @@
/*
* @Author: gtz
* @Date: 2021-01-27 10:07:42
* @LastEditors: gtz
* @LastEditTime: 2021-02-26 09:11:54
* @Description: file content
*/
import i18n from '@/lang/i18n'
import Cookies from 'js-cookie'
const language = Cookies.get('language')
const title = i18n.title[language] || 'Vue Element Admin'
export default function getPageTitle(pageTitle) {
// 暂时注释,不需要模块名
// if (pageTitle) {
// return `${pageTitle} - ${title}`
// }
return `${title}`
}

View File

@@ -0,0 +1,35 @@
/**
* @Author: lb
* @Date: 2022-04-19 15:20:00
* @LastEditors: lb
* @LastEditTime: 2022-04-19 15:20:00
* 一些不依赖vue实例的辅助函数
*/
/**
* 从服务器返回的数据提取需要的部分
* 使用说明:
* this.dataForm = refineData(res.data, ['id', 'name', 'code']) // 假如只需要服务器所返回的id name code三个字段
* @param {any} responseRecords
* @param {Array<string>} fields
* @returns
*/
export function refineData(responseRecords, fields) {
const _ = {}
for (const field of fields) {
if (field) { _[field] = Object.prototype.hasOwnProperty.call(responseRecords, field) ? responseRecords[field] : null }
}
return _
}
/**
* 从tree相关的接口响应体中解析出 el-cascader 组件需要的 {value, label, children? } 格式的值
* @param {*} dataList 服务器返回的列表
*/
export function parseTree(dataList) {
const _ = []
dataList.forEach(item => {
_.push({ value: item.id, label: item.name, children: item.children ? parseTree(item.children) : null })
})
return _
}

12
src/utils/i18n.js Normal file
View 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
}

409
src/utils/index.js Normal file
View File

@@ -0,0 +1,409 @@
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
// support "1548221490638"
time = parseInt(time)
} else {
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
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 {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export function byteLength(str) {
// returns the byte length of an utf8 string
let s = str.length
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) s++
else if (code > 0x7ff && code <= 0xffff) s += 2
if (code >= 0xDC00 && code <= 0xDFFF) i--
}
return s
}
/**
* @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 {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 {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 {string} val
* @returns {string}
*/
export function html2Text(val) {
const div = document.createElement('div')
div.innerHTML = val
return div.textContent || div.innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
/**
* @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
}
/**
* @param {string} type
* @returns {Date}
*/
export function getTime(type) {
if (type === 'start') {
return new Date().getTime() - 3600 * 1000 * 24 * 90
} else {
return new Date(new Date().toDateString())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
/**
* @param {Array} arr
* @returns {Array}
*/
export function uniqueArr(arr) {
return Array.from(new Set(arr))
}
/**
* @returns {string}
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* 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, ' ')
}
}
// 对象中无效值过滤
export function objFilter(obj) {
const newObj = {}
Object.keys(obj).forEach(item => {
if (obj[item] !== undefined && obj[item] !== null && obj[item] !== '') {
newObj[item] = obj[item]
}
})
return newObj
}
// 数据字典值转换
export function dictChange(arr, { key = 'id', value = 'name' }) {
const table = {}
arr.forEach(item => {
table[item[key]] = item[value]
})
return table
}
// 数据字典过滤器
export function dictFilter(obj) {
return function(val) {
return obj?.[val]
}
}
// 特定key的值替换
export function arrInsertVal(arr, key, obj) {
return arr.map(item => {
if (item[key] && obj[key]) {
return {
...item,
[key]: obj[key]
}
} else {
return item
}
})
}
// 判断某个时间是否先于另一个时间
import moment from 'moment'
export function timeIsBefore(a, b) {
if (a && b) {
return moment(a).isBefore(b)
}
}
// tableHeight
export function tableHeight(n) {
return window.innerHeight - n
}

455
src/utils/metricflow.js Normal file
View File

@@ -0,0 +1,455 @@
/* written by Huoyo/Chang Zhang ,please respect copyright*/
/* you can use it freely but can not plagiarize it to pretend that you are the owner*/
export function MetricFlow(domId, options) {
const defaultOptions = {
'flow': (undefined !== options && options.hasOwnProperty('flow')) ? options['flow'] : 'horizontal',
'link-start-offsetx': (undefined !== options && options.hasOwnProperty('link-start-offsetx')) ? 2 + options['link-start-offsetx'] : 2,
'link-start-offsety': (undefined !== options && options.hasOwnProperty('link-start-offsety')) ? -4 + options['link-start-offsety'] : -4,
'link-end-offsetx': (undefined !== options && options.hasOwnProperty('link-end-offsetx')) ? -20 + options['link-end-offsetx'] : -20,
'link-end-offsety': (undefined !== options && options.hasOwnProperty('link-end-offsety')) ? -4 + options['link-end-offsety'] : -4,
'link-width-offset': (undefined !== options && options.hasOwnProperty('link-width-offset')) ? 3 + options['link-width-offset'] : 3,
'link-color': (undefined !== options && options.hasOwnProperty('link-color')) ? options['link-color'] : '#4b804b',
'node-distance-x': (undefined !== options && options.hasOwnProperty('node-distance-offsetx')) ? 100 + options['node-distance-offsetx'] : 100,
'node-distance-y': (undefined !== options && options.hasOwnProperty('node-distance-offsety')) ? 300 + options['node-distance-offsety'] : 300
}
const styleDom = document.getElementsByTagName('style')[0]
if (styleDom !== undefined) {
styleDom.innerHTML += '.ko-node{position:absolute;background-color:#5f665f;border:2px solid #4b804b;border-radius:5px;width:auto;}.ko-node .ko-node-title{padding-left:17px;padding-right:10px;background-color:#4b804b;color:white;}.ko-node .ko-node-body{list-style:none;margin-top:5px;margin-bottom:1px;}.ko-node li{padding-right:10px;margin-left:-23px;color:white;border-bottom:1px solid lightslategray;padding-bottom:2px;font-size:10px;}'
} else {
const style = document.createElement('style')
style.type = 'text/css'
style.rel = 'stylesheet'
style.appendChild(document.createTextNode('.ko-node{position:absolute;background-color:#5f665f;border:2px solid #4b804b;border-radius:5px;width:auto;}.ko-node .ko-node-title{padding-left:17px;padding-right:10px;background-color:#4b804b;color:white;}.ko-node .ko-node-body{list-style:none;margin-top:5px;margin-bottom:1px;}.ko-node li{padding-right:10px;margin-left:-23px;color:white;border-bottom:1px solid lightslategray;padding-bottom:2px;font-size:10px;}'))
const head = document.getElementsByTagName('head')[0]
head.appendChild(style)
}
const o = {}
o.dx = defaultOptions['node-distance-x']
o.dy = defaultOptions['node-distance-y']
o.allNodes = new Map()
o.back = document.getElementById(domId)
o.back.className = 'ko-node-back'
const backWidth = Number(o.back.getAttribute('width').replace('px', '').replace('%', '')) * 2
const backHeight = Number(o.back.getAttribute('height').replace('px', '').replace('%', '')) * 1.5
o.back.innerHTML = '<div id="methods"></div><svg id="svgBack" class="ko-node-back" xmlns="http://www.w3.org/2000/svg" version="1.1" height="' + backHeight + '" width="' + backWidth + '" zdrive="true" cbor="false"><g id="points" stroke="' + defaultOptions['link-color'] + '" stroke-width="' + defaultOptions['link-width-offset'] + '" fill="white"></g><g id="relations" stroke="' + defaultOptions['link-color'] + '" stroke-width="' + defaultOptions['link-width-offset'] + '" fill="none"></g><defs><marker id=\'arrow\' markerWidth=\'13\' markerHeight=\'13\' refx=\'6\' refy=\'7\' orient=\'auto\'><path d=\'M2,10 L6,7 L2,4 L2,10\' style="fill:' + defaultOptions['link-color'] + '"/></marker> </defs></svg>'
o.svgBack = document.getElementById('svgBack')
o.nodesBack = document.getElementById('methods')
o.points = document.getElementById('points')
o.relations = document.getElementById('relations')
let levelInit
function getXy(nodeData, i, w, h) {
const rootX = nodeData['x']
const rootY = nodeData['y']
const level = nodeData['level']
const children = nodeData['children']
const dy = o.dy / Math.pow(2, level)
const childrenLength = children.length
let childX
let childY
if (defaultOptions['flow'] === 'vertical') {
if (childrenLength === 1) {
childX = rootX
childY = rootY + h + o.dx
} else if (childrenLength > 1) {
if (i === 0) {
childX = rootX - (childrenLength - 1) * (w + dy) / 2
childY = rootY + h + o.dx
levelInit.set(level, [childX, childY])
} else {
childX = levelInit.get(level)[0] + i * (w + dy)
childY = levelInit.get(level)[1]
}
}
} else {
if (childrenLength === 1) {
childX = rootX + w + o.dx
childY = rootY
} else if (childrenLength > 1) {
if (i === 0) {
childX = rootX + w + o.dx
childY = rootY - (childrenLength - 1) * (h + dy) / 2
levelInit.set(level, [childX, childY])
} else {
childX = levelInit.get(level)[0]
childY = levelInit.get(level)[1] + i * (h + dy)
}
}
}
return [childX, childY]
}
function recurseNode(nodes, formDataFunc) {
let rootDom
if (formDataFunc !== null && formDataFunc !== undefined) {
rootDom = o.createNode(formDataFunc(nodes))
} else {
rootDom = o.createNode(nodes)
} if (nodes.hasOwnProperty('children')) {
const children = nodes['children']
if (children === null || children === undefined) {
return
}
const rootDomW = Number(rootDom.getAttribute('width'))
const rootDomH = Number(rootDom.getAttribute('height'))
for (const index in children) {
const childData = children[index]
childData['from'] = nodes['id']
if (childData.hasOwnProperty('x') === false) {
const newXy = getXy(nodes, index, rootDomW, rootDomH)
childData['x'] = newXy[0]
childData['y'] = newXy[1]
}
childData['level'] = nodes['level'] + 1
recurseNode(childData, formDataFunc)
}
}
}
o.createNodes = function(nodesData, formDataFunc) {
if (nodesData instanceof Array) {
for (const index in nodesData) {
const createData = nodesData[index]
if (formDataFunc !== null && formDataFunc !== undefined) {
if (createData.hasOwnProperty('children')) {
o.createNodes(createData, formDataFunc)
} else {
o.createNode(formDataFunc(createData))
}
} else {
if (createData.hasOwnProperty('children')) {
o.createNodes(createData)
} else {
o.createNode(createData)
}
}
}
} else if (nodesData.hasOwnProperty('children')) {
if (nodesData.hasOwnProperty('x') === false || nodesData.hasOwnProperty('y') === false) {
console.log('invalid data')
return
}
levelInit = new Map()
nodesData['level'] = 1
recurseNode(nodesData, formDataFunc)
levelInit = null
} else {
if (formDataFunc !== null && formDataFunc !== undefined) {
o.createNode(formDataFunc(nodesData))
} else {
o.createNode(nodesData)
}
}
}
o.createNode = function(param, x, y) {
if (o.allNodes.get(param['id']) !== undefined) {
const node = document.getElementById(param['id'])
return node
}
let nodeText = "<div funcs id='idValue' style='top:topValuepx!important;left:leftValuepx!important;background-color: nodeBackgroundColor;border: 2px solid nodeBorderColor;otherStyle' class='ko-node'> <div class='ko-node-title' style='color: titleColor;background-color: titleBackColor;titleOtherStyle'>dataTitle</div>liBody</div>"
if (param.hasOwnProperty('data')) {
nodeText = nodeText.replace('liBody', "<ul class='ko-node-body'>liBody</ul>")
}
let liText = ''
const liTextTemp = '<li class="ko-node-li" style="background-color: liBackColor;liOtherStyle">LiText</li>'
for (const index in param.data) {
const liBackColor = param.data[index]['background-color'] || '#5f665f'
const liOtherStyle = param.data[index]['style'] || ''
liText += liTextTemp.replace('LiText', param.data[index]['name']).replace('liBackColor', liBackColor).replace('liOtherStyle', liOtherStyle)
}
const titleColor = param['title'].hasOwnProperty('color') ? param['title']['color'] : 'white'
const titleBackColor = param['title'].hasOwnProperty('color') ? param['title']['background-color'] : '#4b804b'
const titleOtherStyle = param['title'].hasOwnProperty('color') ? param['title']['style'] : ''
const nodeBackgroundColor = param.hasOwnProperty('background-color') ? param['background-color'] : '#5f665f'
const nodeBorderColor = param.hasOwnProperty('border-color') ? param['border-color'] : '#4b804b'
const otherStyle = param.hasOwnProperty('style') ? param['style'] : ''
const functionText = getFunctionsText(param)
nodeText = nodeText.replace('nodeBorderColor', nodeBorderColor).replace('nodeBackgroundColor', nodeBackgroundColor).replace('titleColor', titleColor).replace('titleBackColor', titleBackColor).replace('dataTitle', param['title']['name']).replace('idValue', param['id']).replace('topValue', (param['y'] || y)).replace('leftValue', (param['x'] || x)).replace('liBody', liText).replace('otherStyle', otherStyle).replace('titleOtherStyle', titleOtherStyle).replace('funcs', functionText)
o.nodesBack.innerHTML += nodeText
const node = document.getElementById(param['id'])
node.setAttribute('x', (param['x'] || x))
node.setAttribute('y', (param['y'] || y))
node.setAttribute('width', node.offsetWidth)
node.setAttribute('height', node.offsetHeight)
const nodeObject = new Map()
nodeObject.set('ins', [])
nodeObject.set('outs', [])
nodeObject.set('node', node)
o.allNodes.set(node.id, nodeObject)
if (param.hasOwnProperty('from')) {
const fromId = param['from']
if (typeof (fromId) === 'string') {
const from = document.getElementById(fromId)
if (from !== undefined) {
o.createLink(from, node)
}
} else if (fromId instanceof Array) {
for (const i in fromId) {
const from = document.getElementById(fromId[i])
if (from !== undefined) {
o.createLink(from, node)
}
}
}
}
return node
}
function getFunctionsText(param) {
let text = ''
if (param.hasOwnProperty('click')) {
text += ' onclick="' + param['click'] + '(event);"'
}
if (param.hasOwnProperty('dblclick')) {
text += ' ondblclick="' + param['dblclick'] + '(event);"'
}
if (param.hasOwnProperty('mousedown')) {
text += ' onmousedown="' + param['mousedown'] + '(event);"'
}
if (param.hasOwnProperty('mouseenter')) {
text += ' onmouseenter="' + param['mouseenter'] + '(event);"'
}
if (param.hasOwnProperty('mouseleave')) {
text += ' onmouseleave="' + param['mouseleave'] + '(event);"'
}
if (param.hasOwnProperty('mousemove')) {
text += ' onmousemove="' + param['mousemove'] + '(event);"'
}
if (param.hasOwnProperty('mouseover')) {
text += ' onmouseover="' + param['mouseover'] + '(event);"'
}
if (param.hasOwnProperty('mouseout')) {
text += ' onmouseout="' + param['mouseout'] + '(event);"'
}
if (param.hasOwnProperty('mouseup')) {
text += ' onmouseup="' + param['mouseup'] + '(event);"'
}
return text
}
o.createSimLink = function(source, target) {
const sourceTop = Number(source.getAttribute('y'))
const sourceLeft = Number(source.getAttribute('x'))
var sourceWidth = Number(source.getAttribute('width'))
var sourceHeight = Number(source.getAttribute('height'))
const targetTop = Number(target.getAttribute('y'))
const targetLeft = Number(target.getAttribute('x'))
var targetHeight = Number(target.getAttribute('height'))
var targetWidth = Number(target.getAttribute('width'))
// 变量未声明报错添加
let startX, startY, endX, endY
if (defaultOptions['flow'] === 'vertical') {
o.points.innerHTML += "<circle id='pointstart" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (sourceLeft + sourceWidth / 2 + defaultOptions['link-start-offsetx'] - 10) + "' cy='" + (sourceTop + sourceHeight + defaultOptions['link-start-offsety']) + "' r='4' />"
o.points.innerHTML += "<circle id='pointend" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (targetLeft + targetWidth / 2 + defaultOptions['link-end-offsetx'] + 10) + "' cy='" + (targetTop + defaultOptions['link-end-offsety'] - 8) + "' r='4' />"
startX = sourceLeft + sourceWidth / 2 + defaultOptions['link-start-offsetx'] - 10
startY = sourceTop + sourceHeight + defaultOptions['link-start-offsety'] + 2
endX = targetLeft + targetWidth / 2 + defaultOptions['link-end-offsetx'] + 10
endY = targetTop + defaultOptions['link-end-offsety'] - 10
} else {
o.points.innerHTML += "<circle id='pointstart" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (sourceLeft + sourceWidth - 5 + defaultOptions['link-start-offsetx']) + "' cy='" + (sourceTop + sourceHeight / 2 + defaultOptions['link-start-offsety']) + "' r='4' />"
o.points.innerHTML += "<circle id='pointend" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (targetLeft + defaultOptions['link-end-offsetx'] + 4) + "' cy='" + (targetTop + targetHeight / 2 + defaultOptions['link-end-offsety']) + "' r='4' />"
startX = sourceLeft + sourceWidth + defaultOptions['link-start-offsetx']
startY = sourceTop + sourceHeight / 2 + defaultOptions['link-start-offsety']
endX = targetLeft + defaultOptions['link-end-offsetx']
endY = targetTop + targetHeight / 2 + defaultOptions['link-end-offsety']
}
o.relations.innerHTML += "<line id='line-" + source.id + '-' + target.id + "' x1='" + startX + "' y1='" + startY + "' x2='" + endX + "' y2='" + endY + "' marker-end='url(#arrow)'/>"
}
o.createLink = function(source, target) {
const sourceOuts = o.allNodes.get(source.id).get('outs')
const targetIns = o.allNodes.get(target.id).get('ins')
if (sourceOuts.indexOf('line' + source.id + target.id) > -1) {
return
}
const sourceTop = Number(source.getAttribute('y'))
const sourceLeft = Number(source.getAttribute('x'))
var sourceWidth = Number(source.getAttribute('width'))
var sourceHeight = Number(source.getAttribute('height'))
const targetTop = Number(target.getAttribute('y'))
const targetLeft = Number(target.getAttribute('x'))
var targetHeight = Number(target.getAttribute('height'))
var targetWidth = Number(target.getAttribute('width'))
// 变量未声明报错添加
let startX, startY, endX, endY
if (defaultOptions['flow'] === 'vertical') {
o.points.innerHTML += "<circle id='pointstart" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (sourceLeft + sourceWidth / 2 + defaultOptions['link-start-offsetx'] - 10) + "' cy='" + (sourceTop + sourceHeight + defaultOptions['link-start-offsety']) + "' r='4' />"
o.points.innerHTML += "<circle id='pointend" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (targetLeft + targetWidth / 2 + defaultOptions['link-end-offsetx'] + 10) + "' cy='" + (targetTop + defaultOptions['link-end-offsety'] - 8) + "' r='4' />"
startX = sourceLeft + sourceWidth / 2 + defaultOptions['link-start-offsetx'] - 10
startY = sourceTop + sourceHeight + defaultOptions['link-start-offsety'] + 2
endX = targetLeft + targetWidth / 2 + defaultOptions['link-end-offsetx'] + 10
endY = targetTop + defaultOptions['link-end-offsety'] - 10
} else {
o.points.innerHTML += "<circle id='pointstart" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (sourceLeft + sourceWidth - 5 + defaultOptions['link-start-offsetx']) + "' cy='" + (sourceTop + sourceHeight / 2 + defaultOptions['link-start-offsety']) + "' r='4' />"
o.points.innerHTML += "<circle id='pointend" + source.getAttribute('id') + target.getAttribute('id') + "' cx='" + (targetLeft + defaultOptions['link-end-offsetx'] + 4) + "' cy='" + (targetTop + targetHeight / 2 + defaultOptions['link-end-offsety']) + "' r='4' />"
startX = sourceLeft + sourceWidth + defaultOptions['link-start-offsetx']
startY = sourceTop + sourceHeight / 2 + defaultOptions['link-start-offsety']
endX = targetLeft + defaultOptions['link-end-offsetx']
endY = targetTop + targetHeight / 2 + defaultOptions['link-end-offsety']
}
o.relations.innerHTML += "<line id='line-" + source.id + '-' + target.id + "' x1='" + startX + "' y1='" + startY + "' x2='" + endX + "' y2='" + endY + "' marker-end='url(#arrow)'/>"
sourceOuts.push('line-' + source.id + '-' + target.id)
targetIns.push('line-' + source.id + '-' + target.id)
}
function getMouseTarget(eventElement) {
const clssName = eventElement.getAttribute('class')
if (clssName === 'ko-node') {
return eventElement
} else if (clssName === 'ko-node-li') {
return eventElement.parentNode.parentNode
} else if (clssName === 'ko-node-title') {
return eventElement.parentNode
} else if (clssName === 'ko-node-body') {
return eventElement.parentNode
} else {
return eventElement
}
}
function reDrawNodeLines(node) {
const objectData = o.allNodes.get(node.id)
if (objectData === undefined) {
return
}
const inIds = objectData.get('ins')
for (const index in inIds) {
const lineId = inIds[index]
const lineIdSplit = lineId.split('-')
const sourceId = lineIdSplit[1]
const targetId = lineIdSplit[2]
if (document.getElementById(lineId) !== undefined) {
document.getElementById(lineId).remove()
document.getElementById('pointstart' + sourceId + targetId).remove()
document.getElementById('pointend' + sourceId + targetId).remove()
o.createSimLink(document.getElementById(sourceId), node)
}
}
const outIds = o.allNodes.get(node.id).get('outs')
for (const index in outIds) {
const lineId = outIds[index]
const lineIdSplit = lineId.split('-')
const sourceId = lineIdSplit[1]
const targetId = lineIdSplit[2]
if (document.getElementById(lineId) !== undefined) {
document.getElementById(lineId).remove()
document.getElementById('pointstart' + sourceId + targetId).remove()
document.getElementById('pointend' + sourceId + targetId).remove()
o.createSimLink(node, document.getElementById(targetId))
}
}
}
o.reDrawLines = function() {
o.allNodes.forEach(function(nodeData, nodeId) {
reDrawNodeLines(document.getElementById(nodeId))
})
}
o.moveNode
o.moveNodeX = 0
o.moveNodeY = 0
o.back.onmousedown = function(e) {
const mouseTarget = getMouseTarget(e.target)
const clssName = mouseTarget.getAttribute('class')
o.moveNodeX = e.clientX
o.moveNodeY = e.clientY
if (clssName === 'ko-node') {
o.moveNode = mouseTarget
o.moveNode.style.cursor = 'move'
o.moveNode.onmousemove = nodeMove
o.moveNode.onmouseup = nodeMoveClose
}
}
o.svgBack.onmousedown = function(e) {
const mouseTarget = getMouseTarget(e.target)
const clssName = mouseTarget.getAttribute('class')
o.moveNodeX = e.clientX
o.moveNodeY = e.clientY
if (clssName === 'ko-node') {
o.moveNode = mouseTarget
o.moveNode.style.cursor = 'move'
o.moveNode.onmousemove = nodeMove
o.moveNode.onmouseup = nodeMoveClose
} else {
o.moveNode = mouseTarget
o.moveNode.style.cursor = 'move'
o.moveNode.onmousemove = backMove
o.moveNode.onmouseup = nodeMoveClose
}
}
function nodeMove(e) {
e = e || window.event
const offsetX = o.moveNodeX - e.clientX
const offsetY = o.moveNodeY - e.clientY
o.moveNodeX = e.clientX
o.moveNodeY = e.clientY
const xOff = (o.moveNode.offsetLeft - offsetX)
const yOff = (o.moveNode.offsetTop - offsetY)
if (Number.isNaN(xOff) || Number.isNaN(yOff)) {
return
}
o.moveNode.style.top = yOff + 'px'
o.moveNode.style.left = xOff + 'px'
o.moveNode.setAttribute('x', xOff)
o.moveNode.setAttribute('y', yOff)
reDrawNodeLines(o.moveNode)
}
function backMove(e) {
e = e || window.event
const offsetX = o.moveNodeX - e.clientX
const offsetY = o.moveNodeY - e.clientY
o.moveNodeX = e.clientX
o.moveNodeY = e.clientY
o.allNodes.forEach(function(nodeData, nodeId) {
const moveNode = document.getElementById(nodeId)
moveNode.style.top = (moveNode.offsetTop - offsetY) + 'px'
moveNode.style.left = (moveNode.offsetLeft - offsetX) + 'px'
moveNode.setAttribute('x', (moveNode.offsetLeft - offsetX))
moveNode.setAttribute('y', (moveNode.offsetTop - offsetY))
reDrawNodeLines(moveNode)
})
}
function nodeMoveClose(e) {
o.moveNode.style.cursor = 'default'
o.moveNode.onmouseup = null
o.moveNode.onmousemove = null
o.moveNodeX = null
o.moveNodeY = null
}
o.back.onmousemove = function(e) {
var nx = e.clientX
var ny = e.clientY
var nl = nx - (o.moveNodeX - o.l)
var nt = ny - (o.moveNodeY - o.t)
if (o.isDragNode === true) {
o.moveNode.style.left = nl + 'px'
o.moveNode.style.top = nt + 'px'
o.reDrawLines(o.moveNode)
} else if (o.isDragBack === true) {
o.allNodes.forEach(function(value, nodeKey) {
const pmoveNode = document.getElementById(nodeKey)
const nl = nx - o.moveNodeX
const nt = ny - o.moveNodeY
if (nl > 10) {
pmoveNode.style.left = Number(pmoveNode.style.left.replace('px', '')) + 10 + 'px'
} else if (nl < -10) {
pmoveNode.style.left = Number(pmoveNode.style.left.replace('px', '')) - 10 + 'px'
}
if (nt > 6) {
pmoveNode.style.top = Number(pmoveNode.style.top.replace('px', '')) + 10 + 'px'
} else if (nt < -6) {
pmoveNode.style.top = Number(pmoveNode.style.top.replace('px', '')) - 10 + 'px'
}
})
o.reDrawLines()
}
}
o.back.onmouseup = function(e) {
o.isDragNode = false
o.isDragBack = false
if ((o.moveNode !== undefined) && (o.moveNode.hasOwnProperty('style') === true) && (o.moveNode.style.hasOwnProperty('cursor') === true)) {
o.moveNode.style.cursor = 'default'
}
}
return o
}

25
src/utils/open-window.js Normal file
View 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()
}
}

25
src/utils/permission.js Normal file
View File

@@ -0,0 +1,25 @@
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)
})
if (!hasPermission) {
return false
}
return true
} else {
console.error(`need roles! Like v-permission="['admin','editor']"`)
return false
}
}

157
src/utils/request.js Normal file
View File

@@ -0,0 +1,157 @@
/*
* @Date: 2020-12-14 09:07:03
* @LastEditors: gtz
* @LastEditTime: 2022-05-26 10:58:42
* @FilePath: \mt-bus-fe\src\utils\request.js
* @Description:
*/
import axios from 'axios'
import { MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import i18n from '@/lang'
// 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: 15000 // request timeout
})
/*
当页面有两个接口时第一个接口loading的close事件会直接将第二个接口的loading实例也close
每次创建Loading实例的时候判断当前是否存在如果当前还没有Loading实例就创建一个
如果有就不会再创建而是计数;每次关闭的时候判断当前的计数,
如果是0了就关闭否则也计数减一直到为0的时候表示当前所有页面所有接口都返回结束了
此时执行关闭Loading.close()操作
*/
let loadingInstance = null
function startLoading() {
loadingInstance = Loading.service({
fullscreen: false,
text: '拼命加载中...',
background: 'rgba(0, 0, 0, 0.1)'
})
}
function endLoading() {
loadingInstance.close()
}
let needLoadingRequestCount = 0
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
startLoading()
}
needLoadingRequestCount++
}
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return
needLoadingRequestCount--
if (needLoadingRequestCount === 0) {
endLoading()
}
}
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
showFullScreenLoading()
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['token'] = getToken()
}
return config
},
error => {
// do something with request error
tryHideFullScreenLoading()
console.log(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 => {
tryHideFullScreenLoading()
// console.log(response)
const res = response.data
// if the custom code is not 20000, it is judged as an error.
if (response.config.responseType === 'blob') {
return response
}
if (res.code !== 0 && res.code !== 401) {
Message({
message: res.msg || 'Error',
type: 'error',
duration: 5 * 1000
})
// 具体看框架对响应码的定义
if (res.code === 401) {
// to re-login
// to do 添加i18n
MessageBox.confirm('登录信息失效,请重新登录', '提示', {
confirmButtonText: '去登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
}
return Promise.reject(new Error(res.msg || 'Error'))
} else {
return res
}
},
error => {
tryHideFullScreenLoading()
console.log('err' + error) // for debug
if ('err' + error === 'errError: timeout of 15000ms exceeded') {
Message({
message: i18n.t('errorLog.timeoutTip'),
type: 'error',
duration: 5 * 1000
})
} else {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
}
return Promise.reject(error)
}
)
export default service
export function requestWithCache(obj) {
const name = (obj.subname || '') + obj.url
const result = localStorage.getItem(name)
if (result) {
return Promise.resolve(JSON.parse(result))
} else {
return service(obj).then(res => {
localStorage.setItem(name, JSON.stringify(res))
setTimeout(() => {
localStorage.removeItem(name)
}, 60000)
return res
})
}
}

View File

@@ -0,0 +1,36 @@
/*
* @Date: 2021-01-26 10:39:44
* @LastEditors: gtz
* @LastEditTime: 2021-01-27 11:25:20
* @FilePath: \basic-admin\src\utils\requestWithCache.js
* @Description: 带缓存的接口请求
*/
import request from './request'
function getStorage(key) {
const result = localStorage.getItem(key)
if (result) {
return JSON.parse(result)
}
}
// function setStorage(key, value) {
// if (key) {
// return localStorage.setItem(key, JSON.stringify(value))
// }
// }
export default function({ url, method, data, ...rest }) {
// 判断是否有缓存数据
if (getStorage(url)) {
return getStorage(url)
} else {
// setStorage(key, value)
return request({
url,
method,
data,
...rest
})
}
}

58
src/utils/scroll-to.js Normal file
View 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()
}

39
src/utils/tree.js Normal file
View File

@@ -0,0 +1,39 @@
export const getListItems = (root, fVisit) => {
const queue = Array.isArray(root) ? [...root] : [root]
while (queue.length) {
const node = queue.shift()
fVisit && fVisit(node)
const children = node.l
if (children && children.length) {
for (let i = 0; i < children.length; i++) queue.push(children[i])
}
}
}
export const getTreeItems = (menus, idName = 'id', pIdName = 'parentId') => {
if (menus === null || menus.length === 0) {
return undefined
}
// 删除 所有 children,以防止多次调用
menus.forEach((item) => {
delete item.children
})
// 将数据存储为 以 id 为 KEY 的 map 索引数据列
const map = {}
menus.forEach((item) => {
map[item[idName]] = item
})
// console.log(map);
const val = []
menus.forEach((item) => {
// 以当前遍历项的pid,去map对象中找到索引的id
const parent = map[item[pIdName]]
// 好绕啊,如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中
if (parent) {
(parent.children || (parent.children = [])).push(item)
} else {
// 如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中作为顶级
val.push(item)
}
})
return val
}

89
src/utils/validate.js Normal file
View File

@@ -0,0 +1,89 @@
/**
* 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
// TODO:检查手机号码
return true
}
/**
* @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)
}