diff --git a/App.vue b/App.vue index 1e4f5d0..f1be3c1 100644 --- a/App.vue +++ b/App.vue @@ -9,8 +9,7 @@ onLaunch: function() { var that = this; util.getOpenidInfo(function(res) { - console.log(res); - + console.log(res); }, true); const updateManager = uni.getUpdateManager(); updateManager.onCheckForUpdate(function(res) { @@ -47,7 +46,7 @@ }, onHide: function() { console.log('App Hide') - } + }, } @@ -98,4 +97,4 @@ .orderBoxInfoRowTxt { font-size: 28rpx !important; } - + diff --git a/manifest.json b/manifest.json index 3c380f0..53600e9 100644 --- a/manifest.json +++ b/manifest.json @@ -86,6 +86,9 @@ "key" : "" } } + }, + "router" : { + "base" : "h5" } } } diff --git a/packages/activity/book.vue b/packages/activity/book.vue index 305872d..94794ae 100644 --- a/packages/activity/book.vue +++ b/packages/activity/book.vue @@ -25,7 +25,7 @@ - 人数限制:{{(list.form==2?10 : (numberlist.total==0?'不限':numberlist.total))}} + 人数限制:{{(list.form==2?10 : (numberlist.total==0?'不限':numberlist.total))}} @@ -198,35 +198,41 @@ - - - - - - {{currentNotice.title}} - - - - - - - 下载模版 - - - - 知道了 - - + keyName="label"> + + + + + + {{currentNotice.title}} + + + + + + + 下载模版 + + + + 知道了 + + - 请授权您的手机号 + {{isH5 ? '请输入您的手机号' : '请授权您的手机号'}} - 授权手机号 + + + + 确认 + + + 授权手机号 @@ -257,6 +263,8 @@ isEdit: false, isEditIndex: 0, showInfo: false, + isH5: false, + inputMobile: '', list: {}, numberlist: {}, common_user: [], @@ -328,55 +336,58 @@ content: "

1.批量上传EXCEL的以xlsx结尾

2.第一列为标题列 姓名 手机号 证件号

3.文件是从微信聊天记录中选取或者微信文件传输助手

