普兆健康管家前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

550 lines
15 KiB

<template>
<view class="page__view">
<navbar :title="`问题 ${current + 1}/${total}`" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="transparent" />
<view class="bar">
<view class="flex tools">
<view class="left">
<button class="flex btn" v-if="showPreBtn" @click="pre">
<image class="btn-icon" src="@/pages_order/static/report/icon-wrapper.png" mode="widthFix"></image>
<text>上一题</text>
</button>
</view>
<view class="right">
选择你的答案进入下一题
</view>
</view>
<view class="progress">
<view class="progress-bar" :style="{ width: `${progress}%` }"></view>
</view>
</view>
<view class="main">
<view class="question">{{ data.question }}</view>
<template v-if="data.type === 'select'">
<view class="select">
<view
v-for="item in data.options"
:key="item.id"
:class="['flex', 'select-option', item.id === value ? 'is-active' : '']"
@click="onSelect(item.id)"
>
{{ item.label }}
</view>
</view>
</template>
<template v-else-if="data.type === 'select-box'">
<view class="select-box">
<view
v-for="item in data.options"
:key="item.id"
:class="['flex', 'flex-column', 'select-box-option', item.id === value ? 'is-active' : '']"
@click="onSelect(item.id)"
>
<!-- todo: img switch → acitve: white -->
<image class="img" :src="item.img" mode="aspectFit"></image>
<view class="text">{{ item.label }}</view>
</view>
</view>
</template>
<template v-else-if="data.type === 'input'">
<view class="input">
<view class="flex input-box">
<input class="input-doc" v-model="value" placeholder="请输入内容" placeholder-style="font-family: PingFang SC; font-weight: 400; line-height: 1.4; font-size: 32rpx; color: #AAAACA;" />
<view class="input-unit" v-if="data.unit">{{ data.unit }}</view>
</view>
</view>
</template>
<template v-else-if="data.type === 'input-group'">
<view class="input">
<view class="flex input-box" v-for="(item, index) in data.options" :key="item.id">
<view class="input-label" v-if="item.label">{{ item.label }}</view>
<input class="input-doc" v-model="value[index]" placeholder="请输入内容" placeholder-style="font-family: PingFang SC; font-weight: 400; line-height: 1.4; font-size: 32rpx; color: #AAAACA;" />
<view class="input-unit" v-if="item.unit">{{ item.unit }}</view>
</view>
</view>
</template>
<view class="flex btns">
<button :class="['btn', 'btn-palin', noneFlag ? 'is-active' : '']" v-if="data.showNoneBtn" @click="onSelectNone">暂 无</button>
<button class="btn" v-if="showConfirmBtn" @click="onConfirm">确 认</button>
<button class="btn" v-if="showSubmitBtn" @click="onSubmit">提 交</button>
</view>
<view class="desc" v-if="data.desc">
<uv-parse :content="data.desc"></uv-parse>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
step: 0,
current: 0,
value: null,
noneFlag: false,
answers: [],
list: [],
total: 0,
}
},
computed: {
showPreBtn() {
return this.current > 0
},
progress() {
return 100 * (this.current + 1) / this.total
},
showSubmitBtn() {
return this.current + 1 === this.total
},
data() {
return this.list[this.current]
},
showConfirmBtn() {
if (this.showSubmitBtn) {
return false
}
return ['input', 'input-group'].includes(this.data?.type)
},
},
onLoad(arg) {
this.step = parseInt(arg.step)
this.current = parseInt(arg.current || 0)
this.fetchQuestionList()
},
methods: {
fetchQuestionList() {
// todo
this.list = [
{
question: '您的年龄是?',
type: 'select',
options: [
{ id: '001', label: '0-3' },
{ id: '002', label: '3-6' },
{ id: '003', label: '6-10' },
{ id: '004', label: '10-18' },
{ id: '005', label: '18-50' },
{ id: '006', label: '50岁+' },
]
},
{
question: '你的性别?',
type: 'select',
options: [
{ id: '001', label: '男' },
{ id: '002', label: '女' },
]
},
{
question: '你的是否本人?',
type: 'select',
options: [
{ id: '001', label: '本人' },
{ id: '002', label: '夫妻' },
{ id: '003', label: '子女' },
{ id: '004', label: '父母' },
{ id: '005', label: '(外)祖父母' },
]
},
{
question: '你的姓名?',
type: 'input',
},
{
question: '你的体重?',
type: 'input',
unit: 'KG',
},
{
question: '你是否在备孕?',
type: 'select',
options: [
{ id: '001', label: '是' },
{ id: '002', label: '否' },
]
},
{
question: '是否有以下问题的困扰?',
type: 'select-box',
options: [
{ id: '001', label: '高血压', img: '/pages_order/static/report/trouble-1.png' },
{ id: '002', label: '高血脂', img: '/pages_order/static/report/trouble-2.png' },
{ id: '003', label: '高血糖', img: '/pages_order/static/report/trouble-3.png' },
{ id: '004', label: '免疫问题', img: '/pages_order/static/report/trouble-4.png' },
{ id: '005', label: '胃肠道疾病', img: '/pages_order/static/report/trouble-5.png' },
{ id: '006', label: '甲状腺疾病', img: '/pages_order/static/report/trouble-6.png' },
{ id: '007', label: '头痛头晕', img: '/pages_order/static/report/trouble-7.png' },
{ id: '008', label: '肝功能不全', img: '/pages_order/static/report/trouble-8.png' },
{ id: '009', label: '肾功能不全', img: '/pages_order/static/report/trouble-9.png' },
{ id: '010', label: '关节疼痛', img: '/pages_order/static/report/trouble-10.png' },
{ id: '011', label: '精神疾病', img: '/pages_order/static/report/trouble-11.png' },
],
showNoneBtn: true,
},
{
question: '是否接受过手术?',
type: 'input',
showNoneBtn: true,
},
{
question: '您的孩子晚上能睡几个小时?',
type: 'select',
options: [
{ id: '001', label: '> 10 小时' },
{ id: '002', label: '8-10 小时' },
{ id: '003', label: '6-8 小时' },
{ id: '004', label: '<6 小时' },
]
},
{
question: '是否有饮酒?',
type: 'input-group',
options: [
{ id: '001', label: '平均每周饮酒', unit: '次' },
{ id: '002', label: '每次饮酒', unit: 'ml' },
],
showNoneBtn: true,
},
{
question: '你经常食用富含不饱和脂肪酸的食物吗?',
type: 'select',
options: [
{ id: '001', label: '基本不吃' },
{ id: '002', label: '偶尔' },
{ id: '003', label: '经常' },
],
desc: `
<p>富含不饱和脂肪酸的食物包括鱼类(三文鱼、鳕鱼、鳟鱼等)、坚果和种子(杏仁、核桃、花生等)、植物油(橄榄油、亚麻籽油等)。</p>
`
},
{
question: '你运动的强度如何?',
type: 'select',
options: [
{ id: '001', label: '高强度' },
{ id: '002', label: '中等强度' },
{ id: '003', label: '低强度' },
],
desc: `
<p>
低强度运动(45分钟以上)如:散步、瑜伽、太极拳、打扫等。<br/>
中强度运动(30-45 分钟) 如:慢跑、骑车、健身操等。<br/>
高强度运动(20-30 分钟)如:跑步、跳绳、游泳、跳舞、HIT等。
</p>
`
},
]
this.answers = this.list.map(item => {
let val = null
if (this.data.type === 'input-group') {
val = new Array(this.data.options.length).fill(0).map(() => null)
}
return val
})
this.total = this.list.length
// todo: delete
this.current = 0
},
pre() {
this.current -= 1
this.value = this.answers[this.current]
this.noneFlag = false
},
next() {
if (this.showSubmitBtn) {
return
}
this.current += 1
this.value = this.answers[this.current]
this.noneFlag = false
},
onSelect(id) {
this.value = id
// todo: fetch submit answer of this question
if (!this.showSubmitBtn) {
this.$nextTick(() => {
setTimeout(() => {
this.next()
}, 500)
})
}
},
onConfirm() {
// todo: check is fill
this.answers[this.current] = this.value
// todo: fetch submit answer of this question
this.next()
},
onSelectNone() {
this.noneFlag = true
let val = null
if (this.data.type === 'input-group') {
val = new Array(this.data.options.length).fill(0).map(() => null)
}
this.answers[this.current] = val
// todo: fetch submit answer of this question
this.next()
},
onSubmit() {
// todo
// todo: fetch submit answer of this step
if (this.step == 3) {
// todo: submit all answer and jump to the report
uni.reLaunch({
url: '/pages/index/report'
})
return
}
this.$utils.redirectTo(`/pages_order/report/test/step?step=${this.step + 1}`)
},
},
}
</script>
<style scoped lang="scss">
.page__view {
width: 100vw;
min-height: 100vh;
background-color: $uni-bg-color;
position: relative;
}
.bar {
margin-top: 24rpx;
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
.left {
text-align: left;
.btn {
display: inline-flex;
font-family: PingFang SC;
font-weight: 400;
font-size: 30rpx;
line-height: 1.4;
color: #7451DE;
&-icon {
width: 32rpx;
height: auto;
margin-right: 8rpx;
}
}
}
.right {
flex: 1;
text-align: right;
font-family: PingFang SC;
font-weight: 400;
font-size: 26rpx;
line-height: 1.4;
color: #989898;
}
}
.progress {
margin-top: 24rpx;
width: 100%;
height: 24rpx;
background: #E5E5E5;
border-radius: 12rpx;
&-bar {
height: 100%;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 12rpx;
}
}
.main {
width: 100%;
padding: 70rpx 104rpx 0 104rpx;
box-sizing: border-box;
}
.question {
text-align: center;
font-family: PingFang SC;
font-weight: 400;
font-size: 40rpx;
line-height: 1.4;
color: #000000;
margin-bottom: 64rpx;
}
.select {
&-option {
padding: 30rpx 0;
font-family: PingFang SC;
font-weight: 400;
line-height: 1.4;
font-size: 32rpx;
color: #252545;
background-image: linear-gradient(to right, #FFFFFF, #F4F4F6, #F2F2F4);
border-radius: 52rpx;
box-shadow: -2rpx -2rpx 10rpx 0 #FFFFFFC4,
4rpx 4rpx 20rpx 0 #AAAACC1F,
2rpx 2rpx 4rpx 0 #AAAACC40,
-1rpx -1rpx 2rpx 0 #FFFFFF;
& + & {
margin-top: 40rpx;
}
&.is-active {
color: #FFFFFF;
background: #7451DE;
}
}
}
.select-box {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 32rpx;
&-option {
padding: 24rpx 0;
border-radius: 24rpx;
background-image: linear-gradient(to right, #FFFFFF, #F2F2F4);
box-shadow: -2rpx -2rpx 10rpx 0 #FFFFFFC4,
4rpx 4rpx 20rpx 0 #AAAACC1F,
2rpx 2rpx 4rpx 0 #AAAACC40,
-1rpx -1rpx 2rpx 0 #FFFFFF;
.img {
width: 100%;
height: 64rpx;
}
.text {
margin-top: 8rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
line-height: 1.4;
color: #969696;
}
&.is-active {
background: #7451DE;
.text {
color: #FFFFFFC4;
}
}
}
}
.input {
&-box {
width: 100%;
height: 104rpx;
padding: 0 40rpx;
box-sizing: border-box;
border-radius: 52rpx;
background-image: linear-gradient(to right, #FFFFFF, #F4F4F6, #F2F2F4);
box-shadow: -2rpx -2rpx 10rpx 0 #FFFFFFC4,
4rpx 4rpx 20rpx 0 #AAAACC1F,
2rpx 2rpx 4rpx 0 #AAAACC40,
-1rpx -1rpx 2rpx 0 #FFFFFF;
& + & {
margin-top: 40rpx;
}
}
&-doc {
text-align: center;
flex: 1;
}
&-label {
padding: 21rpx 40rpx 21rpx 0;
font-family: PingFang SC;
font-weight: 600;
font-size: 30rpx;
line-height: 1.4;
color: #252545;
border-right: 2rpx solid #E0DFF0;
}
&-unit {
padding: 21rpx 0 21rpx 40rpx;
font-family: PingFang SC;
font-weight: 600;
font-size: 30rpx;
line-height: 1.4;
color: #252545;
border-left: 2rpx solid #E0DFF0;
}
}
.btns {
margin-top: 64rpx;
column-gap: 36rpx;
.btn {
flex: 1;
padding: 24rpx 0;
font-family: PingFang SC;
font-weight: 600;
font-size: 30rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #4B348F, #845CFA);
border-radius: 45rpx;
&-palin {
padding: 22rpx 0;
font-weight: 400;
color: #252545;
background: transparent;
border: 2rpx solid #252545;
&.is-active {
color: $uni-color;
border-color: $uni-color;
}
}
}
}
.desc {
margin-top: 220rpx;
font-family: PingFang SC;
font-weight: 400;
line-height: 1.4;
font-size: 26rpx;
color: #989898;
}
</style>