feat: 增加表格和雷达图

This commit is contained in:
huanghao1412 2024-02-03 10:29:31 +08:00
parent 97a3d24939
commit 54a4cafefd
11 changed files with 346 additions and 129 deletions

View File

@ -29,6 +29,7 @@ type ChartEditStoreType = typeof useChartEditStore
export const useChartCommonData = ( export const useChartCommonData = (
targetComponent: CreateComponentType, targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType, useChartEditStore: ChartEditStoreType,
updateCallback?: (...args: any) => any
) => { ) => {
const vChartRef = ref<typeof VChart | null>(null) const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0 let fetchInterval: any = 0
@ -139,17 +140,29 @@ export const useChartCommonData = (
// 多值的 // 多值的
if(isMultiple) { if(isMultiple) {
if(Object.prototype.toString.call(data) === '[object Array]') { if(Object.prototype.toString.call(data) === '[object Array]') {
if(data.length && data[0].dimensions && data[0].source) echartsUpdateHandle(data[0]) if(data.length && data[0].dimensions && data[0].source) {
echartsUpdateHandle(data[0])
// 更新回调函数
if (updateCallback) updateCallback(data)
}
else throw Error() else throw Error()
} }
else if(Object.prototype.toString.call(data) === '[object Object]'){ else if(Object.prototype.toString.call(data) === '[object Object]'){
if(data.dimensions && data.source) echartsUpdateHandle(data) if(data.dimensions && data.source) {
echartsUpdateHandle(data)
// 更新回调函数
if (updateCallback) updateCallback(data)
}
else throw Error() else throw Error()
} }
} }
// 单值的 // 单值的
else { else {
if(data) echartsUpdateHandle(data) if(data) {
echartsUpdateHandle(data)
// 更新回调函数
if (updateCallback) updateCallback(data)
}
else throw Error() else throw Error()
} }
} catch (error) { } catch (error) {

View File

@ -12,14 +12,25 @@ export const RadarShapeEnumList = [
{ label: '圆形', value: 'circle' } { label: '圆形', value: 'circle' }
] ]
interface maxMapType {
[k: string]: {
max: number,
min: number
}
}
export const option = { export const option = {
maxMap: {} as maxMapType,
tooltip: { tooltip: {
show: true show: true
}, },
legend: { legend: {
data: dataJson.seriesData.map(i => i.name) data: []
},
dataset: {
dimensions: [],
source: []
}, },
dataset: { ...dataJson },
radar: { radar: {
shape: 'polygon', shape: 'polygon',
radius: ['0%', '60%'], radius: ['0%', '60%'],
@ -28,8 +39,8 @@ export const option = {
splitLine: { show: true }, splitLine: { show: true },
axisName: { show: true, color: '#eee', fontSize: 12 }, axisName: { show: true, color: '#eee', fontSize: 12 },
axisLine: { show: true }, axisLine: { show: true },
axisTick: { show: true }, axisTick: { show: false },
indicator: dataJson.radarIndicator indicator: []
}, },
series: [ series: [
{ {
@ -38,7 +49,7 @@ export const option = {
areaStyle: { areaStyle: {
opacity: 0.1 opacity: 0.1
}, },
data: dataJson.seriesData data: []
} }
] ]
} }

View File

@ -94,12 +94,21 @@
></n-input-number> ></n-input-number>
</SettingItem> </SettingItem>
</SettingItemBox> </SettingItemBox>
<SettingItemBox :name="item.key" v-for="(item, i) in maxList" :key="i">
<SettingItem name="最小值">
<n-input-number :value="item.min" @update:value="v => handleUpdate(item.key, 'min', v)" size="small" :min="0"/>
</SettingItem>
<SettingItem name="最大值">
<n-input-number :value="item.max" @update:value="v => handleUpdate(item.key, 'max', v)" size="small" :min="0"/>
</SettingItem>
</SettingItemBox>
</CollapseItem> </CollapseItem>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed, reactive } from 'vue' import { PropType, computed, reactive, ref } from 'vue'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option, RadarShapeEnumList } from './config' import { option, RadarShapeEnumList } from './config'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index' import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
@ -142,4 +151,22 @@ const updateCenter1 = (value: number) => {
const sliderFormatTooltip = (v: number) => { const sliderFormatTooltip = (v: number) => {
return `${v}%` return `${v}%`
} }
let maxList = computed(() => {
let arr = props.optionData.dataset.source.map(_ => {
let nameKey = props.optionData.dataset.dimensions[0]
return {
key: _[nameKey],
//
max: props.optionData.maxMap[_[nameKey]].max,
min: props.optionData.maxMap[_[nameKey]].min
}
})
return arr
})
const handleUpdate = (k: string, type: string, v: string) => {
if(type === 'min') props.optionData.maxMap[k].min = v
else if(type === 'max') props.optionData.maxMap[k].max = v
}
</script> </script>

View File

@ -3,7 +3,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, PropType, watch } from 'vue' import { ref, computed, PropType, watch, toRefs } from 'vue'
import VChart from 'vue-echarts' import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook' import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import dataJson from './data.json' import dataJson from './data.json'
@ -12,10 +12,10 @@ import { CanvasRenderer } from 'echarts/renderers'
import { RadarChart } from 'echarts/charts' import { RadarChart } from 'echarts/charts'
import { includes } from './config' import { includes } from './config'
import { mergeTheme, setOption } from '@/packages/public/chart' import { mergeTheme, setOption } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks' import {useChartCommonData, useChartDataFetch} from '@/hooks'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils' import {isPreview, setTooltipPosition} from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
const props = defineProps({ const props = defineProps({
@ -33,6 +33,8 @@ const props = defineProps({
} }
}) })
props.chartConfig.option.tooltip.position = setTooltipPosition(props.chartConfig.attr)
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting) const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
use([DatasetComponent, CanvasRenderer, RadarChart, GridComponent, TooltipComponent, LegendComponent]) use([DatasetComponent, CanvasRenderer, RadarChart, GridComponent, TooltipComponent, LegendComponent])
@ -43,35 +45,80 @@ const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes) return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
}) })
const dataSetHandle = (dataset: typeof dataJson) => { // const dataSetHandle = (dataset: typeof dataJson) => {
if (dataset.seriesData) { // if (dataset.seriesData) {
props.chartConfig.option.series[0].data = dataset.seriesData // props.chartConfig.option.series[0].data = dataset.seriesData
// @ts-ignore // // @ts-ignore
props.chartConfig.option.legend.data = dataset.seriesData.map((i: { name: string }) => i.name) // props.chartConfig.option.legend.data = dataset.seriesData.map((i: { name: string }) => i.name)
} // }
if (dataset.radarIndicator) { // if (dataset.radarIndicator) {
props.chartConfig.option.radar.indicator = dataset.radarIndicator // props.chartConfig.option.radar.indicator = dataset.radarIndicator
} // }
if (vChartRef.value && isPreview()) { // if (vChartRef.value && isPreview()) {
setOption(vChartRef.value, props.chartConfig.option) // setOption(vChartRef.value, props.chartConfig.option)
} // }
} // }
watch( // watch(
() => props.chartConfig.option.dataset, // () => props.chartConfig.option.dataset,
newData => { // newData => {
try { // try {
dataSetHandle(newData) // dataSetHandle(newData)
} catch (error) { // } catch (error) {
console.log(error) // console.log(error)
// }
// },
// {
// deep: false
// }
// )
watch(() => props.chartConfig.option.dataset, (v) => {
let { dimensions, source } = v
source.forEach(_ => {
if(!Object.prototype.hasOwnProperty.call(props.chartConfig.option.maxMap, _[dimensions[0]])) {
props.chartConfig.option.maxMap[_[dimensions[0]]] = {
max: null,
min: 0
}
} }
}, })
{ props.chartConfig.option.radar.indicator = source.map(_ => {
deep: false return {
} name: _[dimensions[0]],
) max: props.chartConfig.option.maxMap[_[dimensions[0]]].max,
min: props.chartConfig.option.maxMap[_[dimensions[0]]].min,
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => { }
dataSetHandle(newData) })
props.chartConfig.option.series[0].data = dimensions.slice(1).map(k => {
return {
name: k,
value: source.map(_ => _[k])
}
})
props.chartConfig.option.legend.data = dimensions.slice(1)
}, {
immediate: true,
deep: true
}) })
watch(() => props.chartConfig.option.maxMap, v => {
let { dimensions, source } = props.chartConfig.option.dataset
props.chartConfig.option.radar.indicator = source.map(_ => {
return {
name: _[dimensions[0]],
max: props.chartConfig.option.maxMap[_[dimensions[0]]].max,
min: props.chartConfig.option.maxMap[_[dimensions[0]]].min,
}
})
}, {
immediate: true,
deep: true
})
// useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => {
// dataSetHandle(newData)
// })
useChartCommonData(props.chartConfig, useChartEditStore)
</script> </script>