" }] } - }, - onShareAppMessage() { - return this.util.shareInfo - }, - - onShareTimeline(){ - return this.util.shareInfo + }, + onShareAppMessage() { + return this.util.shareInfo + }, + + onShareTimeline(){ + return this.util.shareInfo }, onLoad(options) { this.type = options.type; this.form.type = (options.type == 'user' ? 2 : 1); this.form.activity_id = parseInt(options.activity_id); this.form.activity_number_id = parseInt(options.activity_number_id); - }, - onShow(){ - var that = this; - that.numberlist={}; - wx.getStorage({ - key: 'activityinfo', - success(res) { - that.list = res.data; - for (var m of that.list.numbers) { - if (that.form.activity_number_id == m.id) { - that.numberlist = m - } - } - if (that.form.type == 2) { - that.form.total = 1 - } else if (that.form.type == 1) { - that.form.total = 1;//res.data.team_min_count; - } - } - }) - - //先登录 - that.util.getOpenidInfo(function(res) { - //手机号 - that.util.getUserInfo(function(r) { - //如果手机号为空 需要先授权手机号 - if (that.util.isNull(r.mobile)) { - that.showAuthorization = true; - } else { - that.showAuthorization = false; - that.form.mobile = r.mobile; - } - }, true); - that.loadCommonUser() - - }, true); + + // 检测运行环境 + this.isH5 = typeof window !== 'undefined' && window.location + }, + onShow(){ + var that = this; + that.numberlist={}; + wx.getStorage({ + key: 'activityinfo', + success(res) { + that.list = res.data; + for (var m of that.list.numbers) { + if (that.form.activity_number_id == m.id) { + that.numberlist = m + } + } + if (that.form.type == 2) { + that.form.total = 1 + } else if (that.form.type == 1) { + that.form.total = 1;//res.data.team_min_count; + } + } + }) + + //先登录 + that.util.getOpenidInfo(function(res) { + //手机号 + that.util.getUserInfo(function(r) { + //如果手机号为空 需要先授权手机号 + if (that.util.isNull(r.mobile)) { + that.showAuthorization = true; + } else { + that.showAuthorization = false; + that.form.mobile = r.mobile; + } + }, true); + that.loadCommonUser() + + }, true); }, onHide() { clearInterval(this.t) @@ -387,35 +398,63 @@ clearInterval(this.t) clearTimeout(this.timer) }, - methods: { - - downLoad() { - const downloadTask = uni.downloadFile({ - url: 'https://gbyuyue.szgmbwg.org.cn/Template.xlsx', //仅为示例,并非真实的资源 - success: (res) => { - var filePath = res.tempFilePath - if (res.statusCode === 200) { - uni.openDocument({ - filePath: filePath, - showMenu: true, - success: function(res) { - console.log('打开文档成功') - } - }) - } - } - }); - - downloadTask.onProgressUpdate((res) => { - console.log('下载进度' + res.progress); - console.log('已经下载的数据长度' + res.totalBytesWritten); - console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite); - - }); + methods: { + + downLoad() { + const downloadTask = uni.downloadFile({ + url: 'https://gbyuyue.szgmbwg.org.cn/Template.xlsx', //仅为示例,并非真实的资源 + success: (res) => { + var filePath = res.tempFilePath + if (res.statusCode === 200) { + uni.openDocument({ + filePath: filePath, + showMenu: true, + success: function(res) { + console.log('打开文档成功') + } + }) + } + } + }); + + downloadTask.onProgressUpdate((res) => { + console.log('下载进度' + res.progress); + console.log('已经下载的数据长度' + res.totalBytesWritten); + console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite); + + }); }, closePhone() { this.showAuthorization = false }, + // H5环境:确认手机号 + confirmMobile() { + if (!this.inputMobile) { + uni.showToast({ title: '请输入手机号', icon: 'none' }) + return + } + if (!/^1[3-9]\d{9}$/.test(this.inputMobile)) { + uni.showToast({ title: '请输入正确的手机号', icon: 'none' }) + return + } + + var that = this; + this.util.request({ + api: '/api/mobile/user/save', + method: 'POST', + data: { + mobile: this.inputMobile + }, + utilSuccess: function(res) { + that.form.mobile = that.inputMobile; + that.showAuthorization = false + }, + utilFail: function(res) { + uni.showToast({ title: '手机号保存失败', icon: 'none' }) + } + }) + }, + // 小程序环境:微信授权获取手机号 getPhoneNumber(e) { var that = this; this.util.request({ @@ -709,25 +748,25 @@ } } - \ No newline at end of file diff --git a/pages/mine/index.vue b/pages/mine/index.vue index 62c63bf..05ee62b 100644 --- a/pages/mine/index.vue +++ b/pages/mine/index.vue @@ -66,15 +66,32 @@ - 请授权您的微信头像和昵称 + {{isH5 ? '请完善您的个人信息' : '请授权您的微信头像和昵称'}} - 微信用户一键登录 + + + + + + + + + + + 确认提交 + + + 微信用户一键登录 - + + 请确认编辑您的微信头像和昵称 @@ -92,7 +109,6 @@ 确认提交 - @@ -123,20 +139,24 @@ form: { name: '', avatar: '' - } + }, + isH5: false } }, - onReady() {}, - onShareAppMessage() { - return this.util.shareInfo - }, - - onShareTimeline(){ - return this.util.shareInfo + onReady() {}, + onShareAppMessage() { + return this.util.shareInfo + }, + + onShareTimeline(){ + return this.util.shareInfo }, onShow() { var that = this; + // 检测运行环境 + this.isH5 = typeof window !== 'undefined' && window.location + this.action = this.util.HOST + "/api/mobile/upload-file" this.otherData.token = uni.getStorageSync("userInfo_token").token; this.loadInfo(function(res) { @@ -175,7 +195,13 @@ url: res.avatarUrl }) that.showAuthorization = false - that.showform = true + // 小程序环境:显示确认编辑弹窗 + // H5环境:直接提交(因为已经在第一个弹窗中编辑了) + if (that.isH5) { + that.tosubmit() + } else { + that.showform = true + } }) }, uploadSuccess(res) { @@ -198,12 +224,12 @@ this.avatarList = res.tempFilePaths this.form.avatar = '' }, - tosubmit() { - if(this.util.isNull(this.form.name)){ - uni.showLoading({ - title: "请填写昵称" - }) - return + tosubmit() { + if(this.util.isNull(this.form.name)){ + uni.showLoading({ + title: "请填写昵称" + }) + return } var that = this that.util.request({ @@ -213,7 +239,7 @@ headimgurl: that.form.avatar, nickname: that.form.name }, - utilSuccess: function(r) { + utilSuccess: function(r) { that.showform = false; that.loadInfo(function() { diff --git a/pages/visit/book.vue b/pages/visit/book.vue index 0afa053..b953a25 100644 --- a/pages/visit/book.vue +++ b/pages/visit/book.vue @@ -92,9 +92,9 @@ - - + + @@ -299,10 +299,16 @@ - 请授权您的手机号 + {{isH5 ? '请输入您的手机号' : '请授权您的手机号'}} - 授权手机号 + + + + 确认 + + + 授权手机号 @@ -331,15 +337,17 @@ time: 3, showInfo: false, currentNotice: {}, + isH5: false, + inputMobile: '', maxheight: "", scrollheight: "", notice: [{ title: "参观须知", - content: "参观须知的内容", + content: "参观须知的内容", isTemplate:false }, { title: "批量上传帮助", - content: "

