升级ui vue3版本

This commit is contained in:
吕金泽
2022-03-05 10:42:10 +08:00
parent 4b2134065e
commit 8b8095b91a
367 changed files with 135973 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
import global from './global'
import request from '@/scripts/request'
const TokenKey = 'magic_boot_token'
export function getToken() {
return localStorage.getItem(TokenKey);
}
export function setToken(token) {
localStorage.setItem(TokenKey, token);
}
export function removeToken() {
localStorage.removeItem(TokenKey);
global.user = {
token: '',
authorities: [],
info: {},
permissionRoutes: []
}
}
export async function getUserInfo() {
await request({
url: 'user/info',
method: 'get'
}).then(response => {
const { data } = response
if(data){
var authorities_ = []
for (var i = 0; i < data.authorities.length; i++) {
authorities_.push(data.authorities[i])
}
global.user.authorities = authorities_
global.user.info = data
}
})
}
export function login(data){
return new Promise((resolve, reject) => {
request({
url: 'security/login',
method: 'post',
data
}).then(res => {
var token = res.data
setToken(token)
resolve(token)
})
})
}
export function logout(){
request({
url: 'security/logout',
method: 'get'
}).then(() => {
removeToken()
location.reload()
})
}
+170
View File
@@ -0,0 +1,170 @@
import request from '@/scripts/request'
import { ElMessageBox, ElNotification } from 'element-plus'
import global from '@/scripts/global'
const common = {}
let dictData = []
common.getDictData = async function() {
await request({
url: 'dict/items/all',
method: 'get'
}).then((response) => {
const { data } = response
dictData = data
})
}
common.getDictType = (type) => {
return dictData.filter(it => it.type === type)
}
common.getDictLabel = (type, value) => {
var values = []
value.split(',').forEach(v => {
const list = dictData.filter(it => it.type === type && it.value === v + '')
values.push(list && list[0] && list[0].label || '')
})
return values.join(',')
}
common.handleDelete = (options) => {
const url = options.url
const id = options.id
ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
request({
url: url,
method: 'post',
params: {
id: id
}
}).then(() => {
ElNotification({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
options && options.done()
})
})
}
const formatJson = (list, filterVal) => {
return list.map(v => filterVal.map(j => {
return v[j]
}))
}
common.renderWhere = (where) => {
var newWhere = {}
for(var key in where) {
if(where[key] instanceof Object){
newWhere[key] = where[key].value
}else{
newWhere[key] = where[key]
}
}
return newWhere
}
common.exportExcel = (options) => {
var where = options.where || {}
where = common.renderWhere(where)
where.current = 1
where.size = 99999999
const url = options.url
const headers = options.headers
const columns = options.columns
request({
url: url,
method: 'post',
params: where
}).then(res => {
import('@/vendor/Export2Excel').then(excel => {
const data = formatJson(res.data, columns)
excel.export_json_to_excel({
header: headers,
data,
filename: 'table-list'
})
})
})
}
common.handlerTreeData = (data, id, pid, sort, pidVal) => {
var treeData = []
var addChildren = (it) => {
var children = data.filter(d => d[pid] === it[id])
if (children && children.length > 0) {
children.sort((a, b) => {
return a[sort] - b[sort]
})
it.children = children
children.forEach(chi => {
addChildren(chi)
})
}
}
data.sort((a, b) => {
return a[sort] - b[sort]
})
data.filter(it => it[pid] === pidVal).forEach(it => {
addChildren(it)
treeData.push(it)
})
return treeData
}
common.uuid = () => {
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
return (S4()+S4()+S4()+S4()+S4()+S4()+S4()+S4());
}
common.objAssign = (obj1, obj2, exclude) => {
exclude = exclude || ''
for (var o1 in obj1) {
for (var o2 in obj2) {
if (o1 === o2) {
if(exclude.indexOf(o1) == -1){
obj1[o1] = obj2[o2]
}
}
}
}
}
common.copyNew = (obj) => {
return JSON.parse(JSON.stringify(obj))
}
common.getParam = (data) => {
let url = ''
for (var k in data) {
const value = data[k] !== undefined ? data[k] : ''
url += `&${k}=${encodeURIComponent(value)}`
}
return url ? url.substring(1) : ''
}
common.getUrl = (url, data) => {
url += (url.indexOf('?') < 0 ? '?' : '') + common.getParam(data)
return url
}
common.loadConfig = async() => {
await request({
url: 'config/list'
}).then(res => {
const { data } = res
global.filePrefix = data.filePrefix
})
}
export default common
+14
View File
@@ -0,0 +1,14 @@
import { reactive, ref } from 'vue'
export default {
title: 'Magic Boot',
user: {
token: '',
authorities: [],
info: {},
permissionRoutes: []
},
filePrefix: '',
visitedViews: reactive([]),
tabValue: ref('')
}
@@ -0,0 +1,30 @@
import * as PlusIcons from '@element-plus/icons-vue'
import VueUeditorWrap from 'vue-ueditor-wrap'
import request from './request'
import global from './global'
import common from './common'
import treeTable from './treeTable'
const install = (app) => {
app.config.globalProperties.$request = request
app.config.globalProperties.$post = (url, data) => request.post(url, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: [data => Object.keys(data).map(it => encodeURIComponent(it) + '=' + encodeURIComponent(data[it] === null || data[it] === undefined ? '' : data[it])).join('&')]
})
app.config.globalProperties.$postJson = (url, data) => request.post(url, JSON.stringify(data), {
headers: {
'Content-Type': 'application/json'
}
})
app.config.globalProperties.$get = (url, data) => request({ url, params: data })
app.config.globalProperties.$global = global
app.config.globalProperties.$common = common
app.config.globalProperties.$treeTable = treeTable
for(var key in PlusIcons) {
app.component(`El${key}`, PlusIcons[key])
}
app.use(VueUeditorWrap)
}
export default install
@@ -0,0 +1,17 @@
const hasPermission = {
install(app) {
app.directive('permission', {
beforeMount(el, binding) {
if (binding.value) {
const permissionList = app.config.globalProperties.$global.user.authorities
if (permissionList && permissionList.length && !permissionList.includes(binding.value) && import.meta.env.NODE_ENV != 'preview') {
el.style.display = 'none'
}
}
}
})
}
}
export default hasPermission
+115
View File
@@ -0,0 +1,115 @@
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { logout, login } from '@/scripts/auth'
import { getToken } from '@/scripts/auth'
import global from '@/scripts/global'
// create an axios instance
const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 1000 * 60 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
if (getToken()) {
// 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
console.log(error) // for debug
return Promise.reject(error)
}
)
var currentMessage
// 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 => {
if (response.config.url.indexOf('user/info') !== -1 && response.data.code === 402) {
logout()
}
return new Promise((reslove, reject) => {
const res = response.data
if (res.code !== 200) {
var duration = 5
if (res.code === 402) {
duration = 1
ElMessageBox.prompt(`当前账号:${global.user.info.username}凭证已过期,请输入密码重新登录`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '退出',
inputType: 'password',
closeOnClickModal: false,
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
login({
username: global.user.info.username,
password: instance.inputValue
}).then((res) => {
if (res) {
done()
service(response.config).then(ret => reslove(ret))
}
})
} else if (action === 'cancel') {
logout()
} else {
done()
}
}
})
}
if (res.code !== 402) {
if(currentMessage){
currentMessage.close()
}
if(res.code == 403 && import.meta.env.NODE_ENV == 'preview'){
res.message = '演示模式,不允许操作!'
}
currentMessage = ElMessage({
message: res.message || 'Error',
type: 'error',
duration: duration * 1000,
showClose: true
})
reject(res)
}
} else {
reslove(res)
}
})
},
error => {
// console.log('err' + error) // for debug
if(currentMessage){
currentMessage.close()
}
currentMessage = ElMessage({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
+67
View File
@@ -0,0 +1,67 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '@/layout/layout.vue'
const routes = [
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index')
}
]
},
{
path: '/',
component: Layout,
redirect: '/home',
children: [
{
name: '首页',
path: '/home',
component: () => import('@/views/home.vue')
}
]
},
{
path: '/user-center',
redirect: '/system/user/user-center',
component: Layout,
hidden: true,
children: [{
path: '/system/user/user-center',
name: '个人中心',
component: () => import('@/views/system/user/user-center'),
meta: { title: '个人中心' }
}]
},
{
path: '/login',
component: () => import('@/views/login.vue'),
hidden: true
},
// {
// path: '/404',
// name: '404',
// component: () => import('@/views/404.vue'),
// hidden: true
// },
// {
// path: '/:pathMatch(.*)*',
// redirect: '/404',
// hidden: true
// }
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
@@ -0,0 +1,55 @@
import request from '@/scripts/request'
import common from '@/scripts/common'
import { defineAsyncComponent } from 'vue'
export const filterAsyncRouter = (routers, level) => {
level = level || 0
const accessedRouters = routers.filter(router => {
if (router.isShow === 1) {
if (router.componentName) {
router.component = loadView(`/common/parse-component`)
router.props = {
name: router.componentName,
code: router.code
}
} else if (router.component) {
const component = router.component
if (component === 'Layout') {
router.path = "/" + common.uuid()
router.component = level > 0 ? import(`../layout/none.vue`) : loadLayoutView(component)
} else {
router.path = router.path = router.path.startsWith('/') ? router.path : '/' + router.path
router.component = loadView(component)
}
}
if (router.children && router.children.length) {
router.children = filterAsyncRouter(router.children, level + 1)
}
return true
}
return false
})
return accessedRouters
}
export const loadLayoutView = (view) => {
return import(`../layout/layout.vue`)
}
export const loadView = (view) => {
view = view.substring(0, 1) === '/' ? view : '/' + view
return defineAsyncComponent(() => import(`../views${view}.vue`))
}
export function generateRoutes(){
return new Promise((resolve, reject) => {
request({
url: 'menu/current/menus',
method: 'post'
}).then(response => {
const { data } = response
const asyncRouter = filterAsyncRouter(data)
resolve(asyncRouter)
})
})
}
+58
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()
}
+6
View File
@@ -0,0 +1,6 @@
const svgs = import.meta.glob('../icons/*.svg')
const svgNames = []
for (const [key, value] of Object.entries(svgs)) {
svgNames.push(key.substring(key.lastIndexOf('/') + 1, key.lastIndexOf('.')))
}
export default svgNames
+96
View File
@@ -0,0 +1,96 @@
import common from "@/scripts/common";
const treeTable = {}
treeTable.isChildren = (children, id) => {
var result = false
for(var i in children) {
var chi = children[i]
if(chi.id == id){
result = true
}
if(chi.children && children.length > 0){
if(treeTable.isChildren(chi.children, id)){
result = true
}
}
}
return result
}
treeTable.queryChildren = (children, id) => {
var result = []
for(var i in children){
var chi = children[i]
if(chi.id == id){
if(chi.children && chi.children.length > 0){
result = chi.children
}
}else{
var qc = treeTable.queryChildren(chi.children, id)
if(qc.length > 0){
result = qc
}
}
}
return result
}
treeTable.genTree = (children) => {
var treeData = []
for(var i in children){
var chi = {}
chi.label = children[i].name
chi.id = children[i].id
if(children[i].children && children[i].children.length > 0){
chi.children = treeTable.genTree(children[i].children)
}
treeData.push(chi)
}
return treeData
}
treeTable.deleteEmptyChildren = (children) => {
for(var i in children){
var chi = children[i]
if(chi.children && chi.children.length == 0){
delete chi.children
}else{
treeTable.deleteEmptyChildren(chi.children)
}
}
}
treeTable.recursionSearch = (fields, data, text, html) => {
html = html != undefined ? html : true
var searchData = []
for(var i in data){
var treeNode = data[i]
var children = treeNode.children
if(children && children.length > 0){
var childrenSearch = treeTable.recursionSearch(fields, children, text, html)
treeNode.children = childrenSearch && childrenSearch.length > 0 ? childrenSearch : treeNode.children
treeTable.treeNodeReplace(fields, searchData, treeNode, text, childrenSearch, html)
}else{
treeTable.treeNodeReplace(fields, searchData, treeNode, text, null, html)
}
}
return searchData
}
treeTable.treeNodeReplace = (fields, searchData, treeNode, text, childrenSearch, html) => {
var exist = false
fields.forEach((f) => {
if(treeNode[f] && treeNode[f].indexOf(text) != -1){
if(html){
treeNode[f] = treeNode[f].replace(text, `<font color="#FAA353">${text}</font>`)
}
exist = true
}
})
if(exist || (childrenSearch && childrenSearch.length > 0)){
searchData.push(treeNode)
}
}
export default treeTable
+87
View File
@@ -0,0 +1,87 @@
/**
* 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} 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)
}