feat(component): Add Footer component

This commit is contained in:
kailong321200875 2022-01-22 10:54:28 +08:00
parent e496096539
commit f81e996a42
18 changed files with 940 additions and 837 deletions

View File

@ -25,11 +25,11 @@
"postinstall": "husky install" "postinstall": "husky install"
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^2.1.0", "@iconify/iconify": "^2.1.1",
"@vueuse/core": "^7.5.3", "@vueuse/core": "^7.5.4",
"@zxcvbn-ts/core": "^1.2.0", "@zxcvbn-ts/core": "^1.2.0",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"axios": "^0.24.0", "axios": "^0.25.0",
"element-plus": "1.3.0-beta.5", "element-plus": "1.3.0-beta.5",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
@ -43,29 +43,29 @@
"web-storage-cache": "^1.1.1" "web-storage-cache": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^16.0.2", "@commitlint/cli": "^16.1.0",
"@commitlint/config-conventional": "^16.0.0", "@commitlint/config-conventional": "^16.0.0",
"@iconify/json": "^1.1.454", "@iconify/json": "^1.1.459",
"@intlify/vite-plugin-vue-i18n": "^3.2.1", "@intlify/vite-plugin-vue-i18n": "^3.2.1",
"@purge-icons/generated": "^0.7.0", "@purge-icons/generated": "^0.7.0",
"@types/lodash-es": "^4.17.5", "@types/lodash-es": "^4.17.5",
"@types/node": "^17.0.8", "@types/node": "^17.0.10",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.9.1", "@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.9.1", "@typescript-eslint/parser": "^5.10.0",
"@vitejs/plugin-vue": "^2.0.1", "@vitejs/plugin-vue": "^2.1.0",
"@vitejs/plugin-vue-jsx": "^1.3.3", "@vitejs/plugin-vue-jsx": "^1.3.3",
"autoprefixer": "^10.4.2", "autoprefixer": "^10.4.2",
"commitizen": "^4.2.4", "commitizen": "^4.2.4",
"eslint": "^8.6.0", "eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-define-config": "^1.2.2", "eslint-define-config": "^1.2.3",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.2.0", "eslint-plugin-vue": "^8.3.0",
"husky": "^7.0.4", "husky": "^7.0.4",
"less": "^4.1.2", "less": "^4.1.2",
"lint-staged": "^12.1.7", "lint-staged": "^12.2.2",
"postcss": "^8.4.5", "postcss": "^8.4.5",
"postcss-html": "^1.3.0", "postcss-html": "^1.3.0",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
@ -77,17 +77,17 @@
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^24.0.0", "stylelint-config-standard": "^24.0.0",
"stylelint-order": "^5.0.0", "stylelint-order": "^5.0.0",
"typescript": "4.5.4", "typescript": "4.5.5",
"vite": "2.7.10", "vite": "2.7.13",
"vite-plugin-eslint": "^1.3.0", "vite-plugin-eslint": "^1.3.0",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",
"vite-plugin-purge-icons": "^0.7.0", "vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-style-import": "^1.4.1", "vite-plugin-style-import": "^1.4.1",
"vite-plugin-svg-icons": "^1.1.0", "vite-plugin-svg-icons": "^1.1.0",
"vite-plugin-vue-setup-extend": "^0.3.0", "vite-plugin-vue-setup-extend": "^0.3.0",
"vite-plugin-windicss": "^1.6.2", "vite-plugin-windicss": "^1.6.3",
"vue-tsc": "^0.30.2", "vue-tsc": "^0.30.6",
"windicss": "^3.4.2", "windicss": "^3.4.3",
"windicss-analysis": "^0.3.5" "windicss-analysis": "^0.3.5"
}, },
"engines": { "engines": {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
import Footer from './src/Footer.vue'
export { Footer }

View File

@ -0,0 +1,12 @@
<script setup lang="ts">
import { useAppStore } from '@/store/modules/app'
import { computed } from 'vue'
const appStore = useAppStore()
const title = computed(() => appStore.getTitle)
</script>
<template>
<div class="text-center text-[var(--el-text-color-placeholder)]">Copyright ©2021 {{ title }}</div>
</template>

View File

@ -220,8 +220,8 @@ export default defineComponent({
} }
.v-menu__title { .v-menu__title {
max-height: calc(~'var( - -top-tool-height)') !important; max-height: calc(~'var( - -top-tool-height) - 2px') !important;
line-height: calc(~'var( - -top-tool-height)'); line-height: calc(~'var( - -top-tool-height) - 2px');
} }
} }
} }

