Merge branch 'feature/feature-20250430-h5' of https://e.coding.yili.com/yldc/ylst/ylst-survey-h5 into feature/feature-20250430-h5
This commit is contained in:
@@ -1,19 +1,65 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, useTemplateRef } from 'vue';
|
import { ref, useTemplateRef, watch } from 'vue';
|
||||||
import { useSetPieChart } from '@/hooks/chart/usePieChart';
|
import { useSetPieChart } from '@/hooks/chart/usePieChart';
|
||||||
|
import {
|
||||||
|
formatData,
|
||||||
|
getTableData,
|
||||||
|
setDimensionData
|
||||||
|
} from '@/views/Survey/views/Analysis/components/AnalysisInfo/hooks/pieSeries';
|
||||||
|
|
||||||
// series 信息
|
// series 信息
|
||||||
const series = defineModel<any>('series', { required: true });
|
const tableData = ref([]);
|
||||||
// 饼图 dom 结构
|
const analysis = defineModel('analysis');
|
||||||
const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
|
const series = ref([]);
|
||||||
|
const dimension = defineModel('dimension');
|
||||||
|
|
||||||
|
const index = ref(0);
|
||||||
|
// 饼图 dom 结构
|
||||||
|
// 当 keyword 变动的时候,标记脏数据
|
||||||
|
watch(
|
||||||
|
() => analysis.value,
|
||||||
|
async () => {
|
||||||
|
tableData.value = {
|
||||||
|
...analysis.value,
|
||||||
|
option: getTableData(analysis.value)
|
||||||
|
};
|
||||||
|
|
||||||
|
series.value = formatData(dimension.value ? tableData.value : analysis.value, index.value);
|
||||||
|
const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
|
||||||
useSetPieChart(pieChart, series, { title: false, legend: false });
|
useSetPieChart(pieChart, series, { title: false, legend: false });
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeChart = (i: Number) => {
|
||||||
|
index.value = i;
|
||||||
|
series.value = formatData(tableData.value, index.value);
|
||||||
|
// const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
|
||||||
|
// useSetPieChart(pieChart, series, { title: false, legend: false });
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
|
<div v-if="dimension">
|
||||||
|
<van-radio-group v-model="index" @change="changeChart">
|
||||||
|
<van-radio v-for="(item, index) in tableData.option" :name="index">{{
|
||||||
|
item.option
|
||||||
|
}}</van-radio>
|
||||||
|
</van-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 图表部分 -->
|
<!-- 图表部分 -->
|
||||||
<div style="display: flex; height: 300px; width: 100%; justify-content: center; margin: 16px 0">
|
<div
|
||||||
|
class="charts"
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
height: 300px;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
margin: 16px 0;
|
||||||
|
"
|
||||||
|
>
|
||||||
<span ref="pieChart" style="width: 100%; height: 300px"></span>
|
<span ref="pieChart" style="width: 100%; height: 300px"></span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -26,4 +72,7 @@ useSetPieChart(pieChart, series, { title: false, legend: false });
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
.charts {
|
||||||
|
width: calc(100vw - 50px);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -11,18 +11,14 @@ const option = {
|
|||||||
// orient: 'vertical',
|
// orient: 'vertical',
|
||||||
// left: 'left'
|
// left: 'left'
|
||||||
// },
|
// },
|
||||||
|
label: {
|
||||||
|
formatter: '{b},{c}'
|
||||||
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Access From',
|
name: 'Access From',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: '50%',
|
data: [],
|
||||||
data: [
|
|
||||||
{ value: 1048, name: 'Search Engine' },
|
|
||||||
{ value: 735, name: 'Direct' },
|
|
||||||
{ value: 580, name: 'Email' },
|
|
||||||
{ value: 484, name: 'Union Ads' },
|
|
||||||
{ value: 300, name: 'Video Ads' }
|
|
||||||
],
|
|
||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
|
|||||||
@@ -23,16 +23,24 @@ function useSetPieChart(
|
|||||||
// 在 dom 挂载之后,显示饼图
|
// 在 dom 挂载之后,显示饼图
|
||||||
chartInstance = chart.init(dom.value);
|
chartInstance = chart.init(dom.value);
|
||||||
pieOption.series = JSON.parse(JSON.stringify(series.value));
|
pieOption.series = JSON.parse(JSON.stringify(series.value));
|
||||||
|
|
||||||
console.log(pieOption);
|
|
||||||
|
|
||||||
// 设置图表选项
|
// 设置图表选项
|
||||||
chartInstance.setOption(pieOption, opts);
|
chartInstance.setOption(pieOption, opts);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果 data 变动,重新生成图表w
|
// 如果 data 变动,重新生成图表w
|
||||||
watch(series, (value) => {
|
watch(series, (value) => {
|
||||||
chartInstance.setOption(value, opts);
|
console.log(value);
|
||||||
|
|
||||||
|
const currentOptions = chartInstance.getOption();
|
||||||
|
|
||||||
|
// 合并新的 series 数据到现有配置中
|
||||||
|
chartInstance.setOption(
|
||||||
|
{
|
||||||
|
...currentOptions,
|
||||||
|
series: JSON.parse(JSON.stringify(value)) // 确保深拷贝防止引用污染
|
||||||
|
},
|
||||||
|
opts
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,15 @@
|
|||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
{{ analysis.stem }}
|
{{ analysis.stem }}
|
||||||
|
|
||||||
<chart-msg :series="formatData(analysis)" v-if="showChart.includes(analysis.question_type)" />
|
<chart-msg
|
||||||
|
v-if="showChart.includes(analysis.question_type)"
|
||||||
|
:dimension="analysis.option && analysis.option[0].option"
|
||||||
|
:analysis="analysis"
|
||||||
|
/>
|
||||||
|
|
||||||
<yl-table
|
<yl-table
|
||||||
:props="getTableHeadProps(analysis.head)"
|
:props="getTableHeadProps(analysis.head, analysis.option)"
|
||||||
:data="analysis.option"
|
:data="getTableData(analysis)"
|
||||||
v-if="analysis.head"
|
v-if="analysis.head"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -23,21 +27,39 @@
|
|||||||
import { questionAnalysis } from '../../hooks/useAnalysis';
|
import { questionAnalysis } from '../../hooks/useAnalysis';
|
||||||
import { questionTypeMap } from '@/utils/question/typeMapping';
|
import { questionTypeMap } from '@/utils/question/typeMapping';
|
||||||
import ChartMsg from '@/components/Analysis/Index.vue';
|
import ChartMsg from '@/components/Analysis/Index.vue';
|
||||||
import { formatData } from './hooks/pieSeries';
|
import { getTableData } from './hooks/pieSeries';
|
||||||
import YlTable from '@/components/YlTable/Index.vue';
|
import YlTable from '@/components/YlTable/Index.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
// questionTypeMap 自己去对应
|
// questionTypeMap 自己去对应
|
||||||
const showChart = ref([1, 2, 5, 106, 8, 9, 10]);
|
const showChart = ref([1, 2, 5, 106, 9, 10]);
|
||||||
|
|
||||||
// const showTable = ref([1,2,4])
|
// const showTable = ref([1,2,4])
|
||||||
const getTableHeadProps = (values: any[]) => {
|
|
||||||
return values.map((item: Object) => {
|
// 构建表头
|
||||||
return {
|
const getTableHeadProps = (values: any[], option) => {
|
||||||
|
const head = [];
|
||||||
|
|
||||||
|
if (values && values.length > 0) {
|
||||||
|
values.forEach((item: any) => {
|
||||||
|
if (item.key !== 'option') {
|
||||||
|
head.push({
|
||||||
label: item.title,
|
label: item.title,
|
||||||
prop: item.key
|
prop: item.key,
|
||||||
};
|
width: 120
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (option && option.length > 0 && option[0].option) {
|
||||||
|
head.unshift({
|
||||||
|
label: '选项',
|
||||||
|
prop: 'option',
|
||||||
|
width: 150
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return head;
|
||||||
};
|
};
|
||||||
|
// 构建表格数据
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.mt10 {
|
.mt10 {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ref } from 'vue';
|
|||||||
export const series = ref({
|
export const series = ref({
|
||||||
name: 'Access From',
|
name: 'Access From',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: '70%',
|
radius: ['30%', '50%'],
|
||||||
data: [
|
data: [
|
||||||
{ value: 1048, name: 'Search Engine' },
|
{ value: 1048, name: 'Search Engine' },
|
||||||
{ value: 735, name: 'Direct' },
|
{ value: 735, name: 'Direct' },
|
||||||
@@ -14,18 +14,16 @@ export const series = ref({
|
|||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
// shadowBlur: 10,
|
// shadowBlur: 10,
|
||||||
shadowOffsetX: 0,
|
shadowOffsetX: 0
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
// shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: []
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export function formatData(data: any) {
|
export function formatData(data: any, index) {
|
||||||
const _series = JSON.parse(JSON.stringify(series.value));
|
const _series = JSON.parse(JSON.stringify(series.value));
|
||||||
|
|
||||||
// 当内容为单选的时候处理方式
|
// 当内容为单选的时候处理方式
|
||||||
if (data.question_index === 2 || data.question_index === 1) {
|
if (data.question_type === 1 || data.question_type === 2) {
|
||||||
const { option } = data;
|
const { option } = data;
|
||||||
_series.data = option.map((item: any) => {
|
_series.data = option.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
@@ -34,6 +32,55 @@ export function formatData(data: any) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
data.question_type === 5 ||
|
||||||
|
data.question_type === 106 ||
|
||||||
|
data.question_type === 9 ||
|
||||||
|
data.question_type === 10
|
||||||
|
) {
|
||||||
|
const copyData = setDimensionData(data);
|
||||||
|
_series.data = copyData[index ? index : 0];
|
||||||
|
}
|
||||||
|
|
||||||
return _series;
|
return _series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTableData(data: any) {
|
||||||
|
let analysis = JSON.parse(JSON.stringify(data));
|
||||||
|
const rows = analysis.option || [];
|
||||||
|
return rows.map((rowItem: any) => {
|
||||||
|
const rowData = {
|
||||||
|
option: rowItem.option_title || '未知行'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 遍历每个列字段,填充对应值
|
||||||
|
analysis.head.forEach((col: any) => {
|
||||||
|
if (col.key !== 'option') {
|
||||||
|
const matched = rowItem.option
|
||||||
|
? rowItem.option.find((opt: any) => opt.index === col.key)
|
||||||
|
: '';
|
||||||
|
rowData[col.key] = matched ? `${matched.number}` : rowItem[col.key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return rowData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDimensionData(data) {
|
||||||
|
const { option } = data;
|
||||||
|
return option.map((item: any) => {
|
||||||
|
let array = [];
|
||||||
|
for (let keys in item) {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
if (keys !== 'option' && keys !== 'avg' && item[keys] != 0) {
|
||||||
|
obj.name = data.head.find((head: any) => head.key === keys)?.title;
|
||||||
|
obj.value = item[keys];
|
||||||
|
|
||||||
|
array.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user