feat: 优化问卷分析图表展示功能
- 修复饼图组件显示问题,取消注释使图表正常显示 - 优化数据处理逻辑,支持问题索引1和2的数据处理 - 移除不必要的响应式包装,直接使用JSON对象提高性能 - 清理未使用的导入和函数,如showToast、surveys等 - 添加对空选项数组的条件判断,避免渲染空数据 - 移除控制台日志输出,提高代码整洁度 - 更新IDE图标主题为material-icon-theme - 优化图表配置结构,简化代码
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -5,7 +5,7 @@
|
||||
"*.ipynb": "jupyter.notebook.ipynb"
|
||||
},
|
||||
"window.zoomLevel": 1,
|
||||
"workbench.iconTheme": "vscode-icons",
|
||||
"workbench.iconTheme": "material-icon-theme",
|
||||
"prettier.enable": true,
|
||||
"editor.formatOnSave": false,
|
||||
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, useTemplateRef } from 'vue';
|
||||
import { showToast } from 'vant';
|
||||
import { useSetPieChart } from '@/hooks/chart/usePieChart';
|
||||
import { surveys } from '@/components/Analysis/hooks/useSurvey';
|
||||
import { questionTypeMap } from '@/utils/question/typeMapping';
|
||||
|
||||
// series 信息
|
||||
const series = defineModel<any>('series', { required: true });
|
||||
@@ -19,7 +16,7 @@ useSetPieChart(pieChart, series, { title: false, legend: false });
|
||||
<div
|
||||
style="display: flex; height: 300px; width: 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>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
const option = {
|
||||
// title: {
|
||||
// text: 'Referer of a Website',
|
||||
@@ -36,13 +34,4 @@ const option = {
|
||||
]
|
||||
};
|
||||
|
||||
export const pieOption = ref<Partial<typeof option>>(option);
|
||||
|
||||
// 删除左侧的预览图
|
||||
export function deleteLegend() {
|
||||
delete pieOption.value.legend;
|
||||
}
|
||||
|
||||
export function deleteTitle() {
|
||||
delete pieOption.value.title;
|
||||
}
|
||||
export const pieOption = option;
|
||||
@@ -1,60 +1,36 @@
|
||||
import { onMounted, ref, type ShallowRef, watch } from 'vue';
|
||||
import type { ECOption } from '@/utils/echarts';
|
||||
import { chart } from '@/utils/echarts';
|
||||
import { deleteLegend, deleteTitle } from './data/pie';
|
||||
import { pieOption } from './data/pie';
|
||||
|
||||
type dataOption = Partial<ECOption['data']>;
|
||||
|
||||
/**
|
||||
* 饼图的 option
|
||||
*/
|
||||
// const option = ref(pieOption);
|
||||
|
||||
function useSetPieChart(
|
||||
dom: Readonly<ShallowRef<HTMLSpanElement | null>>,
|
||||
series: any,
|
||||
opts: optsType = {}
|
||||
): void {
|
||||
// 图表实例
|
||||
let pieChart: any;
|
||||
let chartInstance: any;
|
||||
|
||||
// 检测边界范围 dom 和 data 是否存在
|
||||
onMounted(() => {
|
||||
if (!dom.value) {
|
||||
console.error('饼图DOM元素不存在');
|
||||
return;
|
||||
}
|
||||
// 检测边界范围 dom 和 series 是否存在
|
||||
if (!dom.value && !series) return;
|
||||
|
||||
// 在 dom 挂载之后,显示饼图
|
||||
pieChart = chart.init(dom.value);
|
||||
|
||||
if (series.value) {
|
||||
// 创建完整的配置对象
|
||||
const fullOption = {
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: '50%',
|
||||
data: series.value.data || []
|
||||
}
|
||||
]
|
||||
};
|
||||
chartInstance = chart.init(dom.value);
|
||||
pieOption.series = JSON.parse(JSON.stringify(series.value));
|
||||
|
||||
// 设置图表选项
|
||||
pieChart.setOption(fullOption, opts);
|
||||
|
||||
// 强制重绘以确保显示
|
||||
setTimeout(() => {
|
||||
pieChart.resize();
|
||||
}, 100);
|
||||
} else {
|
||||
console.error('饼图数据不存在');
|
||||
}
|
||||
chartInstance.setOption(pieOption, opts);
|
||||
});
|
||||
|
||||
// 如果 data 变动,重新生成图表w
|
||||
watch(series, (value) => {
|
||||
pieChart.value.setOption(value, opts);
|
||||
chartInstance.setOption(value, opts);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
const map = new Map<number, string>();
|
||||
|
||||
map.set(1, '单选题');
|
||||
map.set(2, "多选题")
|
||||
map.set(3, "图片上传题")
|
||||
map.set(5, '数值打分题');
|
||||
map.set(9, '矩阵单选');
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ import { getUserInfo } from '@/api/common/index.js';
|
||||
import { showFailToast } from 'vant';
|
||||
import appBridge from '@/assets/js/appBridge';
|
||||
import ImageSlider from './components/ImageSlider/Index.vue';
|
||||
import MineTask from '@/components/Analysis/Index.vue';
|
||||
import SearchBar from '@/components/Search/Index.vue';
|
||||
import Navigation from '@/components/Navigation/Index.vue';
|
||||
import router from '@/router';
|
||||
|
||||
const contentShow = ref(false);
|
||||
|
||||
@@ -40,11 +41,17 @@ onMounted(async () => {
|
||||
contentShow.value = true;
|
||||
}
|
||||
});
|
||||
|
||||
function handleSearchClick() {
|
||||
router.push({ name: 'search' });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="contentShow" class="container-home">
|
||||
<div class="container-body">
|
||||
<!-- 搜索栏 -->
|
||||
<search-bar @click="handleSearchClick" />
|
||||
<!-- 首页轮播图 -->
|
||||
<image-slider />
|
||||
<create-survey :createdNewPage="false" />
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import {
|
||||
getSurveysPage, deleteSurveys,
|
||||
saveTemplates
|
||||
} from '@/api/home';
|
||||
import { getSurveysPage, deleteSurveys, saveTemplates } from '@/api/home';
|
||||
import { ref } from 'vue';
|
||||
import {
|
||||
showDialog,
|
||||
showConfirmDialog,
|
||||
showFailToast,
|
||||
showToast
|
||||
} from 'vant';
|
||||
import { showDialog, showConfirmDialog, showFailToast, showToast } from 'vant';
|
||||
import { getSurveysDetail } from '@/api/design';
|
||||
|
||||
const form = ref({
|
||||
@@ -45,7 +37,8 @@ async function fetchSurveys() {
|
||||
total.value = res.data.meta.total;
|
||||
survey.value.forEach((item) => {
|
||||
const sceneName = JSON.parse(JSON.stringify(item.scene_name));
|
||||
const nameList = sceneName.split('-');
|
||||
|
||||
const nameList = sceneName ? sceneName.split('-') : [];
|
||||
if (nameList.length > 0) {
|
||||
item.scene_name = nameList[1] ? nameList[1] : nameList[0];
|
||||
}
|
||||
@@ -85,7 +78,7 @@ function deleteItem(item: SurveyItem) {
|
||||
.catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// 保存为模板
|
||||
async function saveTemplate(item: SurveyItem) {
|
||||
@@ -113,5 +106,4 @@ export {
|
||||
saveTemplate,
|
||||
currentSurvey,
|
||||
fetchSingleSurvey
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,8 @@ const route = useRoute();
|
||||
* 如果当前问卷的数据不存在,重新获取数据
|
||||
*/
|
||||
if (!currentSurvey.value) fetchSingleSurvey(route.query.sn as string);
|
||||
// 重置 message 信息
|
||||
aiInsightsConfig.value.message = '';
|
||||
|
||||
useFetchAnalysis(route.query.sn as string);
|
||||
</script>
|
||||
@@ -45,7 +47,7 @@ useFetchAnalysis(route.query.sn as string);
|
||||
</template>
|
||||
</van-cell>
|
||||
|
||||
<van-cell v-if="aiInsightsConfig.message.length > 0" class="ai-insight">
|
||||
<van-cell v-if="aiInsightsConfig.message.length > 0" class="ai-insight" :key="route">
|
||||
<template #extra>
|
||||
<!-- ai 洞察部分内容 -->
|
||||
<div v-html="aiInsightsConfig.message" />
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<section v-for="analysis in questionAnalysis" :key="analysis.stem">
|
||||
<section
|
||||
v-for="analysis in questionAnalysis"
|
||||
:key="analysis.stem"
|
||||
v-if="analysis?.option.length"
|
||||
>
|
||||
<el-tag>{{ questionTypeMap.get(analysis.question_type as number) }}</el-tag>
|
||||
{{ analysis.stem }}
|
||||
|
||||
<chart-msg :series="formatData(analysis)" />
|
||||
|
||||
{{ analysis }}
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
@@ -13,7 +19,5 @@
|
||||
import { questionAnalysis } from '../../hooks/useAnalysis';
|
||||
import { questionTypeMap } from '@/utils/question/typeMapping';
|
||||
import ChartMsg from '@/components/Analysis/Index.vue';
|
||||
import { formatData, series } from './hooks/pieSeries';
|
||||
|
||||
console.log(`question analysis info`, questionAnalysis.value);
|
||||
import { formatData } from './hooks/pieSeries';
|
||||
</script>
|
||||
|
||||
@@ -23,12 +23,12 @@ export const series = ref({
|
||||
});
|
||||
|
||||
export function formatData(data: any) {
|
||||
const _series = ref(JSON.parse(JSON.stringify(series.value)));
|
||||
const _series = JSON.parse(JSON.stringify(series.value));
|
||||
|
||||
// 当内容为单选的时候处理方式
|
||||
if (data.question_index === 2) {
|
||||
if (data.question_index === 2 || data.question_index === 1) {
|
||||
const { option } = data;
|
||||
_series.value.data = option.map((item: any) => {
|
||||
_series.data = option.map((item: any) => {
|
||||
return {
|
||||
value: item.number,
|
||||
name: item.title
|
||||
|
||||
Reference in New Issue
Block a user