鸿宇研学生前端代码
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.
 
 
 

587 lines
16 KiB

<template>
<view>
<uv-popup ref="popup" mode="bottom" bgColor="none" >
<view class="popup__view">
<view class="flex header">
<view class="title">{{ title }}</view>
<button class="btn" @click="close">关闭</button>
</view>
<view class="form">
<uv-form
ref="form"
:model="form"
:rules="rules"
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="name" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
姓名
</view>
<view class="form-item-content">
<formInput v-model="form.name"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="cerNo" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
身份证号
</view>
<view class="form-item-content">
<formInput v-model="form.cerNo"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="type" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
类型
</view>
<view class="form-item-content">
<uv-radio-group v-model="form.periodId"
iconColor="#00A9FF"
iconSize="36rpx"
size="36rpx"
labelColor="#181818"
labelSize="26rpx"
>
<uv-radio
v-for="(item, index) in periodOptions"
:key="index"
:label="item.label"
:name="item.value"
:customStyle="{ flex: 1 }"
></uv-radio>
</uv-radio-group>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="sex" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
性别
</view>
<view class="form-item-content">
<uv-radio-group v-model="form.sex"
iconColor="#00A9FF"
iconSize="36rpx"
size="36rpx"
labelColor="#181818"
labelSize="26rpx"
>
<uv-radio
v-for="(item, index) in sexOptions"
:key="index"
:label="item.label"
:name="item.value"
:customStyle="{ flex: 1 }"
></uv-radio>
</uv-radio-group>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="phone" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
手机号
</view>
<view class="form-item-content">
<formInput v-model="form.phone"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="wechat" :customStyle="formItemStyle">
<view class="form-item-label">微信号</view>
<view class="form-item-content">
<formInput v-model="form.wechat"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="school" :customStyle="formItemStyle">
<view class="form-item-label">学校</view>
<view class="form-item-content">
<formInput v-model="form.school"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="grade" :customStyle="formItemStyle">
<view class="form-item-label">年级</view>
<view class="form-item-content">
<formInput v-model="form.grade"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="age" :customStyle="formItemStyle">
<view class="form-item-label">年龄</view>
<view class="form-item-content">
<formInput v-model="form.age"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="remark" :customStyle="formItemStyle">
<view class="form-item-label">特殊需求(饮食/健康等)备注</view>
<view class="form-item-content">
<formInput v-model="form.remark"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="emergencyPhone" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
紧急联系人
</view>
<view class="form-item-content">
<formInput v-model="form.emergencyPhone"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="chaperonPhone" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
监护人联系方式
</view>
<view class="form-item-content">
<formInput v-model="form.chaperonPhone"></formInput>
</view>
</uv-form-item>
</view>
</uv-form>
</view>
<view class="footer">
<view class="agreement">
<view>
<uv-checkbox-group
v-model="checkboxValue"
shape="circle"
>
<uv-checkbox
size="40rpx"
icon-size="40rpx"
activeColor="#00A9FF"
:name="1"
></uv-checkbox>
</uv-checkbox-group>
</view>
<view class="desc">
我已阅读并同意
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_agreement', '服务协议')">《服务协议》</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '隐私政策')">《隐私政策》</text>
</view>
</view>
<view class="bar">
<button class="flex btn" @click="onSave">保存</button>
</view>
</view>
</view>
</uv-popup>
<agreementModal ref="modal" @confirm="onConfirmAgreement"></agreementModal>
</view>
</template>
<script>
import formInput from '@/pages_order/components/formInput.vue'
import agreementModal from '@/pages_order/components/agreementModal.vue'
export default {
components: {
formInput,
agreementModal,
},
data() {
return {
id: null,
title: null,
form: {
name: null,
cerNo: null,
periodId: 0,
sex: 0,
phone: null,
wechat: null,
school: null,
grade: null,
age: null,
remark: null,
emergencyPhone: null,
chaperonPhone: null,
},
rules: {
'name': {
type: 'string',
required: true,
message: '请输入姓名',
},
'cerNo': {
type: 'string',
required: true,
message: '请输入身份证号',
},
'periodId': {
type: 'string',
required: true,
message: '请选择类型',
},
'sex': {
type: 'string',
required: true,
message: '请选择性别',
},
'phone': {
type: 'string',
required: true,
message: '请输入手机号',
},
'emergencyPhone': {
type: 'string',
required: true,
message: '请输入紧急联系人联系方式',
},
'chaperonPhone': {
type: 'string',
required: true,
message: '请输入监护人联系方式',
},
},
formItemStyle: { padding: 0 },
// todo: fetch
periodOptions: [
{
id: '001',
label: '成人',
value: '0',
},
{
id: '002',
label: '青少年',
value: '1',
},
{
id: '003',
label: '儿童',
value: '2',
},
],
// todo: check
sexOptions: [
{
id: '001',
label: '男',
value: '0',
},
{
id: '002',
label: '女',
value: '1',
},
],
checkboxValue: [],
}
},
methods: {
async fetchTravelerDetail(personId) {
try {
const result = await this.$fetch('queryTouristById', { personId })
const {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
} = result
this.form = {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
}
} catch (err) {
}
},
open(id) {
if (id) {
this.id = id
this.title = '编辑出行人'
this.fetchTravelerDetail(id)
} else {
this.id = null
this.title = '添加出行人'
this.form = {
name: null,
cerNo: null,
// todo: fetch default
periodId: 0,
sex: 0,
phone: null,
wechat: null,
school: null,
grade: null,
age: null,
remark: null,
emergencyPhone: null,
chaperonPhone: null,
}
}
this.$refs.popup.open()
},
close() {
this.$refs.popup.close()
},
onConfirmAgreement(confirm) {
if (confirm) {
this.checkboxValue = [1]
} else {
this.checkboxValue = []
}
},
async onSave() {
if(!this.checkboxValue.length){
return uni.showToast({
title: '请先同意《服务协议》和《隐私政策》',
icon:'none'
})
}
try {
await this.$refs.form.validate()
const {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
} = this.form
const params = {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
}
if (this.id) {
params.id = this.id
await this.$fetch('updateTourist', params)
uni.showToast({
icon: 'success',
title: '修改出行人成功',
});
} else {
await this.$fetch('addTourist', params)
uni.showToast({
icon: 'success',
title: '添加出行人成功',
});
}
this.$emit('submitted')
this.close()
} catch (err) {
console.log('onSave err', err)
}
},
},
}
</script>
<style lang="scss" scoped>
.popup__view {
width: 100vw;
display: flex;
flex-direction: column;
box-sizing: border-box;
background: #FFFFFF;
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
}
.header {
position: relative;
width: 100%;
padding: 24rpx 0;
box-sizing: border-box;
border-bottom: 2rpx solid #EEEEEE;
.title {
font-family: PingFang SC;
font-weight: 500;
font-size: 34rpx;
line-height: 1.4;
color: #181818;
}
.btn {
font-family: PingFang SC;
font-weight: 500;
font-size: 32rpx;
line-height: 1.4;
color: #8B8B8B;
position: absolute;
top: 26rpx;
left: 40rpx;
}
}
.form {
max-height: 75vh;
padding: 32rpx 40rpx;
box-sizing: border-box;
overflow-y: auto;
&-item {
padding: 8rpx 0 6rpx 0;
& + & {
padding-top: 24rpx;
border-top: 2rpx solid #EEEEEE;
}
&-label {
margin-bottom: 14rpx;
display: flex;
align-items: center;
font-family: PingFang SC;
font-weight: 400;
font-size: 26rpx;
line-height: 1.4;
color: #181818;
.icon {
margin-right: 8rpx;
width: 16rpx;
height: auto;
}
}
&-content {
.placeholder {
color: #C6C6C6;
font-size: 32rpx;
font-weight: 400;
}
.region {
min-height: 44rpx;
justify-content: flex-start;
}
}
}
}
.footer {
width: 100%;
.agreement {
display: flex;
padding: 16rpx 40rpx;
background: #E9F8FF;
box-sizing: border-box;
/deep/ .uv-checkbox-group {
flex: none;
}
.desc {
flex: 1;
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
line-height: 40rpx;
color: #8B8B8B;
}
.highlight {
color: $uni-color;
}
}
.bar {
width: 100%;
padding: 32rpx 40rpx;
box-sizing: border-box;
border-top: 2rpx solid #F1F1F1;
}
.btn {
width: 100%;
padding: 14rpx 0;
box-sizing: border-box;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #21FEEC, #019AF9);
border: 2rpx solid #00A9FF;
border-radius: 41rpx;
}
}
</style>