refactor(chart): 优化饼图组件功能和样式

- 修复饼图数据为空时的显示问题
- 优化饼图 tooltip格式化内容
-调整饼图图例和标签样式
- 优化表格组件,支持图片预览功能
This commit is contained in:
陈昱达
2025-05-23 16:47:53 +08:00
parent 8ba8c35094
commit 8f7a0cb4ec
5 changed files with 134 additions and 74 deletions

View File

@@ -58,7 +58,11 @@ watch(
const changeChart = (i: number) => {
index.value = i;
series.value = formatData(tableData.value, index.value);
if (series.value.data.length <= 0) {
series.value.data = [{ value: 0, name: 0 }];
}
// const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
// useSetPieChart(pieChart, series, { title: false, legend: false });
};
@@ -66,13 +70,13 @@ const changeChart = (i: number) => {
<template>
<section>
<!-- <div v-if="dimension">
<van-radio-group v-model="index" @change="changeChart">
<van-radio v-for="(item, index) in tableData.option" :name="index">{{
<div v-if="dimension" style="margin: 10px 0">
<van-radio-group v-model="index" @change="changeChart" direction="horizontal">
<van-radio v-for="(item, index) in tableData.option" icon-size="0.45rem" :name="index">{{
item.option
}}</van-radio>
</van-radio-group>
</div> -->
</div>
<!-- 图表部分 -->
<div

View File

@@ -1,63 +1,97 @@
<script setup lang="ts">
import { type ColumnStyle } from 'element-plus';
const data = defineModel<unknown[]>('data', { default: [] });
const props = defineModel<TablePropsType[]>('props');
// 是否只显示单行
const singleLine = defineModel<boolean>('singleLine', { default: false });
const rowStyle = defineModel<ColumnStyle<any>>('rowStyle', {
default: {}
});
// 显示表格的高度, 默认的高度是 200px
const tableHeight = defineModel<string | number>('height', { default: '300px' });
const headerStyle = defineModel<ColumnStyle<any>>('headerStyle', {
default: {
background: 'red'
}
});
const rounded = defineModel('rounded', { default: true });
const stripeColor = defineModel('stripeColor', { default: 'red' });
// 空数据时的提示文本
const emptyText = defineModel('emptyText', { default: '暂无数据' });
// (data: { row: any; rowIndex: number; }) => string
function setStripeColor(rowData: { row: any; rowIndex: number }): string {
const { rowIndex } = rowData;
return rowIndex % 2 === 0 ? 'even-row' : 'odd-row';
}
</script>
<template>
<div :style="{ borderRadius: rounded ? '10px' : '0', overflow: 'hidden' }" style="height: 100%">
<el-table
:max-height="tableHeight"
:header-cell-style="{ background: '#f2f8ee' }"
:row-class-name="setStripeColor"
:data="data"
:empty-text="emptyText"
style="width: 100%"
>
<el-table-column
v-for="item in props"
:width="item.width"
:prop="item.prop"
:label="item.label"
show-overflow-tooltip
/>
</el-table>
</div>
</template>
<style lang="scss" scoped module="table">
:deep(.even-row) {
background-color: white;
}
:deep(.odd-row) {
background-color: #fafbfa;
}
:deep(.el-table__header-wrapper) {
border-radius: 8px 8px 0 0;
}
</style>
<script setup lang="ts">
import { type ColumnStyle } from 'element-plus';
import { showImagePreview } from 'vant';
const data = defineModel<unknown[]>('data', { default: [] });
const props = defineModel<TablePropsType[]>('props');
// 是否只显示单行
const singleLine = defineModel<boolean>('singleLine', { default: false });
const rowStyle = defineModel<ColumnStyle<any>>('rowStyle', {
default: {}
});
// 显示表格的高度, 默认的高度是 200px
const tableHeight = defineModel<string | number>('height', { default: '300px' });
const headerStyle = defineModel<ColumnStyle<any>>('headerStyle', {
default: {
background: 'red'
}
});
const rounded = defineModel('rounded', { default: true });
const stripeColor = defineModel('stripeColor', { default: 'red' });
// 空数据时的提示文本
const emptyText = defineModel('emptyText', { default: '暂无数据' });
// (data: { row: any; rowIndex: number; }) => string
function setStripeColor(rowData: { row: any; rowIndex: number }): string {
const { rowIndex } = rowData;
return rowIndex % 2 === 0 ? 'even-row' : 'odd-row';
}
function parseTableText(text: string): string {
const imgReg = /<img.*?>/g;
const imgArr = text.match(imgReg);
if (imgArr && imgArr.length > 0) {
return imgArr.join('');
}
return text;
}
function handleImageClick(e: Event) {
console.log(e);
if (e.target instanceof HTMLImageElement) {
const imgSrc = e.target.src;
showImagePreview({
images: [imgSrc],
closeable: true
});
}
}
</script>
<template>
<div :style="{ borderRadius: rounded ? '10px' : '0', overflow: 'hidden' }" style="height: 100%">
<el-table
:max-height="tableHeight"
:header-cell-style="{ background: '#f2f8ee' }"
:row-class-name="setStripeColor"
:data="data"
:empty-text="emptyText"
style="width: 100%"
>
<el-table-column
v-for="item in props"
:width="item.width"
:prop="item.prop"
:label="item.label"
show-overflow-tooltip
>
<template #default="scope">
<div
class="table-view-html"
v-html="scope.row[item.prop]"
@click.native="handleImageClick"
></div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<style>
.table-view-html {
& img {
width: 50px;
height: 100%;
}
}
</style>
<style lang="scss" scoped module="table">
:deep(.even-row) {
background-color: white;
}
:deep(.odd-row) {
background-color: #fafbfa;
}
:deep(.el-table__header-wrapper) {
border-radius: 8px 8px 0 0;
}
</style>

View File

@@ -9,12 +9,29 @@ const option = {
// tooltip: {
// trigger: 'item'
// },
tooltip: {
trigger: 'item',
formatter: (p) => {
console.log(p);
switch (p.data.questionItem.question_type) {
case 1:
case 2:
return `${p.data.name}: ${p.data.value} ${p.data.answerRate ? '(' + p.data.answerRate + ')' : ''}`;
case 10:
case 9:
return `${p.data.name}: ${p.data.value} ${p.data.answerRate ? '(' + p.data.answerRate + ')' : ''}`;
case 5:
case 106:
return `${p.data.avg ? '平均值<br>' : ''} ${p.data.name}: ${p.data.value}`;
}
}
},
legend: {
// orient: 'horizontal',
bottom: 'top'
},
label: {
// formatter: '{b},{c}'
formatter: '{b},{c}'
},
series: [
{

View File

@@ -29,8 +29,6 @@ function useSetPieChart(
// 如果 data 变动重新生成图表w
watch(series, (value) => {
console.log(value);
const currentOptions = chartInstance.getOption();
// 合并新的 series 数据到现有配置中

View File

@@ -19,7 +19,7 @@ export const series = ref({
// shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
});
});
export function formatData(data: any, index: number) {
const _series = JSON.parse(JSON.stringify(series.value));
@@ -28,8 +28,10 @@ export function formatData(data: any, index: number) {
const { option } = data;
_series.data = option.map((item: any) => {
return {
...item,
value: item.number,
name: item.title
name: item.title,
questionItem: { ...data }
};
});
}
@@ -40,7 +42,12 @@ export function formatData(data: any, index: number) {
data.question_type === 10
) {
const copyData = setDimensionData(data);
_series.data = copyData[index ? index : 0];
_series.data = copyData[index ? index : 0].map((item) => {
return {
...item,
questionItem: { ...data }
};
});
}
// console.log(`series value is :`, _series);
@@ -78,11 +85,11 @@ export function setDimensionData(data) {
if (keys !== 'option' && keys !== 'avg' && item[keys] != 0) {
obj.name = data.head.find((head: any) => head.key === keys)?.title;
obj.value = item[keys];
obj.avg = item.avg;
array.push(obj);
}
}
return array;
});
}