This commit is contained in:
孟帅
2022-02-25 17:11:17 +08:00
parent 9bd05abb2c
commit 8f3d679a57
897 changed files with 95731 additions and 0 deletions

View File

@@ -0,0 +1,269 @@
import storage from 'store'
import { ACCESS_TOKEN } from '@/store/mutation-types'
/**
* 通用js方法封装处理
* Copyright (c) 2019 aidex
*/
const baseURL = process.env.VUE_APP_BASE_API
// 日期格式化
export function parseTime (time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
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 timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return timeStr
}
// 表单重置
export function resetForm (refName) {
if (this[refName]) {
this[refName].resetFields()
}
}
// 添加日期范围
export function addDateRange (params, dateRange, propName) {
var search = params
// search.params = {}
if (dateRange !== null && dateRange !== '' && dateRange.length === 2) {
if (typeof (propName) === 'undefined') {
search.start_time = dateRange[0]
search.end_time = dateRange[1]
} else {
const startTime = propName + '_start_time'
const endTime = propName + '_end_time'
search[startTime] = dateRange[0]
search[endTime] = dateRange[1]
}
}
return search
}
// 回显数据字典
export function selectDictLabel (datas, value) {
var actions = []
Object.keys(datas).some((key) => {
if (datas[key].value === ('' + value)) {
actions.push(datas[key].label)
return true
}
})
return actions.join('')
}
// 回显数据字典(字符串数组)
export function selectDictLabels (datas, value, separator) {
var actions = []
var currentSeparator = undefined === separator ? ',' : separator
var temp = value.split(currentSeparator)
Object.keys(value.split(currentSeparator)).some((val) => {
Object.keys(datas).some((key) => {
if (datas[key].value === ('' + temp[val])) {
actions.push(datas[key].label + currentSeparator)
}
})
})
return actions.join('').substring(0, actions.join('').length - 1)
}
// 通用导出下载
export function exportDownload(path, params) {
let url = baseURL + path + '?'
params.authorization = storage.get(ACCESS_TOKEN)
for (const propName of Object.keys(params)) {
const value = params[propName]
var part = encodeURIComponent(propName) + '='
// 修改漏洞
if (value != null && typeof (value) !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
const params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + '='
url += subPart + encodeURIComponent(value[key]) + '&'
}
} else {
url += part + encodeURIComponent(value) + '&'
}
}
}
url = url.slice(0, -1)
window.location.href = url
}
// 通用下载方法
export function download (fileName, delFlag) {
if (delFlag === undefined) {
delFlag = true
}
window.location.href = baseURL + '/common/download?fileName=' + encodeURI(fileName) + '&delete=' + delFlag
}
// 通用下载方法
export function downloadByPath (filePath, delFlag) {
if (delFlag === undefined) {
delFlag = true
}
window.location.href = baseURL + '/common/downloadByPath?filePath=' + encodeURI(filePath) + '&delete=' + delFlag
}
// 通用下载到导出任务中心
export function downloadTask () {
this.$router.push({
name: 'SysDownloadFiles',
params: {
key: new Date().toLocaleString()
}
})
}
// 字符串格式化(%s )
export function sprintf (str) {
var args = arguments
var flag = true
var i = 1
str = str.replace(/%s/g, function () {
var arg = args[i++]
if (typeof arg === 'undefined') {
flag = false
return ''
}
return arg
})
return flag ? str : ''
}
// 转换字符串undefined,null等转化为''
export function praseStrEmpty (str) {
if (!str || str === 'undefined' || str === 'null') {
return ''
}
return str
}
/**
* 构造树型结构数据
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
* @param {*} rootId 根Id 默认 0
*/
export function handleTree (data, id, parentId, children, rootId) {
id = id || 'id'
parentId = parentId || 'parentId'
children = children || 'children'
rootId = rootId || '0'
// 对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data))
// 循环所有项
const treeData = cloneData.filter(father => {
var branchArr = cloneData.filter(child => {
// 返回每一项的子级数组
return father[id] === child[parentId]
})
if (branchArr.length > 0) {
father.children = branchArr
} else {
father.children = ''
}
// 返回第一层
return father[parentId] === rootId
})
return treeData !== '' && treeData == null ? treeData : data
}
/**
* 从树中移除指定节点
* @param {Object} list
* @param {Object} node
*/
export function removeTreeNode (list, node) {
console.log('node' + JSON.stringify(node))
const parentList = list
// const parentIds = node.pid.split('/')
const parentIds = node.pid
const currentNodeId = node.id
deleteTreeNode(parentList, list, parentIds, currentNodeId)
}
export function deleteTreeNode (parentList, list, parentIds, currentNodeId) {
for (let s = 0; s < list.length; s++) {
if (list[s].id === currentNodeId) {
list.splice(s, 1)
return
} else if (list[s].children && list[s].children.length > 0) { // 递归条件
// parentIds.splice(0, 1)
deleteTreeNode(list[s], list[s].children, parentIds, currentNodeId)
} else {
continue
}
}
}
export function appendTreeNode (node, data) {
// if (node.treeLeaf === 'y') {
// // 如果节点是叶子节点则直接改为非叶子节点
// node.treeLeaf = 'n'
// node.children.push(data)
// } else {
// const children = node.children
// if (children.length > 0) {
// // 有子节点则直接push数据否则不做操作等待异步加载
// node.children.push(data)
// }
// }
// console.log('node,' + JSON.stringify(node))
// console.log('data,' + JSON.stringify(data))
const children = node.children
if (children.length > 0) {
// 有子节点则直接push数据否则不做操作等待异步加载
node.children.push(data)
}
}
/**
* 按展开几层展开树
* @param {Object} nodes
* @param {Object} expandLevel
* @param {Object} expandedRowKeys 记录展开key
*/
export function expandTree (nodes, expandLevel, expandedRowKeys) {
if (expandLevel > 1) {
// 最后一层不展开
nodes.forEach(node => {
expandedRowKeys.push(node.id)
expandLevel = expandLevel - 1
return expandTree(node.children, expandLevel, expandedRowKeys)
})
}
}

