driverSchool/newPages/register/index.vue

979 lines
25 KiB
Vue
Raw Normal View History

2025-03-27 15:49:36 +08:00
<template>
2025-04-07 18:08:13 +08:00
<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">
2025-04-09 10:05:29 +08:00
<image class="dj-list-left-img" src="../../static/imgs/yfk2.png" mode=""></image>
2025-04-07 18:08:13 +08:00
<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">
2025-04-09 10:05:29 +08:00
<image class="dj-list-left-img" src="../../static/imgs/qbdd2.png" mode=""></image>
2025-04-07 18:08:13 +08:00
<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>
2025-03-27 15:49:36 +08:00
</template>
<script>
2025-04-07 18:08:13 +08:00
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' //签名文字颜色
2025-04-07 16:41:23 +08:00
},
2025-04-07 18:08:13 +08:00
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: {
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/page',
method: 'get',
params: {
tenantId: this.tenantId,
},
tenantIdFlag: false
})
console.log(res);
this.columnjl = [
res.data.records.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.id; // 获取教练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 = { /* ...合同数据... */};
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'
});
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;
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,
}
})
2025-04-09 10:56:33 +08:00
this.updateSysUsersNickName()
2025-04-07 18:08:13 +08:00
},
2025-04-09 10:56:33 +08:00
updateSysUsersNickName(){
request({
url: '/app-api/system/user/update',
method: 'PUT',
params: {
nickName: this.name,
id: this.userInfo.id
}
})
},
2025-04-07 18:08:13 +08:00
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;
},
}
}
2025-03-27 15:49:36 +08:00
</script>
<style scoped lang="scss">
2025-04-07 18:08:13 +08:00
.bm-page {
padding: 30rpx;
.bm-page-button {
margin-top: 30rpx;
.bm-page-button-main {
border-radius: 50rpx;
2025-04-09 10:05:29 +08:00
background-color: #2C78F5;
2025-04-07 18:08:13 +08:00
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 {
2025-04-09 10:05:29 +08:00
background-color: #dfebff;
2025-04-07 18:08:13 +08:00
}
.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;
2025-04-09 10:05:29 +08:00
border: 1px solid #2C78F5;
background: #2C78F5;
2025-04-07 18:08:13 +08:00
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;
2025-04-09 10:05:29 +08:00
background: #2C78F5;
2025-04-07 18:08:13 +08:00
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;
2025-04-09 10:05:29 +08:00
background: #2C78F5;
2025-04-07 18:08:13 +08:00
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;
}
2025-03-27 15:49:36 +08:00
</style>