Files
urbanLifeline/urbanLifelineWeb/packages/workcase_wechat/最终登录方案.md
2026-01-09 12:17:21 +08:00

334 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 微信小程序最终登录方案
## 方案说明
采用**自动静默登录**方案,用户打开小程序即自动完成登录,无需任何授权操作。
## 实现方式
### 1. 进入首页自动登录
- 用户打开小程序,进入首页
- 检查本地缓存,如果有登录信息,直接使用
- 如果没有缓存,自动调用 `wx.login` 获取 code
- 使用 code 调用后端 identify 接口完成登录
- 全程无需用户操作
### 2. 登录流程
```
用户打开小程序
进入首页 (pages/index/index)
检查缓存 (token, userInfo, wechatId)
有缓存 → 直接使用
无缓存 → 自动登录
wx.login 获取 code
调用 identify 接口
保存登录信息
完成登录
```
### 3. Token 过期处理
```
API 请求返回 401
清除缓存
提示"登录已过期,正在重新登录"
刷新页面
触发自动登录
```
### 4. 退出登录
```
点击"退出"按钮
确认对话框
清除登录信息
调用 autoLogin() 重新登录
```
## 代码实现
### 首页 (pages/index/index.uvue)
```typescript
// 初始化用户信息
async function initUserInfo() {
try {
// 1. 先尝试从缓存获取
const cachedWechatId = uni.getStorageSync('wechatId')
const cachedUserInfo = uni.getStorageSync('userInfo')
const cachedToken = uni.getStorageSync('token')
if (cachedWechatId && cachedUserInfo && cachedToken) {
// 有完整缓存,直接使用
const parsedUserInfo = typeof cachedUserInfo === 'string'
? JSON.parse(cachedUserInfo)
: cachedUserInfo
userInfo.value = {
wechatId: cachedWechatId,
username: parsedUserInfo.username || parsedUserInfo.realName || '微信用户',
phone: parsedUserInfo.phone || '',
userId: parsedUserInfo.userId || ''
}
// 判断用户类型
userType.value = parsedUserInfo.status !== 'guest'
console.log('使用缓存的用户信息:', userInfo.value)
return
}
// 2. 没有缓存,自动登录
await autoLogin()
} catch (error) {
console.error('初始化用户信息失败:', error)
await autoLogin()
}
}
// 自动登录
async function autoLogin() {
uni.showLoading({ title: '登录中...' })
try {
uni.login({
provider: 'weixin',
success: async (loginRes) => {
console.log('微信登录成功code:', loginRes.code)
const code = loginRes.code
const wechatId = code.substring(0, 20) // 使用部分code作为临时ID
// 调用 identify 接口
const identifyRes = await guestAPI.identify({
wechatId: wechatId,
phone: ''
})
uni.hideLoading()
if (identifyRes.success && identifyRes.data) {
const loginDomain = identifyRes.data
// 保存登录信息
uni.setStorageSync('token', loginDomain.token || '')
uni.setStorageSync('userInfo', JSON.stringify(loginDomain.user))
uni.setStorageSync('loginDomain', JSON.stringify(loginDomain))
uni.setStorageSync('wechatId', wechatId)
// 更新用户信息
userInfo.value = {
wechatId: wechatId,
username: loginDomain.user?.username || loginDomain.user?.realName || '微信用户',
phone: loginDomain.user?.phone || '',
userId: loginDomain.user?.userId || ''
}
// 判断用户类型
userType.value = loginDomain.user?.status !== 'guest'
console.log('自动登录成功:', userInfo.value)
} else {
uni.showToast({
title: identifyRes.message || '登录失败',
icon: 'none'
})
}
},
fail: (err) => {
console.error('微信登录失败:', err)
uni.hideLoading()
uni.showToast({ title: '登录失败,请重试', icon: 'none' })
}
})
} catch (error: any) {
console.error('自动登录失败:', error)
uni.hideLoading()
uni.showToast({
title: error.message || '登录失败',
icon: 'none'
})
}
}
```
## 优势
### 1. 用户体验极佳
- ✅ 无需任何授权操作
- ✅ 打开即用
- ✅ 无感知登录
- ✅ 无弹窗干扰
### 2. 无权限要求
- ✅ 不需要企业认证
- ✅ 不需要开通手机号快速验证
- ✅ 个人小程序也可使用
- ✅ 测试环境友好
### 3. 代码简洁
- ✅ 删除了授权页面
- ✅ 删除了切换用户功能
- ✅ 删除了所有 mock 相关代码
- ✅ 只保留核心登录逻辑
### 4. 维护方便
- ✅ 登录逻辑集中在首页
- ✅ Token 过期自动处理
- ✅ 错误处理完善
- ✅ 日志清晰
## 后端要求
### identify 接口
```typescript
POST /urban-lifeline/system/guest/identify
{
"wechatId": "微信ID使用code的前20位作为临时标识",
"phone": "" // 可以为空
}
返回:
{
"success": true,
"data": {
"token": "jwt_token",
"user": {
"userId": "用户ID",
"username": "用户名",
"realName": "真实姓名",
"phone": "手机号(可能为空)",
"status": "guest" | "employee"
}
}
}
```
### 建议优化
1. **后端可以通过 code 换取 openid**
- 前端传递完整的 code
- 后端调用微信 API 换取 openid
- 使用 openid 作为用户唯一标识
2. **支持游客模式**
- 如果 wechatId 不存在,创建游客账号
- 返回游客身份的 token
- 允许后续绑定手机号升级为正式用户
## 已删除的内容
### 1. 授权页面
-`pages/auth/auth.uvue` - 已删除
- ❌ pages.json 中的 auth 路由配置 - 已删除
### 2. 切换用户功能
-`switchMockUser()` 函数 - 已删除
-`isMockMode` 变量 - 已删除
- ❌ 切换按钮 UI - 已删除
- ❌ 所有条件编译代码 - 已删除
### 3. getUserProfile
- ❌ 不再使用 `getUserProfile` API
- ❌ 不再需要用户授权昵称
### 4. getPhoneNumber
- ❌ 不再使用 `getPhoneNumber` API
- ❌ 不再需要手机号授权
## 保留的功能
### 1. 退出登录
- ✅ 右上角"退出"按钮
- ✅ 点击后清除缓存并重新自动登录
- ✅ 红色主题,易于识别
### 2. Token 管理
- ✅ 自动检测 401 错误
- ✅ 自动清除过期信息
- ✅ 自动重新登录
### 3. 用户类型识别
- ✅ 区分 guest 和 employee
- ✅ 根据类型控制功能权限
## 测试清单
### 首次使用
- [ ] 打开小程序,自动登录成功
- [ ] 无任何授权弹窗
- [ ] 用户信息正确显示
- [ ] 可以正常使用所有功能
### 再次使用
- [ ] 关闭小程序重新打开
- [ ] 直接进入首页,无需重新登录
- [ ] 用户信息保持不变
### Token 过期
- [ ] 模拟 Token 过期(后端返回 401
- [ ] 自动提示"登录已过期,正在重新登录"
- [ ] 自动完成重新登录
- [ ] 功能恢复正常
### 退出登录
- [ ] 点击"退出"按钮
- [ ] 显示确认对话框
- [ ] 确认后自动重新登录
- [ ] 登录成功后可正常使用
### API 请求
- [ ] 所有 API 请求携带正确的 token
- [ ] 请求路径正确(/urban-lifeline/
- [ ] WebSocket 连接正常
- [ ] 文件上传功能正常
## 部署说明
### 1. 编译
```bash
npm run build:mp-weixin
```
### 2. 上传
- 使用微信开发者工具打开 `unpackage/dist/build/mp-weixin`
- 点击"上传"按钮
- 填写版本号和备注
### 3. 提交审核
- 登录微信公众平台
- 进入"版本管理"
- 提交审核
### 4. 发布
- 审核通过后,点击"发布"
- 用户即可使用
## 总结
当前方案是最简洁、最友好的登录方案:
- ✅ 无需任何用户操作
- ✅ 无需小程序认证
- ✅ 代码简洁易维护
- ✅ 用户体验极佳
- ✅ 适用于所有场景
可以直接部署使用!