View File

@@ -0,0 +1,35 @@
const VueAxios = {
vm: {},
// eslint-disable-next-line no-unused-vars
install (Vue, instance) {
if (this.installed) {
return
}
this.installed = true
if (!instance) {
// eslint-disable-next-line no-console
console.error('You have to install axios')
return
}
Vue.axios = instance
Object.defineProperties(Vue.prototype, {
axios: {
get: function get () {
return instance
}
},
$http: {
get: function get () {
return instance
}
}
})
}
}
export {
VueAxios
}

View File

@@ -0,0 +1,21 @@
import config from '@/config/defaultSettings'
export const setDocumentTitle = function (title) {
document.title = title
const ua = navigator.userAgent
// eslint-disable-next-line
const regex = /\bMicroMessenger\/([\d\.]+)/
if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) {
const i = document.createElement('iframe')
i.src = '/favicon.ico'
i.style.display = 'none'
i.onload = function () {
setTimeout(function () {
i.remove()
}, 9)
}
document.body.appendChild(i)
}
}
export const domTitle = config.title

View File

@@ -0,0 +1,95 @@
const draggable = {
install (Vue) {
Vue.directive('drag', {
inserted (el, binding) {
if (window.Element && !Element.prototype.closest) {
Element.prototype.closest = function (s) {
const matches = (this.document || this.ownerDocument).querySelectorAll(s)
let i
let el = this
do {
i = matches.length
} while (i < 0 && (el = el.parentElement))
return el
}
}
let overWin = false // 拖动是否能超出屏幕,默认不能
if (binding.value) {
overWin = binding.value.over || false
}
const moveTitle = el.parentNode.parentNode.parentNode.querySelector('.ant-modal-header')
el.style.width = '100%'
el.style.height = moveTitle.offsetHeight + 'px'
el.style.position = 'absolute'
el.style.left = 0
el.style.top = 0
el.style.cursor = 'move'
const odiv = el // 获取当前元素操作区
const moveDom = el.closest('.ant-modal') // 位移元素,当前只对a-modal生效
odiv.onmousedown = e => {
const moveDomLeft = moveDom.offsetLeft // 位移元素初始横轴位置
const moveDomTop = moveDom.offsetTop // 位移元素初始纵轴位置
const moveDomW = moveDom.offsetWidth // 位移元素初始宽
const moveDomH = moveDom.offsetHeight // 位移元素初始高
const winWidth = document.body.clientWidth // 父容器初始宽
const winHeight = document.body.clientHeight // 父容器初始高
// 设置位移元素可移动
moveDom.style.position = 'absolute'
moveDom.style.top = moveDomTop + 'px'
moveDom.style.left = moveDomLeft + 'px'
// 算出鼠标相对元素的位置
const disX = e.clientX
const disY = e.clientY
document.onmousemove = e => {
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
const left = e.clientX - disX // X轴相对位移量
const top = e.clientY - disY // Y轴相对位移量
let toMoveTop = 0 // 纵轴最终坐标
let toMoveLeft = 0 // 横轴最终坐标
if (!overWin) {
// 不可超出屏幕时计算移动边界
if (moveDomTop + top + moveDomH > winHeight) {
toMoveTop = winHeight - moveDomH
} else if (moveDomTop + top < 0) {
// 解决漏洞toMoveTop默认为0这里无需重复赋值
// toMoveTop = 0
} else {
toMoveTop = moveDomTop + top
}
if (moveDomLeft + left < 0) {
// 解决漏洞toMoveLeft默认为0这里无需重复赋值
// toMoveLeft = 0
} else if (moveDomLeft + left + moveDomW > winWidth) {
toMoveLeft = winWidth - moveDomW
} else {
toMoveLeft = moveDomLeft + left
}
} else {
// 让弹窗飞
toMoveTop = moveDomTop + top
toMoveLeft = moveDomLeft + left
}
// 移动当前元素
moveDom.style.top = toMoveTop + 'px'
moveDom.style.left = toMoveLeft + 'px'
}
document.onmouseup = () => {
// 注销事件
document.onmousemove = null
document.onmouseup = null
}
}
}
})
}
}
export default draggable

