Conflicts:
	src/layout/Header/index.vue
	src/layout/TagsView/index.vue
This commit is contained in:
zouzhibing 2022-10-23 21:50:22 +08:00
commit a5bfac59b0
58 changed files with 544 additions and 911 deletions

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 KiB

View File

@ -0,0 +1,127 @@
<template>
<div class="echarts" ref="echarts"></div>
</template>
<script>
import * as echarts from "echarts";
export default {
data(){
return{
chart:null
}
},
methods:{
initEcharts(){
let option = {
series: [
{
type: 'gauge',
startAngle: 180,
endAngle: 0,
center: ['50%', '80%'],
radius: '100%',
min: 0,
max: 1,
z: 5,
splitNumber: 12,
axisLine: {
show: true,
lineStyle: {
width: 6,
color: [
[0.12, "#d92d4d"],
[0.35, "#eb8349"],
[0.63, "#e6e462"],
[0.8, "#74c7da"],
[1, "#67b45a"],
]
}
},
axisTick: {
splitNumber: 13,
show: true,
lineStyle: {
color: "auto",
width: 2,
},
length: 17,
},
splitLine: {
length: 25,
lineStyle: {
color: 'auto',
width: 8
}
},
axisLabel: {
color: '#a0a7b8',
fontSize: 20,
distance: -60,
rotate: 'tangential',
formatter: function (value) {
var value = value.toFixed(2);
if (value == 0.0) {
return "危";
} else if (value == 0.25) {
return "差";
} else if (value == 0.5) {
return "中";
} else if (value == 0.75) {
return "良";
} else if (value == 1.0) {
return "优";
} else {
return "";
}
}
},
title: {
offsetCenter: [0, '-10%'],
fontSize: 20
},
anchor: {
show: true,
showAbove: true,
size: 25,
itemStyle: {
borderWidth: 10
}
},
detail: {
fontSize: 30,
offsetCenter: [0, '-25%'],
valueAnimation: true,
formatter: function (value) {
return Math.round(value * 100);
},
color: 'auto'
},
data: [
{
value: 0.7,
name: 'Grade Rating'
}
]
}
]
};
this.chart = echarts.init(this.$refs.echarts)
this.chart.setOption(option)
}
},
mounted() {
this.initEcharts()
}
}
</script>
<style lang="scss" scoped>
.echarts {
width: 100%;
height: 100%;
}
</style>

View File

@ -1,4 +1,4 @@
import CountTo from './vue-countTo.vue'
import CountTo from './index.vue'
export default CountTo
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.component('count-to', CountTo)

View File

@ -1,37 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank">create-vue</a>, the
official Vue + Vite starter
</p>
<p>
Install
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
in your IDE for a better DX
</p>
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>

View File

@ -193,7 +193,7 @@
}
}
::v-deep(.el-drawer__title) {
:deep(.el-drawer__title) {
font-weight: bold;
color: black;
}

View File

@ -13,7 +13,7 @@
width: 100%;
height: 100%;
display: flex;
padding: 20px;
padding: 10px 12px;
box-sizing: border-box;
.m-container-layout-inner {
flex: 1;

View File

@ -1,3 +0,0 @@
<template> </template>
<script lang="ts"></script>

View File

@ -1,154 +0,0 @@
/* eslint-disable promise/prefer-await-to-then */
const methodMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror',
],
// New WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
// Old WebKit
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror',
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError',
],
]
const nativeAPI = (() => {
const unprefixedMethods = methodMap[0]
const returnValue = {}
for (const methodList of methodMap) {
const exitFullscreenMethod = methodList?.[1]
if (exitFullscreenMethod in document) {
for (const [index, method] of methodList.entries()) {
returnValue[unprefixedMethods[index]] = method
}
return returnValue
}
}
return false
})()
const eventNameMap = {
change: nativeAPI.fullscreenchange,
error: nativeAPI.fullscreenerror,
}
// eslint-disable-next-line import/no-mutable-exports
let screenfull = {
// eslint-disable-next-line default-param-last
request(element = document.documentElement, options) {
return new Promise((resolve, reject) => {
const onFullScreenEntered = () => {
screenfull.off('change', onFullScreenEntered)
resolve()
}
screenfull.on('change', onFullScreenEntered)
const returnPromise = element[nativeAPI.requestFullscreen](options)
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenEntered).catch(reject)
}
})
},
exit() {
return new Promise((resolve, reject) => {
if (!screenfull.isFullscreen) {
resolve()
return
}
const onFullScreenExit = () => {
screenfull.off('change', onFullScreenExit)
resolve()
}
screenfull.on('change', onFullScreenExit)
const returnPromise = document[nativeAPI.exitFullscreen]()
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenExit).catch(reject)
}
})
},
toggle(element, options) {
return screenfull.isFullscreen ? screenfull.exit() : screenfull.request(element, options)
},
onchange(callback) {
screenfull.on('change', callback)
},
onerror(callback) {
screenfull.on('error', callback)
},
on(event, callback) {
const eventName = eventNameMap[event]
if (eventName) {
document.addEventListener(eventName, callback, false)
}
},
off(event, callback) {
const eventName = eventNameMap[event]
if (eventName) {
document.removeEventListener(eventName, callback, false)
}
},
raw: nativeAPI,
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: () => Boolean(document[nativeAPI.fullscreenElement]),
},
element: {
enumerable: true,
get: () => document[nativeAPI.fullscreenElement] ?? undefined,
},
isEnabled: {
enumerable: true,
// Coerce to boolean in case of old WebKit.
get: () => Boolean(document[nativeAPI.fullscreenEnabled]),
},
})
if (!nativeAPI) {
screenfull = { isEnabled: false }
}
export default screenfull

