Compare commits

...

2 Commits

Author SHA1 Message Date
zouzhibing 1fcd938cf9 update:antdesign-vue重构中 2022-09-12 13:26:37 +08:00
zouzhibing 544ddeae22 update:antdesign 2022-09-11 12:15:15 +08:00
27 changed files with 1234 additions and 176 deletions

View File

@ -15,10 +15,12 @@
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\""
},
"dependencies": {
"@ant-design/icons-vue": "^6.1.0",
"@better-scroll/core": "^2.4.2",
"@vueuse/core": "^9.1.1",
"@wangeditor/editor": "^5.1.14",
"@wangeditor/editor-for-vue": "^5.1.12",
"ant-design-vue": "^3.2.12",
"axios": "^0.27.2",
"clipboard": "^2.0.10",
"core-js": "^3.6.5",

View File

@ -0,0 +1,8 @@
/**
* copy from element-ui
*/
import Scrollbar from './src/Scrollbar.vue';
export { Scrollbar };
export type { ScrollbarType } from './src/types';

View File

@ -0,0 +1,207 @@
<template>
<div class="scrollbar">
<div
ref="wrap"
:class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']"
:style="style"
@scroll="handleScroll"
>
<component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle">
<slot></slot>
</component>
</div>
<template v-if="!native">
<bar :move="moveX" :size="sizeWidth" />
<bar vertical :move="moveY" :size="sizeHeight" />
</template>
</div>
</template>
<script lang="ts">
import { addResizeListener, removeResizeListener } from './event';
// import componentSetting from '/@/settings/componentSetting';
// const { scrollbar } = componentSetting;
import { toObject } from './util';
import {
defineComponent,
ref,
onMounted,
onBeforeUnmount,
nextTick,
provide,
computed,
unref,
} from 'vue';
import Bar from './bar';
export default defineComponent({
name: 'Scrollbar',
// inheritAttrs: false,
components: { Bar },
props: {
native: {
type: Boolean,
// default: scrollbar?.native ?? false,
default: false,
},
wrapStyle: {
type: [String, Array],
default: '',
},
wrapClass: {
type: [String, Array],
default: '',
},
viewClass: {
type: [String, Array],
default: '',
},
viewStyle: {
type: [String, Array],
default: '',
},
noresize: Boolean, // container
tag: {
type: String,
default: 'div',
},
},
setup(props) {
const sizeWidth = ref('0');
const sizeHeight = ref('0');
const moveX = ref(0);
const moveY = ref(0);
const wrap = ref();
const resize = ref();
provide('scroll-bar-wrap', wrap);
const style = computed(() => {
if (Array.isArray(props.wrapStyle)) {
return toObject(props.wrapStyle);
}
return props.wrapStyle;
});
const handleScroll = () => {
if (!props.native) {
moveY.value = (unref(wrap).scrollTop * 100) / unref(wrap).clientHeight;
moveX.value = (unref(wrap).scrollLeft * 100) / unref(wrap).clientWidth;
}
};
const update = () => {
if (!unref(wrap)) return;
const heightPercentage = (unref(wrap).clientHeight * 100) / unref(wrap).scrollHeight;
const widthPercentage = (unref(wrap).clientWidth * 100) / unref(wrap).scrollWidth;
sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : '';
sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : '';
};
onMounted(() => {
if (props.native) return;
nextTick(update);
if (!props.noresize) {
addResizeListener(unref(resize), update);
addResizeListener(unref(wrap), update);
addEventListener('resize', update);
}
});
onBeforeUnmount(() => {
if (props.native) return;
if (!props.noresize) {
removeResizeListener(unref(resize), update);
removeResizeListener(unref(wrap), update);
removeEventListener('resize', update);
}
});
return {
moveX,
moveY,
sizeWidth,
sizeHeight,
style,
wrap,
resize,
update,
handleScroll,
};
},
});
</script>
<style lang="scss">
.scrollbar {
position: relative;
height: 100%;
overflow: hidden;
&__wrap {
height: 100%;
overflow: auto;
&--hidden-default {
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
opacity: 0%;
}
}
}
&__thumb {
position: relative;
display: block;
width: 0;
height: 0;
cursor: pointer;
background-color: rgb(144 147 153 / 30%);
border-radius: inherit;
transition: 0.3s background-color;
&:hover {
background-color: rgb(144 147 153 / 50%);
}
}
&__bar {
position: absolute;
right: 2px;
bottom: 2px;
z-index: 1;
border-radius: 4px;
opacity: 0%;
transition: opacity 80ms ease;
&.is-vertical {
top: 2px;
width: 6px;
& > div {
width: 100%;
}
}
&.is-horizontal {
left: 2px;
height: 6px;
& > div {
height: 100%;
}
}
}
}
.scrollbar:active > .scrollbar__bar,
.scrollbar:focus > .scrollbar__bar,
.scrollbar:hover > .scrollbar__bar {
opacity: 100%;
transition: opacity 340ms ease-out;
}
</style>