View File

@@ -0,0 +1,7 @@
export default {
'0': '操作成功!',
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}

View File

@@ -0,0 +1,20 @@
import Vue from 'vue'
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
Vue.filter('NumberFormat', function (value) {
if (!value) {
return '0'
}
const intPartFormat = value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断
return intPartFormat
})
Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
return moment(dataStr).format(pattern)
})
Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
return moment(dataStr).format(pattern)
})

View File

@@ -0,0 +1,29 @@
// src/utils/highlight.js 文件路径,纯属自定义
// highlight.js 代码高亮指令
import Hljs from 'highlight.js'
import 'highlight.js/styles/vs.css' // 代码高亮风格,选择更多风格需导入 node_modules/hightlight.js/styles/ 目录下其它css文件
const Highlight = {}
// 自定义插件
Highlight.install = function (Vue) {
// 自定义指令 v-highlight
Vue.directive('highlight', {
// 被绑定元素插入父节点时调用
inserted: function (el) {
const blocks = el.querySelectorAll('pre code')
for (let i = 0; i < blocks.length; i++) {
Hljs.highlightBlock(blocks[i])
}
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用
componentUpdated: function (el) {
const blocks = el.querySelectorAll('pre code')
for (let i = 0; i < blocks.length; i++) {
Hljs.highlightBlock(blocks[i])
}
}
})
}
export default Highlight

View File

@@ -0,0 +1,385 @@
/**
* 控制表单列数布局
* @param layout 列布局: 1,2,3,4
*/
const formColLayout = function (layout, colSetting, fixedSetting) {
if (layout && layout === '1') {
// 1列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 6, sm: 6, lg: 6, xl: 6 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 18, sm: 18, lg: 18, xl: 18 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 6, sm: 6, lg: 6, xl: 6 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 18, sm: 18, lg: 18, xl: 18 }
}
}
} else if (layout && layout === '2') {
// 2列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 12, sm: 12, lg: 12, xl: 12 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 8, sm: 8, lg: 8, xl: 8 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 16, sm: 16, lg: 16, xl: 16 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 4, sm: 4, lg: 4, xl: 4 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 20, sm: 20, lg: 20, xl: 20 }
}
}
} else if (layout && layout === '3') {
// 3列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 8, sm: 8, lg: 8, xl: 8 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 9, sm: 9, lg: 9, xl: 9 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 15, sm: 15, lg: 15, xl: 15 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 3, sm: 3, lg: 3, xl: 3 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 21, sm: 21, lg: 21, xl: 21 }
}
}
} else if (layout && layout === '4') {
// 4列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 6, sm: 6, lg: 6, xl: 6 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 8, sm: 8, lg: 8, xl: 8 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 16, sm: 16, lg: 16, xl: 16 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 2, sm: 2, lg: 2, xl: 2 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 22, sm: 22, lg: 22, xl: 22 }
}
}
} else {
// 默认1列
return {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol: { xs: 4, sm: 4, lg: 4, xl: 4 },
wrapperCol: { xs: 20, sm: 20, lg: 20, xl: 20 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol: { xs: 4, sm: 4, lg: 4, xl: 4 },
wrapperCol: { xs: 20, sm: 20, lg: 20, xl: 20 }
}
}
}
}
/**
* 控制详情页表单列数布局
* @param layout 列布局: 1,2,3,4
*/
const flowformColLayout = function (layout, colSetting, fixedSetting) {
if (layout && layout === '1') {
// 1列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
colSetting && colSetting.labelCol
? colSetting.labelCol
: { xs: 22, sm: 22, lg: 22, xl: 22 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 22, sm: 22, lg: 22, xl: 22 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 24, sm: 24, lg: 24, xl: 24 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 20, sm: 20, lg: 20, xl: 20 }
}
}
} else if (layout && layout === '2') {
// 2列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 12, sm: 12, lg: 12, xl: 12 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 6, sm: 6, lg: 6, xl: 6 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 18, sm: 18, lg: 18, xl: 18 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 3, sm: 3, lg: 3, xl: 3 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 21, sm: 21, lg: 21, xl: 21 }
}
}
} else if (layout && layout === '3') {
// 3列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 8, sm: 8, lg: 8, xl: 8 },
labelCol:
colSetting && colSetting.labelCol ? colSetting.labelCol : { xs: 6, sm: 6, lg: 6, xl: 6 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 18, sm: 18, lg: 18, xl: 18 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 2, sm: 2, lg: 2, xl: 2 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 22, sm: 22, lg: 22, xl: 22 }
}
}
} else if (layout && layout === '4') {
// 4列
return {
cols: colSetting && colSetting.cols ? colSetting.cols : { xs: 6, sm: 6, lg: 6, xl: 6 },
labelCol:
colSetting && colSetting.labelCol
? colSetting.labelCol
: { xs: 24, sm: 24, lg: 24, xl: 24 },
wrapperCol:
colSetting && colSetting.wrapperCol
? colSetting.wrapperCol
: { xs: 24, sm: 24, lg: 24, xl: 24 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol:
fixedSetting && fixedSetting.labelCol
? fixedSetting.labelCol
: { xs: 24, sm: 24, lg: 24, xl: 24 },
wrapperCol:
fixedSetting && fixedSetting.wrapperCol
? fixedSetting.wrapperCol
: { xs: 24, sm: 24, lg: 24, xl: 24 }
}
}
} else {
// 默认1列
return {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol: { xs: 4, sm: 4, lg: 4, xl: 4 },
wrapperCol: { xs: 20, sm: 20, lg: 20, xl: 20 },
fixed: {
cols: { xs: 24, sm: 24, lg: 24, xl: 24 },
labelCol: { xs: 4, sm: 4, lg: 4, xl: 4 },
wrapperCol: { xs: 20, sm: 20, lg: 20, xl: 20 }
}
}
}
}
/**
* 控制弹窗modal的宽高
* @param widthRatio 弹窗modal宽度占屏幕比例
* @param heightRatio 弹窗modal高度占屏幕比例
* @param cutHeight 弹窗modal的body的高度比整个弹窗modal少的高度
* @param bodyOverflowY 弹窗modal的body的overflow-y属性
*/
const modalWidthAndHeight = function (
widthRatio = 0.7,
heightRatio = 0.7,
cutHeight = 40,
bodyOverflowY = 'auto',
backgroundColor = '#fff'
) {
const modalStyleWidth = document.documentElement.clientWidth * widthRatio + 'px'
// let modalStyleHeight = document.documentElement.clientHeight * heightRatio + 'px';
const bodyStyleWidth = document.documentElement.clientWidth * widthRatio + 'px'
const bodyStyleHeight = document.documentElement.clientHeight * heightRatio - cutHeight + 'px'
return {
modalStyle: {
// 弹窗宽高控制
width: modalStyleWidth,
height: 'auto'
},
bodyStyle: {
// 弹窗body宽高控制
width: bodyStyleWidth,
height: bodyStyleHeight,
overflowY: bodyOverflowY,
backgroundColor
}
}
}
/**
* 根据布局列数控制弹窗modal的宽高
* (单列: 580*420 适用于1~6项内容时、
* 两列960*500 适用于6~12项内容时、
* 三列1280*600 适用于12项以上
* @param layout 列数
* @param cutHeight 弹窗modal的body的高度比整个弹窗modal少的高度
* @param bodyOverflowY 弹窗modal的body的overflow-y属性
*/
const modalWidthAndHeightBylayout = function (
layout = 1,
cutHeight = 40,
bodyOverflowY = 'auto',
backgroundColor = '#fff'
) {
let modalStyleWidth = null
// let modalStyleHeight = document.documentElement.clientHeight * heightRatio + 'px';
let bodyStyleWidth = null
let bodyStyleHeight = null
let bodyStylePadding = null
if (layout === 1) {
modalStyleWidth = 580 + 'px'
bodyStyleWidth = 580 + 'px'
bodyStyleHeight = 420 - cutHeight + 'px'
bodyStylePadding = '20px 50px'
} else if (layout === 2) {
modalStyleWidth = 960 + 'px'
bodyStyleWidth = 960 + 'px'
bodyStyleHeight = 500 - cutHeight + 'px'
bodyStylePadding = '20px'
} else if (layout === 3) {
modalStyleWidth = 1280 + 'px'
bodyStyleWidth = 1280 + 'px'
bodyStyleHeight = 600 - cutHeight + 'px'
bodyStylePadding = '20px 40px'
}
return {
modalStyle: {
// 弹窗宽高控制
width: modalStyleWidth,
height: 'auto'
},
bodyStyle: {
// 弹窗body宽高控制
width: bodyStyleWidth,
height: bodyStyleHeight,
padding: bodyStylePadding,
overflowY: bodyOverflowY,
backgroundColor
}
}
}
/**
* 获取内容高度: 传入元素的父元素高度 - 父元素除去内容之外的元素的高度
* @param wrapId 元素的id
* @param cutHeight 内容与父元素相差的高度,一般包括:父元素padding,按钮高度及margin,及其他
*/
const getContentHeight = function (params) {
// 默认值auto
let contentHeight = 'auto'
if (params) {
// 获取元素父元素
const el = document.querySelector('#' + params.wrapId)
if (el) {
// 获取父元素高度
const parentHeight = el.parentNode.offsetHeight
// 传入的元素高度设为父元素高度
// el.style.height = parentHeight + 'px'; 为加resize改变大小,注释掉这句.
// 内容高度为 父元素高度 减去 父元素除去内容之外的元素的高度
if (params.cutHeight) {
contentHeight = parentHeight - params.cutHeight + 'px'
} else {
contentHeight = parentHeight + 'px'
}
}
}
return contentHeight
}
/**
* 校验不通过,滚动到校验不通过元素位置,提示用户
*/
const getFirstCheckErrorElement = function (err) {
for (const key in err) {
// return document.querySelector("div[for='" + key + "']") || document.querySelector("div[for='" + key + "Alias']") || document.querySelector("div[for='" + key + "Name']");
return document.querySelector('#' + key)
}
}
const appointModalWidthAndHeight = function (
height,
width,
cutHeight,
bodyOverflowY = 'auto',
backgroundColor = '#fff'
) {
let modalStyleWidth
let bodyStyleWidth
let bodyStyleHeight
if (width === '100%' && height === '100%') {
// 全屏模式
modalStyleWidth = document.documentElement.clientWidth + 'px'
bodyStyleWidth = document.documentElement.clientWidth + 'px'
bodyStyleHeight = document.documentElement.clientHeight - cutHeight + 'px'
} else {
// 指定宽高
modalStyleWidth = width + 'px'
bodyStyleWidth = width + 'px'
bodyStyleHeight = height - cutHeight + 'px'
}
return {
modalStyle: {
// 弹窗宽高控制
width: modalStyleWidth,
height: 'auto'
},
bodyStyle: {
// 弹窗body宽高控制
width: bodyStyleWidth,
height: bodyStyleHeight,
overflowY: bodyOverflowY,
backgroundColor
}
}
}
export {
formColLayout,
flowformColLayout,
modalWidthAndHeight,
modalWidthAndHeightBylayout,
getContentHeight,
getFirstCheckErrorElement,
appointModalWidthAndHeight
}

