feat: supply option panel of gloabl and bar chart setting

This commit is contained in:
skie1997 2024-12-20 15:44:24 +08:00
parent 026e4809c8
commit 152786c652
20 changed files with 8049 additions and 32 deletions

7604
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@
<script setup lang="ts">
import { ref, PropType, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { VChart, type IVChart, type IInitOption, type ISpec } from '@visactor/vchart'
import { transformHandler } from './transformProps'
import { IOption } from '@/packages/components/VChart/index.d'
// v1.13.0 https://www.visactor.io/vchart/api/API/event
const event = [
@ -189,13 +191,14 @@ watch(
//
const createOrUpdateChart = (
chartProps: ISpec & {
chartProps: IOption & {
dataset: any
}
) => {
if (vChartRef.value && !chart) {
const spec = transformHandler[chartProps.category](chartProps)
chart = new VChart(
{ ...chartProps, data: chartProps.dataset },
{ ...spec, data: chartProps.dataset },
{
dom: vChartRef.value,
...props.initOptions
@ -204,8 +207,8 @@ const createOrUpdateChart = (
chart.renderSync()
return true
} else if (chart) {
chart.updateSpec(chartProps)
chart.renderSync()
const spec = transformHandler[chartProps.category](chartProps)
chart.updateSpec({ ...spec, data: chartProps.dataset })
return true
}
return false

View File

@ -0,0 +1,32 @@
import { cloneDeep } from "lodash"
export default (chartProps: any) => {
const spec = cloneDeep(chartProps)
delete spec.category
// tooltip
const keyFill = spec.tooltip.style.keyLabel.fill
const valueFill = spec.tooltip.style.valueLabel.fill
const titleFill = spec.tooltip.style.titleLabel.keyFill
delete spec.tooltip.style.keyLabel.fill
delete spec.tooltip.style.valueLabel.fill
delete spec.tooltip.style.titleLabel.keyFill
spec.tooltip.style.keyLabel.fontColor = keyFill
spec.tooltip.style.valueLabel.fontColor = valueFill
spec.tooltip.style.titleLabel.fontColor = titleFill
// axis
const { name: xAxisName, ...restXAxisProps } = chartProps.xAxis
const { name: yAxisName, ...restYAxisProps } = chartProps.yAxis
spec.axes = [{
orient: 'bottom',
...restXAxisProps
}, {
orient: 'left',
...restYAxisProps
}]
delete spec.xAxis
delete spec.yAxis
console.log('spec-transform', spec)
return spec
}

View File

@ -0,0 +1,8 @@
import { ChatCategoryEnum, IOption } from "@/packages/components/VChart/index.d";
import bars from './bars'
export const transformHandler: {
[key: string]: (args: IOption) => any
} = {
[ChatCategoryEnum.BAR]: bars,
// todo: more charts handler
}

View File

@ -0,0 +1,71 @@
<template>
<collapse-item v-model:name="axis.name">
<template #header>
<n-switch v-model:value="axis.visible" size="small"></n-switch>
</template>
<setting-item-box name="轴标签">
<setting-item name="可见性">
<n-space>
<n-switch v-model:value="axis.label.visible" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="角度">
<n-input-number v-model:value="axis.label.style.angle" :min="0" :max="360" size="small" />
</setting-item>
<FontStyle :style="axis.label.style"></FontStyle>
</setting-item-box>
<setting-item-box name="轴标题">
<setting-item name="可见性">
<n-space>
<n-switch v-model:value="axis.title.visible" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="标题内容">
<n-input v-model:value="axis.title.style.text" size="small"></n-input>
</setting-item>
<FontStyle :style="axis.title.style"></FontStyle>
</setting-item-box>
<setting-item-box name="轴线">
<setting-item name="可见性">
<n-space>
<n-switch v-model:value="axis.domainLine.visible" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name=""> </setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="axis.domainLine.style.lineWidth" :min="0" size="small" />
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="axis.domainLine.style.stroke" size="small" />
</setting-item>
</setting-item-box>
<setting-item-box name="网格线">
<setting-item name="可见性">
<n-space>
<n-switch v-model:value="axis.grid.visible" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name=""> </setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="axis.grid.style.lineWidth" :min="0" size="small" />
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="axis.grid.style.stroke" size="small" />
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import FontStyle from './common/FontStyle.vue'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
axis: {
type: Object as PropType<vChartGlobalThemeJsonType>,
required: true
}
})
</script>

View File

@ -15,15 +15,7 @@
</setting-item>
</setting-item-box>
<setting-item-box name="项配置">
<setting-item name="标题位置">
<n-select v-model:value="legendItem.item.align" size="small" :options="legendsConfig.align" />
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="legendItem.item.label.style.fill"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="legendItem.item.label.style.fontSize" :min="1" size="small"></n-input-number>
</setting-item>
<FontStyle :style="legendItem.item.label.style"></FontStyle>
</setting-item-box>
</collapse-item>
</div>
@ -33,6 +25,7 @@
<script setup lang="ts">
import { PropType } from 'vue'
import { legendsConfig } from '@/packages/chartConfiguration/vcharts/index'
import FontStyle from './common/FontStyle.vue'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'

View File

@ -0,0 +1,47 @@
<template>
<!-- todo 补充常用配置项 -->
<div v-if="optionData.tooltip">
<collapse-item name="提示框">
<template #header>
<n-switch v-model:value="optionData.tooltip.visible" size="small"></n-switch>
</template>
<setting-item-box name="框">
<setting-item name="填充">
<n-color-picker v-model:value="optionData.tooltip.style.panel.backgroundColor" size="small" />
</setting-item>
<setting-item name="瞄边">
<n-color-picker v-model:value="optionData.tooltip.style.panel.border.color" size="small" />
</setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="optionData.tooltip.style.panel.border.width" :min="0" size="small" />
</setting-item>
<setting-item name="圆角">
<n-input-number v-model:value="optionData.tooltip.style.panel.border.radius" :min="0" size="small" />
</setting-item>
</setting-item-box>
<setting-item-box name="标题">
<FontStyle :style="optionData.tooltip.style.titleLabel"></FontStyle>
</setting-item-box>
<setting-item-box name="名称">
<FontStyle :style="optionData.tooltip.style.keyLabel"></FontStyle>
</setting-item-box>
<setting-item-box name="值">
<FontStyle :style="optionData.tooltip.style.valueLabel"></FontStyle>
</setting-item-box>
</collapse-item>
</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import FontStyle from './common/FontStyle.vue'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
optionData: {
type: Object as PropType<vChartGlobalThemeJsonType>,
required: true
}
})
</script>

View File

@ -1,14 +1,14 @@
<template>
<!-- 图例 -->
<Legends :optionData="optionData"></Legends>
<Tooltip :optionData="optionData"></Tooltip>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { PropType } from 'vue'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
import Legends from './Legends.vue'
import Tooltip from './Tooltip.vue'
const props = defineProps({
optionData: {
type: Object as PropType<vChartGlobalThemeJsonType>,

View File

@ -0,0 +1,33 @@
<template>
<!-- todo 补充常用配置项 -->
<!-- <div v-if="style"> -->
<!-- <setting-item-box v-if="style" name=""> -->
<setting-item name="颜色">
<n-color-picker v-model:value="style.fill" size="small" />
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="style.fontSize" :min="1" size="small" />
</setting-item>
<setting-item name="字体">
<n-select v-model:value="style.fontFamily" :options="fontStyleConfig.fontFamily" size="small" />
</setting-item>
<setting-item name="字重">
<n-select v-model:value="style.fontSize" :options="fontStyleConfig.fontWeight" size="small" />
</setting-item>
<!-- </setting-item-box> -->
<!-- </div> -->
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { fontStyleConfig } from '@/packages/chartConfiguration/vcharts/index'
import { FontType } from '@/settings/vchartThemes/index'
import { SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
style: {
type: Object as PropType<FontType>,
required: true
}
})
</script>

View File

@ -1,3 +1,4 @@
import VChartGlobalSetting from './VChartGlobalSetting.vue'
import Axis from './Axis.vue'
export { VChartGlobalSetting }
export { VChartGlobalSetting, Axis }

View File

@ -45,3 +45,55 @@ export const legendsConfig = {
}
]
}
export const fontStyleConfig = {
// 字重
fontWeight: [
{
label: '100',
value: 100
},
{
label: '200',
value: 200
},
{
label: '300',
value: 300
},
{
label: '400',
value: 400
},
{
label: '500',
value: 500
},
{
label: '600',
value: 600
},
{
label: '正常',
value: "normal"
},
{
label: '加粗',
value: "bold"
}
],
fontFamily: [
{
label: '宋体',
value: 'SimSun'
},
{
label: '黑体',
value: 'SimHei'
},
{
label: '楷体',
value: '楷体'
}
]
}

View File

@ -4,16 +4,39 @@ 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'
import axisThemeJson from '@/settings/vchartThemes/axis.theme.json'
import { IBarOption } from '../../index.d'
export const includes = ['legends']
export const option: ISpec & { dataset?: any } = {
export const includes = ['legends', 'tooltip']
export const option: IBarOption & { dataset?: any } = {
// 图表配置
type: 'bar',
dataset: data,
stack: true,
xField: ['year', 'type'],
yField: 'value',
seriesField: 'type'
seriesField: 'type',
// 业务配置后续会被转换为图表spec)
category: VChartBarCommonConfig.category,
xAxis: {
name: 'x轴',
...axisThemeJson,
grid: {
...axisThemeJson.grid,
visible: false
}
},
yAxis: {
name: 'y轴',
...axisThemeJson,
grid: {
...axisThemeJson.grid,
style: {
...axisThemeJson.grid.style,
lineDash: [3, 3]
}
}
}
}
export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@ -1,11 +1,13 @@
<template>
<!-- vCharts 全局设置 -->
<VChartGlobalSetting :optionData="optionData"></VChartGlobalSetting>
<Axis :axis="optionData.xAxis"></Axis>
<Axis :axis="optionData.yAxis"></Axis>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { VChartGlobalSetting } from '@/components/Pages/VChartItemSetting'
import { VChartGlobalSetting, Axis } from '@/components/Pages/VChartItemSetting'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
defineProps({

View File

@ -4,16 +4,39 @@ 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'
import axisThemeJson from '@/settings/vchartThemes/axis.theme.json'
import { IBarOption } from '../../index.d'
export const includes = ['legends']
export const option: ISpec & { dataset?: any } = {
export const includes = ['legends', 'tooltip']
export const option: IBarOption & { dataset?: any } = {
// 图表配置
type: 'bar',
dataset: data,
xField: 'State',
yField: 'Population',
seriesField: 'Age',
stack: true
stack: true,
// 业务配置后续会被转换为图表spec)
category: VChartBarStackConfig.category,
xAxis: {
name: 'x轴',
...axisThemeJson,
grid: {
...axisThemeJson.grid,
visible: false
}
},
yAxis: {
name: 'y轴',
...axisThemeJson,
grid: {
...axisThemeJson.grid,
style: {
...axisThemeJson.grid.style,
lineDash: [3, 3]
}
}
}
}
export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@ -1,11 +1,13 @@
<template>
<!-- vCharts 全局设置 -->
<VChartGlobalSetting :optionData="optionData"></VChartGlobalSetting>
<Axis :axis="optionData.xAxis"></Axis>
<Axis :axis="optionData.yAxis"></Axis>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { VChartGlobalSetting } from '@/components/Pages/VChartItemSetting'
import { VChartGlobalSetting, Axis } from '@/components/Pages/VChartItemSetting'
import { vChartGlobalThemeJsonType } from '@/settings/vchartThemes/index'
defineProps({

View File

@ -1,3 +1,7 @@
import { IBarChartSpec } from '@visactor/vchart'
import { ICartesianAxisCommonSpec } from '@visactor/vchart/esm/component/axis'
export enum ChatCategoryEnum {
BAR = 'Bars',
}
@ -5,3 +9,18 @@ export enum ChatCategoryEnum {
export enum ChatCategoryEnumName {
BAR = '柱状图',
}
export interface IBarOption extends Omit<IBarChartSpec, 'axes'> {
category: ChatCategoryEnum.BAR
type: 'bar'
xAxis?: {
name: string
} & ICartesianAxisCommonSpec
yAxis?: {
name: string
} & ICartesianAxisCommonSpec
}
// todo
// export type IOption = IBarOption | ILineOption ....
export type IOption = IBarOption

View File

@ -1,6 +1,7 @@
import { BaseEvent, EventLife, InteractEvents, InteractEventOn, InteractActionsType } from '@/enums/eventEnum'
import type { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import type { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import type { ChatCategoryEnum, ChatCategoryEnumName } from '@/packages/components/VChart/index.d'
export enum ChartFrameEnum {
// 支持 dataset 的 echarts 框架
@ -26,11 +27,11 @@ export type ConfigType = {
// 标题
title: string
// 分类
category: string
category: ChatCategoryEnum
// 分类名称
categoryName: string
categoryName: ChatCategoryEnumName
// 所属包
package: string
package: PackagesCategoryEnum
// 归类
chartFrame?: ChartFrameEnum
// 预览图

View File

@ -0,0 +1,37 @@
{
"visible": true,
"label": {
"visible": true,
"style": {
"fontSize": 12,
"fill": "#B9B8CE",
"fontFamily": "SimSun",
"fontWeight": "normal",
"angle": 0
}
},
"title": {
"visible": true,
"style": {
"text": "",
"fontSize": 12,
"fill": "#B9B8CE",
"fontFamily": "SimSun",
"fontWeight": "normal"
}
},
"domainLine": {
"visible": false,
"style": {
"lineWidth": 1,
"stroke": "#D5D7E2"
}
},
"grid": {
"visible": true,
"style": {
"lineWidth": 1,
"stroke": "#FFFFFF24"
}
}
}

View File

@ -7,13 +7,72 @@
"item": {
"visible": true,
"align": "left",
"shape": "circle",
"label": {
"style": {
"fontSize": 16,
"fill": "#B9B8CE"
"fill": "#B9B8CE",
"fontFamily": "SimSun",
"fontWeight": "normal"
}
}
}
}
]
],
"tooltip": {
"visible": true,
"style": {
"panel": {
"padding": {
"top": 5,
"bottom": 10,
"left": 10,
"right": 10
},
"backgroundColor": "rgba(8, 28, 48, 0.95)",
"border": {
"color": "#CFCFCF",
"width": 0,
"radius": 2
},
"shadow": {
"x": 0,
"y": 4,
"blur": 12,
"spread": 0,
"color": "rgba(0, 0, 0, 0.2)"
}
},
"titleLabel": {
"fontSize": 14,
"fill": "#FFF",
"fontWeight": "bold",
"fontFamily": "SimSun",
"align": "left",
"lineHeight": 18
},
"keyLabel": {
"fontSize": 12,
"fill": "rgba(255,255,255,0.65)",
"fontWeight": "normal",
"fontFamily": "SimSun",
"align": "left",
"lineHeight": 18
},
"valueLabel": {
"fontSize": 12,
"fill": "#FFF",
"fontWeight": "normal",
"fontFamily": "SimSun",
"align": "right",
"lineHeight": 18
},
"shape": {
"size": 10,
"spacing": 10,
"shapeLineWidth": 0
},
"spaceRow": 10
}
}
}

View File

@ -1,6 +1,13 @@
import themeJson from './global.theme.json'
type ThemeJsonType = typeof themeJson
export type FontType = {
fontSize: number
fontFamily: string
fontWeight: string
fill: string
[T: string]: any
}
export interface vChartGlobalThemeJsonType extends Partial<ThemeJsonType> {
dataset?: any
[T: string]: any