feat: 布局问题

master
LCJ-MinYa 12 months ago
parent 1af036dfad
commit 5d0d614637

@ -0,0 +1,25 @@
<template>
<section class="base-container">
<slot></slot>
</section>
</template>
<script setup>
// import { computed } from 'vue';
// import { useGlobal } from '@pureadmin/utils';
// const { $storage } = useGlobal();
// const hideTabs = computed(() => {
// return $storage?.configure.hideTabs;
// });
</script>
<style lang="scss">
.base-container {
overflow: auto;
display: flex;
flex: 1;
flex-direction: column;
height: calc(100vh - 81px);
}
</style>

@ -0,0 +1,5 @@
<template>
<section class="base-container">
<slot></slot>
</section>
</template>

@ -0,0 +1,5 @@
<template>
<section class="base-container">
<slot></slot>
</section>
</template>

@ -0,0 +1,15 @@
<template>
<main class="base-main">
<slot></slot>
</main>
</template>
<style lang="scss">
.base-main {
display: flex;
flex-direction: column;
flex: 1;
overflow: auto;
height: calc(100vh - 81px);
}
</style>

@ -0,0 +1,14 @@
import { App, Component } from 'vue';
import BaseContainer from '@/components/AutoImport/BaseContainer/index.vue';
import BaseMain from '@/components/AutoImport/BaseMain/index.vue';
import BaseHeader from '@/components/AutoImport/BaseHeader/index.vue';
import BaseFooter from '@/components/AutoImport/BaseFooter/index.vue';
/** 注入全局组件 */
export function useAutoImport(app: App) {
// 全局注册组件
app.component('BaseContainer', BaseContainer);
app.component('BaseMain', BaseMain);
app.component('BaseHeader', BaseHeader);
app.component('BaseFooter', BaseFooter);
}