View File

@ -32,7 +32,7 @@ const setSystemTheme = (color: string) => {
} }
// //
const headerTheme = ref(appStore.getTheme.topHeaderBgColor) const headerTheme = ref(appStore.getTheme.topHeaderBgColor || '')
const setHeaderTheme = (color: string) => { const setHeaderTheme = (color: string) => {
const isDarkColor = colorIsDark(color) const isDarkColor = colorIsDark(color)
@ -55,7 +55,7 @@ const setHeaderTheme = (color: string) => {
} }
// //
const menuTheme = ref(appStore.getTheme.leftMenuBgColor) const menuTheme = ref(appStore.getTheme.leftMenuBgColor || '')
const setMenuTheme = (color: string) => { const setMenuTheme = (color: string) => {
const primaryColor = useCssVar('--el-color-primary', document.documentElement) const primaryColor = useCssVar('--el-color-primary', document.documentElement)
@ -91,13 +91,11 @@ const setMenuTheme = (color: string) => {
// layout // layout
watch( watch(
() => layout.value, () => layout.value,
(n, o) => { (n) => {
if (o === 'top') { if (n === 'top') {
menuTheme.value = '#fff' headerTheme.value = '#fff'
setMenuTheme('#fff') setHeaderTheme('#fff')
} } else {
if ((o === 'classic' || o === 'topLeft') && n === 'top') {
menuTheme.value = headerTheme.value
setMenuTheme(unref(menuTheme)) setMenuTheme(unref(menuTheme))
} }
} }
@ -125,6 +123,8 @@ tagsView: ${appStore.getTagsView},
logo: ${appStore.getLogo}, logo: ${appStore.getLogo},
// header // header
fixedHeader: ${appStore.getFixedHeader}, fixedHeader: ${appStore.getFixedHeader},
//
footer: ${appStore.getFooter},
// //
greyMode: ${appStore.getGreyMode}, greyMode: ${appStore.getGreyMode},
// layout // layout

View File

@ -71,6 +71,13 @@ const fixedHeaderChange = (show: boolean) => {
appStore.setFixedHeader(show) appStore.setFixedHeader(show)
} }
//
const footer = ref(appStore.getFooter)
const footerChange = (show: boolean) => {
appStore.setFooter(show)
}
// //
const greyMode = ref(appStore.getGreyMode) const greyMode = ref(appStore.getGreyMode)
@ -137,6 +144,11 @@ watch(
<ElSwitch v-model="fixedHeader" @change="fixedHeaderChange" /> <ElSwitch v-model="fixedHeader" @change="fixedHeaderChange" />
</div> </div>
<div class="flex justify-between items-center">
<span class="text-14px">{{ t('setting.footer') }}</span>
<ElSwitch v-model="footer" @change="footerChange" />
</div>
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="text-14px">{{ t('setting.greyMode') }}</span> <span class="text-14px">{{ t('setting.greyMode') }}</span>
<ElSwitch v-model="greyMode" @change="greyModeChange" /> <ElSwitch v-model="greyMode" @change="greyModeChange" />

View File

@ -4,6 +4,22 @@ const { wsCache } = useCache()
export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu' export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu'
export type ThemeTypes = {
elColorPrimary?: string
leftMenuBorderColor?: string
leftMenuBgColor?: string
leftMenuBgLightColor?: string
leftMenuBgActiveColor?: string
leftMenuCollapseBgActiveColor?: string
leftMenuTextColor?: string
leftMenuTextActiveColor?: string
logoTitleTextColor?: string
logoBorderColor?: string
topHeaderBgColor?: string
topHeaderTextColor?: string
topHeaderHoverColor?: string
topToolBorderColor?: string
}
export interface AppState { export interface AppState {
breadcrumb: boolean breadcrumb: boolean
breadcrumbIcon: boolean breadcrumbIcon: boolean
@ -24,7 +40,8 @@ export interface AppState {
currentSize: ElememtPlusSzie currentSize: ElememtPlusSzie
sizeMap: ElememtPlusSzie[] sizeMap: ElememtPlusSzie[]
mobile: boolean mobile: boolean
theme: Recordable footer: boolean
theme: ThemeTypes
} }
export const appModules: AppState = { export const appModules: AppState = {
@ -44,6 +61,7 @@ export const appModules: AppState = {
tagsView: true, // 标签页 tagsView: true, // 标签页
logo: true, // logo logo: true, // logo
fixedHeader: true, // 固定toolheader fixedHeader: true, // 固定toolheader
footer: true, // 显示页脚
greyMode: false, // 是否开始灰色模式,用于特殊悼念日 greyMode: false, // 是否开始灰色模式,用于特殊悼念日
layout: wsCache.get('layout') || 'classic', // layout布局 layout: wsCache.get('layout') || 'classic', // layout布局

View File

@ -8,7 +8,9 @@ export const usePageLoading = () => {
} }
const loadDone = () => { const loadDone = () => {
appStore.setPageLoading(false) setTimeout(() => {
appStore.setPageLoading(false)
}, 1000)
} }
return { return {

View File

@ -63,4 +63,10 @@ export default defineComponent({
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app'; @prefix-cls: ~'@{namespace}-app';
:deep(.@{namespace}-content) {
.el-scrollbar__view {
height: 100%;
}
}
</style> </style>

View File

@ -1,7 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { useTagsViewStore } from '@/store/modules/tagsView' import { useTagsViewStore } from '@/store/modules/tagsView'
import { useAppStore } from '@/store/modules/app'
import { Footer } from '@/components/Footer'
import { computed } from 'vue' import { computed } from 'vue'
const appStore = useAppStore()
const layout = computed(() => appStore.getLayout)
const fixedHeader = computed(() => appStore.getFixedHeader)
const footer = computed(() => appStore.getFooter)
const tagsViewStore = useTagsViewStore() const tagsViewStore = useTagsViewStore()
const getCaches = computed((): string[] => { const getCaches = computed((): string[] => {
@ -10,7 +20,24 @@ const getCaches = computed((): string[] => {
</script> </script>
<template> <template>
<section class="p-[var(--app-content-padding)] w-[100%]"> <section
:class="[
'p-[var(--app-content-padding)] w-[100%]',
{
'!min-h-[calc(100%-calc(var(--app-content-padding)*2))]':
fixedHeader && layout === 'classic' && footer,
'!min-h-[calc(100%-var(--tags-view-height)-var(--top-tool-height)-calc(var(--app-content-padding)*2))]':
((!fixedHeader && layout === 'classic') || layout === 'top') && footer,
'!min-h-[calc(100%-var(--tags-view-height))]':
fixedHeader && layout === 'topLeft' && footer,
'!min-h-[calc(100%-var(--tags-view-height)-calc(var(--app-content-padding)*2))]':
!fixedHeader && layout === 'topLeft' && footer,
'!min-h-[calc(100%-var(--top-tool-height))]': fixedHeader && layout === 'cutMenu' && footer,
'!min-h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))]':
!fixedHeader && layout === 'cutMenu' && footer
}
]"
>
<router-view> <router-view>
<template #default="{ Component, route }"> <template #default="{ Component, route }">
<keep-alive :include="getCaches"> <keep-alive :include="getCaches">
@ -19,4 +46,5 @@ const getCaches = computed((): string[] => {
</template> </template>
</router-view> </router-view>
</section> </section>
<Footer v-if="footer" />
</template> </template>

View File

@ -143,7 +143,7 @@ export const useRenderLayout = () => {
!collapse.value && fixedHeader.value !collapse.value && fixedHeader.value
} }
]} ]}
style="transition: all var(--transition-time-02);" style="transition: width var(--transition-time-02), left var(--transition-time-02);"
></TagsView> ></TagsView>
) : undefined} ) : undefined}
@ -181,7 +181,7 @@ export const useRenderLayout = () => {
'!fixed w-full top-[var(--top-tool-height)] left-0': fixedHeader.value '!fixed w-full top-[var(--top-tool-height)] left-0': fixedHeader.value
} }
]} ]}
style="transition: all var(--transition-time-02);" style="transition: width var(--transition-time-02), left var(--transition-time-02);"
></TagsView> ></TagsView>
) : undefined} ) : undefined}

View File

@ -41,7 +41,8 @@ export default {
cutMenu: 'Cut Menu', cutMenu: 'Cut Menu',
copy: 'Copy', copy: 'Copy',
clearAndReset: 'Clear cache and reset', clearAndReset: 'Clear cache and reset',
copySuccess: 'Copy success' copySuccess: 'Copy success',
footer: 'Footer'
}, },
size: { size: {
default: 'Default', default: 'Default',

View File

@ -41,7 +41,8 @@ export default {
cutMenu: '切割菜单', cutMenu: '切割菜单',
copy: '拷贝', copy: '拷贝',
clearAndReset: '清除缓存并且重置', clearAndReset: '清除缓存并且重置',
copySuccess: '拷贝成功' copySuccess: '拷贝成功',
footer: '页脚'
}, },
size: { size: {
default: '默认', default: '默认',

View File

@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
import { store } from '../index' import { store } from '../index'
import { useCache } from '@/hooks/web/useCache' import { useCache } from '@/hooks/web/useCache'
import { appModules } from '@/config/app' import { appModules } from '@/config/app'
import type { AppState, LayoutType } from '@/config/app' import type { AppState, LayoutType, ThemeTypes } from '@/config/app'
import { setCssVar, humpToUnderline } from '@/utils' import { setCssVar, humpToUnderline } from '@/utils'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
@ -69,8 +69,11 @@ export const useAppStore = defineStore({
getMobile(): boolean { getMobile(): boolean {
return this.mobile return this.mobile
}, },
getTheme(): Recordable { getTheme(): ThemeTypes {
return this.theme return this.theme
},
getFooter(): boolean {
return this.footer
} }
}, },
actions: { actions: {
@ -139,7 +142,7 @@ export const useAppStore = defineStore({
setMobile(mobile: boolean) { setMobile(mobile: boolean) {
this.mobile = mobile this.mobile = mobile
}, },
setTheme(theme: Recordable) { setTheme(theme: ThemeTypes) {
this.theme = Object.assign(this.theme, theme) this.theme = Object.assign(this.theme, theme)
wsCache.set('theme', this.theme) wsCache.set('theme', this.theme)
}, },
@ -147,6 +150,9 @@ export const useAppStore = defineStore({
for (const key in this.theme) { for (const key in this.theme) {
setCssVar(`--${humpToUnderline(key)}`, this.theme[key]) setCssVar(`--${humpToUnderline(key)}`, this.theme[key])
} }
},
setFooter(footer: boolean) {
this.footer = footer
} }
} }
}) })

View File

@ -1,33 +0,0 @@
.hover-tigger {
@apply flex h-full pt-1px px-10px cursor-pointer items-center;
transition: background var(--transition-time-02);
&:hover {
background-color: var(--top-header-hover-color);
}
}
.border-bottom {
border-bottom: 1px solid var(--top-tool-border-color);
}
.border-bottom--after {
@apply relative;
&:after {
content: '';
border-top: 1px solid var(--top-tool-border-color);
@apply absolute bottom-0 left-0 w-full h-1px;
}
}
.border-top {
border-top: 1px solid var(--top-tool-border-color);
}
.border-top--before {
@apply relative;
&:before {
content: '';
border-top: 1px solid var(--top-tool-border-color);
@apply absolute top-0 left-0 w-full h-1px;
}
}

View File

@ -1,2 +1 @@
@import './var.css'; @import './var.css';
// @import './common.less';

3
types/router.d.ts vendored
View File

@ -30,8 +30,6 @@ import { defineComponent } from 'vue'
followAuth: '/dashboard' followAuth: '/dashboard'
canTo: true true即使hidden为true( false) canTo: true true即使hidden为true( false)
followRoute: '/dashboard'
} }
**/ **/
declare module 'vue-router' { declare module 'vue-router' {
@ -47,7 +45,6 @@ declare module 'vue-router' {
noTagsView?: boolean noTagsView?: boolean
followAuth?: string followAuth?: string
canTo?: boolean canTo?: boolean
followRoute?: string
} }
} }