perf:优化缓存,布局,样式

This commit is contained in:
zouzhibing 2022-09-28 22:06:33 +08:00
parent a985df0af7
commit 15d7e0c555
27 changed files with 179 additions and 94 deletions

View File

@ -2,9 +2,9 @@
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
<title>Vue admin perfect</title>
</head>
<body>
<div id="app">

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="icon" href="/favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>

View File

@ -1,8 +1,8 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb" mode="out-in">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
<el-breadcrumb-item v-for="(item, index) in matched" :key="item.name">
<span v-if="item.redirect === 'noRedirect' || index == matched.length - 1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
@ -11,45 +11,20 @@
<script lang="ts" setup>
import pathToRegexp from 'path-to-regexp'
import { onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { onMounted, ref, watch,computed } from 'vue'
import { useRoute ,useRouter} from 'vue-router'
const levelList = ref([])
const route = useRoute()
const router = useRouter()
//
const getBreadcrumb = () => {
let matched = route.matched.filter((item) => item.meta && item.meta.title)
const first = matched[0]
levelList.value = matched.filter(
(item) => item.meta && item.meta.title && item.meta.breadcrumb !== false,
)
}
const handleLink = ()=>{
}
onMounted(() => {
getBreadcrumb()
watch(route, () => {
if (route.path.startsWith('/redirect/')) {
return
}
getBreadcrumb()
})
const handleLink = (item)=>{
router.push({
path:item.path
})
}
const matched = computed(() => route.matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false));
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
margin-left: 10px;
display: inline-block;
font-size: 14px;
margin-bottom: 4px;
.no-redirect {
color:#303133;
cursor: text;
}
}
</style>

View File

@ -11,11 +11,11 @@
<el-form-item label="姓名">
<el-input v-model="ruleForm.name" disabled></el-input>
</el-form-item>
<el-form-item label="手机号码">
<el-input v-model="ruleForm.mobile" disabled></el-input>
<el-form-item label="旧的密码" prop="password">
<el-input v-model="ruleForm.password" type="password"></el-input>
</el-form-item>
<el-form-item label="修改密码" prop="password">
<el-input v-model="ruleForm.password"></el-input>
<el-form-item label="新的密码" prop="configPassword">
<el-input v-model="ruleForm.configPassword" type="password"></el-input>
</el-form-item>
</el-form>
<template #footer>
@ -29,9 +29,10 @@
<script lang="ts" setup>
import { ref, defineExpose, reactive } from 'vue'
import { ElMessageBox } from 'element-plus'
import type { ElForm } from 'element-plus'
const dialogVisible = ref(false)
import {useUserStore} from "@/store/modules/user"
const UserStore = useUserStore()
const show = () => {
dialogVisible.value = true
}
@ -43,15 +44,15 @@
const formSize = ref('')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({
name: '',
mobile: '',
password: '',
name: UserStore.userInfo.username,
password: UserStore.userInfo.password,
configPassword: '',
})
const rules = reactive({
password: [
configPassword: [
{
required: true,
message: '请输入密码',
message: '请输入新的密码',
trigger: 'blur',
},
],

View File

@ -33,5 +33,9 @@ const setAssemblySize = (item: string) => {
</script>
<style scoped lang="scss">
.transverseMenu {
.size-icon {
color: white;
}
}
</style>

View File

@ -2,12 +2,10 @@
<div
class="m-layout-header"
:class="[
SettingStore.themeConfig.fixedHeader&&'zb-fixed-header',
isCollapse?'fixed-header-collapse':'fixed-header-no-collapse'
SettingStore.themeConfig.fixedHeader?'zb-fixed-header':'zb-no-fixed-header',
mode === 'horizontal'?'':isCollapse?'fixed-header-collapse':'fixed-header-no-collapse'
]"
>
<!-- :style="{ left: `${mode === 'horizontal' ? 0 : isCollapse ? '60' : '210'}px` }"-->
<div
class="header"
:class="{
@ -16,7 +14,7 @@
>
<u-menu v-if="mode === 'horizontal'" />
<div class="left" v-if="mode === 'vertical'">
<div>
<div class="hamburger-container">
<el-icon class="icon" v-if="isCollapse" @click="handleCollapse"><expand /></el-icon>
<el-icon class="icon" v-else @click="handleCollapse"><fold /></el-icon>
</div>
@ -44,8 +42,10 @@
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="1">退出登录</el-dropdown-item>
<el-dropdown-item :command="2">修改密码</el-dropdown-item>
<el-dropdown-item :command="2" >
<el-icon><Edit /></el-icon></el-dropdown-item>
<el-dropdown-item :command="1" divided>
<el-icon><SwitchButton /></el-icon>退</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@ -98,10 +98,14 @@
})
.then(async () => {
try {
await UserStore.logout()
router.push({ path: '/login' })
await UserStore.logout()
PermissionStore.clearRoutes()
TagsViewStore.clearVisitedView()
ElMessage({
type: "success",
message: "退出登录成功!"
});
} catch (e) {}
})
.catch(() => {})
@ -139,12 +143,13 @@
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
padding: 0 10px;
padding: 0 10px 0 0;
box-sizing: border-box;
justify-content: space-between;
.left {
display: flex;
align-items: center;
height: 100%;
}
.right {
display: flex;
@ -160,7 +165,18 @@
right: 0;
z-index: 9;
}
.zb-no-fixed-header{
width: 100%!important;;
}
.hamburger-container{
padding: 0px 15px;
height: 100%;
display: flex;
align-items: center;
&:hover {
background: rgba(0, 0, 0, .025)
}
}
.m-layout-header {
width: 100%;
background: white;

View File

@ -2,7 +2,7 @@
<el-menu
:default-active="activeMenu"
background-color="#304156"
text-color="#fff"
text-color="#bfcbd9"
:mode="mode"
:unique-opened="SettingStore.themeConfig.uniqueOpened"
:collapse-transition="false"
@ -23,7 +23,7 @@
import { useRoute } from 'vue-router'
import {usePermissionStore} from "@/store/modules/permission"
import {useSettingStore} from "@/store/modules/setting"
import { ref, computed } from 'vue'
import { computed } from 'vue'
// setupstore
const route = useRoute()
@ -33,8 +33,6 @@
//
const permission_routes = computed(() => PermissionStore.permission_routes)
const activeMenu = computed(() => {
const { meta, path } = route
// if set path, the sidebar will highlight the path you set

View File

@ -11,7 +11,7 @@
import UMenu from './components/Menu.vue'
import logo from './components/Logo.vue'
import {useSettingStore} from "@/store/modules/setting"
import { ref, computed } from 'vue'
import { computed } from 'vue'
const SettingStore = useSettingStore()
//

View File

@ -5,7 +5,7 @@ import Layout from "@/layout/index.vue";
const chartsRouter = {
path: '/charts',
component: Layout,
redirect: 'noRedirect',
redirect: '/charts/migration',
name: 'Charts',
meta: {
title: '可视化图表',

View File

@ -5,7 +5,7 @@ import Layout from "@/layout/index.vue";
const chartsRouter = {
path: '/chat',
component: Layout,
redirect: 'noRedirect',
redirect: '/charts/index',
name: 'chat',
meta: {
title: '聊天框',

View File

@ -3,7 +3,7 @@ import Layout from '@/layout/index.vue'
const clipboardTable = {
path: '/clipboard',
component: Layout,
redirect: 'noRedirect',
redirect: '/clipboard/index',
name: 'clipboard',
meta: {
title: 'clipboard',

View File

@ -7,7 +7,7 @@ import Layout from "@/layout/index.vue";
const errorRouter = {
path: '/error',
component: Layout,
redirect: 'noRedirect',
redirect: '/error/404',
name: 'error',
meta: {
title: '错误页面',

View File

@ -7,7 +7,7 @@ import Layout from "@/layout/index.vue";
const excelRouter = {
path: '/excel',
component: Layout,
redirect: 'noRedirect',
redirect: '/excel/export-excel',
name: 'excel',
meta: {
title: 'Excel',

View File

@ -6,7 +6,7 @@ import Layout from "@/layout/index.vue";
const formRouter = {
path: '/form',
component: Layout,
redirect: 'noRedirect',
redirect: '/form/validateForm',
name: 'form',
alwaysShow:true,
meta: {

View File

@ -7,7 +7,7 @@ import Layout from "@/layout/index.vue";
const nestedRouter = {
path: '/nested',
component: Layout,
redirect: 'noRedirect',
redirect: '/form/menu1',
name: 'nested',
meta: {
title: '路由嵌套',

View File

@ -5,7 +5,7 @@ import Layout from '@/layout/index.vue'
const othersRouter = {
path: '/other',
component: Layout,
redirect: 'noRedirect',
redirect: '/other/editor',
name: 'other',
meta: {
title: '扩展组件',

View File

@ -5,7 +5,7 @@ import Layout from '@/layout/index.vue'
const systemRouter = {
path: '/system',
component: Layout,
redirect: 'noRedirect',
redirect: '/system/page',
name: 'system',
meta: {
title: '系统管理',

View File

@ -6,7 +6,7 @@ import Layout from "@/layout/index.vue";
const tableRouter = {
path: '/table',
component: Layout,
redirect: 'noRedirect',
redirect: '/table/comprehensive',
name: 'table',
meta: {
title: '超级表格',

View File

@ -104,7 +104,14 @@ html.dark {
}
}
}
.zb-pro-table .header{
background: none!important;
border: var(--zb-border-light);
}
.zb-pro-table .footer{
background: none!important;
border: var(--zb-border-light);
}
// m-layout-header
.m-layout-header{
color: var(--el-text-color-primary) !important;
@ -143,5 +150,9 @@ html.dark {
color: white!important;
}
.el-table__header th {
font-weight: bold;
color: white;
}
}

5
src/styles/element.scss Normal file
View File

@ -0,0 +1,5 @@
.el-table__header th {
font-weight: bold;
color: #252525;
background: #fafafa;
}

View File

@ -2,5 +2,6 @@
@import './sidebar.scss';
@import './transition.scss';
@import "./common.scss";
@import "./element.scss";

View File

@ -63,6 +63,19 @@
// position: absolute;
// z-index: -1;
//}
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all 0.2s ease;
}
.breadcrumb-enter-from,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(10px);
}
.breadcrumb-leave-active {
position: absolute;
z-index: -1;
}
.fade-transform-leave-active,

View File

@ -479,3 +479,16 @@ export function getLightColor(color: string, level: number) {
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
return rgbToHex(rgb[0], rgb[1], rgb[2]);
}
export function getTimeState() {
// 获取当前时间
let timeNow = new Date();
// 获取当前小时
let hours = timeNow.getHours();
// 判断当前时间段
if (hours >= 6 && hours <= 10) return `早上好 ⛅`;
if (hours >= 10 && hours <= 14) return `中午好 🌞`;
if (hours >= 14 && hours <= 18) return `下午好 🌞`;
if (hours >= 18 && hours <= 24) return `晚上好 🌛`;
if (hours >= 0 && hours <= 6) return `凌晨好 🌛`;
}

View File

@ -1,6 +1,6 @@
<template>
<u-container-layout>
<div style="margin-bottom: 15px; display: flex; align-items: center">
<div class="header">
<el-input
v-model="input"
placeholder="请输入文件名"
@ -22,11 +22,13 @@
<el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel
</el-button>
</div>
<el-table :data="list" style="width: 100%" border>
<div class="footer">
<el-table :data="list" border class="table">
<template v-for="(item, index) in column" :key="index">
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
</template>
</el-table>
</div>
</u-container-layout>
</template>
@ -100,4 +102,22 @@
}
</script>
<style></style>
<style lang="scss" scoped>
.header{
display: flex;
align-items: center;
margin-bottom: 15px;
flex-shrink: 0;
}
.footer{
flex: 1;
position: relative;
.table{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<u-container-layout>
<div style="margin-bottom: 15px; display: flex; align-items: center">
<div class=".header">
<el-input
v-model="input"
placeholder="请输入文件名"
@ -10,11 +10,13 @@
<el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel
</el-button>
</div>
<el-table :data="list" style="width: 100%" border>
<div class="footer">
<el-table :data="list" class="table" border>
<template v-for="(item, index) in column" :key="index">
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
</template>
</el-table>
</div>
</u-container-layout>
</template>
@ -88,4 +90,22 @@
}
</script>
<style></style>
<style lang="scss" scoped>
.header{
display: flex;
align-items: center;
margin-bottom: 15px;
flex-shrink: 0;
}
.footer{
flex: 1;
position: relative;
.table{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%
}
}
</style>

View File

@ -63,9 +63,12 @@
<script lang="ts" setup>
import { ref, reactive } from 'vue'
import type { FormInstance } from 'element-plus'
import { ElNotification } from "element-plus";
import { useRouter } from 'vue-router'
import {useUserStore} from "@/store/modules/user"
import { ElMessage } from 'element-plus'
import {getTimeState} from '@/utils/index'
const ruleFormRef = ref<FormInstance>()
const router = useRouter()
const UserStore = useUserStore()
@ -108,14 +111,18 @@
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate(async (valid) => {
console.log('valid==', valid)
if (valid) {
//
await UserStore.login( ruleForm)
ElMessage.success('登录成功')
router.push({
path: '/',
})
ElNotification({
title: getTimeState(),
message: "欢迎登录 Vue Admin Perfect",
type: "success",
duration: 3000
});
} else {
console.log('error submit!')
return false

View File

@ -1,6 +1,6 @@
<template>
<u-container-layout style="min-height: 300px">
<el-button @contextmenu.prevent="rightClick">右键菜单</el-button>
<el-button @contextmenu.prevent="rightClick" style="width: 200px">右键菜单</el-button>
<u-right-click-menu :left="clientX" :top="clientY" @ok="operatingRightAction" :data="data" />
</u-container-layout>
</template>
@ -8,6 +8,7 @@
<script lang="ts" setup>
import { ref } from 'vue'
import URightClickMenu from '@/components/u-rightClickMenu/index.vue'
const clientX = ref(0)
const clientY = ref(0)
import { useRouter } from 'vue-router'