feat: 质惠游 H5 一期 —— 门票模块全链路(微信公众号版)

从 xghmall(云闪付版湘工游)迁移民票模块,改造为微信公众号 H5:

- 技术栈沿用 uni-app + Vue2 + uView(含定制版日历组件)
- 登录/支付独立成层(common/auth.js、common/pay.js):
  一期假登录(测试手机号)+ 模拟支付,后端微信接口就绪后只换这两处
- 登录页重写:短信验证码 + 公众号网页授权(code 换用户信息)预留
- 门票列表页为入口页(进页必须登录),加订单悬浮按钮
- 支付成功页接通:查看订单/继续逛逛 + 订单状态轮询
- 详情页定位导航改用 uni.openLocation + 高德网页兜底
- 出行人页:身份证 18 位格式校验,删除死的删除按钮,修正证件类型回显笔误
- 清理云闪付 SDK、支付宝授权、死页面引用等残留

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
xuchao
2026-07-21 00:43:59 +08:00
co-authored by Claude Opus 4.8
commit 4190565eb7
192 changed files with 35664 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
<template>
<view class="auth_rq">
<image class="auth_rq_image" src="https://aliyunoss.hn12301.net/sd/ali_logo.png"></image>
<view class="auth_rq_view">质惠游</view>
<!-- xuchao: 开发模式提示(正式环境不显示) -->
<view class="auth_rq_tips" v-if="devMode">开发模式:输入测试手机号直接登录</view>
<view class="auth_rq_input" :style="{marginTop: devMode ? '40rpx' : '146rpx'}">
<u-input v-model="value" type="number" :border="false" :custom-style='customStyle' placeholder='请输入手机号' />
</view>
<!-- xuchao: 开发模式免验证码 -->
<view class="auth_rq_input" v-if="!devMode" style="margin-top: 50rpx;">
<u-input v-model="value1" type="number" :border="false" :custom-style='customStyle' placeholder='请输入验证码' />
<text style="margin-left: 30rpx;" :style="{color:isFlag?'#488CFE':'#666'}" @tap="getCode">{{tips}}</text>
</view>
<button class="auth_rq_button1" :style="{marginTop: devMode ? '80rpx' : '80rpx'}" @click="doLogin">立即登录</button>
<view style="margin-top: 32rpx;margin-left: 70rpx;">
<u-checkbox-group>
<u-checkbox v-model="checked" shape="circle" style="color: #929292;">我已阅读并同意<text
style="color: #488CFE;" @click="readXy()">用户服务协议</text></u-checkbox>
</u-checkbox-group>
</view>
<u-verification-code :seconds="seconds" @end="end" @start="start" ref="uCode"
@change="codeChange"></u-verification-code>
</view>
</template>
<script>
// xuchao: 登录页 —— 微信版
// 开发模式:输入测试手机号直接登录(假登录)
// 正式流程:微信网页授权(code 换用户信息)+ 短信验证码绑定手机号
import config from '@/common/config.js'
import auth from '@/common/auth.js'
export default {
data() {
return {
devMode: config.devMode,
redirect: '',
tips: '发送验证码',
seconds: 60,
checked: false,
value: '',
value1: '',
isFlag: true,
customStyle: {
background: '#f8f8f8',
}
}
},
onLoad(options) {
// xuchao: 记录登录前的页面,登录成功后回跳
if (options.redirect) {
this.redirect = decodeURIComponent(options.redirect)
}
// xuchao: 正式流程 —— 公众号网页授权重定向回来时 URL 带 code,用它换用户信息
if (options.code && !config.devMode) {
auth.loginByWechat(options.code).then(res => {
// 后端已绑定手机的用户直接登录成功
if (res && res.mobile) {
uni.setStorageSync('openId', res.openId)
uni.setStorageSync('phone', res.mobile)
this.finishLogin()
}
// 未绑定手机的用户停留在本页,走短信验证码绑定
}).catch(() => {})
}
},
methods: {
// xuchao: 登录入口
doLogin() {
if (!this.checked) {
uni.showToast({ icon: 'none', title: '请先阅读并同意用户服务协议' })
return
}
if (!/^1\d{10}$/.test(this.value)) {
uni.showToast({ icon: 'none', title: '请输入正确的手机号' })
return
}
if (config.devMode) {
// 开发模式:只允许测试手机号登录
if (config.testPhones.indexOf(this.value) === -1) {
uni.showToast({ icon: 'none', title: '开发模式仅支持测试手机号' })
return
}
auth.loginByMock(this.value)
this.finishLogin()
return
}
// 正式流程:短信验证码校验 + 绑定手机号
if (!this.value1) {
uni.showToast({ icon: 'none', title: '请输入验证码' })
return
}
auth.bindPhoneBySms(this.value, this.value1).then(() => {
this.finishLogin()
}).catch(() => {})
},
// xuchao: 登录成功后回跳
finishLogin() {
uni.showToast({ icon: 'success', title: '登录成功' })
setTimeout(() => {
if (this.redirect) {
uni.reLaunch({ url: this.redirect })
} else if (getCurrentPages().length > 1) {
uni.navigateBack()
} else {
uni.reLaunch({ url: '/pages/ticket/scenic' })
}
}, 500)
},
end() {
this.isFlag = true
},
start() {
this.isFlag = false
},
readXy() {
uni.downloadFile({
url: "https://aliyunoss.hn12301.net/sd/zfzxy.docx",
success: function(res) {
uni.openDocument({
filePath: res.tempFilePath,
showMenu: true
});
}
});
},
codeChange(text) {
this.tips = text;
},
// xuchao: 发送验证码 —— 开发模式仅走倒计时,正式流程需后端短信接口
getCode() {
if (!/^1\d{10}$/.test(this.value)) {
uni.showToast({ icon: 'none', title: '请输入正确的手机号' })
return
}
if (!this.$refs.uCode.canGetCode) {
this.$u.toast('倒计时结束后再发送');
return
}
if (config.devMode) {
this.$u.toast('验证码已发送');
this.$refs.uCode.start();
return
}
// TODO 后端就绪后替换为真实发送短信验证码接口
uni.showLoading({ title: '正在获取验证码' })
setTimeout(() => {
uni.hideLoading();
this.$u.toast('短信接口未接入');
}, 1000);
}
}
}
</script>
<style>
page {
background: #ffffff;
}
</style>
<style lang="less" scoped>
.auth_rq {
.auth_rq_input {
display: flex;
width: 610rpx;
height: 98rpx;
align-items: center;
padding-left: 40rpx;
margin-left: 70rpx;
background-color: #F8F8F8;
border-radius: 8px;
padding-right: 40rpx;
}
.auth_rq_image {
width: 164rpx;
height: 140rpx;
margin-top: 182rpx;
margin-left: 294rpx;
}
.auth_rq_view {
width: 750rpx;
text-align: center;
color: #0DD381;
font-size: 36rpx;
margin-top: 18rpx;
}
// xuchao: 开发模式提示条
.auth_rq_tips {
width: 610rpx;
margin: 40rpx 0 0 70rpx;
padding: 16rpx 24rpx;
box-sizing: border-box;
background-color: #FDF6EC;
color: #E6A23C;
font-size: 24rpx;
border-radius: 8px;
}
.auth_rq_button1 {
width: 610rpx;
margin-left: 70rpx;
margin-top: 80rpx;
height: 98rpx;
border-radius: 49rpx;
background-color: #488CFE;
color: #fff;
}
}
</style>