generated from duanshuwen/webapp-vue-frontend
feat: 问卷功能开发
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
}
|
||||
|
||||
[data-theme='dark'] {
|
||||
|
||||
&,
|
||||
* {
|
||||
color-scheme: dark !important;
|
||||
@@ -20,7 +19,6 @@
|
||||
}
|
||||
|
||||
[data-theme='light'] {
|
||||
|
||||
&,
|
||||
* {
|
||||
color-scheme: light !important;
|
||||
@@ -54,43 +52,67 @@
|
||||
}
|
||||
}
|
||||
|
||||
.van-safe-area-top {
|
||||
padding-top: var(--safe-area-inset-top) !important;
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.van-image-preview__index,
|
||||
.van-image-preview__close-icon--top-right {
|
||||
top: 46px !important;
|
||||
.item-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// 表单样式
|
||||
.van-field__error-message {
|
||||
text-align: right !important;
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.van-hairline--top-bottom:after,
|
||||
.van-hairline-unset--top-bottom:after {
|
||||
border-width: 0 !important;
|
||||
.mb-12 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// 弹窗样式
|
||||
.van-dialog {
|
||||
width: 270px !important;
|
||||
.m-16 {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.van-dialog__confirm,
|
||||
.van-dialog__confirm:active {
|
||||
color: #14b498 !important;
|
||||
.mb-30 {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.van-dialog__content--isolated {
|
||||
min-height: 72px !important;
|
||||
.van-cell-group__title {
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.van-dialog__message {
|
||||
color: #333333;
|
||||
font-size: 17px !important;
|
||||
font-family: PingFangSC-Semibold, PingFang SC;
|
||||
font-weight: 600;
|
||||
line-height: 24px !important;
|
||||
}
|
||||
.fz-14 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fz-26 {
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.color-66 {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.line-height-21 {
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.round-100 {
|
||||
background-color: #1989fa;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.w-200 {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.h-100 {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="page-container" :style="{ backgroundColor: bgColor }">
|
||||
<van-nav-bar :class="['nav-bar', navBgColor, isCustom ? 'custom-style' : '']" safe-area-inset-top left-arrow fixed
|
||||
v-if="showNavigator" :border="false" :left-text="navBarLeftText" @click-left="handleBack">
|
||||
<van-nav-bar class="nav-bar" safe-area-inset-top left-arrow :border="false" @click-left="handleBack">
|
||||
<template #title>
|
||||
<slot name="title">{{ title === '首页' ? '' : metaTitle }}</slot>
|
||||
</template>
|
||||
@@ -87,45 +86,34 @@ const handleBack = () => {
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
background-color: white;
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.body {
|
||||
min-height: calc(100vh - 46px + var(--safe-area-inset-top));
|
||||
padding-top: calc(46px + var(--safe-area-inset-top));
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.nav-bar {
|
||||
:deep(.van-icon-arrow-left) {
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
background-color: transparent;
|
||||
z-index: 2000;
|
||||
position: fixed;
|
||||
:deep(.van-nav-bar__title) {
|
||||
color: #333;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
line-height: 22px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.van-icon-arrow-left) {
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
}
|
||||
.body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 12px;
|
||||
|
||||
:deep(.van-nav-bar__title) {
|
||||
color: #333;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
line-height: 22px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.custom-style {
|
||||
background-color: rgba(22, 187, 191, 1);
|
||||
|
||||
:deep(.van-icon-arrow-left) {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,8 @@ import store from '@/store'
|
||||
|
||||
import Layout from '@/components/Layout.vue'
|
||||
|
||||
import 'vant/lib/index.css'
|
||||
|
||||
const app = createApp(App)
|
||||
app.config.globalProperties.$store = store
|
||||
|
||||
|
||||
@@ -10,6 +10,15 @@ const routes = [
|
||||
title: '问卷调查', // 自动设置当前页面的标题
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/result',
|
||||
name: 'result', // 请和文件名一样
|
||||
component: () => import('@/views/result/index.vue'),
|
||||
meta: {
|
||||
title: '问卷调查结果', // 自动设置当前页面的标题
|
||||
keepAlive: true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -2,15 +2,59 @@
|
||||
<Layout>
|
||||
<template #title>{{ questionnaire.title }}</template>
|
||||
|
||||
<div class="list">
|
||||
{{ questionnaire.questions }}
|
||||
</div>
|
||||
<van-form @submit="onSubmit">
|
||||
<van-cell-group :title="`${index + 1}. ${item.question}`" v-for="(item, index) in questionnaire.questions"
|
||||
:key="item.id">
|
||||
<!-- 单选框 -->
|
||||
<van-field v-if="item.type === 'radio'" name="radio">
|
||||
<template #input>
|
||||
<van-radio-group v-model="item.answer">
|
||||
<van-radio v-for="(option, index) in item.options" :key="item.id + index" :name="option.id" class="mb-12">
|
||||
{{ option.text }}
|
||||
</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
|
||||
<!-- 复选框 -->
|
||||
<van-field v-if="item.type === 'checkbox'" name="checkboxGroup">
|
||||
<template #input>
|
||||
<van-checkbox-group v-model="item.answer" shape="square">
|
||||
<van-checkbox v-for="(option, index) in item.options" :key="item.id + index" :name="option.id"
|
||||
class="mb-12">
|
||||
{{ option.text }}
|
||||
</van-checkbox>
|
||||
</van-checkbox-group>
|
||||
</template>
|
||||
</van-field>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<van-field v-if="item.type === 'text'" v-model="item.answer" placeholder="请填写内容" />
|
||||
|
||||
<!-- 文本域 -->
|
||||
<van-field v-if="item.type === 'textarea'" type="textarea" v-model="item.answer" placeholder="请填写内容"
|
||||
maxlength="100" show-word-limit />
|
||||
</van-cell-group>
|
||||
|
||||
<div class="m-16">
|
||||
<van-button round block type="primary" native-type="submit">
|
||||
提交
|
||||
</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script setup name="home">
|
||||
import { getSurveyQuestionnaireUsingGet } from '@api'
|
||||
const router = useRouter()
|
||||
import { getSurveyQuestionnaireUsingGet, submitSurveyQuestionnaireAnswerUsingPost } from '@api'
|
||||
import { showToast } from 'vant';
|
||||
|
||||
|
||||
|
||||
const form = ref({
|
||||
surveyId: '',
|
||||
answers: []
|
||||
})
|
||||
|
||||
// 跳转按钮操作
|
||||
const handleClick = () => {
|
||||
@@ -19,17 +63,45 @@ const handleClick = () => {
|
||||
|
||||
const questionnaire = ref({})
|
||||
const getQuestionnaire = async () => {
|
||||
questionnaire.value = await getSurveyQuestionnaireUsingGet({})
|
||||
const res = await getSurveyQuestionnaireUsingGet({})
|
||||
|
||||
questionnaire.value = {
|
||||
surveyId: res.id,
|
||||
title: res.title,
|
||||
questions: res.questions.map((item) => ({
|
||||
...item,
|
||||
answer: item.type === 'checkbox' ? [] : ''
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log('onMounted')
|
||||
getQuestionnaire()
|
||||
})
|
||||
onMounted(() => getQuestionnaire())
|
||||
|
||||
const router = useRouter()
|
||||
const onSubmit = async () => {
|
||||
// 验证表单
|
||||
if (questionnaire.value.questions.some((item) => !item.answer)) {
|
||||
showToast('请填写完整')
|
||||
return
|
||||
}
|
||||
|
||||
form.value.surveyId = questionnaire.value.surveyId
|
||||
form.value.answers = questionnaire.value.questions.map((item) => ({
|
||||
questionId: item.id,
|
||||
answer: item.type === 'checkbox' ? item.answer.join(',') : item.answer
|
||||
}))
|
||||
console.log('onSubmit', form.value)
|
||||
|
||||
const res = await submitSurveyQuestionnaireAnswerUsingPost({ body: form.value })
|
||||
|
||||
if (res) {
|
||||
getQuestionnaire()
|
||||
form.value.surveyId = ''
|
||||
form.value.answers = []
|
||||
|
||||
router.push({ name: 'result' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
section {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
35
src/views/result/index.vue
Normal file
35
src/views/result/index.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<section>
|
||||
<div class="round-100 h-100 w-100 flex item-center justify-center mb-30">
|
||||
<van-icon name="success" color="#fff" size="70" />
|
||||
</div>
|
||||
<div class="fz-26 mb-12">提交成功</div>
|
||||
<div class="color-66 fz-14 line-height-21 mb-12 text-center mb-30">感谢您参与息烽南山天沐温泉的客户调研问卷, 您的宝贵意见将帮助我们不断提升服务质量,
|
||||
请凭此截图于前台兑换精美礼品一份!
|
||||
</div>
|
||||
|
||||
<van-button class="fz-14 w-200" round block type="primary" @click="handleClick">
|
||||
完成
|
||||
</van-button>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const handleClick = () => {
|
||||
// 确保在wx.ready中调用
|
||||
wx.ready(() => {
|
||||
// 关闭当前H5页面
|
||||
wx.miniProgram.navigateBack({});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
section {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 100px 30px 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user