Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot] 3b0a13cb93
chore(deps): bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-28 22:07:24 +00:00
14 changed files with 68 additions and 196 deletions

View File

@ -1,5 +1,3 @@
简体中文 | [English](./README.en-US.md)
<h1 align="center">Vue Antd Admin</h1>
@ -8,12 +6,6 @@
[Ant Design Pro](https://github.com/ant-design/ant-design-pro) 的 Vue 实现版本
开箱即用的中后台前端/设计解决方案
:star::star::star:
vue3 版本现已推出,更名为
[stepin-template](https://github.com/stepui/stepin-template),欢迎体验,
[立即前往](https://github.com/stepui/stepin-template)
--
[![MIT](https://img.shields.io/github/license/iczer/vue-antd-admin)](https://github.com/iczer/vue-antd-admin/blob/master/LICENSE)
[![Dependence](https://img.shields.io/david/iczer/vue-antd-admin)](https://david-dm.org/iczer/vue-antd-admin)
[![DevDependencies](https://img.shields.io/david/dev/iczer/vue-antd-admin)](https://david-dm.org/iczer/vue-antd-admin?type=dev)

View File

@ -44,7 +44,7 @@ const tokenCheck = {
* `options: Object`: 应用配置,包含: {router, i18n, store, message},可根据需要扩展。
### onRejected
我们会为 onRejected 钩子函数注入 error 和 options 两个参数:
我们会为 onFulfilled 钩子函数注入 error 和 options 两个参数:
* `error: Error`: axios 请求错误对象
* `options: Object`: 应用配置,包含: {router, i18n, store, message},可根据需要扩展。
@ -128,4 +128,4 @@ export default {
response: [resp401, resp403] // 响应拦截
}
```
:::
:::

View File

@ -23,7 +23,7 @@
:expandedRowKeys="expandedRowKeys"
:expandedRowRender="expandedRowRender"
@change="onChange"
:rowSelection="selectedRows ? {selectedRowKeys, onSelect, onSelectAll} : undefined"
:rowSelection="selectedRows ? {selectedRowKeys: selectedRowKeys, onChange: updateSelect} : undefined"
>
<template slot-scope="text, record, index" :slot="slot" v-for="slot in Object.keys($scopedSlots).filter(key => key !== 'expandedRowRender') ">
<slot :name="slot" v-bind="{text, record, index}"></slot>
@ -64,70 +64,22 @@ export default {
}
},
methods: {
equals(record1, record2) {
if (record1 === record2) {
return true
}
const {rowKey} = this
if (rowKey && typeof rowKey === 'string') {
return record1[rowKey] === record2[rowKey]
} else if (rowKey && typeof rowKey === 'function') {
return rowKey(record1) === rowKey(record2)
}
return false
},
contains(arr, item) {
if (!arr || arr.length === 0) {
return false
}
const {equals} = this
for (let i = 0; i < arr.length; i++) {
if (equals(arr[i], item)) {
return true
}
}
return false
},
onSelectAll(selected, rows) {
const {getKey, contains} = this
const unselected = this.dataSource.filter(item => !contains(rows, item, this.rowKey))
const _selectedRows = this.selectedRows.filter(item => !contains(unselected, item, this.rowKey))
const set = {}
_selectedRows.forEach(item => set[getKey(item)] = item)
rows.forEach(item => set[getKey(item)] = item)
const _rows = Object.values(set)
this.$emit('update:selectedRows', _rows)
this.$emit('selectedRowChange', _rows.map(item => getKey(item)), _rows)
},
getKey(record) {
const {rowKey} = this
if (!rowKey || !record) {
return undefined
}
if (typeof rowKey === 'string') {
return record[rowKey]
} else {
return rowKey(record)
}
},
onSelect(record, selected) {
const {equals, selectedRows, getKey} = this
const _selectedRows = selected ? [...selectedRows, record] : selectedRows.filter(row => !equals(row, record))
this.$emit('update:selectedRows', _selectedRows)
this.$emit('selectedRowChange', _selectedRows.map(item => getKey(item)), _selectedRows)
updateSelect (selectedRowKeys, selectedRows) {
this.$emit('update:selectedRows', selectedRows)
this.$emit('selectedRowChange', selectedRowKeys, selectedRows)
},
initTotalList (columns) {
return columns.filter(item => item.needTotal)
const totalList = columns.filter(item => item.needTotal)
.map(item => {
return {
...item,
total: 0
}
})
return totalList
},
onClear() {
this.$emit('update:selectedRows', [])
this.$emit('selectedRowChange', [], [])
this.updateSelect([], [])
this.$emit('clear')
},
onChange(pagination, filters, sorter, {currentDataSource}) {
@ -158,8 +110,10 @@ export default {
},
computed: {
selectedRowKeys() {
return this.selectedRows.map(record => this.getKey(record))
},
return this.selectedRows.map(record => {
return (typeof this.rowKey === 'function') ? this.rowKey(record) : record[this.rowKey]
})
}
}
}
</script>

View File

@ -22,11 +22,10 @@ const ANTD = {
'component-background': '#fff',
'heading-color': 'rgba(0, 0, 0, 0.85)',
'text-color': 'rgba(0, 0, 0, 0.65)',
'text-color-inverse': '#fefefe',
'text-color-inverse': '#fff',
'text-color-secondary': 'rgba(0, 0, 0, 0.45)',
'shadow-color': 'rgba(0, 0, 0, 0.15)',
'border-color-split': '#f0f0f0',
'border-color-base': '#d9d9d9',
'background-color-light': '#fafafa',
'background-color-base': '#f5f5f5',
'table-selected-row-bg': '#fafafa',
@ -35,9 +34,8 @@ const ANTD = {
'disabled-color': 'rgba(0, 0, 0, 0.25)',
'menu-dark-color': 'rgba(254, 254, 254, 0.65)',
'menu-dark-highlight-color': '#fefefe',
'menu-dark-selected-item-icon-color': '#fefefe',
'menu-dark-arrow-color': '#fefefe',
'btn-primary-color': '#fefefe',
'btn-primary-color': '#fff',
},
light: {
'layout-body-background': '#f0f2f5',
@ -45,11 +43,10 @@ const ANTD = {
'component-background': '#fff',
'heading-color': 'rgba(0, 0, 0, 0.85)',
'text-color': 'rgba(0, 0, 0, 0.65)',
'text-color-inverse': '#fefefe',
'text-color-inverse': '#fff',
'text-color-secondary': 'rgba(0, 0, 0, 0.45)',
'shadow-color': 'rgba(0, 0, 0, 0.15)',
'border-color-split': '#f0f0f0',
'border-color-base': '#d9d9d9',
'background-color-light': '#fafafa',
'background-color-base': '#f5f5f5',
'table-selected-row-bg': '#fafafa',
@ -58,9 +55,8 @@ const ANTD = {
'disabled-color': 'rgba(0, 0, 0, 0.25)',
'menu-dark-color': 'rgba(1, 1, 1, 0.65)',
'menu-dark-highlight-color': '#fefefe',
'menu-dark-selected-item-icon-color': '#fefefe',
'menu-dark-arrow-color': '#fefefe',
'btn-primary-color': '#fefefe',
'btn-primary-color': '#fff',
},
night: {
'layout-body-background': '#000',
@ -68,11 +64,10 @@ const ANTD = {
'component-background': '#141414',
'heading-color': 'rgba(255, 255, 255, 0.85)',
'text-color': 'rgba(255, 255, 255, 0.85)',
'text-color-inverse': '#fefefe',
'text-color-inverse': '#141414',
'text-color-secondary': 'rgba(255, 255, 255, 0.45)',
'shadow-color': 'rgba(255, 255, 255, 0.15)',
'border-color-split': '#303030',
'border-color-base': '#282828',
'background-color-light': '#ffffff0a',
'background-color-base': '#2a2a2a',
'table-selected-row-bg': '#ffffff0a',
@ -81,9 +76,8 @@ const ANTD = {
'disabled-color': 'rgba(255, 255, 255, 0.25)',
'menu-dark-color': 'rgba(254, 254, 254, 0.65)',
'menu-dark-highlight-color': '#fefefe',
'menu-dark-selected-item-icon-color': '#fefefe',
'menu-dark-arrow-color': '#fefefe',
'btn-primary-color': '#fefefe',
'btn-primary-color': '#141414',
}
}
}

View File

@ -92,7 +92,7 @@ export default {
let routes = this.$route.matched
const path = this.$route.path
let breadcrumb = []
routes.filter(item => path.includes(item.path) || item.regex.test(path))
routes.filter(item => path.includes(item.path))
.forEach(route => {
const path = route.path.length === 0 ? '/home' : route.path
breadcrumb.push(this.$t(getI18nKey(path)))

View File

@ -95,7 +95,8 @@
this.$emit('contextmenu', pageKey, e)
},
pageName(page) {
const custom = this.customTitles.find(item => item.path === page.path)
const pagePath = page.fullPath.split('?')[0]
const custom = this.customTitles.find(item => item.path === pagePath)
return (custom && custom.title) || page.title || this.$t(getI18nKey(page.keyPath))
}
}

View File

@ -13,7 +13,7 @@
<div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
<a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
<router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
<router-view v-if="!refreshing" ref="tabContent" :key="$route.path" />
</a-keep-alive>
<router-view ref="tabContent" v-else-if="!refreshing" />
</page-toggle-transition>
@ -62,10 +62,10 @@ export default {
this.loadCacheConfig(this.$router?.options?.routes)
this.loadCachedTabs()
const route = this.$route
if (this.pageList.findIndex(item => item.path === route.fullPath) === -1) {
if (this.pageList.findIndex(item => item.path === route.path) === -1) {
this.pageList.push(this.createPage(route))
}
this.activePage = route.fullPath
this.activePage = route.path
if (this.multiPage) {
this.$nextTick(() => {
this.setCachedKey(route)
@ -86,8 +86,8 @@ export default {
this.loadCacheConfig(val)
},
'$route': function (newRoute) {
this.activePage = newRoute.fullPath
const page = this.pageList.find(item => item.path === newRoute.fullPath)
this.activePage = newRoute.path
const page = this.pageList.find(item => item.path === newRoute.path)
if (!this.multiPage) {
this.pageList = [this.createPage(newRoute)]
} else if (page) {
@ -261,7 +261,7 @@ export default {
return {
keyPath: route.matched[route.matched.length - 1].path,
fullPath: route.fullPath, loading: false,
path: route.fullPath,
path: route.path,
title: route.meta && route.meta.page && route.meta.page.title,
unclose: route.meta && route.meta.page && (route.meta.page.closable === false),
}
@ -271,7 +271,7 @@ export default {
* @param route 页面对应的路由
*/
setCachedKey(route) {
const page = this.pageList.find(item => item.path === route.fullPath)
const page = this.pageList.find(item => item.path === route.path)
page.unclose = route.meta && route.meta.page && (route.meta.page.closable === false)
if (!page._init_) {
const vnode = this.$refs.tabContent.$vnode
@ -301,7 +301,7 @@ export default {
routes.forEach(item => {
const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true
if (!cacheAble) {
this.excludeKeys.push(new RegExp(`${item.path.replace(/:[^/]*/g, '[^/]*')}(\\?.*)?\\d*$`))
this.excludeKeys.push(new RegExp(`${item.path}\\d+$`))
}
if (item.children) {
this.loadCacheConfig(item.children, cacheAble)

View File

@ -5,7 +5,6 @@ import '@/mock/user/login'
import '@/mock/workplace'
import '@/mock/user/routes'
import '@/mock/goods'
import '@/mock/list'
// 设置全局延时
Mock.setup({

View File

@ -1,52 +0,0 @@
import Mock from 'mockjs'
import '@/mock/extend'
import {parseUrlParams} from '@/utils/request'
const current = new Date().getTime()
const source = Mock.mock({
'list|100': [{
'key|+1': 0,
'no': `${current}-@integer(1,100)`,
'description': '这是一段描述',
'callNo|0-50': 5,
'status|1-4': 1,
'updatedAt': '@DATETIME',
}]
})
Mock.mock(RegExp(`${process.env.VUE_APP_API_BASE_URL}/list` + '.*'),'get', ({url}) => {
const params = parseUrlParams(decodeURI(url))
let {page, pageSize} = params
page = eval(page) - 1 || 0
pageSize = eval(pageSize) || 10
delete params.page
delete params.pageSize
let result = source.list.filter(item => {
for (let [key, value] of Object.entries(params)) {
if (item[key] !== value) {
return false
}
}
return true
})
const total = result.length
if ((page) * pageSize > total) {
result = []
} else {
result = result.slice(page * pageSize, (page + 1) * pageSize)
}
return {
code: 0,
message: 'success',
data: {
page: page + 1,
pageSize,
total: 100,
list: result
}
}
})

View File

@ -98,7 +98,6 @@
:selectedRows.sync="selectedRows"
@clear="onClear"
@change="onChange"
:pagination="{...pagination, onChange: onPageChange}"
@selectedRowChange="onSelectChange"
>
<div slot="description" slot-scope="{text}">
@ -129,7 +128,6 @@
<script>
import StandardTable from '@/components/table/StandardTable'
import {request} from '@/utils/request'
const columns = [
{
title: '规则编号',
@ -163,6 +161,19 @@ const columns = [
}
]
const dataSource = []
for (let i = 0; i < 100; i++) {
dataSource.push({
key: i,
no: 'NO ' + i,
description: '这是一段描述',
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 4,
updatedAt: '2018-07-26'
})
}
export default {
name: 'QueryList',
components: {StandardTable},
@ -170,37 +181,14 @@ export default {
return {
advanced: true,
columns: columns,
dataSource: [],
selectedRows: [],
pagination: {
current: 1,
pageSize: 10,
total: 0
}
dataSource: dataSource,
selectedRows: []
}
},
authorize: {
deleteRecord: 'delete'
},
mounted() {
this.getData()
},
methods: {
onPageChange(page, pageSize) {
this.pagination.current = page
this.pagination.pageSize = pageSize
this.getData()
},
getData() {
request(process.env.VUE_APP_API_BASE_URL + '/list', 'get', {page: this.pagination.current,
pageSize: this.pagination.pageSize}).then(res => {
const {list, page, pageSize, total} = res?.data?.data ?? {}
this.dataSource = list
this.pagination.current = page
this.pagination.pageSize = pageSize
this.pagination.total = total
})
},
deleteRecord(key) {
this.dataSource = this.dataSource.filter(item => item.key !== key)
this.selectedRows = this.selectedRows.filter(item => item.key !== key)

View File

@ -17,9 +17,8 @@ const TabsPagePlugin = {
},
$setPageTitle(route, title) {
if (title) {
// let path = typeof route === 'object' ? route.path : route
// path = path && path.split('?')[0]
let path = typeof route === 'object' ? this.$router.resolve(route).route.fullPath : route
let path = typeof route === 'object' ? route.path : route
path = path && path.split('?')[0]
this.$store.commit('setting/setCustomTitle', {path, title})
}
}
@ -27,8 +26,8 @@ const TabsPagePlugin = {
computed: {
customTitle() {
const customTitles = this.$store.state.setting.customTitles
// const path = this.$route.path.split('?')[0]
const custom = customTitles.find(item => item.path === this.$route.fullPath)
const path = this.$route.path.split('?')[0]
const custom = customTitles.find(item => item.path === path)
return custom && custom.title
}
}

View File

@ -8,12 +8,10 @@ function hasPermission(authority, permissions) {
let required = '*'
if (typeof authority === 'string') {
required = authority
} else if (Array.isArray(authority)) {
required = authority
} else if (typeof authority === 'object') {
required = authority.permission
}
return required === '*' || hasAnyItem(required, permissions, (r, t) => !!(r === t || r === t.id))
return required === '*' || (permissions && permissions.findIndex(item => item === required || item.id === required) !== -1)
}
/**
@ -26,23 +24,25 @@ function hasRole(authority, roles) {
if (typeof authority === 'object') {
required = authority.role
}
return authority === '*' || hasAnyItem(required, roles, (r, t) => !!(r === t || r === t.id))
return authority === '*' || hasAnyRole(required, roles)
}
/**
* 判断目标数组是否有所需元素
* @param {String | String[]}required 所需元素数组或单个元素
* @param {String[]|Object[]} source 目标数组
* @param {Function} filter 匹配条件
* (r: String, s: String|Object) => boolean
* 判断是否有需要的任意一个角色
* @param required {String | Array[String]} 需要的角色可以是单个角色或者一个角色数组
* @param roles 拥有的角色
* @returns {boolean}
*/
function hasAnyItem(required, source, filter) {
function hasAnyRole(required, roles) {
if (!required) {
return false
} else if(Array.isArray(required)) {
return roles.findIndex(role => {
return required.findIndex(item => item === role || item === role.id) !== -1
}) !== -1
} else {
return roles.findIndex(role => role === required || role.id === required) !== -1
}
let checkedList = Array.isArray(required) ? required : [required]
return !!source.find(s => checkedList.find(r => filter(r, s)))
}
/**

View File

@ -75,9 +75,6 @@ function parseRoutes(routesConfig, routerMap) {
redirect: routeCfg.redirect || router.redirect,
meta: {...meta, authority: meta.authority || '*'}
}
if (router.beforeEnter) {
route.beforeEnter = router.beforeEnter
}
if (routeCfg.invisible || router.invisible) {
route.meta.invisible = true
}
@ -215,7 +212,7 @@ function formatAuthority(routes, pAuthorities = []) {
let authority = {}
if (!meta.authority) {
authority = defaultAuthority
}else if (typeof meta.authority === 'string' || Array.isArray(meta.authority)) {
}else if (typeof meta.authority === 'string') {
authority.permission = meta.authority
} else if (typeof meta.authority === 'object') {
authority = meta.authority

View File

@ -2148,9 +2148,9 @@ async-validator@^3.0.3:
integrity sha1-HZIZO75g1tbIskZpLHAF6e0UqO4=
async@^2.6.1, async@^2.6.2:
version "2.6.3"
resolved "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=
version "2.6.4"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
dependencies:
lodash "^4.17.14"
@ -6491,9 +6491,9 @@ lodash.uniq@^4.5.0:
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^2.2.0:
version "2.2.0"