View File

@ -1,60 +0,0 @@
<template>
<div class="m-screenful">
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" class="full-screen"/>
</div>
</template>
<script lang="ts" setup>
import screenfull from './index'
import { ElMessage } from 'element-plus'
import { onBeforeUnmount, onMounted, ref } from 'vue'
let isFullscreen = ref(false)
const click = () => {
if (!screenfull.isEnabled) {
ElMessage({
message: '你的浏览器不支持',
type: 'warning',
})
return false
}
screenfull.toggle()
}
const change = () => {
isFullscreen.value = screenfull.isFullscreen
}
const init = () => {
if (screenfull.isEnabled) {
screenfull.on('change', change)
}
}
const destroy = () => {
if (screenfull.isEnabled) {
screenfull.off('change', change)
}
}
onMounted(() => {
init()
})
onBeforeUnmount(() => {
destroy()
})
</script>
<style lang="scss" scoped>
.m-screenful {
display: flex;
align-items: center;
padding-right: 0;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
}
.transverseMenu {
.full-screen {
color: white;
}
}
</style>

View File

@ -0,0 +1,30 @@
<template>
<div class="hamburger-container" @click="handleCollapse">
<el-icon class="icon" v-if="isCollapse" ><expand /></el-icon>
<el-icon class="icon" v-else><fold /></el-icon>
</div>
</template>
<script lang="ts" setup>
import {useSettingStore} from "@/store/modules/setting"
import {computed} from "_vue@3.2.40@vue";
const SettingStore = useSettingStore()
const isCollapse = computed(() =>!SettingStore.isCollapse)
const handleCollapse = () => {
SettingStore.setCollapse(isCollapse.value)
}
</script>
<style lang="scss" scoped>
.hamburger-container{
padding: 0px 15px;
height: 100%;
display: flex;
align-items: center;
&:hover {
background: rgba(0, 0, 0, .025)
}
.icon {
font-size: 24px;
cursor: pointer;
}
}
</style>

View File

