🎉添加更多本地化组件,移除骨架屏组件

This commit is contained in:
chuzhixin 2020-10-04 12:12:57 +08:00
parent af0646d13f
commit e769919073
10 changed files with 594 additions and 26 deletions

View File

@ -61,8 +61,7 @@
"zx-comparison": "^1.0.3",
"zx-count": "^0.3.7",
"zx-icon": "^1.1.9",
"zx-keel": "^0.9.4",
"zx-layouts": "^0.6.14",
"zx-layouts": "^0.6.15",
"zx-magnifie": "^0.4.0",
"zx-markdown-editor": "^0.0.2",
"zx-player": "^1.0.1",

View File

@ -26,12 +26,10 @@ module.exports = {
devPort: "80",
//版本号
version: process.env.VUE_APP_VERSION,
//烦请保留package.json作者信息 保留版权可免费商用 如需去除并自定义为自己企业的版权请联系群主QQ 1204505056 需支付299元 恶意修改发生纠纷及出现任何问题 由修改人自行承担
//烦请保留package.json作者信息 即可免费商用
copyright: process.env.VUE_APP_AUTHOR,
//是否显示页面底部版权信息,建议您显示,当然您也可以选择不显示,不管您是付费用户还是未付费用户您都有选择显示或者不显示的权利
footerCopyright: process.env.NODE_ENV !== "development",
//是否显示右上角github图标
githubCorner: false,
//是否显示页面底部自定义版权信息
footerCopyright: true,
//是否显示顶部进度条
progressBar: true,
//缓存路由的最大数量
@ -60,8 +58,6 @@ module.exports = {
themeBar: true,
//是否显示多标签页
tabsBar: true,
//是否显示骨架屏
skeleton: false,
//配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: "application/json;charset=UTF-8",
//消息框消失时间

View File

@ -0,0 +1,103 @@
<template>
<section v-if="routerView" class="app-main-container">
<transition mode="out-in" name="fade-transform">
<keep-alive :include="cachedRoutes" :max="keepAliveMaxNum">
<router-view :key="key" class="app-main-height" />
</keep-alive>
</transition>
<footer v-show="footerCopyright" class="footer-copyright">
Copyright
<vab-icon :icon="['fas', 'copyright']"></vab-icon>
xxx-项目 {{ fullYear }}
</footer>
</section>
</template>
<script>
import { VabKeel, VabKeelHeading, VabKeelText } from "@/plugins/vabKeel";
import { mapActions, mapGetters } from "vuex";
import {
copyright,
footerCopyright,
keepAliveMaxNum,
title,
} from "@/config/settings";
export default {
name: "AppMain",
data() {
return {
show: false,
fullYear: new Date().getFullYear(),
copyright,
title,
keepAliveMaxNum,
routerView: true,
footerCopyright,
};
},
computed: {
...mapGetters({
visitedRoutes: "tabsBar/visitedRoutes",
device: "settings/device",
}),
cachedRoutes() {
const cachedRoutesArr = [];
this.visitedRoutes.forEach((item) => {
if (!item.meta.noKeepAlive) {
cachedRoutesArr.push(item.name);
}
});
return cachedRoutesArr;
},
key() {
return this.$route.path;
},
},
watch: {
$route: {
handler(route) {
if ("mobile" === this.device) this.foldSideBar();
},
immediate: true,
},
},
created() {
//
this.$baseEventBus.$on("reload-routerview", () => {
this.routerView = false;
this.$nextTick(() => {
this.routerView = true;
});
});
},
mounted() {},
methods: {
...mapActions({
foldSideBar: "settings/foldSideBar",
}),
},
};
</script>
<style lang="scss" scoped>
.app-main-container {
position: relative;
width: 100%;
overflow: hidden;
.vab-keel {
margin: $base-padding;
}
.app-main-height {
min-height: $base-app-main-height;
}
.footer-copyright {
min-height: 55px;
line-height: 55px;
color: rgba(0, 0, 0, 0.45);
text-align: center;
border-top: 1px dashed $base-border-color;
}
}
</style>

View File

@ -0,0 +1,63 @@
<template>
<el-breadcrumb class="breadcrumb-container" separator=">">
<el-breadcrumb-item v-for="item in list" :key="item.path">
{{ item.meta.title }}
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
name: "Breadcrumb",
data() {
return {
list: this.getBreadcrumb(),
};
},
watch: {
$route() {
this.list = this.getBreadcrumb();
},
},
methods: {
getBreadcrumb() {
return this.$route.matched.filter(
(item) => item.name && item.meta.title
);
},
},
};
</script>
<style lang="scss" scoped>
.breadcrumb-container {
height: $base-nav-bar-height;
font-size: $base-font-size-default;
line-height: $base-nav-bar-height;
::v-deep {
.el-breadcrumb__item {
.el-breadcrumb__inner {
a {
display: flex;
float: left;
font-weight: normal;
color: #515a6e;
i {
margin-right: 3px;
}
}
}
&:last-child {
.el-breadcrumb__inner {
a {
color: #999;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<div class="nav-bar-container">
<el-row :gutter="15">
<el-col :xs="4" :sm="12" :md="12" :lg="12" :xl="12">
<div class="left-panel">
<i
:class="collapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
:title="collapse ? '展开' : '收起'"
class="fold-unfold"
@click="handleCollapse"
></i>
<breadcrumb class="hidden-xs-only" />
</div>
</el-col>
<el-col :xs="20" :sm="12" :md="12" :lg="12" :xl="12">
<div class="right-panel">
<error-log></error-log>
<full-screen-bar @refresh="refreshRoute"></full-screen-bar>
<theme-bar class="hidden-xs-only"></theme-bar>
<vab-icon
title="重载所有路由"
:pulse="pulse"
:icon="['fas', 'redo']"
@click="refreshRoute"
></vab-icon>
<avatar></avatar>
<!-- <vab-icon
title="退出系统"
:icon="['fas', 'sign-out-alt']"
@click="logout"
/>-->
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import {
Avatar,
Breadcrumb,
ErrorLog,
FullScreenBar,
ThemeBar,
} from "@/layouts/components";
export default {
name: "NavBar",
components: {
Avatar,
Breadcrumb,
ErrorLog,
FullScreenBar,
ThemeBar,
},
data() {
return {
pulse: false,
};
},
computed: {
...mapGetters({
collapse: "settings/collapse",
visitedRoutes: "tabsBar/visitedRoutes",
device: "settings/device",
routes: "routes/routes",
}),
},
methods: {
...mapActions({
changeCollapse: "settings/changeCollapse",
}),
handleCollapse() {
this.changeCollapse();
},
async refreshRoute() {
this.$baseEventBus.$emit("reload-routerview");
this.pulse = true;
setTimeout(() => {
this.pulse = false;
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
.nav-bar-container {
position: relative;
height: $base-nav-bar-height;
padding-right: $base-padding;
padding-left: $base-padding;
overflow: hidden;
user-select: none;
background: $base-color-white;
box-shadow: $base-box-shadow;
.left-panel {
display: flex;
align-items: center;
justify-items: center;
height: $base-nav-bar-height;
.fold-unfold {
font-size: 20px;
color: $base-color-gray;
cursor: pointer;
}
::v-deep {
.breadcrumb-container {
margin-left: 10px;
}
}
}
.right-panel {
display: flex;
align-content: center;
align-items: center;
justify-content: flex-end;
height: $base-nav-bar-height;
::v-deep {
svg {
width: 1em;
height: 1em;
margin-right: 15px;
font-size: $base-font-size-big;
color: $base-color-gray;
cursor: pointer;
fill: $base-color-gray;
}
button {
svg {
margin-right: 0;
color: $base-color-white;
cursor: pointer;
fill: $base-color-white;
}
}
.el-badge {
margin-right: 15px;
}
}
}
}
</style>

View File

@ -0,0 +1,261 @@
<template>
<span v-if="themeBar">
<vab-icon
title="主题配置"
:icon="['fas', 'palette']"
@click="handleOpenThemeBar"
/>
<div class="theme-bar-setting">
<div @click="handleOpenThemeBar">
<vab-icon :icon="['fas', 'palette']" />
<p>主题配置</p>
</div>
<div @click="handleGetCode">
<vab-icon :icon="['fas', 'laptop-code']"></vab-icon>
<p>拷贝源码</p>
</div>
</div>
<el-drawer
title="主题配置"
:visible.sync="drawerVisible"
direction="rtl"
append-to-body
size="470px"
>
<el-scrollbar style="height: 94vh; overflow: hidden">
<div class="el-drawer__body">
<el-form ref="form" :model="theme">
<el-form-item label="主题">
<el-radio-group v-model="theme.name">
<el-radio-button label="default">默认</el-radio-button>
<el-radio-button label="ocean">海洋之心</el-radio-button>
<el-radio-button label="green">绿荫草场</el-radio-button>
<el-radio-button label="glory">荣耀典藏</el-radio-button>
<el-radio-button label="dark">暗黑之子</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="布局">
<el-radio-group v-model="theme.layout">
<el-radio-button label="vertical">纵向布局</el-radio-button>
<el-radio-button label="horizontal">横向布局</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="头部">
<el-radio-group v-model="theme.header">
<el-radio-button label="fixed">固定头部</el-radio-button>
<el-radio-button label="noFixed">不固定头部</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="多标签">
<el-radio-group v-model="theme.tabsBar">
<el-radio-button label="true">开启</el-radio-button>
<el-radio-button label="false">不开启</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button @click="handleSetDfaultTheme">恢复默认</el-button>
<el-button type="primary" @click="handleSaveTheme">
保存
</el-button>
</el-form-item>
</el-form>
</div>
</el-scrollbar>
</el-drawer>
</span>
</template>
<script>
import variables from "@/styles/variables.scss";
import { mapActions, mapGetters } from "vuex";
import { layout as defaultLayout } from "@/config/settings";
export default {
name: "ThemeBar",
data() {
return {
drawerVisible: false,
theme: {
name: "default",
layout: "",
header: "",
tabsBar: "",
},
};
},
computed: {
...mapGetters({
layout: "settings/layout",
header: "settings/header",
tabsBar: "settings/tabsBar",
themeBar: "settings/themeBar",
}),
},
created() {
this.$baseEventBus.$on("theme", () => {
this.handleOpenThemeBar();
});
const theme = localStorage.getItem("vue-admin-beautiful-theme");
if (null !== theme) {
this.theme = JSON.parse(theme);
this.handleSetTheme();
} else {
this.theme.layout = this.layout;
this.theme.header = this.header;
this.theme.tabsBar = this.tabsBar;
}
},
methods: {
...mapActions({
changeLayout: "settings/changeLayout",
changeHeader: "settings/changeHeader",
changeTabsBar: "settings/changeTabsBar",
}),
handleIsMobile() {
return document.body.getBoundingClientRect().width - 1 < 992;
},
handleOpenThemeBar() {
this.drawerVisible = true;
},
handleSetTheme() {
let { name, layout, header, tabsBar } = this.theme;
localStorage.setItem(
"vue-admin-beautiful-theme",
`{
"name":"${name}",
"layout":"${layout}",
"header":"${header}",
"tabsBar":"${tabsBar}"
}`
);
if (!this.handleIsMobile()) this.changeLayout(layout);
this.changeHeader(header);
this.changeTabsBar(tabsBar);
document.getElementsByTagName(
"body"
)[0].className = `vue-admin-beautiful-theme-${name}`;
this.drawerVisible = false;
},
handleSaveTheme() {
this.handleSetTheme();
},
handleSetDfaultTheme() {
let { name } = this.theme;
document
.getElementsByTagName("body")[0]
.classList.remove(`vue-admin-beautiful-theme-${name}`);
localStorage.removeItem("vue-admin-beautiful-theme");
this.$refs["form"].resetFields();
Object.assign(this.$data, this.$options.data());
this.changeHeader(defaultLayout);
this.theme.name = "default";
this.theme.layout = this.layout;
this.theme.header = this.header;
this.theme.tabsBar = this.tabsBar;
this.drawerVisible = false;
},
handleGetCode() {
const url =
"https://github.com/chuzhixin/vue-admin-beautiful/tree/master/src/views";
let path = this.$route.path + "/index.vue";
if (path === "/vab/menu1/menu1-1/menu1-1-1/index.vue") {
path = "/vab/nested/menu1/menu1-1/menu1-1-1/index.vue";
}
if (path === "/vab/icon/awesomeIcon/index.vue") {
path = "/vab/icon/index.vue";
}
if (path === "/vab/icon/remixIcon/index.vue") {
path = "/vab/icon/remixIcon.vue";
}
if (path === "/vab/icon/colorfulIcon/index.vue") {
path = "/vab/icon/colorfulIcon.vue";
}
if (path === "/vab/table/comprehensiveTable/index.vue") {
path = "/vab/table/index.vue";
}
if (path === "/vab/table/inlineEditTable/index.vue") {
path = "/vab/table/inlineEditTable.vue";
}
window.open(url + path);
},
},
};
</script>
<style lang="scss" scoped>
@mixin right-bar {
position: fixed;
right: 0;
z-index: $base-z-index;
width: 60px;
min-height: 60px;
text-align: center;
cursor: pointer;
background: $base-color-blue;
border-radius: $base-border-radius;
> div {
padding-top: 10px;
border-bottom: 0 !important;
&:hover {
opacity: 0.9;
}
& + div {
border-top: 1px solid $base-color-white;
}
p {
padding: 0;
margin: 0;
font-size: $base-font-size-small;
line-height: 30px;
color: $base-color-white;
}
}
}
.theme-bar-setting {
@include right-bar;
top: calc((100vh - 110px) / 2);
::v-deep {
svg:not(:root).svg-inline--fa {
display: block;
margin-right: auto;
margin-left: auto;
color: $base-color-white;
}
.svg-icon {
display: block;
margin-right: auto;
margin-left: auto;
font-size: 20px;
color: $base-color-white;
fill: $base-color-white;
}
}
}
.el-drawer__body {
padding: 20px;
}
</style>
<style lang="scss">
.el-drawer__wrapper {
outline: none !important;
* {
outline: none !important;
}
}
.vab-color-picker {
.el-color-dropdown__link-btn {
display: none;
}
}
</style>

View File

@ -15,12 +15,16 @@ export { default as Logo } from "./Logo";
export { default as Avatar } from "./Avatar";
//本地化广告组件如不需要全局搜索ad组件删掉即可
export { default as Ad } from "./Ad";
export { default as AppMain } from "zx-layouts/AppMain";
//本地化AppMain组件
export { default as AppMain } from "./AppMain";
export { default as TabsBar } from "zx-layouts/TabsBar";
export { default as SideBar } from "zx-layouts/SideBar";
export { default as Breadcrumb } from "zx-layouts/Breadcrumb";
//本地化Breadcrumb组件
export { default as Breadcrumb } from "./Breadcrumb";
export { default as FullScreenBar } from "zx-layouts/FullScreenBar";
export { default as ErrorLog } from "zx-layouts/ErrorLog";
export { default as ThemeBar } from "zx-layouts/ThemeBar";
//本地化ThemeBar组件
export { default as ThemeBar } from "./ThemeBar";
export { default as TopBar } from "zx-layouts/TopBar";
export { default as NavBar } from "zx-layouts/NavBar";
//本地化NavBar组件
export { default as NavBar } from "./NavBar";

View File

@ -1,8 +0,0 @@
import { Heading, Img, Keel, Text } from "zx-keel";
import "zx-keel/dist/zx-keel.css";
const VabKeel = Keel;
const VabKeelHeading = Heading;
const VabKeelImg = Img;
const VabKeelText = Text;
export { VabKeel, VabKeelHeading, VabKeelImg, VabKeelText };

View File

@ -398,12 +398,12 @@ const router = new VueRouter({
routes: constantRoutes,
});
//注释的地方是允许路由重复点击,如果你觉得框架路由跳转规范太过严格可选择放开
/* const originalPush = VueRouter.prototype.push;
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject);
return originalPush.call(this, location).catch((err) => err);
}; */
};
export function resetRouter() {
router.matcher = new VueRouter({

View File

@ -5,7 +5,7 @@
import defaultSettings from "@/config/settings";
const { tabsBar, logo, layout, header, themeBar, skeleton } = defaultSettings;
const { tabsBar, logo, layout, header, themeBar } = defaultSettings;
const theme =
JSON.parse(localStorage.getItem("vue-admin-beautiful-theme")) || "";
const state = {
@ -14,7 +14,6 @@ const state = {
collapse: false,
layout: theme.layout || layout,
header: theme.header || header,
skeleton,
device: "desktop",
themeBar,
};
@ -26,7 +25,6 @@ const getters = {
logo: (state) => state.logo,
tabsBar: (state) => state.tabsBar,
themeBar: (state) => state.themeBar,
skeleton: (state) => state.skeleton,
};
const mutations = {
changeLayout: (state, layout) => {