box_app: add wx-h5-demo standalone project (two mini-program auth scenarios); mount /wx-h5-demo; update auth doc; drop old examples/wx-h5-auth
This commit is contained in:
40
README.md
Normal file
40
README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# wx-h5-demo · 独立示例 H5(小程序授权 / 跳转)
|
||||||
|
|
||||||
|
> 独立二级目录项目,由 box_app 挂载到 `/wx-h5-demo`(即 `https://mp.yizhezhe.com/wx-h5-demo/`)。
|
||||||
|
> 配套说明:`docs/h5-miniprogram-auth.md`。
|
||||||
|
|
||||||
|
## 两种场景
|
||||||
|
| 场景 | 流程 | 用到的小程序页 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| **场景1** | 微信(浏览器)打开 H5 链接 → 跳**小程序授权页**授权 → 授权后小程序用 web-view 加载本 H5(结果在 URL)→ “回到 H5” | `miniapp/scenario1-auth-bridge.*`(授权桥页) |
|
||||||
|
| **场景2** | 微信跳到**小程序 web-view 的 H5 应用** → H5 `postMessage` 请求授权 → 宿主弹原生授权面板 → 授权 → 更新 `web-view src`(带结果)→ H5 重载显示 | `miniapp/scenario2-host-page.*`(web-view 宿主页) |
|
||||||
|
|
||||||
|
> 说明:场景2 的宿主页 `scenario2-host-page` 同时是场景1 授权后 redirectTo 的落地页(从 `globalData` 读结果拼 H5 url)。
|
||||||
|
|
||||||
|
## 文件
|
||||||
|
```
|
||||||
|
wx-h5-demo/
|
||||||
|
├─ index.html # 示例 H5(自包含):环境检测(webview/微信浏览器/纯浏览器)、
|
||||||
|
│ # 场景1 跳小程序授权 或 场景2 postMessage 授权、读回传参数展示。
|
||||||
|
├─ miniapp/
|
||||||
|
│ ├─ scenario1-auth-bridge.wxml/.js # 场景1 小程序授权桥页(launch-weapp/URL Scheme 进入)
|
||||||
|
│ └─ scenario2-host-page.wxml/.js # 场景2 web-view 宿主页(也作场景1 落地页)
|
||||||
|
└─ README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 怎么做
|
||||||
|
1. **H5**:改 `index.html`(H5 地址 = `https://mp.yizhezhe.com/wx-h5-demo/`)。
|
||||||
|
2. **小程序端**:把 `miniapp/*` 的两个页面代码并入你的小程序(如 CRMEB),改 3 处:
|
||||||
|
- `app.globalData.openid`(登录态)。
|
||||||
|
- `H5_BASE` 指向你的 H5。
|
||||||
|
- `https://YOUR_API/phone|avatar`(或注释里说明;手机号 `code`→后端换明文;头像需上传换正式地址)。
|
||||||
|
3. **入口**:
|
||||||
|
- 场景2:宿主页已用 `<web-view src="{{url}}">` 加载 H5,H5 点「在 web-view 里请求授权」即可。
|
||||||
|
- 场景1:H5 点「去小程序授权」→ 需给 `jumpToMiniAuth()` 配一个**小程序 URL Scheme**(后端用 appid+path 换)或把页面放进公众号/env 用 `<wx-open-launch-weapp path="/pages/demo/auth">`。
|
||||||
|
|
||||||
|
## 注意
|
||||||
|
- 手机号:前端只拿 `code`,**明文必须后端** `wx.business.getuserphonenumber` 换(旧 `code2Session`+解密已收紧)。
|
||||||
|
- 头像:`e.detail.avatarUrl` 是临时 URL,需 `wx.uploadFile` 上传存后端,回传正式地址。
|
||||||
|
- `getUserProfile` 已废弃(匿名);用 `getPhoneNumber` / `<input type="nickname">` / `chooseAvatar`。
|
||||||
|
- 身份:保留 `openid`(query);授权结果走 **hash**(`#phone/nickname/avatar`,微信 webview 丢 query 不丢 hash)。
|
||||||
|
- 纯浏览器打开 `index.html`:仅 UI 演示(有降级提示),无法真授权。
|
||||||
121
index.html
Normal file
121
index.html
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||||
|
<meta name="theme-color" content="#F4593C">
|
||||||
|
<title>wx-h5-demo · 小程序授权演示(独立项目)</title>
|
||||||
|
<style>
|
||||||
|
* { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
|
||||||
|
body { font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif; background:#F8F3EF; color:#2B2320; min-height:100vh; display:flex; justify-content:center; }
|
||||||
|
.wrap { width:100%; max-width:430px; padding:24px 20px 40px; }
|
||||||
|
.brand { font-size:22px; font-weight:800; color:#F4593C; } .brand small{color:#A79C95;font-size:13px;font-weight:500;margin-left:8px}
|
||||||
|
.env { margin:14px 0 8px; font-size:13px; color:#6B615B; } .env b{color:#2B2320}
|
||||||
|
.tag { display:inline-block; padding:2px 8px; border-radius:8px; font-size:12px; }
|
||||||
|
.tag.s0{background:#E8F2EB;color:#5F8A4A} .tag.s1{background:#FDEEDD;color:#B8860B} .tag.s2{background:#F6DCD6;color:#C4553A}
|
||||||
|
.card { background:#fff; border:1px solid #EFE7E1; border-radius:16px; padding:16px; margin-top:14px; }
|
||||||
|
.card h2{font-size:15px;font-weight:800;margin-bottom:10px}
|
||||||
|
.row{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px dashed #EFE7E1;font-size:14px}
|
||||||
|
.row:last-child{border-bottom:none} .row .k{color:#6B615B} .row .v{font-weight:600} .row .v.placeholder{color:#C9B7AC;font-weight:500}
|
||||||
|
.avatar{width:44px;height:44px;border-radius:50%;background:#F1E6E0;overflow:hidden;display:flex;align-items:center;justify-content:center;font-size:18px}
|
||||||
|
.avatar img{width:100%;height:100%;object-fit:cover}
|
||||||
|
.btn{display:block;width:100%;padding:15px;border:none;border-radius:14px;font-size:15px;font-weight:700;margin-top:14px;cursor:pointer}
|
||||||
|
.btn.main{background:#F4593C;color:#fff} .btn.ghost{background:#fff;color:#6B615B;border:1px solid #EFE7E1}
|
||||||
|
.hint{font-size:12px;color:#A79C95;margin-top:12px;line-height:1.6}
|
||||||
|
#toast{position:fixed;left:50%;bottom:14%;transform:translateX(-50%);background:rgba(30,22,18,.9);color:#fff;padding:10px 18px;border-radius:10px;font-size:13px;opacity:0;pointer-events:none;transition:opacity .25s;z-index:99}
|
||||||
|
#toast.show{opacity:1}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrap">
|
||||||
|
<div class="brand">wx-h5-demo <small>独立示例 · 小程序授权</small></div>
|
||||||
|
<div class="env">场景:<b id="envTxt">检测中…</b> <span id="envTag" class="tag s2">纯浏览器</span></div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2>当前可用的授权方式</h2>
|
||||||
|
<p id="scenarioTxt" style="font-size:13px;color:#6B615B;line-height:1.6">检测环境后,这里会给出「场景1 或 场景2」对应的授权入口。</p>
|
||||||
|
<button class="btn main" id="btnJump">去小程序授权</button>
|
||||||
|
<button class="btn ghost" id="btnPost">在 web-view 里请求授权(postMessage)</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2>授权结果(小程序回传后读取)</h2>
|
||||||
|
<div class="row"><span class="k">手机号</span><span class="v placeholder" id="rPhone">—</span></div>
|
||||||
|
<div class="row"><span class="k">昵称</span><span class="v placeholder" id="rNick">—</span></div>
|
||||||
|
<div class="row"><span class="k">头像</span><span class="v"><span class="avatar" id="rAvatarWrap"><span id="rAvatarText">宝</span></span></span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="hint">
|
||||||
|
场景1(微信浏览器打开 H5):点「去小程序授权」→ 经 <code>wx-open-launch-weapp</code> / 小程序 <code>URL Scheme</code> 跳进小程序授权页 → 授权后,小程序用 <code>web-view</code> 加载本 H5(结果在 URL),即「回到 H5」。
|
||||||
|
场景2(web-view 里的 H5):点「在 web-view 里请求授权」→ <code>postMessage</code> → 宿主小程序弹原生授权面板 → 更新 <code>web-view src</code>(带 #phone/nickname/avatar)→ 本页重载显示。
|
||||||
|
完整说明见 <code>docs/h5-miniprogram-auth.md</code>;小程序端配套代码见本目录 <code>miniapp/</code>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div id="toast"></div>
|
||||||
|
|
||||||
|
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
function $(s) { return document.querySelector(s); }
|
||||||
|
function toast(msg) { var t=$('#toast'); t.textContent=msg; t.classList.add('show'); clearTimeout(t._t); t._t=setTimeout(function(){t.classList.remove('show');},1800); }
|
||||||
|
function readParam(name){ try{ var h=location.hash.slice(1)+'&'+location.search.slice(1); var m=h.match(new RegExp('(?:^|[&#])'+name+'=([^&#]*)(?:$|[&#])')); return m?decodeURIComponent(m[1]):''; }catch(e){return '';} }
|
||||||
|
|
||||||
|
var MODE = ''; // 'webview' | 'wechat-browser' | 'browser'
|
||||||
|
var isWechat = /MicroMessenger/i.test(navigator.userAgent);
|
||||||
|
var inWebview = false;
|
||||||
|
|
||||||
|
function setEnv(mode, label, cls) {
|
||||||
|
MODE = mode; inWebview = (mode === 'webview');
|
||||||
|
$('#envTxt').textContent = label; $('#envTag').textContent = label; $('#envTag').className = 'tag ' + cls;
|
||||||
|
var txt = '';
|
||||||
|
if (mode === 'webview') txt = '场景2:本页运行在小程序 web-view 里。点下方「在 web-view 里请求授权」→ postMessage 通知宿主小程序弹原生授权面板;授权后宿主更新 web-view src 回传,本页重载显示结果。';
|
||||||
|
else if (mode === 'wechat-browser') txt = '场景1:本页在微信浏览器打开(非 web-view)。点「去小程序授权」→ 跳进小程序授权页授权;授权后小程序用 web-view 加载本 H5(结果在 URL)即回到 H5。';
|
||||||
|
else txt = '纯浏览器:仅演示 UI,无法真授权(去小程序按钮/场景2需在微信内)。';
|
||||||
|
$('#scenarioTxt').textContent = txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectEnv() {
|
||||||
|
if (window.wx && window.wx.miniProgram) {
|
||||||
|
var responded = false;
|
||||||
|
window.wx.miniProgram.getEnv(function (r) { responded = true; setEnv(r && r.miniprogram ? 'webview' : (isWechat ? 'wechat-browser' : 'browser'), r && r.miniprogram ? '小程序 web-view' : (isWechat ? '微信浏览器' : '纯浏览器'), r && r.miniprogram ? 's0' : (isWechat ? 's1' : 's2')); });
|
||||||
|
setTimeout(function () { if (!responded) setEnv(isWechat ? 'wechat-browser' : 'browser', isWechat ? '微信浏览器' : '纯浏览器', isWechat ? 's1' : 's2'); }, 800);
|
||||||
|
} else {
|
||||||
|
setEnv(isWechat ? 'wechat-browser' : 'browser', isWechat ? '微信浏览器' : '纯浏览器', isWechat ? 's1' : 's2');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 场景1:跳小程序授权(wx-open-launch-weapp 或 URL Scheme) → 小程序授权页
|
||||||
|
function jumpToMiniAuth() {
|
||||||
|
if (MODE === 'browser') { toast('请在微信内打开'); return; }
|
||||||
|
// 方式A:公众号/网页 JSSDK `<wx-open-launch-weapp>`(需 jsapi 签名 + 微信内打开)
|
||||||
|
// 方式B:小程序 URL Scheme(后端用 appid+path 换 scheme,形如 weixin://dl/business/?t=xxx)
|
||||||
|
var scheme = $('#launchPath') && $('#launchPath').value; // 你可在下面填 scheme 或 path
|
||||||
|
if (scheme) { location.href = scheme; return; }
|
||||||
|
toast('请在此填入小程序授权页的 scheme/launch 入口(见 README)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 场景2:postMessage 请求 web-view 宿主弹授权面板
|
||||||
|
function requestAuthInWebview() {
|
||||||
|
if (MODE !== 'webview') { toast('仅 web-view 环境可用(场景2)'); return; }
|
||||||
|
window.wx.miniProgram.postMessage({ data: { action: 'requestProfile' } });
|
||||||
|
toast('请在弹出的小程序面板授权');
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderResult() {
|
||||||
|
var phone = readParam('phone'), nick = readParam('nickname'), avatar = readParam('avatar'), authed = readParam('authed');
|
||||||
|
if (phone) { $('#rPhone').textContent = phone; $('#rPhone').classList.remove('placeholder'); }
|
||||||
|
if (nick) { $('#rNick').textContent = nick; $('#rNick').classList.remove('placeholder'); }
|
||||||
|
if (avatar){ $('#rAvatarWrap').innerHTML = '<img src="' + avatar + '" alt="头像">'; }
|
||||||
|
if (authed) toast('授权完成,已回传');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
detectEnv(); renderResult();
|
||||||
|
$('#btnJump').addEventListener('click', jumpToMiniAuth);
|
||||||
|
$('#btnPost').addEventListener('click', requestAuthInWebview);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
33
miniapp/scenario1-auth-bridge.js
Normal file
33
miniapp/scenario1-auth-bridge.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// 场景1:授权桥页(H5 在微信浏览器 → 跳进本页 → 授权 → 回到 H5)
|
||||||
|
// 路径:/pages/demo/auth.js
|
||||||
|
// 入口:<wx-open-launch-weapp path="/pages/demo/auth"> 或 小程序 URL Scheme
|
||||||
|
// ⚠️ openid 由登录态/onLoad 取;授权结果放 globalData,webview 页再拼进 H5 url。
|
||||||
|
const app = getApp();
|
||||||
|
const H5_BASE = 'https://mp.yizhezhe.com/wx-h5-demo/'; // 示例 H5(独立二级目录项目)
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: { nickname: '', avatar: '' },
|
||||||
|
_phone: '', _nick: '', _avatar: '', _openid: '',
|
||||||
|
|
||||||
|
onLoad(q) { this._openid = q.openid || app.globalData.openid || 'YOUR_OPENID'; },
|
||||||
|
|
||||||
|
onPhone(e) {
|
||||||
|
if (e.detail.errMsg === 'getPhoneNumber:ok' && e.detail.code) {
|
||||||
|
wx.request({ url: 'https://YOUR_API/phone', method: 'POST', data: { code: e.detail.code },
|
||||||
|
success: r => { this._phone = r.data.phoneNumber; wx.showToast({ title: '已获取手机号', icon: 'none' }); } });
|
||||||
|
} else { wx.showToast({ title: '未授权手机号', icon: 'none' }); }
|
||||||
|
},
|
||||||
|
onNick(e) { this._nick = e.detail.value; this.setData({ nickname: this._nick }); },
|
||||||
|
onAvatar(e) {
|
||||||
|
const p = e.detail.avatarUrl;
|
||||||
|
wx.uploadFile({ url: 'https://YOUR_API/avatar', filePath: p, name: 'file',
|
||||||
|
success: (res) => { const r = JSON.parse(res.data || '{}'); this._avatar = r.url || p; this.setData({ avatar: this._avatar }); } });
|
||||||
|
},
|
||||||
|
|
||||||
|
// 授权完成 → 写 globalData → 去 webview 页加载 H5(结果在 URL)→ 即“回到 H5”
|
||||||
|
finishAuth() {
|
||||||
|
app.globalData.wxH5Result = { openid: this._openid, phone: this._phone, nickname: this._nick, avatar: this._avatar };
|
||||||
|
wx.redirectTo({ url: '/pages/demo/webview' });
|
||||||
|
},
|
||||||
|
cancel() { wx.navigateBack({}); },
|
||||||
|
});
|
||||||
16
miniapp/scenario1-auth-bridge.wxml
Normal file
16
miniapp/scenario1-auth-bridge.wxml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!-- 场景1:授权桥页(H5 在微信浏览器 → 跳进本页 → 授权 → 回到 H5)
|
||||||
|
START:经 <wx-open-launch-weapp path="/pages/demo/auth"> 或 小程序 URL Scheme(path=/pages/demo/auth) 进入 -->
|
||||||
|
<!-- wxml -->
|
||||||
|
<view class="auth-wrap">
|
||||||
|
<view class="auth-title">授权获取资料</view>
|
||||||
|
<view class="auth-sub">授权后自动回到「wx-h5-demo」H5</view>
|
||||||
|
|
||||||
|
<button class="auth-btn" open-type="getPhoneNumber" bindgetphonenumber="onPhone">获取手机号</button>
|
||||||
|
<input class="auth-input" type="nickname" bindblur="onNick" bindchange="onNick" placeholder="输入昵称" />
|
||||||
|
<button class="auth-btn avatar" open-type="chooseAvatar" bindchooseavatar="onAvatar">
|
||||||
|
<image wx:if="{{avatar}}" class="auth-avatar" src="{{avatar}}" mode="aspectFill" /><text wx:else>选择头像</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="auth-done" bindtap="finishAuth">完成</button>
|
||||||
|
<view class="auth-cancel" bindtap="cancel">取消</view>
|
||||||
|
</view>
|
||||||
51
miniapp/scenario2-host-page.js
Normal file
51
miniapp/scenario2-host-page.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// 场景2(也是场景1落地页):web-view 承载 H5 + postMessage 授权 + 回传
|
||||||
|
// 路径:/pages/demo/webview.js
|
||||||
|
// H5 地址(独立二级目录项目)
|
||||||
|
const H5_BASE = 'https://mp.yizhezhe.com/wx-h5-demo/';
|
||||||
|
const app = getApp();
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: { url: '', showAuth: false, nickname: '', avatar: '' },
|
||||||
|
_phone: '', _nick: '', _avatar: '', _openid: '',
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this._openid = app.globalData.openid || 'YOUR_OPENID';
|
||||||
|
// 场景1:auth-bridge 授权后 redirectTo 本页,结果在 globalData
|
||||||
|
const r = app.globalData.wxH5Result;
|
||||||
|
if (r) { this._phone = r.phone || ''; this._nick = r.nickname || ''; this._avatar = r.avatar || ''; }
|
||||||
|
this.applyUrl();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 拼 H5 url:openid 走 query;授权结果走 hash(webview 丢 query、不丢 hash)
|
||||||
|
applyUrl() {
|
||||||
|
const u = H5_BASE + '?openid=' + encodeURIComponent(this._openid) +
|
||||||
|
'#phone=' + encodeURIComponent(this._phone || '') +
|
||||||
|
'&nickname=' + encodeURIComponent(this._nick || '') +
|
||||||
|
'&avatar=' + encodeURIComponent(this._avatar || '');
|
||||||
|
this.setData({ url: u });
|
||||||
|
},
|
||||||
|
|
||||||
|
// 场景2:H5 通过 postMessage 请求授权
|
||||||
|
onMessage(e) {
|
||||||
|
const data = (e.detail && e.detail.data) || [];
|
||||||
|
(Array.isArray(data) ? data : [data]).forEach((m) => {
|
||||||
|
if (m && m.action === 'requestProfile') this.setData({ showAuth: true });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onPhone(e) {
|
||||||
|
if (e.detail.errMsg === 'getPhoneNumber:ok' && e.detail.code) {
|
||||||
|
wx.request({ url: 'https://YOUR_API/phone', method: 'POST', data: { code: e.detail.code },
|
||||||
|
success: r => { this._phone = r.data.phoneNumber; this.finishAuth(); } });
|
||||||
|
} else { wx.showToast({ title: '未授权手机号', icon: 'none' }); }
|
||||||
|
},
|
||||||
|
onNick(e) { this._nick = e.detail.value; this.setData({ nickname: this._nick }); },
|
||||||
|
onAvatar(e) {
|
||||||
|
const p = e.detail.avatarUrl;
|
||||||
|
wx.uploadFile({ url: 'https://YOUR_API/avatar', filePath: p, name: 'file',
|
||||||
|
success: (res) => { const r = JSON.parse(res.data || '{}'); this._avatar = r.url || p; this.setData({ avatar: this._avatar }); } });
|
||||||
|
},
|
||||||
|
finishAuth() { this.setData({ showAuth: false }); this.applyUrl(); }, // 更新 web-view src → H5 重载显示结果
|
||||||
|
closeAuth() { this.setData({ showAuth: false }); },
|
||||||
|
noop() {},
|
||||||
|
});
|
||||||
19
miniapp/scenario2-host-page.wxml
Normal file
19
miniapp/scenario2-host-page.wxml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- 场景2(也是场景1授权后的落地页):web-view 承载 H5 + postMessage 授权 + 回传
|
||||||
|
用法:本页 <web-view src="{{url}}"> 加载 wx-h5-demo/index.html。
|
||||||
|
- 场景2:H5 请求授权 → bindmessage 收到 → 弹原生面板 → 授权 → 更新 web-view src(带结果)。
|
||||||
|
- 场景1:auth-bridge 授权后 redirectTo 本页,本页 onLoad 从 globalData 读结果拼进 H5 url。 -->
|
||||||
|
<!-- wxml -->
|
||||||
|
<web-view wx:if="{{url}}" src="{{url}}" bindmessage="onMessage"></web-view>
|
||||||
|
|
||||||
|
<view wx:if="{{showAuth}}" class="auth-mask" bindtap="closeAuth">
|
||||||
|
<view class="auth-panel" catchtap="noop">
|
||||||
|
<view class="auth-title">授权获取资料</view>
|
||||||
|
<view class="auth-sub">用于在 wx-h5-demo 中展示昵称/头像/手机号</view>
|
||||||
|
<button class="auth-btn" open-type="getPhoneNumber" bindgetphonenumber="onPhone">获取手机号</button>
|
||||||
|
<input class="auth-input" type="nickname" bindblur="onNick" bindchange="onNick" placeholder="输入昵称" />
|
||||||
|
<button class="auth-btn avatar" open-type="chooseAvatar" bindchooseavatar="onAvatar">
|
||||||
|
<image wx:if="{{avatar}}" class="auth-avatar" src="{{avatar}}" mode="aspectFill" /><text wx:else>选择头像</text>
|
||||||
|
</button>
|
||||||
|
<view class="auth-cancel" bindtap="closeAuth">取消</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
Reference in New Issue
Block a user