@wu529778790/user-avatar
v0.1.32
Published
A zero-dependency avatar account widget: WeChat subscription login, user menu, settings panel with GitHub binding and nickname editing.
Maintainers
Readme
@wu529778790/user-avatar
右上角用户头像账号组件:未登录显示默认人形头像,点击弹出微信订阅号登录窗口;已登录显示真实头像,点击弹出下拉菜单(设置 / 退出登录),设置弹窗内含 GitHub 绑定、openid 展示、修改昵称、用户序号(本站第 N 位用户)。
与 wx-auth 微信订阅号认证体系深度集成:复用其 SDK(window.WxAuth)与后端接口(/api/auth/userinfo、/api/auth/profile、/api/oauth/github/authorize)。
特性
- 🧩 Web Component 封装,一行
<script>注入即可用 - 🎨 头像组件零样式依赖:CSS 变量驱动(
--ua-*),可整套换肤 - 🌗 默认深浅色自动适配(
light-dark()):宿主页面声明color-scheme: light / dark时跟随宿主配色,未声明时跟随系统,无需任何配置 - 🔐 与 wx-auth 微信登录无缝衔接:未登录点击 → 弹扫码/验证码;登录后自动识别人头
- 🐙 设置弹窗内绑定 / 解绑 GitHub(子窗口授权,
postMessage自动刷新) - ✏️ 修改昵称(复用后端 nickname 配置),openid 一键复制
- 🔢 展示用户序号(userinfo 的
userSeq):设置弹窗内显示「你是本站第 N 位用户」 - 📦 NPM + CDN 双通道
安装
pnpm add @wu529778790/user-avatar快速开始(推荐 · Web Component)
⚠️ 前置:本组件依赖 wx-auth-sdk(
window.WxAuth,建议>= 1.2.41)。请先引入 SDK 并WxAuth.init({ silent: true, required: false }),组件会自动探测并复用。 头像登录弹窗的「能否关闭」由组件自己按login-required决定,不受宿主全局required影响,详见下方「登录弹窗能不能关?」。
方式一:CDN 一行引入
<!-- 1. 先引入 wx-auth-sdk(微信认证,登录弹窗由它渲染) -->
<script src="https://unpkg.com/wx-auth-sdk/dist/wx-auth.umd.js"></script>
<script>
// silent:true = 加载时只静默校验登录态、绝不自动弹登录窗(头像组件是可选项登录,
// 弹窗只由点击头像时 SDK.requireAuth() 触发)
// required:false = 可选认证:弹窗带 × 关闭按钮,用户可主动关闭
WxAuth.init({ silent: true, required: false, onVerified: () => location.reload() })
</script>
<!-- 2. 再引入本组件 -->
<script src="https://unpkg.com/@wu529778790/user-avatar@latest/dist/user-avatar.wc.js"></script>
<!-- 3. 页面放一个标签即出现右上角头像 -->
<user-avatar></user-avatar>备选 CDN(GitHub 直连,push 即生效):
https://cdn.jsdmirror.com/gh/wu529778790/components@main/cdn/user-avatar.wc.js
方式二:声明式属性
<user-avatar
size="44px" <!-- 头像尺寸 -->
fixed <!-- 固定右上角 -->
offset="1rem 1.5rem" <!-- top right 偏移 -->
>
</user-avatar>方式三:NPM 双轨(React/Vue 项目)
import UserAvatar from '@wu529778790/user-avatar'
import '@wu529778790/user-avatar/style.css'
// 已登录用户状态由组件自动探测(读 wxauth-token cookie + userinfo 接口)
const avatar = new UserAvatar({ apiBase: '' })
avatar.mount(document.body)
// 手动控制
await avatar.login() // 弹微信登录(默认可关闭),返回是否成功
await avatar.refresh() // 重新拉取用户信息
avatar.unmount() // 卸载
// 需要「必须登录才能继续」的宿主流程:让本次弹窗强制不可关闭
const forced = new UserAvatar({ loginRequired: true })属性一览(Web Component)
| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| api-base | string | https://wx-auth.shenzjd.com | 后端 API 前缀(默认写死自家 wx-auth 后端,一般无需配置) |
| fixed | boolean | true | 是否固定右上角(fixed 存在即 true) |
| offset | string | '1rem 1.5rem' | 固定定位偏移(top right) |
| size | string | '2.5rem' | 头像直径 |
| z-index | number | 12000 | 弹窗层级 |
| portal | boolean | true | 设置弹窗 / 下拉菜单是否挂到顶层(body)。开启后弹窗始终全屏居中,避免被 backdrop-filter / transform / filter / contain / overflow 祖先困住;关闭则内联到组件根节点(旧行为) |
| portal-el | string | — | Portal 挂载容器。接受 CSS 选择器或元素 id(如 #app 或 .overlay-root),解析不到则回退到 body |
| login-required | boolean | false | 点击头像触发的登录弹窗是否强制不可关闭。默认 false = 带 × 可关闭(用户主动点登录允许反悔);只有「必须完成登录才能继续」的宿主场景才设为 true |
| theme-accent | string | #1f2328 | 主色(头像/按钮/toast,默认中性灰黑) |
| theme-size | string | 2.5rem | 头像尺寸(略同 size) |
| theme-radius | string | 16px | 卡片/弹窗圆角 |
| theme-bg | string | #fff | 卡片背景 |
| theme-text / theme-sub-text | string | — | 正文 / 次要文字色 |
| theme-overlay | string | — | 遮罩色 |
| theme-danger | string | — | 危险按钮色(退出/解绑) |
| theme-success | string | — | 成功色(已绑定) |
也可直接覆盖 CSS 变量:--ua-btn-bg --ua-size --ua-accent --ua-btn-border --ua-radius --ua-bg --ua-text --ua-sub --ua-overlay --ua-danger --ua-success。
程序化传参:el.props(优先级最高)
回调、SDK 实例等复杂对象无法走标签属性,可用 JS 属性 props 传入完整配置。优先级:props > 标签属性 > window.__USER_AVATAR_OPTIONS__:
<user-avatar id="ua" fixed></user-avatar>
<script>
document.getElementById('ua').props = {
apiBase: 'https://api.example.com',
onLogin: (user) => console.log('登录成功', user)
}
</script>宿主组件嵌入场景(如 site-navbar)即在脚本加载前/后设置 props,元素升级后自动生效。
JS API(NPM 用法)
import { UserAvatar, UserAvatarOptions } from '@wu529778790/user-avatar'
const avatar = new UserAvatar({
// apiBase 不传即默认 https://wx-auth.shenzjd.com(自家后端,一般无需配置)
sdk: window.WxAuth, // 可显式传 SDK,缺省自动取 window.WxAuth
fixed: true, offset: '1rem 1.5rem',
portal: true, // 弹窗/菜单挂 body(默认 true)。若容器在 transform/overflow 祖先内,请保持 true
// portalEl: document.querySelector('#overlay-root'), // 可选:自定义 Portal 容器,缺省 document.body
theme: { accent: '#1f2328' },
onLogin: (user) => console.log('登录', user),
onLogout: () => console.log('登出'),
onGithubBound: (user) => console.log('绑定 GitHub', user),
})
avatar.mount(document.body)
// 主动登录:等待用户完成微信扫码/验证码
const ok = await avatar.login()
// 强制刷新用户(登录/解绑后)
await avatar.refresh()
avatar.unmount()交互流程
未登录 已登录
┌──────────┐ 点击头像 ┌──────────────────┐
│ 默认人形 │ ─────────► │ 微信扫码登录窗(SDK)│
└──────────┘ └──────────────────┘
验证成功 ──► 头像变真实头像 + 下拉菜单
│
├─ 设置 ──► 设置弹窗(GitHub 绑定/解绑、改昵称、openid、用户序号)
└─ 退出登录(清 cookie)登录弹窗能不能关?(重要)
用户主动点头像属于可反悔操作,弹窗默认可关闭(右上角 ×)。组件调用 SDK 时会显式传本次语义:
sdk.requireAuth({ required: this.opts.loginRequired }) // 默认 false → 可关闭为什么必须显式传:required 在 wx-auth-sdk 里是调用级入参,缺省才回落到 WxAuth.init() 的全局配置。
而宿主页面常常会为「搜索 / 获取 / 上传」这类后端校验流程把全局配置 init 成 required: true(强制不可关),
同一个页面里的头像弹窗就会被一起带成强制——用户点了头像却关不掉,只能刷新页面。
本组件自己传 required: false 后与宿主全局配置解耦,各是各的语义。
反向需求:如果宿主希望「点头像必须完成登录才能继续」,设 loginRequired: true(或属性 login-required)。
依赖
wx-auth-sdk >= 1.2.41;更老的 SDK 会忽略该入参(不报错),此时弹窗形态取决于宿主 init 的required。
数据接口依赖(后端应为 wx-auth 同款)
| 接口 | 说明 |
| --- | --- |
| GET /api/auth/userinfo?token= | 拉取当前用户(openid / nickname / github 等) |
| POST /api/auth/profile | {action:'set-nickname', nickname} / {action:'unbind-github'} |
| GET /api/oauth/github/authorize?token= | 发起 GitHub OAuth 绑定(新窗口),子窗 postMessage({type:'github-bound'}) |
若无这些接口,组件依然能渲染头像与登录,但设置面板的能力(绑定/改名)不可用。
License
MIT
