diff --git a/src/hooks/useCreateElement.ts b/src/hooks/useCreateElement.ts index 3663dc52..f30ee9a5 100644 --- a/src/hooks/useCreateElement.ts +++ b/src/hooks/useCreateElement.ts @@ -94,6 +94,7 @@ export default () => { gridColor: fontColor.value, data: { labels: ['类别1', '类别2', '类别3', '类别4', '类别5'], + legends: ['系列1'], series: [ [12, 19, 5, 2, 18], ], diff --git a/src/hooks/useExport.ts b/src/hooks/useExport.ts index 5427c0aa..74606b40 100644 --- a/src/hooks/useExport.ts +++ b/src/hooks/useExport.ts @@ -400,6 +400,12 @@ export default () => { } if (el.fill) options.fill = formatColor(el.fill).color + if (el.legend) { + options.showLegend = true + options.legendPos = el.legend === 'top' ? 't' : 'b' + options.legendColor = formatColor(el.gridColor || '#000000').color + options.legendFontSize = 14 * 0.75 + } let type = pptx.ChartType.bar if (el.chartType === 'bar') { diff --git a/src/types/slides.ts b/src/types/slides.ts index b01b82a5..dccd5f2e 100644 --- a/src/types/slides.ts +++ b/src/types/slides.ts @@ -325,6 +325,7 @@ export interface PPTLineElement extends Omit { export type ChartType = 'bar' | 'line' | 'pie' export interface ChartData { labels: string[]; + legends: string[]; series: number[][]; } @@ -346,6 +347,8 @@ export interface ChartData { * themeColor: 主题色 * * gridColor?: 网格&坐标颜色 + * + * legend?: 图例/位置 */ export interface PPTChartElement extends PPTBaseElement { type: 'chart'; @@ -356,6 +359,7 @@ export interface PPTChartElement extends PPTBaseElement { outline?: PPTElementOutline; themeColor: string[]; gridColor?: string; + legend?: '' | 'top' | 'bottom', } diff --git a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue index fb653772..e8154f29 100644 --- a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue +++ b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/ChartDataEditor.vue @@ -23,8 +23,12 @@ - - +
+
- - +
+ +
+
+ + +
@@ -89,10 +98,11 @@ export default defineComponent({ const initData = () => { const _data: string[][] = [] - const { labels, series } = props.data + const { labels, legends, series } = props.data const rowCount = labels.length const colCount = series.length + _data.push(['', ...legends]) for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { const row = [labels[rowIndex]] for (let colIndex = 0; colIndex < colCount; colIndex++) { @@ -101,7 +111,7 @@ export default defineComponent({ _data.push(row) } - for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { + for (let rowIndex = 0; rowIndex < rowCount + 1; rowIndex++) { for (let colIndex = 0; colIndex < colCount + 1; colIndex++) { const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement if (!inputRef) continue @@ -109,7 +119,7 @@ export default defineComponent({ } } - selectedRange.value = [colCount + 1, rowCount] + selectedRange.value = [colCount + 1, rowCount + 1] } onMounted(initData) @@ -140,19 +150,26 @@ export default defineComponent({ const [col, row] = selectedRange.value const labels: string[] = [] + const legends: string[] = [] const series: number[][] = [] - // 第一列为系列名,实际数据从第二列开始 - for (let rowIndex = 0; rowIndex < row; rowIndex++) { - let labelsItem = `类别${rowIndex + 1}` + // 第一行为系列名,第一列为项目名,实际数据从第二行第二列开始 + for (let rowIndex = 1; rowIndex < row; rowIndex++) { + let labelsItem = `类别${rowIndex}` const labelInputRef = document.querySelector(`#cell-${rowIndex}-0`) as HTMLInputElement if (labelInputRef && labelInputRef.value) labelsItem = labelInputRef.value labels.push(labelsItem) } + for (let colIndex = 1; colIndex < col; colIndex++) { + let legendsItem = `系列${colIndex}` + const labelInputRef = document.querySelector(`#cell-0-${colIndex}`) as HTMLInputElement + if (labelInputRef && labelInputRef.value) legendsItem = labelInputRef.value + legends.push(legendsItem) + } for (let colIndex = 1; colIndex < col; colIndex++) { const seriesItem = [] - for (let rowIndex = 0; rowIndex < row; rowIndex++) { + for (let rowIndex = 1; rowIndex < row; rowIndex++) { const valueInputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement let value = 0 if (valueInputRef && valueInputRef.value && !!(+valueInputRef.value)) { @@ -162,8 +179,19 @@ export default defineComponent({ } series.push(seriesItem) } - const data = { labels, series } - emit('save', data) + + emit('save', { labels, legends, series }) + } + + // 清空表格数据 + const clear = () => { + for (let rowIndex = 1; rowIndex < 31; rowIndex++) { + for (let colIndex = 1; colIndex < 7; colIndex++) { + const inputRef = document.querySelector(`#cell-${rowIndex}-${colIndex}`) as HTMLInputElement + if (!inputRef) continue + inputRef.value = '' + } + } } // 关闭图表数据编辑器 @@ -230,6 +258,7 @@ export default defineComponent({ changeSelectRange, getTableData, closeEditor, + clear, } }, }) @@ -346,10 +375,7 @@ table { } .btns { margin-top: 10px; - text-align: right; - - .btn { - margin-left: 10px; - } + display: flex; + justify-content: space-between; } \ No newline at end of file diff --git a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue index 983e5253..9edbdde9 100644 --- a/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue +++ b/src/views/Editor/Toolbar/ElementStylePanel/ChartStylePanel/index.vue @@ -41,6 +41,17 @@ +
+
图例:
+ +
+ + +
背景填充:
@@ -145,6 +156,7 @@ export default defineComponent({ const themeColor = ref([]) const gridColor = ref('') + const legend = ref('') const lineSmooth = ref(true) const showLine = ref(true) @@ -174,6 +186,7 @@ export default defineComponent({ themeColor.value = handleElement.value.themeColor gridColor.value = handleElement.value.gridColor || 'rgba(0, 0, 0, 0.4)' + legend.value = handleElement.value.legend || '' }, { deep: true, immediate: true }) // 设置图表数据 @@ -234,6 +247,13 @@ export default defineComponent({ addHistorySnapshot() } + // 设置图例位置/不显示 + const updateLegend = (legend: '' | 'top' | 'bottom') => { + const props = { legend } + store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props }) + addHistorySnapshot() + } + const openDataEditor = () => chartDataEditorVisible.value = true emitter.on(EmitterEvents.OPEN_CHART_DATA_EDITOR, openDataEditor) @@ -255,10 +275,12 @@ export default defineComponent({ updateOptions, themeColor, gridColor, + legend, updateTheme, addThemeColor, deleteThemeColor, updateGridColor, + updateLegend, } }, }) diff --git a/src/views/components/element/ChartElement/Chart.vue b/src/views/components/element/ChartElement/Chart.vue index 221594c5..2beebe3c 100644 --- a/src/views/components/element/ChartElement/Chart.vue +++ b/src/views/components/element/ChartElement/Chart.vue @@ -1,19 +1,33 @@ \ No newline at end of file diff --git a/src/views/components/element/ChartElement/ScreenChartElement.vue b/src/views/components/element/ChartElement/ScreenChartElement.vue index 578179a8..b6479d3f 100644 --- a/src/views/components/element/ChartElement/ScreenChartElement.vue +++ b/src/views/components/element/ChartElement/ScreenChartElement.vue @@ -26,6 +26,8 @@ :options="elementInfo.options" :themeColor="elementInfo.themeColor" :gridColor="elementInfo.gridColor" + :legends="elementInfo.data.legends" + :legend="elementInfo.legend || ''" />
diff --git a/src/views/components/element/ChartElement/index.vue b/src/views/components/element/ChartElement/index.vue index f1a55614..1507d58c 100644 --- a/src/views/components/element/ChartElement/index.vue +++ b/src/views/components/element/ChartElement/index.vue @@ -30,6 +30,8 @@ :options="elementInfo.options" :themeColor="elementInfo.themeColor" :gridColor="elementInfo.gridColor" + :legends="elementInfo.data.legends" + :legend="elementInfo.legend || ''" />