修复引入问题
This commit is contained in:
@@ -4,13 +4,9 @@
|
|||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<div class="setting-title">布局模式</div>
|
<div class="setting-title">布局模式</div>
|
||||||
<div class="layout-mode-list">
|
<div class="layout-mode-list">
|
||||||
<div
|
<div v-for="mode in layoutModes" :key="mode.value" class="layout-mode-item"
|
||||||
v-for="mode in layoutModes"
|
|
||||||
:key="mode.value"
|
|
||||||
class="layout-mode-item"
|
|
||||||
:class="{ active: layoutStore.layoutMode === mode.value }"
|
:class="{ active: layoutStore.layoutMode === mode.value }"
|
||||||
@click="handleLayoutChange(mode.value)"
|
@click="handleLayoutChange(mode.value)">
|
||||||
>
|
|
||||||
<div class="layout-preview" :class="`preview-${mode.value}`">
|
<div class="layout-preview" :class="`preview-${mode.value}`">
|
||||||
<div class="preview-sidebar"></div>
|
<div class="preview-sidebar"></div>
|
||||||
<div v-if="mode.value === 'default'" class="preview-sidebar-2"></div>
|
<div v-if="mode.value === 'default'" class="preview-sidebar-2"></div>
|
||||||
@@ -28,14 +24,9 @@
|
|||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<div class="setting-title">主题颜色</div>
|
<div class="setting-title">主题颜色</div>
|
||||||
<div class="color-list">
|
<div class="color-list">
|
||||||
<div
|
<div v-for="color in themeColors" :key="color" class="color-item"
|
||||||
v-for="color in themeColors"
|
:class="{ active: themeColor === color }" :style="{ backgroundColor: color }"
|
||||||
:key="color"
|
@click="changeThemeColor(color)">
|
||||||
class="color-item"
|
|
||||||
:class="{ active: themeColor === color }"
|
|
||||||
:style="{ backgroundColor: color }"
|
|
||||||
@click="changeThemeColor(color)"
|
|
||||||
>
|
|
||||||
<CheckOutlined v-if="themeColor === color" />
|
<CheckOutlined v-if="themeColor === color" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,14 +60,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, defineExpose, defineOptions, watch, onMounted } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { useLayoutStore } from '@/stores/modules/layout'
|
import { useLayoutStore } from '@/stores/modules/layout'
|
||||||
import { CheckOutlined, ReloadOutlined } from '@ant-design/icons-vue'
|
import { CheckOutlined, ReloadOutlined } from '@ant-design/icons-vue'
|
||||||
|
|
||||||
// 定义组件名称(多词命名)
|
// 定义组件名称(多词命名)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'LayoutSetting'
|
name: 'LayoutSetting',
|
||||||
})
|
})
|
||||||
|
|
||||||
const layoutStore = useLayoutStore()
|
const layoutStore = useLayoutStore()
|
||||||
@@ -89,19 +80,10 @@ const showBreadcrumb = ref(true)
|
|||||||
const layoutModes = [
|
const layoutModes = [
|
||||||
{ value: 'default', label: '默认布局' },
|
{ value: 'default', label: '默认布局' },
|
||||||
{ value: 'menu', label: '菜单布局' },
|
{ value: 'menu', label: '菜单布局' },
|
||||||
{ value: 'top', label: '顶部布局' }
|
{ value: 'top', label: '顶部布局' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const themeColors = [
|
const themeColors = ['#1890ff', '#f5222d', '#fa541c', '#faad14', '#13c2c2', '#52c41a', '#2f54eb', '#722ed1']
|
||||||
'#1890ff',
|
|
||||||
'#f5222d',
|
|
||||||
'#fa541c',
|
|
||||||
'#faad14',
|
|
||||||
'#13c2c2',
|
|
||||||
'#52c41a',
|
|
||||||
'#2f54eb',
|
|
||||||
'#722ed1'
|
|
||||||
]
|
|
||||||
|
|
||||||
const openDrawer = () => {
|
const openDrawer = () => {
|
||||||
open.value = true
|
open.value = true
|
||||||
@@ -113,13 +95,13 @@ const closeDrawer = () => {
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
openDrawer,
|
openDrawer,
|
||||||
closeDrawer
|
closeDrawer,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 切换布局
|
// 切换布局
|
||||||
const handleLayoutChange = (mode) => {
|
const handleLayoutChange = (mode) => {
|
||||||
layoutStore.setLayoutMode(mode)
|
layoutStore.setLayoutMode(mode)
|
||||||
const modeLabel = layoutModes.find(m => m.value === mode)?.label || mode
|
const modeLabel = layoutModes.find((m) => m.value === mode)?.label || mode
|
||||||
message.success(`已切换到${modeLabel}`)
|
message.success(`已切换到${modeLabel}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,19 +53,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onMounted, defineOptions } from 'vue'
|
import { ref, computed, watch, onMounted } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { useLayoutStore } from '@/stores/modules/layout'
|
import { useLayoutStore } from '@/stores/modules/layout'
|
||||||
import {
|
import { ReloadOutlined, CloseOutlined, ColumnWidthOutlined, CloseCircleOutlined } from '@ant-design/icons-vue'
|
||||||
ReloadOutlined,
|
|
||||||
CloseOutlined,
|
|
||||||
ColumnWidthOutlined,
|
|
||||||
CloseCircleOutlined
|
|
||||||
} from '@ant-design/icons-vue'
|
|
||||||
|
|
||||||
// 定义组件名称(多词命名)
|
// 定义组件名称(多词命名)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'TagsView'
|
name: 'TagsView',
|
||||||
})
|
})
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -91,7 +86,7 @@ const addTags = () => {
|
|||||||
name: name,
|
name: name,
|
||||||
query: route.query,
|
query: route.query,
|
||||||
params: route.params,
|
params: route.params,
|
||||||
meta: route.meta
|
meta: route.meta,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +102,7 @@ const closeSelectedTag = (view) => {
|
|||||||
|
|
||||||
// 如果关闭的是当前激活的标签,需要跳转
|
// 如果关闭的是当前激活的标签,需要跳转
|
||||||
if (isActive(view)) {
|
if (isActive(view)) {
|
||||||
const nextTag = visitedViews.value.find(tag => tag.fullPath !== view.fullPath)
|
const nextTag = visitedViews.value.find((tag) => tag.fullPath !== view.fullPath)
|
||||||
if (nextTag) {
|
if (nextTag) {
|
||||||
router.push(nextTag.fullPath)
|
router.push(nextTag.fullPath)
|
||||||
} else {
|
} else {
|
||||||
@@ -124,9 +119,7 @@ const closeOthersTags = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保留固定标签和当前选中的标签
|
// 保留固定标签和当前选中的标签
|
||||||
const tagsToKeep = visitedViews.value.filter(tag =>
|
const tagsToKeep = visitedViews.value.filter((tag) => tag.meta?.affix || tag.fullPath === selectedTag.value.fullPath)
|
||||||
tag.meta?.affix || tag.fullPath === selectedTag.value.fullPath
|
|
||||||
)
|
|
||||||
|
|
||||||
// 更新标签列表
|
// 更新标签列表
|
||||||
layoutStore.viewTags = tagsToKeep
|
layoutStore.viewTags = tagsToKeep
|
||||||
@@ -140,7 +133,7 @@ const closeOthersTags = () => {
|
|||||||
// 关闭所有标签
|
// 关闭所有标签
|
||||||
const closeAllTags = () => {
|
const closeAllTags = () => {
|
||||||
// 只保留固定标签
|
// 只保留固定标签
|
||||||
const affixTags = visitedViews.value.filter(tag => tag.meta?.affix)
|
const affixTags = visitedViews.value.filter((tag) => tag.meta?.affix)
|
||||||
layoutStore.viewTags = affixTags
|
layoutStore.viewTags = affixTags
|
||||||
|
|
||||||
// 如果还有固定标签,跳转到第一个固定标签
|
// 如果还有固定标签,跳转到第一个固定标签
|
||||||
@@ -192,16 +185,20 @@ const handleMenuClick = ({ key }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 监听路由变化,自动添加标签
|
// 监听路由变化,自动添加标签
|
||||||
watch(() => route.fullPath, () => {
|
watch(
|
||||||
addTags()
|
() => route.fullPath,
|
||||||
// 更新当前选中的标签
|
() => {
|
||||||
selectedTag.value = visitedViews.value.find(tag => isActive(tag)) || {}
|
addTags()
|
||||||
}, { immediate: true })
|
// 更新当前选中的标签
|
||||||
|
selectedTag.value = visitedViews.value.find((tag) => isActive(tag)) || {}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
addTags()
|
addTags()
|
||||||
// 初始化选中的标签
|
// 初始化选中的标签
|
||||||
selectedTag.value = visitedViews.value.find(tag => isActive(tag)) || {}
|
selectedTag.value = visitedViews.value.find((tag) => isActive(tag)) || {}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -111,28 +111,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, onUnmounted, defineOptions } from 'vue'
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { useUserStore } from '@/stores/modules/user'
|
import { useUserStore } from '@/stores/modules/user'
|
||||||
import { useI18nStore } from '@/stores/modules/i18n'
|
import { useI18nStore } from '@/stores/modules/i18n'
|
||||||
import {
|
import { DownOutlined, UserOutlined, LogoutOutlined, FullscreenOutlined, FullscreenExitOutlined, BellOutlined, CheckSquareOutlined, GlobalOutlined, SearchOutlined, SettingOutlined } from '@ant-design/icons-vue'
|
||||||
DownOutlined,
|
|
||||||
UserOutlined,
|
|
||||||
LogoutOutlined,
|
|
||||||
FullscreenOutlined,
|
|
||||||
FullscreenExitOutlined,
|
|
||||||
BellOutlined,
|
|
||||||
CheckSquareOutlined,
|
|
||||||
GlobalOutlined,
|
|
||||||
SearchOutlined,
|
|
||||||
SettingOutlined
|
|
||||||
} from '@ant-design/icons-vue'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
// 定义组件名称(多词命名)
|
// 定义组件名称(多词命名)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'UserBar'
|
name: 'UserBar',
|
||||||
})
|
})
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -147,7 +136,7 @@ const messages = ref([
|
|||||||
{ id: 1, title: '系统通知:新版本已发布', time: '10分钟前', read: false },
|
{ id: 1, title: '系统通知:新版本已发布', time: '10分钟前', read: false },
|
||||||
{ id: 2, title: '任务提醒:请完成待审核的用户', time: '30分钟前', read: false },
|
{ id: 2, title: '任务提醒:请完成待审核的用户', time: '30分钟前', read: false },
|
||||||
{ id: 3, title: '安全警告:检测到异常登录', time: '1小时前', read: true },
|
{ id: 3, title: '安全警告:检测到异常登录', time: '1小时前', read: true },
|
||||||
{ id: 4, title: '数据备份已完成', time: '2小时前', read: true }
|
{ id: 4, title: '数据备份已完成', time: '2小时前', read: true },
|
||||||
])
|
])
|
||||||
|
|
||||||
const messageCount = computed(() => messages.value.filter((m) => !m.read).length)
|
const messageCount = computed(() => messages.value.filter((m) => !m.read).length)
|
||||||
@@ -156,7 +145,7 @@ const messageCount = computed(() => messages.value.filter((m) => !m.read).length
|
|||||||
const tasks = ref([
|
const tasks = ref([
|
||||||
{ id: 1, title: '完成用户审核', completed: false },
|
{ id: 1, title: '完成用户审核', completed: false },
|
||||||
{ id: 2, title: '更新系统文档', completed: false },
|
{ id: 2, title: '更新系统文档', completed: false },
|
||||||
{ id: 3, title: '优化数据库查询', completed: true }
|
{ id: 3, title: '优化数据库查询', completed: true },
|
||||||
])
|
])
|
||||||
|
|
||||||
const taskCount = computed(() => tasks.value.filter((t) => !t.completed).length)
|
const taskCount = computed(() => tasks.value.filter((t) => !t.completed).length)
|
||||||
@@ -244,7 +233,7 @@ const handleLogout = () => {
|
|||||||
} catch {
|
} catch {
|
||||||
message.error(t('common.logoutFailed'))
|
message.error(t('common.logoutFailed'))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -89,7 +89,8 @@
|
|||||||
<div class="logo-box-top">
|
<div class="logo-box-top">
|
||||||
<span class="logo-text">VUE ADMIN</span>
|
<span class="logo-text">VUE ADMIN</span>
|
||||||
</div>
|
</div>
|
||||||
<a-menu v-model:selectedKeys="selectedKeys" mode="horizontal" :selected-keys="[route.path]" style="line-height: 60px">
|
<a-menu v-model:selectedKeys="selectedKeys" mode="horizontal" :selected-keys="[route.path]"
|
||||||
|
style="line-height: 60px">
|
||||||
<navMenu :menu-items="menuList" :active-path="route.path" />
|
<navMenu :menu-items="menuList" :active-path="route.path" />
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,7 +119,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, defineOptions, ref, watch, onMounted } from 'vue'
|
import { computed, ref, watch, onMounted } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { useLayoutStore } from '@/stores/modules/layout'
|
import { useLayoutStore } from '@/stores/modules/layout'
|
||||||
import { useUserStore } from '@/stores/modules/user'
|
import { useUserStore } from '@/stores/modules/user'
|
||||||
@@ -133,8 +134,8 @@ import setting from './components/setting.vue'
|
|||||||
|
|
||||||
// 定义组件名称(多词命名)
|
// 定义组件名称(多词命名)
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'AppLayouts'
|
name: 'AppLayouts',
|
||||||
});
|
})
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -149,9 +150,7 @@ const selectedParentMenu = computed(() => layoutStore.selectedParentMenu)
|
|||||||
|
|
||||||
// 缓存的视图列表
|
// 缓存的视图列表
|
||||||
const cachedViews = computed(() => {
|
const cachedViews = computed(() => {
|
||||||
return layoutStore.viewTags
|
return layoutStore.viewTags.filter((tag) => !tag.meta?.noCache).map((tag) => tag.name)
|
||||||
.filter(tag => !tag.meta?.noCache)
|
|
||||||
.map(tag => tag.name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 布局类名
|
// 布局类名
|
||||||
@@ -160,7 +159,7 @@ const layoutClass = computed(() => {
|
|||||||
'layout-default': layoutMode.value === 'default',
|
'layout-default': layoutMode.value === 'default',
|
||||||
'layout-menu': layoutMode.value === 'menu',
|
'layout-menu': layoutMode.value === 'menu',
|
||||||
'layout-top': layoutMode.value === 'top',
|
'layout-top': layoutMode.value === 'top',
|
||||||
'is-collapse': sidebarCollapsed.value
|
'is-collapse': sidebarCollapsed.value,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -207,8 +206,8 @@ const updateMenuState = () => {
|
|||||||
selectedKeys.value = [route.path]
|
selectedKeys.value = [route.path]
|
||||||
|
|
||||||
// 获取所有父级路径
|
// 获取所有父级路径
|
||||||
const matched = route.matched.filter(item => item.path !== '/' && item.path !== route.path)
|
const matched = route.matched.filter((item) => item.path !== '/' && item.path !== route.path)
|
||||||
const parentPaths = matched.map(item => item.path)
|
const parentPaths = matched.map((item) => item.path)
|
||||||
|
|
||||||
// 对于不同的布局模式,处理方式不同
|
// 对于不同的布局模式,处理方式不同
|
||||||
if (layoutMode.value === 'default') {
|
if (layoutMode.value === 'default') {
|
||||||
@@ -271,24 +270,34 @@ const findParentMenu = (menus, path) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 监听路由变化,更新菜单状态
|
// 监听路由变化,更新菜单状态
|
||||||
watch(() => route.path, (newPath) => {
|
watch(
|
||||||
console.log('路由变化:', newPath)
|
() => route.path,
|
||||||
updateMenuState()
|
(newPath) => {
|
||||||
}, { immediate: true })
|
console.log('路由变化:', newPath)
|
||||||
|
updateMenuState()
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
|
||||||
// 监听布局模式变化,确保菜单状态正确
|
// 监听布局模式变化,确保菜单状态正确
|
||||||
watch(() => layoutMode.value, () => {
|
watch(
|
||||||
updateMenuState()
|
() => layoutMode.value,
|
||||||
})
|
() => {
|
||||||
|
updateMenuState()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// 监听折叠状态
|
// 监听折叠状态
|
||||||
watch(() => sidebarCollapsed.value, (val) => {
|
watch(
|
||||||
if (val) {
|
() => sidebarCollapsed.value,
|
||||||
openKeys.value = []
|
(val) => {
|
||||||
} else {
|
if (val) {
|
||||||
updateMenuState()
|
openKeys.value = []
|
||||||
}
|
} else {
|
||||||
})
|
updateMenuState()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user