1
0
mirror of https://github.com/zclzone/vue-naive-admin.git synced 2025-05-01 06:39:01 +08:00

Merge branch '2.x-beta-theme' into 2.x-beta

This commit is contained in:
zclzone 2023-12-16 18:57:51 +08:00
commit 1a840728a5
29 changed files with 484 additions and 95 deletions

View File

@ -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
---------------------------------> --------------------------------->
@ -12,7 +12,7 @@
:locale="zhCN" :locale="zhCN"
:date-locale="dateZhCN" :date-locale="dateZhCN"
:theme="appStore.isDark ? darkTheme : undefined" :theme="appStore.isDark ? darkTheme : undefined"
:theme-overrides="settings.naiveThemeOverrides" :theme-overrides="appStore.naiveThemeOverrides"
> >
<router-view v-if="Layout" v-slot="{ Component, route: curRoute }"> <router-view v-if="Layout" v-slot="{ Component, route: curRoute }">
<component :is="Layout"> <component :is="Layout">
@ -20,16 +20,18 @@
<component :is="Component" v-if="!tabStore.reloading" :key="curRoute.fullPath" /> <component :is="Component" v-if="!tabStore.reloading" :key="curRoute.fullPath" />
</KeepAlive> </KeepAlive>
</component> </component>
<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 { 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'
import settings from '@/settings'
const layouts = new Map() const layouts = new Map()
function getLayout(name) { function getLayout(name) {
@ -42,13 +44,14 @@ 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 || settings.defaultLayout) return getLayout(route.meta?.layout || appStore.layout)
}) })
function setupCssVar() { function setupCssVar() {
const common = settings.naiveThemeOverrides?.common || {} const common = appStore.naiveThemeOverrides?.common || {}
for (const key in common) { for (const key in common) {
useCssVar(`--${kebabCase(key)}`, document.documentElement).value = common[key] || '' useCssVar(`--${kebabCase(key)}`, document.documentElement).value = common[key] || ''
if (key === 'primaryColor') window.localStorage.setItem('__THEME_COLOR__', common[key] || '') if (key === 'primaryColor') window.localStorage.setItem('__THEME_COLOR__', common[key] || '')

View File

@ -0,0 +1,21 @@
<svg
t="1702480351321"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="11122"
width="200"
height="200"
>
<path
d="M509.9008 519.8336m-450.816 0a450.816 450.816 0 1 0 901.632 0 450.816 450.816 0 1 0-901.632 0Z"
fill="#C65EDB"
p-id="11123"
></path>
<path
d="M798.1568 512.512l-113.3056-78.3872a47.4112 47.4112 0 0 1-20.4288-39.0656l0.3584-137.7792c0.1024-39.2704-44.9024-61.5936-76.0832-37.7856l-109.568 83.5072a47.2832 47.2832 0 0 1-43.4688 7.3216l-130.9184-42.9056c-37.3248-12.2368-72.448 23.6544-59.4432 60.7232l45.568 129.9968A47.3088 47.3088 0 0 1 284.416 501.76l-81.2544 111.2576c-23.1424 31.6928 0.1024 76.2368 39.3728 75.3152l137.728-3.1744a47.3344 47.3344 0 0 1 39.4752 19.6096l80.6912 111.6672c22.9888 31.8464 72.4992 23.4496 83.7632-14.1824l37.9392-126.6176 126.5664 118.272a27.648 27.648 0 0 0 17.7664 7.4752c7.8848 0.3584 15.872-2.6112 21.7088-8.8064a27.91936 27.91936 0 0 0-1.3312-39.4752l-124.8768-116.6848 123.8016-39.8848c37.376-11.9808 44.6976-61.6448 12.3904-84.0192z m-389.6832-6.5024l-42.8032 77.824a27.86816 27.86816 0 0 1-37.9392 11.008 27.93984 27.93984 0 0 1-11.008-37.9392l40.0384-72.7552-19.0464-63.6928c-4.4032-14.7968 3.9936-30.3616 18.7392-34.7648 14.7456-4.4032 30.3616 3.9936 34.7648 18.7392l20.6848 69.2224c3.2256 10.752 1.9968 22.528-3.4304 32.3584z"
fill="#FFFFFF"
p-id="11124"
></path>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View 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>

View File

@ -2,3 +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 LayoutSetting } from './LayoutSetting.vue'

View File

@ -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 = {}) {
// propsoptionsmodalOptions // propsoptionsmodalOptions
modalOptions.value = { ...props, ...options } modalOptions.value = { ...props, ...options }
// showtrue // showtrue
show.value = true show.value = true
} }

View 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>

View 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>

View File

@ -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>

View File

@ -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
---------------------------------> --------------------------------->

View File

@ -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>

View File

@ -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'

View File

@ -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
---------------------------------> --------------------------------->

View File

@ -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
---------------------------------> --------------------------------->

View File

@ -1,2 +0,0 @@
export { default as UserAvatar } from './UserAvatar.vue'
export { default as AppTab } from './tab/index.vue'

View File

@ -0,0 +1,57 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:51:10
- @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">
<MenuCollapse />
<BreadCrumb />
<div class="ml-auto 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 { MenuCollapse, UserAvatar, BreadCrumb } from '@/layouts/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>

View File

@ -0,0 +1,42 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:51:02
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
<template>
<div class="wh-full flex">
<aside
class="flex-col flex-shrink-0 transition-width-300"
:class="appStore.collapsed ? 'w-64' : 'w-220'"
border-r="1px solid light_border dark:dark_border"
>
<SideBar />
</aside>
<article class="w-0 flex-col flex-1">
<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 />
</article>
</div>
</template>
<script setup>
import { useAppStore } from '@/store'
import { AppTab } from '@/layouts/components'
import SideBar from './sidebar/index.vue'
import AppHeader from './header/index.vue'
const appStore = useAppStore()
</script>
<style>
.collapsed {
width: 64px;
}
</style>

View File

@ -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>

View File

@ -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()

View File

@ -1,7 +1,7 @@
<!-------------------------------- <!--------------------------------
- @Author: Ronnie Zhang - @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang - @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/05 21:24:19 - @LastEditTime: 2023/12/13 20:54:55
- @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,7 @@
</aside> </aside>
<article class="w-0 flex-col flex-1"> <article class="w-0 flex-col flex-1">
<AppHeader :class="`h-${header.height}`" class="flex-shrink-0" /> <AppHeader class="h-60 flex-shrink-0" />
<slot /> <slot />
</article> </article>
</div> </div>
@ -28,9 +28,6 @@ import { useAppStore } from '@/store'
import SideBar from './sidebar/index.vue' import SideBar from './sidebar/index.vue'
import AppHeader from './header/index.vue' import AppHeader from './header/index.vue'
import settings from '@/settings'
const { header } = settings
const appStore = useAppStore() const appStore = useAppStore()
</script> </script>

View File

@ -0,0 +1,16 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:46:06
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
<template>
<SideLogo border-b="1px solid light_border dark:dark_border" />
<SideMenu class="cus-scroll-y mt-4 h-0 flex-1" />
</template>
<script setup>
import { SideLogo, SideMenu } from '@/layouts/components'
</script>

View File

@ -0,0 +1,36 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:51:47
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
<template>
<div class="wh-full flex">
<aside
class="flex-col flex-shrink-0 transition-width-300"
:class="appStore.collapsed ? 'w-64' : 'w-220'"
border-r="1px solid light_border dark:dark_border"
>
<SideBar />
</aside>
<article class="w-0 flex-col flex-1">
<slot />
</article>
</div>
</template>
<script setup>
import { useAppStore } from '@/store'
import SideBar from './sidebar/index.vue'
const appStore = useAppStore()
</script>
<style>
.collapsed {
width: 64px;
}
</style>

View File

@ -0,0 +1,23 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/05 21:24:09
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
<template>
<SideLogo border-b="1px solid light_border dark:dark_border" />
<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>
<script setup>
import { UserAvatar, MenuCollapse, SideLogo, SideMenu } from '@/layouts/components'
import { useAppStore } from '@/store'
const appStore = useAppStore()
</script>

View File

@ -1,47 +1,39 @@
/********************************** /**********************************
* @Author: Ronnie Zhang * @Author: Ronnie Zhang
* @LastEditor: Ronnie Zhang * @LastEditor: Ronnie Zhang
* @LastEditTime: 2023/12/05 21:30:24 * @LastEditTime: 2023/12/13 20:54:36
* @Email: zclzone@outlook.com * @Email: zclzone@outlook.com
* Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
**********************************/ **********************************/
export default { export const defaultLayout = 'normal'
defaultLayout: 'default',
header: {
height: 60,
},
tab: {
visible: true,
height: 50,
},
naiveThemeOverrides: {
common: {
primaryColor: '#316C72FF',
primaryColorHover: '#316C72E3',
primaryColorPressed: '#2B4C59FF',
primaryColorSuppl: '#316C72E3',
infoColor: '#2080F0FF', export const naiveThemeOverrides = {
infoColorHover: '#4098FCFF', common: {
infoColorPressed: '#1060C9FF', primaryColor: '#316C72FF',
infoColorSuppl: '#4098FCFF', primaryColorHover: '#316C72E3',
primaryColorPressed: '#2B4C59FF',
primaryColorSuppl: '#316C72E3',
successColor: '#18A058FF', infoColor: '#2080F0FF',
successColorHover: '#36AD6AFF', infoColorHover: '#4098FCFF',
successColorPressed: '#0C7A43FF', infoColorPressed: '#1060C9FF',
successColorSuppl: '#36AD6AFF', infoColorSuppl: '#4098FCFF',
warningColor: '#F0A020FF', successColor: '#18A058FF',
warningColorHover: '#FCB040FF', successColorHover: '#36AD6AFF',
warningColorPressed: '#C97C10FF', successColorPressed: '#0C7A43FF',
warningColorSuppl: '#FCB040FF', successColorSuppl: '#36AD6AFF',
errorColor: '#D03050FF', warningColor: '#F0A020FF',
errorColorHover: '#DE576DFF', warningColorHover: '#FCB040FF',
errorColorPressed: '#AB1F3FFF', warningColorPressed: '#C97C10FF',
errorColorSuppl: '#DE576DFF', warningColorSuppl: '#FCB040FF',
},
errorColor: '#D03050FF',
errorColorHover: '#DE576DFF',
errorColorPressed: '#AB1F3FFF',
errorColorSuppl: '#DE576DFF',
}, },
} }

View File

@ -8,13 +8,14 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { useDark } from '@vueuse/core' import { useDark } from '@vueuse/core'
import settings from '@/settings' import { defaultLayout, naiveThemeOverrides } from '@/settings'
export const useAppStore = defineStore('app', { export const useAppStore = defineStore('app', {
state: () => ({ state: () => ({
collapsed: false, collapsed: false,
isDark: useDark(), isDark: useDark(),
layout: settings.defaultLayout, layout: defaultLayout,
naiveThemeOverrides,
}), }),
actions: { actions: {
switchCollapsed() { switchCollapsed() {
@ -26,12 +27,12 @@ export const useAppStore = defineStore('app', {
toggleDark() { toggleDark() {
this.isDark = !this.isDark this.isDark = !this.isDark
}, },
setDeaultLayout(v) { setLayout(v) {
this.layout = v this.layout = v
}, },
}, },
persist: { persist: {
paths: ['layout', 'collapsed'], paths: ['collapsed', 'naiveThemeOverrides'],
storage: localStorage, storage: localStorage,
}, },
}) })

View File

@ -64,7 +64,7 @@ export const usePermissionStore = defineStore('permission', {
meta: { meta: {
icon: item.icon, icon: item.icon,
title: item.name, title: item.name,
layout: item.layout || 'default', layout: item.layout,
keepAlive: !!item.keepAlive, keepAlive: !!item.keepAlive,
parentKey, parentKey,
btns: item.children btns: item.children

View File

@ -9,7 +9,6 @@
import * as NaiveUI from 'naive-ui' import * as NaiveUI from 'naive-ui'
import { isNullOrUndef } from '@/utils' import { isNullOrUndef } from '@/utils'
import settings from '@/settings'
import { useAppStore } from '@/store/modules/app' import { useAppStore } from '@/store/modules/app'
export function setupMessage(NMessage) { export function setupMessage(NMessage) {
@ -104,10 +103,9 @@ export function setupDialog(NDialog) {
export function setupNaiveDiscreteApi() { export function setupNaiveDiscreteApi() {
const appStore = useAppStore() const appStore = useAppStore()
const { naiveThemeOverrides: themeOverrides } = settings
const configProviderProps = computed(() => ({ const configProviderProps = computed(() => ({
theme: appStore.isDark ? NaiveUI.darkTheme : undefined, theme: appStore.isDark ? NaiveUI.darkTheme : undefined,
themeOverrides, themeOverrides: useAppStore().naiveThemeOverrides,
})) }))
const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi( const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi(
['message', 'dialog', 'notification', 'loadingBar'], ['message', 'dialog', 'notification', 'loadingBar'],

View File

@ -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() {
// modaloptions
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>

View File

@ -155,7 +155,10 @@ const iconOptions = icons.map((item) => ({
value: item, value: item,
})) }))
const layoutOptions = [ const layoutOptions = [
{ label: '默认-default', value: 'default' }, { label: '跟随系统', value: '' },
{ label: '简约-simple', value: 'simple' },
{ label: '通用-normal', value: 'normal' },
{ label: '全面-full', value: 'full' },
{ label: '空白-empty', value: 'empty' }, { label: '空白-empty', value: 'empty' },
] ]
const required = { const required = {

View File

@ -49,7 +49,7 @@
<span v-else></span> <span v-else></span>
</n-descriptions-item> </n-descriptions-item>
<n-descriptions-item label="layout"> <n-descriptions-item label="layout">
{{ currentMenu.layout ?? 'default' }} {{ currentMenu.layout || '跟随系统' }}
</n-descriptions-item> </n-descriptions-item>
<n-descriptions-item label="是否显示"> <n-descriptions-item label="是否显示">
{{ currentMenu.show ? '是' : '否' }} {{ currentMenu.show ? '是' : '否' }}