feat(survey): 优化问卷列表和分析页面

- 更新了多个图片资源
- 优化了问卷分析页面的图表展示逻辑
- 调整了导航栏和重定向页面的样式
- 统一了空容器组件的样式
- 优化了问卷列表页面的布局
This commit is contained in:
Huangzhe
2025-05-27 14:40:00 +08:00
parent 2b297d5e80
commit 0dd4600d35
11 changed files with 141 additions and 71 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -6,29 +6,32 @@ import {
getTableData,
setDimensionData
} from '@/views/Survey/views/Analysis/components/AnalysisInfo/hooks/pieSeries';
import EmptyContainer from '@/views/Survey/components/EmptyContainer.vue';
// series 信息
const tableData = ref([]);
const analysis = defineModel<any>('analysis');
// console.log('analysis', analysis.value);
// series 信息
const series = ref([]);
const dimension = defineModel('dimension');
// 图标高度
const chartHeight = computed(() => {
// 需要增加的高度, 由于字多了他就会高度异常,所有要指定一个动态高度
let addHeight = 0;
const optionLength = analysis.value?.option?.length;
// const optionLength = analysis.value?.option?.length;
// 做一些额外的检测, 如果 option 下面的title 字段超过 8 个,就把 addHeight 增加
analysis.value?.option?.forEach((item: any) => {
console.log(item);
if (item.title?.length > 8) {
addHeight += 9;
addHeight += 2;
}
});
console.log(`addHeight`, addHeight);
// 每三个选项高度增加 20px 默认 300px
return dimension.value ? 280 : 280 + (optionLength - 1) * addHeight;
return dimension.value ? 280 : 280 + addHeight;
});
const index = ref(0);
@@ -37,18 +40,17 @@ const index = ref(0);
watch(
() => analysis.value,
async (value) => {
// 排除空数据渲染图标步骤
tableData.value = {
...analysis.value,
option: getTableData(analysis.value)
};
// console.log(`图标的高度是`, chartHeight.value);
// console.log(`tableData.value`, tableData.value);
series.value = formatData(dimension.value ? tableData.value : analysis.value, index.value);
// console.log(`series value`, series.value);
const pieChart = useTemplateRef<HTMLSpanElement>('pieChart');
// console.log(`series value `, series.value);
if (!series.value?.data?.length) return;
useSetPieChart(pieChart, series, { title: false, legend: false });
@@ -60,12 +62,42 @@ const changeChart = (i: number) => {
index.value = i;
series.value = formatData(tableData.value, index.value);
// console.log(`series value. by changeChart`, series.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 });
};
const chartVisible = computed(() => {
/**
* 针对特殊题型做处理,
* 首先就是矩阵的题目 question_type 为 8 9 10
*
* */
if (
analysis.value.question_type === 8 ||
analysis.value.question_type === 9 ||
analysis.value.question_type === 10
) {
// console.log(`series.value on matrix`, series.value?.data);
const data = series.value?.data as { name: any; value: any }[];
// 过滤后的 data 数据,
const filterData = data.filter((item) => item.value != 0 && item.name != 0);
return filterData.length;
// series.value?.data.forEach((item: any`1[]) => {
// if (item.value > 0) {
// return true;
// }
// });
}
return series.value?.data?.length;
});
</script>
<template>
@@ -85,7 +117,7 @@ const changeChart = (i: number) => {
<!-- 图表部分 -->
<div
v-if="series?.data?.length"
v-if="chartVisible"
class="charts"
:style="{
display: 'flex',
@@ -98,10 +130,14 @@ const changeChart = (i: number) => {
ref="pieChart"
:style="{
width: '100%',
height: series?.data?.length ? chartHeight + 'px' : ''
height: chartVisible ? chartHeight + 'px' : ''
}"
></span>
</div>
<!-- 图标没有实例就开始展示空图标 -->
<div v-else>
<empty-container :error-msg="'本题暂无有效答题数据'" />
</div>
</section>
</template>

View File

@@ -17,14 +17,14 @@ const navigation = ref([
icon: 'home-o',
inactive: ''
},
{
title: '伊调研',
// link: {
// name: 'home',
// path: '/home'
// },
icon: yl
},
// {
// title: '伊调研',
// // link: {
// // name: 'home',
// // path: '/home'
// // },
// icon: yl
// },
{
title: '我的',
link: {
@@ -66,7 +66,7 @@ watch(activeTab, (value) => {
<template>
<van-tabbar v-model="activeTab" class="navigation">
<template v-for="(item, index) in navigation" :key="item.title">
<span
<!-- <span
v-if="index === 1"
style="
display: flex;
@@ -77,8 +77,8 @@ watch(activeTab, (value) => {
>
<img :src="item.icon" alt="" style="width: 30px; height: 30px" />
{{ item.title }}
</span>
<van-tabbar-item v-else :icon="item.icon" :name="item.title">
</span> -->
<van-tabbar-item :icon="item.icon" :name="item.title">
{{ item.title }}
</van-tabbar-item>
</template>
@@ -87,7 +87,7 @@ watch(activeTab, (value) => {
<style scoped lang="scss">
.navigation {
padding: 3px 0;
padding: 10px 0;
// width: 100vw;
// background-color: white;
// display: flex;

View File

@@ -3,7 +3,7 @@
<!-- title 标题和搜索栏 -->
<header class="header">
<van-nav-bar
:class="[$route.meta.pureBGC ? '' : 'navbar-header']"
:class="redirectHeaderStyle"
:title="$route.meta.title"
left-arrow
safe-area-inset-top
@@ -31,27 +31,40 @@
</div>
</template>
<script setup>
<script setup lang="ts">
import { RiShareForwardBoxFill } from 'vue-icons-plus/ri';
import { RouterView, useRoute } from 'vue-router';
import appBridge from '@/assets/js/appBridge';
import { computed } from 'vue';
import type { CSSProperties } from 'vue';
const route = useRoute();
// console.log(route.meta.pureBGC);
/**
* 控制 body 的 style
*/
const redirectBodyStyle = computed(() => {
// 背景色控制
const bgc = route.meta.bgc as string;
// 是否纯色背景
const pureBGC = route.meta.pureBGC;
const bgc = route.meta.bgc;
// style 样式
const style = {} as CSSProperties;
// 如果存在 bgc 优先选取 bgc, 如果没有则使用 pureBGC
// pureBGC 为兼容处理
if (bgc) style.background = bgc;
else if (pureBGC) style.background = '#fff';
if (bgc) return { background: bgc };
return style;
});
return {
background: pureBGC ? '#fff' : ''
};
/**
* 控制 header 的 style
*/
const redirectHeaderStyle = computed(() => {
const css = [];
if (route.meta.header?.bgc === 'green') css.push('green-header');
else css.push('navbar-header');
return css;
});
function goBack() {
@@ -97,8 +110,13 @@ const handlePopState = () => {
}
}
.green-header {
background-color: theme.$theme-color;
}
.redirect-body {
overflow: scroll;
width: 100vw;
height: calc(100vh - var(--sticky-top-height) - 1px);
background: transparent;
}

View File

@@ -53,7 +53,15 @@ const router = createRouter({
{
path: '/create',
name: 'create',
meta: { title: '问卷编辑' },
meta: {
title: '问卷编辑',
pureBGC: true,
bgc: '#71b73c',
header: {
bgc: 'green',
pureBGC: false
}
},
component: () => import('../views/Survey/views/Create/Index.vue')
},
{

View File

@@ -1,43 +1,45 @@
<template>
<!-- survey container -->
<div class="survey-search">
<nav-search
v-model:value="searchValue"
@search="handleSearchClick"
@cancel="handleCancelClick"
/>
<!-- <nav-search
<section>
<!-- survey container -->
<div class="survey-search">
<nav-search
v-model:value="searchValue"
@search="handleSearchClick"
@cancel="handleCancelClick"
/>
<!-- <nav-search
placeholder="请输入关键词"
v-model:value="searchValue"
@click="() => $router.push({ name: 'search' })"
/> -->
</div>
<div v-loading="requestLoading" class="new-survey-container">
<div style="margin-bottom: 80px">
<van-list v-model:loading="loading" :finished="finished" @load="handleLoadSurveys">
<template #finished>
<!-- 如果存在搜索文字的话显示没有更多了 -->
<span v-if="searchValue">
<el-text>无符合要求的结果</el-text>
</span>
</template>
<template v-if="survey.length > 0">
<div v-for="item in survey" :key="item" class="new-survey_item">
<survey-item :survey="item" :is-analysis="true" :disable-action-button="false" />
</div>
</template>
<!-- 如果问卷等于0的话显示空容器 -->
<empty-container
v-if="survey.length === 0 && !searchValue"
:img-src="emptyImg"
:show-button="true"
@handle-click="handleEmptyClick"
/>
<NewSurvey v-model:show="showModel" />
</van-list>
</div>
</div>
<div v-loading="requestLoading" class="new-survey-container">
<div style="margin-bottom: 80px">
<van-list v-model:loading="loading" :finished="finished" @load="handleLoadSurveys">
<template #finished>
<!-- 如果存在搜索文字的话显示没有更多了 -->
<span v-if="searchValue">
<el-text>无符合要求的结果</el-text>
</span>
</template>
<template v-if="survey.length > 0">
<div v-for="item in survey" :key="item" class="new-survey_item">
<survey-item :survey="item" :is-analysis="true" :disable-action-button="false" />
</div>
</template>
<!-- 如果问卷等于0的话显示空容器 -->
<empty-container
v-if="survey.length === 0 && !searchValue"
:img-src="emptyImg"
:show-button="true"
@handle-click="handleEmptyClick"
/>
<NewSurvey v-model:show="showModel" />
</van-list>
</div>
</div>
</section>
</template>
<script setup>

View File

@@ -1,9 +1,10 @@
<script setup lang="ts">
import { useCssModule } from 'vue';
import emptyImg from '@/assets/img/emptyImg.png';
const errorMsg = defineModel<string>('errorMsg', { default: ' - 更多任务期待您的创建 - ' });
const showButton = defineModel<boolean>('showButton', { default: false });
const imgSrc = defineModel<string>('imgSrc');
const imgSrc = defineModel<string>('imgSrc', { default: emptyImg });
const emit = defineEmits(['handle-click']);
const style = useCssModule();

View File

@@ -59,7 +59,7 @@ function setImg(code: number) {
const isShortTitle = ref(false);
onMounted(() => {
console.log(titleRef.value);
// console.log(titleRef.value);
if (titleRef.value) {
const offsetWidth = titleRef.value.$el.offsetWidth;
isShortTitle.value = 130 <= offsetWidth;
@@ -302,6 +302,11 @@ function copyItem(item: SurveyItem) {
position: absolute;
top: -25px;
right: -25px;
img {
transform: translate(50%, 50%);
width: 98px;
}
}
.survey_item_info_title {