View File

@ -0,0 +1,110 @@
import {
defineComponent,
h,
computed,
ref,
getCurrentInstance,
onUnmounted,
inject,
Ref,
} from 'vue';
import { on, off } from './domUtils';
import { renderThumbStyle, BAR_MAP } from './util';
export default defineComponent({
name: 'Bar',
props: {
vertical: Boolean,
size: String,
move: Number,
},
setup(props) {
const instance = getCurrentInstance();
const thumb = ref();
const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
const bar = computed(() => {
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
});
const barStore = ref<Recordable>({});
const cursorDown = ref();
const clickThumbHandler = (e: any) => {
// prevent click event of right button
if (e.ctrlKey || e.button === 2) {
return;
}
window.getSelection()?.removeAllRanges();
startDrag(e);
barStore.value[bar.value.axis] =
e.currentTarget[bar.value.offset] -
(e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
};
const clickTrackHandler = (e: any) => {
const offset = Math.abs(
e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client],
);
const thumbHalf = thumb.value[bar.value.offset] / 2;
const thumbPositionPercentage =
((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
wrap.value[bar.value.scroll] =
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
};
const startDrag = (e: any) => {
e.stopImmediatePropagation();
cursorDown.value = true;
on(document, 'mousemove', mouseMoveDocumentHandler);
on(document, 'mouseup', mouseUpDocumentHandler);
document.onselectstart = () => false;
};
const mouseMoveDocumentHandler = (e: any) => {
if (cursorDown.value === false) return;
const prevPage = barStore.value[bar.value.axis];
if (!prevPage) return;
const offset =
(instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
-1;
const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
const thumbPositionPercentage =
((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
wrap.value[bar.value.scroll] =
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
};
function mouseUpDocumentHandler() {
cursorDown.value = false;
barStore.value[bar.value.axis] = 0;
off(document, 'mousemove', mouseMoveDocumentHandler);
document.onselectstart = null;
}
onUnmounted(() => {
off(document, 'mouseup', mouseUpDocumentHandler);
});
return () =>
h(
'div',
{
class: ['scrollbar__bar', 'is-' + bar.value.key],
onMousedown: clickTrackHandler,
},
h('div', {
ref: thumb,
class: 'scrollbar__thumb',
onMousedown: clickThumbHandler,
style: renderThumbStyle({
size: props.size,
move: props.move,
bar: bar.value,
}),
}),
);
},
});

View File

@ -0,0 +1,180 @@
import type { FunctionArgs } from '@vueuse/core';
import { upperFirst } from 'lodash-es';
export interface ViewportOffsetResult {
left: number;
top: number;
right: number;
bottom: number;
rightIncludeBody: number;
bottomIncludeBody: number;
}
export function getBoundingClientRect(element: Element): DOMRect | number {
if (!element || !element.getBoundingClientRect) {
return 0;
}
return element.getBoundingClientRect();
}
function trim(string: string) {
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
}
/* istanbul ignore next */
export function hasClass(el: Element, cls: string) {
if (!el || !cls) return false;
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
if (el.classList) {
return el.classList.contains(cls);
} else {
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
}
/* istanbul ignore next */
export function addClass(el: Element, cls: string) {
if (!el) return;
let curClass = el.className;
const classes = (cls || '').split(' ');
for (let i = 0, j = classes.length; i < j; i++) {
const clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.add(clsName);
} else if (!hasClass(el, clsName)) {
curClass += ' ' + clsName;
}
}
if (!el.classList) {
el.className = curClass;
}
}
/* istanbul ignore next */
export function removeClass(el: Element, cls: string) {
if (!el || !cls) return;
const classes = cls.split(' ');
let curClass = ' ' + el.className + ' ';
for (let i = 0, j = classes.length; i < j; i++) {
const clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.remove(clsName);
} else if (hasClass(el, clsName)) {
curClass = curClass.replace(' ' + clsName + ' ', ' ');
}
}
if (!el.classList) {
el.className = trim(curClass);
}
}
/**
* Get the left and top offset of the current element
* left: the distance between the leftmost element and the left side of the document
* top: the distance from the top of the element to the top of the document
* right: the distance from the far right of the element to the right of the document
* bottom: the distance from the bottom of the element to the bottom of the document
* rightIncludeBody: the distance between the leftmost element and the right side of the document
* bottomIncludeBody: the distance from the bottom of the element to the bottom of the document
*
* @description:
*/
export function getViewportOffset(element: Element): ViewportOffsetResult {
const doc = document.documentElement;
const docScrollLeft = doc.scrollLeft;
const docScrollTop = doc.scrollTop;
const docClientLeft = doc.clientLeft;
const docClientTop = doc.clientTop;
const pageXOffset = window.pageXOffset;
const pageYOffset = window.pageYOffset;
const box = getBoundingClientRect(element);
const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect;
const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0);
const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0);
const offsetLeft = retLeft + pageXOffset;
const offsetTop = rectTop + pageYOffset;
const left = offsetLeft - scrollLeft;
const top = offsetTop - scrollTop;
const clientWidth = window.document.documentElement.clientWidth;
const clientHeight = window.document.documentElement.clientHeight;
return {
left: left,
top: top,
right: clientWidth - rectWidth - left,
bottom: clientHeight - rectHeight - top,
rightIncludeBody: clientWidth - left,
bottomIncludeBody: clientHeight - top,
};
}
export function hackCss(attr: string, value: string) {
const prefix: string[] = ['webkit', 'Moz', 'ms', 'OT'];
const styleObj: any = {};
prefix.forEach((item) => {
styleObj[`${item}${upperFirst(attr)}`] = value;
});
return {
...styleObj,
[attr]: value,
};
}
/* istanbul ignore next */
export function on(
element: Element | HTMLElement | Document | Window,
event: string,
handler: EventListenerOrEventListenerObject,
): void {
if (element && event && handler) {
element.addEventListener(event, handler, false);
}
}
/* istanbul ignore next */
export function off(
element: Element | HTMLElement | Document | Window,
event: string,
handler: Fn,
): void {
if (element && event && handler) {
element.removeEventListener(event, handler, false);
}
}
/* istanbul ignore next */
export function once(el: HTMLElement, event: string, fn: EventListener): void {
const listener = function (this: any, ...args: unknown[]) {
if (fn) {
fn.apply(this, args);
}
off(el, event, listener);
};
on(el, event, listener);
}
export function useRafThrottle<T extends FunctionArgs>(fn: T): T {
let locked = false;
// @ts-ignore
return function (...args: any[]) {
if (locked) return;
locked = true;
window.requestAnimationFrame(() => {
// @ts-ignore
fn.apply(this, args);
locked = false;
});
};
}

View File

@ -0,0 +1,42 @@
import ResizeObserver from 'resize-observer-polyfill';
const isServer = typeof window === 'undefined';
/* istanbul ignore next */
function resizeHandler(entries: any[]) {
for (const entry of entries) {
const listeners = entry.target.__resizeListeners__ || [];
if (listeners.length) {
listeners.forEach((fn: () => any) => {
fn();
});
}
}
}
/* istanbul ignore next */
export function addResizeListener(element: any, fn: () => any) {
if (isServer) return;
if (!element.__resizeListeners__) {
element.__resizeListeners__ = [];
element.__ro__ = new ResizeObserver(resizeHandler);
element.__ro__.observe(element);
}
element.__resizeListeners__.push(fn);
}
/* istanbul ignore next */
export function removeResizeListener(element: any, fn: () => any) {
if (!element || !element.__resizeListeners__) return;
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
if (!element.__resizeListeners__.length) {
element.__ro__.disconnect();
}
}
export function triggerWindowResize() {
const event = document.createEvent('HTMLEvents');
event.initEvent('resize', true, true);
(event as any).eventType = 'message';
window.dispatchEvent(event);
}

18
src/components/Scrollbar/src/types.d.ts vendored Normal file
View File

@ -0,0 +1,18 @@
export interface BarMapItem {
offset: string;
scroll: string;
scrollSize: string;
size: string;
key: string;
axis: string;
client: string;
direction: string;
}
export interface BarMap {
vertical: BarMapItem;
horizontal: BarMapItem;
}
export interface ScrollbarType {
wrap: ElRef;
}

View File

@ -0,0 +1,50 @@
import type { BarMap } from './types';
export const BAR_MAP: BarMap = {
vertical: {
offset: 'offsetHeight',
scroll: 'scrollTop',
scrollSize: 'scrollHeight',
size: 'height',
key: 'vertical',
axis: 'Y',
client: 'clientY',
direction: 'top',
},
horizontal: {
offset: 'offsetWidth',
scroll: 'scrollLeft',
scrollSize: 'scrollWidth',
size: 'width',
key: 'horizontal',
axis: 'X',
client: 'clientX',
direction: 'left',
},
};
// @ts-ignore
export function renderThumbStyle({ move, size, bar }) {
const style = {} as any;
const translate = `translate${bar.axis}(${move}%)`;
style[bar.size] = size;
style.transform = translate;
style.msTransform = translate;
style.webkitTransform = translate;
return style;
}
function extend<T, K>(to: T, _from: K): T & K {
return Object.assign(to, _from);
}
export function toObject<T>(arr: Array<T>): Recordable<T> {
const res = {};
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res;
}

View File

@ -1,7 +1,7 @@
<template>
<section class="app-main" v-if="isReload">
<router-view v-slot="{ Component, route }">
<transition name="fade-slide" mode="out-in" appear>
<transition name="fade-slide" mode="out-in">
<keep-alive v-if="route.meta && route.meta.keepAlive">
<component :is="Component" :key="route.path" />
</keep-alive>

View File

@ -26,7 +26,6 @@ defineProps<{ isCollapse: boolean }>();
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
text-decoration: none;
height: 100%;
@ -37,17 +36,16 @@ defineProps<{ isCollapse: boolean }>();
& .sidebar-logo {
width: 32px;
height: 32px;
margin-right: 12px;
}
}
& .sidebar-title {
color: #fff;
margin-left: 12px;
font-weight: 600;
font-size: 14px;
white-space: nowrap;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;

View File

@ -1,25 +1,39 @@
<template>
<el-menu
:default-active="activeMenu"
active-text-color="#ffd04b"
background-color="#304156"
text-color="#fff"
:mode="mode"
:collapse-transition="false"
class="el-menu-vertical-demo"
:collapse="isCollapse"
<div>
<a-menu
v-model:openKeys="state.openKeys"
v-model:selectedKeys="state.selectedKeys"
mode="inline"
theme="dark"
:inline-collapsed="isCollapse"
>
<a-menu-item key="1">
<template #icon>
<PieChartOutlined />
</template>
<span>Option 1</span>
</a-menu-item>
<sub-item
v-for="route in permission_routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</a-menu>
</div>
</template>
<script lang="ts" setup>
import SubItem from './SubItem.vue'
import { defineComponent, reactive, toRefs, watch } from 'vue';
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
PieChartOutlined,
MailOutlined,
DesktopOutlined,
InboxOutlined,
AppstoreOutlined,
} from '@ant-design/icons-vue';
import { useRoute } from 'vue-router'
import {usePermissionStore} from "@/store/modules/permission"
import {useSettingStore} from "@/store/modules/setting"
@ -49,4 +63,27 @@
//
const mode = computed(() => SettingStore.themeConfig.mode)
const state = reactive({
collapsed: false,
selectedKeys: ['1'],
openKeys: ['sub1'],
preOpenKeys: ['sub1'],
});
watch(
() => state.openKeys,
(_val, oldVal) => {
state.preOpenKeys = oldVal;
},
);
const toggleCollapsed = () => {
state.collapsed = !state.collapsed;
state.openKeys = state.collapsed ? [] : state.preOpenKeys;
};
</script>
<style>
.ant-menu.ant-menu-inline-collapsed{
width: 60px!important;
}
</style>

View File

@ -1,18 +1,20 @@
<template>
<template v-if="!item.hidden">
<template v-if="!item.alwaysShow && hasOneShowingChild(item.children, item)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)">
<el-icon :size="20">
<a-menu-item :key="resolvePath(onlyOneChild.path)" v-if="onlyOneChild.meta">
<template #icon>
<span :style="{fontSize: '16px', width:'16px'}">
<component :is="onlyOneChild?.meta.icon" ></component>
</el-icon>
<template #title>{{ onlyOneChild.meta && onlyOneChild.meta.title }}</template>
</el-menu-item>
</app-link>
</span>
</template>
<el-sub-menu :index="resolvePath(item.path)" v-else popper-append-to-body>
<app-link :to="resolvePath(onlyOneChild.path)">
<span>{{ onlyOneChild.meta && onlyOneChild.meta.title }}</span>
</app-link>
</a-menu-item>
</template>
<a-sub-menu :key="resolvePath(item.path)" v-else popper-append-to-body>
<template #icon> <component :is="item.meta?.icon" :style="{fontSize: '16px', width:'16px'}"></component></template>
<template #title>
<el-icon :size="20"> <component :is="item.meta?.icon"></component></el-icon>
<span>{{ item.meta && item.meta.title }}</span>
</template>
<sub-item
@ -21,7 +23,7 @@
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-sub-menu>
</a-sub-menu>
</template>
</template>

View File

@ -1,15 +1,16 @@
<template>
<div :class="{ 'has-logo': themeConfig.showLogo }">
<logo :isCollapse="isCollapse" v-if="themeConfig.showLogo"/>
<el-scrollbar wrap-class="scrollbar-wrapper">
<Scrollbar wrap-class="scrollbar-wrapper">
<u-menu/>
</el-scrollbar>
</Scrollbar>
</div>
</template>
<script lang="ts" setup>
import UMenu from './components/Menu.vue'
import logo from './components/Logo.vue'
import {Scrollbar} from '@/components/Scrollbar'
import {useSettingStore} from "@/store/modules/setting"
import { ref, computed } from 'vue'

View File

@ -0,0 +1,49 @@
<template>
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
</template>
<script lang="ts">
import { isExternal } from '@/utils/validate.js'
export default {
props: {
to: {
type: String,
required: true,
},
},
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
},
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener',
}
}
return {
to: to,
}
},
},
}
</script>
<style lang="scss" scoped>
a {
text-decoration: none;
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<div class="sidebar-logo-container" >
<transition name="sidebarLogoFade">
<router-link v-if="isCollapse" key="collapse" class="sidebar-logo-link" to="/">
<img src="@/assets/logo.png" class="sidebar-logo">
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img src="@/assets/logo.png" class="sidebar-logo">
<h1 class="sidebar-title">Vue Admin Perfect</h1>
</router-link>
</transition>
</div>
</template>
<script lang="ts" setup>
defineProps<{ isCollapse: boolean }>();
</script>
<style lang="scss" scoped>
.sidebar-logo-container {
position: relative;
width: 100%;
height: 60px;
display: flex;
align-items: center;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
text-decoration: none;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
& .sidebar-logo {
width: 32px;
height: 32px;
}
& .sidebar-title {
color: #fff;
margin-left: 12px;
font-weight: 600;
font-size: 14px;
white-space: nowrap;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@ -0,0 +1,52 @@
<template>
<el-menu
:default-active="activeMenu"
active-text-color="#ffd04b"
background-color="#304156"
text-color="#fff"
:mode="mode"
:collapse-transition="false"
class="el-menu-vertical-demo"
:collapse="isCollapse"
>
<sub-item
v-for="route in permission_routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</template>
<script lang="ts" setup>
import SubItem from './SubItem.vue'
import { useRoute } from 'vue-router'
import {usePermissionStore} from "@/store/modules/permission"
import {useSettingStore} from "@/store/modules/setting"
import { ref, computed } from 'vue'
// setupstore
const route = useRoute()
const PermissionStore = usePermissionStore()
const SettingStore = useSettingStore()
//
const permission_routes = computed(() => PermissionStore.permission_routes)
const activeMenu = computed(() => {
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
//
const isCollapse = computed(() => !SettingStore.isCollapse)
//
const mode = computed(() => SettingStore.themeConfig.mode)
</script>

View File

@ -0,0 +1,79 @@
<template>
<template v-if="!item.hidden">
<template v-if="!item.alwaysShow && hasOneShowingChild(item.children, item)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)">
<el-icon :size="20">
<component :is="onlyOneChild?.meta.icon"></component>
</el-icon>
<template #title>{{ onlyOneChild.meta && onlyOneChild.meta.title }}</template>
</el-menu-item>
</app-link>
</template>
<el-sub-menu :index="resolvePath(item.path)" v-else popper-append-to-body>
<template #title>
<el-icon :size="20"> <component :is="item.meta?.icon"></component></el-icon>
<span>{{ item.meta && item.meta.title }}</span>
</template>
<sub-item
v-for="child in item.children"
:key="child.path"
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-sub-menu>
</template>
</template>
<script lang="ts" setup>
import { isExternal } from '@/utils/validate.js'
import AppLink from './Link.vue'
import path from 'path-browserify'
import { ref, computed } from 'vue'
const props = defineProps({
item: {
type: Object,
required: true,
},
basePath: {
type: String,
default: '',
},
})
const onlyOneChild = ref(null)
const hasOneShowingChild = (children = [], parent) => {
const showingChildren = children.filter((item) => {
//
if (item.hidden) {
return false
} else {
// 使
onlyOneChild.value = item
return true
}
})
//
if (showingChildren.length === 1) {
return true
}
//
if (showingChildren.length === 0) {
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
return true
}
return false
}
const resolvePath = (routePath) => {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(props.basePath)) {
return props.basePath
}
return path.resolve(props.basePath, routePath)
}
</script>

View File

@ -0,0 +1,34 @@
<template>
<div :class="{ 'has-logo': themeConfig.showLogo }">
<logo :isCollapse="isCollapse" v-if="themeConfig.showLogo"/>
<el-scrollbar wrap-class="scrollbar-wrapper">
<u-menu/>
</el-scrollbar>
</div>
</template>
<script lang="ts" setup>
import UMenu from './components/Menu.vue'
import logo from './components/Logo.vue'
import {useSettingStore} from "@/store/modules/setting"
import { ref, computed } from 'vue'
const SettingStore = useSettingStore()
//
const isCollapse = computed(() => !SettingStore.isCollapse)
//
const themeConfig = computed(() =>SettingStore.themeConfig )
</script>
<style lang="scss">
.el-menu-vertical-demo:not(.el-menu--collapse) {
//width: 200px;
height: 100%;
}
.crollbar-wrapper {
height: 100%;
.el-scrollbar__view {
height: 100%;
}
}
</style>

View File

@ -17,6 +17,10 @@ import 'element-plus/theme-chalk/dark/css-vars.css'
// 自定义暗黑模式
import "@/styles/element-dark.scss";
// 引入 ant-design-vue
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
// 引入全局组件布局
import UContainerLayout from '@/components/u-container-layout/index.vue'
@ -35,6 +39,7 @@ Object.keys(ElIconsModules).forEach((key) => {//循环遍历组件名称
}
});
app.use(pinia)
app.use(Antd)
app.use(router)
app.use(ElementPlus).mount('#app')

View File

@ -19,7 +19,7 @@
.sidebar-container {
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
//background-color: $menuBg;
height: 100%;
position: fixed;
font-size: 0px;
@ -61,43 +61,43 @@
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
//.svg-icon {
// margin-right: 16px;
//}
//
//.sub-el-icon {
// margin-right: 12px;
// margin-left: -2px;
//}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
background: none;
}
// menu hover
.sub-menu-title-noDropdown,
.el-sub-menu__title {
&:hover {
background-color: $menuHover !important;
}
}
.is-active > .el-sub-menu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $subMenuHover !important;
}
}
//.el-menu {
// border: none;
// height: 100%;
// width: 100% !important;
// background: none;
//}
//
//// menu hover
//.sub-menu-title-noDropdown,
//.el-sub-menu__title {
// &:hover {
// background-color: $menuHover !important;
// }
//}
//
//.is-active > .el-sub-menu__title {
// color: $subMenuActiveText !important;
//}
//
//& .nest-menu .el-sub-menu > .el-sub-menu__title,
//& .el-sub-menu .el-menu-item {
// min-width: $sideBarWidth !important;
// background-color: $subMenuBg !important;
//
// &:hover {
// background-color: $subMenuHover !important;
// }
//}
}
.hideSidebar {
@ -161,74 +161,74 @@
}
}
.el-menu--collapse .el-menu .el-sub-menu {
min-width: $sideBarWidth !important;
}
//.el-menu--collapse .el-menu .el-sub-menu {
// min-width: $sideBarWidth !important;
//}
// mobile responsive
.mobile {
.main-container {
margin-left: 0px;
}
//.mobile {
// .main-container {
// margin-left: 0px;
// }
//
// .sidebar-container {
// transition: transform 0.28s;
// width: $sideBarWidth !important;
// }
//
// &.hideSidebar {
// .sidebar-container {
// pointer-events: none;
// transition-duration: 0.3s;
// transform: translate3d(-$sideBarWidth, 0, 0);
// }
// }
//}
.sidebar-container {
transition: transform 0.28s;
width: $sideBarWidth !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
//.withoutAnimation {
// .main-container,
// .sidebar-container {
// transition: none;
// }
//}
}
// when menu collapsed
.el-menu--vertical {
& > .el-menu {
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
.nest-menu .el-sub-menu > .el-sub-menu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
background-color: $menuHover !important;
}
}
// the scroll bar appears when the subMenu is too long
> .el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}
//.el-menu--vertical {
// & > .el-menu {
// .svg-icon {
// margin-right: 16px;
// }
// .sub-el-icon {
// margin-right: 12px;
// margin-left: -2px;
// }
// }
//
// .nest-menu .el-sub-menu > .el-sub-menu__title,
// .el-menu-item {
// &:hover {
// // you can use $subMenuHover
// background-color: $menuHover !important;
// }
// }
//
// // the scroll bar appears when the subMenu is too long
// > .el-menu--popup {
// max-height: 100vh;
// overflow-y: auto;
//
// &::-webkit-scrollbar-track-piece {
// background: #d3dce6;
// }
//
// &::-webkit-scrollbar {
// width: 6px;
// }
//
// &::-webkit-scrollbar-thumb {
// background: #99a9bf;
// border-radius: 20px;
// }
// }
//}

