feat: 问卷分析页面功能实现
- 修复路径别名问题 - 添加问卷类型映射工具 - 实现饼图数据格式化功能 - 优化图表组件传参方式 - 重构分析信息展示组件
This commit is contained in:
7
components.d.ts
vendored
7
components.d.ts
vendored
@@ -11,6 +11,7 @@ declare module 'vue' {
|
|||||||
Contenteditable: typeof import('./src/components/contenteditable.vue')['default']
|
Contenteditable: typeof import('./src/components/contenteditable.vue')['default']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
@@ -22,6 +23,7 @@ declare module 'vue' {
|
|||||||
ElSpace: typeof import('element-plus/es')['ElSpace']
|
ElSpace: typeof import('element-plus/es')['ElSpace']
|
||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||||
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElText: typeof import('element-plus/es')['ElText']
|
ElText: typeof import('element-plus/es')['ElText']
|
||||||
Index: typeof import('./src/components/Analysis/Index.vue')['default']
|
Index: typeof import('./src/components/Analysis/Index.vue')['default']
|
||||||
MarketItem: typeof import('./src/components/MarketItem/MarketItem.vue')['default']
|
MarketItem: typeof import('./src/components/MarketItem/MarketItem.vue')['default']
|
||||||
@@ -34,6 +36,7 @@ declare module 'vue' {
|
|||||||
VanCellGroup: typeof import('vant/es')['CellGroup']
|
VanCellGroup: typeof import('vant/es')['CellGroup']
|
||||||
VanCheckbox: typeof import('vant/es')['Checkbox']
|
VanCheckbox: typeof import('vant/es')['Checkbox']
|
||||||
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
|
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
|
||||||
|
VanCol: typeof import('vant/es')['Col']
|
||||||
VanDivider: typeof import('vant/es')['Divider']
|
VanDivider: typeof import('vant/es')['Divider']
|
||||||
VanField: typeof import('vant/es')['Field']
|
VanField: typeof import('vant/es')['Field']
|
||||||
VanIcon: typeof import('vant/es')['Icon']
|
VanIcon: typeof import('vant/es')['Icon']
|
||||||
@@ -44,6 +47,7 @@ declare module 'vue' {
|
|||||||
VanPopup: typeof import('vant/es')['Popup']
|
VanPopup: typeof import('vant/es')['Popup']
|
||||||
VanRadio: typeof import('vant/es')['Radio']
|
VanRadio: typeof import('vant/es')['Radio']
|
||||||
VanRadioGroup: typeof import('vant/es')['RadioGroup']
|
VanRadioGroup: typeof import('vant/es')['RadioGroup']
|
||||||
|
VanRow: typeof import('vant/es')['Row']
|
||||||
VanSearch: typeof import('vant/es')['Search']
|
VanSearch: typeof import('vant/es')['Search']
|
||||||
VanSpace: typeof import('vant/es')['Space']
|
VanSpace: typeof import('vant/es')['Space']
|
||||||
VanStepper: typeof import('vant/es')['Stepper']
|
VanStepper: typeof import('vant/es')['Stepper']
|
||||||
@@ -60,4 +64,7 @@ declare module 'vue' {
|
|||||||
YLPicker: typeof import('./src/components/YLPicker.vue')['default']
|
YLPicker: typeof import('./src/components/YLPicker.vue')['default']
|
||||||
YLSelect: typeof import('./src/components/YLSelect.vue')['default']
|
YLSelect: typeof import('./src/components/YLSelect.vue')['default']
|
||||||
}
|
}
|
||||||
|
export interface ComponentCustomProperties {
|
||||||
|
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,3 +11,15 @@ export function analysisInsights (sn: string, params?: ParticalParams) {
|
|||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* ai 洞察检查分析是否完成
|
||||||
|
* @param sn 循环题组sn
|
||||||
|
* @param data {1|2} 1=AI样本标记;2=AI洞察
|
||||||
|
*/
|
||||||
|
export function checkAnalysisSatus(sn: string, data?: 1 | 2) {
|
||||||
|
return request({
|
||||||
|
url: `/console/surveys/${sn}/status`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function getSurveyInfo(sn) {
|
|||||||
* @param data {import('@/api/types/analysis.js').AnalysisParam}
|
* @param data {import('@/api/types/analysis.js').AnalysisParam}
|
||||||
* @returns {Promise<axios.AxiosResponse<any>> | *}
|
* @returns {Promise<axios.AxiosResponse<any>> | *}
|
||||||
*/
|
*/
|
||||||
export function surveyAnalysis(sn, data) {
|
export function surveyAnalysis(sn, data = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: `/console/surveys/${sn}/chart_analysis`,
|
url: `/console/surveys/${sn}/chart_analysis`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
|||||||
@@ -3,94 +3,23 @@ import { ref, useTemplateRef } from 'vue';
|
|||||||
import { showToast } from 'vant';
|
import { showToast } from 'vant';
|
||||||
import { useSetPieChart } from '@/hooks/chart/usePieChart';
|
import { useSetPieChart } from '@/hooks/chart/usePieChart';
|
||||||
import { surveys } from '@/components/Analysis/hooks/useSurvey';
|
import { surveys } from '@/components/Analysis/hooks/useSurvey';
|
||||||
|
import { questionTypeMap } from '@/utils/question/typeMapping';
|
||||||
|
|
||||||
|
// const info = defineModel<any>('info', { required: true });
|
||||||
|
// series 信息
|
||||||
|
const series = defineModel<any>('series', { required: true });
|
||||||
// 饼图 dom 结构
|
// 饼图 dom 结构
|
||||||
const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
|
const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
|
||||||
|
|
||||||
useSetPieChart(pieChart, [1], { title: false, ledge: false });
|
useSetPieChart(pieChart, series.value, { title: false, ledge: false });
|
||||||
|
|
||||||
// 任务数据
|
|
||||||
const taskData = ref({
|
|
||||||
title: '问卷A',
|
|
||||||
progress: 100,
|
|
||||||
deadline: '2025-03-31至04-01',
|
|
||||||
creator: '张三',
|
|
||||||
creationMethod: '移动端',
|
|
||||||
creationTime: '2025-03-04',
|
|
||||||
responseCount: 10,
|
|
||||||
responseRate: '10%',
|
|
||||||
submissionRate: '10%',
|
|
||||||
status: '草稿中'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 图表数据
|
|
||||||
const chartData = ref([
|
|
||||||
{
|
|
||||||
name: '选项1',
|
|
||||||
value: 66.77,
|
|
||||||
color: '#F56C6C'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '选项2',
|
|
||||||
value: 33.33,
|
|
||||||
color: '#F7BA2A'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '选项3',
|
|
||||||
value: 0,
|
|
||||||
color: '#67C23A'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '选项4',
|
|
||||||
value: 0,
|
|
||||||
color: '#409EFF'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 导航按钮点击事件
|
|
||||||
const handlePrev = () => {
|
|
||||||
showToast('点击了上一个问题');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleNext = () => {
|
|
||||||
showToast('点击了下一个问题');
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<!-- 卡片内容 -->
|
|
||||||
<van-space direction="vertical" fill style="width: 100%; padding-top: 16px">
|
|
||||||
<p>1. 能描述您为自己或家人购买这款产品A的可能性吗?(单选)</p>
|
|
||||||
|
|
||||||
<!-- 图表部分 -->
|
<!-- 图表部分 -->
|
||||||
<div style="display: flex; justify-content: center; margin: 16px 0">
|
<div style="display: flex; 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>
|
||||||
|
|
||||||
<!-- 选项列表 -->
|
|
||||||
<van-cell-group inset>
|
|
||||||
<van-cell v-for="(item, index) in chartData" :key="index">
|
|
||||||
<template #title>
|
|
||||||
<van-tag :color="item.value > 0 ? item.color : '#dcdfe6'" plain>
|
|
||||||
{{ item.name }}
|
|
||||||
</van-tag>
|
|
||||||
</template>
|
|
||||||
<template #value>
|
|
||||||
<span>{{ item.value.toFixed(2) }}%</span>
|
|
||||||
</template>
|
|
||||||
</van-cell>
|
|
||||||
</van-cell-group>
|
|
||||||
</van-space>
|
|
||||||
<!-- 导航按钮 左右按钮-->
|
|
||||||
<!-- <div style="position: fixed; left: 16px; top: 50%; transform: translateY(-50%)">-->
|
|
||||||
<!-- <van-button round icon="arrow-left" @click="handlePrev" />-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- <div style="position: fixed; right: 16px; top: 50%; transform: translateY(-50%)">-->
|
|
||||||
<!-- <van-button round icon="arrow" @click="handleNext" />-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -9,27 +9,27 @@ const pieChart = ref();
|
|||||||
/**
|
/**
|
||||||
* 定义数据集
|
* 定义数据集
|
||||||
*/
|
*/
|
||||||
const series = ref<dataOption[]>([
|
// const series = ref<dataOption[]>([
|
||||||
{
|
// {
|
||||||
name: 'Access From',
|
// name: 'Access From',
|
||||||
type: 'pie',
|
// type: 'pie',
|
||||||
radius: '50%',
|
// radius: '50%',
|
||||||
data: [
|
// data: [
|
||||||
{ value: 1048, name: 'Search Engine' },
|
// { value: 1048, name: 'Search Engine' },
|
||||||
{ value: 735, name: 'Direct' },
|
// { value: 735, name: 'Direct' },
|
||||||
{ value: 580, name: 'Email' },
|
// { value: 580, name: 'Email' },
|
||||||
{ value: 484, name: 'Union Ads' },
|
// { value: 484, name: 'Union Ads' },
|
||||||
{ value: 300, name: 'Video Ads' }
|
// { value: 300, name: 'Video Ads' }
|
||||||
],
|
// ],
|
||||||
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)'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 饼图的 option
|
* 饼图的 option
|
||||||
@@ -38,18 +38,18 @@ const option = ref(pieOption);
|
|||||||
|
|
||||||
function useSetPieChart(
|
function useSetPieChart(
|
||||||
dom: Readonly<ShallowRef<HTMLSpanElement | null>>,
|
dom: Readonly<ShallowRef<HTMLSpanElement | null>>,
|
||||||
data: any[],
|
series: any,
|
||||||
opts: optsType = {}
|
opts: optsType = {}
|
||||||
): void {
|
): void {
|
||||||
for (let item in opts) {
|
if (!series) return;
|
||||||
|
for (const item in opts) {
|
||||||
if (item === 'legend') !opts[item] && deleteLegend();
|
if (item === 'legend') !opts[item] && deleteLegend();
|
||||||
else if (item === 'title') !opts[item] && deleteTitle();
|
else if (item === 'title') !opts[item] && deleteTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检测边界范围 dom 和 data 是否存在
|
// 检测边界范围 dom 和 data 是否存在
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// console.log(dom);
|
if (!dom || series.data.length === 0) return;
|
||||||
if (!dom || data.length === 0) return;
|
|
||||||
// 在 dom 挂载之后,显示饼图
|
// 在 dom 挂载之后,显示饼图
|
||||||
pieChart.value = chart.init(dom.value);
|
pieChart.value = chart.init(dom.value);
|
||||||
pieChart.value.setOption(option.value, opts);
|
pieChart.value.setOption(option.value, opts);
|
||||||
|
|||||||
7
src/utils/question/typeMapping.ts
Normal file
7
src/utils/question/typeMapping.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const map = new Map<number, string>();
|
||||||
|
|
||||||
|
map.set(1, '单选题');
|
||||||
|
map.set(5, '数值打分题');
|
||||||
|
map.set(9, '矩阵单选');
|
||||||
|
|
||||||
|
export { map as questionTypeMap };
|
||||||
@@ -11,7 +11,13 @@ import { showDialog, showFailToast, showSuccessToast } from 'vant';
|
|||||||
import { finish } from '@/api/survey';
|
import { finish } from '@/api/survey';
|
||||||
import { copySurveys } from '@/api/home';
|
import { copySurveys } from '@/api/home';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { form, fetchSurveys, deleteItem, saveTemplate, currentSurvey } from '@/views/Survey/hooks/useSurveyData';
|
import {
|
||||||
|
form,
|
||||||
|
fetchSurveys,
|
||||||
|
deleteItem,
|
||||||
|
saveTemplate,
|
||||||
|
currentSurvey
|
||||||
|
} from '@/views/Survey/hooks/useSurveyData';
|
||||||
|
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -119,7 +125,6 @@ function copyItem (item: SurveyItem) {
|
|||||||
// on cancel
|
// on cancel
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -136,14 +141,25 @@ function copyItem (item: SurveyItem) {
|
|||||||
{{ `${survey.start_time} 至 ${survey.end_time ?? '无限期'}` }}
|
{{ `${survey.start_time} 至 ${survey.end_time ?? '无限期'}` }}
|
||||||
</el-text>
|
</el-text>
|
||||||
|
|
||||||
<el-button v-if="isAnalysis" type="primary" size="small" @click="emit('post-analysis')">AI 洞察</el-button>
|
<el-button
|
||||||
|
v-if="isAnalysis"
|
||||||
|
style="margin-left: 30px"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="emit('post-analysis')"
|
||||||
|
>
|
||||||
|
AI 洞察
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="survey_item_info_status">
|
<div class="survey_item_info_status">
|
||||||
<el-space spacer="|">
|
<el-space spacer="|">
|
||||||
<!--报名签到-->
|
<!--报名签到-->
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img :src="setImg(survey.scene_code_info as number)" alt="Content Icon"
|
<img
|
||||||
style="width: 15px; height: 15px" />
|
:src="setImg(survey.scene_code_info as number)"
|
||||||
|
alt="Content Icon"
|
||||||
|
style="width: 15px; height: 15px"
|
||||||
|
/>
|
||||||
<el-text size="small">{{ survey.owner }}</el-text>
|
<el-text size="small">{{ survey.owner }}</el-text>
|
||||||
</div>
|
</div>
|
||||||
<!-- 问卷来源 -->
|
<!-- 问卷来源 -->
|
||||||
@@ -186,9 +202,7 @@ function copyItem (item: SurveyItem) {
|
|||||||
<!-- action 功能位置 -->
|
<!-- action 功能位置 -->
|
||||||
<div v-if="!isAnalysis" class="survey_item_action">
|
<div v-if="!isAnalysis" class="survey_item_action">
|
||||||
<div>
|
<div>
|
||||||
<el-button :disabled="survey.source === 0" @click="editItem(survey)">
|
<el-button :disabled="survey.source === 0" @click="editItem(survey)"> 编辑 </el-button>
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<!-- <el-button-->
|
<!-- <el-button-->
|
||||||
<!-- style="border: 1px solid #71b73c"-->
|
<!-- style="border: 1px solid #71b73c"-->
|
||||||
<!-- @click="toPreview(survey)"-->
|
<!-- @click="toPreview(survey)"-->
|
||||||
@@ -205,19 +219,22 @@ function copyItem (item: SurveyItem) {
|
|||||||
</el-text>
|
</el-text>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown v-if="survey.source === 1" placement="top-end" trigger="click" active-color="#71b73c">
|
<el-dropdown
|
||||||
|
v-if="survey.source === 1"
|
||||||
|
placement="top-end"
|
||||||
|
trigger="click"
|
||||||
|
active-color="#71b73c"
|
||||||
|
>
|
||||||
<van-icon class-prefix="mobilefont" name="gengduo" size="0.7rem"></van-icon>
|
<van-icon class-prefix="mobilefont" name="gengduo" size="0.7rem"></van-icon>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu active-color="#71b73c" :close-on-click-overlay="false" :close-on-click-outside="false">
|
<el-dropdown-menu
|
||||||
<el-dropdown-item @click="copyItem(survey)">
|
active-color="#71b73c"
|
||||||
复制
|
:close-on-click-overlay="false"
|
||||||
</el-dropdown-item>
|
:close-on-click-outside="false"
|
||||||
<el-dropdown-item @click="deleteItem(survey)">
|
>
|
||||||
删除
|
<el-dropdown-item @click="copyItem(survey)"> 复制 </el-dropdown-item>
|
||||||
</el-dropdown-item>
|
<el-dropdown-item @click="deleteItem(survey)"> 删除 </el-dropdown-item>
|
||||||
<el-dropdown-item @click="saveTemplate(survey)">
|
<el-dropdown-item @click="saveTemplate(survey)"> 保存为模板 </el-dropdown-item>
|
||||||
保存为模板
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@@ -226,8 +243,8 @@ function copyItem (item: SurveyItem) {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "@/assets/css/base";
|
@import '@/assets/css/base';
|
||||||
@import "@/assets/css/main";
|
@import '@/assets/css/main';
|
||||||
|
|
||||||
.survey_item_info {
|
.survey_item_info {
|
||||||
.survey_item_info_status {
|
.survey_item_info_status {
|
||||||
|
|||||||
@@ -4,16 +4,21 @@ import SurveyItem from '@/views/Survey/components/SurveyItem.vue';
|
|||||||
import LogicInfo from '@/views/Survey/views/Analysis/components/LogicInfo/Index.vue';
|
import LogicInfo from '@/views/Survey/views/Analysis/components/LogicInfo/Index.vue';
|
||||||
import AiInsightResults from '@/views/Survey/views/Analysis/components/AiInsightResults/Index.vue';
|
import AiInsightResults from '@/views/Survey/views/Analysis/components/AiInsightResults/Index.vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useFetchAnalysis, postAnalysis, aiInsightsConfig } from '@/views/Survey/views/Analysis/hooks/useAnalysis';
|
import {
|
||||||
|
useFetchAnalysis,
|
||||||
|
postAnalysis,
|
||||||
|
aiInsightsConfig
|
||||||
|
} from '@/views/Survey/views/Analysis/hooks/useAnalysis';
|
||||||
import Wait from '@/views/Survey/views/Analysis/components/Wait/Index.vue';
|
import Wait from '@/views/Survey/views/Analysis/components/Wait/Index.vue';
|
||||||
|
import AnalysisInfo from '@/views/Survey/views/Analysis/components/AnalysisInfo/Index.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
/**
|
/**
|
||||||
* 如果当前问卷的数据不存在,重新获取数据
|
* 如果当前问卷的数据不存在,重新获取数据
|
||||||
*/
|
*/
|
||||||
if (!currentSurvey.value) fetchSingleSurvey(<string>route.query.sn);
|
if (!currentSurvey.value) fetchSingleSurvey(route.query.sn as string);
|
||||||
|
|
||||||
useFetchAnalysis(<string>route.query.sn);
|
useFetchAnalysis(route.query.sn as string);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -21,11 +26,14 @@ useFetchAnalysis(<string>route.query.sn);
|
|||||||
<!-- 问卷详情部分 -->
|
<!-- 问卷详情部分 -->
|
||||||
<van-cell class="survey-item">
|
<van-cell class="survey-item">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<survey-item @post-analysis="postAnalysis(route.query.sn as string)" :is-analysis="true"
|
<survey-item
|
||||||
:survey="<SurveyItem>currentSurvey" />
|
:is-analysis="true"
|
||||||
|
:survey="currentSurvey as SurveyItem"
|
||||||
|
@post-analysis="postAnalysis(route.query.sn as string)"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 弹窗组件 -->
|
<!-- 弹窗组件 -->
|
||||||
<el-dialog align-center width="70%" v-model="aiInsightsConfig.visible">
|
<el-dialog v-model="aiInsightsConfig.visible" align-center width="70%">
|
||||||
<wait />
|
<wait />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
@@ -37,19 +45,24 @@ useFetchAnalysis(<string>route.query.sn);
|
|||||||
</template>
|
</template>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
|
|
||||||
<van-cell class="ai-insight">
|
<van-cell v-if="false" class="ai-insight">
|
||||||
|
<template #extra>
|
||||||
<!-- ai 洞察部分内容 -->
|
<!-- ai 洞察部分内容 -->
|
||||||
<AiInsightResults />
|
<AiInsightResults />
|
||||||
|
</template>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
|
|
||||||
<van-cell class="analysis">
|
<van-cell class="analysis">
|
||||||
|
<template #extra>
|
||||||
<!-- 图表分析部分 -->
|
<!-- 图表分析部分 -->
|
||||||
|
<analysis-info />
|
||||||
|
</template>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@use "@/assets/css/theme";
|
@use '@/assets/css/theme';
|
||||||
|
|
||||||
.survey-container {
|
.survey-container {
|
||||||
padding: theme.$gap;
|
padding: theme.$gap;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<section v-for="analysis in questionAnalysis" :key="analysis.stem">
|
||||||
|
<el-tag>{{ questionTypeMap.get(analysis.question_type as number) }}</el-tag>
|
||||||
|
{{ analysis.stem }}
|
||||||
|
|
||||||
|
<chart-msg :series="formatData(analysis)" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
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);
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
export const series = ref({
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['40%', '70%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
});
|
||||||
|
|
||||||
|
export function formatData(data: any) {
|
||||||
|
console.log(data);
|
||||||
|
const { option } = data;
|
||||||
|
|
||||||
|
series.value.data = option.map((item) => {
|
||||||
|
return {
|
||||||
|
value: item.number,
|
||||||
|
name: item.title
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`series data`, series.value);
|
||||||
|
|
||||||
|
return series.value;
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { surveyAnalysis } from '@/api/survey';
|
import { surveyAnalysis } from '@/api/survey';
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { analysisInsights } from '@/api/anslysis/aiInsight';
|
import { analysisInsights, checkAnalysisSatus } from '@/api/anslysis/aiInsight';
|
||||||
|
|
||||||
type AiInsightType = {
|
type AiInsightType = {
|
||||||
visible: boolean,
|
visible: boolean;
|
||||||
timer: NodeJS.Timeout | undefined
|
timer: NodeJS.Timeout | undefined;
|
||||||
}
|
};
|
||||||
// ai 智能洞察
|
// ai 智能洞察
|
||||||
export const aiInsightsConfig = ref<AiInsightType>({
|
export const aiInsightsConfig = ref<AiInsightType>({
|
||||||
visible: false,
|
visible: false,
|
||||||
timer: void 0
|
timer: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const questionAnalysis = ref();
|
const questionAnalysis = ref();
|
||||||
@@ -20,23 +20,28 @@ const params: AnalysisParam = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function postAnalysis(sn: string) {
|
export function postAnalysis(sn: string) {
|
||||||
console.log(sn);
|
|
||||||
aiInsightsConfig.value.visible = true;
|
aiInsightsConfig.value.visible = true;
|
||||||
// analysisInsights(sn);
|
analysisInsights(sn);
|
||||||
if (!aiInsightsConfig.value.timer) {
|
if (!aiInsightsConfig.value.timer) {
|
||||||
// 每 1 s 检查一次是否分析完成
|
// 每 1 s 检查一次是否分析完成
|
||||||
aiInsightsConfig.value.timer = setInterval(() => {
|
aiInsightsConfig.value.timer = setInterval(() => {
|
||||||
checkAnalysis(sn);
|
checkAnalysis(sn);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 当组件取消挂载时, 取消 interval 定时
|
||||||
|
clearInterval(aiInsightsConfig.value.timer);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkAnalysis (sn: string) {
|
export async function checkAnalysis(sn: string) {
|
||||||
console.log(sn);
|
const res = checkAnalysisSatus(sn, 2);
|
||||||
|
console.log(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function useFetchAnalysis(sn: string) {
|
async function useFetchAnalysis(sn: string) {
|
||||||
const res = await surveyAnalysis(sn, params);
|
const res = await surveyAnalysis(sn);
|
||||||
questionAnalysis.value = res.data.data;
|
questionAnalysis.value = res.data.data;
|
||||||
console.log(`question analysis`, questionAnalysis.value);
|
console.log(`question analysis`, questionAnalysis.value);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user