Commit 21d0ed92dffd28f45c98afee547d25d9b40dde7f

Authored by vben
1 parent e9536b5b

feat(chart): add useEcharts and useApexChart demo

README.md
... ... @@ -68,7 +68,7 @@
68 68  
69 69 ### UI 框架
70 70  
71   -- [Tailwind CSS](https://tailwindcss.com/)
  71 +- [Tailwind CSS](https://tailwindcss.com/) - 2.0.0-beta.5 已删除
72 72 - [Ant Design Vue 2.0](https://2x.antdv.com/docs/vue/introduce-cn/)
73 73  
74 74 ### 图标
... ... @@ -215,11 +215,10 @@ yarn clean:lib # 删除node_modules,兼容window系统
215 215 - [x] 树组件
216 216 - [x] 图片预览组件
217 217 - [x] 表格组件
  218 +- [x] 图表库
218 219  
219 220 ## 正在开发的功能
220 221  
221   -- [ ] 全局错误处理
222   -- [ ] 图表库
223 222 - [ ] 数字动画
224 223 - [ ] 主题配置
225 224 - [ ] 富文本组件
... ... @@ -227,6 +226,7 @@ yarn clean:lib # 删除node_modules,兼容window系统
227 226 - [ ] 上传组件
228 227 - [ ] 数据导入导出
229 228 - [ ] 黑暗主题
  229 +- [ ] 全局错误处理
230 230 - [ ] 打包 Gzip
231 231 - [ ] 抽取生产环境配置文件
232 232 - [ ] 系统性能优化
... ... @@ -235,7 +235,7 @@ yarn clean:lib # 删除node_modules,兼容window系统
235 235  
236 236 ## 加入我们
237 237  
238   -`VUE-VBEN-ADMIN` 是完全开源免费的项目,旨在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群(项目刚起步,人数较少,有兴趣的可以加群一起讨论),使用问题欢迎在群内提问。
  238 +`Vue-Vben-Aadmin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群(项目刚起步,人数较少,有兴趣的可以加群一起讨论),使用问题欢迎在群内提问。
239 239  
240 240 - QQ 群 `569291866`
241 241  
... ...
package.json
... ... @@ -22,7 +22,9 @@
22 22 "dependencies": {
23 23 "@iconify/iconify": "^2.0.0-rc.1",
24 24 "ant-design-vue": "^2.0.0-beta.10",
  25 + "apexcharts": "^3.22.0",
25 26 "axios": "^0.20.0",
  27 + "echarts": "^4.9.0",
26 28 "lodash-es": "^4.17.15",
27 29 "mockjs": "^1.1.0",
28 30 "nprogress": "^0.2.0",
... ... @@ -41,6 +43,7 @@
41 43 "@iconify/json": "^1.1.233",
42 44 "@ls-lint/ls-lint": "^1.9.2",
43 45 "@purge-icons/generated": "^0.4.1",
  46 + "@types/echarts": "^4.8.0",
44 47 "@types/fs-extra": "^9.0.1",
45 48 "@types/inquirer": "^7.3.1",
46 49 "@types/koa-static": "^4.0.1",
... ...
src/hooks/web/useApexCharts.ts 0 → 100644
  1 +import { useTimeout } from '/@/hooks/core/useTimeout';
  2 +import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
  3 +import { ref, unref, Ref, nextTick } from 'vue';
  4 +
  5 +import ApexCharts from 'apexcharts';
  6 +
  7 +export function useApexCharts(elRef: Ref<HTMLDivElement>) {
  8 + const chartInstanceRef = ref<Nullable<ApexCharts>>(null);
  9 +
  10 + function setOptions(options: any) {
  11 + const el = unref(elRef);
  12 +
  13 + if (!el || !unref(el)) {
  14 + return;
  15 + }
  16 + chartInstanceRef.value = new ApexCharts(el, options);
  17 +
  18 + const chartInstance = unref(chartInstanceRef);
  19 +
  20 + nextTick(() => {
  21 + useTimeout(() => {
  22 + chartInstance && chartInstance.render();
  23 + }, 30);
  24 + });
  25 + }
  26 +
  27 + tryOnUnmounted(() => {
  28 + const chartInstance = unref(chartInstanceRef);
  29 + if (!chartInstance) {
  30 + return;
  31 + }
  32 + chartInstanceRef.value = null;
  33 + });
  34 + return {
  35 + setOptions,
  36 + };
  37 +}
... ...
src/hooks/web/useECharts.ts 0 → 100644
  1 +import { useTimeout } from '/@/hooks/core/useTimeout';
  2 +import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
  3 +import { ref, unref, Ref, nextTick } from 'vue';
  4 +import type { EChartOption, ECharts } from 'echarts';
  5 +import echarts from 'echarts';
  6 +import { useDebounce } from '/@/hooks/core/useDebounce';
  7 +import { useEvent } from '/@/hooks/event/useEvent';
  8 +import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
  9 +
  10 +export type { EChartOption, ECharts };
  11 +export function useECharts(
  12 + elRef: Ref<HTMLDivElement>,
  13 + theme: 'light' | 'dark' | 'default' = 'light'
  14 +) {
  15 + const chartInstanceRef = ref<Nullable<ECharts>>(null);
  16 + let resizeFn: Fn = resize;
  17 +
  18 + const [debounceResize] = useDebounce(resize, 200);
  19 + resizeFn = debounceResize;
  20 +
  21 + function init() {
  22 + const el = unref(elRef);
  23 +
  24 + if (!el || !unref(el)) {
  25 + return;
  26 + }
  27 + chartInstanceRef.value = echarts.init(el, theme);
  28 + useEvent({
  29 + el: window,
  30 + name: 'resize',
  31 + listener: resizeFn,
  32 + });
  33 + const { widthRef, screenEnum } = useBreakpoint();
  34 + if (unref(widthRef) <= screenEnum.MD) {
  35 + useTimeout(() => {
  36 + resizeFn();
  37 + }, 0);
  38 + }
  39 + }
  40 +
  41 + function setOptions(options: any, clear = true) {
  42 + // function setOptions(options: EChartOption, clear = true) {
  43 + let chartInstance = unref(chartInstanceRef);
  44 +
  45 + if (!chartInstance) {
  46 + init();
  47 + chartInstance = chartInstance = unref(chartInstanceRef);
  48 + if (!chartInstance) {
  49 + return;
  50 + }
  51 + }
  52 + clear && chartInstance.clear();
  53 + nextTick(() => {
  54 + useTimeout(() => {
  55 + chartInstance && chartInstance.setOption(options);
  56 + }, 30);
  57 + });
  58 + }
  59 +
  60 + function resize() {
  61 + const chartInstance = unref(chartInstanceRef);
  62 + if (!chartInstance) {
  63 + return;
  64 + }
  65 + chartInstance.resize();
  66 + }
  67 + tryOnUnmounted(() => {
  68 + const chartInstance = unref(chartInstanceRef);
  69 + if (!chartInstance) {
  70 + return;
  71 + }
  72 + chartInstance.dispose();
  73 + chartInstanceRef.value = null;
  74 + });
  75 + return {
  76 + setOptions,
  77 + echarts,
  78 + };
  79 +}
... ...
src/layouts/default/index.tsx
... ... @@ -15,7 +15,7 @@ import { useFullContent } from &#39;/@/hooks/web/useFullContent&#39;;
15 15 import LockPage from '/@/views/sys/lock/index.vue';
16 16  
17 17 import './index.less';
18   -import { userStore } from '/@/store/modules/user';
  18 +// import { userStore } from '/@/store/modules/user';
19 19 export default defineComponent({
20 20 name: 'DefaultLayout',
21 21 setup() {
... ... @@ -52,7 +52,7 @@ export default defineComponent({
52 52 // const { currentRoute } = useRouter();
53 53 onMounted(() => {
54 54 // Each refresh will request the latest user information, if you don’t need it, you can delete it
55   - userStore.getUserInfoAction({ userId: userStore.getUserInfoState.userId });
  55 + // userStore.getUserInfoAction({ userId: userStore.getUserInfoState.userId });
56 56 });
57 57  
58 58 // Get project configuration
... ...
src/router/menus/index.ts
... ... @@ -16,8 +16,17 @@ import iframeDemo from &#39;./modules/demo/iframe&#39;;
16 16 import compDemo from './modules/demo/comp';
17 17 import permissionDemo from './modules/demo/permission';
18 18 import featDemo from './modules/demo/feat';
  19 +import chartsDemo from './modules/demo/charts';
19 20  
20   -const menuModules = [dashboardDemo, featDemo, exceptionDemo, iframeDemo, compDemo, permissionDemo];
  21 +const menuModules = [
  22 + dashboardDemo,
  23 + featDemo,
  24 + exceptionDemo,
  25 + iframeDemo,
  26 + compDemo,
  27 + permissionDemo,
  28 + chartsDemo,
  29 +];
21 30  
22 31 // ===========================
23 32 // ==========Helper===========
... ...
src/router/menus/modules/demo/charts.ts 0 → 100644
  1 +import type { MenuModule } from '/@/router/types.d';
  2 +const menu: MenuModule = {
  3 + orderNo: 500,
  4 + menu: {
  5 + name: '图表',
  6 + path: '/charts',
  7 + children: [
  8 + {
  9 + path: '/echarts',
  10 + name: 'Echarts',
  11 + children: [
  12 + {
  13 + path: '/map',
  14 + name: '地图',
  15 + },
  16 + {
  17 + path: '/line',
  18 + name: '折线图',
  19 + },
  20 + {
  21 + path: '/pie',
  22 + name: '饼图',
  23 + },
  24 + ],
  25 + },
  26 + {
  27 + path: '/apexChart',
  28 + name: 'ApexChart',
  29 + },
  30 + ],
  31 + },
  32 +};
  33 +export default menu;
... ...
src/router/routes/index.ts
... ... @@ -11,6 +11,7 @@ import iframeDemo from &#39;./modules/demo/iframe&#39;;
11 11 import compDemo from './modules/demo/comp';
12 12 import permissionDemo from './modules/demo/permission';
13 13 import featDemo from './modules/demo/feat';
  14 +import chartsDemo from './modules/demo/charts';
14 15  
15 16 const routeModuleList: AppRouteModule[] = [
16 17 exceptionDemo,
... ... @@ -19,6 +20,7 @@ const routeModuleList: AppRouteModule[] = [
19 20 compDemo,
20 21 featDemo,
21 22 permissionDemo,
  23 + chartsDemo,
22 24 ];
23 25  
24 26 export const asyncRoutes = [
... ...
src/router/routes/modules/demo/charts.ts 0 → 100644
  1 +import type { AppRouteModule } from '/@/router/types';
  2 +
  3 +import { PAGE_LAYOUT_COMPONENT } from '/@/router/constant';
  4 +
  5 +export default {
  6 + layout: {
  7 + path: '/charts',
  8 + name: 'Charts',
  9 + component: PAGE_LAYOUT_COMPONENT,
  10 + redirect: '/charts/welcome',
  11 + meta: {
  12 + icon: 'ant-design:area-chart-outlined',
  13 + title: '图表库',
  14 + },
  15 + },
  16 +
  17 + routes: [
  18 + {
  19 + path: '/echarts',
  20 + name: 'Echarts',
  21 + meta: {
  22 + title: 'Echarts',
  23 + },
  24 + children: [
  25 + {
  26 + path: 'map',
  27 + name: 'Map',
  28 + component: () => import('/@/views/demo/echarts/Map.vue'),
  29 + meta: {
  30 + title: '地图',
  31 + },
  32 + },
  33 + {
  34 + path: 'line',
  35 + name: 'Line',
  36 + component: () => import('/@/views/demo/echarts/Line.vue'),
  37 + meta: {
  38 + title: '折线图',
  39 + },
  40 + },
  41 + {
  42 + path: 'pie',
  43 + name: 'Pie',
  44 + component: () => import('/@/views/demo/echarts/Pie.vue'),
  45 + meta: {
  46 + title: '饼图',
  47 + },
  48 + },
  49 + ],
  50 + },
  51 + {
  52 + path: '/apexChart',
  53 + name: 'ApexChart',
  54 + meta: {
  55 + title: 'ApexChart',
  56 + },
  57 + component: () => import('/@/views/demo/echarts/apex/index.vue'),
  58 + },
  59 + ],
  60 +} as AppRouteModule;
... ...
src/views/demo/echarts/Line.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4">
  3 + <div ref="chartRef" :style="{ height, width }" />
  4 + </div>
  5 +</template>
  6 +<script lang="ts">
  7 + import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
  8 +
  9 + import echarts from 'echarts';
  10 + import { useECharts } from '/@/hooks/web/useECharts';
  11 + import { getLineData } from './data';
  12 +
  13 + export default defineComponent({
  14 + props: {
  15 + width: {
  16 + type: String as PropType<string>,
  17 + default: '100%',
  18 + },
  19 + height: {
  20 + type: String as PropType<string>,
  21 + default: '80vh',
  22 + },
  23 + },
  24 + setup() {
  25 + const chartRef = ref<HTMLDivElement | null>(null);
  26 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  27 + const { barData, lineData, category } = getLineData;
  28 + onMounted(() => {
  29 + setOptions({
  30 + backgroundColor: '#0f375f',
  31 + tooltip: {
  32 + trigger: 'axis',
  33 + axisPointer: {
  34 + type: 'shadow',
  35 + label: {
  36 + show: true,
  37 + backgroundColor: '#333',
  38 + },
  39 + },
  40 + },
  41 + legend: {
  42 + data: ['line', 'bar'],
  43 + textStyle: {
  44 + color: '#ccc',
  45 + },
  46 + },
  47 + xAxis: {
  48 + data: category,
  49 + axisLine: {
  50 + lineStyle: {
  51 + color: '#ccc',
  52 + },
  53 + },
  54 + },
  55 + yAxis: {
  56 + splitLine: { show: false },
  57 + axisLine: {
  58 + lineStyle: {
  59 + color: '#ccc',
  60 + },
  61 + },
  62 + },
  63 + series: [
  64 + {
  65 + name: 'line',
  66 + type: 'line',
  67 + smooth: true,
  68 + showAllSymbol: true,
  69 + symbol: 'emptyCircle',
  70 + symbolSize: 15,
  71 + data: lineData,
  72 + },
  73 + {
  74 + name: 'bar',
  75 + type: 'bar',
  76 + barWidth: 10,
  77 + itemStyle: {
  78 + normal: {
  79 + barBorderRadius: 5,
  80 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  81 + { offset: 0, color: '#14c8d4' },
  82 + { offset: 1, color: '#43eec6' },
  83 + ]),
  84 + },
  85 + },
  86 + data: barData,
  87 + },
  88 + {
  89 + name: 'line',
  90 + type: 'bar',
  91 + barGap: '-100%',
  92 + barWidth: 10,
  93 + itemStyle: {
  94 + normal: {
  95 + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  96 + { offset: 0, color: 'rgba(20,200,212,0.5)' },
  97 + { offset: 0.2, color: 'rgba(20,200,212,0.2)' },
  98 + { offset: 1, color: 'rgba(20,200,212,0)' },
  99 + ]),
  100 + },
  101 + },
  102 + z: -12,
  103 + data: lineData,
  104 + },
  105 + {
  106 + name: 'dotted',
  107 + type: 'pictorialBar',
  108 + symbol: 'rect',
  109 + itemStyle: {
  110 + normal: {
  111 + color: '#0f375f',
  112 + },
  113 + },
  114 + symbolRepeat: true,
  115 + symbolSize: [12, 4],
  116 + symbolMargin: 1,
  117 + z: -10,
  118 + data: lineData,
  119 + },
  120 + ],
  121 + });
  122 + });
  123 + return { chartRef };
  124 + },
  125 + });
  126 +</script>
... ...
src/views/demo/echarts/Map.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4">
  3 + <div ref="chartRef" :style="{ height, width }" />
  4 + </div>
  5 +</template>
  6 +<script lang="ts">
  7 + import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
  8 +
  9 + import { useECharts } from '/@/hooks/web/useECharts';
  10 + import { mapData } from './data';
  11 +
  12 + import 'echarts/map/js/china';
  13 + export default defineComponent({
  14 + props: {
  15 + width: {
  16 + type: String as PropType<string>,
  17 + default: '100%',
  18 + },
  19 + height: {
  20 + type: String as PropType<string>,
  21 + default: '80vh',
  22 + },
  23 + },
  24 + setup() {
  25 + const chartRef = ref<HTMLDivElement | null>(null);
  26 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  27 +
  28 + onMounted(() => {
  29 + setOptions({
  30 + visualMap: {
  31 + min: 0,
  32 + max: 1000,
  33 + left: 'left',
  34 + top: 'bottom',
  35 + text: ['高', '低'],
  36 + calculable: false,
  37 + orient: 'horizontal',
  38 + inRange: {
  39 + color: ['#e0ffff', '#006edd'],
  40 + symbolSize: [30, 100],
  41 + },
  42 + },
  43 + tooltip: {
  44 + trigger: 'item',
  45 + backgroundColor: 'rgba(0, 0, 0, .6)',
  46 + textStyle: {
  47 + color: '#fff',
  48 + fontSize: 12,
  49 + },
  50 + },
  51 + series: [
  52 + {
  53 + name: 'iphone4',
  54 + type: 'map',
  55 + mapType: 'china',
  56 + label: {
  57 + normal: {
  58 + show: true,
  59 + textStyle: {
  60 + color: 'rgb(249, 249, 249)',
  61 + fontSize: 10,
  62 + },
  63 + },
  64 + emphasis: {
  65 + show: true,
  66 + textStyle: {
  67 + color: 'rgb(249, 249, 249)',
  68 + fontSize: 14,
  69 + },
  70 + },
  71 + },
  72 + itemStyle: {
  73 + normal: {
  74 + label: { show: true },
  75 + areaColor: '#2f82ce',
  76 + borderColor: '#0DAAC1',
  77 + },
  78 + emphasis: {
  79 + label: { show: true },
  80 + areaColor: '#2f82ce',
  81 + },
  82 + },
  83 + data: mapData,
  84 + },
  85 + ],
  86 + });
  87 + });
  88 + return { chartRef };
  89 + },
  90 + });
  91 +</script>
... ...
src/views/demo/echarts/Pie.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4">
  3 + <div ref="chartRef" :style="{ height, width }" />
  4 + </div>
  5 +</template>
  6 +<script lang="ts">
  7 + import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
  8 +
  9 + import { useECharts } from '/@/hooks/web/useECharts';
  10 +
  11 + export default defineComponent({
  12 + props: {
  13 + width: {
  14 + type: String as PropType<string>,
  15 + default: '100%',
  16 + },
  17 + height: {
  18 + type: String as PropType<string>,
  19 + default: '80vh',
  20 + },
  21 + },
  22 + setup() {
  23 + const chartRef = ref<HTMLDivElement | null>(null);
  24 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  25 + const dataAll = [389, 259, 262, 324, 232, 176, 196, 214, 133, 370];
  26 + const yAxisData = [
  27 + '原因1',
  28 + '原因2',
  29 + '原因3',
  30 + '原因4',
  31 + '原因5',
  32 + '原因6',
  33 + '原因7',
  34 + '原因8',
  35 + '原因9',
  36 + '原因10',
  37 + ];
  38 + onMounted(() => {
  39 + setOptions({
  40 + backgroundColor: '#0f375f',
  41 + title: [
  42 + {
  43 + text: '各渠道投诉占比',
  44 + x: '2%',
  45 + y: '1%',
  46 + textStyle: { color: '#fff', fontSize: 14 },
  47 + },
  48 + {
  49 + text: '投诉原因TOP10',
  50 + x: '40%',
  51 + y: '1%',
  52 + textStyle: { color: '#fff', fontSize: 14 },
  53 + },
  54 + {
  55 + text: '各级别投诉占比',
  56 + x: '2%',
  57 + y: '50%',
  58 + textStyle: { color: '#fff', fontSize: 14 },
  59 + },
  60 + ],
  61 + grid: [{ x: '50%', y: '7%', width: '45%', height: '90%' }],
  62 + tooltip: {
  63 + formatter: '{b} ({c})',
  64 + },
  65 + xAxis: [
  66 + {
  67 + gridIndex: 0,
  68 + axisTick: { show: false },
  69 + axisLabel: { show: false },
  70 + splitLine: { show: false },
  71 + axisLine: { show: false },
  72 + },
  73 + ],
  74 + yAxis: [
  75 + {
  76 + gridIndex: 0,
  77 + interval: 0,
  78 + data: yAxisData.reverse(),
  79 + axisTick: { show: false },
  80 + axisLabel: { show: true },
  81 + splitLine: { show: false },
  82 + axisLine: { show: true, lineStyle: { color: '#6173a3' } },
  83 + },
  84 + ],
  85 + series: [
  86 + {
  87 + name: '各渠道投诉占比',
  88 + type: 'pie',
  89 + radius: '30%',
  90 + center: ['22%', '25%'],
  91 + color: ['#86c9f4', '#4da8ec', '#3a91d2', '#005fa6', '#315f97'],
  92 + data: [
  93 + { value: 335, name: '客服电话' },
  94 + { value: 310, name: '奥迪官网' },
  95 + { value: 234, name: '媒体曝光' },
  96 + { value: 135, name: '质检总局' },
  97 + { value: 105, name: '其他' },
  98 + ],
  99 + labelLine: { normal: { show: false } },
  100 + itemStyle: {
  101 + normal: {
  102 + label: {
  103 + show: true,
  104 + formatter: '{b} \n ({d}%)',
  105 + textStyle: { color: '#B1B9D3' },
  106 + },
  107 + },
  108 + },
  109 + },
  110 + {
  111 + name: '各级别投诉占比',
  112 + type: 'pie',
  113 + radius: '30%',
  114 + center: ['22%', '75%'],
  115 + color: ['#86c9f4', '#4da8ec', '#3a91d2', '#005fa6', '#315f97'],
  116 + labelLine: { normal: { show: false } },
  117 + data: [
  118 + { value: 335, name: 'A级' },
  119 + { value: 310, name: 'B级' },
  120 + { value: 234, name: 'C级' },
  121 + { value: 135, name: 'D级' },
  122 + ],
  123 + itemStyle: {
  124 + normal: {
  125 + label: {
  126 + show: true,
  127 + formatter: '{b} \n ({d}%)',
  128 + textStyle: { color: '#B1B9D3' },
  129 + },
  130 + },
  131 + },
  132 + },
  133 + {
  134 + name: '投诉原因TOP10',
  135 + type: 'bar',
  136 + xAxisIndex: 0,
  137 + yAxisIndex: 0,
  138 + barWidth: '45%',
  139 + itemStyle: { normal: { color: '#86c9f4' } },
  140 + label: { normal: { show: true, position: 'right', textStyle: { color: '#9EA7C4' } } },
  141 + data: dataAll.sort(),
  142 + },
  143 + ],
  144 + });
  145 + });
  146 + return { chartRef };
  147 + },
  148 + });
  149 +</script>
... ...
src/views/demo/echarts/apex/Area.vue 0 → 100644
  1 +<template>
  2 + <div ref="chartRef" :style="{ width: '100%' }" />
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, ref, Ref, onMounted } from 'vue';
  6 +
  7 + import { useApexCharts } from '/@/hooks/web/useApexCharts';
  8 +
  9 + export default defineComponent({
  10 + setup() {
  11 + const chartRef = ref<HTMLDivElement | null>(null);
  12 + const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
  13 +
  14 + onMounted(() => {
  15 + setOptions({
  16 + series: [
  17 + {
  18 + name: 'series1',
  19 + data: [31, 40, 28, 51, 42, 109, 100],
  20 + },
  21 + {
  22 + name: 'series2',
  23 + data: [11, 32, 45, 32, 34, 52, 41],
  24 + },
  25 + ],
  26 + chart: {
  27 + height: 350,
  28 + type: 'area',
  29 + },
  30 + dataLabels: {
  31 + enabled: false,
  32 + },
  33 + stroke: {
  34 + curve: 'smooth',
  35 + },
  36 + xaxis: {
  37 + type: 'datetime',
  38 + categories: [
  39 + '2018-09-19T00:00:00.000Z',
  40 + '2018-09-19T01:30:00.000Z',
  41 + '2018-09-19T02:30:00.000Z',
  42 + '2018-09-19T03:30:00.000Z',
  43 + '2018-09-19T04:30:00.000Z',
  44 + '2018-09-19T05:30:00.000Z',
  45 + '2018-09-19T06:30:00.000Z',
  46 + ],
  47 + },
  48 + tooltip: {
  49 + x: {
  50 + format: 'dd/MM/yy HH:mm',
  51 + },
  52 + },
  53 + });
  54 + });
  55 + return { chartRef };
  56 + },
  57 + });
  58 +</script>
... ...
src/views/demo/echarts/apex/Bar.vue 0 → 100644
  1 +<template>
  2 + <div ref="chartRef" :style="{ width: '100%' }" />
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, ref, Ref, onMounted } from 'vue';
  6 +
  7 + import { useApexCharts } from '/@/hooks/web/useApexCharts';
  8 +
  9 + export default defineComponent({
  10 + setup() {
  11 + const chartRef = ref<HTMLDivElement | null>(null);
  12 + const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
  13 +
  14 + onMounted(() => {
  15 + setOptions({
  16 + series: [
  17 + {
  18 + data: [400, 430, 448, 470, 540, 580, 690, 1100, 1200, 1380],
  19 + },
  20 + ],
  21 + chart: {
  22 + type: 'bar',
  23 + height: 350,
  24 + },
  25 + plotOptions: {
  26 + bar: {
  27 + horizontal: true,
  28 + },
  29 + },
  30 + dataLabels: {
  31 + enabled: false,
  32 + },
  33 + xaxis: {
  34 + categories: [
  35 + 'South Korea',
  36 + 'Canada',
  37 + 'United Kingdom',
  38 + 'Netherlands',
  39 + 'Italy',
  40 + 'France',
  41 + 'Japan',
  42 + 'United States',
  43 + 'China',
  44 + 'Germany',
  45 + ],
  46 + },
  47 + });
  48 + });
  49 + return { chartRef };
  50 + },
  51 + });
  52 +</script>
... ...
src/views/demo/echarts/apex/Line.vue 0 → 100644
  1 +<template>
  2 + <div ref="chartRef" :style="{ width: '100%' }" />
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, ref, Ref, onMounted } from 'vue';
  6 +
  7 + import { useApexCharts } from '/@/hooks/web/useApexCharts';
  8 +
  9 + export default defineComponent({
  10 + setup() {
  11 + const chartRef = ref<HTMLDivElement | null>(null);
  12 + const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
  13 +
  14 + onMounted(() => {
  15 + setOptions({
  16 + series: [
  17 + {
  18 + name: 'Desktops',
  19 + data: [10, 41, 35, 51, 49, 62, 69, 91, 148],
  20 + },
  21 + ],
  22 + chart: {
  23 + height: 350,
  24 + type: 'line',
  25 + zoom: {
  26 + enabled: false,
  27 + },
  28 + },
  29 + dataLabels: {
  30 + enabled: false,
  31 + },
  32 + stroke: {
  33 + curve: 'straight',
  34 + },
  35 + title: {
  36 + text: 'Product Trends by Month',
  37 + align: 'left',
  38 + },
  39 + grid: {
  40 + row: {
  41 + colors: ['#f3f3f3', 'transparent'], // takes an array which will be repeated on columns
  42 + opacity: 0.5,
  43 + },
  44 + },
  45 + xaxis: {
  46 + categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
  47 + },
  48 + });
  49 + });
  50 + return { chartRef };
  51 + },
  52 + });
  53 +</script>
... ...
src/views/demo/echarts/apex/Mixed.vue 0 → 100644
  1 +<template>
  2 + <div ref="chartRef" :style="{ width: '100%' }" />
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, ref, Ref, onMounted } from 'vue';
  6 +
  7 + import { useApexCharts } from '/@/hooks/web/useApexCharts';
  8 +
  9 + export default defineComponent({
  10 + setup() {
  11 + const chartRef = ref<HTMLDivElement | null>(null);
  12 + const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
  13 +
  14 + onMounted(() => {
  15 + setOptions({
  16 + series: [
  17 + {
  18 + name: 'Income',
  19 + type: 'column',
  20 + data: [1.4, 2, 2.5, 1.5, 2.5, 2.8, 3.8, 4.6],
  21 + },
  22 + {
  23 + name: 'Cashflow',
  24 + type: 'column',
  25 + data: [1.1, 3, 3.1, 4, 4.1, 4.9, 6.5, 8.5],
  26 + },
  27 + {
  28 + name: 'Revenue',
  29 + type: 'line',
  30 + data: [20, 29, 37, 36, 44, 45, 50, 58],
  31 + },
  32 + ],
  33 + chart: {
  34 + height: 350,
  35 + type: 'line',
  36 + stacked: false,
  37 + },
  38 + dataLabels: {
  39 + enabled: false,
  40 + },
  41 + stroke: {
  42 + width: [1, 1, 4],
  43 + },
  44 + title: {
  45 + text: 'XYZ - Stock Analysis (2009 - 2016)',
  46 + align: 'left',
  47 + offsetX: 110,
  48 + },
  49 + xaxis: {
  50 + categories: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016],
  51 + },
  52 + yaxis: [
  53 + {
  54 + axisTicks: {
  55 + show: true,
  56 + },
  57 + axisBorder: {
  58 + show: true,
  59 + color: '#008FFB',
  60 + },
  61 + labels: {
  62 + style: {
  63 + colors: '#008FFB',
  64 + },
  65 + },
  66 + title: {
  67 + text: 'Income (thousand crores)',
  68 + style: {
  69 + color: '#008FFB',
  70 + },
  71 + },
  72 + tooltip: {
  73 + enabled: true,
  74 + },
  75 + },
  76 + {
  77 + seriesName: 'Income',
  78 + opposite: true,
  79 + axisTicks: {
  80 + show: true,
  81 + },
  82 + axisBorder: {
  83 + show: true,
  84 + color: '#00E396',
  85 + },
  86 + labels: {
  87 + style: {
  88 + colors: '#00E396',
  89 + },
  90 + },
  91 + title: {
  92 + text: 'Operating Cashflow (thousand crores)',
  93 + style: {
  94 + color: '#00E396',
  95 + },
  96 + },
  97 + },
  98 + {
  99 + seriesName: 'Revenue',
  100 + opposite: true,
  101 + axisTicks: {
  102 + show: true,
  103 + },
  104 + axisBorder: {
  105 + show: true,
  106 + color: '#FEB019',
  107 + },
  108 + labels: {
  109 + style: {
  110 + colors: '#FEB019',
  111 + },
  112 + },
  113 + title: {
  114 + text: 'Revenue (thousand crores)',
  115 + style: {
  116 + color: '#FEB019',
  117 + },
  118 + },
  119 + },
  120 + ],
  121 + tooltip: {
  122 + fixed: {
  123 + enabled: true,
  124 + position: 'topLeft', // topRight, topLeft, bottomRight, bottomLeft
  125 + offsetY: 30,
  126 + offsetX: 60,
  127 + },
  128 + },
  129 + legend: {
  130 + horizontalAlign: 'left',
  131 + offsetX: 40,
  132 + },
  133 + });
  134 + });
  135 + return { chartRef };
  136 + },
  137 + });
  138 +</script>
... ...
src/views/demo/echarts/apex/index.vue 0 → 100644
  1 +<template>
  2 + <div class="apex-demo p-4">
  3 + <div class="demo-box">
  4 + <Line />
  5 + </div>
  6 + <div class="demo-box">
  7 + <Bar />
  8 + </div>
  9 + <div class="demo-box">
  10 + <Area />
  11 + </div>
  12 + <div class="demo-box">
  13 + <Mixed />
  14 + </div>
  15 + </div>
  16 +</template>
  17 +<script>
  18 + import { defineComponent } from 'vue';
  19 +
  20 + import Line from './Line.vue';
  21 + import Bar from './Bar.vue';
  22 + import Area from './Area.vue';
  23 + import Mixed from './Mixed.vue';
  24 + export default defineComponent({
  25 + components: { Line, Bar, Area, Mixed },
  26 + setup() {},
  27 + });
  28 +</script>
  29 +<style lang="less" scoped>
  30 + .apex-demo {
  31 + display: flex;
  32 + flex-wrap: wrap;
  33 + justify-content: space-between;
  34 +
  35 + .demo-box {
  36 + width: 49%;
  37 + margin-bottom: 20px;
  38 + background: #fff;
  39 + border-radius: 10px;
  40 + }
  41 + }
  42 +</style>
... ...
src/views/demo/echarts/data.ts 0 → 100644
  1 +export const mapData: any = [
  2 + {
  3 + name: '北京',
  4 + value: Math.round(Math.random() * 1000),
  5 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  6 + },
  7 + {
  8 + name: '天津',
  9 + value: Math.round(Math.random() * 1000),
  10 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  11 + },
  12 + {
  13 + name: '上海',
  14 + value: Math.round(Math.random() * 1000),
  15 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  16 + },
  17 + {
  18 + name: '重庆',
  19 + value: Math.round(Math.random() * 1000),
  20 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  21 + },
  22 + {
  23 + name: '河北',
  24 + value: Math.round(Math.random() * 1000),
  25 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  26 + },
  27 + {
  28 + name: '河南',
  29 + value: Math.round(Math.random() * 1000),
  30 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  31 + },
  32 + {
  33 + name: '云南',
  34 + value: Math.round(Math.random() * 1000),
  35 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  36 + },
  37 + {
  38 + name: '辽宁',
  39 + value: Math.round(Math.random() * 1000),
  40 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  41 + },
  42 + {
  43 + name: '黑龙江',
  44 + value: Math.round(Math.random() * 1000),
  45 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  46 + },
  47 + {
  48 + name: '湖南',
  49 + value: Math.round(Math.random() * 1000),
  50 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  51 + },
  52 + {
  53 + name: '安徽',
  54 + value: Math.round(Math.random() * 1000),
  55 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  56 + },
  57 + {
  58 + name: '山东',
  59 + value: Math.round(Math.random() * 1000),
  60 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  61 + },
  62 + {
  63 + name: '新疆',
  64 + value: Math.round(Math.random() * 1000),
  65 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  66 + },
  67 + {
  68 + name: '江苏',
  69 + value: Math.round(Math.random() * 1000),
  70 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  71 + },
  72 + {
  73 + name: '浙江',
  74 + value: Math.round(Math.random() * 1000),
  75 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  76 + },
  77 + {
  78 + name: '江西',
  79 + value: Math.round(Math.random() * 1000),
  80 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  81 + },
  82 + {
  83 + name: '湖北',
  84 + value: Math.round(Math.random() * 1000),
  85 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  86 + },
  87 + {
  88 + name: '广西',
  89 + value: Math.round(Math.random() * 1000),
  90 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  91 + },
  92 + {
  93 + name: '甘肃',
  94 + value: Math.round(Math.random() * 1000),
  95 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  96 + },
  97 + {
  98 + name: '山西',
  99 + value: Math.round(Math.random() * 1000),
  100 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  101 + },
  102 + {
  103 + name: '内蒙古',
  104 + value: Math.round(Math.random() * 1000),
  105 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  106 + },
  107 + {
  108 + name: '陕西',
  109 + value: Math.round(Math.random() * 1000),
  110 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  111 + },
  112 + {
  113 + name: '吉林',
  114 + value: Math.round(Math.random() * 1000),
  115 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  116 + },
  117 + {
  118 + name: '福建',
  119 + value: Math.round(Math.random() * 1000),
  120 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  121 + },
  122 + {
  123 + name: '贵州',
  124 + value: Math.round(Math.random() * 1000),
  125 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  126 + },
  127 + {
  128 + name: '广东',
  129 + value: Math.round(Math.random() * 1000),
  130 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  131 + },
  132 + {
  133 + name: '青海',
  134 + value: Math.round(Math.random() * 1000),
  135 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  136 + },
  137 + {
  138 + name: '西藏',
  139 + value: Math.round(Math.random() * 1000),
  140 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  141 + },
  142 + {
  143 + name: '四川',
  144 + value: Math.round(Math.random() * 1000),
  145 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  146 + },
  147 + {
  148 + name: '宁夏',
  149 + value: Math.round(Math.random() * 1000),
  150 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  151 + },
  152 + {
  153 + name: '海南',
  154 + value: Math.round(Math.random() * 1000),
  155 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  156 + },
  157 + {
  158 + name: '台湾',
  159 + value: Math.round(Math.random() * 1000),
  160 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  161 + },
  162 + {
  163 + name: '香港',
  164 + value: Math.round(Math.random() * 1000),
  165 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  166 + },
  167 + {
  168 + name: '澳门',
  169 + value: Math.round(Math.random() * 1000),
  170 + tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
  171 + },
  172 +];
  173 +
  174 +export const getLineData = (() => {
  175 + const category: any[] = [];
  176 + let dottedBase = +new Date();
  177 + const lineData: any[] = [];
  178 + const barData: any[] = [];
  179 +
  180 + for (let i = 0; i < 20; i++) {
  181 + const date = new Date((dottedBase += 1000 * 3600 * 24));
  182 + category.push([date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-'));
  183 + const b = Math.random() * 200;
  184 + const d = Math.random() * 200;
  185 + barData.push(b);
  186 + lineData.push(d + b);
  187 + }
  188 + return { barData, category, lineData };
  189 +})();
... ...
vite.config.ts
... ... @@ -108,7 +108,13 @@ const viteConfig: UserConfig = {
108 108 // 配置Dep优化行为
109 109 // 会使用 rollup 对 包重新编译,将编译成符合 esm 模块规范的新的包放入 node_modules 下的 .
110 110 optimizeDeps: {
111   - include: ['ant-design-vue/es/locale/zh_CN', '@ant-design/icons-vue', 'moment/locale/zh-cn'],
  111 + include: [
  112 + 'echarts',
  113 + 'echarts/map/js/china',
  114 + 'ant-design-vue/es/locale/zh_CN',
  115 + '@ant-design/icons-vue',
  116 + 'moment/locale/zh-cn',
  117 + ],
112 118 },
113 119 // 本地跨域代理
114 120 proxy: createProxy(VITE_PROXY),
... ...
yarn.lock
... ... @@ -373,9 +373,9 @@
373 373 integrity sha512-ji5H04VjYtR4seIEgVVLPxg1KRhrFquOiyfPyLVS6vYPkuqV6bcWdssi05YSmf/OAzG4E7Qsg80/bOKyd5tYTw==
374 374  
375 375 "@iconify/json@^1.1.233":
376   - version "1.1.239"
377   - resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.239.tgz#bfef53a0a2e2fcd5549b421d551146254b1420b6"
378   - integrity sha512-6c3k6+MDZ23FrZsTLhx6sc5XKqz54yKGYeSYRVpcLOeou6SkK3WhCo/eCZvfTCR6dnuXrCk736/vrtgknWdhpA==
  376 + version "1.1.240"
  377 + resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.240.tgz#c7f2e822fc9e09994d3fd02a0c25684978a1b9fb"
  378 + integrity sha512-FNeTQ/N9c63Zn+LQyli2vY1C5Mub64fcwvAzrph0Vk+Qzv8dfPgcZtvfK08hukWKOEBUhSjfasQIfnZ5CynkmQ==
379 379  
380 380 "@ls-lint/ls-lint@^1.9.2":
381 381 version "1.9.2"
... ... @@ -569,6 +569,13 @@
569 569 "@types/keygrip" "*"
570 570 "@types/node" "*"
571 571  
  572 +"@types/echarts@^4.8.0":
  573 + version "4.8.0"
  574 + resolved "https://registry.npmjs.org/@types/echarts/-/echarts-4.8.0.tgz#60499909599ecb08f8e53cfe441e8933396fe0e9"
  575 + integrity sha512-U/BSemNukeU3Ly6e9Pi+b+Pb0Y/aDmbFAPkX1skDpZu19N2RH1fYc7cM1WpAGj6f8nWbzvRnhj5JHHdg7Y4SFw==
  576 + dependencies:
  577 + "@types/zrender" "*"
  578 +
572 579 "@types/estree@*", "@types/estree@0.0.45":
573 580 version "0.0.45"
574 581 resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
... ... @@ -685,9 +692,9 @@
685 692 "@types/lodash" "*"
686 693  
687 694 "@types/lodash@*":
688   - version "4.14.161"
689   - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz#a21ca0777dabc6e4f44f3d07f37b765f54188b18"
690   - integrity sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==
  695 + version "4.14.162"
  696 + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.162.tgz#65d78c397e0d883f44afbf1f7ba9867022411470"
  697 + integrity sha512-alvcho1kRUnnD1Gcl4J+hK0eencvzq9rmzvFPRmP5rPHx9VVsJj6bKLTATPVf9ktgv4ujzh7T+XWKp+jhuODig==
691 698  
692 699 "@types/lru-cache@^5.1.0":
693 700 version "5.1.0"
... ... @@ -794,6 +801,11 @@
794 801 resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
795 802 integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
796 803  
  804 +"@types/zrender@*":
  805 + version "4.0.0"
  806 + resolved "https://registry.npmjs.org/@types/zrender/-/zrender-4.0.0.tgz#a6806f12ec4eccaaebd9b0d816f049aca6188fbd"
  807 + integrity sha512-s89GOIeKFiod2KSqHkfd2rzx+T2DVu7ihZCBEBnhFrzvQPUmzvDSBot9Fi1DfMQm9Odg+rTqoMGC38RvrwJK2w==
  808 +
797 809 "@types/zxcvbn@^4.4.0":
798 810 version "4.4.0"
799 811 resolved "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.0.tgz#fbc1d941cc6d9d37d18405c513ba6b294f89b609"
... ... @@ -994,9 +1006,9 @@ aggregate-error@^3.0.0:
994 1006 indent-string "^4.0.0"
995 1007  
996 1008 ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4:
997   - version "6.12.5"
998   - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
999   - integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
  1009 + version "6.12.6"
  1010 + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
  1011 + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
1000 1012 dependencies:
1001 1013 fast-deep-equal "^3.1.1"
1002 1014 fast-json-stable-stringify "^2.0.0"
... ... @@ -1095,6 +1107,18 @@ anymatch@~3.1.1:
1095 1107 normalize-path "^3.0.0"
1096 1108 picomatch "^2.0.4"
1097 1109  
  1110 +apexcharts@^3.22.0:
  1111 + version "3.22.0"
  1112 + resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.22.0.tgz#df6f1030d0d5bba605069907102d2c261afe97cb"
  1113 + integrity sha512-DDh2eXnAEA8GoKU/hdicOaS2jzGehXwv8Bj1djYYudkeQzEdglFoWsVyIxff+Ds7+aUtVAJzd/9ythZuyyIbXQ==
  1114 + dependencies:
  1115 + svg.draggable.js "^2.2.2"
  1116 + svg.easing.js "^2.0.0"
  1117 + svg.filter.js "^2.0.2"
  1118 + svg.pathmorphing.js "^0.1.3"
  1119 + svg.resize.js "^1.4.3"
  1120 + svg.select.js "^3.0.1"
  1121 +
1098 1122 arg@^4.1.0:
1099 1123 version "4.1.3"
1100 1124 resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
... ... @@ -1445,9 +1469,9 @@ camelcase@^5.0.0, camelcase@^5.3.1:
1445 1469 integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
1446 1470  
1447 1471 caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135:
1448   - version "1.0.30001146"
1449   - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001146.tgz#c61fcb1474520c1462913689201fb292ba6f447c"
1450   - integrity sha512-VAy5RHDfTJhpxnDdp2n40GPPLp3KqNrXz1QqFv4J64HvArKs8nuNMOWkB3ICOaBTU/Aj4rYAo/ytdQDDFF/Pug==
  1472 + version "1.0.30001147"
  1473 + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001147.tgz#84d27e5b691a8da66e16887b34c78dacf3935f00"
  1474 + integrity sha512-CPyN875geYk46eIqPl5jlmotCr5YZC2KxIVfb4z0FrNfLxPM+MyodWD2irJGDG8vUUE1fmg3De9vt8uaC6Nf6w==
1451 1475  
1452 1476 ccount@^1.0.0:
1453 1477 version "1.0.5"
... ... @@ -2292,6 +2316,13 @@ duplexer@0.1.1:
2292 2316 resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
2293 2317 integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
2294 2318  
  2319 +echarts@^4.9.0:
  2320 + version "4.9.0"
  2321 + resolved "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz#a9b9baa03f03a2a731e6340c55befb57a9e1347d"
  2322 + integrity sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==
  2323 + dependencies:
  2324 + zrender "4.3.2"
  2325 +
2295 2326 ee-first@1.1.1:
2296 2327 version "1.1.1"
2297 2328 resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
... ... @@ -2371,9 +2402,9 @@ esbuild@^0.6.10:
2371 2402 integrity sha512-InRdL/Q96pUucPqovJzvuLhquZr6jOn81FDVwFjCKz1rYKIm9OdOC+7Fs4vr6x48vKBl5LzKgtjU39BUpO636A==
2372 2403  
2373 2404 esbuild@^0.7.1:
2374   - version "0.7.13"
2375   - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.13.tgz#ca614002e70814d548dd3243eb3ccc5d93833112"
2376   - integrity sha512-IHBqE0blYhBw3fSgaQOHI1hdxq5OJgzdU/Tg0FPIZyag6eHCB5I8wirz1Oyse7W+TwCcFeCxMNLhdyjzdFACcw==
  2405 + version "0.7.14"
  2406 + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.14.tgz#9de555e75669187c2315317fbf489b229b1a4cbb"
  2407 + integrity sha512-w2CEVeRcUhCGYMHnNNwb8q+9w42scL7RcNzJm85gZVzNBE3AF0sLq5YP/IdaTBJIFBphIKG3bGbwRH+zsgH/ig==
2377 2408  
2378 2409 escalade@^3.1.0:
2379 2410 version "3.1.0"
... ... @@ -6297,6 +6328,61 @@ svg-tags@^1.0.0:
6297 6328 resolved "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
6298 6329 integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
6299 6330  
  6331 +svg.draggable.js@^2.2.2:
  6332 + version "2.2.2"
  6333 + resolved "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz#c514a2f1405efb6f0263e7958f5b68fce50603ba"
  6334 + integrity sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==
  6335 + dependencies:
  6336 + svg.js "^2.0.1"
  6337 +
  6338 +svg.easing.js@^2.0.0:
  6339 + version "2.0.0"
  6340 + resolved "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz#8aa9946b0a8e27857a5c40a10eba4091e5691f12"
  6341 + integrity sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI=
  6342 + dependencies:
  6343 + svg.js ">=2.3.x"
  6344 +
  6345 +svg.filter.js@^2.0.2:
  6346 + version "2.0.2"
  6347 + resolved "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz#91008e151389dd9230779fcbe6e2c9a362d1c203"
  6348 + integrity sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM=
  6349 + dependencies:
  6350 + svg.js "^2.2.5"
  6351 +
  6352 +svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5:
  6353 + version "2.7.1"
  6354 + resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz#eb977ed4737001eab859949b4a398ee1bb79948d"
  6355 + integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
  6356 +
  6357 +svg.pathmorphing.js@^0.1.3:
  6358 + version "0.1.3"
  6359 + resolved "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz#c25718a1cc7c36e852ecabc380e758ac09bb2b65"
  6360 + integrity sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==
  6361 + dependencies:
  6362 + svg.js "^2.4.0"
  6363 +
  6364 +svg.resize.js@^1.4.3:
  6365 + version "1.4.3"
  6366 + resolved "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz#885abd248e0cd205b36b973c4b578b9a36f23332"
  6367 + integrity sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==
  6368 + dependencies:
  6369 + svg.js "^2.6.5"
  6370 + svg.select.js "^2.1.2"
  6371 +
  6372 +svg.select.js@^2.1.2:
  6373 + version "2.1.2"
  6374 + resolved "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz#e41ce13b1acff43a7441f9f8be87a2319c87be73"
  6375 + integrity sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==
  6376 + dependencies:
  6377 + svg.js "^2.2.5"
  6378 +
  6379 +svg.select.js@^3.0.1:
  6380 + version "3.0.1"
  6381 + resolved "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz#a4198e359f3825739226415f82176a90ea5cc917"
  6382 + integrity sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==
  6383 + dependencies:
  6384 + svg.js "^2.6.5"
  6385 +
6300 6386 table@^5.2.3:
6301 6387 version "5.4.6"
6302 6388 resolved "https://registry.npmjs.org/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
... ... @@ -7024,6 +7110,11 @@ yn@3.1.1:
7024 7110 resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
7025 7111 integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
7026 7112  
  7113 +zrender@4.3.2:
  7114 + version "4.3.2"
  7115 + resolved "https://registry.npmjs.org/zrender/-/zrender-4.3.2.tgz#ec7432f9415c82c73584b6b7b8c47e1b016209c6"
  7116 + integrity sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==
  7117 +
7027 7118 zxcvbn@^4.4.2:
7028 7119 version "4.4.2"
7029 7120 resolved "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"
... ...