View File

@@ -0,0 +1,136 @@
import axios from 'axios'
import store from '@/store'
import storage from 'store'
import notification from 'ant-design-vue/es/notification'
import { VueAxios } from './axios'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import errorCode from '@/utils/errorCode'
// 创建 axios 实例
const request = axios.create({
// API 请求的默认前缀
baseURL: process.env.VUE_APP_BASE_API,
// baseURL: 'https://aidex.setworld.net',
timeout: 20000 // 请求超时时间
})
// 异常拦截处理器
const errorHandler = (error) => {
console.log('err' + error)
let { message } = error
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
notification.error({
message: message,
duration: 5
})
// return Promise.reject(error) //注释该行,否则接口请求失败会一直请求刷新错误数据,这里保证请求一次
}
// request interceptor
request.interceptors.request.use(config => {
const token = storage.get(ACCESS_TOKEN)
// 如果 token 存在
// 让每个请求携带自定义 token 请根据实际情况自行修改
if (token) {
config.headers['Authorization'] = 'Bearer ' + token // 让每个请求携带自定义token 请根据实际情况自行修改
// config.headers['accessAccess-Token'] = token
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?'
for (const propName of Object.keys(config.params)) {
const value = config.params[propName]
var part = encodeURIComponent(propName) + '='
// 修改漏洞
if (value != null && typeof (value) !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
const params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + '='
url += subPart + encodeURIComponent(value[key]) + '&'
}
} else {
url += part + encodeURIComponent(value) + '&'
}
}
}
url = url.slice(0, -1)
config.params = {}
config.url = url
}
return config
}, errorHandler)
// response interceptor
request.interceptors.response.use((res) => {
// 请求rul
const requestUrl = res.config.url
// 未设置状态码则默认成功状态
const code = res.data.code || 0
// 获取错误信息
const msg = errorCode[code] || res.data.message || errorCode['default']
if (code === 401) {
notification.open({
key: 'loginExpireTip',
message: '系统提示',
description: '登录状态已过期,请重新登录',
btn: h => {
return h(
'a-button',
{
props: {
type: 'primary',
size: 'small'
},
on: {
click: () => {
store.dispatch('Logout').then(() => {
location.href = '/index'
})
}
}
},
'确认'
)
},
duration: 0,
onClose: close
})
} else if (code === 500) {
if (requestUrl !== '/login') {
notification.error({
message: msg,
description: msg
})
}
} else if (code !== 0) {
notification.error({
message: msg,
duration: 5
})
} else {
return res.data.data
}
return Promise.reject(msg)
}, errorHandler)
const installer = {
vm: {},
install(Vue) {
Vue.use(VueAxios, request)
}
}
export default request
export {
installer as VueAxios,
request as axios
}

