Merge branch 'master' of https://github.com/zouzhibin/vue-admin-perfect into vue-i18n
Conflicts: src/layout/Header/index.vue src/layout/TagsView/index.vue
This commit is contained in:
commit
a5bfac59b0
BIN
src/assets/3.png
BIN
src/assets/3.png
Binary file not shown.
|
Before Width: | Height: | Size: 634 KiB |
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
|
|
@ -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>
|
||||
|
|
@ -193,7 +193,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-drawer__title) {
|
||||
:deep(.el-drawer__title) {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
<template> </template>
|
||||
|
||||
<script lang="ts"></script>
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 />
|
||||
|
|
|
|||
|
|
@ -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}`)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>()
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
|
|
|
|||
|
|
@ -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>()
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
$dark_gray: #889aa4;
|
||||
::v-deep(input) {
|
||||
:deep(input) {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: white;
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue