feat(auth): 共享授权页 pages/annex/auth/index + web_view 宿主授权面板与回传(__AUTH_RESULT__ → H5 hash)
This commit is contained in:
@@ -2,6 +2,24 @@
|
||||
<view>
|
||||
<web-view v-if="url" class="web-view" :webview-styles="webviewStyles" :src="url"
|
||||
:style="{width: windowW + 'px', height: windowH + 'px'}" @message="handleMessage"></web-view>
|
||||
|
||||
<!-- 共享原生授权面板(任意 H5 应用 postMessage({action:'requestProfile'}) 后显示) -->
|
||||
<view v-if="showAuth" class="mb-auth-mask" @tap="closeAuth">
|
||||
<view class="mb-auth-panel" @tap.stop="noop">
|
||||
<view class="mb-auth-title">授权完善资料</view>
|
||||
<view class="mb-auth-sub">用于在应用里展示你的昵称 / 头像 / 手机号</view>
|
||||
<button class="mb-auth-btn avatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<image v-if="authAvatar" class="mb-auth-ava" :src="authAvatar" mode="aspectFill" />
|
||||
<text v-else>选择头像</text>
|
||||
</button>
|
||||
<input class="mb-auth-input" type="nickname" v-model="authNickname" placeholder="输入昵称" maxlength="16" />
|
||||
<button class="mb-auth-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhone">获取手机号</button>
|
||||
<view class="mb-auth-actions">
|
||||
<button class="mb-auth-cancel" @tap="closeAuth">取消</button>
|
||||
<button class="mb-auth-ok" @tap="submitAuth">保存并返回</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
@@ -101,7 +119,11 @@ export default {
|
||||
shareTimelineImage: '',
|
||||
shareHref: '',
|
||||
savedUrl: '',
|
||||
_shareFetched: false
|
||||
_shareFetched: false,
|
||||
showAuth: false, // 授权面板开关(H5 postMessage 后显示)
|
||||
authNickname: '',
|
||||
authAvatar: '',
|
||||
_authCode: '' // getPhoneNumber 的 code(提交时交 box_app 解密手机号)
|
||||
}
|
||||
},
|
||||
onLoad(option) {
|
||||
@@ -132,6 +154,26 @@ export default {
|
||||
// 1) 首次登录返回(savedUrl 有值,url 未设置)→ 用保存的 URL 重新处理身份
|
||||
// 2) H5 内 requireAuth 跳登录页返回 → url 已有值,但 token/身份可能刚更新 → 强制刷新注入新身份
|
||||
// 3) 退出登录后再次进入 web_view(url 已存在)→ 用缓存的 openid 重新注入
|
||||
|
||||
// 0) 授权页返回:读取 __AUTH_RESULT__,把授权结果写入当前 H5 URL 的 hash,让 H5 重载读取
|
||||
try {
|
||||
const authRes = uni.getStorageSync('__AUTH_RESULT__');
|
||||
if (authRes && authRes.openid && this.url) {
|
||||
uni.removeStorageSync('__AUTH_RESULT__');
|
||||
console.log('[auth-flow] 🎯 授权页返回,刷新身份 hash → openid=' + (authRes.openid || '').substring(0, 8) + '...');
|
||||
const base = this.url.split('#')[0];
|
||||
const joiner = base.indexOf('?') !== -1 ? '&' : '?';
|
||||
this.url = base + joiner + 't=' + Date.now() +
|
||||
'#openid=' + encodeURIComponent(authRes.openid) +
|
||||
'&phone=' + encodeURIComponent(authRes.phone || '') +
|
||||
'&nickname=' + encodeURIComponent(authRes.nickname || '') +
|
||||
'&avatar=' + encodeURIComponent(authRes.avatar || '');
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[auth-flow] 读取授权结果失败:', e);
|
||||
}
|
||||
|
||||
const { openid, unionid } = getCurrentUser();
|
||||
if (this.savedUrl && !this.url) {
|
||||
console.log('[auth-flow] 🔄 onShow: savedUrl 重新处理 → openid=' + (openid || '(空)'));
|
||||
@@ -386,6 +428,17 @@ export default {
|
||||
if (qIdx !== -1) console.log('[web_view] params:', targetUrl.slice(qIdx + 1));
|
||||
} catch (_) {}
|
||||
|
||||
// 强制缓存刷新:微信 webview 对相同 URL 会复用缓存。
|
||||
// 每次进入都追加唯一 _v 参数(不受身份分支影响),保证加载最新 H5。
|
||||
try {
|
||||
const base = targetUrl.split('#')[0];
|
||||
const joiner = base.indexOf('?') !== -1 ? '&' : '?';
|
||||
targetUrl = base + joiner + '_v=' + Date.now() + (targetUrl.indexOf('#') !== -1 ? '#' + targetUrl.split('#')[1] : '');
|
||||
console.log('[web_view] 已加缓存版本参数 _v →', targetUrl.substring(0, 120));
|
||||
} catch (e) {
|
||||
console.warn('[web_view] 加缓存版本参数失败:', e);
|
||||
}
|
||||
|
||||
// #ifdef MP
|
||||
uni.showShareMenu({ menus: ['shareAppMessage', 'shareTimeline'] });
|
||||
// #endif
|
||||
@@ -545,6 +598,11 @@ export default {
|
||||
})
|
||||
break
|
||||
|
||||
case 'requestProfile':
|
||||
// 任意 H5 应用请求授权 → 弹共享原生授权面板(手机号/昵称/头像)
|
||||
this.showAuth = true;
|
||||
break
|
||||
|
||||
case 'setTitle':
|
||||
if (data.title) {
|
||||
this.shareTitle = data.title;
|
||||
@@ -554,5 +612,76 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/* ---------- 共享授权面板(任意 H5 应用 requestProfile → 弹面板 → box_app /auth/profile) ---------- */
|
||||
onChooseAvatar(e) {
|
||||
const avatarUrl = e.detail.avatarUrl;
|
||||
if (!avatarUrl) return uni.showToast({ title: '未获取到头像', icon: 'none' });
|
||||
// 上传到 box_app 公开接口:授权链路不依赖 CRMEB 登录态(退出登录后 uploadImgs 会 401 弹「请登录」)
|
||||
uni.uploadFile({
|
||||
url: 'https://mp.yizhezhe.com/api/upload',
|
||||
filePath: avatarUrl,
|
||||
name: 'file',
|
||||
success: (res) => {
|
||||
try {
|
||||
const d = JSON.parse(res.data);
|
||||
if (d.code === 200 && d.result && d.result.url) this.authAvatar = d.result.url;
|
||||
else uni.showToast({ title: '头像上传失败', icon: 'none' });
|
||||
} catch (e) { uni.showToast({ title: '头像上传失败', icon: 'none' }); }
|
||||
},
|
||||
fail: () => uni.showToast({ title: '头像上传失败,请检查网络', icon: 'none' })
|
||||
});
|
||||
},
|
||||
onGetPhone(e) {
|
||||
if (e.detail.errMsg === 'getPhoneNumber:ok' && e.detail.code) { this._authCode = e.detail.code; }
|
||||
else { uni.showToast({ title: '未授权手机号', icon: 'none' }); }
|
||||
},
|
||||
submitAuth() {
|
||||
if (!this.authNickname && !this.authAvatar && !this._authCode) {
|
||||
return uni.showToast({ title: '请至少授权一项', icon: 'none' });
|
||||
}
|
||||
const openid = getOpenid();
|
||||
if (!openid) return uni.showToast({ title: '未获得 openid,请先登录', icon: 'none' });
|
||||
const api = 'https://mp.yizhezhe.com/api/mp/public/auth/profile?openid=' + encodeURIComponent(openid) +
|
||||
(this._authCode ? '&code=' + encodeURIComponent(this._authCode) : '') +
|
||||
(this.authNickname ? '&nickname=' + encodeURIComponent(this.authNickname) : '') +
|
||||
(this.authAvatar ? '&avatar=' + encodeURIComponent(this.authAvatar) : '');
|
||||
uni.request({ url: api, method: 'POST', timeout: 10000,
|
||||
success: (r) => {
|
||||
const d = r.data || {};
|
||||
if (d.code === 200) {
|
||||
const res = d.result || {};
|
||||
this.showAuth = false; this._authCode = '';
|
||||
// 更新 web-view src(保留 query + 追加 hash 结果)→ H5 重载读取
|
||||
const base = this.url.split('#')[0];
|
||||
this.url = base + (base.indexOf('?') >= 0 ? '&' : '?') + 't=' + Date.now() +
|
||||
'#openid=' + encodeURIComponent(openid) +
|
||||
'&phone=' + encodeURIComponent(res.phone || '') +
|
||||
'&nickname=' + encodeURIComponent(res.userName || this.authNickname || '') +
|
||||
'&avatar=' + encodeURIComponent(res.avatar || this.authAvatar || '');
|
||||
} else {
|
||||
uni.showToast({ title: d.message || '授权保存失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
fail: () => uni.showToast({ title: '授权请求失败,请检查网络', icon: 'none' })
|
||||
});
|
||||
},
|
||||
closeAuth() { this.showAuth = false; },
|
||||
noop() {},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mb-auth-mask { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center; }
|
||||
.mb-auth-panel { width: 82%; max-width: 340px; background: #fff; border-radius: 18px; padding: 24px 20px 18px; }
|
||||
.mb-auth-title { font-size: 17px; font-weight: 700; color: #2B2320; text-align: center; }
|
||||
.mb-auth-sub { font-size: 12px; color: #A79C95; text-align: center; margin: 8px 0 18px; line-height: 1.5; }
|
||||
.mb-auth-btn { width: 100%; height: 46px; line-height: 46px; text-align: center; border-radius: 12px; background: #F8F3EF; color: #2B2320; font-size: 14px; margin-top: 12px; }
|
||||
.mb-auth-btn.avatar { display: flex; align-items: center; justify-content: center; gap: 8px; }
|
||||
.mb-auth-ava { width: 40px; height: 40px; border-radius: 50%; }
|
||||
.mb-auth-input { width: 100%; height: 46px; border-radius: 12px; background: #F8F3EF; font-size: 14px; color: #2B2320; padding: 0 14px; margin-top: 12px; }
|
||||
.mb-auth-actions { display: flex; gap: 12px; margin-top: 20px; }
|
||||
.mb-auth-cancel, .mb-auth-ok { flex: 1; height: 44px; line-height: 44px; text-align: center; border-radius: 12px; font-size: 14px; font-weight: 600; }
|
||||
.mb-auth-cancel { background: #F1E6E0; color: #6B615B; }
|
||||
.mb-auth-ok { background: #F4593C; color: #fff; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user