@ -1,14 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import LayFrame from "../lay-frame/index.vue"; import LayFrame from '../lay-frame/index.vue';
import LayFooter from "../lay-footer/index.vue"; import LayFooter from '../lay-footer/index.vue';
import { useTags } from "@/layout/hooks/useTag"; import { useTags } from '@/layout/hooks/useTag';
import { useGlobal, isNumber } from "@pureadmin/utils"; import { useGlobal, isNumber } from '@pureadmin/utils';
import BackTopIcon from "@/assets/svg/back_top.svg?component"; import BackTopIcon from '@/assets/svg/back_top.svg?component';
import { h, computed, Transition, defineComponent } from "vue"; import { h, computed, Transition, defineComponent } from 'vue';
import { usePermissionStoreHook } from "@/store/modules/permission"; import { usePermissionStoreHook } from '@/store/modules/permission';
const props = defineProps({ const props = defineProps({
fixedHeader: Boolean fixedHeader: Boolean,
}); });
const { showModel } = useTags(); const { showModel } = useTags();
@ -19,7 +19,7 @@ const isKeepAlive = computed(() => {
}); });
const transitions = computed(() => { const transitions = computed(() => {
return route => { return (route) => {
return route.meta.transition; return route.meta.transition;
}; };
}); });
@ -37,38 +37,20 @@ const stretch = computed(() => {
}); });
const layout = computed(() => { const layout = computed(() => {
return $storage?.layout.layout === "vertical"; return $storage?.layout.layout === 'vertical';
}); });
const getMainWidth = computed(() => { const getMainWidth = computed(() => {
return isNumber(stretch.value) return isNumber(stretch.value) ? stretch.value + 'px' : stretch.value ? '1440px' : '100%';
? stretch.value + "px"
: stretch.value
? "1440px"
: "100%";
}); });
const getSectionStyle = computed(() => { const getSectionStyle = computed(() => {
return [ return [
hideTabs.value && layout ? "padding-top: 48px;" : "", hideTabs.value && layout ? 'padding-top: 48px;' : '',
!hideTabs.value && layout !hideTabs.value && layout ? (showModel.value == 'chrome' ? 'padding-top: 85px;' : 'padding-top: 81px;') : '',
? showModel.value == "chrome" hideTabs.value && !layout.value ? 'padding-top: 48px;' : '',
? "padding-top: 85px;" !hideTabs.value && !layout.value ? (showModel.value == 'chrome' ? 'padding-top: 85px;' : 'padding-top: 81px;') : '',
: "padding-top: 81px;" props.fixedHeader ? '' : `padding-top: 0;${hideTabs.value ? 'min-height: calc(100vh - 48px);' : 'min-height: calc(100vh - 86px);'}`,
: "",
hideTabs.value && !layout.value ? "padding-top: 48px;" : "",
!hideTabs.value && !layout.value
? showModel.value == "chrome"
? "padding-top: 85px;"
: "padding-top: 81px;"
: "",
props.fixedHeader
? ""
: `padding-top: 0;${
hideTabs.value
? "min-height: calc(100vh - 48px);"
: "min-height: calc(100vh - 86px);"
}`
]; ];
}); });
@ -76,32 +58,27 @@ const transitionMain = defineComponent({
props: { props: {
route: { route: {
type: undefined, type: undefined,
required: true required: true,
} },
}, },
render() { render() {
const transitionName = const transitionName = transitions.value(this.route)?.name || 'fade-transform';
transitions.value(this.route)?.name || "fade-transform";
const enterTransition = transitions.value(this.route)?.enterTransition; const enterTransition = transitions.value(this.route)?.enterTransition;
const leaveTransition = transitions.value(this.route)?.leaveTransition; const leaveTransition = transitions.value(this.route)?.leaveTransition;
return h( return h(
Transition, Transition,
{ {
name: enterTransition ? "pure-classes-transition" : transitionName, name: enterTransition ? 'pure-classes-transition' : transitionName,
enterActiveClass: enterTransition enterActiveClass: enterTransition ? `animate__animated ${enterTransition}` : undefined,
? `animate__animated ${enterTransition}` leaveActiveClass: leaveTransition ? `animate__animated ${leaveTransition}` : undefined,
: undefined, mode: 'out-in',
leaveActiveClass: leaveTransition appear: true,
? `animate__animated ${leaveTransition}`
: undefined,
mode: "out-in",
appear: true
}, },
{ {
default: () => [this.$slots.default()] default: () => [this.$slots.default()],
} }
); );
} },
}); });
</script> </script>
@ -112,7 +89,10 @@ const transitionMain = defineComponent({
> >
<router-view> <router-view>
<template #default="{ Component, route }"> <template #default="{ Component, route }">
<LayFrame :currComp="Component" :currRoute="route"> <LayFrame
:currComp="Component"
:currRoute="route"
>
<template #default="{ Comp, fullPath, frameInfo }"> <template #default="{ Comp, fullPath, frameInfo }">
<el-scrollbar <el-scrollbar
v-if="fixedHeader" v-if="fixedHeader"
@ -121,13 +101,13 @@ const transitionMain = defineComponent({
'flex-wrap': 'wrap', 'flex-wrap': 'wrap',
'max-width': getMainWidth, 'max-width': getMainWidth,
margin: '0 auto', margin: '0 auto',
transition: 'all 300ms cubic-bezier(0.4, 0, 0.2, 1)' transition: 'all 300ms cubic-bezier(0.4, 0, 0.2, 1)',
}" }"
:view-style="{ :view-style="{
display: 'flex', display: 'flex',
flex: 'auto', flex: 'auto',
overflow: 'hidden', overflow: 'hidden',
'flex-direction': 'column' 'flex-direction': 'column',
}" }"
> >
<el-backtop <el-backtop
@ -136,7 +116,7 @@ const transitionMain = defineComponent({
> >
<BackTopIcon /> <BackTopIcon />
</el-backtop> </el-backtop>
<div class="grow">
<transitionMain :route="route"> <transitionMain :route="route">
<keep-alive <keep-alive
v-if="isKeepAlive" v-if="isKeepAlive"
@ -157,10 +137,10 @@ const transitionMain = defineComponent({
class="main-content" class="main-content"
/> />
</transitionMain> </transitionMain>
</div>
<LayFooter v-if="!hideFooter" /> <LayFooter v-if="!hideFooter" />
</el-scrollbar> </el-scrollbar>
<div v-else class="grow"> <template v-else>
<transitionMain :route="route"> <transitionMain :route="route">
<keep-alive <keep-alive
v-if="isKeepAlive" v-if="isKeepAlive"
@ -181,7 +161,7 @@ const transitionMain = defineComponent({
class="main-content" class="main-content"
/> />
</transitionMain> </transitionMain>
</div> </template>
</template> </template>
</LayFrame> </LayFrame>
</template> </template>
@ -208,6 +188,6 @@ const transitionMain = defineComponent({
} }
.main-content { .main-content {
margin: 24px; margin: 0;
} }
</style> </style>

@ -1,64 +1,61 @@
import App from "./App.vue"; import App from './App.vue';
import router from "./router"; import router from './router';
import { setupStore } from "@/store"; import { setupStore } from '@/store';
import { getPlatformConfig } from "./config"; import { getPlatformConfig } from './config';
import { MotionPlugin } from "@vueuse/motion"; import { MotionPlugin } from '@vueuse/motion';
// import { useEcharts } from "@/plugins/echarts"; // import { useEcharts } from "@/plugins/echarts";
import { createApp, type Directive } from "vue"; import { createApp, type Directive } from 'vue';
import { useElementPlus } from "@/plugins/elementPlus"; import { useElementPlus } from '@/plugins/elementPlus';
import { injectResponsiveStorage } from "@/utils/responsive"; import { injectResponsiveStorage } from '@/utils/responsive';
import { useAutoImport } from '@/components/AutoImport';
import Table from "@pureadmin/table"; import Table from '@pureadmin/table';
// import PureDescriptions from "@pureadmin/descriptions"; // import PureDescriptions from "@pureadmin/descriptions";
// 引入重置样式 // 引入重置样式
import "./style/reset.scss"; import './style/reset.scss';
// 导入公共样式 // 导入公共样式
import "./style/index.scss"; import './style/index.scss';
// 一定要在main.ts中导入tailwind.css防止vite每次hmr都会请求src/style/index.scss整体css文件导致热更新慢的问题 // 一定要在main.ts中导入tailwind.css防止vite每次hmr都会请求src/style/index.scss整体css文件导致热更新慢的问题
import "./style/tailwind.css"; import './style/tailwind.css';
import "element-plus/dist/index.css"; import 'element-plus/dist/index.css';
// 导入字体图标 // 导入字体图标
import "./assets/iconfont/iconfont.js"; import './assets/iconfont/iconfont.js';
import "./assets/iconfont/iconfont.css"; import './assets/iconfont/iconfont.css';
const app = createApp(App); const app = createApp(App);
// 自定义指令 // 自定义指令
import * as directives from "@/directives"; import * as directives from '@/directives';
Object.keys(directives).forEach(key => { Object.keys(directives).forEach((key) => {
app.directive(key, (directives as { [key: string]: Directive })[key]); app.directive(key, (directives as { [key: string]: Directive })[key]);
}); });
// 全局注册@iconify/vue图标库 // 全局注册@iconify/vue图标库
import { import { IconifyIconOffline, IconifyIconOnline, FontIcon } from './components/ReIcon';
IconifyIconOffline, app.component('IconifyIconOffline', IconifyIconOffline);
IconifyIconOnline, app.component('IconifyIconOnline', IconifyIconOnline);
FontIcon app.component('FontIcon', FontIcon);
} from "./components/ReIcon";
app.component("IconifyIconOffline", IconifyIconOffline);
app.component("IconifyIconOnline", IconifyIconOnline);
app.component("FontIcon", FontIcon);
// 全局注册按钮级别权限组件 // 全局注册按钮级别权限组件
import { Auth } from "@/components/ReAuth"; import { Auth } from '@/components/ReAuth';
import { Perms } from "@/components/RePerms"; import { Perms } from '@/components/RePerms';
app.component("Auth", Auth); app.component('Auth', Auth);
app.component("Perms", Perms); app.component('Perms', Perms);
// 全局注册vue-tippy // 全局注册vue-tippy
import "tippy.js/dist/tippy.css"; import 'tippy.js/dist/tippy.css';
import "tippy.js/themes/light.css"; import 'tippy.js/themes/light.css';
import VueTippy from "vue-tippy"; import VueTippy from 'vue-tippy';
app.use(VueTippy); app.use(VueTippy);
getPlatformConfig(app).then(async config => { getPlatformConfig(app).then(async (config) => {
setupStore(app); setupStore(app);
app.use(router); app.use(router);
await router.isReady(); await router.isReady();
injectResponsiveStorage(app, config); injectResponsiveStorage(app, config);
app.use(MotionPlugin).use(useElementPlus).use(Table); app.use(MotionPlugin).use(useElementPlus).use(useAutoImport).use(Table);
// .use(PureDescriptions) // .use(PureDescriptions)
// .use(useEcharts); // .use(useEcharts);
app.mount("#app"); app.mount('#app');
}); });

@ -1,5 +1,5 @@
// 按需引入element-plus该方法稳定且明确。当然也支持https://element-plus.org/zh-CN/guide/quickstart.html#%E6%8C%89%E9%9C%80%E5%AF%BC%E5%85%A5 // 按需引入element-plus该方法稳定且明确。当然也支持https://element-plus.org/zh-CN/guide/quickstart.html#%E6%8C%89%E9%9C%80%E5%AF%BC%E5%85%A5
import type { App, Component } from "vue"; import type { App, Component } from 'vue';
import { import {
/** /**
* 便 element-plus 使 * 便 element-plus 使
@ -117,8 +117,8 @@ import {
ElPopoverDirective, // v-popover 指令 ElPopoverDirective, // v-popover 指令
ElMessage, // $message 全局属性对象globalProperties ElMessage, // $message 全局属性对象globalProperties
ElMessageBox, // $msgbox、$alert、$confirm、$prompt 全局属性对象globalProperties ElMessageBox, // $msgbox、$alert、$confirm、$prompt 全局属性对象globalProperties
ElNotification // $notify 全局属性对象globalProperties ElNotification, // $notify 全局属性对象globalProperties
} from "element-plus"; } from 'element-plus';
const components = [ const components = [
ElAffix, ElAffix,
@ -223,17 +223,14 @@ const components = [
ElWatermark, ElWatermark,
ElTour, ElTour,
ElTourStep, ElTourStep,
ElSegmented ElSegmented,
]; ];
const plugins = [ const plugins = [ElLoading, ElInfiniteScroll, ElPopoverDirective, ElMessage, ElMessageBox, ElNotification];
ElLoading,
ElInfiniteScroll, /** 设置部分组件的默认属性 */
ElPopoverDirective, ElCard.props.shadow = { type: String, default: 'never' };
ElMessage, ElButton.props.round = { type: Boolean, default: true };
ElMessageBox,
ElNotification
];
/** 按需引入`element-plus` */ /** 按需引入`element-plus` */
export function useElementPlus(app: App) { export function useElementPlus(app: App) {
@ -242,7 +239,7 @@ export function useElementPlus(app: App) {
app.component(component.name, component); app.component(component.name, component);
}); });
// 全局注册插件 // 全局注册插件
plugins.forEach(plugin => { plugins.forEach((plugin) => {
app.use(plugin); app.use(plugin);
}); });
} }

@ -19,5 +19,13 @@ export default {
title: '基础模版', title: '基础模版',
}, },
}, },
{
path: '/template/layout',
name: 'TemplateLayout',
component: () => import('@/views/template/layout/index.vue'),
meta: {
title: '布局模版',
},
},
], ],
} satisfies RouteConfigsTable; } satisfies RouteConfigsTable;

@ -16,7 +16,7 @@
} }
/* 重置 el-button 中 icon 的 margin */ /* 重置 el-button 中 icon 的 margin */
.reset-margin [class*="el-icon"] + span { .reset-margin [class*='el-icon'] + span {
margin-left: 2px !important; margin-left: 2px !important;
} }
@ -186,3 +186,8 @@
background: rgb(199 201 203); /* 滑块hover颜色 */ background: rgb(199 201 203); /* 滑块hover颜色 */
} }
} }
/** 默认el-card没有边框 */
.el-card {
border: none !important;
}

@ -0,0 +1,225 @@
<template>
<Base-Container>
<pure-table
class="base-main"
:data="tableData"
:columns="columns"
size="large"
/>
</Base-Container>
</template>
<script setup lang="jsx">
import { ref } from 'vue';
defineOptions({
name: 'TemplateLayout',
});
const tableData = ref([
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
{
name: 'John',
age: 25,
},
{
name: 'Jane',
age: 30,
},
{
name: 'Bob',
age: 28,
},
]);
const columns = [
{
label: '姓名',
prop: 'name',
},
{
label: '年龄',
prop: 'age',
},
];
</script>
<style lang="scss" scoped></style>
Loading…
Cancel
Save