driverSchool/newPages/register/index.vue
2025-04-09 18:02:45 +08:00

1008 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="content">
<view class="container">
<!-- #ifdef MP-WEIXIN -->
<!-- #ifdef MP-WEIXIN -->
<headers :titles="titles">
<uni-icons @click="goback()" type="left" color="#000000" size="22px"></uni-icons>
</headers>
<!-- #endif -->
<!-- #endif -->
<u-loadmore :status="status" v-if="show == true"/>
</view>
<view class="bm-page">
<view class="bm-page-top">
<image class="top-left-img" :src="baseUrl +'/'+ rightInfoList.photo" mode=""></image>
<view class="bm-page-right">
<view class="bm-page-right-1">{{ rightInfoList.name }}</view>
<view class="bm-page-right-2">
<view class="bm-page-right-zd">{{ rightInfoList.tittle }}</view>
<view class="bm-page-right-c2">{{ rightInfoList.type }}</view>
</view>
<view class="bm-page-right-3">
<text class="bm-page-right-price">¥{{ rightInfoList.price }}</text>
<text class="bm-page-right-jprice">¥{{ rightInfoList.price }}</text>
</view>
</view>
</view>
<view class="bm-page-info" v-if="hideTeacher==0">
<view style="width: 100%; display: flex;align-items: center;justify-content: space-between; ">
<view class="bm-page-info-title">
选择教练
</view>
<view class="d-s" @click="showjl = true">
<view class="" v-if="!jlName">请选择</view>
<view class="" v-else>{{ jlName }}</view>
<u-icon name="arrow-right" size="16"></u-icon>
</view>
</view>
</view>
<view class="bm-page-info">
<view style="width: 100%; display: flex;align-items: center;justify-content: space-between; ">
<view class="bm-page-info-title">
填写身份信息
</view>
<view class="anniu" @click="popupShow = true">
点击上传身份证
</view>
</view>
<view class="info-name">
<view class="info-name-left">姓名</view>
<view class="info-name-right">
<input class="info-name-input" v-model="name" type="text" placeholder="请填写真实姓名">
</view>
</view>
<view class="info-name">
<view class="info-name-left">性别</view>
<view class="d-s" style="width: 70%;">
<view class="size-lv" :class="{'clv' : sex == index }" v-for=" (item,index) in sexlist"
:key="index" @click="getsexindex(index)">{{ item }}
</view>
</view>
</view>
<view class="info-name">
<view class="info-name-left">年龄</view>
<view class="info-name-right">
<input class="info-name-input" v-model="age" type="number" placeholder="请填写真实年龄">
</view>
</view>
<view class="info-name">
<view class="info-name-left">手机号</view>
<view class="info-name-right">
<input class="info-name-input" v-model="phone" type="text" placeholder="请输入正确手机号">
</view>
</view>
<view class="info-name">
<view class="info-name-left">身份证号</view>
<view class="info-name-right">
<input class="info-name-input" v-model="identity" type="text" placeholder="请输入身份证号">
</view>
</view>
<!-- <view style="padding: 0;" class="info-name">
<view class="info-name-left">选择教练</view>
<view class="info-name-right">
<view class="bm-page-button">
<button @click="goBookingJl()" class="bm-page-button-main">预约教师</button>
</view>
</view>
</view> -->
</view>
<view class="bm-page-dj">
<view class="bm-page-dj-title" @click="show = true">
<view class="d-s">
<view>{{ dname }}</view>
<text class="bm-page-dj-title-price">
¥{{ currentPrice }} <!-- 动态显示当前价格 -->
</text>
</view>
<u-icon name="arrow-right" color="#999" size="18"></u-icon>
</view>
<view @click="changeStartPay(2)" class="dj-list">
<view class="dj-list-left">
<image class="dj-list-left-img" src="../../static/imgs/yfk2.png" mode=""></image>
<view class="dj-list-left-name">线下支付</view>
</view>
<view class="dj-list-right">
<view v-if="startPay === 1" class="onel"></view>
<view v-else class="twol">
<u-icon name="checkmark" color="#FFF" size="16"></u-icon>
</view>
</view>
</view>
<view @click="changeStartPay(1)" class="dj-list">
<view class="dj-list-left">
<image class="dj-list-left-img" src="../../static/imgs/qbdd2.png" mode=""></image>
<view class="dj-list-left-name">微信</view>
</view>
<view class="dj-list-right">
<view v-if="startPay === 2" class="onel"></view>
<view v-else class="twol">
<u-icon name="checkmark" color="#FFF" size="16"></u-icon>
</view>
</view>
</view>
</view>
<view class="bm-page-button">
<button @click="applicationClick" class="bm-page-button-main">点击报名</button>
</view>
<u-picker :show="show" :columns="columns" keyName="label" @confirm="confirm" @cancel="cancel"></u-picker>
<u-picker :show="showjl" :columns="columnjl" keyName="label" @confirm="jlconfirm"
@cancel="jlcancel"></u-picker>
<u-popup :show="popupShow" :round="10" mode="center" @close="close" @open="open">
<view class="popup-box">
<view class="title_s">请上传身份证人像面</view>
<u-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple
:maxCount="1" width="280" height="150">
<image src="https://cdn.uviewui.com/uview/demo/upload/positive.png" mode="widthFix"
style="width: 280px;height: 150px;"></image>
</u-upload>
</view>
</u-popup>
</view>
</view>
</template>
<script>
import headers from '../../components/header/headers.vue'
import request from '@/utils/request.js'
import tabbar from '../../components/tabbar/tabbar.vue'
import upload from '@/utils/upload.js'
import {getLocalUserInfo} from '../../utils/auth'
export default {
data() {
return {
titles: "报名",
id: null,
List: [],
show: false,
showjl: false,
popupShow: false,
sfzimg: null,
fileList1: [],
baseUrl: this.$imagesUrl,
status: 'loading',
sexlist: [
"男",
"女"
],
name: null,
phone: null,
sex: 0,
identity: null,
age: null,
startPay: 2,
courseId: null,
rightInfoList: [],
columnjl: [],
jxId: null,
orderId: null,
orderNo: null,
dname: "全款", // 默认显示全款
currentPrice: 0,
selectedPayType: 2, // 默认选中全款(2)
settings: { //签名设置
width: '750', //签名区域的宽
height: '500', //签名区域的高
lineWidth: 4, //签名时线宽
textColor: '#000' //签名文字颜色
},
jlName: null,
jlId: null,
hideTeacher: 0,
Address: '',
djshow: false,
userId: null,
tenantId: null,
userinfo: [],
payPrice: null,
payStatus: null,
loading: false,
columns: [
[{
label: '全款',
// 其他属性值
id: 2
// ...
}, {
label: '定金',
id: 1
}]
],
}
},
onLoad: function (option) {
uni.showToast({
title: '请完善个人信息',
icon: 'none'
})
if (uni.getStorageSync('jlId')) {
this.hideTeacher = 1
}
this.jlId = uni.getStorageSync('jlId');
this.courseId = option.courseId,
this.userId = option.userId,
this.tenantId = option.tenantId
this.userinfo = getLocalUserInfo()
console.log("驾校id", this.jxId, "课程id", this.courseId)
console.log("userId", this.userId, "tenantId", this.tenantId)
console.log("userinfo", this.userinfo)
console.log('当前存储的所有键:', uni.getStorageInfoSync().keys)
console.log('token值:', uni.getStorageSync('App-Token'))
},
onShow() {
this.getListAll()
// this.actList = ["1", "1", "1", "1", "1", ]
// this.status = "nomore" 底部刷新结束
this.getRightInfoList()
},
onPullDownRefresh() {
console.log("刷新");
uni.stopPullDownRefresh()
},
onReachBottom() {
// this.show = true
setTimeout(() => {
console.log("加载执行");
}, 2000)
},
// 发送好友
onShareAppMessage(res) {
return {
title: this.titles,
path: '/pages/index/index',
}
},
// 分享朋友圈
onShareTimeline(res) {
return {
title: this.titles,
path: '/pages/index/index',
}
},
components: {
headers,
tabbar
},
methods: {
// 定金价格 or 全款价格
updateDisplayPrice() {
this.currentPrice = this.selectedPayType === 1
? this.rightInfoList.reserveMoney
: this.rightInfoList.price;
},
// 教练信息
async getListAll() {
this.columnjl = []
let res = await request({
url: '/app-api/dl-drive-school-coach-small/list',
method: 'GET',
params: {
tenantId: this.tenantId,
},
tenantIdFlag: false
})
console.log(res);
this.columnjl = [
res.data.map(coach => ({
label: coach.name,
value: coach
}))
];
},
getsexindex(index) {
this.sex = index
},
open() {
// console.log('open');
},
close() {
this.popupShow = false
// console.log('close');
},
// 选择教练
jlconfirm(e) {
console.log("选中教练:", e.value[0]);
this.jlName = e.value[0].label; // 显示名称
this.jlId = e.value[0].value.userId; // 获取教练ID
this.showjl = false;
},
jlcancel() {
this.showjl = false
},
confirm(e) {
const selected = e.value[0];
this.dname = selected.label;
this.selectedPayType = selected.id;
this.updateDisplayPrice(); // 只在切换时更新价格
this.show = false;
},
cancel() {
this.show = false
},
goback() {
uni.navigateBack()
},
changeStartPay(id) {
this.startPay = id
},
/* goBookingJl() {
uni.navigateTo({
url: '/pages/index/bookingJl',
})
}, */
// 校验手机号
isValidPhoneNumber(phoneNumber) {
const regex = /^1[3-9]\d{9}$/;
if (regex.test(phoneNumber)) {
return true;
} else {
return false;
}
},
// 校验身份证
isValidIDNumber(idNumber) {
const regex = /^\d{15}|\d{17}(?:\d|X)$/;
if (regex.test(idNumber)) {
return true;
} else {
return false;
}
},
// 表单校验
async validateForm() {
if (!this.sfzimg) {
uni.showToast({title: '请上传身份证照片', icon: 'error'});
return false;
}
if (!this.phone || !this.name || !this.identity) {
uni.showToast({title: '请输入完整信息', icon: 'error'});
return false;
}
if (!this.isValidPhoneNumber(this.phone)) {
uni.showToast({title: '手机号不规范', icon: 'error'});
return false;
}
if (!this.isValidIDNumber(this.identity)) {
uni.showToast({title: '身份证不规范', icon: 'error'});
return false;
}
return true;
},
// 报名按钮主逻辑
async applicationClick() {
if (this.loading) return;
this.loading = true;
try {
// 1. 基础校验
if (!this.checkLogin()) {
uni.navigateTo({url: '/pages/login/login'});
return;
}
if (!await this.validateForm()) return;
// 2. 处理已有订单
if (this.orderId) {
const status = await this.getPayStatus(this.orderId);
if (status === '2') {
this.signContract();
return;
} else if (status === '0') {
const result = await this.processExistingOrder();
if (result === 'cancelled') return;
return;
}
}
// 3. 创建新订单
await this.createNewOrder();
} catch (error) {
console.error("报名出错:", error);
if (!error.message.includes('cancel')) {
uni.showToast({title: error.message || '操作失败', icon: 'none'});
}
} finally {
this.loading = false;
}
},
// 微信支付(新订单)
async wxPayClick(name, phone, identity, courseId, payType, reserveMoney, restMoney) {
const res = await request({
url: '/small/jxInfo/onLinePay',
method: 'post',
data: {
userName: name,
userPhone: phone,
userSex: this.sex,
tenantId: this.tenantId,
userNo: identity,
courseId: courseId,
coachUserName: this.jlName,
coachUserId: this.jlId,
courseType: this.rightInfoList.type,
courseName: this.rightInfoList.name,
userId: this.userId,
reserveMoney: reserveMoney,
payType: payType,
restMoney: restMoney,
}
});
this.orderId = res.orderId;
this.orderNo = res.orderNo;
const prepayRes = await request({
url: `/small/jxInfo/prepayment?type=jsapi&orderNo=${this.orderNo}&orderId=${this.orderId}&payType=${payType}`,
method: 'get'
});
const result = await this.handleWxPayment(prepayRes);
if (result === 'success') {
await Promise.all([
this.updateOrderStatus(this.orderId, '2'),
this.insertSchoolStudent()
]);
this.signContract();
}
return result;
},
// 线下支付
async xxiaPayClick() {
const res = await request({
url: '/small/jxInfo/offLinePay',
method: 'post',
data: {
userName: this.name,
userPhone: this.phone,
userSex: this.sex,
tenantId: this.tenantId,
userNo: this.identity,
courseId: this.courseId,
coachUserName: this.jlName,
coachUserId: this.jlId,
courseType: this.rightInfoList.type,
courseName: this.rightInfoList.name,
reserveMoney: this.rightInfoList.price,
payType: '2',
userId: this.userId,
}
});
if (res.code === 0) {
const contractData = {
adress: this.Address,
name: this.name,
tenantId: this.tenantId,
type: this.rightInfoList.price,
money: this.getRightInfoList,
indent: this.identity,
phone: this.phone,
time: this.getCurrentDateTime()
};
uni.navigateTo({
url: '/pages/index/contract?data=' + encodeURIComponent(JSON.stringify(contractData))
});
}
},
async getRightInfoList() {
let res = await request({
url: '/app-api/dl-drive-school-course-small/get?id=' + this.courseId,
method: 'get',
})
this.rightInfoList = res.data,
this.currentPrice = this.rightInfoList.price;
console.log("111222333", this.rightInfoList)
},
// 处理已存在的订单
async processExistingOrder() {
uni.showLoading({title: '准备支付...', mask: true});
try {
if (this.startPay === 1) {
const payType = this.selectedPayType;
const res = await request({
url: `/small/jxInfo/prepayment?type=jsapi&orderNo=${this.orderNo}&orderId=${this.orderId}&payType=${payType}`,
method: 'get'
});
/* if(res.userName != this.name ||
res.userPhone != this.phone ||
res.coachUserId != this.jlId ||
res.coachUserName != jlName ||
res.userNo != this.identity ||
res.userSex != this.sex ||
res.reserveMoney != this.payPrice ||
res.payType != this.payType
res.restMoney != ){
} */
const result = await this.handleWxPayment(res);
if (result === 'success') {
await Promise.all([
this.updateOrderStatus(this.orderId, '2'),
this.insertSchoolStudent()
]);
this.signContract();
}
return result;
} else {
this.xxiaPayClick();
return 'success';
}
} finally {
uni.hideLoading();
}
},
// 微信支付处理
handleWxPayment(paymentParams) {
return new Promise((resolve) => {
wx.requestPayment({
...paymentParams,
success: (res) => {
resolve(res.errMsg === 'requestPayment:ok' ? 'success' : 'fail');
},
fail: (err) => {
resolve(err.errMsg === 'requestPayment:fail cancel' ? 'cancelled' : 'fail');
}
});
});
},
// 创建新订单
async createNewOrder() {
uni.showLoading({title: '创建订单中...', mask: true});
try {
if (this.startPay === 1) {
const payType = this.selectedPayType;
const reserveMoney = payType === 1
? this.rightInfoList.reserveMoney
: this.rightInfoList.price;
this.payPrice = reserveMoney
await this.wxPayClick(
this.name,
this.phone,
this.identity,
this.courseId,
payType,
reserveMoney,
payType === 1 ? this.rightInfoList.price - reserveMoney : 0
);
} else {
this.xxiaPayClick();
}
} finally {
uni.hideLoading();
}
},
// 上传
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1)
if (event.name == '1') {
this.photoUrl.splice(event.index, 1)
}
if (event.name == '2') {
this.videoUr = null
}
},
// 新增图片
async afterRead(event) {
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}))
fileListLen++
}
},
uploadFilePromise(e) {
console.log(e);
upload({
url: '/app-api/small-upload/common/upload',
filePath: e,
}).then((res) => {
console.log('sfz', res)
this.sfzimg = this.baseUrl + '/' + res.data.url
console.log(this.sfzimg);
if (this.sfzimg) {
this.idOcr(this.sfzimg)
}
})
},
async idOcr(url) {
console.log('url', url)
console.log('sfz', this.sfzimg)
let that = this
let res = await request({
url: '/app-api/small-upload/idOcr',
method: 'post',
params: {
imagePath: url
}
})
console.log('321', res)
that.name = res.data.name
that.phone = res.data.phone
that.sex = res.data.sex
that.identity = res.data.idCard
that.age = res.data.age
that.Address = res.data.Address
console.log('654', res);
that.popupShow = false
},
// 更新订单状态
async updateOrderStatus(orderId, status) {
await request({
url: '/app-api/small/drive/school-course-order/update',
method: 'put',
data: {
id: orderId,
paymentStatus: status
}
});
},
// 插入学员信息
insertSchoolStudent() {
request({
url: '/app-api/small/dl-drive-school-student/create',
method: 'post',
data: {
avatar: this.userinfo.avatar,
name: this.name,
age: this.age,
sex: this.sex,
phone: this.phone,
idCard: this.identity,
registAddress: this.Address,
userId: this.userinfo.id,
tenantId: this.tenantId,
idPhoto: this.sfzimg,
}
})
this.updateSysUsersNickName()
},
// 修改users信息
updateSysUsersNickName(){
request({
url: '/app-api/system/user/update',
method: 'PUT',
data: {
nickname: this.name,
id: this.userInfo.id
}
})
},
// 校验是否登录
checkLogin() {
const token = uni.getStorageSync('App-Token');
console.log(token)
if (!token) {
uni.showToast({title: '请先登录', icon: 'none'});
return false;
}
return true;
},
// 格式化时间
getCurrentDateTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
// return now;
},
// 签合同
signContract() {
const contractData = {
adress: this.Address,
name: this.name,
tenantId: this.tenantId,
type: this.rightInfoList.type,
money: this.payPrice,
indent: this.identity,
phone: this.phone,
time: this.getCurrentDateTime()
};
uni.navigateTo({
url: '/pages/index/contract?data=' + encodeURIComponent(JSON.stringify(contractData))
})
},
// 获取订单状态
async getPayStatus(orderId) {
const res = await request({
url: '/app-api/small/drive/school-course-order/get?id=' + orderId,
method: 'GET'
});
this.payStatus = res.data.paymentStatus;
return res.data.paymentStatus;
},
}
}
</script>
<style scoped lang="scss">
.bm-page {
padding: 30rpx;
.bm-page-button {
margin-top: 30rpx;
.bm-page-button-main {
border-radius: 50rpx;
background-color: #2C78F5;
color: #fff;
}
}
.bm-page-dj {
margin-top: 30rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 20rpx;
.dj-list {
padding: 20rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
.dj-list-left {
display: flex;
align-items: center;
.dj-list-left-name {
margin-left: 20rpx;
}
.dj-list-left-img {
height: 50rpx;
width: 50rpx;
}
}
}
.bm-page-dj-title {
border-bottom: 1rpx solid #eee;
padding-bottom: 20rpx;
margin-bottom: 10rpx;
display: flex;
align-items: center;
justify-content: space-between;
.bm-page-dj-title-price {
color: red;
}
}
}
.bm-page-info {
margin-top: 30rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 20rpx;
.info-name {
width: 100%;
padding: 40rpx 0;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
.info-name-right {
display: flex;
align-items: center;
margin-left: 30rpx;
flex: 3;
}
.info-name-left {
flex: 1;
}
}
.bm-page-info-title {
font-size: 34rpx;
font-weight: 600;
}
}
.bm-page-top {
display: flex;
padding: 30rpx;
background-color: #fff;
border-radius: 20rpx;
.bm-page-right {
margin-left: 30rpx;
display: flex;
justify-content: space-between;
flex-direction: column;
.bm-page-right-3 {
.bm-page-right-price {
color: red;
}
.bm-page-right-jprice {
margin-left: 20rpx;
text-decoration: underline;
font-size: 20rpx;
}
}
.bm-page-right-1 {
font-weight: 800;
}
.bm-page-right-2 {
display: flex;
font-size: 22rpx;
.bm-page-right-zd {
background-color: #dfebff;
}
.bm-page-right-c2 {
background-color: rgba(255, 208, 112, 0.2);
}
view {
text-align: center;
border-radius: 12rpx;
padding: 10rpx;
background-color: red;
margin-right: 10rpx;
}
&:last-child {
margin-right: 20rpx;
}
}
}
.top-left-img {
height: 150rpx;
width: 230rpx;
border-radius: 12rpx;
}
}
}
.content {
background: #f4f5f6;
// background: linear-gradient(180deg, #9ffcc5 0%, #84fcbc 14%, rgba(255, 255, 255, 0.84) 24%, rgba(255, 255, 255, 0.84) 100%);
height: 100vh;
}
.container {
width: 100%;
background: #f4f5f6;
box-sizing: border-box;
padding-top: 88px;
}
.onel {
width: 18px;
height: 18px;
border-radius: 50%;
overflow: hidden;
border: 1px solid #8c8c8d;
}
.twol {
width: 18px;
height: 18px;
border-radius: 50%;
overflow: hidden;
border: 1px solid #2C78F5;
background: #2C78F5;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.d-s {
display: flex;
align-items: center;
}
.anniu {
width: 120px;
height: 35px;
border-radius: 4px;
background: #2C78F5;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.popup-box {
width: 300px;
border-radius: 10px;
background: #fff;
box-sizing: border-box;
padding: 10px;
}
.title_s {
font-weight: bold;
margin-bottom: 10px;
}
.clv {
color: #fff;
background: #2C78F5;
width: 26px;
height: 26px;
border-radius: 50%;
display: flex;
font-size: 14px;
align-items: center;
justify-content: center;
font-weight: bold;
}
.size-lv {
margin-right: 35px;
}
</style>