generated from duanshuwen/webapp-vue-frontend
feat: 问卷功能开发
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
VITE_ENV = development
|
VITE_ENV = development
|
||||||
|
|
||||||
# vconsole开关控制器
|
# vconsole开关控制器
|
||||||
VITE_CONSOLE = 1
|
VITE_CONSOLE = 0
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_BASE_API = http://8.138.234.141/ingress/hotelBiz
|
VITE_BASE_API = http://8.138.234.141/ingress/hotelBiz
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// .preitterrc.js
|
// .preitterrc.js
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// 一行的字符数,如果超过会进行换行,默认为80
|
// 一行的字符数,如果超过会进行换行,默认为80
|
||||||
printWidth: 80,
|
printWidth: 200,
|
||||||
// 一个tab代表几个空格数,默认为80
|
// 一个tab代表几个空格数,默认为80
|
||||||
tabWidth: 2,
|
tabWidth: 2,
|
||||||
// 是否使用tab进行缩进,默认为false,表示用空格进行缩减
|
// 是否使用tab进行缩进,默认为false,表示用空格进行缩减
|
||||||
@@ -11,7 +11,7 @@ module.exports = {
|
|||||||
// 行位是否使用分号,默认为true
|
// 行位是否使用分号,默认为true
|
||||||
semi: false,
|
semi: false,
|
||||||
// 是否使用尾逗号,有三个可选值"<none|es5|all>"
|
// 是否使用尾逗号,有三个可选值"<none|es5|all>"
|
||||||
trailingComma: "none",
|
trailingComma: 'none',
|
||||||
// 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
|
// 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
|
||||||
bracketSpacing: true,
|
bracketSpacing: true,
|
||||||
// 代码的解析引擎,默认为babylon,与babel相同
|
// 代码的解析引擎,默认为babylon,与babel相同
|
||||||
|
|||||||
30
index.html
30
index.html
@@ -1,20 +1,18 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
||||||
|
<meta name="format-detection" content="telephone=no" />
|
||||||
|
<meta name="applicable-device" content="mobile" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
|
<title>‎</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
<head>
|
<body>
|
||||||
<meta charset="UTF-8" />
|
<div id="app"></div>
|
||||||
<meta name="viewport"
|
<script type="module" src="/src/main.js"></script>
|
||||||
content="width=device-width, viewport-fit=cover, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||||
<meta name="format-detection" content="telephone=no" />
|
</body>
|
||||||
<meta name="applicable-device" content="mobile" />
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
|
||||||
<title>‎</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
|
|
||||||
&,
|
&,
|
||||||
* {
|
* {
|
||||||
color-scheme: dark !important;
|
color-scheme: dark !important;
|
||||||
@@ -20,7 +19,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-theme='light'] {
|
[data-theme='light'] {
|
||||||
|
|
||||||
&,
|
&,
|
||||||
* {
|
* {
|
||||||
color-scheme: light !important;
|
color-scheme: light !important;
|
||||||
@@ -54,43 +52,67 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-safe-area-top {
|
.flex {
|
||||||
padding-top: var(--safe-area-inset-top) !important;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-image-preview__index,
|
.item-center {
|
||||||
.van-image-preview__close-icon--top-right {
|
align-items: center;
|
||||||
top: 46px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单样式
|
.justify-center {
|
||||||
.van-field__error-message {
|
justify-content: center;
|
||||||
text-align: right !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-hairline--top-bottom:after,
|
.mb-12 {
|
||||||
.van-hairline-unset--top-bottom:after {
|
margin-bottom: 12px;
|
||||||
border-width: 0 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹窗样式
|
.m-16 {
|
||||||
.van-dialog {
|
margin: 16px;
|
||||||
width: 270px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-dialog__confirm,
|
.mb-30 {
|
||||||
.van-dialog__confirm:active {
|
margin-bottom: 30px;
|
||||||
color: #14b498 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-dialog__content--isolated {
|
.van-cell-group__title {
|
||||||
min-height: 72px !important;
|
color: #333 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.van-dialog__message {
|
.fz-14 {
|
||||||
color: #333333;
|
font-size: 14px;
|
||||||
font-size: 17px !important;
|
}
|
||||||
font-family: PingFangSC-Semibold, PingFang SC;
|
|
||||||
font-weight: 600;
|
.fz-26 {
|
||||||
line-height: 24px !important;
|
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>
|
<template>
|
||||||
<div class="page-container" :style="{ backgroundColor: bgColor }">
|
<div class="page-container" :style="{ backgroundColor: bgColor }">
|
||||||
<van-nav-bar :class="['nav-bar', navBgColor, isCustom ? 'custom-style' : '']" safe-area-inset-top left-arrow fixed
|
<van-nav-bar class="nav-bar" safe-area-inset-top left-arrow :border="false" @click-left="handleBack">
|
||||||
v-if="showNavigator" :border="false" :left-text="navBarLeftText" @click-left="handleBack">
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<slot name="title">{{ title === '首页' ? '' : metaTitle }}</slot>
|
<slot name="title">{{ title === '首页' ? '' : metaTitle }}</slot>
|
||||||
</template>
|
</template>
|
||||||
@@ -87,45 +86,34 @@ const handleBack = () => {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.page-container {
|
.page-container {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow-y: auto;
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding-bottom: var(--safe-area-inset-bottom);
|
padding-bottom: var(--safe-area-inset-bottom);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.body {
|
.nav-bar {
|
||||||
min-height: calc(100vh - 46px + var(--safe-area-inset-top));
|
:deep(.van-icon-arrow-left) {
|
||||||
padding-top: calc(46px + var(--safe-area-inset-top));
|
color: #333;
|
||||||
overflow-y: auto;
|
font-size: 20px;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-bar {
|
:deep(.van-nav-bar__title) {
|
||||||
background-color: transparent;
|
color: #333;
|
||||||
z-index: 2000;
|
font-size: 18px;
|
||||||
position: fixed;
|
font-weight: bold;
|
||||||
|
line-height: 22px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.van-icon-arrow-left) {
|
.body {
|
||||||
color: #333;
|
flex: 1;
|
||||||
font-size: 20px;
|
overflow-y: auto;
|
||||||
}
|
padding: 0 12px;
|
||||||
|
|
||||||
:deep(.van-nav-bar__title) {
|
&::-webkit-scrollbar {
|
||||||
color: #333;
|
display: none;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import store from '@/store'
|
|||||||
|
|
||||||
import Layout from '@/components/Layout.vue'
|
import Layout from '@/components/Layout.vue'
|
||||||
|
|
||||||
|
import 'vant/lib/index.css'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.config.globalProperties.$store = store
|
app.config.globalProperties.$store = store
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ const routes = [
|
|||||||
title: '问卷调查', // 自动设置当前页面的标题
|
title: '问卷调查', // 自动设置当前页面的标题
|
||||||
keepAlive: true
|
keepAlive: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/result',
|
||||||
|
name: 'result', // 请和文件名一样
|
||||||
|
component: () => import('@/views/result/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '问卷调查结果', // 自动设置当前页面的标题
|
||||||
|
keepAlive: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,59 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<template #title>{{ questionnaire.title }}</template>
|
<template #title>{{ questionnaire.title }}</template>
|
||||||
|
|
||||||
<div class="list">
|
<van-form @submit="onSubmit">
|
||||||
{{ questionnaire.questions }}
|
<van-cell-group :title="`${index + 1}. ${item.question}`" v-for="(item, index) in questionnaire.questions"
|
||||||
</div>
|
: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>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="home">
|
<script setup name="home">
|
||||||
import { getSurveyQuestionnaireUsingGet } from '@api'
|
import { getSurveyQuestionnaireUsingGet, submitSurveyQuestionnaireAnswerUsingPost } from '@api'
|
||||||
const router = useRouter()
|
import { showToast } from 'vant';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
surveyId: '',
|
||||||
|
answers: []
|
||||||
|
})
|
||||||
|
|
||||||
// 跳转按钮操作
|
// 跳转按钮操作
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
@@ -19,17 +63,45 @@ const handleClick = () => {
|
|||||||
|
|
||||||
const questionnaire = ref({})
|
const questionnaire = ref({})
|
||||||
const getQuestionnaire = async () => {
|
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(() => {
|
onMounted(() => getQuestionnaire())
|
||||||
console.log('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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped></style>
|
||||||
section {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
</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>
|
||||||
@@ -43,18 +43,6 @@ export default defineConfig(({ mode }) => {
|
|||||||
// dts: 'src/auto-imports...', // 可以自定义文件生成的位置与是否生成,默认是根目录下
|
// dts: 'src/auto-imports...', // 可以自定义文件生成的位置与是否生成,默认是根目录下
|
||||||
dts: false
|
dts: false
|
||||||
}),
|
}),
|
||||||
createStyleImportPlugin({
|
|
||||||
resolves: [VantResolve()],
|
|
||||||
libs: [
|
|
||||||
{
|
|
||||||
libraryName: 'vant',
|
|
||||||
esModule: false,
|
|
||||||
resolveStyle: (name) => {
|
|
||||||
return `vant/es/${name}/style`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
viteVConsole({
|
viteVConsole({
|
||||||
entry: [resolve('src/main.js')],
|
entry: [resolve('src/main.js')],
|
||||||
localEnabled: isVconsole,
|
localEnabled: isVconsole,
|
||||||
|
|||||||
Reference in New Issue
Block a user