更新
This commit is contained in:
@@ -1,15 +1,17 @@
|
|||||||
<template><el-breadcrumb separator="/">
|
<template>
|
||||||
<transition-group name="breadcrumb">
|
<el-breadcrumb separator="/">
|
||||||
<el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
|
<transition-group name="breadcrumb">
|
||||||
<span v-if="index === breadcrumbs.length - 1" class="no-redirect">
|
<el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
|
||||||
{{ item.meta?.title }}
|
<span v-if="index === breadcrumbs.length - 1" class="no-redirect">
|
||||||
</span>
|
{{ item.meta?.title }}
|
||||||
<a v-else class="redirect" @click.prevent="handleLink(item)">
|
</span>
|
||||||
{{ item.meta?.title }}
|
<a v-else class="redirect" @click.prevent="handleLink(item)">
|
||||||
</a>
|
{{ item.meta?.title }}
|
||||||
</el-breadcrumb-item>
|
</a>
|
||||||
</transition-group>
|
</el-breadcrumb-item>
|
||||||
</el-breadcrumb></template>
|
</transition-group>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|||||||
@@ -1,26 +1,28 @@
|
|||||||
<template><template v-for="menu in menuList" :key="menu.path">
|
<template>
|
||||||
<!-- 有子菜单 -->
|
<template v-for="menu in menuList" :key="menu.path">
|
||||||
<el-sub-menu v-if="hasChildren(menu) && !menu.meta?.hidden" :index="menu.path">
|
<!-- 有子菜单 -->
|
||||||
<template #title>
|
<el-sub-menu v-if="hasChildren(menu) && !menu.meta?.hidden" :index="menu.path">
|
||||||
|
<template #title>
|
||||||
|
<el-icon v-if="menu.meta?.icon">
|
||||||
|
<component :is="menu.meta.icon" />
|
||||||
|
</el-icon>
|
||||||
|
<span>{{ menu.meta?.title }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- 递归渲染子菜单 -->
|
||||||
|
<menu-item :menu-list="menu.children" :parent-path="menu.path" />
|
||||||
|
</el-sub-menu>
|
||||||
|
|
||||||
|
<!-- 无子菜单 -->
|
||||||
|
<el-menu-item v-else-if="!menu.meta?.hidden" :index="menu.path">
|
||||||
<el-icon v-if="menu.meta?.icon">
|
<el-icon v-if="menu.meta?.icon">
|
||||||
<component :is="menu.meta.icon" />
|
<component :is="menu.meta.icon" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>{{ menu.meta?.title }}</span>
|
<template #title>
|
||||||
</template>
|
<span>{{ menu.meta?.title }}</span>
|
||||||
<!-- 递归渲染子菜单 -->
|
</template>
|
||||||
<menu-item :menu-list="menu.children" :parent-path="menu.path" />
|
</el-menu-item>
|
||||||
</el-sub-menu>
|
</template>
|
||||||
|
</template>
|
||||||
<!-- 无子菜单 -->
|
|
||||||
<el-menu-item v-else-if="!menu.meta?.hidden" :index="menu.path">
|
|
||||||
<el-icon v-if="menu.meta?.icon">
|
|
||||||
<component :is="menu.meta.icon" />
|
|
||||||
</el-icon>
|
|
||||||
<template #title>
|
|
||||||
<span>{{ menu.meta?.title }}</span>
|
|
||||||
</template>
|
|
||||||
</el-menu-item>
|
|
||||||
</template></template>
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
|||||||
@@ -1,29 +1,30 @@
|
|||||||
<template><el-menu :default-active="activeMenu" :mode="menuMode" :collapse="isCollapse" :unique-opened="uniqueOpened"
|
<template>
|
||||||
:router="true" :collapse-transition="false" @select="handleSelect">
|
<el-menu :default-active="activeMenu" :mode="menuMode" :collapse="isCollapse" :unique-opened="uniqueOpened" :router="true" :collapse-transition="false" @select="handleSelect">
|
||||||
<template v-for="menu in menuList" :key="menu.path">
|
<template v-for="menu in menuList" :key="menu.path">
|
||||||
<!-- 有子菜单 -->
|
<!-- 有子菜单 -->
|
||||||
<el-sub-menu v-if="hasChildren(menu) && !menu.meta?.hidden" :index="menu.path">
|
<el-sub-menu v-if="hasChildren(menu) && !menu.meta?.hidden" :index="menu.path">
|
||||||
<template #title>
|
<template #title>
|
||||||
|
<el-icon v-if="menu.meta?.icon">
|
||||||
|
<component :is="menu.meta.icon" />
|
||||||
|
</el-icon>
|
||||||
|
<span>{{ menu.meta?.title }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- 递归渲染子菜单 -->
|
||||||
|
<menu-item :menu-list="menu.children" :parent-path="menu.path" />
|
||||||
|
</el-sub-menu>
|
||||||
|
|
||||||
|
<!-- 无子菜单 -->
|
||||||
|
<el-menu-item v-else-if="!menu.meta?.hidden" :index="menu.path">
|
||||||
<el-icon v-if="menu.meta?.icon">
|
<el-icon v-if="menu.meta?.icon">
|
||||||
<component :is="menu.meta.icon" />
|
<component :is="menu.meta.icon" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>{{ menu.meta?.title }}</span>
|
<template #title>
|
||||||
</template>
|
<span>{{ menu.meta?.title }}</span>
|
||||||
<!-- 递归渲染子菜单 -->
|
</template>
|
||||||
<menu-item :menu-list="menu.children" :parent-path="menu.path" />
|
</el-menu-item>
|
||||||
</el-sub-menu>
|
</template>
|
||||||
|
</el-menu>
|
||||||
<!-- 无子菜单 -->
|
</template>
|
||||||
<el-menu-item v-else-if="!menu.meta?.hidden" :index="menu.path">
|
|
||||||
<el-icon v-if="menu.meta?.icon">
|
|
||||||
<component :is="menu.meta.icon" />
|
|
||||||
</el-icon>
|
|
||||||
<template #title>
|
|
||||||
<span>{{ menu.meta?.title }}</span>
|
|
||||||
</template>
|
|
||||||
</el-menu-item>
|
|
||||||
</template>
|
|
||||||
</el-menu></template>
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|||||||
@@ -1,150 +1,140 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="setting-container">
|
<div class="setting-container">
|
||||||
<!-- 设置按钮 -->
|
<!-- 设置按钮 -->
|
||||||
<div class="setting-btn" @click="showDrawer = true">
|
<div class="setting-btn" @click="showDrawer = true">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Setting />
|
<Setting />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 设置抽屉 -->
|
|
||||||
<el-drawer v-model="showDrawer" title="系统设置" :size="300" :close-on-click-modal="false">
|
|
||||||
<div class="setting-content">
|
|
||||||
<!-- 布局模式 -->
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-title">布局模式</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<el-radio-group v-model="layoutMode" @change="handleLayoutModeChange">
|
|
||||||
<el-radio label="default">
|
|
||||||
<div class="layout-option">
|
|
||||||
<div class="layout-preview layout-default">
|
|
||||||
<div class="layout-aside-left"></div>
|
|
||||||
<div class="layout-aside-right"></div>
|
|
||||||
<div class="layout-main"></div>
|
|
||||||
</div>
|
|
||||||
<span>双栏布局</span>
|
|
||||||
</div>
|
|
||||||
</el-radio>
|
|
||||||
<el-radio label="menu">
|
|
||||||
<div class="layout-option">
|
|
||||||
<div class="layout-preview layout-menu">
|
|
||||||
<div class="layout-aside"></div>
|
|
||||||
<div class="layout-main"></div>
|
|
||||||
</div>
|
|
||||||
<span>菜单布局</span>
|
|
||||||
</div>
|
|
||||||
</el-radio>
|
|
||||||
<el-radio label="top">
|
|
||||||
<div class="layout-option">
|
|
||||||
<div class="layout-preview layout-top">
|
|
||||||
<div class="layout-header"></div>
|
|
||||||
<div class="layout-main"></div>
|
|
||||||
</div>
|
|
||||||
<span>顶部布局</span>
|
|
||||||
</div>
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 主题色 -->
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-title">主题色</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<div class="color-picker-wrapper">
|
|
||||||
<el-color-picker v-model="themeColor" show-alpha :predefine="predefineColors"
|
|
||||||
@change="handleThemeColorChange" />
|
|
||||||
</div>
|
|
||||||
<div class="color-presets">
|
|
||||||
<div v-for="color in predefineColors" :key="color" class="color-preset"
|
|
||||||
:class="{ active: themeColor === color }" :style="{ backgroundColor: color }"
|
|
||||||
@click="handleColorPresetClick(color)"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 主题模式 -->
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-title">主题模式</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<el-radio-group v-model="isDark" @change="handleThemeModeChange">
|
|
||||||
<el-radio :label="false">
|
|
||||||
<el-icon>
|
|
||||||
<Sunny />
|
|
||||||
</el-icon>
|
|
||||||
浅色
|
|
||||||
</el-radio>
|
|
||||||
<el-radio :label="true">
|
|
||||||
<el-icon>
|
|
||||||
<Moon />
|
|
||||||
</el-icon>
|
|
||||||
深色
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 标签栏 -->
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-title">
|
|
||||||
<span>显示标签栏</span>
|
|
||||||
<el-tooltip content="开启后页面顶部显示标签页" placement="top">
|
|
||||||
<el-icon>
|
|
||||||
<QuestionFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<el-switch v-model="showTags" @change="handleShowTagsChange" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 面包屑 -->
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-title">
|
|
||||||
<span>显示面包屑</span>
|
|
||||||
<el-tooltip content="开启后页面顶部显示面包屑导航" placement="top">
|
|
||||||
<el-icon>
|
|
||||||
<QuestionFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<el-switch v-model="showBreadcrumb" @change="handleShowBreadcrumbChange" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
|
||||||
<div class="setting-actions">
|
|
||||||
<el-button type="primary" @click="handleSave">
|
|
||||||
<el-icon>
|
|
||||||
<Check />
|
|
||||||
</el-icon>
|
|
||||||
保存配置
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleReset">
|
|
||||||
<el-icon>
|
|
||||||
<RefreshLeft />
|
|
||||||
</el-icon>
|
|
||||||
重置默认
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
|
||||||
</div>
|
<!-- 设置抽屉 -->
|
||||||
|
<el-drawer v-model="showDrawer" title="系统设置" :size="300" :close-on-click-modal="false">
|
||||||
|
<div class="setting-content">
|
||||||
|
<!-- 布局模式 -->
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-title">布局模式</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
<el-radio-group v-model="layoutMode" @change="handleLayoutModeChange">
|
||||||
|
<el-radio label="default">
|
||||||
|
<div class="layout-option">
|
||||||
|
<div class="layout-preview layout-default">
|
||||||
|
<div class="layout-aside-left"></div>
|
||||||
|
<div class="layout-aside-right"></div>
|
||||||
|
<div class="layout-main"></div>
|
||||||
|
</div>
|
||||||
|
<span>双栏布局</span>
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
<el-radio label="menu">
|
||||||
|
<div class="layout-option">
|
||||||
|
<div class="layout-preview layout-menu">
|
||||||
|
<div class="layout-aside"></div>
|
||||||
|
<div class="layout-main"></div>
|
||||||
|
</div>
|
||||||
|
<span>菜单布局</span>
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
<el-radio label="top">
|
||||||
|
<div class="layout-option">
|
||||||
|
<div class="layout-preview layout-top">
|
||||||
|
<div class="layout-header"></div>
|
||||||
|
<div class="layout-main"></div>
|
||||||
|
</div>
|
||||||
|
<span>顶部布局</span>
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主题色 -->
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-title">主题色</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
<div class="color-picker-wrapper">
|
||||||
|
<el-color-picker v-model="themeColor" show-alpha :predefine="predefineColors" @change="handleThemeColorChange" />
|
||||||
|
</div>
|
||||||
|
<div class="color-presets">
|
||||||
|
<div v-for="color in predefineColors" :key="color" class="color-preset" :class="{ active: themeColor === color }" :style="{ backgroundColor: color }" @click="handleColorPresetClick(color)"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主题模式 -->
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-title">主题模式</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
<el-radio-group v-model="isDark" @change="handleThemeModeChange">
|
||||||
|
<el-radio :label="false">
|
||||||
|
<el-icon>
|
||||||
|
<Sunny />
|
||||||
|
</el-icon>
|
||||||
|
浅色
|
||||||
|
</el-radio>
|
||||||
|
<el-radio :label="true">
|
||||||
|
<el-icon>
|
||||||
|
<Moon />
|
||||||
|
</el-icon>
|
||||||
|
深色
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标签栏 -->
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-title">
|
||||||
|
<span>显示标签栏</span>
|
||||||
|
<el-tooltip content="开启后页面顶部显示标签页" placement="top">
|
||||||
|
<el-icon>
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
<el-switch v-model="showTags" @change="handleShowTagsChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 面包屑 -->
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-title">
|
||||||
|
<span>显示面包屑</span>
|
||||||
|
<el-tooltip content="开启后页面顶部显示面包屑导航" placement="top">
|
||||||
|
<el-icon>
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
<el-switch v-model="showBreadcrumb" @change="handleShowBreadcrumbChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="setting-actions">
|
||||||
|
<el-button type="primary" @click="handleSave">
|
||||||
|
<el-icon>
|
||||||
|
<Check />
|
||||||
|
</el-icon>
|
||||||
|
保存配置
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleReset">
|
||||||
|
<el-icon>
|
||||||
|
<RefreshLeft />
|
||||||
|
</el-icon>
|
||||||
|
重置默认
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import {
|
import { Setting, Sunny, Moon, QuestionFilled, Check, RefreshLeft } from '@element-plus/icons-vue'
|
||||||
Setting,
|
|
||||||
Sunny,
|
|
||||||
Moon,
|
|
||||||
QuestionFilled,
|
|
||||||
Check,
|
|
||||||
RefreshLeft,
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
import { useLayoutStore } from '@/stores/modules/layout'
|
import { useLayoutStore } from '@/stores/modules/layout'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -267,7 +257,6 @@ onMounted(() => {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.setting-container {
|
.setting-container {
|
||||||
|
|
||||||
// 设置按钮
|
// 设置按钮
|
||||||
.setting-btn {
|
.setting-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -321,7 +310,6 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setting-value {
|
.setting-value {
|
||||||
|
|
||||||
// 布局选项
|
// 布局选项
|
||||||
:deep(.el-radio-group) {
|
:deep(.el-radio-group) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1,43 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tags-view-container">
|
<div class="tags-view-container">
|
||||||
<el-scrollbar class="tags-view-wrapper">
|
<el-scrollbar class="tags-view-wrapper">
|
||||||
<router-link v-for="tag in visibleTags" :key="tag.fullPath" :class="isActive(tag) ? 'active' : ''"
|
<router-link v-for="tag in visibleTags" :key="tag.fullPath" :class="isActive(tag) ? 'active' : ''" class="tags-view-item" :to="{ path: tag.fullPath }" @click.middle="closeTag(tag)" @contextmenu.prevent="openMenu(tag, $event)">
|
||||||
class="tags-view-item" :to="{ path: tag.fullPath }" @click.middle="closeTag(tag)"
|
{{ tag.title || tag.meta?.title }}
|
||||||
@contextmenu.prevent="openMenu(tag, $event)">
|
<el-icon v-if="!tag.meta?.affix" class="el-icon-close" @click.prevent.stop="closeTag(tag)">
|
||||||
{{ tag.title || tag.meta?.title }}
|
<Close />
|
||||||
<el-icon v-if="!tag.meta?.affix" class="el-icon-close" @click.prevent.stop="closeTag(tag)">
|
</el-icon>
|
||||||
<Close />
|
</router-link>
|
||||||
</el-icon>
|
</el-scrollbar>
|
||||||
</router-link>
|
|
||||||
</el-scrollbar>
|
|
||||||
|
|
||||||
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
|
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
|
||||||
<li @click="refreshSelectedTag(selectedTag)">
|
<li @click="refreshSelectedTag(selectedTag)">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Refresh />
|
<Refresh />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
刷新
|
刷新
|
||||||
</li>
|
</li>
|
||||||
<li v-if="!selectedTag?.meta?.affix" @click="closeSelectedTag(selectedTag)">
|
<li v-if="!selectedTag?.meta?.affix" @click="closeSelectedTag(selectedTag)">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Close />
|
<Close />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
关闭
|
关闭
|
||||||
</li>
|
</li>
|
||||||
<li @click="closeOthersTags">
|
<li @click="closeOthersTags">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<CircleClose />
|
<CircleClose />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
关闭其他
|
关闭其他
|
||||||
</li>
|
</li>
|
||||||
<li @click="closeAllTags(selectedTag)">
|
<li @click="closeAllTags(selectedTag)">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<CircleCloseFilled />
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
关闭全部
|
关闭全部
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1,132 +1,115 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="userbar-container">
|
<div class="userbar-container">
|
||||||
<!-- 全屏切换 -->
|
<!-- 全屏切换 -->
|
||||||
<el-tooltip content="全屏" placement="bottom">
|
<el-tooltip content="全屏" placement="bottom">
|
||||||
<div class="icon-btn" @click="toggleFullScreen">
|
<div class="icon-btn" @click="toggleFullScreen">
|
||||||
<el-icon v-if="!isFullScreen">
|
<el-icon v-if="!isFullScreen">
|
||||||
<FullScreen />
|
<FullScreen />
|
||||||
</el-icon>
|
|
||||||
<el-icon v-else>
|
|
||||||
<Aim />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<!-- 语言切换 -->
|
|
||||||
<el-dropdown trigger="click" @command="handleLanguageChange">
|
|
||||||
<div class="icon-btn">
|
|
||||||
<el-icon>
|
|
||||||
<Location />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item :disabled="currentLanguage === 'zh-CN'" command="zh-CN">
|
|
||||||
简体中文
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item :disabled="currentLanguage === 'en-US'" command="en-US">
|
|
||||||
English
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
|
|
||||||
<!-- 主题设置 -->
|
|
||||||
<el-dropdown trigger="click">
|
|
||||||
<div class="icon-btn">
|
|
||||||
<el-icon>
|
|
||||||
<Sunny />
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item @click="setTheme('light')">
|
|
||||||
<el-icon>
|
|
||||||
<Sunny />
|
|
||||||
</el-icon>
|
|
||||||
浅色主题
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item @click="setTheme('dark')">
|
|
||||||
<el-icon>
|
|
||||||
<Moon />
|
|
||||||
</el-icon>
|
|
||||||
深色主题
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
|
|
||||||
<!-- 消息通知 -->
|
|
||||||
<el-tooltip content="消息" placement="bottom">
|
|
||||||
<div class="icon-btn">
|
|
||||||
<el-badge :value="messageCount" :hidden="messageCount === 0" :max="99">
|
|
||||||
<el-icon>
|
|
||||||
<Bell />
|
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-badge>
|
<el-icon v-else>
|
||||||
</div>
|
<Aim />
|
||||||
</el-tooltip>
|
</el-icon>
|
||||||
<el-dropdown trigger="click" @command="handleCommand">
|
</div>
|
||||||
<div class="avatar-wrapper">
|
</el-tooltip>
|
||||||
<el-avatar v-if="userStore.userInfo?.avatar" :src="userStore.userInfo.avatar" />
|
|
||||||
<el-avatar v-else>
|
<!-- 语言切换 -->
|
||||||
<UserFilled />
|
<el-dropdown trigger="click" @command="handleLanguageChange">
|
||||||
</el-avatar>
|
<div class="icon-btn">
|
||||||
<span class="username">{{ userStore.userInfo?.username || 'Admin' }}</span>
|
<el-icon>
|
||||||
<el-icon class="el-icon-caret-bottom">
|
<Location />
|
||||||
<ArrowDown />
|
</el-icon>
|
||||||
</el-icon>
|
</div>
|
||||||
</div>
|
<template #dropdown>
|
||||||
<template #dropdown>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-item :disabled="currentLanguage === 'zh-CN'" command="zh-CN"> 简体中文 </el-dropdown-item>
|
||||||
<el-dropdown-item command="home">
|
<el-dropdown-item :disabled="currentLanguage === 'en-US'" command="en-US"> English </el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
|
<!-- 主题设置 -->
|
||||||
|
<el-dropdown trigger="click">
|
||||||
|
<div class="icon-btn">
|
||||||
|
<el-icon>
|
||||||
|
<Sunny />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click="setTheme('light')">
|
||||||
|
<el-icon>
|
||||||
|
<Sunny />
|
||||||
|
</el-icon>
|
||||||
|
浅色主题
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click="setTheme('dark')">
|
||||||
|
<el-icon>
|
||||||
|
<Moon />
|
||||||
|
</el-icon>
|
||||||
|
深色主题
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
|
<!-- 消息通知 -->
|
||||||
|
<el-tooltip content="消息" placement="bottom">
|
||||||
|
<div class="icon-btn">
|
||||||
|
<el-badge :value="messageCount" :hidden="messageCount === 0" :max="99">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<HomeFilled />
|
<Bell />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
首页
|
</el-badge>
|
||||||
</el-dropdown-item>
|
</div>
|
||||||
<el-dropdown-item command="profile">
|
</el-tooltip>
|
||||||
<el-icon>
|
<el-dropdown trigger="click" @command="handleCommand">
|
||||||
<User />
|
<div class="avatar-wrapper">
|
||||||
</el-icon>
|
<el-avatar v-if="userStore.userInfo?.avatar" :src="userStore.userInfo.avatar" />
|
||||||
个人中心
|
<el-avatar v-else>
|
||||||
</el-dropdown-item>
|
<UserFilled />
|
||||||
<el-dropdown-item divided command="settings">
|
</el-avatar>
|
||||||
<el-icon>
|
<span class="username">{{ userStore.userInfo?.username || 'Admin' }}</span>
|
||||||
<Setting />
|
<el-icon class="el-icon-caret-bottom">
|
||||||
</el-icon>
|
<ArrowDown />
|
||||||
系统设置
|
</el-icon>
|
||||||
</el-dropdown-item>
|
</div>
|
||||||
<el-dropdown-item divided command="logout">
|
<template #dropdown>
|
||||||
<el-icon>
|
<el-dropdown-menu>
|
||||||
<SwitchButton />
|
<el-dropdown-item command="home">
|
||||||
</el-icon>
|
<el-icon>
|
||||||
退出登录
|
<HomeFilled />
|
||||||
</el-dropdown-item>
|
</el-icon>
|
||||||
</el-dropdown-menu>
|
首页
|
||||||
</template>
|
</el-dropdown-item>
|
||||||
</el-dropdown>
|
<el-dropdown-item command="profile">
|
||||||
</div>
|
<el-icon>
|
||||||
|
<User />
|
||||||
|
</el-icon>
|
||||||
|
个人中心
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided command="settings">
|
||||||
|
<el-icon>
|
||||||
|
<Setting />
|
||||||
|
</el-icon>
|
||||||
|
系统设置
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided command="logout">
|
||||||
|
<el-icon>
|
||||||
|
<SwitchButton />
|
||||||
|
</el-icon>
|
||||||
|
退出登录
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import {
|
import { ArrowDown, HomeFilled, User, Setting, SwitchButton, FullScreen, Aim, Location, Sunny, Moon, Bell, UserFilled } from '@element-plus/icons-vue'
|
||||||
ArrowDown,
|
|
||||||
HomeFilled,
|
|
||||||
User,
|
|
||||||
Setting,
|
|
||||||
SwitchButton,
|
|
||||||
FullScreen,
|
|
||||||
Aim,
|
|
||||||
Location,
|
|
||||||
Sunny,
|
|
||||||
Moon,
|
|
||||||
Bell,
|
|
||||||
UserFilled,
|
|
||||||
} from '@element-plus/icons-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'
|
||||||
|
|
||||||
|
|||||||
@@ -1,124 +1,124 @@
|
|||||||
<template><el-container class="app-wrapper" :class="layoutClass">
|
<template>
|
||||||
<!-- 默认布局:左侧双栏布局 -->
|
<el-container class="app-wrapper" :class="layoutClass">
|
||||||
<template v-if="layoutMode === 'default'">
|
<!-- 默认布局:左侧双栏布局 -->
|
||||||
<!-- 一级菜单栏 (窄侧边栏) -->
|
<template v-if="layoutMode === 'default'">
|
||||||
<el-aside width="60px" class="first-sidebar">
|
<!-- 一级菜单栏 (窄侧边栏) -->
|
||||||
<div class="logo-mini">
|
<el-aside width="60px" class="first-sidebar">
|
||||||
<img v-if="logo" :src="logo" alt="logo" />
|
<div class="logo-mini">
|
||||||
<span v-else class="logo-text-mini">{{ logoText }}</span>
|
<img v-if="logo" :src="logo" alt="logo" />
|
||||||
</div>
|
<span v-else class="logo-text-mini">{{ logoText }}</span>
|
||||||
<div class="menu-list">
|
|
||||||
<div v-for="menu in parentMenus" :key="menu.path" class="menu-item"
|
|
||||||
:class="{ active: selectedParentMenu?.path === menu.path }" @click="handleParentMenuClick(menu)">
|
|
||||||
<el-icon v-if="menu.meta?.icon">
|
|
||||||
<component :is="menu.meta.icon" />
|
|
||||||
</el-icon>
|
|
||||||
<span class="menu-text">{{ menu.meta?.title }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="menu-list">
|
||||||
</el-aside>
|
<div v-for="menu in parentMenus" :key="menu.path" class="menu-item" :class="{ active: selectedParentMenu?.path === menu.path }" @click="handleParentMenuClick(menu)">
|
||||||
|
<el-icon v-if="menu.meta?.icon">
|
||||||
<!-- 二级菜单栏 -->
|
<component :is="menu.meta.icon" />
|
||||||
<el-aside :width="sidebarCollapsed ? '60px' : '220px'" class="second-sidebar">
|
</el-icon>
|
||||||
<div v-if="!sidebarCollapsed" class="logo">
|
<span class="menu-text">{{ menu.meta?.title }}</span>
|
||||||
<img v-if="logo" :src="logo" alt="logo" />
|
|
||||||
<span class="logo-text">{{ logoText }}</span>
|
|
||||||
</div>
|
|
||||||
<el-scrollbar class="menu-scrollbar">
|
|
||||||
<menu-component />
|
|
||||||
</el-scrollbar>
|
|
||||||
</el-aside>
|
|
||||||
|
|
||||||
<!-- 主内容区 -->
|
|
||||||
<el-container class="main-container">
|
|
||||||
<el-header class="app-header">
|
|
||||||
<div class="header-left">
|
|
||||||
<el-icon class="collapse-icon" @click="toggleSidebar">
|
|
||||||
<component :is="sidebarCollapsed ? 'Expand' : 'Fold'" />
|
|
||||||
</el-icon>
|
|
||||||
<breadcrumb v-if="showBreadcrumb" />
|
|
||||||
</div>
|
|
||||||
<div class="header-right">
|
|
||||||
<userbar />
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<el-main class="app-main">
|
|
||||||
<tags v-if="showTags" />
|
|
||||||
<router-view v-slot="{ Component, route }">
|
|
||||||
<keep-alive :include="cachedViews">
|
|
||||||
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
|
||||||
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
|
||||||
</keep-alive>
|
|
||||||
</router-view>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Menu布局:左侧菜单栏布局 -->
|
|
||||||
<template v-else-if="layoutMode === 'menu'">
|
|
||||||
<el-aside :width="sidebarCollapsed ? '60px' : '220px'" class="menu-sidebar">
|
|
||||||
<div v-if="!sidebarCollapsed" class="logo">
|
|
||||||
<img v-if="logo" :src="logo" alt="logo" />
|
|
||||||
<span class="logo-text">{{ logoText }}</span>
|
|
||||||
</div>
|
|
||||||
<el-scrollbar class="menu-scrollbar">
|
|
||||||
<menu-component />
|
|
||||||
</el-scrollbar>
|
|
||||||
</el-aside>
|
|
||||||
<el-container class="main-container">
|
|
||||||
<el-header class="app-header">
|
|
||||||
<div class="header-left">
|
|
||||||
<el-icon class="collapse-icon" @click="toggleSidebar">
|
|
||||||
<component :is="sidebarCollapsed ? 'Expand' : 'Fold'" />
|
|
||||||
</el-icon>
|
|
||||||
<breadcrumb v-if="showBreadcrumb" />
|
|
||||||
</div>
|
|
||||||
<div class="header-right">
|
|
||||||
<tags v-if="showTags" />
|
|
||||||
<userbar />
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<el-main class="app-main">
|
|
||||||
<router-view v-slot="{ Component, route }">
|
|
||||||
<keep-alive :include="cachedViews">
|
|
||||||
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
|
||||||
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
|
||||||
</keep-alive>
|
|
||||||
</router-view>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Top布局:顶部菜单栏布局 -->
|
|
||||||
<template v-else-if="layoutMode === 'top'">
|
|
||||||
<el-container class="main-container">
|
|
||||||
<el-header class="top-header">
|
|
||||||
<div class="header-left">
|
|
||||||
<div class="logo">
|
|
||||||
<img v-if="logo" :src="logo" alt="logo" />
|
|
||||||
<span class="logo-text">{{ logoText }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<menu-component mode="horizontal" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
</el-aside>
|
||||||
<tags v-if="showTags" />
|
|
||||||
<userbar />
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<el-main class="app-main">
|
|
||||||
<router-view v-slot="{ Component, route }">
|
|
||||||
<keep-alive :include="cachedViews">
|
|
||||||
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
|
||||||
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
|
||||||
</keep-alive>
|
|
||||||
</router-view>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
</el-container>
|
|
||||||
|
|
||||||
<!-- 设置组件 -->
|
<!-- 二级菜单栏 -->
|
||||||
<setting />
|
<el-aside :width="sidebarCollapsed ? '60px' : '220px'" class="second-sidebar">
|
||||||
|
<div v-if="!sidebarCollapsed" class="logo">
|
||||||
|
<img v-if="logo" :src="logo" alt="logo" />
|
||||||
|
<span class="logo-text">{{ logoText }}</span>
|
||||||
|
</div>
|
||||||
|
<el-scrollbar class="menu-scrollbar">
|
||||||
|
<menu-component />
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-aside>
|
||||||
|
|
||||||
|
<!-- 主内容区 -->
|
||||||
|
<el-container class="main-container">
|
||||||
|
<el-header class="app-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<el-icon class="collapse-icon" @click="toggleSidebar">
|
||||||
|
<component :is="sidebarCollapsed ? 'Expand' : 'Fold'" />
|
||||||
|
</el-icon>
|
||||||
|
<breadcrumb v-if="showBreadcrumb" />
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<userbar />
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="app-main">
|
||||||
|
<tags v-if="showTags" />
|
||||||
|
<router-view v-slot="{ Component, route }">
|
||||||
|
<keep-alive :include="cachedViews">
|
||||||
|
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
||||||
|
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
||||||
|
</keep-alive>
|
||||||
|
</router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Menu布局:左侧菜单栏布局 -->
|
||||||
|
<template v-else-if="layoutMode === 'menu'">
|
||||||
|
<el-aside :width="sidebarCollapsed ? '60px' : '220px'" class="menu-sidebar">
|
||||||
|
<div v-if="!sidebarCollapsed" class="logo">
|
||||||
|
<img v-if="logo" :src="logo" alt="logo" />
|
||||||
|
<span class="logo-text">{{ logoText }}</span>
|
||||||
|
</div>
|
||||||
|
<el-scrollbar class="menu-scrollbar">
|
||||||
|
<menu-component />
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-aside>
|
||||||
|
<el-container class="main-container">
|
||||||
|
<el-header class="app-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<el-icon class="collapse-icon" @click="toggleSidebar">
|
||||||
|
<component :is="sidebarCollapsed ? 'Expand' : 'Fold'" />
|
||||||
|
</el-icon>
|
||||||
|
<breadcrumb v-if="showBreadcrumb" />
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<tags v-if="showTags" />
|
||||||
|
<userbar />
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="app-main">
|
||||||
|
<router-view v-slot="{ Component, route }">
|
||||||
|
<keep-alive :include="cachedViews">
|
||||||
|
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
||||||
|
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
||||||
|
</keep-alive>
|
||||||
|
</router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Top布局:顶部菜单栏布局 -->
|
||||||
|
<template v-else-if="layoutMode === 'top'">
|
||||||
|
<el-container class="main-container">
|
||||||
|
<el-header class="top-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<div class="logo">
|
||||||
|
<img v-if="logo" :src="logo" alt="logo" />
|
||||||
|
<span class="logo-text">{{ logoText }}</span>
|
||||||
|
</div>
|
||||||
|
<menu-component mode="horizontal" />
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<tags v-if="showTags" />
|
||||||
|
<userbar />
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="app-main">
|
||||||
|
<router-view v-slot="{ Component, route }">
|
||||||
|
<keep-alive :include="cachedViews">
|
||||||
|
<component v-if="!route.meta.link" :is="Component" :key="refreshKey" />
|
||||||
|
<iframe v-else :src="route.meta.link" class="iframe-container" />
|
||||||
|
</keep-alive>
|
||||||
|
</router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
</el-container>
|
||||||
|
|
||||||
|
<!-- 设置组件 -->
|
||||||
|
<setting />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -165,9 +165,7 @@ const layoutClass = computed(() => {
|
|||||||
|
|
||||||
// 缓存的视图
|
// 缓存的视图
|
||||||
const cachedViews = computed(() => {
|
const cachedViews = computed(() => {
|
||||||
return viewTags.value
|
return viewTags.value.filter((tag) => tag.meta?.keepAlive).map((tag) => tag.name)
|
||||||
.filter((tag) => tag.meta?.keepAlive)
|
|
||||||
.map((tag) => tag.name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 父级菜单(一级菜单)
|
// 父级菜单(一级菜单)
|
||||||
@@ -213,10 +211,7 @@ watch(
|
|||||||
if (layoutMode.value === 'default') {
|
if (layoutMode.value === 'default') {
|
||||||
const menus = userStore.getMenu() || []
|
const menus = userStore.getMenu() || []
|
||||||
for (const parentMenu of menus) {
|
for (const parentMenu of menus) {
|
||||||
if (
|
if (parentMenu.children && parentMenu.children.some((child) => route.path.startsWith(child.path))) {
|
||||||
parentMenu.children &&
|
|
||||||
parentMenu.children.some((child) => route.path.startsWith(child.path))
|
|
||||||
) {
|
|
||||||
layoutStore.setSelectedParentMenu(parentMenu)
|
layoutStore.setSelectedParentMenu(parentMenu)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'HomeIndex'
|
name: 'HomeIndex',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,58 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="auth-container">
|
<div class="auth-container">
|
||||||
<div class="tech-decoration">
|
<div class="tech-decoration">
|
||||||
<div class="tech-circle"></div>
|
<div class="tech-circle"></div>
|
||||||
<div class="tech-circle"></div>
|
<div class="tech-circle"></div>
|
||||||
<div class="tech-circle"></div>
|
<div class="tech-circle"></div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="auth-card">
|
|
||||||
<div class="auth-header">
|
|
||||||
<h1 class="auth-title">欢迎回来</h1>
|
|
||||||
<p class="auth-subtitle">登录您的账户继续探索科技世界</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="auth-form"
|
<div class="auth-card">
|
||||||
@submit.prevent="handleLogin">
|
<div class="auth-header">
|
||||||
<el-form-item prop="username">
|
<h1 class="auth-title">欢迎回来</h1>
|
||||||
<el-input v-model="loginForm.username" placeholder="请输入用户名/邮箱" size="large" clearable>
|
<p class="auth-subtitle">登录您的账户继续探索科技世界</p>
|
||||||
<template #prefix>
|
|
||||||
<el-icon>
|
|
||||||
<User />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item prop="password">
|
|
||||||
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码" size="large" clearable
|
|
||||||
show-password @keyup.enter="handleLogin">
|
|
||||||
<template #prefix>
|
|
||||||
<el-icon>
|
|
||||||
<Lock />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<div class="auth-links">
|
|
||||||
<el-checkbox v-model="loginForm.rememberMe" class="remember-me"> 记住我 </el-checkbox>
|
|
||||||
<router-link to="/forgot-password" class="forgot-password"> 忘记密码? </router-link>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-button type="primary" :loading="loading" size="large" style="width: 100%" @click="handleLogin">
|
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="auth-form" @submit.prevent="handleLogin">
|
||||||
{{ loading ? '登录中...' : '登录' }}
|
<el-form-item prop="username">
|
||||||
</el-button>
|
<el-input v-model="loginForm.username" placeholder="请输入用户名/邮箱" size="large" clearable>
|
||||||
</el-form>
|
<template #prefix>
|
||||||
|
<el-icon>
|
||||||
|
<User />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<div class="auth-footer">
|
<el-form-item prop="password">
|
||||||
<p class="auth-footer-text">
|
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码" size="large" clearable show-password @keyup.enter="handleLogin">
|
||||||
还没有账户?
|
<template #prefix>
|
||||||
<router-link to="/register" class="auth-link"> 立即注册 </router-link>
|
<el-icon>
|
||||||
</p>
|
<Lock />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="auth-links">
|
||||||
|
<el-checkbox v-model="loginForm.rememberMe" class="remember-me"> 记住我 </el-checkbox>
|
||||||
|
<router-link to="/forgot-password" class="forgot-password"> 忘记密码? </router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-button type="primary" :loading="loading" size="large" style="width: 100%" @click="handleLogin">
|
||||||
|
{{ loading ? '登录中...' : '登录' }}
|
||||||
|
</el-button>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<div class="auth-footer">
|
||||||
|
<p class="auth-footer-text">
|
||||||
|
还没有账户?
|
||||||
|
<router-link to="/register" class="auth-link"> 立即注册 </router-link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
Reference in New Issue
Block a user