feat: 图表类型相互转换

This commit is contained in:
zxc 2024-09-15 12:45:44 +08:00
parent 16aaea3310
commit da43a56f96
4 changed files with 58 additions and 12 deletions

View File

@ -118,7 +118,7 @@ npm run dev
- Style - Style
- Endpoint style - Endpoint style
#### Charts (bar, column, line, area, scatter, pie, donut, radar) #### Charts (bar, column, line, area, scatter, pie, donut, radar)
- Chart conversion - Chart type conversion
- Data editing - Data editing
- Background fill - Background fill
- Theme color - Theme color

View File

@ -114,7 +114,7 @@ npm run dev
- 样式 - 样式
- 端点样式 - 端点样式
#### 图表(柱状图、条形图、折线图、面积图、散点图、饼图、环形图、雷达图) #### 图表(柱状图、条形图、折线图、面积图、散点图、饼图、环形图、雷达图)
- 图表转换 - 图表类型转换
- 数据编辑 - 数据编辑
- 背景填充 - 背景填充
- 主题色 - 主题色

View File

@ -68,11 +68,23 @@
<div class="btns"> <div class="btns">
<div class="left"> <div class="left">
<Button class="btn" @click="clear()">清空</Button> 图表类型{{ CHART_TYPE_MAP[chartType] }}
<Popover trigger="click" placement="top" v-model:value="chartTypeSelectVisible">
<template #content>
<PopoverMenuItem
center
v-for="item in chartList"
:key="item"
@click="chartType = item; chartTypeSelectVisible = false"
>{{CHART_TYPE_MAP[item]}}</PopoverMenuItem>
</template>
<span class="change">点击更换</span>
</Popover>
</div> </div>
<div class="right"> <div class="right">
<Button class="btn" @click="closeEditor()">取消</Button> <Button class="btn" @click="closeEditor()">取消</Button>
<Button type="primary" class="btn" @click="getTableData()" style="margin-left: 10px;">确认</Button> <Button class="btn" @click="clear()">清空数据</Button>
<Button type="primary" class="btn" @click="getTableData()">确认</Button>
</div> </div>
</div> </div>
</div> </div>
@ -82,8 +94,11 @@
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import type { ChartData, ChartType } from '@/types/slides' import type { ChartData, ChartType } from '@/types/slides'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import { CHART_TYPE_MAP } from '@/configs/chart'
import { pasteCustomClipboardString, pasteExcelClipboardString } from '@/utils/clipboard' import { pasteCustomClipboardString, pasteExcelClipboardString } from '@/utils/clipboard'
import Button from '@/components/Button.vue' import Button from '@/components/Button.vue'
import Popover from '@/components/Popover.vue'
import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
const props = defineProps<{ const props = defineProps<{
type: ChartType type: ChartType
@ -91,7 +106,10 @@ const props = defineProps<{
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
(event: 'save', payload: ChartData): void (event: 'save', payload: {
data: ChartData
type: ChartType
}): void
(event: 'close'): void (event: 'close'): void
}>() }>()
@ -99,9 +117,12 @@ const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
const CELL_WIDTH = 100 const CELL_WIDTH = 100
const CELL_HEIGHT = 32 const CELL_HEIGHT = 32
const chartList: ChartType[] = ['bar', 'column', 'line', 'area', 'scatter', 'pie', 'ring', 'radar']
const chartTypeSelectVisible = ref(false)
const selectedRange = ref([0, 0]) const selectedRange = ref([0, 0])
const tempRangeSize = ref({ width: 0, height: 0 }) const tempRangeSize = ref({ width: 0, height: 0 })
const focusCell = ref<[number, number] | null>(null) const focusCell = ref<[number, number] | null>(null)
const chartType = ref<ChartType>('bar')
// 线 // 线
const rangeLines = computed(() => { const rangeLines = computed(() => {
@ -124,6 +145,8 @@ const resizablePointStyle = computed(() => {
// DOM // DOM
const initData = () => { const initData = () => {
chartType.value = props.type
const _data: string[][] = [] const _data: string[][] = []
const { labels, legends, series } = props.data const { labels, legends, series } = props.data
@ -210,7 +233,7 @@ const getTableData = () => {
// //
// //
if (props.type === 'scatter') { if (chartType.value === 'scatter') {
if (legends.length > 2) { if (legends.length > 2) {
legends = legends.slice(0, 2) legends = legends.slice(0, 2)
series = series.slice(0, 2) series = series.slice(0, 2)
@ -221,14 +244,14 @@ const getTableData = () => {
} }
} }
// //
if (props.type === 'ring' || props.type === 'pie') { if (chartType.value === 'ring' || chartType.value === 'pie') {
if (legends.length > 1) { if (legends.length > 1) {
legends = legends.slice(0, 1) legends = legends.slice(0, 1)
series = series.slice(0, 1) series = series.slice(0, 1)
} }
} }
emit('save', { labels, legends, series }) emit('save', { data: { labels, legends, series }, type: chartType.value })
} }
// //
@ -439,6 +462,26 @@ table {
margin-top: 10px; margin-top: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.btn {
margin-left: 10px;
}
.left {
display: flex;
align-items: center;
font-size: 12px;
.change {
color: #ccc;
margin-left: 5px;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
} }
.col-header { .col-header {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="chart-style-panel"> <div class="chart-style-panel">
<Button class="full-width-btn" @click="chartDataEditorVisible = true"> <Button class="full-width-btn" @click="chartDataEditorVisible = true">
<IconEdit class="btn-icon" /> 编辑图表数据 <IconEdit class="btn-icon" /> 编辑图表
</Button> </Button>
<Divider /> <Divider />
@ -118,7 +118,7 @@
import { onUnmounted, ref, watch, type Ref } from 'vue' import { onUnmounted, ref, watch, type Ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import type { ChartData, ChartOptions, PPTChartElement } from '@/types/slides' import type { ChartData, ChartOptions, ChartType, PPTChartElement } from '@/types/slides'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import { CHART_PRESET_THEMES } from '@/configs/chart' import { CHART_PRESET_THEMES } from '@/configs/chart'
@ -181,9 +181,12 @@ const updateElement = (props: Partial<PPTChartElement>) => {
} }
// //
const updateData = (data: ChartData) => { const updateData = (payload: {
data: ChartData
type: ChartType
}) => {
chartDataEditorVisible.value = false chartDataEditorVisible.value = false
updateElement({ data }) updateElement({ data: payload.data, chartType: payload.type })
} }
// //