View File

@ -29,7 +29,7 @@
// logo动画
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
transition: opacity 2s;
}
.sidebarLogoFade-enter-from{
opacity: 0;
@ -42,7 +42,7 @@
// 面包屑动画
.breadcrumb-enter-active {
transition: all 0.25s;
transition: all 0.2s;
}
.breadcrumb-enter-from,
.breadcrumb-leave-active {

View File

@ -1,6 +1,3 @@
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* Parse the time to string

View File

@ -1,6 +1,3 @@
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path

View File

@ -1,7 +1,9 @@
<template>
<div style="padding: 30px">
<el-alert title="menu 1" :closable="false">
<router-view />
<router-view v-slot="{ Component }">
<component :is="Component" />
</router-view>
</el-alert>
</div>
</template>

View File

@ -1,7 +1,9 @@
<template>
<div style="padding: 30px">
<el-alert title="menu 1-1" type="success" :closable="false">
<router-view />
<router-view v-slot="{ Component }">
<component :is="Component" />
</router-view>
</el-alert>
</div>
</template>

View File

@ -1,7 +1,9 @@
<template>
<div style="padding: 30px">
<el-alert title="menu 1-2" type="success" :closable="false">
<router-view />
<router-view v-slot="{ Component }">
<component :is="Component" />
</router-view>
</el-alert>
</div>
</template>

137
yarn.lock
View File

@ -2,6 +2,26 @@
# yarn lockfile v1
"@ant-design/colors@^6.0.0":
version "6.0.0"
resolved "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz#9b9366257cffcc47db42b9d0203bb592c13c0298"
integrity sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==
dependencies:
"@ctrl/tinycolor" "^3.4.0"
"@ant-design/icons-svg@^4.2.1":
version "4.2.1"
resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz#8630da8eb4471a4aabdaed7d1ff6a97dcb2cf05a"
integrity sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==
"@ant-design/icons-vue@^6.1.0":
version "6.1.0"
resolved "https://registry.npmmirror.com/@ant-design/icons-vue/-/icons-vue-6.1.0.tgz#f9324fdc0eb4cea943cf626d2bf3db9a4ff4c074"
integrity sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==
dependencies:
"@ant-design/colors" "^6.0.0"
"@ant-design/icons-svg" "^4.2.1"
"@antfu/utils@^0.5.2":
version "0.5.2"
resolved "https://registry.npmmirror.com/@antfu/utils/-/utils-0.5.2.tgz#8c2d931ff927be0ebe740169874a3d4004ab414b"
@ -12,6 +32,13 @@
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.18.10.tgz#94b5f8522356e69e8277276adf67ed280c90ecc1"
integrity sha512-TYk3OA0HKL6qNryUayb5UUEhM/rkOQozIBEA5ITXh5DWrSp0TlUQXMyZmnWxG/DizSWBeeQ0Zbc5z8UGaaqoeg==
"@babel/runtime@^7.10.5":
version "7.19.0"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.0":
version "7.18.9"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
@ -31,7 +58,7 @@
resolved "https://registry.npmmirror.com/@better-scroll/shared-utils/-/shared-utils-2.4.2.tgz#1ac5c97495727093a22a8009560795dd5e3c18da"
integrity sha512-Gy/Jfbpu+hq0u+PcjkTqyXGqAf+0dexTzEZ5IDXEVwJVLmd3cx8A73oTcAZ8QZgk4wSHvlMjXecSaptkhnNPEw==
"@ctrl/tinycolor@^3.4.1":
"@ctrl/tinycolor@^3.4.0", "@ctrl/tinycolor@^3.4.1":
version "3.4.1"
resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32"
integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==
@ -151,6 +178,14 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@simonwep/pickr@~1.8.0":
version "1.8.2"
resolved "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz#96dc86675940d7cad63d69c22083dd1cbb9797cb"
integrity sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==
dependencies:
core-js "^3.15.1"
nanopop "^2.1.0"
"@transloadit/prettier-bytes@0.0.7":
version "0.0.7"
resolved "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b"
@ -614,6 +649,29 @@ ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
ant-design-vue@^3.2.12:
version "3.2.12"
resolved "https://registry.npmmirror.com/ant-design-vue/-/ant-design-vue-3.2.12.tgz#996361982884b1d0d82186dba67962983bc1fbac"
integrity sha512-CPsoWJ3t+sqq/EPINPXb4fC5/9iKkUdYOfK9M9kLKbXlRN3MAoVwWUbaFnUqc+ngtbEpn/d69hTF/Eh7MeWMhQ==
dependencies:
"@ant-design/colors" "^6.0.0"
"@ant-design/icons-vue" "^6.1.0"
"@babel/runtime" "^7.10.5"
"@ctrl/tinycolor" "^3.4.0"
"@simonwep/pickr" "~1.8.0"
array-tree-filter "^2.1.0"
async-validator "^4.0.0"
dayjs "^1.10.5"
dom-align "^1.12.1"
dom-scroll-into-view "^2.0.0"
lodash "^4.17.21"
lodash-es "^4.17.15"
resize-observer-polyfill "^1.5.1"
scroll-into-view-if-needed "^2.2.25"
shallow-equal "^1.0.0"
vue-types "^3.0.0"
warning "^4.0.0"
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
@ -671,6 +729,11 @@ arr-union@^3.1.0:
resolved "https://registry.npmmirror.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==
array-tree-filter@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190"
integrity sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@ -686,7 +749,7 @@ assign-symbols@^1.0.0:
resolved "https://registry.npmmirror.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==
async-validator@^4.2.5:
async-validator@^4.0.0, async-validator@^4.2.5:
version "4.2.5"
resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
@ -1010,6 +1073,11 @@ copy-descriptor@^0.1.0:
resolved "https://registry.npmmirror.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
core-js@^3.15.1:
version "3.25.1"
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.25.1.tgz#5818e09de0db8956e16bf10e2a7141e931b7c69c"
integrity sha512-sr0FY4lnO1hkQ4gLDr24K0DGnweGO1QwSj5BpfQjpSJPdqWalja4cTps29Y/PJVG/P7FYlPDkH3hO+Tr0CvDgQ==
core-js@^3.6.5:
version "3.24.1"
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f"
@ -1116,6 +1184,11 @@ dart-sass@^1.25.0:
dependencies:
chokidar ">=2.0.0 <4.0.0"
dayjs@^1.10.5:
version "1.11.5"
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
dayjs@^1.11.3, dayjs@^1.11.4, dayjs@^1.8.34:
version "1.11.4"
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.4.tgz#3b3c10ca378140d8917e06ebc13a4922af4f433e"
@ -1208,6 +1281,16 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
dom-align@^1.12.1:
version "1.12.3"
resolved "https://registry.npmmirror.com/dom-align/-/dom-align-1.12.3.tgz#a36d02531dae0eefa2abb0c4db6595250526f103"
integrity sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==
dom-scroll-into-view@^2.0.0:
version "2.0.1"
resolved "https://registry.npmmirror.com/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz#0decc8522801fd8d3f1c6ba355a74d382c5f989b"
integrity sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==
dom-serializer@0:
version "0.2.2"
resolved "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@ -2247,6 +2330,11 @@ is-plain-obj@^1.1:
resolved "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
is-plain-object@3.0.1:
version "3.0.1"
resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b"
integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -2301,6 +2389,11 @@ js-binary-schema-parser@^2.0.2:
resolved "https://registry.npmmirror.com/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz#3d7848748e8586e63b34e8911b643f59cfb6396e"
integrity sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@ -2421,7 +2514,7 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash-es@^4.17.21:
lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@ -2536,6 +2629,13 @@ lodash@^4.17.21:
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.0.0:
version "1.4.0"
resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@ -2738,6 +2838,11 @@ nanomatch@^1.2.1:
snapdragon "^0.8.1"
to-regex "^3.0.1"
nanopop@^2.1.0:
version "2.2.0"
resolved "https://registry.npmmirror.com/nanopop/-/nanopop-2.2.0.tgz#bd1c25588a7beaf68865bc2df19db4c58c77dcc9"
integrity sha512-E9JaHcxh3ere8/BEZHAcnuD10RluTSPyTToBvoFWS9/7DcCx6gyKjbn7M7Bx7E1veCxCuY1iO6h4+gdAf1j73Q==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@ -3132,6 +3237,11 @@ repeat-string@^1.6.1:
resolved "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@ -3222,7 +3332,7 @@ saxes@^5.0.1:
dependencies:
xmlchars "^2.2.0"
scroll-into-view-if-needed@^2.2.28:
scroll-into-view-if-needed@^2.2.25, scroll-into-view-if-needed@^2.2.28:
version "2.2.29"
resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885"
integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==
@ -3261,6 +3371,11 @@ setimmediate@^1.0.5, setimmediate@~1.0.4:
resolved "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
shallow-equal@^1.0.0:
version "1.2.1"
resolved "https://registry.npmmirror.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@ -3959,6 +4074,13 @@ vue-tsc@^0.38.4:
dependencies:
"@volar/vue-typescript" "0.38.9"
vue-types@^3.0.0:
version "3.0.2"
resolved "https://registry.npmmirror.com/vue-types/-/vue-types-3.0.2.tgz#ec16e05d412c038262fc1efa4ceb9647e7fb601d"
integrity sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==
dependencies:
is-plain-object "3.0.1"
vue@^3.0.0:
version "3.2.37"
resolved "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e"
@ -3984,6 +4106,13 @@ vuex@^4.0.0-0:
dependencies:
"@vue/devtools-api" "^6.0.0-beta.11"
warning@^4.0.0:
version "4.0.3"
resolved "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
dependencies:
loose-envify "^1.0.0"
webpack-sources@^3.2.3:
version "3.2.3"
resolved "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"