From e20fa76cad0894a69fd04c81c2108faabf392684 Mon Sep 17 00:00:00 2001 From: kailong321200875 <321200875@qq.com> Date: Sat, 22 Jan 2022 19:39:44 +0800 Subject: [PATCH] feat(component): Add CountTo component and Echart component --- package.json | 2 + pnpm-lock.yaml | 130 +++++++++++----- src/components/CountTo/index.ts | 0 src/components/CountTo/src/CountTo.vue | 175 ++++++++++++++++++++++ src/components/Echart/index.ts | 3 + src/components/Echart/src/Echart.vue | 110 ++++++++++++++ src/components/TagsView/src/TagsView.vue | 4 +- src/layout/components/useRenderLayout.tsx | 12 +- src/locales/en.ts | 4 +- src/locales/zh-CN.ts | 4 +- src/permission.ts | 2 +- src/plugins/echarts/index.ts | 33 ++++ src/router/index.ts | 23 +++ src/views/Dashboard/Analysis.vue | 7 + src/views/Dashboard/echarts-data.ts | 0 15 files changed, 461 insertions(+), 48 deletions(-) create mode 100644 src/components/CountTo/index.ts create mode 100644 src/components/CountTo/src/CountTo.vue create mode 100644 src/components/Echart/index.ts create mode 100644 src/components/Echart/src/Echart.vue create mode 100644 src/plugins/echarts/index.ts create mode 100644 src/views/Dashboard/Analysis.vue create mode 100644 src/views/Dashboard/echarts-data.ts diff --git a/package.json b/package.json index 90fbfbb..754149b 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "@zxcvbn-ts/core": "^1.2.0", "animate.css": "^4.1.1", "axios": "^0.25.0", + "echarts": "^5.2.2", + "echarts-wordcloud": "^2.0.0", "element-plus": "1.3.0-beta.5", "lodash-es": "^4.17.21", "mockjs": "^1.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9dd38e..dc3b93d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,8 @@ specifiers: autoprefixer: ^10.4.2 axios: ^0.25.0 commitizen: ^4.2.4 + echarts: ^5.2.2 + echarts-wordcloud: ^2.0.0 element-plus: 1.3.0-beta.5 eslint: ^8.7.0 eslint-config-prettier: ^8.3.0 @@ -70,6 +72,8 @@ dependencies: '@zxcvbn-ts/core': registry.npmmirror.com/@zxcvbn-ts/core/1.2.0 animate.css: registry.npmmirror.com/animate.css/4.1.1 axios: registry.npmmirror.com/axios/0.25.0 + echarts: registry.npmmirror.com/echarts/5.2.2 + echarts-wordcloud: registry.npmmirror.com/echarts-wordcloud/2.0.0_echarts@5.2.2 element-plus: registry.npmmirror.com/element-plus/1.3.0-beta.5_vue@3.2.26 lodash-es: registry.nlark.com/lodash-es/4.17.21 mockjs: registry.npmmirror.com/mockjs/1.1.0 @@ -350,38 +354,6 @@ packages: version: 1.0.2 dev: true - registry.nlark.com/acorn-jsx/5.3.2_acorn@7.4.1: - resolution: - { - integrity: sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=, - registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz - } - id: registry.nlark.com/acorn-jsx/5.3.2 - name: acorn-jsx - version: 5.3.2 - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: registry.npmmirror.com/acorn/7.4.1 - dev: true - - registry.nlark.com/acorn-jsx/5.3.2_acorn@8.7.0: - resolution: - { - integrity: sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=, - registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz - } - id: registry.nlark.com/acorn-jsx/5.3.2 - name: acorn-jsx - version: 5.3.2 - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: registry.npmmirror.com/acorn/8.7.0 - dev: true - registry.nlark.com/acorn-walk/8.2.0: resolution: { @@ -1781,7 +1753,7 @@ packages: { integrity: sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/eslint-utils/download/eslint-utils-2.1.0.tgz + tarball: https://registry.nlark.com/eslint-utils/download/eslint-utils-2.1.0.tgz?cache=0&sync_timestamp=1631600361784&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint-utils%2Fdownload%2Feslint-utils-2.1.0.tgz } name: eslint-utils version: 2.1.0 @@ -6244,6 +6216,19 @@ packages: engines: { node: '>=10' } dev: true + registry.nlark.com/zrender/5.2.1: + resolution: + { + integrity: sha1-X0u9qRW6bUErCxncJDG+qtBUF7s=, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.nlark.com/zrender/download/zrender-5.2.1.tgz + } + name: zrender + version: 5.2.1 + dependencies: + tslib: registry.npmmirror.com/tslib/2.3.0 + dev: false + registry.npmmirror.com/@antfu/utils/0.3.0: resolution: { @@ -8402,6 +8387,38 @@ packages: through: registry.nlark.com/through/2.3.8 dev: true + registry.npmmirror.com/acorn-jsx/5.3.2_acorn@7.4.1: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz + } + id: registry.npmmirror.com/acorn-jsx/5.3.2 + name: acorn-jsx + version: 5.3.2 + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: registry.npmmirror.com/acorn/7.4.1 + dev: true + + registry.npmmirror.com/acorn-jsx/5.3.2_acorn@8.7.0: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz + } + id: registry.npmmirror.com/acorn-jsx/5.3.2 + name: acorn-jsx + version: 5.3.2 + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: registry.npmmirror.com/acorn/8.7.0 + dev: true + registry.npmmirror.com/acorn/7.4.1: resolution: { @@ -9378,6 +9395,36 @@ packages: domhandler: registry.npmmirror.com/domhandler/4.3.0 dev: true + registry.npmmirror.com/echarts-wordcloud/2.0.0_echarts@5.2.2: + resolution: + { + integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/echarts-wordcloud/download/echarts-wordcloud-2.0.0.tgz + } + id: registry.npmmirror.com/echarts-wordcloud/2.0.0 + name: echarts-wordcloud + version: 2.0.0 + peerDependencies: + echarts: ^5.0.1 + dependencies: + echarts: registry.npmmirror.com/echarts/5.2.2 + dev: false + + registry.npmmirror.com/echarts/5.2.2: + resolution: + { + integrity: sha512-yxuBfeIH5c+0FsoRP60w4De6omXhA06c7eUYBsC1ykB6Ys2yK5fSteIYWvkJ4xJVLQgCvAdO8C4mN6MLeJpBaw==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/echarts/download/echarts-5.2.2.tgz + } + name: echarts + version: 5.2.2 + dependencies: + tslib: registry.npmmirror.com/tslib/2.3.0 + zrender: registry.nlark.com/zrender/5.2.1 + dev: false + registry.npmmirror.com/electron-to-chromium/1.4.30: resolution: { @@ -10035,7 +10082,7 @@ packages: engines: { node: '>=6.0.0' } dependencies: acorn: registry.npmmirror.com/acorn/7.4.1 - acorn-jsx: registry.nlark.com/acorn-jsx/5.3.2_acorn@7.4.1 + acorn-jsx: registry.npmmirror.com/acorn-jsx/5.3.2_acorn@7.4.1 eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0 dev: true @@ -10051,7 +10098,7 @@ packages: engines: { node: ^10.12.0 || >=12.0.0 } dependencies: acorn: registry.npmmirror.com/acorn/7.4.1 - acorn-jsx: registry.nlark.com/acorn-jsx/5.3.2_acorn@7.4.1 + acorn-jsx: registry.npmmirror.com/acorn-jsx/5.3.2_acorn@7.4.1 eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0 dev: true @@ -10067,7 +10114,7 @@ packages: engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dependencies: acorn: registry.npmmirror.com/acorn/8.7.0 - acorn-jsx: registry.nlark.com/acorn-jsx/5.3.2_acorn@8.7.0 + acorn-jsx: registry.npmmirror.com/acorn-jsx/5.3.2_acorn@8.7.0 eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/3.2.0 dev: true @@ -12239,6 +12286,17 @@ packages: version: 1.14.1 dev: true + registry.npmmirror.com/tslib/2.3.0: + resolution: + { + integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/tslib/download/tslib-2.3.0.tgz + } + name: tslib + version: 2.3.0 + dev: false + registry.npmmirror.com/tslib/2.3.1: resolution: { diff --git a/src/components/CountTo/index.ts b/src/components/CountTo/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CountTo/src/CountTo.vue b/src/components/CountTo/src/CountTo.vue new file mode 100644 index 0000000..a5d54dc --- /dev/null +++ b/src/components/CountTo/src/CountTo.vue @@ -0,0 +1,175 @@ +<script setup lang="ts"> +import { reactive, computed, watch, onMounted, unref, toRef, PropType } from 'vue' +import { isNumber } from '@/utils/is' +import { propTypes } from '@/utils/propTypes' + +const props = defineProps({ + startVal: propTypes.number.def(0), + endVal: propTypes.number.def(2021), + duration: propTypes.number.def(3000), + autoplay: propTypes.bool.def(false), + decimals: propTypes.number.validate((value: number) => value >= 0).def(0), + decimal: propTypes.string.def('.'), + separator: propTypes.string.def(','), + prefix: propTypes.string.def(''), + suffix: propTypes.string.def(''), + useEasing: propTypes.bool.def(true), + easingFn: { + type: Function as PropType<(t: number, b: number, c: number, d: number) => number>, + default(t: number, b: number, c: number, d: number) { + return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b + } + } +}) + +const emit = defineEmits(['mounted', 'callback']) + +const formatNumber = (num: number | string) => { + const { decimals, decimal, separator, suffix, prefix } = props + num = Number(num).toFixed(decimals) + num += '' + const x = num.split('.') + let x1 = x[0] + const x2 = x.length > 1 ? decimal + x[1] : '' + const rgx = /(\d+)(\d{3})/ + if (separator && !isNumber(separator)) { + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + separator + '$2') + } + } + return prefix + x1 + x2 + suffix +} + +const state = reactive<{ + localStartVal: number + printVal: number | null + displayValue: string + paused: boolean + localDuration: number | null + startTime: number | null + timestamp: number | null + rAF: any + remaining: number | null +}>({ + localStartVal: props.startVal, + displayValue: formatNumber(props.startVal), + printVal: null, + paused: false, + localDuration: props.duration, + startTime: null, + timestamp: null, + remaining: null, + rAF: null +}) + +const displayValue = toRef(state, 'displayValue') + +onMounted(() => { + if (props.autoplay) { + start() + } + emit('mounted') +}) + +const getCountDown = computed(() => { + return props.startVal > props.endVal +}) + +watch([() => props.startVal, () => props.endVal], () => { + if (props.autoplay) { + start() + } +}) + +const start = () => { + const { startVal, duration } = props + state.localStartVal = startVal + state.startTime = null + state.localDuration = duration + state.paused = false + state.rAF = requestAnimationFrame(count) +} + +const pauseResume = () => { + if (state.paused) { + resume() + state.paused = false + } else { + pause() + state.paused = true + } +} + +const pause = () => { + cancelAnimationFrame(state.rAF) +} + +const resume = () => { + state.startTime = null + state.localDuration = +(state.remaining as number) + state.localStartVal = +(state.printVal as number) + requestAnimationFrame(count) +} + +const reset = () => { + state.startTime = null + cancelAnimationFrame(state.rAF) + state.displayValue = formatNumber(props.startVal) +} + +const count = (timestamp: number) => { + const { useEasing, easingFn, endVal } = props + if (!state.startTime) state.startTime = timestamp + state.timestamp = timestamp + const progress = timestamp - state.startTime + state.remaining = (state.localDuration as number) - progress + if (useEasing) { + if (unref(getCountDown)) { + state.printVal = + state.localStartVal - + easingFn(progress, 0, state.localStartVal - endVal, state.localDuration as number) + } else { + state.printVal = easingFn( + progress, + state.localStartVal, + endVal - state.localStartVal, + state.localDuration as number + ) + } + } else { + if (unref(getCountDown)) { + state.printVal = + state.localStartVal - + (state.localStartVal - endVal) * (progress / (state.localDuration as number)) + } else { + state.printVal = + state.localStartVal + + (endVal - state.localStartVal) * (progress / (state.localDuration as number)) + } + } + if (unref(getCountDown)) { + state.printVal = state.printVal < endVal ? endVal : state.printVal + } else { + state.printVal = state.printVal > endVal ? endVal : state.printVal + } + state.displayValue = formatNumber(state.printVal) + if (progress < (state.localDuration as number)) { + state.rAF = requestAnimationFrame(count) + } else { + emit('callback') + } +} + +defineExpose({ + pauseResume, + reset, + start, + pause +}) +</script> + +<template> + <span> + {{ displayValue }} + </span> +</template> diff --git a/src/components/Echart/index.ts b/src/components/Echart/index.ts new file mode 100644 index 0000000..4822092 --- /dev/null +++ b/src/components/Echart/index.ts @@ -0,0 +1,3 @@ +import Echart from './src/Echart.vue' + +export { Echart } diff --git a/src/components/Echart/src/Echart.vue b/src/components/Echart/src/Echart.vue new file mode 100644 index 0000000..98d9456 --- /dev/null +++ b/src/components/Echart/src/Echart.vue @@ -0,0 +1,110 @@ +<script setup lang="ts"> +import type { EChartsOption } from 'echarts' +import echarts from '@/plugins/echarts' +import { debounce } from 'lodash-es' +import 'echarts-wordcloud' +import { propTypes } from '@/utils/propTypes' +import { computed, PropType, ref, unref, watch, onMounted, onBeforeUnmount, onActivated } from 'vue' +import { useAppStore } from '@/store/modules/app' +import { isString } from '@/utils/is' + +const appStore = useAppStore() + +const props = defineProps({ + options: { + type: Object as PropType<EChartsOption>, + required: true + }, + width: propTypes.oneOfType([Number, String]).def(''), + height: propTypes.oneOfType([Number, String]).def('500px') +}) + +const isDark = computed(() => appStore.getIsDark) + +const theme = computed(() => { + const echartTheme: boolean | string = unref(isDark) ? true : 'auto' + + return echartTheme +}) + +const options = computed(() => { + return Object.assign(props.options, { + darkMode: unref(theme) + }) +}) + +const elRef = ref<ElRef>() + +const echartRef = ref<echarts.ECharts>() + +const contentEl = ref<Element>() + +const styles = computed(() => { + const width = isString(props.width) ? props.width : `${props.width}px` + const height = isString(props.height) ? props.height : `${props.height}px` + + return { + width, + height + } +}) + +const initChart = () => { + if (unref(elRef) && props.options) { + echartRef.value = echarts.init(unref(elRef) as HTMLElement, unref(options)) + } +} + +watch( + () => options.value, + (options) => { + const chart = unref(echartRef) + if (chart) { + chart?.setOption(options) + } + }, + { + deep: true + } +) + +const resizeHandler = debounce(() => { + const chart = unref(echartRef) + if (chart) { + chart.resize() + } +}, 100) + +const contentResizeHandler = (e: TransitionEvent) => { + if (e.propertyName === 'width') { + resizeHandler() + } +} + +onMounted(() => { + initChart() + + window.addEventListener('resize', resizeHandler) + + contentEl.value = document.getElementsByClassName('v-content')[0] + unref(contentEl) && + (unref(contentEl) as Element).addEventListener('transitionend', contentResizeHandler) +}) + +onBeforeUnmount(() => { + window.removeEventListener('resize', resizeHandler) + unref(contentEl) && + (unref(contentEl) as Element).removeEventListener('transitionend', contentResizeHandler) +}) + +onActivated(() => { + const chart = unref(echartRef) + if (chart) { + chart.resize() + } +}) +</script> + +<template> + <div ref="elRef" :class="$attrs.class" :style="styles" /> +</template> diff --git a/src/components/TagsView/src/TagsView.vue b/src/components/TagsView/src/TagsView.vue index f06590c..986404f 100644 --- a/src/components/TagsView/src/TagsView.vue +++ b/src/components/TagsView/src/TagsView.vue @@ -147,6 +147,7 @@ watch( { icon: 'ant-design:close-outlined', label: t('common.closeTab'), + disabled: !!visitedViews?.length && selectedTag?.meta.affix, command: () => { closeSelectedTag(item) } @@ -243,7 +244,8 @@ watch( }, { icon: 'ant-design:close-outlined', - label: t('common.closeTab') + label: t('common.closeTab'), + disabled: !!visitedViews?.length && selectedTag?.meta.affix }, { divided: true, diff --git a/src/layout/components/useRenderLayout.tsx b/src/layout/components/useRenderLayout.tsx index 3b5fa19..94f3ba0 100644 --- a/src/layout/components/useRenderLayout.tsx +++ b/src/layout/components/useRenderLayout.tsx @@ -49,7 +49,7 @@ export const useRenderLayout = () => { </div> <div class={[ - 'v-app-right', + 'v-content', 'absolute top-0 h-[100%]', { 'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]': @@ -64,7 +64,6 @@ export const useRenderLayout = () => { <ElScrollbar v-loading={pageLoading.value} class={[ - 'v-content', { '!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]': fixedHeader.value @@ -110,7 +109,7 @@ export const useRenderLayout = () => { <Menu class="!h-full"></Menu> <div class={[ - 'v-app-right', + 'v-content', 'h-[100%]', { 'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]': @@ -124,7 +123,6 @@ export const useRenderLayout = () => { <ElScrollbar v-loading={pageLoading.value} class={[ - 'v-content', { '!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]': fixedHeader.value && tagsView.value @@ -163,11 +161,10 @@ export const useRenderLayout = () => { <Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu> <ToolHeader></ToolHeader> </div> - <div class="v-app-right h-full w-full"> + <div class="v-content h-full w-full"> <ElScrollbar v-loading={pageLoading.value} class={[ - 'v-content', { 'mt-[var(--tags-view-height)]': fixedHeader.value } @@ -205,7 +202,7 @@ export const useRenderLayout = () => { {/* <Menu class="!h-full"></Menu> */} <div class={[ - 'v-app-right', + 'v-content', 'h-[100%]', { 'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]': @@ -219,7 +216,6 @@ export const useRenderLayout = () => { <ElScrollbar v-loading={pageLoading.value} class={[ - 'v-content', { '!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]': fixedHeader.value && tagsView.value diff --git a/src/locales/en.ts b/src/locales/en.ts index 17e551d..be4af66 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -69,7 +69,9 @@ export default { menu11: 'Menu1-1', menu111: 'Menu1-1-1', menu12: 'Menu1-2', - menu2: 'Menu2' + menu2: 'Menu2', + dashboard: 'Dashboard', + analysis: 'Analysis' }, formDemo: { input: 'Input', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index f18940f..0e50ba0 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -69,7 +69,9 @@ export default { menu11: '菜单1-1', menu111: '菜单1-1-1', menu12: '菜单1-2', - menu2: '菜单2' + menu2: '菜单2', + dashboard: '首页', + analysis: '分析页' }, formDemo: { input: '输入框', diff --git a/src/permission.ts b/src/permission.ts index 7d1b18a..f9ef5d3 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -38,7 +38,7 @@ router.beforeEach(async (to, from, next) => { const redirect = decodeURIComponent(redirectPath as string) const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } permissionStore.setIsAddRouters(true) - next(nextData) + next(to.path === '/' ? { path: permissionStore.addRouters[0]?.path as string } : nextData) } } else { if (whiteList.indexOf(to.path) !== -1) { diff --git a/src/plugins/echarts/index.ts b/src/plugins/echarts/index.ts new file mode 100644 index 0000000..54bc668 --- /dev/null +++ b/src/plugins/echarts/index.ts @@ -0,0 +1,33 @@ +import * as echarts from 'echarts/core' + +import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart } from 'echarts/charts' + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent +} from 'echarts/components' + +import { CanvasRenderer } from 'echarts/renderers' + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + CanvasRenderer, + PictorialBarChart +]) + +export default echarts diff --git a/src/router/index.ts b/src/router/index.ts index 2b6be16..4e371b2 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -37,6 +37,29 @@ export const constantRouterMap: AppRouteRecordRaw[] = [ ] export const asyncRouterMap: AppRouteRecordRaw[] = [ + { + path: '/dashboard', + component: Layout, + redirect: '/dashboard/analysis', + name: 'Dashboard', + meta: { + title: t('router.dashboard'), + icon: 'ant-design:dashboard-filled', + alwaysShow: true + }, + children: [ + { + path: 'analysis', + component: () => import('@/views/Dashboard/Analysis.vue'), + name: 'Analysis', + meta: { + title: t('router.analysis'), + noCache: true, + affix: true + } + } + ] + }, { path: '/level', component: Layout, diff --git a/src/views/Dashboard/Analysis.vue b/src/views/Dashboard/Analysis.vue new file mode 100644 index 0000000..4dde1e6 --- /dev/null +++ b/src/views/Dashboard/Analysis.vue @@ -0,0 +1,7 @@ +<script setup lang="ts"> +// import { ElRow, ElCol } from 'element-plus' +</script> + +<template> + <div>dddd</div> +</template> diff --git a/src/views/Dashboard/echarts-data.ts b/src/views/Dashboard/echarts-data.ts new file mode 100644 index 0000000..e69de29