Conflicts:
	src/layout/Header/components/globalComSize.vue
	src/router/modules/charts.ts
	src/router/modules/error.ts
	src/router/modules/other.ts
	src/router/modules/table.ts
This commit is contained in:
zouzhibing 2022-09-28 22:09:03 +08:00
commit c0f5728373
27 changed files with 182 additions and 99 deletions

View File

@ -2,9 +2,9 @@
<html lang="en" class="dark"> <html lang="en" class="dark">
<head> <head>
<meta charset="UTF-8" /> <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" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title> <title>Vue admin perfect</title>
</head> </head>
<body> <body>
<div id="app"> <div id="app">

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <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> <title><%= htmlWebpackPlugin.options.title %></title>
</head> </head>
<body> <body>

View File

@ -1,8 +1,8 @@
<template> <template>
<el-breadcrumb class="app-breadcrumb" separator="/"> <el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb" mode="out-in"> <transition-group name="breadcrumb" mode="out-in">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path"> <el-breadcrumb-item v-for="(item, index) in matched" :key="item.name">
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span> <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> <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item> </el-breadcrumb-item>
</transition-group> </transition-group>
@ -11,45 +11,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import pathToRegexp from 'path-to-regexp' import pathToRegexp from 'path-to-regexp'
import { onMounted, ref, watch } from 'vue' import { onMounted, ref, watch,computed } from 'vue'
import { useRoute } from 'vue-router' import { useRoute ,useRouter} from 'vue-router'
const levelList = ref([]) const levelList = ref([])
const route = useRoute() const route = useRoute()
const router = useRouter()
// const handleLink = (item)=>{
const getBreadcrumb = () => { router.push({
let matched = route.matched.filter((item) => item.meta && item.meta.title) path:item.path
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 matched = computed(() => route.matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false));
</script> </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-form-item label="姓名">
<el-input v-model="ruleForm.name" disabled></el-input> <el-input v-model="ruleForm.name" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="手机号码"> <el-form-item label="旧的密码" prop="password">
<el-input v-model="ruleForm.mobile" disabled></el-input> <el-input v-model="ruleForm.password" type="password"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="修改密码" prop="password"> <el-form-item label="新的密码" prop="configPassword">
<el-input v-model="ruleForm.password"></el-input> <el-input v-model="ruleForm.configPassword" type="password"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -29,9 +29,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, defineExpose, reactive } from 'vue' import { ref, defineExpose, reactive } from 'vue'
import { ElMessageBox } from 'element-plus'
import type { ElForm } from 'element-plus' import type { ElForm } from 'element-plus'
const dialogVisible = ref(false) const dialogVisible = ref(false)
import {useUserStore} from "@/store/modules/user"
const UserStore = useUserStore()
const show = () => { const show = () => {
dialogVisible.value = true dialogVisible.value = true
} }
@ -43,15 +44,15 @@
const formSize = ref('') const formSize = ref('')
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({ const ruleForm = reactive({
name: '', name: UserStore.userInfo.username,
mobile: '', password: UserStore.userInfo.password,
password: '', configPassword: '',
}) })
const rules = reactive({ const rules = reactive({
password: [ configPassword: [
{ {
required: true, required: true,
message: '请输入密码', message: '请输入新的密码',
trigger: 'blur', trigger: 'blur',
}, },
], ],

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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
.m-layout-header{ .m-layout-header{
color: var(--el-text-color-primary) !important; color: var(--el-text-color-primary) !important;
@ -143,5 +150,9 @@ html.dark {
color: white!important; 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 './sidebar.scss';
@import './transition.scss'; @import './transition.scss';
@import "./common.scss"; @import "./common.scss";
@import "./element.scss";

View File

@ -63,6 +63,19 @@
// position: absolute; // position: absolute;
// z-index: -1; // 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, .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]); 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]); 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> <template>
<u-container-layout> <u-container-layout>
<div style="margin-bottom: 15px; display: flex; align-items: center"> <div class="header">
<el-input <el-input
v-model="input" v-model="input"
placeholder="请输入文件名" placeholder="请输入文件名"
@ -22,11 +22,13 @@
<el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel <el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel
</el-button> </el-button>
</div> </div>
<el-table :data="list" style="width: 100%" border> <div class="footer">
<template v-for="(item, index) in column" :key="index"> <el-table :data="list" border class="table">
<el-table-column :prop="item.name" :label="item.label" :width="item.width" /> <template v-for="(item, index) in column" :key="index">
</template> <el-table-column :prop="item.name" :label="item.label" :width="item.width" />
</el-table> </template>
</el-table>
</div>
</u-container-layout> </u-container-layout>
</template> </template>
@ -100,4 +102,22 @@
} }
</script> </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> <template>
<u-container-layout> <u-container-layout>
<div style="margin-bottom: 15px; display: flex; align-items: center"> <div class=".header">
<el-input <el-input
v-model="input" v-model="input"
placeholder="请输入文件名" placeholder="请输入文件名"
@ -10,11 +10,13 @@
<el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel <el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel
</el-button> </el-button>
</div> </div>
<el-table :data="list" style="width: 100%" border> <div class="footer">
<template v-for="(item, index) in column" :key="index"> <el-table :data="list" class="table" border>
<el-table-column :prop="item.name" :label="item.label" :width="item.width" /> <template v-for="(item, index) in column" :key="index">
</template> <el-table-column :prop="item.name" :label="item.label" :width="item.width" />
</el-table> </template>
</el-table>
</div>
</u-container-layout> </u-container-layout>
</template> </template>
@ -88,4 +90,22 @@
} }
</script> </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> <script lang="ts" setup>
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { ElNotification } from "element-plus";
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import {useUserStore} from "@/store/modules/user" import {useUserStore} from "@/store/modules/user"
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import {getTimeState} from '@/utils/index'
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const router = useRouter() const router = useRouter()
const UserStore = useUserStore() const UserStore = useUserStore()
@ -108,14 +111,18 @@
const submitForm = (formEl: FormInstance | undefined) => { const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate(async (valid) => { formEl.validate(async (valid) => {
console.log('valid==', valid)
if (valid) { if (valid) {
// //
await UserStore.login( ruleForm) await UserStore.login( ruleForm)
ElMessage.success('登录成功')
router.push({ router.push({
path: '/', path: '/',
}) })
ElNotification({
title: getTimeState(),
message: "欢迎登录 Vue Admin Perfect",
type: "success",
duration: 3000
});
} else { } else {
console.log('error submit!') console.log('error submit!')
return false return false

View File

@ -1,6 +1,6 @@
<template> <template>
<u-container-layout style="min-height: 300px"> <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-right-click-menu :left="clientX" :top="clientY" @ok="operatingRightAction" :data="data" />
</u-container-layout> </u-container-layout>
</template> </template>
@ -8,6 +8,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'
import URightClickMenu from '@/components/u-rightClickMenu/index.vue' import URightClickMenu from '@/components/u-rightClickMenu/index.vue'
const clientX = ref(0) const clientX = ref(0)
const clientY = ref(0) const clientY = ref(0)
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'