View File

@@ -0,0 +1,9 @@
const req = require.context('../assets/icons', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys()
const re = /\.\/(.*)\.svg/
const icons = requireAll(req).map(i => {
return i.match(re)[1]
})
export default icons

View File

@@ -0,0 +1,30 @@
import cloneDeep from 'lodash.clonedeep'
export function convertRoutes (nodes) {
if (!nodes) return null
nodes = cloneDeep(nodes)
let queue = Array.isArray(nodes) ? nodes.concat() : [nodes]
while (queue.length) {
const levelSize = queue.length
for (let i = 0; i < levelSize; i++) {
const node = queue.shift()
if (!node.children || !node.children.length) continue
node.children.forEach(child => {
// 转化相对路径
if (child.path[0] !== '/' && !child.path.startsWith('http')) {
child.path = node.path.replace(/(\w*)[/]*$/, `$1/${child.path}`)
}
})
queue = queue.concat(node.children)
}
}
return nodes
}

View File

@@ -0,0 +1,5 @@
/* eslint-disable */
export const printANSI = () => {
// console.clear()
// 这里可以配置首次加载输出到控制台的brand
}

128
hotgo-web/src/utils/util.js Normal file
View File

@@ -0,0 +1,128 @@
export function timeFix () {
const time = new Date()
const hour = time.getHours()
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}
export function welcome () {
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
const index = Math.floor(Math.random() * arr.length)
return arr[index]
}
/**
* 触发 window.resize
*/
export function triggerWindowResizeEvent () {
const event = document.createEvent('HTMLEvents')
event.initEvent('resize', true, true)
event.eventType = 'message'
window.dispatchEvent(event)
}
export function handleScrollHeader (callback) {
let timer = 0
let beforeScrollTop = window.pageYOffset
callback = callback || function () {}
window.addEventListener(
'scroll',
event => {
clearTimeout(timer)
timer = setTimeout(() => {
let direction = 'up'
const afterScrollTop = window.pageYOffset
const delta = afterScrollTop - beforeScrollTop
if (delta === 0) {
return false
}
direction = delta > 0 ? 'down' : 'up'
callback(direction)
beforeScrollTop = afterScrollTop
}, 50)
},
false
)
}
export function isIE () {
const bw = window.navigator.userAgent
const compare = (s) => bw.indexOf(s) >= 0
const ie11 = (() => 'ActiveXObject' in window)()
return compare('MSIE') || ie11
}
/**
* Remove loading animate
* @param id parent element id or class
* @param timeout
*/
export function removeLoadingAnimate (id = '', timeout = 1500) {
if (id === '') {
return
}
setTimeout(() => {
document.body.removeChild(document.getElementById(id))
}, timeout)
}
/**
* 随机生成数字
* @param min 最小值
* @param max 最大值
* @return int 生成后的数字
*/
export function randomNumber (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
/**
* 随机生成字符串
* @param length 字符串的长度
* @param chats 可选字符串区间(只会生成传入的字符串中的字符)
* @return string 生成的字符串
*/
export function randomString (length, chats) {
if (!length) length = 1
if (!chats) chats = '0123456789qwertyuioplkjhgfdsazxcvbnm'
let str = ''
for (let i = 0; i < length; i++) {
const num = randomNumber(0, chats.length - 1)
str += chats[num]
}
return str
}
/**
* 随机生成uuid
* @return string 生成的uuid
*/
export function randomUUID () {
const chats = '0123456789abcdef'
return randomString(32, chats)
}
/**
* json对象单层,转换url参数
* @param {*} paramObj
*/
export function formateObjToParamStr (paramObj) {
const sdata = []
for (const attr in paramObj) {
sdata.push(`${attr} = ${filter(paramObj[attr])}`)
}
return sdata.join('&')
}
// 过滤特殊符号
function filter (str) {
// 特殊字符转义
str += '' // 隐式转换
str = str.replace(/%/g, '%25')
str = str.replace(/\+/g, '%2B')
str = str.replace(/ /g, '%20')
str = str.replace(/\//g, '%2F')
str = str.replace(/\?/g, '%3F')
str = str.replace(/&/g, '%26')
str = str.replace(/=/g, '%3D')
str = str.replace(/#/g, '%23')
return str
}

View File

@@ -0,0 +1,50 @@
.textOverflow() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.textOverflowMulti(@line: 3, @bg: #fff) {
position: relative;
max-height: @line * 1.5em;
margin-right: -1em;
padding-right: 1em;
overflow: hidden;
line-height: 1.5em;
text-align: justify;
&::before {
position: absolute;
right: 14px;
bottom: 0;
padding: 0 1px;
background: @bg;
content: '...';
}
&::after {
position: absolute;
right: 14px;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: white;
content: '';
}
}
// mixins for clearfix
// ------------------------
.clearfix() {
zoom: 1;
&::before,
&::after {
display: table;
content: ' ';
}
&::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
}

View File

@@ -0,0 +1,83 @@
/**
* @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 validMap = ['admin', 'editor']
return validMap.indexOf(str.trim()) >= 0
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL (url) {
const reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-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)
}

View File

@@ -0,0 +1,42 @@
import axios from 'axios'
import storage from 'store'
import { ACCESS_TOKEN } from '@/store/mutation-types'
const mimeMap = {
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
zip: 'application/zip'
}
const baseUrl = process.env.VUE_APP_BASE_API
export function downLoadZip (str, filename) {
var url = baseUrl + str
axios({
method: 'get',
url: url,
responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + storage.get(ACCESS_TOKEN) }
}).then(res => {
resolveBlob(res, mimeMap.zip)
})
}
/**
* 解析blob响应内容并下载
* @param {*} res blob响应内容
* @param {String} mimeType MIME类型
*/
export function resolveBlob (res, mimeType) {
const aLink = document.createElement('a')
var blob = new Blob([res.data], { type: mimeType })
// //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
var patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
var contentDisposition = decodeURI(res.headers['content-disposition'])
var result = patt.exec(contentDisposition)
console.log(result)
var fileName = result[1]
fileName = fileName.replace(/"/g, '')
aLink.href = URL.createObjectURL(blob)
aLink.setAttribute('download', fileName) // 设置下载文件名称
document.body.appendChild(aLink)
aLink.click()
document.body.removeChild(aLink)
}