feat(projects): 引入echarts替换antvG2plot
This commit is contained in:
parent
14c145eef1
commit
e7ad08685e
2
.gitignore
vendored
2
.gitignore
vendored
@ -28,3 +28,5 @@ stats.html
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
/src/typings/components.d.ts
|
||||||
|
@ -50,7 +50,7 @@ Soybean Admin 是一个基于 Vue3、Vite、TypeScript、Naive UI 的免费中
|
|||||||
|
|
||||||
## 开发计划
|
## 开发计划
|
||||||
|
|
||||||
- [ ] 引入ECharts替换AntV G2Plot
|
- [x] 引入ECharts替换AntV G2Plot
|
||||||
- [ ] 多页签:同一页面支持多个Tab(应用场景:不同query参数的详情页面在不同tab展示)
|
- [ ] 多页签:同一页面支持多个Tab(应用场景:不同query参数的详情页面在不同tab展示)
|
||||||
- [ ] 最近功能的有关文档更新
|
- [ ] 最近功能的有关文档更新
|
||||||
- [ ] 性能优化(优化递归函数)
|
- [ ] 性能优化(优化递归函数)
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/g2plot": "^2.4.16",
|
|
||||||
"@better-scroll/core": "^2.4.2",
|
"@better-scroll/core": "^2.4.2",
|
||||||
"@soybeanjs/vue-admin-layout": "^1.0.3",
|
"@soybeanjs/vue-admin-layout": "^1.0.3",
|
||||||
"@soybeanjs/vue-admin-tab": "^1.0.1",
|
"@soybeanjs/vue-admin-tab": "^1.0.1",
|
||||||
@ -36,6 +35,7 @@
|
|||||||
"colord": "^2.9.2",
|
"colord": "^2.9.2",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "^1.11.1",
|
"dayjs": "^1.11.1",
|
||||||
|
"echarts": "^5.3.2",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"naive-ui": "^2.28.2",
|
"naive-ui": "^2.28.2",
|
||||||
|
622
pnpm-lock.yaml
622
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,8 @@
|
|||||||
|
import useEcharts from './useEcharts';
|
||||||
import useCountDown from './useCountDown';
|
import useCountDown from './useCountDown';
|
||||||
import useSmsCode from './useSmsCode';
|
import useSmsCode from './useSmsCode';
|
||||||
import useImageVerify from './useImageVerify';
|
import useImageVerify from './useImageVerify';
|
||||||
|
|
||||||
export { useCountDown, useSmsCode, useImageVerify };
|
export { useEcharts, useCountDown, useSmsCode, useImageVerify };
|
||||||
|
|
||||||
|
export * from './useEcharts';
|
||||||
|
136
src/hooks/business/useEcharts.ts
Normal file
136
src/hooks/business/useEcharts.ts
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import { ref, watch, nextTick, onUnmounted, computed } from 'vue';
|
||||||
|
import type { Ref, ComputedRef } from 'vue';
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { BarChart, LineChart, PieChart } from 'echarts/charts';
|
||||||
|
import type { BarSeriesOption, LineSeriesOption, PieSeriesOption } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
LegendComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
ToolboxComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
import type {
|
||||||
|
TitleComponentOption,
|
||||||
|
LegendComponentOption,
|
||||||
|
TooltipComponentOption,
|
||||||
|
GridComponentOption,
|
||||||
|
ToolboxComponentOption,
|
||||||
|
DatasetComponentOption
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import { useElementSize } from '@vueuse/core';
|
||||||
|
|
||||||
|
export type ECOption = echarts.ComposeOption<
|
||||||
|
| BarSeriesOption
|
||||||
|
| LineSeriesOption
|
||||||
|
| PieSeriesOption
|
||||||
|
| TitleComponentOption
|
||||||
|
| LegendComponentOption
|
||||||
|
| TooltipComponentOption
|
||||||
|
| GridComponentOption
|
||||||
|
| ToolboxComponentOption
|
||||||
|
| DatasetComponentOption
|
||||||
|
>;
|
||||||
|
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
LegendComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
ToolboxComponent,
|
||||||
|
BarChart,
|
||||||
|
LineChart,
|
||||||
|
PieChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Echarts hooks函数
|
||||||
|
* @param options - 图表配置
|
||||||
|
* @param renderFun - 图表函数(例如:图表监听函数)
|
||||||
|
*/
|
||||||
|
export default function useEcharts(
|
||||||
|
options: Ref<ECOption> | ComputedRef<ECOption>,
|
||||||
|
darkMode?: ComputedRef<boolean>,
|
||||||
|
renderFun?: (chartInstance: echarts.ECharts) => void
|
||||||
|
) {
|
||||||
|
let chart: echarts.ECharts | null = null;
|
||||||
|
const domRef = ref<HTMLElement>();
|
||||||
|
const initialSize = { width: 0, height: 0 };
|
||||||
|
const { width, height } = useElementSize(domRef, initialSize);
|
||||||
|
|
||||||
|
function canRender() {
|
||||||
|
return initialSize.width > 0 && initialSize.height > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRendered() {
|
||||||
|
return Boolean(domRef.value && chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(updateOptions: ECOption) {
|
||||||
|
if (isRendered()) {
|
||||||
|
chart!.setOption({ ...updateOptions, backgroundColor: 'transparent' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function render() {
|
||||||
|
if (domRef.value) {
|
||||||
|
const theme = darkMode?.value ? 'dark' : 'light';
|
||||||
|
await nextTick();
|
||||||
|
chart = echarts.init(domRef.value, theme);
|
||||||
|
if (renderFun) {
|
||||||
|
renderFun(chart);
|
||||||
|
}
|
||||||
|
update(options.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resize() {
|
||||||
|
chart?.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroy() {
|
||||||
|
chart?.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTheme() {
|
||||||
|
destroy();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([width, height], ([newWidth, newHeight]) => {
|
||||||
|
initialSize.width = newWidth;
|
||||||
|
initialSize.height = newHeight;
|
||||||
|
if (canRender()) {
|
||||||
|
if (!isRendered()) {
|
||||||
|
render();
|
||||||
|
} else {
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options, newValue => {
|
||||||
|
update(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(darkMode || computed(() => false), () => {
|
||||||
|
updateTheme();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
domRef
|
||||||
|
};
|
||||||
|
}
|
105
src/typings/components.d.ts
vendored
105
src/typings/components.d.ts
vendored
@ -1,105 +0,0 @@
|
|||||||
// generated by unplugin-vue-components
|
|
||||||
// We suggest you to commit this file into source control
|
|
||||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
|
||||||
import '@vue/runtime-core'
|
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
export interface GlobalComponents {
|
|
||||||
BetterScroll: typeof import('./../components/custom/BetterScroll.vue')['default']
|
|
||||||
CountTo: typeof import('./../components/custom/CountTo.vue')['default']
|
|
||||||
DarkModeContainer: typeof import('./../components/common/DarkModeContainer.vue')['default']
|
|
||||||
DarkModeSwitch: typeof import('./../components/common/DarkModeSwitch.vue')['default']
|
|
||||||
GithubLink: typeof import('./../components/custom/GithubLink.vue')['default']
|
|
||||||
HoverContainer: typeof import('./../components/common/HoverContainer.vue')['default']
|
|
||||||
IconAntDesignCloseOutlined: typeof import('~icons/ant-design/close-outlined')['default']
|
|
||||||
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
|
||||||
IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
|
|
||||||
IconCustomActivity: typeof import('~icons/custom/activity')['default']
|
|
||||||
IconCustomAvatar: typeof import('~icons/custom/avatar')['default']
|
|
||||||
IconCustomBanner: typeof import('~icons/custom/banner')['default']
|
|
||||||
IconCustomCast: typeof import('~icons/custom/cast')['default']
|
|
||||||
IconCustomEmptyData: typeof import('~icons/custom/empty-data')['default']
|
|
||||||
IconCustomLogo: typeof import('~icons/custom/logo')['default']
|
|
||||||
IconCustomLogoFill: typeof import('~icons/custom/logo-fill')['default']
|
|
||||||
IconCustomNetworkError: typeof import('~icons/custom/network-error')['default']
|
|
||||||
IconCustomNoPermission: typeof import('~icons/custom/no-permission')['default']
|
|
||||||
IconCustomNotFound: typeof import('~icons/custom/not-found')['default']
|
|
||||||
IconCustomServiceError: typeof import('~icons/custom/service-error')['default']
|
|
||||||
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
|
||||||
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
|
||||||
IconIcBaselineDoNotDisturb: typeof import('~icons/ic/baseline-do-not-disturb')['default']
|
|
||||||
IconIcOutlineCheck: typeof import('~icons/ic/outline-check')['default']
|
|
||||||
IconIcRoundHdrAuto: typeof import('~icons/ic/round-hdr-auto')['default']
|
|
||||||
IconLineMdMenuFoldLeft: typeof import('~icons/line-md/menu-fold-left')['default']
|
|
||||||
IconLineMdMenuUnfoldLeft: typeof import('~icons/line-md/menu-unfold-left')['default']
|
|
||||||
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
|
||||||
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
|
||||||
IconMdiClose: typeof import('~icons/mdi/close')['default']
|
|
||||||
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
|
||||||
IconMdiMoonWaningCrescent: typeof import('~icons/mdi/moon-waning-crescent')['default']
|
|
||||||
IconMdiPin: typeof import('~icons/mdi/pin')['default']
|
|
||||||
IconMdiPinOff: typeof import('~icons/mdi/pin-off')['default']
|
|
||||||
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
|
|
||||||
IconMdiWechat: typeof import('~icons/mdi/wechat')['default']
|
|
||||||
IconMdiWhiteBalanceSunny: typeof import('~icons/mdi/white-balance-sunny')['default']
|
|
||||||
IconPhCaretDoubleLeftBold: typeof import('~icons/ph/caret-double-left-bold')['default']
|
|
||||||
IconPhCaretDoubleRightBold: typeof import('~icons/ph/caret-double-right-bold')['default']
|
|
||||||
IconSelect: typeof import('./../components/custom/IconSelect.vue')['default']
|
|
||||||
IconUilSearch: typeof import('~icons/uil/search')['default']
|
|
||||||
ImageVerify: typeof import('./../components/custom/ImageVerify.vue')['default']
|
|
||||||
LoadingEmptyWrapper: typeof import('./../components/business/LoadingEmptyWrapper.vue')['default']
|
|
||||||
LoginAgreement: typeof import('./../components/business/LoginAgreement.vue')['default']
|
|
||||||
NaiveProvider: typeof import('./../components/common/NaiveProvider.vue')['default']
|
|
||||||
NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
|
|
||||||
NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
|
|
||||||
NButton: typeof import('naive-ui')['NButton']
|
|
||||||
NCard: typeof import('naive-ui')['NCard']
|
|
||||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
|
||||||
NColorPicker: typeof import('naive-ui')['NColorPicker']
|
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
|
||||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
|
||||||
NDescriptions: typeof import('naive-ui')['NDescriptions']
|
|
||||||
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
|
|
||||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
|
||||||
NDivider: typeof import('naive-ui')['NDivider']
|
|
||||||
NDrawer: typeof import('naive-ui')['NDrawer']
|
|
||||||
NDrawerContent: typeof import('naive-ui')['NDrawerContent']
|
|
||||||
NDropdown: typeof import('naive-ui')['NDropdown']
|
|
||||||
NEmpty: typeof import('naive-ui')['NEmpty']
|
|
||||||
NForm: typeof import('naive-ui')['NForm']
|
|
||||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
|
||||||
NGradientText: typeof import('naive-ui')['NGradientText']
|
|
||||||
NGrid: typeof import('naive-ui')['NGrid']
|
|
||||||
NGridItem: typeof import('naive-ui')['NGridItem']
|
|
||||||
NInput: typeof import('naive-ui')['NInput']
|
|
||||||
NInputGroup: typeof import('naive-ui')['NInputGroup']
|
|
||||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
|
||||||
NList: typeof import('naive-ui')['NList']
|
|
||||||
NListItem: typeof import('naive-ui')['NListItem']
|
|
||||||
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
|
|
||||||
NMenu: typeof import('naive-ui')['NMenu']
|
|
||||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
|
||||||
NModal: typeof import('naive-ui')['NModal']
|
|
||||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
|
||||||
NPopover: typeof import('naive-ui')['NPopover']
|
|
||||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
|
||||||
NSelect: typeof import('naive-ui')['NSelect']
|
|
||||||
NSpace: typeof import('naive-ui')['NSpace']
|
|
||||||
NSpin: typeof import('naive-ui')['NSpin']
|
|
||||||
NStatistic: typeof import('naive-ui')['NStatistic']
|
|
||||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
|
||||||
NTabPane: typeof import('naive-ui')['NTabPane']
|
|
||||||
NTabs: typeof import('naive-ui')['NTabs']
|
|
||||||
NTag: typeof import('naive-ui')['NTag']
|
|
||||||
NThing: typeof import('naive-ui')['NThing']
|
|
||||||
NTimeline: typeof import('naive-ui')['NTimeline']
|
|
||||||
NTimelineItem: typeof import('naive-ui')['NTimelineItem']
|
|
||||||
NTooltip: typeof import('naive-ui')['NTooltip']
|
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
|
||||||
SystemLogo: typeof import('./../components/common/SystemLogo.vue')['default']
|
|
||||||
WebSiteLink: typeof import('./../components/custom/WebSiteLink.vue')['default']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {}
|
|
@ -1,152 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"date": "2021/10/1",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 4623
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/1",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2208
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/2",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 6145
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/2",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2016
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/3",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 508
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/3",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2916
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/4",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 6268
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/4",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 4512
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/5",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 6411
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/5",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 8281
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/6",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 1890
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/6",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2008
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/7",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 4251
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/7",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 1963
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/8",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 2978
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/8",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2367
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/9",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 3880
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/9",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2956
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/10",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 3606
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/10",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 678
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/11",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 4311
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/11",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 3188
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/12",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 4116
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/12",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 3491
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/13",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 6419
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/13",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 2852
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/14",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 1643
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/14",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 4788
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/15",
|
|
||||||
"type": "下载量",
|
|
||||||
"value": 445
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "2021/10/15",
|
|
||||||
"type": "注册数",
|
|
||||||
"value": 4319
|
|
||||||
}
|
|
||||||
]
|
|
@ -31,99 +31,159 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { Line, Pie } from '@antv/g2plot';
|
import { useThemeStore } from '@/store';
|
||||||
import data from './data.json';
|
import { useEcharts, type ECOption } from '@/hooks';
|
||||||
|
|
||||||
const lineRef = ref<HTMLElement>();
|
const theme = useThemeStore();
|
||||||
const line = ref<Line>();
|
|
||||||
const pieRef = ref<HTMLElement>();
|
|
||||||
const pie = ref<Pie>();
|
|
||||||
|
|
||||||
function renderLineChart() {
|
const darkMode = computed(() => theme.darkMode);
|
||||||
if (!lineRef.value) return;
|
|
||||||
line.value = new Line(lineRef.value, {
|
const { domRef: lineRef } = useEcharts(
|
||||||
data,
|
ref<ECOption>({
|
||||||
autoFit: true,
|
tooltip: {
|
||||||
xField: 'date',
|
trigger: 'axis',
|
||||||
yField: 'value',
|
axisPointer: {
|
||||||
seriesField: 'type',
|
type: 'cross',
|
||||||
lineStyle: {
|
label: {
|
||||||
lineWidth: 4
|
backgroundColor: '#6a7985'
|
||||||
},
|
|
||||||
area: {
|
|
||||||
style: {
|
|
||||||
fill: 'l(270) 0:#ffffff 0.5:#7ec2f3 1:#1890ff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
smooth: true,
|
|
||||||
animation: {
|
|
||||||
appear: {
|
|
||||||
animation: 'wave-in',
|
|
||||||
duration: 2000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
line.value.render();
|
|
||||||
}
|
|
||||||
function renderPieChart() {
|
|
||||||
if (!pieRef.value) return;
|
|
||||||
const pieData = [
|
|
||||||
{ type: '学习', value: 20 },
|
|
||||||
{ type: '娱乐', value: 10 },
|
|
||||||
{ type: '工作', value: 30 },
|
|
||||||
{ type: '休息', value: 40 }
|
|
||||||
];
|
|
||||||
pie.value = new Pie(pieRef.value, {
|
|
||||||
appendPadding: 10,
|
|
||||||
data: pieData,
|
|
||||||
angleField: 'value',
|
|
||||||
colorField: 'type',
|
|
||||||
radius: 0.8,
|
|
||||||
innerRadius: 0.65,
|
|
||||||
meta: {
|
|
||||||
value: {
|
|
||||||
formatter: v => `${v}%`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
type: 'inner',
|
|
||||||
autoRotate: false,
|
|
||||||
formatter: ({ percent }) => `${(percent * 100).toFixed(0)}%`
|
|
||||||
},
|
|
||||||
statistic: undefined,
|
|
||||||
pieStyle: {
|
|
||||||
radius: [20]
|
|
||||||
},
|
|
||||||
color: ['#025DF4', '#DB6BCF', '#2498D1', '#FF745A', '#007E99', '#FFA8A8', '#2391FF'],
|
|
||||||
legend: {
|
|
||||||
position: 'bottom'
|
|
||||||
},
|
|
||||||
interactions: [
|
|
||||||
{ type: 'element-selected' },
|
|
||||||
{ type: 'element-active' },
|
|
||||||
{
|
|
||||||
type: 'pie-statistic-active',
|
|
||||||
cfg: {
|
|
||||||
start: [
|
|
||||||
{ trigger: 'element:mouseenter', action: 'pie-statistic:change' },
|
|
||||||
{ trigger: 'legend-item:mouseenter', action: 'pie-statistic:change' }
|
|
||||||
],
|
|
||||||
end: [
|
|
||||||
{ trigger: 'element:mouseleave', action: 'pie-statistic:reset' },
|
|
||||||
{ trigger: 'legend-item:mouseleave', action: 'pie-statistic:reset' }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['下载量', '注册数']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00', '24:00']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
color: '#8e9dff',
|
||||||
|
name: '下载量',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
stack: 'Total',
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
offset: 0.25,
|
||||||
|
color: '#8e9dff'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#fff'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [4623, 6145, 6268, 6411, 1890, 4251, 2978, 3880, 3606, 4311]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '#26deca',
|
||||||
|
name: '注册数',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
stack: 'Total',
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
offset: 0.25,
|
||||||
|
color: '#26deca'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#fff'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [2208, 2016, 2916, 4512, 8281, 2008, 1963, 2367, 2956, 678]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
});
|
}),
|
||||||
|
darkMode
|
||||||
|
);
|
||||||
|
|
||||||
pie.value.render();
|
const { domRef: pieRef } = useEcharts(
|
||||||
}
|
ref<ECOption>({
|
||||||
|
tooltip: {
|
||||||
onMounted(() => {
|
trigger: 'item'
|
||||||
renderLineChart();
|
},
|
||||||
renderPieChart();
|
legend: {
|
||||||
});
|
bottom: '1%',
|
||||||
|
left: 'center',
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
color: ['#5da8ff', '#8e9dff', '#fedc69', '#26deca'],
|
||||||
|
name: '时间安排',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['45%', '75%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 1
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: '12'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 20, name: '学习' },
|
||||||
|
{ value: 10, name: '娱乐' },
|
||||||
|
{ value: 30, name: '工作' },
|
||||||
|
{ value: 40, name: '休息' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
darkMode
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style></style>
|
<style></style>
|
||||||
|
Loading…
Reference in New Issue
Block a user