Files
ylst-h5/src/views/Survey/components/SurveyItem.vue
Huangzhe 9f8fc0a31a feat: 问卷分析页面功能实现
- 修复路径别名问题
- 添加问卷类型映射工具
- 实现饼图数据格式化功能
- 优化图表组件传参方式
- 重构分析信息展示组件
2025-05-15 01:16:29 +08:00

340 lines
8.9 KiB
Vue

<script setup lang="ts">
import png11 from '@/assets/img/home/11.png';
import png13 from '@/assets/img/home/13.png';
import png14 from '@/assets/img/home/14.png';
import png15 from '@/assets/img/home/15.png';
import png16 from '@/assets/img/home/16.png';
import png17 from '@/assets/img/home/17.png';
import png18 from '@/assets/img/home/18.png';
import png31 from '@/assets/img/home/31.png';
import { showDialog, showFailToast, showSuccessToast } from 'vant';
import { finish } from '@/api/survey';
import { copySurveys } from '@/api/home';
import { useRouter } from 'vue-router';
import {
form,
fetchSurveys,
deleteItem,
saveTemplate,
currentSurvey
} from '@/views/Survey/hooks/useSurveyData';
// router
const router = useRouter();
const emit = defineEmits(['post-analysis', 'post-surveys']);
const survey = defineModel<SurveyItem>('survey', { required: true });
const isAnalysis = defineModel('isAnalysis', { default: false, type: Boolean });
const postAnalysis = defineModel<Function>('post-analysis');
function setImg(code: number) {
const imageMap: { [key: number]: string } = {
11: png11,
13: png13,
14: png14,
15: png15,
16: png16,
17: png17,
18: png18,
31: png31
};
// 默认返回 png11 如果 code 不存在
return imageMap[code] || png11;
}
function editItem(item: SurveyItem) {
router.push({
path: '/create',
query: {
sn: item.sn
}
});
}
function toPreview(item: SurveyItem) {
router.push({
path: '/preview',
query: {
sn: item.sn,
name: item.project_name,
source: 0
}
});
}
/**
* 跳转 统计分析 页面
* @param item
*/
function toAnalysis(item: SurveyItem) {
// 设置当前的节点信息
currentSurvey.value = item;
// 跳转
router.push({
path: '/analysis',
query: {
sn: item.sn
}
});
}
function toPublish(item: SurveyItem) {
if (item.status === 1) {
showDialog({
title: `确定要取消投放${item.project_name}?`,
showCancelButton: true
})
.then(() => {
finish(item.sn).then((res) => {
if (res.data) {
// 把数据改掉
item.status = 2;
}
});
})
.catch(() => {
// on cancel
});
} else {
router.push({
path: '/publish',
query: {
sn: item.sn
}
});
}
}
function copyItem(item: SurveyItem) {
showDialog({
title: `确认复制问卷${item.project_name} ?`,
showCancelButton: true,
confirmButtonColor: '#03B03C'
})
.then(async () => {
const res = await copySurveys(item.sn);
if (res.data.code === 200 || res.data.code === 201) {
showSuccessToast('复制成功');
form.value.page = 1;
survey.value = [];
await fetchSurveys();
} else {
showFailToast(res.data);
}
})
.catch(() => {
// on cancel
});
}
</script>
<template>
<section>
<!-- 问卷详情 -->
<div class="survey_item_info">
<div style="position: relative">
<div class="survey_item_info_title">
<el-text>
<b v-html="survey.project_name"></b>
</el-text>
<el-text>{{ survey.answer_num }}</el-text>
<el-text v-if="survey.is_time" size="small">
{{ `${survey.start_time} ${survey.end_time ?? '无限期'}` }}
</el-text>
<el-button
v-if="isAnalysis"
style="margin-left: 30px"
type="primary"
size="small"
@click="emit('post-analysis')"
>
AI 洞察
</el-button>
</div>
<div class="survey_item_info_status">
<el-space spacer="|">
<!--报名签到-->
<div class="flex align-center">
<img
:src="setImg(survey.scene_code_info as number)"
alt="Content Icon"
style="width: 15px; height: 15px"
/>
<el-text size="small">{{ survey.owner }}</el-text>
</div>
<!-- 问卷来源 -->
<div class="flex align-center">
<img v-if="survey.source === 1" src="@/assets/img/publish/phone.png" alt="" />
<img v-else src="@/assets/img/publish/pc.png" alt="" />
<el-text size="small">
{{ survey.source === 1 ? '移动端' : 'PC端' }}
</el-text>
</div>
<!-- 问卷时间 -->
<div class="flex align-center">
<img src="@/assets/img/publish/time.png" alt="" />
<el-text size="small">{{ survey.created_at }}</el-text>
</div>
</el-space>
</div>
<div v-if="!isAnalysis" class="survey_item_status">
<img v-if="survey.status === 0" src="@/assets/img/publish/edit.png" alt="" />
<img v-else-if="survey.status === 1" src="@/assets/img/publish/publish.png" alt="" />
<img v-else-if="survey.status === 2" src="@/assets/img/publish/end.png" alt="" />
</div>
</div>
<!--问卷描述-->
<el-space class="survey_item_info_desc" spacer="|">
<section>
<el-text size="small">回收数量</el-text>
<el-text> {{ survey.answer_num }}</el-text>
</section>
<section>
<el-text size="small">回收数量进度</el-text>
<el-text>{{ survey.recycle_progress }}</el-text>
</section>
<section>
<el-text size="small">投放时间进度</el-text>
<el-text> {{ survey.recycle_time }}</el-text>
</section>
</el-space>
</div>
<!-- action 功能位置 -->
<div v-if="!isAnalysis" class="survey_item_action">
<div>
<el-button :disabled="survey.source === 0" @click="editItem(survey)"> 编辑 </el-button>
<!-- <el-button-->
<!-- style="border: 1px solid #71b73c"-->
<!-- @click="toPreview(survey)"-->
<!-- >-->
<!-- <el-text style="color: #71b73c">预览</el-text>-->
<!-- </el-button>-->
<el-button style="border: 1px solid #71b73c" @click="toAnalysis(survey)">
<el-text style="color: #71b73c">统计</el-text>
</el-button>
<el-button color="#6fb937" @click="toPublish(survey)">
<el-text style="color: white">
{{ survey.status === 1 ? '结束投放' : '开启投放' }}
</el-text>
</el-button>
</div>
<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>
<template #dropdown>
<el-dropdown-menu
active-color="#71b73c"
:close-on-click-overlay="false"
:close-on-click-outside="false"
>
<el-dropdown-item @click="copyItem(survey)"> 复制 </el-dropdown-item>
<el-dropdown-item @click="deleteItem(survey)"> 删除 </el-dropdown-item>
<el-dropdown-item @click="saveTemplate(survey)"> 保存为模板 </el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</section>
</template>
<style scoped lang="scss">
@import '@/assets/css/base';
@import '@/assets/css/main';
.survey_item_info {
.survey_item_info_status {
display: flex;
margin-bottom: 15px;
img {
height: 12px;
margin-right: 3px;
}
}
.survey_item_status {
position: absolute;
top: -16px;
right: -10px;
}
.survey_item_info_title {
display: flex;
.el-text {
font-size: 15px;
&:first-child {
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
& > :nth-child(2) {
position: relative;
left: 10px;
padding: 1px 3px;
border: 2px solid #f5f5f5;
border-radius: 6px;
font-size: 12px;
}
}
.survey_item_info_desc {
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: space-around;
border-radius: 8px;
background-color: #f6f7f8;
overflow: hidden;
text-overflow: ellipsis;
padding: 10px 15px;
box-sizing: border-box;
margin: 0 10px 10px 10px;
color: #828282;
font-weight: 400;
font-size: 12px;
section {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
& > :nth-last-child(-n + 1) {
font-size: 20px;
font-weight: bold;
color: $theme-color;
}
}
}
}
.survey_item_action {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px;
border-top: 1px dashed #f5f5f5;
.el-button {
width: 18vw;
border-radius: 8px;
}
.el-space {
display: flex;
justify-content: space-evenly;
}
}
</style>