@ -28,45 +28,45 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('first')
const toGitHub = (link) => {
window.open(link)
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
const activeName = ref('first')
const toGitHub = (link) => {
window.open(link)
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
</script>
<style lang="scss" scoped>
.m-info {
display: inline-flex;
.m-info {
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
.item-info-pop {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
.item-info-pop {
display: flex;
align-items: center;
}
.bell{
color: black;
}
.item-child {
display: flex;
align-items: center;
font-size: 13px;
}
}
::v-deep(.el-divider--horizontal){
margin-bottom: 10px;
margin-top: 10px;
.bell{
color: black;
}
.transverseMenu {
.bell {
color: white;
}
.item-child {
display: flex;
align-items: center;
font-size: 13px;
}
}
::v-deep(.el-divider--horizontal){
margin-bottom: 10px;
margin-top: 10px;
}
.transverseMenu {
.bell {
color: white;
}
}
</style>

View File

@ -0,0 +1,26 @@
<template>
<div class="m-screenful">
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="toggle" class="full-screen"/>
</div>
</template>
<script lang="ts" setup>
import { useFullscreen } from "@vueuse/core";
const { toggle, isFullscreen } = useFullscreen();
</script>
<style lang="scss" scoped>
.m-screenful {
display: flex;
align-items: center;
padding-right: 0;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
}
.transverseMenu {
.full-screen {
color: white;
}
}
</style>

View File

@ -12,26 +12,21 @@
transverseMenu: mode === 'horizontal',
}"
>
<u-menu v-if="mode === 'horizontal'" />
<UMenu v-if="mode === 'horizontal'" />
<div class="left" v-if="mode === 'vertical'">
<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>
<u-hamburger />
<CollapseIcon/>
<Hamburger />
</div>
<div class="right">
<language class="right-item-menu"/>
<GlobalComSize class="right-item-menu"/>
<global-com-size class="right-item-menu"/>
<HeaderSearch class="right-item-menu"/>
<u-header-search class="right-item-menu"/>
<Remind class="right-item-menu"/>
<u-info class="right-item-menu"/>
<ScreenFull class="right-item-menu"/>
<u-screen-full class="right-item-menu"/>
<u-setting class="right-item-menu"/>
<Setting class="right-item-menu"/>
<el-dropdown @command="commandAction">
<span class="el-dropdown-link">
@ -63,12 +58,12 @@
import Personal from './components/Personal.vue'
import TagViews from '../TagsView/index.vue'
import GlobalComSize from './components/globalComSize.vue'
import Language from './components/Language.vue'
import UHamburger from '@/components/u-Hamburger/index.vue'
import USetting from './components/Setting.vue'
import UScreenFull from '@/components/u-screenfull/index.vue'
import UInfo from '@/components/u-info/index.vue'
import UHeaderSearch from '@/components/u-headerSearch/index.vue'
import Hamburger from '@/components/Hamburger/index.vue'
import Setting from './components/Setting.vue'
import ScreenFull from './components/ScreenFull.vue'
import Remind from './components/Remind'
import HeaderSearch from './components/HeaderSearch'
import CollapseIcon from './components/CollapseIcon'
import UMenu from '../Sidebar/components/Menu.vue'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
@ -136,10 +131,7 @@
width: 100%!important;
}
}
.icon {
font-size: 24px;
cursor: pointer;
}
.header {
height: 50px;
width: 100%;
@ -171,15 +163,7 @@
.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

@ -7,19 +7,19 @@
</keep-alive>
</transition>
</router-view>
<u-theme />
<Theme />
</div>
</template>
<script lang="ts" setup>
import UTheme from '@/components/u-theme/index.vue'
import Theme from '@/components/Theme/index.vue'
import { computed, ref } from 'vue'
import {useSettingStore} from "@/store/modules/setting"
import {usePermissionStore} from "@/store/modules/permission"
const SettingStore = useSettingStore()
const PermissionStor = usePermissionStore()
const cacheRoutes = computed(() =>PermissionStor.cacheRoutes)
const cacheRoutes = computed(() =>PermissionStor.getCacheRoutes())
const isReload = computed(() => SettingStore.isReload)
</script>

View File

@ -1,58 +0,0 @@
<template>
<div ref="bsWrap" class="tags-scroll-wrap">
<div ref="bsContent" class="tags-scroll">
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { useElementSize } from '@vueuse/core'
import BScroll from '@better-scroll/core'
import type { Options } from '@better-scroll/core'
interface Props {
/** better-scroll的配置: https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html */
options: Options
}
const props = defineProps<Props>()
const bsWrap = ref<HTMLElement>()
const instance = ref<BScroll>()
const bsContent = ref<HTMLElement>()
function initBetterScroll() {
nextTick(() => {
instance.value = new BScroll(bsWrap.value, props.options)
})
}
// BS
const { width: wrapWidth } = useElementSize(bsWrap)
const { width, height } = useElementSize(bsContent)
watch([() => wrapWidth.value, () => width.value, () => height.value], () => {
if (instance.value) {
instance.value.refresh()
}
})
onMounted(() => {
initBetterScroll()
})
defineExpose({ instance })
</script>
<style scoped>
.tags-scroll-wrap {
width: 100%;
}
.tags-scroll-inner {
/*display: flex;*/
}
.tags-scroll {
display: inline-block;
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<el-dropdown trigger="hover">
<el-button size="small" type="primary">
<span>更多</span>
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="refresh">刷新当页</el-dropdown-item>
<el-dropdown-item @click="closeCurrentTab">关闭当前</el-dropdown-item>
<el-dropdown-item @click="closeOtherTab">关闭其他</el-dropdown-item>
<el-dropdown-item @click="closeAllTab">关闭所有</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script lang="ts" setup>
import {computed} from "vue";
import {useSettingStore} from "@/store/modules/setting"
import {useTagsViewStore} from "@/store/modules/tagsView"
const SettingStore = useSettingStore()
const TagsViewStore = useTagsViewStore()
const visitedViews = computed(() => TagsViewStore.visitedViews)
const refresh = () => {
SettingStore.setReload()
}
//
const closeCurrentTab = (event)=>{
closeSelectedTag(event,route)
}
//
const closeOtherTab= async ()=>{
const { name } = route
for(let item of visitedViews.value){
if(item.name!==name){
await closeSelectedTag(null,item)
}
}
}
//
const closeAllTab = async ()=>{
let visitedViews = await TagsViewStore.delAllViews()
await TagsViewStore.goHome()
}
</script>
<style lang="scss" scoped>
.more{
background-color: $primaryColor;
color: white;
.tags-view-item{
display: flex;
align-items: center;
}
}
</style>

View File

@ -1,329 +1,166 @@
<template>
<div class="tags-wrap-container">
<div class="tags-view" ref="scrollContainer">
<better-scroll :options="{ scrollX: true, scrollY: false }" ref="bsScroll">
<div class="tags-scroll-inner">
<div
v-for="tag in visitedViews"
:ref="setTagRef"
:path="tag.path"
:data-id="tag.path"
:fullPath="tag.fullPath"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
:key="tag.path"
class="item-tag-wrap"
:class="isActive(tag) ? 'active' : ''"
@click="routerGo(tag)"
>
<div class="tags-view-item">{{ tag.title }}</div>
<el-icon
v-if="!isAffix(tag)"
@click.prevent.stop="(e) => closeSelectedTag(e, tag)" class="tag-icon">
<circle-close-filled
/></el-icon>
</div>
</div>
</better-scroll>
<div class="tags-view">
<el-tabs
v-model="activeTabsValue"
type="card"
@tab-click="tabClick"
@tab-remove="removeTab"
>
<el-tab-pane
v-for="item in visitedViews"
:key="item.path"
:path="item.path"
:label="item.title"
:name="item.path"
:closable="!(item.meta&&item.meta.affix)"
>
<template #label>
<el-icon class="tabs-icon" v-if="item.icon">
<component :is="item.icon"></component>
</el-icon>
{{ item.title }}
</template>
</el-tab-pane>
</el-tabs>
</div>
<div class="right-btn">
<MoreButton/>
</div>
<el-dropdown trigger="click">
<div class="item-tag-wrap more">
<div class="tags-view-item"> {{ $t("tagsView.more") }} <el-icon class="el-icon--right"><arrow-down /></el-icon></div>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="refresh">{{ $t("tagsView.refresh") }}</el-dropdown-item>
<el-dropdown-item @click="closeCurrentTab"> {{ $t("tagsView.closeCurrent") }}</el-dropdown-item>
<el-dropdown-item @click="closeOtherTab"> {{ $t("tagsView.closeOther") }}</el-dropdown-item>
<el-dropdown-item @click="closeAllTab"> {{ $t("tagsView.closeAll") }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script lang="ts" setup>
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import betterScroll from './betterScroll.vue'
import { useRoute, useRouter } from 'vue-router'
import {computed, watch, ref, onMounted} from "vue";
import { useRoute, useRouter } from "vue-router";
import { TabsPaneContext } from "element-plus";
import MoreButton from './components/MoreButton'
import path from 'path-browserify'
import {useTagsViewStore} from "@/store/modules/tagsView"
import {usePermissionStore} from "@/store/modules/permission"
import {useSettingStore} from "@/store/modules/setting"
import {useTagsViewStore} from "@/store/modules/tagsView"
import {usePermissionStore} from "@/store/modules/permission"
const route = useRoute()
const router = useRouter()
const TagsViewStore = useTagsViewStore()
const PermissionStore = usePermissionStore()
const visitedViews = computed(() => TagsViewStore.visitedViews)
const routes = computed(() => PermissionStore.routes)
import path from 'path-browserify'
const route = useRoute()
const router = useRouter()
const SettingStore = useSettingStore()
const TagsViewStore = useTagsViewStore()
const PermissionStore = usePermissionStore()
const refresh = () => {
SettingStore.setReload()
const addTags = () => {
const { name } = route
if (name === 'Login') {
return
}
const routes = computed(() => PermissionStore.routes)
const visitedViews = computed(() => TagsViewStore.visitedViews)
const bsScroll = ref<Expose.BetterScroll>()
let obj = new WeakMap()
let affixTags = ref([])
const tags = ref(new Map())
// ref tag
const setTagRef = (el) => {
if (el) {
if (!obj.get(el)) {
tags.value.set(el.dataset['id'], el)
}
obj.set(el, el)
}
if (name) {
TagsViewStore.addView(route)
}
const rollPane = ref()
const scrollContainer = ref()
function filterAffixTags(routes, basePath = '/') {
let tags = []
routes.forEach((route) => {
if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path)
tags.push({
fullPath: tagPath,
path: tagPath,
name: route.name,
meta: { ...route.meta },
})
}
if (route.children) {
const tempTags = filterAffixTags(route.children, route.path)
if (tempTags.length >= 1) {
tags = [...tags, ...tempTags]
}
}
})
return tags
}
const initTags = () => {
let routesNew = routes.value
let affixTag = (affixTags.value = filterAffixTags(routesNew))
for (const tag of affixTag) {
if (tag.name) {
TagsViewStore.addVisitedView(tag)
}
}
}
const isActive = (rou) => {
return rou.path === route.path
}
const isAffix = (tag) => {
return tag.meta && tag.meta.affix
}
const addTags = () => {
const { name } = route
if (name === 'Login') {
return
}
if (name) {
TagsViewStore.addView(route)
}
return false
}
function toLastView(visitedViews, view) {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
router.push(latestView.fullPath)
} else {
if (view.name === 'home') {
router.replace({ path: '/redirect' + view.fullPath })
} else {
router.push('/')
}
}
}
const closeSelectedTag = async (event, view) => {
if (tags.value.get(view.path)) {
tags.value.delete(view.path)
}
let { visitedViews } = await TagsViewStore.delView(view)
if (isActive(view)) {
toLastView(visitedViews, view)
}
}
//
const closeCurrentTab = (event)=>{
closeSelectedTag(event,route)
}
//
const closeOtherTab= async ()=>{
const { name } = route
for(let item of visitedViews.value){
if(item.name!==name){
await closeSelectedTag(null,item)
}
}
}
//
const closeAllTab = async ()=>{
let visitedViews = await TagsViewStore.delAllViews()
toLastView(visitedViews,route)
}
const routerGo = (tag) => {
router.push({
path: tag.path,
query: tag.query,
})
}
function handleScrollAction(currentTag) {
const scrollContainerRect = scrollContainer.value.getBoundingClientRect()
let { left: currx, width: currentWidth } = currentTag.getBoundingClientRect()
const clientX = currx + currentWidth / 2
const currentX = clientX - scrollContainerRect.left
const deltaX = currentX - scrollContainerRect.width / 2
if (bsScroll.value) {
const { maxScrollX, x: leftX } = bsScroll.value.instance
const rightX = maxScrollX - leftX
const update = deltaX > 0 ? Math.max(-deltaX, rightX) : Math.min(-deltaX, -leftX)
bsScroll.value?.instance.scrollBy(update, 0, 300)
}
}
function moveToCurrentTag() {
nextTick(() => {
for (const [key, tag] of tags.value) {
let path = tag.attributes.path.value
if (path === route.path) {
let fullPath = tag.attributes.fullPath.value
//
handleScrollAction(tag, tags.value)
if (fullPath !== route.fullPath) {
TagsViewStore.updateVisitedView(route)
}
break
}
}
})
}
onMounted(() => {
initTags()
addTags()
nextTick(() => {
setTimeout(() => {
moveToCurrentTag()
}, 50)
})
watch(route, () => {
addTags()
nextTick(() => {
setTimeout(() => {
moveToCurrentTag()
}, 100)
return false
}
let affixTags = ref([])
function filterAffixTags(routes, basePath = '/') {
let tags = []
routes.forEach((route) => {
if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path)
tags.push({
fullPath: tagPath,
path: tagPath,
name: route.name,
meta: { ...route.meta },
})
})
router.beforeEach(async (to, from, next) => {
if (
(from.fullPath === '/error/404' || from.fullPath === '/error/401') &&
to.fullPath === '/home'
) {
let whiteList = ['/error/404', '/error/401']
await TagsViewStore.removeView(whiteList)
}
if (route.children) {
const tempTags = filterAffixTags(route.children, route.path)
if (tempTags.length >= 1) {
tags = [...tags, ...tempTags]
}
next()
})
}
})
</script>
return tags
}
const initTags = () => {
let routesNew = routes.value
let affixTag = (affixTags.value = filterAffixTags(routesNew))
for (const tag of affixTag) {
if (tag.name) {
TagsViewStore.addVisitedView(tag)
}
}
}
onMounted(()=>{
initTags()
addTags()
})
watch(route, () => {
addTags()
})
let tabIndex = 2
const activeTabsValue = computed({
get: () => {
return TagsViewStore.activeTabsValue;
},
set: val => {
TagsViewStore.setTabsMenuValue(val);
}
});
function toLastView(activeTabPath) {
let index = visitedViews.value.findIndex(item=>item.path===activeTabPath)
const nextTab = visitedViews.value[index + 1] || visitedViews.value[index - 1];
if (!nextTab) return;
router.push(nextTab.path);
TagsViewStore.addVisitedView(nextTab)
}
// Tab Click
const tabClick = (tabItem: TabsPaneContext) => {
let path = tabItem.props.name as string;
router.push(path);
};
const isActive = (path) => {
return path === route.path
}
const removeTab = async (activeTabPath: string) => {
if (isActive(activeTabPath)) {
toLastView(activeTabPath)
}
await TagsViewStore.delView(activeTabPath)
}
</script>
<style lang="scss" scoped>
.tags-wrap-container {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 10px;
.tags-view {
height: 30px;
background: white;
display: flex;
align-items: center;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
.refresh {
//margin-left: 20px;
cursor: pointer;
font-size: 22px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
.refresh-inner {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 100%;
}
//box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
}
//padding-right: 10px;
.tags-wrap-container{
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 10px;
padding-right: 10px;
.right-btn{
height: 100%;
flex-shrink: 0;
}
.item-tag-wrap {
position: relative;
display: inline-flex;
align-items: center;
padding: 4px 12px;
font-size: 14px;
cursor: pointer;
margin-right: 10px;
border: 1px solid #d8dce5;
&.active .tag-icon {
display: block;
}
.tags-view {
flex: 1;
overflow: hidden;
box-sizing: border-box;
}
.tags-view{
.el-tabs--card :deep(.el-tabs__header){
box-sizing: border-box;
height: 40px;
padding: 0 10px;
margin: 0;
}
:deep(.el-tabs){
.el-tabs__nav {
border: none;
}
&.active {
background-color: $primaryColor;
color: #fff;
border-color: $primaryColor;
}
}
.item-tag-wrap:hover {
border-color: $primaryColor;
}
.tags-scroll-inner {
display: flex;
flex-wrap: nowrap;
}
.tag-icon {
margin-left: 6px;
}
.tags-view-item {
position: relative;
z-index: 2;
white-space: nowrap;
font-size: 12px;
.tags-inner {
display: flex;
align-items: center;
white-space: nowrap;
}
}
.more{
background-color: $primaryColor;
color: white;
.tags-view-item{
display: flex;
align-items: center;
.el-tabs__header .el-tabs__item {
border: none;
}
.el-tabs__header .el-tabs__item.is-active {
color: $primaryColor;
border-bottom:2px solid $primaryColor;
}
}
}
</style>

View File

@ -8,7 +8,7 @@
hideSliderLayout: mode === 'horizontal',
}"
>
<div :style="{ height:`${showTag?80:50}px` }" v-if="SettingStore.themeConfig.fixedHeader"></div>
<div :style="{ height:`${showTag?90:50}px` }" v-if="SettingStore.themeConfig.fixedHeader"></div>
<u-header />
<div class="m-container-content" :class="{ 'app-main-hide-tag': !showTag }">
<u-main />

View File

@ -17,7 +17,7 @@ router.beforeEach(async(to, from, next) => {
if(typeof(to.meta.title) === 'string'){
document.title = to.meta.title ||'vue-admin-perfect'
}
const UserStore = useUserStore();
const UserStore = useUserStore();
// 确定用户是否已登录过存在Token
const hasToken = UserStore.token
if (hasToken) {
@ -46,7 +46,6 @@ router.beforeEach(async(to, from, next) => {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})

View File

@ -1,12 +1,10 @@
import { createRouter, createWebHistory, RouteRecordRaw,createWebHashHistory,Router } from 'vue-router'
import Layout from "@/layout/index.vue";
// 扩展继承属性
interface extendRoute {
hidden?:boolean
}
// 引入组件
//
import tableRouter from './modules/table'
import dataScreenRouter from './modules/dataScreen'
import errorRouter from './modules/error'
@ -21,22 +19,21 @@ import formRouter from './modules/from'
import zipRoutes from './modules/zip'
import clipboardTable from './modules/clipboard'
// 异步组件
export const asyncRoutes = [
dataScreenRouter,
chartsRouter,
tableRouter,
formRouter,
chatRouter,
othersRouter,
nestedRouter,
excelRouter,
zipRoutes,
errorRouter,
externalLink,
clipboardTable,
systemRouter,
...dataScreenRouter,
...chartsRouter,
...tableRouter,
...formRouter,
...chatRouter,
...othersRouter,
...nestedRouter,
...excelRouter,
...zipRoutes,
...errorRouter,
...externalLink,
...clipboardTable,
...systemRouter,
{
path: '/:pathMatch(.*)',
redirect: '/error/404'
@ -82,9 +79,6 @@ export const constantRoutes: Array<RouteRecordRaw&extendRoute> = [
},
]
const router = createRouter({
// history: createWebHistory(process.env.BASE_URL), // history
history: createWebHashHistory(), // hash

View File

@ -2,7 +2,7 @@
import Layout from "@/layout/index.vue";
const chartsRouter = {
const chartsRouter = [{
path: '/charts',
component: Layout,
redirect: '/charts/migration',
@ -31,13 +31,13 @@ const chartsRouter = {
name: 'charts-complex',
meta: { title: '复杂图表', roles:['other'] , icon: 'MenuIcon'}
},
{
path: 'animation',
component: () => import('@/views/charts/animation.vue'),
name: 'charts-animation',
meta: { title: '动画', roles:['other'],icon: 'MenuIcon' }
},
// {
// path: 'animation',
// component: () => import('@/views/charts/animation.vue'),
// name: 'charts-animation',
// meta: { title: '动画', roles:['other'],icon: 'MenuIcon' }
// },
]
}
}]
export default chartsRouter

View File

@ -2,7 +2,7 @@
import Layout from "@/layout/index.vue";
const chartsRouter = {
const chartsRouter = [{
path: '/chat',
component: Layout,
redirect: '/charts/index',
@ -19,6 +19,6 @@ const chartsRouter = {
meta: { title: '聊天框', icon: 'chat-square' }
},
]
}
}]
export default chartsRouter

View File

@ -1,6 +1,6 @@
import Layout from '@/layout/index.vue'
const clipboardTable = {
const clipboardTable = [{
path: '/clipboard',
component: Layout,
redirect: '/clipboard/index',
@ -19,5 +19,5 @@ const clipboardTable = {
},
]
}
}]
export default clipboardTable

View File

@ -1,4 +1,4 @@
const dataScreenRouter= {
const dataScreenRouter= [{
path: "/dataScreen",
name: "dataScreen",
meta: {
@ -6,7 +6,7 @@ const dataScreenRouter= {
icon:'Histogram'
},
component: () => import("@/views/dataScreen/index.vue")
}
}]
;
export default dataScreenRouter;

View File

@ -4,7 +4,7 @@
import Layout from "@/layout/index.vue";
const errorRouter = {
const errorRouter = [{
path: '/error',
component: Layout,
redirect: '/error/404',
@ -27,6 +27,6 @@ const errorRouter = {
meta: { title: '401', icon: 'MenuIcon'}
},
]
}
}]
export default errorRouter

View File

@ -4,7 +4,7 @@
import Layout from "@/layout/index.vue";
const excelRouter = {
const excelRouter = [{
path: '/excel',
component: Layout,
redirect: '/excel/export-excel',
@ -39,6 +39,6 @@ const excelRouter = {
meta: { title: '自定义样式导出 Excel', icon: 'MenuIcon' }
},
]
}
}]
export default excelRouter

View File

@ -2,7 +2,7 @@
import Layout from "@/layout/index.vue";
const externalLink = {
const externalLink = [{
path: '/external-link',
component: Layout,
redirect: 'noRedirect',
@ -14,6 +14,6 @@ const externalLink = {
meta: { title: 'Github地址', icon: 'link' }
},
]
}
}]
export default externalLink

View File

@ -3,7 +3,7 @@
import Layout from "@/layout/index.vue";
const formRouter = {
const formRouter = [{
path: '/form',
component: Layout,
redirect: '/form/validateForm',
@ -27,6 +27,6 @@ const formRouter = {
meta: { title: '可收缩 Form', keepAlive: true , icon: 'MenuIcon'}
},
]
}
}]
export default formRouter

View File

@ -4,7 +4,7 @@
import Layout from "@/layout/index.vue";
const nestedRouter = {
const nestedRouter = [{
path: '/nested',
component: Layout,
redirect: '/form/menu1',
@ -64,6 +64,6 @@ const nestedRouter = {
},
]
}
}]
export default nestedRouter

View File

@ -2,7 +2,7 @@
import Layout from '@/layout/index.vue'
const othersRouter = {
const othersRouter = [{
path: '/other',
component: Layout,
redirect: '/other/editor',
@ -85,6 +85,6 @@ const othersRouter = {
meta: { title: '数字自增长', icon: 'MenuIcon' }
}
]
}
}]
export default othersRouter

View File

@ -2,7 +2,7 @@
import Layout from '@/layout/index.vue'
const systemRouter = {
const systemRouter = [{
path: '/system',
component: Layout,
redirect: '/system/page',
@ -37,6 +37,6 @@ const systemRouter = {
meta: { title: '菜单管理', roles: ['other'] , icon: 'MenuIcon'}
},
]
}
}]
export default systemRouter

View File

@ -3,7 +3,7 @@
import Layout from "@/layout/index.vue";
const tableRouter = {
const tableRouter = [{
path: '/table',
component: Layout,
redirect: '/table/comprehensive',
@ -38,6 +38,6 @@ const tableRouter = {
// meta: { title: '虚拟表格', keepAlive: true , icon: 'MenuIcon'}
// },
]
}
}]
export default tableRouter

View File

@ -1,6 +1,6 @@
import Layout from '@/layout/index.vue'
const zipRoutes = {
const zipRoutes = [{
path: '/zip',
component: Layout,
isShow:true,
@ -21,7 +21,7 @@ const zipRoutes = {
},
]
}
}]
export default zipRoutes

View File

@ -1,5 +1,5 @@
import {defineStore} from 'pinia'
import { asyncRoutes, constantRoutes } from '@/router/index'
import { asyncRoutes, constantRoutes,routerArray } from '@/router/index'
import {hasPermission,filterAsyncRoutes} from "@/utils/routers"
import {filterKeepAlive} from "../../utils/routers";
export const usePermissionStore = defineStore({
@ -24,7 +24,6 @@ export const usePermissionStore = defineStore({
// 生成路由
generateRoutes(roles){
return new Promise(resolve => {
this.getCacheRoutes()
// 在这判断是否有权限,哪些角色拥有哪些权限
let accessedRoutes
if (roles&&roles.length&&!roles.includes('admin')) {
@ -45,6 +44,7 @@ export const usePermissionStore = defineStore({
},
getCacheRoutes(){
this.cacheRoutes = filterKeepAlive(asyncRoutes)
return this.cacheRoutes
}
},

View File

@ -1,11 +1,13 @@
import {defineStore} from 'pinia'
import { useRouter } from "vue-router";
const router = useRouter()
export const useTagsViewStore = defineStore({
// id: 必须的,在所有 Store 中唯一
id:'tagsViewState',
// state: 返回对象的函数
state: ()=>({
activeTabsValue:'/home',
visitedViews:[],
cachedViews:[],
@ -13,6 +15,9 @@ export const useTagsViewStore = defineStore({
getters: {},
// 可以同步 也可以异步
actions:{
setTabsMenuValue(val){
this.activeTabsValue = val
},
addView(view){
this.addVisitedView(view)
},
@ -23,7 +28,9 @@ export const useTagsViewStore = defineStore({
})
},
addVisitedView(view){
this.setTabsMenuValue(view.path);
if (this.visitedViews.some(v => v.path === view.path)) return
this.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
@ -32,11 +39,12 @@ export const useTagsViewStore = defineStore({
if (view.meta.keepAlive) {
this.cachedViews.push(view.name)
}
},
delView(view){
delView(activeTabPath){
return new Promise(resolve => {
this.delVisitedView(view)
this.delCachedView(view)
this.delVisitedView(activeTabPath)
this.delCachedView(activeTabPath)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
@ -44,13 +52,13 @@ export const useTagsViewStore = defineStore({
})
},
delVisitedView(view){
delVisitedView(path){
return new Promise(resolve => {
this.visitedViews = this.visitedViews.filter(v=>{
return (v.path !== view.path||v.meta.affix)
return (v.path !== path||v.meta.affix)
})
this.cachedViews = this.cachedViews.filter(v=>{
return (v.path !== view.path||v.meta.affix)
return (v.path !== path||v.meta.affix)
})
resolve([...this.visitedViews])
})
@ -74,6 +82,10 @@ export const useTagsViewStore = defineStore({
resolve([...this.visitedViews])
})
},
async goHome() {
router.push('/home');
this.activeTabsValue = '/home';
},
updateVisitedView(view){
for (let v of this.visitedViews) {
if (v.path === view.path) {

View File

@ -1,81 +0,0 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@ -47,46 +47,5 @@
.breadcrumb-enter-from,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(30px) skewX(-50deg);
}
/* 面包屑动画 方案2 */
//.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;
//}
.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-enter-active {
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s;
}
.fade-transform-enter-from {
opacity: 0;
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(10px) skewX(-10deg);
}

View File

@ -34,7 +34,7 @@
</div>
</template>
<script setup lang="ts">
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import CountTo from '@/components/CountTo/index.vue'
import { nextTick, onMounted, ref } from 'vue'
const mAnimation = ref<HTMLElement | null>()

View File

@ -5,33 +5,33 @@ export const cityIconData = [
value: [88.999903, 43.607078],
},
{
adcode: 150000,
// adcode: 150000,
name: '内蒙古自治区',
value: [119.24787, 42.205741],
},
,
{
adcode: 150000,
// adcode: 150000,
name: '内蒙古自治区',
value: [110.627161, 41.16628],
},
{
adcode: 540000,
// adcode: 540000,
name: '西藏自治区',
value: [89.483714, 30.251951],
},
{
adcode: 630000,
// adcode: 630000,
name: '青海省',
value: [102.064693, 37.084008],
},
{
adcode: 530000,
// adcode: 530000,
name: '云南省',
value: [102.187665, 25.083688],
},
{
adcode: 610000,
// adcode: 610000,
name: '陕西省',
value: [109.20663, 35.018625],
},

View File

@ -54,7 +54,7 @@
<script lang="ts" setup>
import {onBeforeUnmount, onMounted, ref} from 'vue'
import FullScreenContainer from './components/full-screen-container.vue'
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import CountTo from '@/components/CountTo/index.vue'
import LineCharts from '@/views/charts/components/complex/line/index.vue'
import BarCharts from '@/views/charts/components/complex/bar/index.vue'
import MigrationCharts from '@/views/charts/components/migration/index.vue'
@ -98,7 +98,8 @@ onBeforeUnmount(()=>{
height: 1080px;
box-sizing: border-box;
overflow:hidden;
background: url("/static/screen/bg.png") no-repeat center center;
//background: url("/static/screen/bg.png") no-repeat center center;
background: #041c4a;
.header{
box-sizing: border-box;
width: 100%;

View File

@ -57,7 +57,7 @@
</el-radio-group>
</el-form-item>
<el-form-item label="上传图片" prop="img">
<u-upload v-model="ruleForm.img" />
<Upload v-model="ruleForm.img" />
</el-form-item>
<el-form-item label="备注" prop="desc">
<el-input v-model="ruleForm.desc" type="textarea" />
@ -74,7 +74,7 @@
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance } from 'element-plus'
import UUpload from './components/Upload.vue'
import Upload from './components/Upload.vue'
const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()

View File

@ -149,7 +149,7 @@
<script setup lang="ts">
import { User } from '@element-plus/icons-vue'
import { ref } from 'vue'
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import CountTo from '@/components/CountTo/index.vue'
import BarCharts from '@/views/charts/components/simple/bar.vue'
const circleUrl = ref('https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png')

View File

@ -1,5 +1,5 @@
$dark_gray: #889aa4;
::v-deep(input) {
:deep(input) {
background: transparent;
border: 0;
color: white;

View File

@ -89,7 +89,7 @@
</template>
<script lang="ts" setup>
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import CountTo from '@/components/CountTo/index.vue'
const example = ref()
import { reactive, ref } from 'vue'
let options = reactive({

View File

@ -13,7 +13,7 @@
label="标题"
:rules="[{ required: true, message: '请输入内容', trigger: 'blur' }]"
>
<u-wang-edior v-model="dynamicValidateForm.content" />
<wang-edior v-model="dynamicValidateForm.content" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(formRef)">保存</el-button>
@ -49,7 +49,7 @@
</template>
<script lang="ts" setup>
import UWangEdior from '@/components/u-wangEdior/index.vue'
import WangEdior from '@/components/WangEdior/index.vue'
import { reactive, ref } from 'vue'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'

View File

@ -7,7 +7,7 @@
<el-button type="primary" @click="print(3)">打印HTML</el-button>
</div>
<div style="margin-top: 20px">
<img :src="printImg" style="width: 300px" />
<img :src="logo" style="width: 200px" />
</div>
<div id="tableBox">
<el-table :data="tableData" style="width: 100%">
@ -36,7 +36,7 @@
<script lang="ts" setup>
import printJS from 'print-js'
import '@/utils/Print'
import printImg from '@/assets/image/im1.jpeg'
import logo from '@/assets/logo.png'
const tableData = [
{
@ -66,7 +66,7 @@
case 1:
printJS({
type: 'image',
printable: [printImg],
printable: [logo],
documentTitle: '打印图片',
})
break

View File

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

View File

@ -25,7 +25,7 @@
<template #header>
<span>多图片上传</span>
</template>
<u-upload @update="update" v-model="imgs" />
<Upload @update="update" v-model="imgs" />
</el-card>
<el-card>
@ -58,13 +58,13 @@
</template>
<script setup lang="ts">
import UUpload from '@/components/u-upload/index.vue'
import Upload from '@/components/Upload/index.vue'
import { ElMessage } from 'element-plus'
import TwoPng from '@/assets/image/im1.jpeg'
import { reactive, ref } from 'vue'
import logo from '@/assets/logo.png'
import { ref } from 'vue'
const imgs = ref([
{
url: TwoPng,
url: logo,
name: 'female.png',
uid: '1651408956803',
status: 'success',

View File

@ -2,16 +2,15 @@ import { defineConfig,ConfigEnv, UserConfig,loadEnv } from 'vite'
import path from 'path'
// vite.config.ts中无法使用import.meta.env 所以需要引入
import vue from '@vitejs/plugin-vue'
// 按需加载
// import AutoImport from 'unplugin-auto-import/vite'
// import Components from 'unplugin-vue-components/vite'
//import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// 增加 vue文件 script name值
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
// 生产gz文件
import viteCompression from 'vite-plugin-compression'
// 按需加载
// import AutoImport from 'unplugin-auto-import/vite'
// import Components from 'unplugin-vue-components/vite'
//import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
function resolve (dir) {
return path.join(__dirname, '.', dir)
@ -19,7 +18,6 @@ function resolve (dir) {
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
console.log('mode================',mode)
return {
plugins: [vue(),
vueSetupExtend(),