mirror of
https://github.com/zclzone/vue-naive-admin.git
synced 2025-05-01 06:39:01 +08:00
feat: 添加simple、normal、full 等layout布局
This commit is contained in:
parent
3f1e92e066
commit
b4ebae4f42
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:30:17
|
- @LastEditTime: 2023/12/16 18:49:42
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -21,14 +21,14 @@
|
|||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</component>
|
</component>
|
||||||
|
|
||||||
<ThemeSetting class="fixed bottom-12 right-12" />
|
<LayoutSetting class="fixed right-12 top-1/2 z-999" />
|
||||||
</router-view>
|
</router-view>
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { zhCN, dateZhCN, darkTheme } from 'naive-ui'
|
import { zhCN, dateZhCN, darkTheme } from 'naive-ui'
|
||||||
import { ThemeSetting } from '@/components'
|
import { LayoutSetting } from '@/components'
|
||||||
import { useCssVar } from '@vueuse/core'
|
import { useCssVar } from '@vueuse/core'
|
||||||
import { kebabCase } from 'lodash-es'
|
import { kebabCase } from 'lodash-es'
|
||||||
import { useAppStore, useTabStore } from '@/store'
|
import { useAppStore, useTabStore } from '@/store'
|
||||||
@ -44,6 +44,7 @@ function getLayout(name) {
|
|||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
if (appStore.layout === 'default') appStore.setLayout('')
|
||||||
const Layout = computed(() => {
|
const Layout = computed(() => {
|
||||||
if (!route.matched?.length) return null
|
if (!route.matched?.length) return null
|
||||||
return getLayout(route.meta?.layout || appStore.layout)
|
return getLayout(route.meta?.layout || appStore.layout)
|
||||||
|
106
src/components/common/LayoutSetting.vue
Normal file
106
src/components/common/LayoutSetting.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<!--------------------------------
|
||||||
|
- @Author: Ronnie Zhang
|
||||||
|
- @LastEditor: Ronnie Zhang
|
||||||
|
- @LastEditTime: 2023/12/16 18:49:53
|
||||||
|
- @Email: zclzone@outlook.com
|
||||||
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
|
--------------------------------->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-tooltip trigger="hover" placement="left">
|
||||||
|
<template #trigger>
|
||||||
|
<i class="i-fe:settings cursor-pointer text-32 color-primary" @click="modalRef.open()" />
|
||||||
|
</template>
|
||||||
|
布局设置
|
||||||
|
</n-tooltip>
|
||||||
|
|
||||||
|
<MeModal
|
||||||
|
ref="modalRef"
|
||||||
|
title="布局设置"
|
||||||
|
:show-footer="false"
|
||||||
|
width="600px"
|
||||||
|
:modal-style="{ opacity: 0.85 }"
|
||||||
|
>
|
||||||
|
<n-space justify="space-between">
|
||||||
|
<div class="flex-col cursor-pointer justify-center" @click="appStore.setLayout('simple')">
|
||||||
|
<div class="flex">
|
||||||
|
<n-skeleton :width="20" :height="60" />
|
||||||
|
<div class="ml-4">
|
||||||
|
<n-skeleton :width="80" :height="60" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-button
|
||||||
|
class="mt-12"
|
||||||
|
size="small"
|
||||||
|
:type="appStore.layout === 'simple' ? 'primary' : ''"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
简约
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex-col cursor-pointer justify-center" @click="appStore.setLayout('normal')">
|
||||||
|
<div class="flex">
|
||||||
|
<n-skeleton :width="20" :height="60" />
|
||||||
|
<div class="ml-4">
|
||||||
|
<n-skeleton :width="80" :height="10" />
|
||||||
|
<n-skeleton class="mt-4" :width="80" :height="46" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-button
|
||||||
|
class="mt-12"
|
||||||
|
size="small"
|
||||||
|
:type="appStore.layout === 'normal' ? 'primary' : ''"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
通用
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-col cursor-pointer justify-center" @click="appStore.setLayout('full')">
|
||||||
|
<div class="flex">
|
||||||
|
<n-skeleton :width="20" :height="60" />
|
||||||
|
<div class="ml-4">
|
||||||
|
<n-skeleton :width="80" :height="6" />
|
||||||
|
<n-skeleton class="mt-4" :width="80" :height="4" />
|
||||||
|
<n-skeleton class="mt-4" :width="80" :height="42" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-button
|
||||||
|
class="mt-12"
|
||||||
|
size="small"
|
||||||
|
:type="appStore.layout === 'full' ? 'primary' : ''"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
全面
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex-col cursor-pointer justify-center" @click="appStore.setLayout('empty')">
|
||||||
|
<div class="flex">
|
||||||
|
<n-skeleton :width="104" :height="60" />
|
||||||
|
</div>
|
||||||
|
<n-button
|
||||||
|
class="mt-12"
|
||||||
|
size="small"
|
||||||
|
:type="appStore.layout === 'empty' ? 'primary' : ''"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
空白
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</n-space>
|
||||||
|
<p class="mt-16 opacity-50">
|
||||||
|
注: 此设置仅对未设置layout或者设置成跟随系统的页面有效,菜单设置的layout优先级最高
|
||||||
|
</p>
|
||||||
|
</MeModal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { MeModal } from '@/components'
|
||||||
|
import { useAppStore } from '@/store'
|
||||||
|
import { useModal } from '@/composables'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
const [modalRef] = useModal()
|
||||||
|
</script>
|
@ -1,38 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<n-popover trigger="click">
|
|
||||||
<template #trigger>
|
|
||||||
<i class="i-me-theme cursor-pointer text-40" />
|
|
||||||
</template>
|
|
||||||
<div class="h-600 w-260">
|
|
||||||
<h3 class="font-normal">主题设置</h3>
|
|
||||||
|
|
||||||
<n-divider>布局</n-divider>
|
|
||||||
<ul class="h-32 flex items-center justify-between">
|
|
||||||
<li
|
|
||||||
v-for="(item, index) in layouts"
|
|
||||||
:key="index"
|
|
||||||
class="cursor-pointer opacity-70"
|
|
||||||
@click="appStore.setLayout(item.value)"
|
|
||||||
>
|
|
||||||
{{ item.desc }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<n-divider>主题色</n-divider>
|
|
||||||
</div>
|
|
||||||
</n-popover>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useAppStore } from '@/store'
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const layouts = [
|
|
||||||
{ value: 'simple', desc: '简约' },
|
|
||||||
{ value: 'normal', desc: '通用' },
|
|
||||||
{ value: 'full', desc: '全面' },
|
|
||||||
{ value: 'empty', desc: '空白' },
|
|
||||||
]
|
|
||||||
</script>
|
|
@ -2,4 +2,4 @@ export { default as AppCard } from './AppCard.vue'
|
|||||||
export { default as TheFooter } from './TheFooter.vue'
|
export { default as TheFooter } from './TheFooter.vue'
|
||||||
export { default as AppPage } from './AppPage.vue'
|
export { default as AppPage } from './AppPage.vue'
|
||||||
export { default as CommonPage } from './CommonPage.vue'
|
export { default as CommonPage } from './CommonPage.vue'
|
||||||
export { default as ThemeSetting } from './ThemeSetting.vue'
|
export { default as LayoutSetting } from './LayoutSetting.vue'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/12 09:03:22
|
- @LastEditTime: 2023/12/16 18:50:02
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -9,7 +9,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-modal
|
<n-modal
|
||||||
v-model:show="show"
|
v-model:show="show"
|
||||||
:style="{ width: modalOptions.width, ...modalOptions.style }"
|
:style="{ width: modalOptions.width, ...modalOptions.modalStyle }"
|
||||||
:preset="undefined"
|
:preset="undefined"
|
||||||
size="huge"
|
size="huge"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
@ -78,7 +78,7 @@ const props = defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
style: {
|
modalStyle: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
@ -104,6 +104,7 @@ const modalOptions = ref({})
|
|||||||
function open(options = {}) {
|
function open(options = {}) {
|
||||||
// 将props和options合并赋值给modalOptions
|
// 将props和options合并赋值给modalOptions
|
||||||
modalOptions.value = { ...props, ...options }
|
modalOptions.value = { ...props, ...options }
|
||||||
|
|
||||||
// 将show的值设置为true
|
// 将show的值设置为true
|
||||||
show.value = true
|
show.value = true
|
||||||
}
|
}
|
||||||
|
80
src/layouts/components/BreadCrumb.vue
Normal file
80
src/layouts/components/BreadCrumb.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<!--------------------------------
|
||||||
|
- @Author: Ronnie Zhang
|
||||||
|
- @LastEditor: Ronnie Zhang
|
||||||
|
- @LastEditTime: 2023/12/16 18:50:10
|
||||||
|
- @Email: zclzone@outlook.com
|
||||||
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
|
--------------------------------->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n-breadcrumb>
|
||||||
|
<n-breadcrumb-item v-if="!breadItems?.length" :clickable="false">
|
||||||
|
{{ route.meta.title }}
|
||||||
|
</n-breadcrumb-item>
|
||||||
|
<n-breadcrumb-item
|
||||||
|
v-for="item of breadItems"
|
||||||
|
v-else
|
||||||
|
:key="item.code"
|
||||||
|
:clickable="!!item.path"
|
||||||
|
@click="handleItemClick(item)"
|
||||||
|
>
|
||||||
|
<n-dropdown :options="getDropOptions(item.children)" @select="handleDropSelect">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<i :class="item.icon" class="mr-8" />
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
</n-dropdown>
|
||||||
|
</n-breadcrumb-item>
|
||||||
|
</n-breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { usePermissionStore } from '@/store'
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
const permissionStore = usePermissionStore()
|
||||||
|
|
||||||
|
const breadItems = ref([])
|
||||||
|
watch(
|
||||||
|
() => route.name,
|
||||||
|
(v) => {
|
||||||
|
breadItems.value = findMatchs(permissionStore.permissions, v)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
function findMatchs(tree, code, parents = []) {
|
||||||
|
for (const item of tree) {
|
||||||
|
if (item.code === code) {
|
||||||
|
return [...parents, item]
|
||||||
|
}
|
||||||
|
if (item.children?.length) {
|
||||||
|
const found = findMatchs(item.children, code, [...parents, item])
|
||||||
|
if (found) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleItemClick(item) {
|
||||||
|
if (item.path && item.code !== route.name) {
|
||||||
|
router.push(item.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDropOptions(list = []) {
|
||||||
|
return list.map((child) => ({
|
||||||
|
label: child.name,
|
||||||
|
key: child.code,
|
||||||
|
icon: () => h('i', { class: child.icon }),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDropSelect(item) {
|
||||||
|
if (item.path && item.code !== route.name) {
|
||||||
|
router.push(item.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
22
src/layouts/components/MenuCollapse.vue
Normal file
22
src/layouts/components/MenuCollapse.vue
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!--------------------------------
|
||||||
|
- @Author: Ronnie Zhang
|
||||||
|
- @LastEditor: Ronnie Zhang
|
||||||
|
- @LastEditTime: 2023/12/16 18:50:18
|
||||||
|
- @Email: zclzone@outlook.com
|
||||||
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
|
--------------------------------->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="f-c-c cursor-pointer rounded-4 p-6 text-22 transition-all-300 auto-bg-hover"
|
||||||
|
@click="appStore.switchCollapsed"
|
||||||
|
>
|
||||||
|
<i :class="appStore.collapsed ? 'i-line-md-menu-unfold-left' : 'i-line-md-menu-fold-left'" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useAppStore } from '@/store'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
</script>
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:55
|
- @LastEditTime: 2023/12/16 18:50:28
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<img src="@/assets/images/logo.png" class="h-40" />
|
<img src="@/assets/images/logo.png" class="h-40" />
|
||||||
<h2
|
<h2
|
||||||
v-show="!appStore.collapsed"
|
v-show="!appStore.collapsed"
|
||||||
class="ml-10 max-w-140 flex-shrink-0 text-16 font-bold color-primary"
|
class="ml-10 max-w-140 flex-shrink-0 text-16 color-primary font-bold"
|
||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</h2>
|
</h2>
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:24:02
|
- @LastEditTime: 2023/12/16 18:50:35
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:46
|
- @LastEditTime: 2023/12/16 18:50:42
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -9,8 +9,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-dropdown :options="options" @select="handleSelect">
|
<n-dropdown :options="options" @select="handleSelect">
|
||||||
<div class="flex cursor-pointer items-center">
|
<div class="flex cursor-pointer items-center">
|
||||||
<n-avatar round :size="36" :src="userStore.avatar" class="mr-12" />
|
<n-avatar round :size="36" :src="userStore.avatar" />
|
||||||
<div v-if="userStore.userInfo" class="flex-col items-center">
|
<div v-if="userStore.userInfo" class="ml-12 flex-col flex-shrink-0 items-center">
|
||||||
<span class="text-14">{{ userStore.nickName ?? userStore.username }}</span>
|
<span class="text-14">{{ userStore.nickName ?? userStore.username }}</span>
|
||||||
<span class="text-12 opacity-50">[{{ userStore.currentRole?.name }}]</span>
|
<span class="text-12 opacity-50">[{{ userStore.currentRole?.name }}]</span>
|
||||||
</div>
|
</div>
|
@ -1 +1,7 @@
|
|||||||
export { default as RoleSelect } from './RoleSelect.vue'
|
export { default as RoleSelect } from './RoleSelect.vue'
|
||||||
|
export { default as UserAvatar } from './UserAvatar.vue'
|
||||||
|
export { default as MenuCollapse } from './MenuCollapse.vue'
|
||||||
|
export { default as BreadCrumb } from './BreadCrumb.vue'
|
||||||
|
export { default as AppTab } from './tab/index.vue'
|
||||||
|
export { default as SideLogo } from './SideLogo.vue'
|
||||||
|
export { default as SideMenu } from './SideMenu.vue'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:32
|
- @LastEditTime: 2023/12/16 18:50:48
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:38
|
- @LastEditTime: 2023/12/16 18:50:54
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
@ -1,83 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:46
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-dropdown :options="options" @select="handleSelect">
|
|
||||||
<div class="flex cursor-pointer items-center">
|
|
||||||
<n-avatar round :size="36" :src="userStore.avatar" class="mr-12" />
|
|
||||||
<div v-if="userStore.userInfo" class="flex-col items-center">
|
|
||||||
<span class="text-14">{{ userStore.nickName ?? userStore.username }}</span>
|
|
||||||
<span class="text-12 opacity-50">[{{ userStore.currentRole?.name }}]</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</n-dropdown>
|
|
||||||
|
|
||||||
<RoleSelect ref="roleSelectRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useUserStore, useAuthStore, usePermissionStore } from '@/store'
|
|
||||||
import { RoleSelect } from '@/layouts/components'
|
|
||||||
import { initUserAndPermissions } from '@/router'
|
|
||||||
import api from '@/api'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const authStore = useAuthStore()
|
|
||||||
const permissionStore = usePermissionStore()
|
|
||||||
|
|
||||||
const options = reactive([
|
|
||||||
{
|
|
||||||
label: '个人资料',
|
|
||||||
key: 'profile',
|
|
||||||
icon: () => h('i', { class: 'i-material-symbols:person-outline text-14' }),
|
|
||||||
show: computed(() => permissionStore.accessRoutes?.some((item) => item.path === '/profile')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '切换角色',
|
|
||||||
key: 'toggleRole',
|
|
||||||
icon: () => h('i', { class: 'i-basil:exchange-solid text-14' }),
|
|
||||||
show: computed(() => userStore.roles.length > 1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '退出登录',
|
|
||||||
key: 'logout',
|
|
||||||
icon: () => h('i', { class: 'i-mdi:exit-to-app text-14' }),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const roleSelectRef = ref(null)
|
|
||||||
function handleSelect(key) {
|
|
||||||
switch (key) {
|
|
||||||
case 'profile':
|
|
||||||
router.push('/profile')
|
|
||||||
break
|
|
||||||
case 'toggleRole':
|
|
||||||
roleSelectRef.value?.open({
|
|
||||||
onOk() {
|
|
||||||
initUserAndPermissions().then(() => {
|
|
||||||
router.replace('/')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'logout':
|
|
||||||
$dialog.confirm({
|
|
||||||
title: '提示',
|
|
||||||
type: 'info',
|
|
||||||
content: '确认退出?',
|
|
||||||
async confirm() {
|
|
||||||
await api.logout()
|
|
||||||
authStore.logout()
|
|
||||||
$message.success('已退出登录')
|
|
||||||
},
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||||||
export { default as UserAvatar } from './UserAvatar.vue'
|
|
||||||
export { default as AppTab } from './tab/index.vue'
|
|
@ -1,125 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:32
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-dropdown
|
|
||||||
:show="show"
|
|
||||||
:options="options"
|
|
||||||
:x="x"
|
|
||||||
:y="y"
|
|
||||||
placement="bottom-start"
|
|
||||||
@clickoutside="handleHideDropdown"
|
|
||||||
@select="handleSelect"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useTabStore } from '@/store'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
show: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
currentPath: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
|
|
||||||
const tabStore = useTabStore()
|
|
||||||
|
|
||||||
const options = computed(() => [
|
|
||||||
{
|
|
||||||
label: '重新加载',
|
|
||||||
key: 'reload',
|
|
||||||
disabled: props.currentPath !== tabStore.activeTab,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:refresh text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭',
|
|
||||||
key: 'close',
|
|
||||||
disabled: tabStore.tabs.length <= 1,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:close text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭其他',
|
|
||||||
key: 'close-other',
|
|
||||||
disabled: tabStore.tabs.length <= 1,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-horizontal text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭左侧',
|
|
||||||
key: 'close-left',
|
|
||||||
disabled: tabStore.tabs.length <= 1 || props.currentPath === tabStore.tabs[0].path,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-left text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭右侧',
|
|
||||||
key: 'close-right',
|
|
||||||
disabled:
|
|
||||||
tabStore.tabs.length <= 1 ||
|
|
||||||
props.currentPath === tabStore.tabs[tabStore.tabs.length - 1].path,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-right text-14' }),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
const actionMap = new Map([
|
|
||||||
[
|
|
||||||
'reload',
|
|
||||||
() => {
|
|
||||||
tabStore.reloadTab(route.fullPath, route.meta?.keepAlive)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close',
|
|
||||||
() => {
|
|
||||||
tabStore.removeTab(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-other',
|
|
||||||
() => {
|
|
||||||
tabStore.removeOther(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-left',
|
|
||||||
() => {
|
|
||||||
tabStore.removeLeft(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-right',
|
|
||||||
() => {
|
|
||||||
tabStore.removeRight(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
])
|
|
||||||
|
|
||||||
function handleHideDropdown() {
|
|
||||||
emit('update:show', false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSelect(key) {
|
|
||||||
const actionFn = actionMap.get(key)
|
|
||||||
actionFn && actionFn()
|
|
||||||
handleHideDropdown()
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,25 +1,18 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:23
|
- @LastEditTime: 2023/12/16 18:51:10
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppCard class="flex items-center px-12" border-b="1px solid light_border dark:dark_border">
|
<AppCard class="flex items-center px-12" border-b="1px solid light_border dark:dark_border">
|
||||||
<div
|
<MenuCollapse />
|
||||||
class="f-c-c cursor-pointer rounded-4 p-6 text-22 transition-all-300 auto-bg-hover"
|
|
||||||
@click="appStore.switchCollapsed"
|
|
||||||
>
|
|
||||||
<i :class="appStore.collapsed ? 'i-line-md-menu-unfold-left' : 'i-line-md-menu-fold-left'" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AppTab class="w-0 flex-1 px-12" />
|
<BreadCrumb />
|
||||||
|
|
||||||
<span class="mx-6 opacity-20">|</span>
|
<div class="ml-auto flex flex-shrink-0 items-center px-12 text-18">
|
||||||
|
|
||||||
<div class="flex flex-shrink-0 items-center px-12 text-18">
|
|
||||||
<i
|
<i
|
||||||
class="mr-16 cursor-pointer"
|
class="mr-16 cursor-pointer"
|
||||||
:class="isDark ? 'i-fe:moon' : 'i-fe:sun'"
|
:class="isDark ? 'i-fe:moon' : 'i-fe:sun'"
|
||||||
@ -45,7 +38,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { AppTab, UserAvatar } from './components'
|
import { MenuCollapse, UserAvatar, BreadCrumb } from '@/layouts/components'
|
||||||
import { useAppStore } from '@/store'
|
import { useAppStore } from '@/store'
|
||||||
import { useDark, useToggle, useFullscreen } from '@vueuse/core'
|
import { useDark, useToggle, useFullscreen } from '@vueuse/core'
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/13 20:54:55
|
- @LastEditTime: 2023/12/16 18:51:02
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
<article class="w-0 flex-col flex-1">
|
<article class="w-0 flex-col flex-1">
|
||||||
<AppHeader class="h-60 flex-shrink-0" />
|
<AppHeader class="h-60 flex-shrink-0" />
|
||||||
|
<div class="p-12" border-b="1px solid light_border dark:dark_border">
|
||||||
|
<AppTab class="flex-shrink-0" />
|
||||||
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
@ -25,6 +28,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useAppStore } from '@/store'
|
import { useAppStore } from '@/store'
|
||||||
|
import { AppTab } from '@/layouts/components'
|
||||||
import SideBar from './sidebar/index.vue'
|
import SideBar from './sidebar/index.vue'
|
||||||
import AppHeader from './header/index.vue'
|
import AppHeader from './header/index.vue'
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:24:09
|
- @LastEditTime: 2023/12/16 18:51:25
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SideLogo from './components/SideLogo.vue'
|
|
||||||
import SideMenu from './components/SideMenu.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<SideLogo border-b="1px solid light_border dark:dark_border" />
|
<SideLogo border-b="1px solid light_border dark:dark_border" />
|
||||||
<SideMenu class="cus-scroll-y mt-4 h-0 flex-1" />
|
<SideMenu class="cus-scroll-y mt-4 h-0 flex-1" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { SideLogo, SideMenu } from '@/layouts/components'
|
||||||
|
</script>
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
export { default as UserAvatar } from './UserAvatar.vue'
|
|
||||||
export { default as AppTab } from './tab/index.vue'
|
|
@ -1,101 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:38
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<n-tabs
|
|
||||||
:value="tabStore.activeTab"
|
|
||||||
:closable="tabStore.tabs.length > 1"
|
|
||||||
:style="`--selected-bg: ${appStore.isDark ? '#1b2429' : '#eaf0f1'}`"
|
|
||||||
type="card"
|
|
||||||
@close="(path) => tabStore.removeTab(path)"
|
|
||||||
>
|
|
||||||
<n-tab
|
|
||||||
v-for="item in tabStore.tabs"
|
|
||||||
:key="item.path"
|
|
||||||
:name="item.path"
|
|
||||||
@click="handleItemClick(item.path)"
|
|
||||||
@contextmenu.prevent="handleContextMenu($event, item)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</n-tab>
|
|
||||||
</n-tabs>
|
|
||||||
|
|
||||||
<ContextMenu
|
|
||||||
v-if="contextMenuOption.show"
|
|
||||||
v-model:show="contextMenuOption.show"
|
|
||||||
:current-path="contextMenuOption.currentPath"
|
|
||||||
:x="contextMenuOption.x"
|
|
||||||
:y="contextMenuOption.y"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import ContextMenu from './ContextMenu.vue'
|
|
||||||
import { useTabStore, useAppStore } from '@/store'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const tabStore = useTabStore()
|
|
||||||
|
|
||||||
const contextMenuOption = reactive({
|
|
||||||
show: false,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
currentPath: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleItemClick = (path) => {
|
|
||||||
tabStore.setActiveTab(path)
|
|
||||||
router.push(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
function showContextMenu() {
|
|
||||||
contextMenuOption.show = true
|
|
||||||
}
|
|
||||||
function hideContextMenu() {
|
|
||||||
contextMenuOption.show = false
|
|
||||||
}
|
|
||||||
function setContextMenu(x, y, currentPath) {
|
|
||||||
Object.assign(contextMenuOption, { x, y, currentPath })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右击菜单
|
|
||||||
async function handleContextMenu(e, tagItem) {
|
|
||||||
const { clientX, clientY } = e
|
|
||||||
hideContextMenu()
|
|
||||||
setContextMenu(clientX, clientY, tagItem.path)
|
|
||||||
await nextTick()
|
|
||||||
showContextMenu()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
:deep(.n-tabs) {
|
|
||||||
.n-tabs-tab {
|
|
||||||
padding-left: 16px;
|
|
||||||
height: 36px;
|
|
||||||
background: transparent !important;
|
|
||||||
border-radius: 4px !important;
|
|
||||||
margin-right: 4px;
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.n-tabs-tab--active {
|
|
||||||
border: 1px solid var(--primary-color) !important;
|
|
||||||
background-color: var(--selected-bg) !important;
|
|
||||||
}
|
|
||||||
.n-tabs-pad,
|
|
||||||
.n-tabs-tab-pad,
|
|
||||||
.n-tabs-scroll-padding {
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,19 +1,14 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:23:23
|
- @LastEditTime: 2023/12/16 18:52:48
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppCard class="flex items-center px-12" border-b="1px solid light_border dark:dark_border">
|
<AppCard class="flex items-center px-12" border-b="1px solid light_border dark:dark_border">
|
||||||
<div
|
<MenuCollapse />
|
||||||
class="f-c-c cursor-pointer rounded-4 p-6 text-22 transition-all-300 auto-bg-hover"
|
|
||||||
@click="appStore.switchCollapsed"
|
|
||||||
>
|
|
||||||
<i :class="appStore.collapsed ? 'i-line-md-menu-unfold-left' : 'i-line-md-menu-fold-left'" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AppTab class="w-0 flex-1 px-12" />
|
<AppTab class="w-0 flex-1 px-12" />
|
||||||
|
|
||||||
@ -45,9 +40,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { AppTab, UserAvatar } from './components'
|
import { UserAvatar, MenuCollapse, AppTab } from '@/layouts/components'
|
||||||
import { useAppStore } from '@/store'
|
|
||||||
import { useDark, useToggle, useFullscreen } from '@vueuse/core'
|
import { useDark, useToggle, useFullscreen } from '@vueuse/core'
|
||||||
|
import { useAppStore } from '@/store'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:55
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<router-link class="h-60 f-c-c" to="/">
|
|
||||||
<img src="@/assets/images/logo.png" class="h-40" />
|
|
||||||
<h2
|
|
||||||
v-show="!appStore.collapsed"
|
|
||||||
class="ml-10 max-w-140 flex-shrink-0 text-16 font-bold color-primary"
|
|
||||||
>
|
|
||||||
{{ title }}
|
|
||||||
</h2>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useAppStore } from '@/store'
|
|
||||||
const title = import.meta.env.VITE_TITLE
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
</script>
|
|
@ -1,62 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:24:02
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-menu
|
|
||||||
ref="menu"
|
|
||||||
class="side-menu"
|
|
||||||
accordion
|
|
||||||
:indent="18"
|
|
||||||
:collapsed-icon-size="22"
|
|
||||||
:collapsed-width="64"
|
|
||||||
:collapsed="appStore.collapsed"
|
|
||||||
:options="permissionStore.menus"
|
|
||||||
:value="activeKey"
|
|
||||||
@update:value="handleMenuSelect"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useAppStore, usePermissionStore } from '@/store'
|
|
||||||
import { isExternal } from '@/utils'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const route = useRoute()
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const permissionStore = usePermissionStore()
|
|
||||||
|
|
||||||
const activeKey = computed(() => route.meta?.parentKey || route.name)
|
|
||||||
|
|
||||||
const menu = ref(null)
|
|
||||||
watch(route, async () => {
|
|
||||||
await nextTick()
|
|
||||||
menu.value?.showOption()
|
|
||||||
})
|
|
||||||
|
|
||||||
function handleMenuSelect(key, item) {
|
|
||||||
if (isExternal(item.path)) {
|
|
||||||
window.open(item.path)
|
|
||||||
} else {
|
|
||||||
router.push(item.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.side-menu:not(.n-menu--collapsed) {
|
|
||||||
.n-menu-item-content {
|
|
||||||
&::before {
|
|
||||||
left: 8px;
|
|
||||||
right: 8px;
|
|
||||||
}
|
|
||||||
&.n-menu-item-content--selected::before {
|
|
||||||
border-left: 4px solid var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:24:09
|
- @LastEditTime: 2023/12/16 18:46:06
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -12,6 +12,5 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SideLogo from './components/SideLogo.vue'
|
import { SideLogo, SideMenu } from '@/layouts/components'
|
||||||
import SideMenu from './components/SideMenu.vue'
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:46
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-dropdown :options="options" @select="handleSelect">
|
|
||||||
<div class="flex cursor-pointer items-center">
|
|
||||||
<n-avatar round :size="36" :src="userStore.avatar" class="mr-12" />
|
|
||||||
<div v-if="userStore.userInfo" class="flex-col items-center">
|
|
||||||
<span class="text-14">{{ userStore.nickName ?? userStore.username }}</span>
|
|
||||||
<span class="text-12 opacity-50">[{{ userStore.currentRole?.name }}]</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</n-dropdown>
|
|
||||||
|
|
||||||
<RoleSelect ref="roleSelectRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useUserStore, useAuthStore, usePermissionStore } from '@/store'
|
|
||||||
import { RoleSelect } from '@/layouts/components'
|
|
||||||
import { initUserAndPermissions } from '@/router'
|
|
||||||
import api from '@/api'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const authStore = useAuthStore()
|
|
||||||
const permissionStore = usePermissionStore()
|
|
||||||
|
|
||||||
const options = reactive([
|
|
||||||
{
|
|
||||||
label: '个人资料',
|
|
||||||
key: 'profile',
|
|
||||||
icon: () => h('i', { class: 'i-material-symbols:person-outline text-14' }),
|
|
||||||
show: computed(() => permissionStore.accessRoutes?.some((item) => item.path === '/profile')),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '切换角色',
|
|
||||||
key: 'toggleRole',
|
|
||||||
icon: () => h('i', { class: 'i-basil:exchange-solid text-14' }),
|
|
||||||
show: computed(() => userStore.roles.length > 1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '退出登录',
|
|
||||||
key: 'logout',
|
|
||||||
icon: () => h('i', { class: 'i-mdi:exit-to-app text-14' }),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const roleSelectRef = ref(null)
|
|
||||||
function handleSelect(key) {
|
|
||||||
switch (key) {
|
|
||||||
case 'profile':
|
|
||||||
router.push('/profile')
|
|
||||||
break
|
|
||||||
case 'toggleRole':
|
|
||||||
roleSelectRef.value?.open({
|
|
||||||
onOk() {
|
|
||||||
initUserAndPermissions().then(() => {
|
|
||||||
router.replace('/')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'logout':
|
|
||||||
$dialog.confirm({
|
|
||||||
title: '提示',
|
|
||||||
type: 'info',
|
|
||||||
content: '确认退出?',
|
|
||||||
async confirm() {
|
|
||||||
await api.logout()
|
|
||||||
authStore.logout()
|
|
||||||
$message.success('已退出登录')
|
|
||||||
},
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||||||
export { default as UserAvatar } from './UserAvatar.vue'
|
|
||||||
export { default as AppTab } from './tab/index.vue'
|
|
@ -1,125 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:32
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-dropdown
|
|
||||||
:show="show"
|
|
||||||
:options="options"
|
|
||||||
:x="x"
|
|
||||||
:y="y"
|
|
||||||
placement="bottom-start"
|
|
||||||
@clickoutside="handleHideDropdown"
|
|
||||||
@select="handleSelect"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useTabStore } from '@/store'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
show: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
currentPath: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
|
|
||||||
const tabStore = useTabStore()
|
|
||||||
|
|
||||||
const options = computed(() => [
|
|
||||||
{
|
|
||||||
label: '重新加载',
|
|
||||||
key: 'reload',
|
|
||||||
disabled: props.currentPath !== tabStore.activeTab,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:refresh text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭',
|
|
||||||
key: 'close',
|
|
||||||
disabled: tabStore.tabs.length <= 1,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:close text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭其他',
|
|
||||||
key: 'close-other',
|
|
||||||
disabled: tabStore.tabs.length <= 1,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-horizontal text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭左侧',
|
|
||||||
key: 'close-left',
|
|
||||||
disabled: tabStore.tabs.length <= 1 || props.currentPath === tabStore.tabs[0].path,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-left text-14' }),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '关闭右侧',
|
|
||||||
key: 'close-right',
|
|
||||||
disabled:
|
|
||||||
tabStore.tabs.length <= 1 ||
|
|
||||||
props.currentPath === tabStore.tabs[tabStore.tabs.length - 1].path,
|
|
||||||
icon: () => h('i', { class: 'i-mdi:arrow-expand-right text-14' }),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
const actionMap = new Map([
|
|
||||||
[
|
|
||||||
'reload',
|
|
||||||
() => {
|
|
||||||
tabStore.reloadTab(route.fullPath, route.meta?.keepAlive)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close',
|
|
||||||
() => {
|
|
||||||
tabStore.removeTab(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-other',
|
|
||||||
() => {
|
|
||||||
tabStore.removeOther(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-left',
|
|
||||||
() => {
|
|
||||||
tabStore.removeLeft(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'close-right',
|
|
||||||
() => {
|
|
||||||
tabStore.removeRight(props.currentPath)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
])
|
|
||||||
|
|
||||||
function handleHideDropdown() {
|
|
||||||
emit('update:show', false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSelect(key) {
|
|
||||||
const actionFn = actionMap.get(key)
|
|
||||||
actionFn && actionFn()
|
|
||||||
handleHideDropdown()
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,101 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:38
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<n-tabs
|
|
||||||
:value="tabStore.activeTab"
|
|
||||||
:closable="tabStore.tabs.length > 1"
|
|
||||||
:style="`--selected-bg: ${appStore.isDark ? '#1b2429' : '#eaf0f1'}`"
|
|
||||||
type="card"
|
|
||||||
@close="(path) => tabStore.removeTab(path)"
|
|
||||||
>
|
|
||||||
<n-tab
|
|
||||||
v-for="item in tabStore.tabs"
|
|
||||||
:key="item.path"
|
|
||||||
:name="item.path"
|
|
||||||
@click="handleItemClick(item.path)"
|
|
||||||
@contextmenu.prevent="handleContextMenu($event, item)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</n-tab>
|
|
||||||
</n-tabs>
|
|
||||||
|
|
||||||
<ContextMenu
|
|
||||||
v-if="contextMenuOption.show"
|
|
||||||
v-model:show="contextMenuOption.show"
|
|
||||||
:current-path="contextMenuOption.currentPath"
|
|
||||||
:x="contextMenuOption.x"
|
|
||||||
:y="contextMenuOption.y"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import ContextMenu from './ContextMenu.vue'
|
|
||||||
import { useTabStore, useAppStore } from '@/store'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const tabStore = useTabStore()
|
|
||||||
|
|
||||||
const contextMenuOption = reactive({
|
|
||||||
show: false,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
currentPath: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleItemClick = (path) => {
|
|
||||||
tabStore.setActiveTab(path)
|
|
||||||
router.push(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
function showContextMenu() {
|
|
||||||
contextMenuOption.show = true
|
|
||||||
}
|
|
||||||
function hideContextMenu() {
|
|
||||||
contextMenuOption.show = false
|
|
||||||
}
|
|
||||||
function setContextMenu(x, y, currentPath) {
|
|
||||||
Object.assign(contextMenuOption, { x, y, currentPath })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右击菜单
|
|
||||||
async function handleContextMenu(e, tagItem) {
|
|
||||||
const { clientX, clientY } = e
|
|
||||||
hideContextMenu()
|
|
||||||
setContextMenu(clientX, clientY, tagItem.path)
|
|
||||||
await nextTick()
|
|
||||||
showContextMenu()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
:deep(.n-tabs) {
|
|
||||||
.n-tabs-tab {
|
|
||||||
padding-left: 16px;
|
|
||||||
height: 36px;
|
|
||||||
background: transparent !important;
|
|
||||||
border-radius: 4px !important;
|
|
||||||
margin-right: 4px;
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid var(--primary-color) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.n-tabs-tab--active {
|
|
||||||
border: 1px solid var(--primary-color) !important;
|
|
||||||
background-color: var(--selected-bg) !important;
|
|
||||||
}
|
|
||||||
.n-tabs-pad,
|
|
||||||
.n-tabs-tab-pad,
|
|
||||||
.n-tabs-scroll-padding {
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,64 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:23
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<AppCard class="flex items-center px-12" border-b="1px solid light_border dark:dark_border">
|
|
||||||
<div
|
|
||||||
class="f-c-c cursor-pointer rounded-4 p-6 text-22 transition-all-300 auto-bg-hover"
|
|
||||||
@click="appStore.switchCollapsed"
|
|
||||||
>
|
|
||||||
<i :class="appStore.collapsed ? 'i-line-md-menu-unfold-left' : 'i-line-md-menu-fold-left'" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AppTab class="w-0 flex-1 px-12" />
|
|
||||||
|
|
||||||
<span class="mx-6 opacity-20">|</span>
|
|
||||||
|
|
||||||
<div class="flex flex-shrink-0 items-center px-12 text-18">
|
|
||||||
<i
|
|
||||||
class="mr-16 cursor-pointer"
|
|
||||||
:class="isDark ? 'i-fe:moon' : 'i-fe:sun'"
|
|
||||||
@click="toggleDark"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
class="mr-16 cursor-pointer"
|
|
||||||
:class="isFullscreen ? 'i-fe:minimize' : 'i-fe:maximize'"
|
|
||||||
@click="toggle"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<i
|
|
||||||
class="i-fe:github mr-16 cursor-pointer"
|
|
||||||
@click="handleLinkClick('https://github.com/zclzone/vue-naive-admin/tree/2.x-beta')"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
class="i-me:gitee mr-16 cursor-pointer"
|
|
||||||
@click="handleLinkClick('https://gitee.com/isme-admin/vue-naive-admin/tree/2.x-beta')"
|
|
||||||
/>
|
|
||||||
<UserAvatar />
|
|
||||||
</div>
|
|
||||||
</AppCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { AppTab, UserAvatar } from './components'
|
|
||||||
import { useAppStore } from '@/store'
|
|
||||||
import { useDark, useToggle, useFullscreen } from '@vueuse/core'
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const isDark = useDark()
|
|
||||||
const toggleDark = () => {
|
|
||||||
appStore.toggleDark()
|
|
||||||
useToggle(isDark)()
|
|
||||||
}
|
|
||||||
|
|
||||||
const { isFullscreen, toggle } = useFullscreen()
|
|
||||||
|
|
||||||
function handleLinkClick(link) {
|
|
||||||
window.open(link)
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/13 20:54:55
|
- @LastEditTime: 2023/12/16 18:51:47
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -17,7 +17,6 @@
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<article class="w-0 flex-col flex-1">
|
<article class="w-0 flex-col flex-1">
|
||||||
<AppHeader class="h-60 flex-shrink-0" />
|
|
||||||
<slot />
|
<slot />
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
@ -26,7 +25,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useAppStore } from '@/store'
|
import { useAppStore } from '@/store'
|
||||||
import SideBar from './sidebar/index.vue'
|
import SideBar from './sidebar/index.vue'
|
||||||
import AppHeader from './header/index.vue'
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:23:55
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<router-link class="h-60 f-c-c" to="/">
|
|
||||||
<img src="@/assets/images/logo.png" class="h-40" />
|
|
||||||
<h2
|
|
||||||
v-show="!appStore.collapsed"
|
|
||||||
class="ml-10 max-w-140 flex-shrink-0 text-16 font-bold color-primary"
|
|
||||||
>
|
|
||||||
{{ title }}
|
|
||||||
</h2>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useAppStore } from '@/store'
|
|
||||||
const title = import.meta.env.VITE_TITLE
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
</script>
|
|
@ -1,62 +0,0 @@
|
|||||||
<!--------------------------------
|
|
||||||
- @Author: Ronnie Zhang
|
|
||||||
- @LastEditor: Ronnie Zhang
|
|
||||||
- @LastEditTime: 2023/12/05 21:24:02
|
|
||||||
- @Email: zclzone@outlook.com
|
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
|
||||||
--------------------------------->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-menu
|
|
||||||
ref="menu"
|
|
||||||
class="side-menu"
|
|
||||||
accordion
|
|
||||||
:indent="18"
|
|
||||||
:collapsed-icon-size="22"
|
|
||||||
:collapsed-width="64"
|
|
||||||
:collapsed="appStore.collapsed"
|
|
||||||
:options="permissionStore.menus"
|
|
||||||
:value="activeKey"
|
|
||||||
@update:value="handleMenuSelect"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useAppStore, usePermissionStore } from '@/store'
|
|
||||||
import { isExternal } from '@/utils'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const route = useRoute()
|
|
||||||
const appStore = useAppStore()
|
|
||||||
const permissionStore = usePermissionStore()
|
|
||||||
|
|
||||||
const activeKey = computed(() => route.meta?.parentKey || route.name)
|
|
||||||
|
|
||||||
const menu = ref(null)
|
|
||||||
watch(route, async () => {
|
|
||||||
await nextTick()
|
|
||||||
menu.value?.showOption()
|
|
||||||
})
|
|
||||||
|
|
||||||
function handleMenuSelect(key, item) {
|
|
||||||
if (isExternal(item.path)) {
|
|
||||||
window.open(item.path)
|
|
||||||
} else {
|
|
||||||
router.push(item.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.side-menu:not(.n-menu--collapsed) {
|
|
||||||
.n-menu-item-content {
|
|
||||||
&::before {
|
|
||||||
left: 8px;
|
|
||||||
right: 8px;
|
|
||||||
}
|
|
||||||
&.n-menu-item-content--selected::before {
|
|
||||||
border-left: 4px solid var(--primary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -6,12 +6,18 @@
|
|||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SideLogo from './components/SideLogo.vue'
|
|
||||||
import SideMenu from './components/SideMenu.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<SideLogo border-b="1px solid light_border dark:dark_border" />
|
<SideLogo border-b="1px solid light_border dark:dark_border" />
|
||||||
<SideMenu class="cus-scroll-y mt-4 h-0 flex-1" />
|
<SideMenu class="cus-scroll-y mt-4 h-0 flex-1" />
|
||||||
|
<div class="my-12 flex items-center justify-around px-12">
|
||||||
|
<UserAvatar v-if="!appStore.collapsed" />
|
||||||
|
<MenuCollapse />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { UserAvatar, MenuCollapse, SideLogo, SideMenu } from '@/layouts/components'
|
||||||
|
import { useAppStore } from '@/store'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
</script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!--------------------------------
|
<!--------------------------------
|
||||||
- @Author: Ronnie Zhang
|
- @Author: Ronnie Zhang
|
||||||
- @LastEditor: Ronnie Zhang
|
- @LastEditor: Ronnie Zhang
|
||||||
- @LastEditTime: 2023/12/05 21:27:43
|
- @LastEditTime: 2023/12/16 18:51:56
|
||||||
- @Email: zclzone@outlook.com
|
- @Email: zclzone@outlook.com
|
||||||
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
|
||||||
--------------------------------->
|
--------------------------------->
|
||||||
@ -32,6 +32,10 @@ function openModal1() {
|
|||||||
okText: '再弹个窗',
|
okText: '再弹个窗',
|
||||||
cancelText: '关闭',
|
cancelText: '关闭',
|
||||||
async onOk() {
|
async onOk() {
|
||||||
|
if (!text.value) {
|
||||||
|
$message.warning('请输入内容')
|
||||||
|
return false // 阻止弹窗关闭
|
||||||
|
}
|
||||||
okLoading1.value = true
|
okLoading1.value = true
|
||||||
$message.loading('正在提交...', { key: 'modal1' })
|
$message.loading('正在提交...', { key: 'modal1' })
|
||||||
await sleep(1000)
|
await sleep(1000)
|
||||||
@ -48,16 +52,10 @@ function openModal1() {
|
|||||||
|
|
||||||
const [$modal2, okLoading2] = useModal()
|
const [$modal2, okLoading2] = useModal()
|
||||||
function openModal2() {
|
function openModal2() {
|
||||||
// modal的options都是可变的
|
|
||||||
if ($modal1.value) {
|
|
||||||
$modal1.value.options.style.top = '-100px'
|
|
||||||
$modal1.value.options.title = '我走了'
|
|
||||||
}
|
|
||||||
|
|
||||||
$modal2.value?.open({
|
$modal2.value?.open({
|
||||||
cancelText: '关闭当前',
|
cancelText: '关闭当前',
|
||||||
okText: '关闭所有弹窗',
|
okText: '关闭所有弹窗',
|
||||||
style: { width: '320px', padding: '12px', top: '100px' },
|
modalStyle: { width: '320px', padding: '12px', top: '100px' },
|
||||||
async onOk() {
|
async onOk() {
|
||||||
okLoading2.value = true
|
okLoading2.value = true
|
||||||
$message.loading('正在关闭...', { key: 'modal2' })
|
$message.loading('正在关闭...', { key: 'modal2' })
|
||||||
@ -68,12 +66,6 @@ function openModal2() {
|
|||||||
$modal1.value?.close()
|
$modal1.value?.close()
|
||||||
$message.success('已关闭', { key: 'modal2' })
|
$message.success('已关闭', { key: 'modal2' })
|
||||||
},
|
},
|
||||||
onCancel() {
|
|
||||||
if ($modal1.value) {
|
|
||||||
$modal1.value.options.style.top = '0'
|
|
||||||
$modal1.value.options.title = '我又回来了'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user