Compare commits

...
17 Commits
Author SHA1 Message Date
hooray 25458835e9 chore: release v2.0.2 2022-10-15 04:05:54 +08:00
hooray abc0ac8e4c chore: 更新依赖 2022-10-14 18:42:59 +08:00
hooray 0e222b986d revert: 回退部分定位组件的 z-index 设置,强制重写 v-loading 的 z-index 样式 2022-10-13 19:19:11 +08:00
hooray 925ee00287 fix: 调整部分定位组件的z-index层级
element plus 的 v-loading 遮罩层默认 z-index 为 2000
导致会遮挡住框架部分组件
2022-10-13 14:21:47 +08:00
hooray d9291175b9 docs: 路由导航守卫代码注释调整 2022-10-13 14:19:13 +08:00
hooray c2e9b16917 refactor: 优化代码逻辑 2022-10-13 14:15:23 +08:00
hooray c0881951d3 chore: 更新依赖 2022-10-13 14:12:48 +08:00
hooray f0c6ddd221 chore: 调整文件忽略 2022-10-12 01:35:34 +08:00
hooray 07b9e31b22 fix: 修复获取侧边栏导航最深一级路由可能返回为空的问题 2022-10-12 01:30:40 +08:00
hooray a0708253af refactor: 简化导航守卫里的逻辑 2022-10-12 01:29:32 +08:00
hooray a1e1f2e4db chore: 更新依赖 2022-10-10 23:43:55 +08:00
Hooray b93c86aa44 chore: 更新依赖 2022-10-09 02:41:17 +08:00
Hooray 49e78d5c20 style: 更新 stylelint 规则 2022-10-03 22:12:09 +08:00
Hooray 33ea08fa4b style: 控制语句代码风格调整 2022-10-02 03:29:37 +08:00
Hooray 0e89630b54 docs: 更新 readme 链接 2022-09-30 14:27:31 +08:00
Hooray d6d67d357d style: 优化文件生成模版 2022-09-29 22:04:29 +08:00
Hooray 848e107388 chore: 更新依赖 2022-09-29 21:59:19 +08:00
46 changed files with 725 additions and 713 deletions
-2
View File
@@ -1,2 +0,0 @@
dist/
node_modules/
+4 -1
View File
@@ -1,3 +1,6 @@
{
"extends": "@antfu"
"extends": "@antfu",
"rules": {
"curly": ["error", "all"]
}
}
+1
View File
@@ -5,3 +5,4 @@ dist-ssr
*.local
src/assets/sprites/*.*
!src/assets/sprites/.gitkeep
public/icons
+4 -7
View File
@@ -1,14 +1,9 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-standard-scss",
"stylelint-config-standard-vue/scss"
],
"overrides": [
{
"files": ["**/*.scss"],
"customSyntax": "postcss-scss"
}
],
"plugins": [
"stylelint-scss"
],
@@ -18,6 +13,8 @@
"property-no-unknown": null,
"font-family-no-missing-generic-family-keyword": null,
"selector-class-pattern": null,
"max-line-length": null
"max-line-length": null,
"scss/double-slash-comment-empty-line-before": null,
"scss/no-global-function-names": null
}
}
+2 -2
View File
@@ -11,8 +11,8 @@
( <a href="https://hooray.github.io/fantastic-admin" target="_blank">备用</a> )
<span>&nbsp;|&nbsp;</span>
演示
( <a href="https://hooray.gitee.io/fantastic-admin/vue3/basic" target="_blank">基础版</a>
<a href="https://hooray.gitee.io/fantastic-admin/vue3/pro" target="_blank">专业版</a> )
( <a href="https://hooray.gitee.io/fantastic-admin-example" target="_blank">基础版</a>
<a href="https://hooray.gitee.io/fantastic-admin-pro-example" target="_blank">专业版</a> )
<span>&nbsp;|&nbsp;</span>
<a href="https://hooray.gitee.io/fantastic-admin/support.html" target="_blank">技术支持</a>
<span>&nbsp;|&nbsp;</span>
+14 -15
View File
@@ -1,5 +1,5 @@
{
"version": "2.0.1",
"version": "2.0.2",
"scripts": {
"dev": "vite",
"build:test": "vue-tsc --noEmit && vite build --mode test",
@@ -18,11 +18,11 @@
},
"dependencies": {
"@tinymce/tinymce-vue": "^5.0.0",
"@vueuse/core": "^9.2.0",
"@vueuse/integrations": "^9.2.0",
"@vueuse/core": "^9.3.0",
"@vueuse/integrations": "^9.3.0",
"axios": "^0.27.2",
"dayjs": "^1.11.5",
"element-plus": "^2.2.17",
"element-plus": "^2.2.18",
"hotkeys-js": "^3.10.0",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",
@@ -30,25 +30,25 @@
"nprogress": "^0.2.0",
"path-browserify": "^1.0.1",
"path-to-regexp": "^6.2.1",
"pinia": "^2.0.22",
"pinia": "^2.0.23",
"qs": "^6.11.0",
"tinymce": "^6.2.0",
"vue": "^3.2.39",
"vue": "^3.2.41",
"vue-router": "^4.1.5"
},
"devDependencies": {
"@antfu/eslint-config": "^0.27.0",
"@iconify-json/ep": "^1.1.7",
"@iconify-json/ep": "^1.1.8",
"@iconify/vue": "^4.0.0",
"@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0",
"@types/qs": "^6.9.7",
"@vitejs/plugin-vue": "^3.1.0",
"@vitejs/plugin-vue": "^3.1.2",
"@vitejs/plugin-vue-jsx": "^2.0.1",
"autoprefixer": "^10.4.12",
"bumpp": "^8.2.1",
"cz-git": "^1.3.11",
"eslint": "^8.24.0",
"eslint": "^8.25.0",
"esno": "^0.16.3",
"fs-extra": "^10.1.0",
"http-server": "^14.1.1",
@@ -56,18 +56,17 @@
"lint-staged": "^13.0.3",
"plop": "^3.1.1",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.5",
"sass": "^1.55.0",
"stylelint": "^14.12.1",
"stylelint": "^14.13.0",
"stylelint-config-standard": "^28.0.0",
"stylelint-config-standard-scss": "^5.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-scss": "^4.3.0",
"svgo": "^2.8.0",
"typescript": "^4.8.3",
"typescript": "^4.8.4",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.7",
"vite": "^3.1.3",
"unplugin-vue-components": "^0.22.8",
"vite": "^3.1.8",
"vite-plugin-banner": "^0.5.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
@@ -78,7 +77,7 @@
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-layouts": "^0.6.0",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.40.13"
"vue-tsc": "^1.0.7"
},
"config": {
"commitizen": {
+8 -7
View File
@@ -36,22 +36,23 @@ module.exports = {
name: 'name',
message: '请输入组件名称',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '组件名称不能为空'
else
}
else {
return true
}
},
},
],
actions: (data) => {
let path = ''
if (data.isGlobal)
if (data.isGlobal) {
path = 'src/components/{{properCase name}}/index.vue'
else
}
else {
path = `${data.path}/components/{{properCase name}}/index.vue`
}
const actions = [
{
type: 'add',
+4 -3
View File
@@ -28,11 +28,12 @@ module.exports = {
name: 'name',
message: '请输入文件名',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '文件名不能为空'
else
}
else {
return true
}
},
},
],
+2 -2
View File
@@ -4,8 +4,8 @@ const use{{ properCase name }}Store = defineStore(
{
state: () => ({}),
getters: {},
actions: {}
}
actions: {},
},
)
export default use{{ properCase name }}Store
+5 -4
View File
@@ -6,11 +6,12 @@ module.exports = {
name: 'name',
message: '请输入模块名称',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '模块名称不能为空'
else
}
else {
return true
}
},
},
],
@@ -18,7 +19,7 @@ module.exports = {
const actions = [
{
type: 'add',
path: 'src/store/modules/{{camelCase name}}.js',
path: 'src/store/modules/{{camelCase name}}.ts',
templateFile: 'plop-templates/store/index.hbs',
},
]
+487 -487
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+8 -7
View File
@@ -14,27 +14,28 @@ const buttonConfig = ref({
// 侧边栏主导航当前实际宽度
const mainSidebarActualWidth = computed(() => {
let actualWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--g-main-sidebar-width'))
if (['head', 'single'].includes(settingsStore.menu.menuMode))
if (['head', 'single'].includes(settingsStore.menu.menuMode)) {
actualWidth = 0
}
return `${actualWidth}px`
})
// 侧边栏次导航当前实际宽度
const subSidebarActualWidth = computed(() => {
let actualWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--g-sub-sidebar-width'))
if (settingsStore.menu.subMenuCollapse)
if (settingsStore.menu.subMenuCollapse) {
actualWidth = 64
}
return `${actualWidth}px`
})
watch(() => settingsStore.app.colorScheme, () => {
if (settingsStore.app.colorScheme === 'dark')
if (settingsStore.app.colorScheme === 'dark') {
document.documentElement.classList.add('dark')
else
}
else {
document.documentElement.classList.remove('dark')
}
}, {
immediate: true,
})
+8 -8
View File
@@ -25,9 +25,9 @@ api.interceptors.request.use(
* 全局拦截请求发送前提交的参数
* 以下代码为示例,在请求头里带上 token 信息
*/
if (userStore.isLogin && request.headers)
if (userStore.isLogin && request.headers) {
request.headers.Token = userStore.token
}
// 是否将 POST 请求参数进行字符串化处理
if (request.method === 'post') {
// request.data = qs.stringify(request.data, {
@@ -63,15 +63,15 @@ api.interceptors.response.use(
},
(error) => {
let message = error.message
if (message === 'Network Error')
if (message === 'Network Error') {
message = '后端网络故障'
else if (message.includes('timeout'))
}
else if (message.includes('timeout')) {
message = '接口请求超时'
else if (message.includes('Request failed with status code'))
}
else if (message.includes('Request failed with status code')) {
message = `接口${message.substr(message.length - 3)}异常`
}
ElMessage({
message,
type: 'error',
-1
View File
@@ -6,5 +6,4 @@
"overlay": #1d1e1f,
)
);
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
@@ -5,6 +5,5 @@
// )
// )
// );
@use "element-plus/theme-chalk/src/index.scss" as *;
@use "./dark.scss";
+4
View File
@@ -82,3 +82,7 @@ textarea {
margin-left: 10px;
}
}
.el-loading-mask {
z-index: 900 !important;
}
+5 -7
View File
@@ -1,12 +1,10 @@
// 文字超出隐藏,默认为单行超出隐藏,可设置多行
@mixin text-overflow($line: 1, $fixed-width: true) {
@if ($line == 1 and $fixed-width == true) {
@if $line == 1 and $fixed-width == true {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@else {
} @else {
/* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
-webkit-box-orient: vertical;
@@ -19,17 +17,17 @@
@mixin position-center($type: x) {
position: absolute;
@if ($type == x) {
@if $type == x {
left: 50%;
transform: translateX(-50%);
}
@if ($type == y) {
@if $type == y {
top: 50%;
transform: translateY(-50%);
}
@if ($type == xy) {
@if $type == xy {
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
+4 -4
View File
@@ -15,9 +15,9 @@ const emit = defineEmits(['checkAll', 'checkNull'])
const checkAll = computed({
get() {
let flag = false
if (props.data.length !== 0 && props.data.length === props.selectionData.length)
if (props.data.length !== 0 && props.data.length === props.selectionData.length) {
flag = true
}
return flag
},
set(newVal) {
@@ -27,9 +27,9 @@ const checkAll = computed({
const isIndeterminate = computed(() => {
let flag = false
if (props.selectionData.length > 0 && props.selectionData.length < props.data.length)
if (props.selectionData.length > 0 && props.selectionData.length < props.data.length) {
flag = true
}
return flag
})
</script>
+4 -4
View File
@@ -48,12 +48,12 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传文件只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传文件大小不能超过 ${props.size}MB!`)
}
return isTypeOk && isSizeOk
}
+6 -6
View File
@@ -75,15 +75,15 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传图片只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)
if (isTypeOk && isSizeOk)
}
if (isTypeOk && isSizeOk) {
uploadData.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
const onProgress: UploadProps['onProgress'] = (file) => {
+10 -10
View File
@@ -81,12 +81,12 @@ function remove(index: number) {
// 移动
function move(index: number, type: 'left' | 'right') {
const url = props.url
if (type === 'left' && index !== 0)
if (type === 'left' && index !== 0) {
url[index] = url.splice(index - 1, 1, url[index])[0]
if (type === 'right' && index !== url.length - 1)
}
if (type === 'right' && index !== url.length - 1) {
url[index] = url.splice(index + 1, 1, url[index])[0]
}
emit('update:url', url)
}
@@ -95,15 +95,15 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传图片只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)
if (isTypeOk && isSizeOk)
}
if (isTypeOk && isSizeOk) {
uploadData.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
const onProgress: UploadProps['onProgress'] = (file) => {
+10 -7
View File
@@ -91,18 +91,20 @@ function anyToCode(value: any[], dictionarie: any[] = pcasData.value) {
const input: string[] = []
if (value.length > 0) {
const findItem = dictionarie.find((item) => {
if (props.format === 'code')
if (props.format === 'code') {
return item.code === value[0]
else if (props.format === 'name')
}
else if (props.format === 'name') {
return item.name === value[0]
else
}
else {
return item.name === value[0].name && item.code === value[0].code
}
})
input.push(findItem.code)
if (findItem.children)
if (findItem.children) {
input.push(...anyToCode(value.slice(1 - value.length), findItem.children))
}
}
return input
}
@@ -125,8 +127,9 @@ function codeToAny(codes: string[], dictionarie: any[] = pcasData.value): any {
})
}
const newCodes = codes.slice(1 - codes.length)
if (newCodes.length > 0 && findItem.children)
if (newCodes.length > 0 && findItem.children) {
output.push(...codeToAny(newCodes, findItem.children))
}
}
return output
}
+2 -2
View File
@@ -32,9 +32,9 @@ const transformStyle = computed(() => {
break
}
}
if (props.rotate !== 0)
if (props.rotate !== 0) {
style.push(`rotate(${props.rotate}deg)`)
}
return `transform: ${style.join(' ')};`
})
</script>
+2 -2
View File
@@ -24,9 +24,9 @@ const props = defineProps({
const isUp = computed(() => {
let isUp = props.type === 'up'
if (props.reverse)
if (props.reverse) {
isUp = !isUp
}
return isUp
})
</script>
+2 -1
View File
@@ -31,8 +31,9 @@ onMounted(() => {
const { copy, copied, isSupported } = useClipboard()
watch(copied, (val) => {
if (val)
if (val) {
ElMessage.success('复制成功,请粘贴到 src/settings.ts 文件中!')
}
})
function handleCopy() {
+2 -2
View File
@@ -22,9 +22,9 @@ const to = computed(() => {
const rtn: {
name?: string
} = {}
if (settingsStore.dashboard.enable)
if (settingsStore.dashboard.enable) {
rtn.name = 'dashboard'
}
return rtn
})
</script>
+26 -23
View File
@@ -38,15 +38,15 @@ const resultList = computed(() => {
let result = []
result = sourceList.value.filter((item) => {
let flag = false
if (item.title.includes(searchInput.value))
if (item.title.includes(searchInput.value)) {
flag = true
if (item.path.includes(searchInput.value))
}
if (item.path.includes(searchInput.value)) {
flag = true
if (item.breadcrumb.some(b => b.includes(searchInput.value)))
}
if (item.breadcrumb.some(b => b.includes(searchInput.value))) {
flag = true
}
return flag
})
return result
@@ -111,9 +111,9 @@ onMounted(() => {
function hasChildren(item: Route.recordRaw) {
let flag = true
if (item.children && item.children.every(i => i.meta.sidebar === false))
if (item.children && item.children.every(i => i.meta.sidebar === false)) {
flag = false
}
return flag
}
function getSourceList(arr: Route.recordRaw[], basePath?: string, icon?: string, breadcrumb?: string[]) {
@@ -127,12 +127,12 @@ function getSourceList(arr: Route.recordRaw[], basePath?: string, icon?: string,
else {
breadcrumbTemp.push(typeof item.meta.title === 'function' ? item.meta.title() : item.meta.title)
let path = ''
if (isExternalLink(item.path))
if (isExternalLink(item.path)) {
path = item.path
else
}
else {
path = basePath ? [basePath, item.path].join('/') : item.path
}
sourceList.value.push({
icon: item.meta.icon || icon,
title: typeof item.meta.title === 'function' ? item.meta.title() : item.meta.title,
@@ -165,24 +165,25 @@ function getSourceListByMenus(arr: Menu.recordRaw[], icon?: string, breadcrumb?:
function keyUp() {
if (resultList.value.length) {
actived.value -= 1
if (actived.value < 0)
if (actived.value < 0) {
actived.value = resultList.value.length - 1
}
handleScroll()
}
}
function keyDown() {
if (resultList.value.length) {
actived.value += 1
if (actived.value > resultList.value.length - 1)
if (actived.value > resultList.value.length - 1) {
actived.value = 0
}
handleScroll()
}
}
function keyEnter() {
if (actived.value !== -1)
if (actived.value !== -1) {
searchResultItemRef.value[actived.value].click()
}
}
function handleScroll() {
let scrollTo = 0
@@ -192,11 +193,12 @@ function handleScroll() {
const activedClientHeight = searchResultItemRef.value[actived.value].clientHeight
const searchScrollTop = searchResultRef.value.scrollTop
const searchClientHeight = searchResultRef.value.clientHeight
if (activedOffsetTop + activedClientHeight > searchScrollTop + searchClientHeight)
if (activedOffsetTop + activedClientHeight > searchScrollTop + searchClientHeight) {
scrollTo = activedOffsetTop + activedClientHeight - searchClientHeight
else if (activedOffsetTop <= searchScrollTop)
}
else if (activedOffsetTop <= searchScrollTop) {
scrollTo = activedOffsetTop
}
}
searchResultRef.value.scrollTo({
top: scrollTo,
@@ -204,11 +206,12 @@ function handleScroll() {
}
function pageJump(url: string) {
if (isExternalLink(url))
if (isExternalLink(url)) {
window.open(url, 'top')
else
}
else {
router.push(url)
}
}
</script>
+2 -1
View File
@@ -17,8 +17,9 @@ const props = defineProps({
const hasChildren = computed(() => {
let flag = true
if (props.item.children) {
if (props.item.children.every(item => item.meta.sidebar === false))
if (props.item.children.every(item => item.meta.sidebar === false)) {
flag = false
}
}
else {
flag = false
+2 -2
View File
@@ -22,9 +22,9 @@ const breadcrumbList = computed(() => {
title: settingsStore.dashboard.title,
})
}
if (route.meta.breadcrumbNeste)
if (route.meta.breadcrumbNeste) {
breadcrumbList.push(...route.meta.breadcrumbNeste.filter(item => item.hide === false))
}
return breadcrumbList
})
+4 -3
View File
@@ -19,11 +19,12 @@ const menuStore = useMenuStore()
watch(() => settingsStore.menu.subMenuCollapse, (val) => {
if (settingsStore.mode === 'mobile') {
if (!val)
if (!val) {
document.body.classList.add('hidden')
else
}
else {
document.body.classList.remove('hidden')
}
}
})
+2 -1
View File
@@ -13,8 +13,9 @@ import 'virtual:svg-icons-register'
import '@/assets/styles/globals.scss'
// 加载 iconify 图标(element plus)
import { downloadAndInstall } from '@/iconify-ep'
if (useSettingsStore().app.iconifyOfflineUse)
if (useSettingsStore().app.iconifyOfflineUse) {
downloadAndInstall()
}
const app = createApp(App)
app.use(ElementPlus)
+35 -40
View File
@@ -26,47 +26,37 @@ router.beforeEach(async (to, from, next) => {
settingsStore.app.enableProgress && (isLoading.value = true)
// 是否已登录
if (userStore.isLogin) {
// 是否已根据权限动态生成并挂载路由
// 是否已根据权限动态生成并注册路由
if (routeStore.isGenerate) {
// 导航栏如果不是 single 模式,则需要根据 path 定位主导航的选中状态
settingsStore.menu.menuMode !== 'single' && menuStore.setActived(to.path)
if (to.name) {
if (to.matched.length !== 0) {
// 如果已登录状态下,进入登录页会强制跳转到控制台页面
if (to.name === 'login') {
next({
name: 'dashboard',
replace: true,
})
}
else if (!settingsStore.dashboard.enable && to.name === 'dashboard') {
// 如果未开启控制台页面,则默认进入侧边栏导航第一个模块
if (menuStore.sidebarMenus.length > 0) {
next({
path: menuStore.sidebarMenusFirstDeepestPath,
replace: true,
})
}
else {
next()
}
}
else {
next()
}
}
else {
// 如果是通过 name 跳转,并且 name 对应的路由没有权限时,需要做这步处理,手动指向到 404 页面
// 如果已登录状态下,进入登录页会强制跳转到控制台页面
if (to.name === 'login') {
next({
name: 'dashboard',
replace: true,
})
}
// 如果未开启控制台,但进入的是控制台页面,则会进入侧边栏导航第一个模块
else if (!settingsStore.dashboard.enable && to.name === 'dashboard') {
if (menuStore.sidebarMenus.length > 0) {
next({
path: '/404',
path: menuStore.sidebarMenusFirstDeepestPath,
replace: true,
})
}
// 如果侧边栏导航第一个模块无法命中,则还是进入控制台页面
else {
next()
}
}
// 正常访问页面
else {
next()
}
}
else {
// 生成动态路由
switch (settingsStore.app.routeBaseOn) {
case 'frontend':
await routeStore.generateRoutesAtFront(asyncRoutes)
@@ -76,6 +66,7 @@ router.beforeEach(async (to, from, next) => {
break
case 'filesystem':
await routeStore.generateRoutesAtFilesystem(asyncRoutesByFilesystem)
// 文件系统生成的路由,需要手动生成导航数据
switch (settingsStore.menu.baseOn) {
case 'frontend':
await menuStore.generateMenusAtFront()
@@ -86,18 +77,21 @@ router.beforeEach(async (to, from, next) => {
}
break
}
// 注册并记录路由数据
// 记录的数据会在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
const removeRoutes: Function[] = []
routeStore.flatRoutes.forEach((route) => {
if (!/^(https?:|mailto:|tel:)/.test(route.path))
if (!/^(https?:|mailto:|tel:)/.test(route.path)) {
removeRoutes.push(router.addRoute(route as RouteRecordRaw))
}
})
if (settingsStore.app.routeBaseOn !== 'filesystem') {
routeStore.flatSystemRoutes.forEach((route) => {
removeRoutes.push(router.addRoute(route as RouteRecordRaw))
})
}
// 记录路由数据,在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
routeStore.setCurrentRemoveRoutes(removeRoutes)
// 动态路由生成并注册后,重新进入当前路由
next({
path: to.path,
query: to.query,
@@ -129,11 +123,12 @@ router.afterEach((to, from) => {
// 判断当前页面是否开启缓存,如果开启,则将当前页面的 name 信息存入 keep-alive 全局状态
if (to.meta.cache) {
const componentName = to.matched.at(-1)?.components?.default.name
if (componentName)
if (componentName) {
keepAliveStore.add(componentName)
else
}
else {
console.warn('该页面组件未设置组件名,会导致缓存失效,请检查')
}
}
// 判断离开页面是否开启缓存,如果开启,则根据缓存规则判断是否需要清空 keep-alive 全局状态里离开页面的 name 信息
if (from.meta.cache) {
@@ -142,22 +137,22 @@ router.afterEach((to, from) => {
// 通过 meta.cache 判断针对哪些页面进行缓存
switch (typeof from.meta.cache) {
case 'string':
if (from.meta.cache !== to.name)
if (from.meta.cache !== to.name) {
keepAliveStore.remove(componentName)
}
break
case 'object':
if (!from.meta.cache.includes(to.name as string))
if (!from.meta.cache.includes(to.name as string)) {
keepAliveStore.remove(componentName)
}
break
}
// 如果进入的是 reload 页面,则也将离开页面的缓存清空
if (to.name === 'reload')
if (to.name === 'reload') {
keepAliveStore.remove(componentName)
}
}
}
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
})
+9 -12
View File
@@ -10,7 +10,7 @@ import menu from '@/menu'
function getDeepestPath(menu: Menu.recordRaw, rootPath = '') {
let retnPath = ''
if (menu.path) {
if (menu.path !== undefined) {
if (menu.children) {
if (
menu.children.some((item) => {
@@ -75,8 +75,9 @@ function getDefaultOpenedPaths(menus: Menu.recordRaw[], rootPath = '') {
if (item.path && item.meta.defaultOpened && item.children) {
defaultOpenedPaths.push(resolveRoutePath(rootPath, item.path))
const childrenDefaultOpenedPaths = getDefaultOpenedPaths(item.children, resolveRoutePath(rootPath, item.path))
if (childrenDefaultOpenedPaths.length > 0)
if (childrenDefaultOpenedPaths.length > 0) {
defaultOpenedPaths.push(...childrenDefaultOpenedPaths)
}
}
})
return defaultOpenedPaths
@@ -133,9 +134,9 @@ const useMenuStore = defineStore(
defaultOpenedPaths() {
const settingsStore = useSettingsStore()
let defaultOpenedPaths: string[] = []
if (settingsStore.app.routeBaseOn !== 'filesystem')
if (settingsStore.app.routeBaseOn !== 'filesystem') {
defaultOpenedPaths = getDefaultOpenedPaths(this.sidebarMenus)
}
return defaultOpenedPaths
},
},
@@ -189,14 +190,10 @@ const useMenuStore = defineStore(
}
else {
// 如果是 string 类型,则认为是路由,需要查找对应的主导航索引
this.allMenus.forEach((item, index) => {
if (
item.children.some((r) => {
return data.indexOf(`${r.path}/`) === 0 || data === r.path
})
)
this.actived = index
})
const findIndex = this.allMenus.findIndex(item => item.children.some(r => data.indexOf(`${r.path}/`) === 0 || data === r.path))
if (findIndex >= 0) {
this.actived = findIndex
}
}
},
},
+6 -4
View File
@@ -47,12 +47,13 @@ function formatBackRoutes(routes: any, views = import.meta.glob('../../views/**/
route.component = () => import('@/layouts/index.vue')
break
default:
if (route.component)
if (route.component) {
route.component = views[`../../views/${route.component}`]
}
}
if (route.children)
if (route.children) {
route.children = formatBackRoutes(route.children, views)
}
return route
})
}
@@ -91,8 +92,9 @@ function flatAsyncRoutesRecursive(routes: Route.recordRaw[], breadcrumb: Route.b
// 如果 path 一样则覆盖,因为子路由的 path 可能设置为空,导致和父路由一样,直接注册会提示路由重复
if (res.some(v => v.path === item.path)) {
res.forEach((v, i) => {
if (v.path === item.path)
if (v.path === item.path) {
res[i] = item
}
})
}
else {
+3 -6
View File
@@ -40,11 +40,7 @@ const useSettingsStore = defineStore(
}
else {
// 如果为桌面设备,再根据页面宽度判断是否需要切换为移动端展示
if (width < 992)
this.mode = 'mobile'
else
this.mode = 'pc'
this.mode = width < 992 ? 'mobile' : 'pc'
}
}
else {
@@ -54,8 +50,9 @@ const useSettingsStore = defineStore(
// 切换侧边栏导航展开/收起
toggleSidebarCollapse() {
this.menu.subMenuCollapse = !this.menu.subMenuCollapse
if (this.mode === 'pc')
if (this.mode === 'pc') {
this.subMenuCollapseLastStatus = !this.subMenuCollapseLastStatus
}
},
// 设置主题颜色模式
setColorScheme(color: Required<Settings.app>['colorScheme']) {
+2 -1
View File
@@ -16,8 +16,9 @@ const useUserStore = defineStore(
isLogin: (state) => {
let retn = false
if (state.token) {
if (new Date().getTime() < parseInt(state.failure_time) * 1000)
if (new Date().getTime() < parseInt(state.failure_time) * 1000) {
retn = true
}
}
return retn
},
+4 -3
View File
@@ -5,11 +5,12 @@ export default function useAuth() {
function hasPermission(permission: string) {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
if (settingsStore.app.enablePermission)
if (settingsStore.app.enablePermission) {
return userStore.permissions.includes(permission)
else
}
else {
return true
}
}
function auth(value: string | string[]) {
+4 -3
View File
@@ -10,11 +10,12 @@ export default function useMenu() {
function switchTo(index: number | string) {
menuStore.setActived(index)
if (settingsStore.menu.switchMainMenuAndPageJump) {
if (isExternalLink(menuStore.sidebarMenusFirstDeepestPath))
if (isExternalLink(menuStore.sidebarMenusFirstDeepestPath)) {
window.open(menuStore.sidebarMenusFirstDeepestPath, '_blank')
else
}
else {
router.push(menuStore.sidebarMenusFirstDeepestPath)
}
}
}
+4 -2
View File
@@ -4,14 +4,16 @@ export default function directive(app: App) {
// 注册 v-auth 和 v-auth-all 指令
app.directive('auth', {
mounted: (el, binding) => {
if (!useAuth().auth(binding.value))
if (!useAuth().auth(binding.value)) {
el.remove()
}
},
})
app.directive('auth-all', {
mounted: (el, binding) => {
if (!useAuth().authAll(binding.value))
if (!useAuth().authAll(binding.value)) {
el.remove()
}
},
})
}
+4 -4
View File
@@ -5,11 +5,11 @@ export function isExternalLink(path: string) {
}
export function resolveRoutePath(basePath: string, routePath: string) {
if (isExternalLink(routePath))
if (isExternalLink(routePath)) {
return routePath
if (isExternalLink(basePath))
}
if (isExternalLink(basePath)) {
return basePath
}
return basePath ? path.resolve(basePath, routePath) : routePath
}
+8 -7
View File
@@ -46,12 +46,12 @@ function handleLogin() {
loading.value = true
userStore.login(loginForm.value).then(() => {
loading.value = false
if (loginForm.value.remember)
if (loginForm.value.remember) {
localStorage.setItem('login_account', loginForm.value.account)
else
}
else {
localStorage.removeItem('login_account')
}
router.push(redirect.value)
}).catch(() => {
loading.value = false
@@ -85,11 +85,12 @@ const registerRules = ref<FormRules>({
{ required: true, trigger: 'blur', message: '请再次输入密码' },
{
validator: (rule, value, callback) => {
if (value !== registerForm.value.password)
if (value !== registerForm.value.password) {
callback(new Error('两次输入的密码不一致'))
else
}
else {
callback()
}
},
},
],
+4 -3
View File
@@ -32,11 +32,12 @@ const rules = ref<FormRules>({
{ required: true, message: '请输入新密码', trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (value !== form.value.newpassword)
if (value !== form.value.newpassword) {
callback(new Error('请确认新密码'))
else
}
else {
callback()
}
},
},
],
+4 -3
View File
@@ -19,11 +19,12 @@ const form = ref({
})
const handleSuccess: UploadProps['onSuccess'] = (res) => {
if (res.error === '')
if (res.error === '') {
form.value.headimg = res.data.path
else
}
else {
ElMessage.warning(res.error)
}
}
const editPassword = () => {
router.push({
+2 -1
View File
@@ -4,8 +4,9 @@ import ViteRestart from 'vite-plugin-restart'
export default function createRestart() {
const pluginsFile: string[] = []
fs.readdirSync('vite/plugins').forEach((dirname) => {
if (fs.statSync(`vite/plugins/${dirname}`).isFile())
if (fs.statSync(`vite/plugins/${dirname}`).isFile()) {
pluginsFile.push(`vite/plugins/${dirname}`)
}
})
return ViteRestart({
restart: pluginsFile,
+2 -1
View File
@@ -4,8 +4,9 @@ import spritesmith from 'vite-plugin-spritesmith'
export default function createSpritesmith(isBuild) {
const spriteDirnames: string[] = []
fs.readdirSync('src/assets/sprites').forEach((dirname) => {
if (fs.statSync(`src/assets/sprites/${dirname}`).isDirectory())
if (fs.statSync(`src/assets/sprites/${dirname}`).isDirectory()) {
spriteDirnames.push(dirname)
}
})
const plugin: any[] = []
spriteDirnames.forEach((item) => {