generated from duanshuwen/webapp-vue-frontend
feat: 问卷功能开发
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
VITE_ENV = development
|
||||
|
||||
# vconsole开关控制器
|
||||
VITE_CONSOLE = 1
|
||||
VITE_CONSOLE = 0
|
||||
|
||||
# 接口地址
|
||||
VITE_BASE_API = http://8.138.234.141/ingress/hotelBiz
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// .preitterrc.js
|
||||
module.exports = {
|
||||
// 一行的字符数,如果超过会进行换行,默认为80
|
||||
printWidth: 80,
|
||||
printWidth: 200,
|
||||
// 一个tab代表几个空格数,默认为80
|
||||
tabWidth: 2,
|
||||
// 是否使用tab进行缩进,默认为false,表示用空格进行缩减
|
||||
@@ -11,7 +11,7 @@ module.exports = {
|
||||
// 行位是否使用分号,默认为true
|
||||
semi: false,
|
||||
// 是否使用尾逗号,有三个可选值"<none|es5|all>"
|
||||
trailingComma: "none",
|
||||
trailingComma: 'none',
|
||||
// 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
|
||||
bracketSpacing: true,
|
||||
// 代码的解析引擎,默认为babylon,与babel相同
|
||||
|
||||
32
index.html
32
index.html
@@ -1,20 +1,18 @@
|
||||
<!DOCTYPE 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>
|
||||
<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>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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>
|
||||
@@ -43,18 +43,6 @@ export default defineConfig(({ mode }) => {
|
||||
// dts: 'src/auto-imports...', // 可以自定义文件生成的位置与是否生成,默认是根目录下
|
||||
dts: false
|
||||
}),
|
||||
createStyleImportPlugin({
|
||||
resolves: [VantResolve()],
|
||||
libs: [
|
||||
{
|
||||
libraryName: 'vant',
|
||||
esModule: false,
|
||||
resolveStyle: (name) => {
|
||||
return `vant/es/${name}/style`
|
||||
}
|
||||
}
|
||||
]
|
||||
}),
|
||||
viteVConsole({
|
||||
entry: [resolve('src/main.js')],
|
||||
localEnabled: isVconsole,
|
||||
|
||||
Reference in New Issue
Block a user