1.批量上传EXCEL的以xlsx结尾

2.第一行为标题行 姓名 手机号 行动不便者

3.文件是从微信聊天记录中选取或者微信文件传输助手

", + content: "

1.批量上传EXCEL的以xlsx结尾

2.第一行为标题行 姓名 手机号 行动不便者

3.文件是从微信聊天记录中选取或者微信文件传输助手

", isTemplate:true }], specialtype: false, @@ -472,6 +480,8 @@ //this.maxCount = (type == 'user' ? 5 : 50); var that = this; + // 检测运行环境 + this.isH5 = typeof window !== 'undefined' && window.location //先登录 that.util.getOpenidInfo(function(res) { @@ -499,10 +509,10 @@ }, onShareAppMessage() { return this.util.shareInfo - }, - - onShareTimeline(){ - return this.util.shareInfo + }, + + onShareTimeline(){ + return this.util.shareInfo }, onUnload() { clearInterval(this.t) @@ -513,7 +523,34 @@ closePhone() { this.showAuthorization = false }, - //获取手机授权 + // H5环境:确认手机号 + confirmMobile() { + if (!this.inputMobile) { + uni.showToast({ title: '请输入手机号', icon: 'none' }) + return + } + if (!/^1[3-9]\d{9}$/.test(this.inputMobile)) { + uni.showToast({ title: '请输入正确的手机号', icon: 'none' }) + return + } + + var that = this; + this.util.request({ + api: '/api/mobile/user/save', + method: 'POST', + data: { + mobile: this.inputMobile + }, + utilSuccess: function(res) { + that.form.mobile = that.inputMobile; + that.showAuthorization = false + }, + utilFail: function(res) { + uni.showToast({ title: '手机号保存失败', icon: 'none' }) + } + }) + }, + // 小程序环境:微信授权获取手机号 getPhoneNumber(e) { var that = this; this.util.request({ @@ -599,7 +636,7 @@ downLoad() { const downloadTask = uni.downloadFile({ url: 'https://gbyuyue.szgmbwg.org.cn/Template.xlsx', //仅为示例,并非真实的资源 - success: (res) => { + success: (res) => { var filePath = res.tempFilePath if (res.statusCode === 200) { uni.openDocument({ @@ -671,14 +708,14 @@ this.form.date = this.currentDate.date; this.form.rule_id = this.currentTime.id; - if(this.type!='team'){ - if (this.form.details_list.length != this.form.total) { - uni.showToast({ - icon: "none", - title: "请正确添加观众信息" - }) - return false; - } + if(this.type!='team'){ + if (this.form.details_list.length != this.form.total) { + uni.showToast({ + icon: "none", + title: "请正确添加观众信息" + }) + return false; + } } if (this.type != "user") { @@ -966,9 +1003,9 @@ this.$forceUpdate(); }, handleSelectTime(index) { - var mod = this.currentDate.rules[index]; - if (!mod.isCanbook) { - return false + var mod = this.currentDate.rules[index]; + if (!mod.isCanbook) { + return false } if (mod.remain_count == 0) { this.util.toast("该时段已不可参观"); @@ -1050,9 +1087,9 @@ that.currentTime = {}; let isDefault = false; for (var mod of rules) { - mod.checked = false; - mod.endtime = that.currentDate.date + " " + mod.end_time; - var isCanbook = that.$moment(nt).isBefore(mod.endtime); + mod.checked = false; + mod.endtime = that.currentDate.date + " " + mod.end_time; + var isCanbook = that.$moment(nt).isBefore(mod.endtime); mod.isCanbook = isCanbook; if (that.bcurrentTime) { if (that.bcurrentTime.id == mod.id) { @@ -1107,10 +1144,10 @@ .timeitem-none { color: #ccc; } - - .commonuser .book-box-row-timeitem{ - font-size:30rpx; - border-radius: 10rpx; + + .commonuser .book-box-row-timeitem{ + font-size:30rpx; + border-radius: 10rpx; } .box-visitor-item { display: flex; @@ -1277,15 +1314,15 @@ .u-radio-group .u-radio { margin-bottom: 10rpx; margin-right: 10rpx - } - .book-box-row-timeitem { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 32%; - padding: 19rpx 21rpx!important; - } - .book-box-row-timeitem-txt { - width:100% + } + .book-box-row-timeitem { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 32%; + padding: 19rpx 21rpx!important; + } + .book-box-row-timeitem-txt { + width:100% } \ No newline at end of file diff --git a/utils/util.js b/utils/util.js index 6bd199f..33c4136 100755 --- a/utils/util.js +++ b/utils/util.js @@ -1,48 +1,48 @@ import md5 from "./md5.min"; const HOSTARR = { // 'development':'https://gb-test.ali251.langye.net', - // 'production': 'https://gb-test.ali251.langye.net', - 'development':'https://gbyuyue.szgmbwg.org.cn', - 'production': 'https://gbyuyue.szgmbwg.org.cn', + // 'production': 'https://gb-test.ali251.langye.net', + 'development':'https://gbyuyue.szgmbwg.org.cn', + 'production': 'https://gbyuyue.szgmbwg.org.cn', // https://gbyuyue.szgmbwg.org.cn/ }; // 审核状态 const HOST = HOSTARR[process.env .NODE_ENV]; //"https://tiantianxinye.365care.langye.net/";//HOSTARR[process.env.NODE_ENV];// - -const replaceImgUrl = (str,before,after)=>{ - if(str.indexOf(before) != -1){ - return str.replace(new RegExp(before, 'g'),after) - }else{ - return str - } -} - -const splitTime = (start,end)=> { - let arrStart = start.substring(0, 10).split("-") - let year = parseInt(arrStart[0]) - let month = parseInt(arrStart[1]) < 10 ? parseInt(arrStart[1]) : parseInt(arrStart[1]) + +const replaceImgUrl = (str,before,after)=>{ + if(str.indexOf(before) != -1){ + return str.replace(new RegExp(before, 'g'),after) + }else{ + return str + } +} + +const splitTime = (start,end)=> { + let arrStart = start.substring(0, 10).split("-") + let year = parseInt(arrStart[0]) + let month = parseInt(arrStart[1]) < 10 ? parseInt(arrStart[1]) : parseInt(arrStart[1]) let day = parseInt(arrStart[2]) < 10 ? parseInt(arrStart[2]) : parseInt(arrStart[2]) - if (end) { - // 判断end 是否为时间格式 - if(isNaN(end)&&!isNaN(Date.parse(end))){ - let arrEnd = end.substring(0, 10).split("-") - let yearEnd = parseInt(arrEnd[0]) - let monthEnd = parseInt(arrEnd[1]) < 10 ? parseInt(arrEnd[1]) : parseInt(arrEnd[1]) - let dayEnd = parseInt(arrEnd[2]) < 10 ? parseInt(arrEnd[2]) : parseInt(arrEnd[2]) - if(year == yearEnd){ - return year + '年' + month + '月' + day + '日' + '至' + monthEnd + '月' + dayEnd + '日' - }else{ - return year + '年' + month + '月' + day + '日' + '至' + yearEnd + '年'+monthEnd + '月' + dayEnd + '日' - } - }else{ - return year + '年' + month + '月' + day + '日' + '至' + end + if (end) { + // 判断end 是否为时间格式 + if(isNaN(end)&&!isNaN(Date.parse(end))){ + let arrEnd = end.substring(0, 10).split("-") + let yearEnd = parseInt(arrEnd[0]) + let monthEnd = parseInt(arrEnd[1]) < 10 ? parseInt(arrEnd[1]) : parseInt(arrEnd[1]) + let dayEnd = parseInt(arrEnd[2]) < 10 ? parseInt(arrEnd[2]) : parseInt(arrEnd[2]) + if(year == yearEnd){ + return year + '年' + month + '月' + day + '日' + '至' + monthEnd + '月' + dayEnd + '日' + }else{ + return year + '年' + month + '月' + day + '日' + '至' + yearEnd + '年'+monthEnd + '月' + dayEnd + '日' + } + }else{ + return year + '年' + month + '月' + day + '日' + '至' + end } } else { return year + '年' + month + '月' + day + '日' + '起' } -} +} const formatTime = date => { const year = date.getFullYear(); @@ -75,32 +75,95 @@ const getUserInfo = (cb, refresh) => { } const getOpenidInfo = (cb, refresh) => { - cb = cb || function() {} - refresh = refresh || false - if (!refresh) { - let user_info = uni.getStorageSync(user_info_key) - if (!isNull(user_info)) { - cb(user_info) - return - } + // cb = cb || function() {} + // refresh = refresh || false + // console.log("getOpenidInfo", refresh) + // if (!refresh) { + // let user_info = uni.getStorageSync(user_info_key) + // if (!isNull(user_info)) { + // cb(user_info) + // return + // } + // } + let user_info = uni.getStorageSync(user_info_key) + if (!isNull(user_info)) { + cb(user_info) + return + } + // 判断运行环境:H5还是小程序 + const isH5 = typeof window !== 'undefined' && window.location + const isWeixinBrowser = isH5 && /MicroMessenger/i.test(navigator.userAgent) + + if (isH5 && isWeixinBrowser) { + // H5环境下的微信授权登录 + wxH5AuthLogin(cb) + } else { + // 小程序环境下的微信登录 + uni.login({ + provider: 'weixin', + success: (res) => { + console.log(res.code); + let url = HOST + '/api/mobile/user/login?code=' + res.code; + uni.request({ + url: url, + method: 'GET', + success: result => { + let user_info = result.data + uni.setStorageSync(user_info_key, user_info) + cb(user_info) + } + }); + } + }); } +} - uni.login({ - provider: 'weixin', - success: (res) => { - console.log(res.code); - let url = HOST + '/api/mobile/user/login?code=' + res.code; - uni.request({ - url: url, - method: 'GET', - success: result => { - let user_info = result.data - uni.setStorageSync(user_info_key, user_info) - cb(user_info) +// H5环境下的微信授权登录 +const wxH5AuthLogin = (cb) => { + let link = window.location.href; + if (/code=/.test(link) || link.indexOf("code") > -1) { + // 已经获取到授权码,直接登录 + let temp = decodeURIComponent((new RegExp('[?|&]' + 'code' + '=' + '([^&;]+?)(&|#|;|$)').exec( + link) || [, ''])[1].replace(/\+/g, '%20')) || null; + console.log("code", temp) + + // 上传 code 到服务器获取 token + request({ + api: `/api/mobile/user/wx-login?code=${temp}`, + method: 'GET', + utilSuccess: (res) => { + if (res.token && res.token.trim() !== '') { + console.log('获取 token 成功:', res.token) + // 保持与小程序登录一致的存储方式 + const userInfo = { + token: res.token, + // 可以根据需要添加其他字段,如 WeChatOpenID 等 + } + uni.setStorageSync(user_info_key, userInfo) + cb(userInfo) + } else { + console.error('登录失败: token为空') + uni.showToast({ title: '登录失败,请重试', icon: 'none' }) } - }); - } - }); + }, + utilFail: (err) => { + console.error('获取 token 失败:', err) + uni.showToast({ title: '登录失败,请重试', icon: 'none' }) + } + }) + } else { + // 未获取授权码,跳转到微信授权页面 + const appId = 'wxbf4862e929ab85b0' + const currentUrl = window.location.href + const redirectUri = encodeURIComponent(currentUrl.replace(/#\//, "")); + const scope = 'snsapi_userinfo' + const state = 'STATE' + console.log(redirectUri) + const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect` + + // 重定向到微信授权页面 + window.location.href = authUrl + } } @@ -108,13 +171,39 @@ const getOpenidInfo = (cb, refresh) => { const getUserProfile = (cb) => { cb = cb || function() {} - wx.getUserProfile({ - desc: '用于完善会员资料', - success: (res) => { - uni.setStorageSync('user_profile', res.userInfo) - cb(res.userInfo) - } - }) + // 判断运行环境:H5还是小程序 + const isH5 = typeof window !== 'undefined' && window.location + const isWeixinBrowser = isH5 && /MicroMessenger/i.test(navigator.userAgent) + + if (isH5 && isWeixinBrowser) { + // H5环境下,通过后端接口获取用户信息 + // 微信公众号H5无法直接调用wx.getUserProfile + request({ + api: '/api/mobile/user/profile', + method: 'GET', + utilSuccess: (res) => { + uni.setStorageSync('user_profile', res) + cb(res) + }, + utilFail: (err) => { + console.error('获取用户信息失败:', err) + cb(null) + } + }) + } else { + // 小程序环境下,使用wx.getUserProfile + wx.getUserProfile({ + desc: '用于完善会员资料', + success: (res) => { + uni.setStorageSync('user_profile', res.userInfo) + cb(res.userInfo) + }, + fail: (err) => { + console.error('获取用户信息失败:', err) + cb(null) + } + }) + } } @@ -338,8 +427,8 @@ const isLogin = () => { const isNull = p => { return p == '' || p == undefined || p == null || p == 'undefined' || p == 'null'; -}; // 正则 - +}; // 正则 + const phoneRegex = /^1[3456789]\d{9}$/; @@ -391,11 +480,11 @@ const isValidCardID = cardID => { var last = parity[sum % 11]; return parity[sum % 11] == code[17]; -}; - -const shareInfo = { - title:"", - imageUrl:"/static/share.jpg" +}; + +const shareInfo = { + title:"", + imageUrl:"/static/share.jpg" } /** * UTF16和UTF8转换对照表 @@ -580,6 +669,7 @@ module.exports = { formatNumber: formatNumber, alert: alert, getOpenidInfo: getOpenidInfo, + wxH5AuthLogin: wxH5AuthLogin, request: request, payOrder: payOrder, isLogin: isLogin, @@ -594,9 +684,9 @@ module.exports = { auditStatusDic: auditStatusDic, getUserProfile: getUserProfile, getUserInfo: getUserInfo, - toast: toast, - isValidCardID:isValidCardID, - shareInfo:shareInfo, - replaceImgUrl:replaceImgUrl, + toast: toast, + isValidCardID:isValidCardID, + shareInfo:shareInfo, + replaceImgUrl:replaceImgUrl, splitTime:splitTime -}; +};