feat(component): Add CountTo component and Echart component
This commit is contained in:
parent
dad7330634
commit
e20fa76cad
|
@ -30,6 +30,8 @@
|
||||||
"@zxcvbn-ts/core": "^1.2.0",
|
"@zxcvbn-ts/core": "^1.2.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
|
"echarts": "^5.2.2",
|
||||||
|
"echarts-wordcloud": "^2.0.0",
|
||||||
"element-plus": "1.3.0-beta.5",
|
"element-plus": "1.3.0-beta.5",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
|
|
130
pnpm-lock.yaml
130
pnpm-lock.yaml
|
@ -21,6 +21,8 @@ specifiers:
|
||||||
autoprefixer: ^10.4.2
|
autoprefixer: ^10.4.2
|
||||||
axios: ^0.25.0
|
axios: ^0.25.0
|
||||||
commitizen: ^4.2.4
|
commitizen: ^4.2.4
|
||||||
|
echarts: ^5.2.2
|
||||||
|
echarts-wordcloud: ^2.0.0
|
||||||
element-plus: 1.3.0-beta.5
|
element-plus: 1.3.0-beta.5
|
||||||
eslint: ^8.7.0
|
eslint: ^8.7.0
|
||||||
eslint-config-prettier: ^8.3.0
|
eslint-config-prettier: ^8.3.0
|
||||||
|
@ -70,6 +72,8 @@ dependencies:
|
||||||
'@zxcvbn-ts/core': registry.npmmirror.com/@zxcvbn-ts/core/1.2.0
|
'@zxcvbn-ts/core': registry.npmmirror.com/@zxcvbn-ts/core/1.2.0
|
||||||
animate.css: registry.npmmirror.com/animate.css/4.1.1
|
animate.css: registry.npmmirror.com/animate.css/4.1.1
|
||||||
axios: registry.npmmirror.com/axios/0.25.0
|
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
|
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
|
lodash-es: registry.nlark.com/lodash-es/4.17.21
|
||||||
mockjs: registry.npmmirror.com/mockjs/1.1.0
|
mockjs: registry.npmmirror.com/mockjs/1.1.0
|
||||||
|
@ -350,38 +354,6 @@ packages:
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
dev: true
|
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:
|
registry.nlark.com/acorn-walk/8.2.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -1781,7 +1753,7 @@ packages:
|
||||||
{
|
{
|
||||||
integrity: sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc=,
|
integrity: sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc=,
|
||||||
registry: https://registry.npm.taobao.org/,
|
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
|
name: eslint-utils
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
|
@ -6244,6 +6216,19 @@ packages:
|
||||||
engines: { node: '>=10' }
|
engines: { node: '>=10' }
|
||||||
dev: true
|
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:
|
registry.npmmirror.com/@antfu/utils/0.3.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -8402,6 +8387,38 @@ packages:
|
||||||
through: registry.nlark.com/through/2.3.8
|
through: registry.nlark.com/through/2.3.8
|
||||||
dev: true
|
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:
|
registry.npmmirror.com/acorn/7.4.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -9378,6 +9395,36 @@ packages:
|
||||||
domhandler: registry.npmmirror.com/domhandler/4.3.0
|
domhandler: registry.npmmirror.com/domhandler/4.3.0
|
||||||
dev: true
|
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:
|
registry.npmmirror.com/electron-to-chromium/1.4.30:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -10035,7 +10082,7 @@ packages:
|
||||||
engines: { node: '>=6.0.0' }
|
engines: { node: '>=6.0.0' }
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: registry.npmmirror.com/acorn/7.4.1
|
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
|
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -10051,7 +10098,7 @@ packages:
|
||||||
engines: { node: ^10.12.0 || >=12.0.0 }
|
engines: { node: ^10.12.0 || >=12.0.0 }
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: registry.npmmirror.com/acorn/7.4.1
|
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
|
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -10067,7 +10114,7 @@ packages:
|
||||||
engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 }
|
engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 }
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: registry.npmmirror.com/acorn/8.7.0
|
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
|
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/3.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -12239,6 +12286,17 @@ packages:
|
||||||
version: 1.14.1
|
version: 1.14.1
|
||||||
dev: true
|
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:
|
registry.npmmirror.com/tslib/2.3.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>
|
|
@ -0,0 +1,3 @@
|
||||||
|
import Echart from './src/Echart.vue'
|
||||||
|
|
||||||
|
export { Echart }
|
|
@ -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>
|
|
@ -147,6 +147,7 @@ watch(
|
||||||
{
|
{
|
||||||
icon: 'ant-design:close-outlined',
|
icon: 'ant-design:close-outlined',
|
||||||
label: t('common.closeTab'),
|
label: t('common.closeTab'),
|
||||||
|
disabled: !!visitedViews?.length && selectedTag?.meta.affix,
|
||||||
command: () => {
|
command: () => {
|
||||||
closeSelectedTag(item)
|
closeSelectedTag(item)
|
||||||
}
|
}
|
||||||
|
@ -243,7 +244,8 @@ watch(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:close-outlined',
|
icon: 'ant-design:close-outlined',
|
||||||
label: t('common.closeTab')
|
label: t('common.closeTab'),
|
||||||
|
disabled: !!visitedViews?.length && selectedTag?.meta.affix
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
divided: true,
|
divided: true,
|
||||||
|
|
|
@ -49,7 +49,7 @@ export const useRenderLayout = () => {
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
'v-app-right',
|
'v-content',
|
||||||
'absolute top-0 h-[100%]',
|
'absolute top-0 h-[100%]',
|
||||||
{
|
{
|
||||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||||
|
@ -64,7 +64,6 @@ export const useRenderLayout = () => {
|
||||||
<ElScrollbar
|
<ElScrollbar
|
||||||
v-loading={pageLoading.value}
|
v-loading={pageLoading.value}
|
||||||
class={[
|
class={[
|
||||||
'v-content',
|
|
||||||
{
|
{
|
||||||
'!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]':
|
'!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]':
|
||||||
fixedHeader.value
|
fixedHeader.value
|
||||||
|
@ -110,7 +109,7 @@ export const useRenderLayout = () => {
|
||||||
<Menu class="!h-full"></Menu>
|
<Menu class="!h-full"></Menu>
|
||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
'v-app-right',
|
'v-content',
|
||||||
'h-[100%]',
|
'h-[100%]',
|
||||||
{
|
{
|
||||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||||
|
@ -124,7 +123,6 @@ export const useRenderLayout = () => {
|
||||||
<ElScrollbar
|
<ElScrollbar
|
||||||
v-loading={pageLoading.value}
|
v-loading={pageLoading.value}
|
||||||
class={[
|
class={[
|
||||||
'v-content',
|
|
||||||
{
|
{
|
||||||
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
||||||
fixedHeader.value && tagsView.value
|
fixedHeader.value && tagsView.value
|
||||||
|
@ -163,11 +161,10 @@ export const useRenderLayout = () => {
|
||||||
<Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu>
|
<Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu>
|
||||||
<ToolHeader></ToolHeader>
|
<ToolHeader></ToolHeader>
|
||||||
</div>
|
</div>
|
||||||
<div class="v-app-right h-full w-full">
|
<div class="v-content h-full w-full">
|
||||||
<ElScrollbar
|
<ElScrollbar
|
||||||
v-loading={pageLoading.value}
|
v-loading={pageLoading.value}
|
||||||
class={[
|
class={[
|
||||||
'v-content',
|
|
||||||
{
|
{
|
||||||
'mt-[var(--tags-view-height)]': fixedHeader.value
|
'mt-[var(--tags-view-height)]': fixedHeader.value
|
||||||
}
|
}
|
||||||
|
@ -205,7 +202,7 @@ export const useRenderLayout = () => {
|
||||||
{/* <Menu class="!h-full"></Menu> */}
|
{/* <Menu class="!h-full"></Menu> */}
|
||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
'v-app-right',
|
'v-content',
|
||||||
'h-[100%]',
|
'h-[100%]',
|
||||||
{
|
{
|
||||||
'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]':
|
'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]':
|
||||||
|
@ -219,7 +216,6 @@ export const useRenderLayout = () => {
|
||||||
<ElScrollbar
|
<ElScrollbar
|
||||||
v-loading={pageLoading.value}
|
v-loading={pageLoading.value}
|
||||||
class={[
|
class={[
|
||||||
'v-content',
|
|
||||||
{
|
{
|
||||||
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
||||||
fixedHeader.value && tagsView.value
|
fixedHeader.value && tagsView.value
|
||||||
|
|
|
@ -69,7 +69,9 @@ export default {
|
||||||
menu11: 'Menu1-1',
|
menu11: 'Menu1-1',
|
||||||
menu111: 'Menu1-1-1',
|
menu111: 'Menu1-1-1',
|
||||||
menu12: 'Menu1-2',
|
menu12: 'Menu1-2',
|
||||||
menu2: 'Menu2'
|
menu2: 'Menu2',
|
||||||
|
dashboard: 'Dashboard',
|
||||||
|
analysis: 'Analysis'
|
||||||
},
|
},
|
||||||
formDemo: {
|
formDemo: {
|
||||||
input: 'Input',
|
input: 'Input',
|
||||||
|
|
|
@ -69,7 +69,9 @@ export default {
|
||||||
menu11: '菜单1-1',
|
menu11: '菜单1-1',
|
||||||
menu111: '菜单1-1-1',
|
menu111: '菜单1-1-1',
|
||||||
menu12: '菜单1-2',
|
menu12: '菜单1-2',
|
||||||
menu2: '菜单2'
|
menu2: '菜单2',
|
||||||
|
dashboard: '首页',
|
||||||
|
analysis: '分析页'
|
||||||
},
|
},
|
||||||
formDemo: {
|
formDemo: {
|
||||||
input: '输入框',
|
input: '输入框',
|
||||||
|
|
|
@ -38,7 +38,7 @@ router.beforeEach(async (to, from, next) => {
|
||||||
const redirect = decodeURIComponent(redirectPath as string)
|
const redirect = decodeURIComponent(redirectPath as string)
|
||||||
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
|
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
|
||||||
permissionStore.setIsAddRouters(true)
|
permissionStore.setIsAddRouters(true)
|
||||||
next(nextData)
|
next(to.path === '/' ? { path: permissionStore.addRouters[0]?.path as string } : nextData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (whiteList.indexOf(to.path) !== -1) {
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
|
|
|
@ -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
|
|
@ -37,6 +37,29 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export const asyncRouterMap: 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',
|
path: '/level',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import { ElRow, ElCol } from 'element-plus'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>dddd</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue