From 6106a8fc5ca9e30d63f72de07ade7f5b9379ea9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=94=E8=B7=91=E7=9A=84=E9=9D=A2=E6=9D=A1?= <1262327911@qq.com> Date: Sun, 15 Dec 2024 12:48:36 +0800 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E6=95=B4=E4=BD=93=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/GoVChart/index.vue | 57 +++++++++---- .../Pages/VChartItemSetting/Legends.vue | 45 ++++++++++ .../VChartItemSetting/VChartGlobalSetting.vue | 18 ++++ .../Pages/VChartItemSetting/index.ts | 3 + src/hooks/index.ts | 3 +- src/hooks/useVCharts.hook.ts | 82 +++++++++++++++++++ .../chartConfiguration/vcharts/index.ts | 1 + .../chartConfiguration/vcharts/legends.ts | 47 +++++++++++ .../Charts/Bars/BarCommon/config.ts | 2 +- .../VChart/Bars/VChartBarCommon/config.ts | 15 +++- .../VChart/Bars/VChartBarCommon/config.vue | 18 +++- .../VChart/Bars/VChartBarCommon/data.json | 22 +++++ .../VChart/Bars/VChartBarCommon/index.vue | 22 +++++ src/packages/public/chart.ts | 2 +- src/packages/public/vChart.ts | 24 ++++++ src/settings/vchartThemes/global.theme.json | 19 +++++ src/settings/vchartThemes/index.ts | 9 ++ .../chartEditStore/chartEditStore.d.ts | 5 +- .../modules/chartEditStore/chartEditStore.ts | 2 + src/views/chart/ContentEdit/index.vue | 9 +- src/views/preview/suspenseIndex.vue | 4 + 21 files changed, 381 insertions(+), 28 deletions(-) create mode 100644 src/components/Pages/VChartItemSetting/Legends.vue create mode 100644 src/components/Pages/VChartItemSetting/VChartGlobalSetting.vue create mode 100644 src/components/Pages/VChartItemSetting/index.ts create mode 100644 src/hooks/useVCharts.hook.ts create mode 100644 src/packages/chartConfiguration/vcharts/index.ts create mode 100644 src/packages/chartConfiguration/vcharts/legends.ts create mode 100644 src/packages/components/VChart/Bars/VChartBarCommon/data.json create mode 100644 src/packages/components/VChart/Bars/VChartBarCommon/index.vue create mode 100644 src/packages/public/vChart.ts create mode 100644 src/settings/vchartThemes/global.theme.json create mode 100644 src/settings/vchartThemes/index.ts diff --git a/src/components/GoVChart/index.vue b/src/components/GoVChart/index.vue index db36e222..bf51c5ae 100644 --- a/src/components/GoVChart/index.vue +++ b/src/components/GoVChart/index.vue @@ -133,13 +133,17 @@ const emit = defineEmits([ const props = defineProps({ option: { - type: Object as PropType, + type: Object as PropType< + ISpec & { + dataset: any + } + >, required: true }, initOptions: { type: Object as PropType< IInitOption & { - deepWatch?: boolean + deepWatch?: boolean | number } >, required: false, @@ -150,27 +154,53 @@ const props = defineProps({ const vChartRef = ref() let chart: IVChart +// 排除 data 监听 watch( - () => props.option, - (chartProps: ISpec) => { + () => ({ + ...props.option, + data: undefined + }), + () => { + nextTick(() => { + createOrUpdateChart(props.option) + }) + }, + { + deep: props.initOptions?.deepWatch || true, + immediate: true + } +) + +// 单独渲染,非深度监听,处理性能问题 +watch( + () => props.option.dataset, + () => { if (vChartRef.value) { nextTick(() => { - createOrUpdateChart(chartProps) + createOrUpdateChart(props.option) }) } }, { - deep: props.initOptions.deepWatch || false + deep: false, + immediate: false } ) // 更新 -const createOrUpdateChart = (chartProps: ISpec) => { +const createOrUpdateChart = ( + chartProps: ISpec & { + dataset: any + } +) => { if (vChartRef.value && !chart) { - chart = new VChart(chartProps, { - dom: vChartRef.value, - ...props.initOptions - }) + chart = new VChart( + { ...chartProps, data: chartProps.dataset }, + { + dom: vChartRef.value, + ...props.initOptions + } + ) chart.renderSync() return true } else if (chart) { @@ -194,11 +224,6 @@ const eventHandlers = (eventData: MouseEvent, eventName: string) => { if (event.includes(eventName)) emit(eventName as any, eventData) } -// 挂载 -onMounted(() => { - createOrUpdateChart(props.option) -}) - // 卸载 onBeforeUnmount(() => { if (chart) { diff --git a/src/components/Pages/VChartItemSetting/Legends.vue b/src/components/Pages/VChartItemSetting/Legends.vue new file mode 100644 index 00000000..e60b9b16 --- /dev/null +++ b/src/components/Pages/VChartItemSetting/Legends.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/components/Pages/VChartItemSetting/VChartGlobalSetting.vue b/src/components/Pages/VChartItemSetting/VChartGlobalSetting.vue new file mode 100644 index 00000000..efcd4190 --- /dev/null +++ b/src/components/Pages/VChartItemSetting/VChartGlobalSetting.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/components/Pages/VChartItemSetting/index.ts b/src/components/Pages/VChartItemSetting/index.ts new file mode 100644 index 00000000..1803ccc1 --- /dev/null +++ b/src/components/Pages/VChartItemSetting/index.ts @@ -0,0 +1,3 @@ +import VChartGlobalSetting from './VChartGlobalSetting.vue' + +export { VChartGlobalSetting } diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 0fa06549..4736216c 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -5,4 +5,5 @@ export * from '@/hooks/useChartDataFetch.hook' export * from '@/hooks/useChartDataPondFetch.hook' export * from '@/hooks/useLifeHandler.hook' export * from '@/hooks/useLang.hook' -export * from '@/hooks/useChartInteract.hook' \ No newline at end of file +export * from '@/hooks/useChartInteract.hook' +export * from '@/hooks/useVCharts.hook' \ No newline at end of file diff --git a/src/hooks/useVCharts.hook.ts b/src/hooks/useVCharts.hook.ts new file mode 100644 index 00000000..3a6dd0f5 --- /dev/null +++ b/src/hooks/useVCharts.hook.ts @@ -0,0 +1,82 @@ +import { watch } from 'vue' +import vScreenVolcanoBlue from '@visactor/vchart-theme/public/vScreenVolcanoBlue.json' +import { VChart, type ITheme } from '@visactor/vchart' + +const themeMap = { + vScreenVolcanoBlue: vScreenVolcanoBlue +} + +export const useVCharts = () => { + // 注册主题(支持自定义主题) + const registerTheme = (themeName: keyof typeof themeMap, theme: any) => { + VChart.ThemeManager.registerTheme(themeName, (themeMap[themeName] as any) || theme) + } + + // 设置当前主题 + const setCurrentTheme = (themeName = 'vScreenVolcanoBlue') => { + VChart.ThemeManager.setCurrentTheme(themeName) + } + + // 判断主题是否存在 + const themeExist = (name: string): boolean => { + return VChart.ThemeManager.themeExist(name) + } + + // 获取主题 + const getTheme = (name: string): ITheme => { + return VChart.ThemeManager.getTheme(name) + } + + // 获取当前主题 + const getCurrentTheme = (): ITheme => { + return VChart.ThemeManager.getCurrentTheme() + } + + // 设置主题 + const setTheme = (name: keyof typeof themeMap): boolean => { + if (themeExist(name)) { + setCurrentTheme(name) + return true + } else { + // 先注册 + const theme = themeMap[name] + if (theme) { + registerTheme(name, theme) + setCurrentTheme(name) + return true + } else { + // 注册默认主题 + registerTheme('vScreenVolcanoBlue', vScreenVolcanoBlue) + } + } + return false + } + + return { + registerTheme, + setCurrentTheme, + themeExist, + getTheme, + setTheme, + getCurrentTheme + } +} + +// 设置全局的 vCharts 主题 +export const useInitVChartsTheme = (chartEditStore: any) => { + const vCharts = useVCharts() + + const initVChartsThemeIns = watch( + () => chartEditStore.getEditCanvasConfig.vChartThemeName, + (newTheme: string) => { + vCharts.setTheme(newTheme as any) + }, + { + immediate: true + } + ) + + return { + initVChartsThemeIns + } +} diff --git a/src/packages/chartConfiguration/vcharts/index.ts b/src/packages/chartConfiguration/vcharts/index.ts new file mode 100644 index 00000000..ab3a2cdf --- /dev/null +++ b/src/packages/chartConfiguration/vcharts/index.ts @@ -0,0 +1 @@ +export * from './legends' \ No newline at end of file diff --git a/src/packages/chartConfiguration/vcharts/legends.ts b/src/packages/chartConfiguration/vcharts/legends.ts new file mode 100644 index 00000000..4511db49 --- /dev/null +++ b/src/packages/chartConfiguration/vcharts/legends.ts @@ -0,0 +1,47 @@ +export const legendsConfig = { + // 位置 + orient: [ + { + label: '顶部', + value: 'top' + }, + { + label: '底部', + value: 'bottom' + }, + { + label: '左侧', + value: 'left' + }, + { + label: '右侧', + value: 'right' + } + ], + // 对齐方式 + position: [ + { + label: '起始', + value: 'start' + }, + { + label: '居中', + value: 'middle' + }, + { + label: '末尾', + value: 'end' + } + ], + // 每一项的图例位置 + align: [ + { + label: '居左', + value: 'left' + }, + { + label: '居右', + value: 'right' + } + ] +} diff --git a/src/packages/components/Charts/Bars/BarCommon/config.ts b/src/packages/components/Charts/Bars/BarCommon/config.ts index a57b6d94..6310864f 100644 --- a/src/packages/components/Charts/Bars/BarCommon/config.ts +++ b/src/packages/components/Charts/Bars/BarCommon/config.ts @@ -28,7 +28,7 @@ export const option = { type: 'shadow' } }, -xAxis: { + xAxis: { show: true, type: 'category' }, diff --git a/src/packages/components/VChart/Bars/VChartBarCommon/config.ts b/src/packages/components/VChart/Bars/VChartBarCommon/config.ts index 7373ed8c..8e0c0ede 100644 --- a/src/packages/components/VChart/Bars/VChartBarCommon/config.ts +++ b/src/packages/components/VChart/Bars/VChartBarCommon/config.ts @@ -1,15 +1,24 @@ import { PublicConfigClass } from '@/packages/public' import { VChartBarCommonConfig } from './index' import { CreateComponentType } from '@/packages/index.d' +import { vChartOptionPrefixHandle } from '@/packages/public/vChart' +import data from './data.json' import cloneDeep from 'lodash/cloneDeep' +import { type ISpec } from '@visactor/vchart' -export const option = { - +export const includes = ['legends'] +export const option: ISpec & { dataset?: any } = { + type: 'bar', + dataset: data, + stack: true, + xField: 'type', + yField: 'value', + seriesField: 'country' } export default class Config extends PublicConfigClass implements CreateComponentType { public key = VChartBarCommonConfig.key public chartConfig = cloneDeep(VChartBarCommonConfig) // 图表配置项 - public option = cloneDeep(option) + public option = vChartOptionPrefixHandle(option, includes) } diff --git a/src/packages/components/VChart/Bars/VChartBarCommon/config.vue b/src/packages/components/VChart/Bars/VChartBarCommon/config.vue index a79b3358..b111a08d 100644 --- a/src/packages/components/VChart/Bars/VChartBarCommon/config.vue +++ b/src/packages/components/VChart/Bars/VChartBarCommon/config.vue @@ -1,3 +1,17 @@ - + - + diff --git a/src/packages/components/VChart/Bars/VChartBarCommon/data.json b/src/packages/components/VChart/Bars/VChartBarCommon/data.json new file mode 100644 index 00000000..04c70222 --- /dev/null +++ b/src/packages/components/VChart/Bars/VChartBarCommon/data.json @@ -0,0 +1,22 @@ +{ + "values": [ + { "type": "Nail polish", "country": "Africa", "value": 4229 }, + { "type": "Nail polish", "country": "EU", "value": 4376 }, + { "type": "Eyebrow pencil", "country": "Africa", "value": 3932 }, + { "type": "Eyebrow pencil", "country": "EU", "value": 3987 }, + { "type": "Rouge", "country": "Africa", "value": 5221 }, + { "type": "Rouge", "country": "EU", "value": 3574 }, + { "type": "Lipstick", "country": "Africa", "value": 9256 }, + { "type": "Lipstick", "country": "EU", "value": 4376 }, + { "type": "Eyeshadows", "country": "Africa", "value": 3308 }, + { "type": "Eyeshadows", "country": "EU", "value": 4572 }, + { "type": "Eyeliner", "country": "Africa", "value": 5432 }, + { "type": "Eyeliner", "country": "EU", "value": 3417 }, + { "type": "Foundation", "country": "Africa", "value": 13701 }, + { "type": "Foundation", "country": "EU", "value": 5231 }, + { "type": "Lip gloss", "country": "Africa", "value": 4008 }, + { "type": "Lip gloss", "country": "EU", "value": 4572 }, + { "type": "Mascara", "country": "Africa", "value": 18712 }, + { "type": "Mascara", "country": "EU", "value": 6134 } + ] +} diff --git a/src/packages/components/VChart/Bars/VChartBarCommon/index.vue b/src/packages/components/VChart/Bars/VChartBarCommon/index.vue new file mode 100644 index 00000000..c70c6676 --- /dev/null +++ b/src/packages/components/VChart/Bars/VChartBarCommon/index.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/packages/public/chart.ts b/src/packages/public/chart.ts index e323542e..75ccdba4 100644 --- a/src/packages/public/chart.ts +++ b/src/packages/public/chart.ts @@ -20,7 +20,7 @@ export const mergeTheme = (option: T, themeSetting: U, includes: string[]) * @param option * @return option */ -export const echartOptionProfixHandle = (option: any, includes: string[]) => { +export const echartOptionProfixHandle = (option: any, includes: string[] = []) => { option['backgroundColor'] = 'rgba(0,0,0,0)' return mergeTheme(option, globalThemeJson, includes) } diff --git a/src/packages/public/vChart.ts b/src/packages/public/vChart.ts new file mode 100644 index 00000000..305726d5 --- /dev/null +++ b/src/packages/public/vChart.ts @@ -0,0 +1,24 @@ +import merge from 'lodash/merge' +import pick from 'lodash/pick' +import { vChartGlobalThemeJson } from '@/settings/vchartThemes/index' + +/** + * * 合并 color 和全局配置项 + * @param option 配置 + * @param themeSetting 设置 + * @param excludes 排除元素 + * @returns object + */ +export const mergeTheme = (option: T, themeSetting: U, includes: string[]) => { + return (option = merge({}, pick(themeSetting, includes), option)) +} + +/** + * * vCharts option 统一前置处理 + * @param option + * @return option + */ +export const vChartOptionPrefixHandle = (option: any, includes: string[] = []) => { + option['background'] = 'rgba(0,0,0,0)' + return mergeTheme(option, vChartGlobalThemeJson, includes) +} diff --git a/src/settings/vchartThemes/global.theme.json b/src/settings/vchartThemes/global.theme.json new file mode 100644 index 00000000..07dae4e1 --- /dev/null +++ b/src/settings/vchartThemes/global.theme.json @@ -0,0 +1,19 @@ +{ + "legends": [ + { + "visible": true, + "position": "middle", + "orient": "bottom", + "item": { + "visible": true, + "align": "left", + "label": { + "style": { + "fontSize": 16, + "fill": "#B9B8CE" + } + } + } + } + ] +} diff --git a/src/settings/vchartThemes/index.ts b/src/settings/vchartThemes/index.ts new file mode 100644 index 00000000..4401bf76 --- /dev/null +++ b/src/settings/vchartThemes/index.ts @@ -0,0 +1,9 @@ +import themeJson from './global.theme.json' + +type ThemeJsonType = typeof themeJson +export interface vChartGlobalThemeJsonType extends Partial { + dataset?: any + [T: string]: any +} + +export const vChartGlobalThemeJson = { ...themeJson, dataset: null, renderer: 'svg' as const } diff --git a/src/store/modules/chartEditStore/chartEditStore.d.ts b/src/store/modules/chartEditStore/chartEditStore.d.ts index 5b986821..2e6f7a49 100644 --- a/src/store/modules/chartEditStore/chartEditStore.d.ts +++ b/src/store/modules/chartEditStore/chartEditStore.d.ts @@ -57,6 +57,7 @@ export enum EditCanvasConfigEnum { CHART_THEME_COLOR = 'chartThemeColor', CHART_CUSTOM_THEME_COLOR_INFO = 'chartCustomThemeColorInfo', CHART_THEME_SETTING = 'chartThemeSetting', + VCHART_THEME_NAME = 'vChartThemeName', BACKGROUND = 'background', BACKGROUND_IMAGE = 'backgroundImage', SELECT_COLOR = 'selectColor', @@ -100,7 +101,9 @@ export interface EditCanvasConfigType { // 图表全局配置 [EditCanvasConfigEnum.CHART_THEME_SETTING]: GlobalThemeJsonType // 图表主题颜色 - [EditCanvasConfigEnum.SELECT_COLOR]: boolean + [EditCanvasConfigEnum.SELECT_COLOR]: boolean, + // vChart 主题 + [EditCanvasConfigEnum.VCHART_THEME_NAME]: string // 预览展示方式 [EditCanvasConfigEnum.PREVIEW_SCALE_TYPE]: PreviewScaleEnum } diff --git a/src/store/modules/chartEditStore/chartEditStore.ts b/src/store/modules/chartEditStore/chartEditStore.ts index 0c96f111..b72d0b54 100644 --- a/src/store/modules/chartEditStore/chartEditStore.ts +++ b/src/store/modules/chartEditStore/chartEditStore.ts @@ -114,6 +114,8 @@ export const useChartEditStore = defineStore({ chartCustomThemeColorInfo: undefined, // 全局配置 chartThemeSetting: globalThemeJson, + // vChart 主题 + vChartThemeName: 'vScreenVolcanoBlue', // 适配方式 previewScaleType: previewScaleType }, diff --git a/src/views/chart/ContentEdit/index.vue b/src/views/chart/ContentEdit/index.vue index b0e8dddb..d44393d4 100644 --- a/src/views/chart/ContentEdit/index.vue +++ b/src/views/chart/ContentEdit/index.vue @@ -83,7 +83,7 @@ diff --git a/src/views/chart/ContentConfigurations/components/CanvasPage/index.vue b/src/views/chart/ContentConfigurations/components/CanvasPage/index.vue index f4ac2d24..90496aea 100644 --- a/src/views/chart/ContentConfigurations/components/CanvasPage/index.vue +++ b/src/views/chart/ContentConfigurations/components/CanvasPage/index.vue @@ -150,6 +150,7 @@ const switchSelectColorLoading = ref(false) const selectColorValue = ref(0) const ChartThemeColor = loadAsyncComponent(() => import('./components/ChartThemeColor/index.vue')) +const VChartThemeColor = loadAsyncComponent(() => import('./components/VChartThemeColor/index.vue')) // 默认应用类型 const selectColorOptions = [ @@ -166,10 +167,16 @@ const selectColorOptions = [ const globalTabList = [ { key: 'ChartTheme', - title: '主题颜色', + title: '默认主题颜色', icon: ColorPaletteIcon, render: ChartThemeColor - } + }, + { + key: 'VChartTheme', + title: 'VChart主题颜色', + icon: ColorPaletteIcon, + render: VChartThemeColor + }, ] const previewTypeList = [ From 844b95987efdaa691ee49859aa4ec38a645645b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=94=E8=B7=91=E7=9A=84=E9=9D=A2=E6=9D=A1?= <1262327911@qq.com> Date: Mon, 16 Dec 2024 21:01:26 +0800 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E4=B8=BB=E9=A2=98=E7=9A=84UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/VChartThemeColor/index.vue | 41 ++++++++++--------- .../components/CanvasPage/index.vue | 4 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/views/chart/ContentConfigurations/components/CanvasPage/components/VChartThemeColor/index.vue b/src/views/chart/ContentConfigurations/components/CanvasPage/components/VChartThemeColor/index.vue index 332f4224..cc416f5c 100644 --- a/src/views/chart/ContentConfigurations/components/CanvasPage/components/VChartThemeColor/index.vue +++ b/src/views/chart/ContentConfigurations/components/CanvasPage/components/VChartThemeColor/index.vue @@ -1,10 +1,12 @@