View File

@ -10,7 +10,7 @@ import { GraphConfig } from './Graph/index'
export default [ export default [
// ProcessConfig, // ProcessConfig,
// RadarConfig, RadarConfig,
// FunnelConfig, // FunnelConfig,
// HeatmapConfig, // HeatmapConfig,
WaterPoloConfig, WaterPoloConfig,

View File

@ -4,12 +4,36 @@ import { TableScrollBoardConfig } from './index'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json' import dataJson from './data.json'
export enum AlignEnum {
LEFT = 'left',
CENTER = 'center',
RIGHT = 'right',
}
export type MapType = {
show: boolean
key: string
header: string
align: AlignEnum
columnWidth: number
}
export const option = { export const option = {
header: ['列1', '列2', '列3'], headerConfig: [],
dataset: dataJson, headerConfigMap: {
index: true, index: {
columnWidth: [30, 100, 100], show: true,
align: ['center', 'right', 'right', 'right'], key: '行号',
header: '#',
align: 'left',
columnWidth: 30,
}
},
// header: ['列1', '列2', '列3'],
dataset: { dimensions: [], source: [] },
// index: true,
// columnWidth: [],
// align: [],
rowNum: 5, rowNum: 5,
waitTime: 2, waitTime: 2,
headerHeight: 35, headerHeight: 35,

View File

@ -25,21 +25,20 @@
placeholder="请输入表头高度" placeholder="请输入表头高度"
></n-input-number> ></n-input-number>
</SettingItem> </SettingItem>
<SettingItem name="显示行号"> <!-- <SettingItem name="显示行号">-->
<n-switch size="small" v-model:value="optionData.index" /> <!-- <n-switch size="small" v-model:value="optionData.index" />-->
</SettingItem> <!-- </SettingItem>-->
</SettingItemBox> </SettingItemBox>
<SettingItemBox name="配置" :alone="true"> <SettingItemBox name="配置" :alone="true">
<SettingItem name="表头数据"> <!-- <SettingItem name="表头数据">-->
<n-input v-model:value="header" :min="1" size="small" placeholder="表头数据(英文','分割)"></n-input> <!-- <n-input v-model:value="header" :min="1" size="small" placeholder="表头数据(英文','分割)"></n-input>-->
</SettingItem> <!-- </SettingItem>-->
<SettingItem name="列对齐方式"> <!-- <SettingItem name="列对齐方式">-->
<n-input v-model:value="align" :min="1" size="small" placeholder="对齐方式(英文','分割)"></n-input> <!-- <n-input v-model:value="align" :min="1" size="small" placeholder="对齐方式(英文','分割)"></n-input>-->
</SettingItem> <!-- </SettingItem>-->
<SettingItem name="列宽度"> <!-- <SettingItem name="列宽度">-->
<n-input v-model:value="columnWidth" :min="1" size="small" placeholder="列宽度(英文','分割)"></n-input> <!-- <n-input v-model:value="columnWidth" :min="1" size="small" placeholder="列宽度(英文','分割)"></n-input>-->
</SettingItem> <!-- </SettingItem>-->
<SettingItem name="轮播方式"> <SettingItem name="轮播方式">
<n-select <n-select
v-model:value="optionData.carousel" v-model:value="optionData.carousel"
@ -62,13 +61,34 @@
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.evenRowBGC"></n-color-picker> <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.evenRowBGC"></n-color-picker>
</SettingItem> </SettingItem>
</SettingItemBox> </SettingItemBox>
<SettingItemBox :name="`列${i + 1}`" v-for="(item, i) in headerConfig" :key="i">
<SettingItem name="展示" style="grid-column: 1 / 3">
<n-space>
<n-switch v-model:value="item.show" size="small"/>
</n-space>
</SettingItem>
<SettingItem name="字段">
<n-text style="height: 28px;line-height: 28px">{{item.key ? item.key : '--'}}</n-text>
</SettingItem>
<SettingItem name="标题">
<n-input v-model:value="item.header" size="small" clearable/>
</SettingItem>
<SettingItem name="列对齐方式">
<n-select v-model:value="item.align" :options="alignOption" size="small"/>
</SettingItem>
<SettingItem name="列宽度">
<n-input-number v-model:value="item.columnWidth" :min="0" size="small"/>
</SettingItem>
</SettingItemBox>
</CollapseItem> </CollapseItem>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, ref, watch } from 'vue' import { PropType, ref, watch, computed, toRefs } from 'vue'
import type { Ref, ToRefs } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config' import { option, AlignEnum, MapType } from './config'
import { PickCreateComponentType } from '@/packages/index.d'
const props = defineProps({ const props = defineProps({
optionData: { optionData: {
@ -77,33 +97,74 @@ const props = defineProps({
} }
}) })
const header = ref()
const align = ref()
const columnWidth = ref()
watch( // const header = ref()
() => props.optionData, // const align = ref()
newData => { // const columnWidth = ref()
header.value = props.optionData.header.toString() //
align.value = props.optionData.align.toString() // watch(
columnWidth.value = props.optionData.columnWidth.toString() // () => props.optionData,
}, // newData => {
{ // header.value = props.optionData.header.toString()
deep: false, // align.value = props.optionData.align.toString()
immediate: true // columnWidth.value = props.optionData.columnWidth.toString()
} // },
) // {
// deep: false,
// immediate: true
// }
// )
//
// watch([header, align, columnWidth], ([headerNew, alignNew, columnWidthNew], [headerOld, alignOld, columnWidthOld]) => {
// if (headerNew !== headerOld) {
// props.optionData.header = headerNew.split(',')
// }
// if (alignNew !== alignOld) {
// props.optionData.align = alignNew.split(',')
// }
// if (columnWidthNew !== columnWidthOld) {
// // @ts-ignore
// props.optionData.columnWidth = columnWidthNew.split(',')
// }
// })
watch([header, align, columnWidth], ([headerNew, alignNew, columnWidthNew], [headerOld, alignOld, columnWidthOld]) => { // const headerConfigMap: Ref<{ [k: string]: any }> = computed(() => {
if (headerNew !== headerOld) { // return props.optionData.headerConfigMap
props.optionData.header = headerNew.split(',') // })
} // const headerConfig: Ref<any[]> = computed(() => {
if (alignNew !== alignOld) { // return props.optionData.headerConfig
props.optionData.align = alignNew.split(',') // })
}
if (columnWidthNew !== columnWidthOld) { const alignOption = [
// @ts-ignore { label: '左', value: AlignEnum.LEFT },
props.optionData.columnWidth = columnWidthNew.split(',') { label: '中', value: AlignEnum.CENTER },
} { label: '右', value: AlignEnum.RIGHT },
]
// const headerConfigMap: Ref<{ [k: string]: any }> = ref(props.optionData.headerConfigMap)
// const headerConfig: Ref<any[]> = ref(props.optionData.headerConfig)
const { headerConfigMap, headerConfig } = toRefs(props.optionData) as ToRefs<{ headerConfigMap: { [k: string] : MapType }, headerConfig: MapType[] }>
watch(() => props.optionData.dataset, (v) => {
v.dimensions.forEach((k: string) => {
//
if(!Object.prototype.hasOwnProperty.call(headerConfigMap.value, k)) {
headerConfigMap.value[k] = {
show: true,
key: k,
header: k,
align: AlignEnum.LEFT,
columnWidth: 100
}
}
headerConfig.value = v.dimensions.map((k: string) => {
return headerConfigMap.value[k]
})
headerConfig.value.unshift(headerConfigMap.value['index'])
})
}, {
immediate: true,
deep: true
}) })
</script> </script>

View File

@ -50,10 +50,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType, onUnmounted, reactive, toRefs, watch, onMounted } from 'vue' import { PropType, onUnmounted, reactive, toRefs, watch, onMounted } from 'vue'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks' import {useChartCommonData, useChartDataFetch} from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import merge from 'lodash/merge' import merge from 'lodash/merge'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import { MapType } from './config'
const props = defineProps({ const props = defineProps({
chartConfig: { chartConfig: {
@ -197,19 +198,29 @@ const mergeConfig = () => {
} }
const calcHeaderData = () => { const calcHeaderData = () => {
let { header, index, indexHeader } = status.mergedConfig let { header, index, indexHeader, headerConfig, headerConfigMap } = status.mergedConfig
if (!header.length) { // if (!header.length) {
status.header = [] // status.header = []
return // return
} // }
header = [...header] // header = [...header]
if (index) header.unshift(indexHeader) // if (index) header.unshift(indexHeader)
status.header = header // status.header = header
type ItemType = { show: boolean, header: string }
status.header = headerConfig.filter((_: ItemType) => _.show).map((_: ItemType) => _.header)
} }
const calcRowsData = () => { const calcRowsData = () => {
let { dataset, index, headerBGC, rowNum } = status.mergedConfig let { dataset: datasetOrigin, index, headerBGC, rowNum } = status.mergedConfig
if (index) { let { headerConfigMap, headerConfig } = status.mergedConfig
interface RowType { [k: string]: any }
let showCols = headerConfig.filter((_: MapType) => _.show && _.key !== '行号').map((_: MapType) => _.key)
let dataset = datasetOrigin.source.map((row: RowType) => {
return datasetOrigin.dimensions.filter((_: string) => showCols.includes(_)).map((key: string) => {
return row[key]
})
})
if (headerConfigMap['index'].show) {
dataset = dataset.map((row: any, i: number) => { dataset = dataset.map((row: any, i: number) => {
row = [...row] row = [...row]
const indexTag = `<span class="index" style="background-color: ${headerBGC};border-radius: 3px;padding: 0px 3px;">${ const indexTag = `<span class="index" style="background-color: ${headerBGC};border-radius: 3px;padding: 0px 3px;">${
@ -232,17 +243,21 @@ const calcRowsData = () => {
const calcWidths = () => { const calcWidths = () => {
const { mergedConfig, rowsData } = status const { mergedConfig, rowsData } = status
const { columnWidth, header } = mergedConfig const { columnWidth, header, headerConfig } = mergedConfig
const usedWidth = columnWidth.reduce((all: any, ws: number) => all + ws, 0) // const usedWidth = columnWidth.reduce((all: any, ws: number) => all + ws, 0)
let columnNum = 0 // let columnNum = 0
if (rowsData[0]) { // if (rowsData[0]) {
columnNum = (rowsData[0] as any).ceils.length // columnNum = (rowsData[0] as any).ceils.length
} else if (header.length) { // } else if (header.length) {
columnNum = header.length // columnNum = header.length
} // }
const avgWidth = (w.value - usedWidth) / (columnNum - columnWidth.length) // const avgWidth = (w.value - usedWidth) / (columnNum - columnWidth.length)
const widths = new Array(columnNum).fill(avgWidth) // const widths = new Array(columnNum).fill(avgWidth)
status.widths = merge(widths, columnWidth) // status.widths = merge(widths, columnWidth)
type ItemType = {show: boolean, columnWidth: number}
let widths = headerConfig.filter((_: ItemType) => _.show).map((_: ItemType) => _.columnWidth)
status.widths = widths
} }
const calcHeights = (onresize = false) => { const calcHeights = (onresize = false) => {
@ -252,19 +267,22 @@ const calcHeights = (onresize = false) => {
if (header.length) allHeight -= headerHeight if (header.length) allHeight -= headerHeight
const avgHeight = allHeight / rowNum const avgHeight = allHeight / rowNum
status.avgHeight = avgHeight status.avgHeight = avgHeight
if (!onresize) status.heights = new Array(dataset.length).fill(avgHeight) if (!onresize) status.heights = new Array(dataset.source.length).fill(avgHeight)
} }
const calcAligns = () => { const calcAligns = () => {
const { header, mergedConfig } = status const { header, mergedConfig } = status
const { headerConfig } = mergedConfig
const columnNum = header.length // const columnNum = header.length
//
// let aligns = new Array(columnNum).fill('left')
//
// const { align } = mergedConfig
//
// status.aligns = merge(aligns, align)
let aligns = new Array(columnNum).fill('left') status.aligns = headerConfig.map((_: any) => _.align)
const { align } = mergedConfig
status.aligns = merge(aligns, align)
} }
const animation = async (start = false) => { const animation = async (start = false) => {
@ -339,7 +357,12 @@ watch(
) )
// ( dataset) // ( dataset)
useChartDataFetch(props.chartConfig, useChartEditStore, (resData: any[]) => { // useChartDataFetch(props.chartConfig, useChartEditStore, (resData: any[]) => {
// props.chartConfig.option.dataset = resData
// onRestart()
// })
useChartCommonData(props.chartConfig, useChartEditStore, (resData: {}) => {
props.chartConfig.option.dataset = resData props.chartConfig.option.dataset = resData
onRestart() onRestart()
}) })

View File

@ -11,7 +11,8 @@ export const option = {
// 展示列 // 展示列
header: { header: {
value: [], value: [],
options: [] options: [],
map: {},
}, },
pagination: { pagination: {
page: 1, page: 1,

View File

@ -2,16 +2,21 @@
<collapse-item name="表格设置" :expanded="true"> <collapse-item name="表格设置" :expanded="true">
<n-tag type="primary">若配置无响应请在预览页面查看效果</n-tag> <n-tag type="primary">若配置无响应请在预览页面查看效果</n-tag>
<setting-item-box name="表头" :alone="true"> <setting-item-box name="表头" :alone="true">
<div class="rows" v-for="(row, i) in optionData.header.options" :key="i"> <div class="rows">
<div class="columns">{{ row.value }}</div> <div class="columns">字段</div>
<n-input class="columns" v-model:value="row.label" size="small"/> <div class="columns">标题</div>
</div>
<div class="rows" v-for="(row: any, i) in optionData.header.options" :key="i">
<div class="columns">{{ row }}</div>
<n-input class="columns" v-model:value="optionData.header.map[row]" size="small"/>
</div> </div>
</setting-item-box> </setting-item-box>
<setting-item-box name="展示列" :alone="true"> <setting-item-box name="展示列" :alone="true">
<n-select <n-select
v-model:value="optionData.header.value" v-model:value="optionData.header.value"
:options="optionData.header.options" :options="optionData.header.options.map(_ => ({label: optionData.header.map[_], value: _}))"
multiple multiple
size="small"
/> />
</setting-item-box> </setting-item-box>
<setting-item-box :alone="true" name="对齐方式"> <setting-item-box :alone="true" name="对齐方式">
@ -178,6 +183,8 @@ const props = defineProps({
.rows { .rows {
margin-bottom: 10px; margin-bottom: 10px;
display: flex; display: flex;
height: 28px;
line-height: 28px;
&:nth-last-child(1){ &:nth-last-child(1){
margin-bottom: 0; margin-bottom: 0;
} }

View File

@ -80,9 +80,12 @@ watch(
(newData: any) => { (newData: any) => {
option.dataset = newData option.dataset = newData
option.header.value = newData.dimensions option.header.value = newData.dimensions
console.log(newData.dimensions.toString(), option.header.options.map((_: {value: string}) => _.value).toString()) option.header.options = newData.dimensions
if(newData.dimensions.toString() === option.header.options.map((_: {value: string}) => _.value).toString()) return newData.dimensions.forEach((key: string) => {
option.header.options = newData.dimensions.map((_: string) => ({label: _, value: _})) if(!Object.prototype.hasOwnProperty.call(option.header.map, key)) option.header.map[key] = key
})
// if(newData.dimensions.toString() === option.header.options.map((_: {value: string}) => _.value).toString()) return
// option.header.options = newData.dimensions.map((_: string) => ({label: _, value: _}))
// option?.dataset?.dimensions?.forEach((header: any) => { // option?.dataset?.dimensions?.forEach((header: any) => {
// header.align = align.value // header.align = align.value
// }) // })
@ -101,11 +104,11 @@ watch(() => props.chartConfig.option.header, v => {
}) })
const columns = computed(() => { const columns = computed(() => {
let dimensions = option.header.options.filter((_: {label: string, value: string}) => option.header.value.includes(_.value)) let dimensions = option.header.options.filter((_: string) => option.header.value.includes(_))
dimensions = dimensions.map((_: {label: string, value: string}) => { dimensions = dimensions.map((_: string) => {
return { return {
title: _.label, title: option.header.map[_],
key: _.value, key: _,
align: align.value align: align.value
} }
}) })