@@ -140,7 +150,7 @@ import api from '@/utils/api.js'; import { setToken, setUser } from '@/utils/request.js'; import { getWxCode } from '@/utils/wxlogin.js'; - import { setRole } from '@/utils/role.js'; + import { getRole, setRole } from '@/utils/role.js'; import { getWindowInfoSafe } from '@/utils/system.js'; const loading = ref(false); @@ -155,19 +165,19 @@ const showModal = ref(false); const modalType = ref('service'); + const remoteAgreementTitle = ref(''); + const remoteAgreementText = ref(''); let redirectUrl = ''; const statusBarHeight = ref(20); const modalTitle = computed(() => { + if (remoteAgreementTitle.value) return remoteAgreementTitle.value; return modalType.value === 'service' ? '优匠优服 用户服务协议' : '优匠优服 隐私保护指引'; }); const modalContent = computed(() => { - if (modalType.value === 'service') { - return `欢迎使用“优匠优服”平台服务!\n\n1. 平台定位:优匠优服为广大客户与专业技能师傅提供安全、规范的上门安装、维修与保洁维保撮合服务。\n2. 服务准则:平台师傅均经严格实名认证与技能核验,推行标准化计费与明码标价制度。\n3. 权益保障:凡通过平台系统下单且在线支付的订单,均享有专属售后质保与纠纷先行兜底保障。\n4. 履约规范:交易双方应恪守诚信原则,禁止私下转账交易,以保障服务质量与合法权益。`; - } - return `优匠优服非常重视您的隐私与个人信息安全保护:\n\n1. 信息收集范围:为您提供维修上门、订单追踪及联系客服等核心功能,经您明确授权后获取手机号码与必要服务地址。\n2. 账号识别机制:通过微信官方手机号授权建立统一登录凭证,严格遵守最小必要原则,绝不向任何未经授权的第三方非法共享。\n3. 数据传输安全:采用全链路 HTTPS/TLS 加密传输协议,全流程防护防止信息泄露或被滥用。\n4. 用户自主权利:您随时可以在个人中心查询、更新或注销您的个人账户。`; + return remoteAgreementText.value || '加载中...'; }); function toast(title) { @@ -181,7 +191,13 @@ } if (options && options.redirect) { - redirectUrl = decodeURIComponent(options.redirect); + let decoded = decodeURIComponent(options.redirect); + if (decoded.startsWith('%2F') || decoded.startsWith('%2f')) { + try { + decoded = decodeURIComponent(decoded); + } catch (e) {} + } + redirectUrl = decoded; } const pages = getCurrentPages(); @@ -208,14 +224,22 @@ handleBackOrHome(); } + function safeVibrate() { + // #ifdef MP-WEIXIN + try { + if (uni.vibrateShort) { + uni.vibrateShort({ type: 'light' }); + } + } catch (e) {} + // #endif + } + /** * 超大热区点击切换协议勾选 */ function toggleAgree() { agreePolicy.value = !agreePolicy.value; - if (uni.vibrateShort) { - uni.vibrateShort({ type: 'light' }); - } + safeVibrate(); } /** @@ -224,9 +248,7 @@ */ function handleTapButton() { if (!agreePolicy.value) { - if (uni.vibrateShort) { - uni.vibrateShort({ type: 'light' }); - } + safeVibrate(); triggerShake(); toast('请先阅读并勾选服务协议与隐私指引'); } @@ -244,9 +266,7 @@ */ async function handleAccountLogin() { if (!agreePolicy.value) { - if (uni.vibrateShort) { - uni.vibrateShort({ type: 'light' }); - } + safeVibrate(); triggerShake(); toast('请先阅读并勾选服务协议与隐私指引'); return; @@ -282,11 +302,13 @@ syncUserData(res); toast('登录成功'); - setTimeout(() => finishLogin(), 600); + setTimeout(() => { + loading.value = false; + finishLogin(); + }, 600); } catch (err) { - toast(err.message || '登录失败,请检查手机号或密码'); - } finally { loading.value = false; + toast(err.message || '登录失败,请检查手机号或密码'); } } @@ -330,38 +352,62 @@ syncUserData(res); toast(res.is_new ? '欢迎加入优匠优服' : '登录成功'); - setTimeout(() => finishLogin(), 600); + setTimeout(() => { + loading.value = false; + finishLogin(); + }, 600); } catch (err) { - toast(err.message || '微信手机号登录失败,请重试'); - } finally { loading.value = false; + toast(err.message || '微信手机号登录失败,请重试'); } } - /** 同步更新全局角色状态(基于真实接口返回的身份资质) */ + /** 同步更新全局角色状态(默认进入业主端,仅当明确从师傅端页面触发登录且具备接单师傅权限时保持师傅身份) */ function syncUserData(res) { - if (res && res.userinfo) { - if (res.userinfo.is_master) { - setRole('master'); - } else if (res.userinfo.is_merchant) { - setRole('merchant'); - } else { - setRole('user'); - } + const userinfo = (res && res.userinfo) || {}; + const canTakeAsMaster = Boolean(userinfo.is_master && (!userinfo.master || userinfo.master.can_take !== false)); + if (redirectUrl) { + const toMasterPage = (redirectUrl.startsWith('/pages/master/') && !redirectUrl.startsWith('/pages/master/apply')) + || redirectUrl.includes('role=master'); + setRole(toMasterPage && canTakeAsMaster ? 'master' : 'user'); + return; } + let prevRoute = ''; + try { + const pages = getCurrentPages() || []; + if (pages.length > 1) { + prevRoute = pages[pages.length - 2]?.route || ''; + } + } catch (e) {} + const fromMasterPage = prevRoute.startsWith('pages/master/') && !prevRoute.startsWith('pages/master/apply'); + setRole(fromMasterPage && canTakeAsMaster ? 'master' : 'user'); } - /** 登录完成后的智能流转 */ + /** 登录完成后的智能流转(确保当前页面与 yjyf_role 100% 匹配) */ function finishLogin() { if (redirectUrl) { - if (redirectUrl.startsWith('/pages/index/') || redirectUrl.startsWith('/pages/mine/')) { + if (getRole() !== 'master' && (redirectUrl.startsWith('/pages/master/') && !redirectUrl.startsWith('/pages/master/apply'))) { + uni.reLaunch({ url: '/pages/index/index' }); + return; + } + if (redirectUrl.startsWith('/pages/index/') || redirectUrl.startsWith('/pages/mine/') || redirectUrl.startsWith('/pages/master/hall')) { uni.reLaunch({ url: redirectUrl }); } else { - uni.redirectTo({ url: redirectUrl }); + uni.redirectTo({ + url: redirectUrl, + fail: () => { + uni.reLaunch({ url: redirectUrl }); + } + }); } return; } + if (getRole() === 'master') { + uni.reLaunch({ url: '/pages/master/hall' }); + return; + } + if (getCurrentPages().length > 1) { uni.navigateBack(); } else { @@ -369,9 +415,23 @@ } } - function openAgreement(type) { + async function openAgreement(type) { modalType.value = type; + remoteAgreementTitle.value = ''; + remoteAgreementText.value = ''; showModal.value = true; + try { + const apiType = type === 'service' ? 'user_service' : 'privacy'; + const res = await api.agreement(apiType); + const data = (res && (res.detail || res)) || {}; + if (data.title) remoteAgreementTitle.value = data.title; + const raw = data.content || ''; + remoteAgreementText.value = raw + ? String(raw).replace(//gi, '\n').replace(/<\/p>/gi, '\n\n').replace(/<[^>]+>/g, '').trim() + : '暂无协议正文'; + } catch (e) { + remoteAgreementText.value = '协议加载失败,请稍后重试'; + } } function confirmAgreement() { @@ -423,28 +483,21 @@ ); } - /* 顶部安全导航栏 */ - .nav-bar { - position: relative; - z-index: 10; - padding-left: 32rpx; - height: 88rpx; - display: flex; - align-items: center; - } - .nav-back-btn { - width: 72rpx; - height: 72rpx; - border-radius: 36rpx; - background: rgba(255, 255, 255, 0.85); - box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08); + /* 顶部安全导航栏返回键(半透明深色圆形底衬提升浅色背景对比度) */ + .login-nav-back { + width: 68rpx; + height: 68rpx; + margin-left: 8rpx; + border-radius: 34rpx; + background: rgba(15, 23, 42, 0.44); + border: 1rpx solid rgba(255, 255, 255, 0.28); + box-shadow: 0 4rpx 14rpx rgba(0, 0, 0, 0.16); display: flex; align-items: center; justify-content: center; backdrop-filter: blur(8px); - transition: background 0.2s ease; } - .nav-back-icon { + .login-nav-back-ico { width: 36rpx; height: 36rpx; } diff --git a/yjyf-app/pages/master/apply.vue b/yjyf-app/pages/master/apply.vue index ce76801..cb773ec 100644 --- a/yjyf-app/pages/master/apply.vue +++ b/yjyf-app/pages/master/apply.vue @@ -1,80 +1,201 @@ - diff --git a/yjyf-app/pages/master/credit.vue b/yjyf-app/pages/master/credit.vue index 3fa35e7..53dd255 100644 --- a/yjyf-app/pages/master/credit.vue +++ b/yjyf-app/pages/master/credit.vue @@ -1,93 +1,285 @@