hookehuyr

feat(权限系统): 添加联系卖家权限并优化注册流程

添加 CONTACT_SELLER 权限类型及相关配置
优化注册页面逻辑,完善后智能返回上一页
统一 API 响应状态码检查方式
更新权限系统修复说明文档
# 权限系统问题修复说明
## 问题描述
用户从商品详情页点击"联系卖家"按钮时,如果没有权限会跳转到注册页面。但是存在以下问题:
1. 注册完成后没有正确返回上一页
2. 手动返回上一页后权限状态没有刷新
3. 点击联系卖家依然进入注册页面
## 修复内容
### 1. 注册页面逻辑优化
**文件**: `/src/pages/register/index.vue`
- 添加了用户状态管理的导入和初始化
- 修改了注册成功后的处理逻辑:
- 更新用户状态到 store 中
- 设置认证状态为 true
- 智能判断页面跳转逻辑(返回上一页或跳转首页)
### 2. 权限类型补充
**文件**: `/src/utils/permission.js`
- 添加了 `CONTACT_SELLER` 权限类型
- 配置了对应的权限检查规则
## 修复后的流程
1. 用户在商品详情页点击"联系卖家"
2. 系统检查用户权限(主要是手机号是否完善)
3. 如果没有权限,显示提示并跳转到注册页面
4. 用户完善信息并保存
5. **新增**: 系统自动更新用户状态到 store
6. **新增**: 智能返回上一页(商品详情页)
7. 用户再次点击"联系卖家"时,权限验证通过,正常显示联系弹窗
## 测试步骤
### 测试场景1:从商品详情页触发权限检查
1. 确保用户信息不完整(特别是手机号为空)
2. 进入任意商品详情页
3. 点击"联系卖家"按钮
4. 验证是否显示权限提示并跳转到注册页面
5. 完善用户信息并保存
6. 验证是否自动返回商品详情页
7. 再次点击"联系卖家"按钮
8. 验证是否正常显示联系卖家弹窗
### 测试场景2:从商品详情页触发买车权限检查
1. 确保用户信息不完整
2. 进入任意商品详情页
3. 点击"我想购买"按钮
4. 验证权限检查和页面跳转流程
5. 完善信息后验证功能是否正常
### 测试场景3:直接访问注册页面
1. 直接访问注册页面(不是从其他页面跳转)
2. 完善信息并保存
3. 验证是否跳转到首页(而不是返回上一页)
## 技术细节
### 用户状态更新
```javascript
// 更新用户状态
userStore.updateUserInfo({
...formData,
avatar: formData.avatar_url
})
userStore.isAuthenticated = true
```
### 智能页面跳转
```javascript
// 获取页面栈信息
const pages = Taro.getCurrentPages()
// 如果页面栈中有多于1个页面,说明是从其他页面跳转过来的
if (pages.length > 1) {
// 返回上一页,权限状态已更新,用户可以正常使用功能
Taro.navigateBack()
} else {
// 如果是直接访问注册页面,跳转到首页
Taro.switchTab({
url: '/pages/index/index'
})
}
```
## 注意事项
1. 修复后用户状态会实时更新,无需刷新页面
2. 权限检查基于用户的手机号字段
3. 支持多种权限类型的扩展
4. 保持了良好的用户体验,避免了重复的权限验证流程
## 相关文件
- `/src/pages/register/index.vue` - 注册页面
- `/src/pages/productDetail/index.vue` - 商品详情页
- `/src/utils/permission.js` - 权限管理工具
- `/src/stores/user.js` - 用户状态管理
\ No newline at end of file
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-09 10:44:50
* @LastEditTime: 2025-07-09 11:36:52
* @FilePath: /jgdl/src/pages/auth/index.vue
* @Description: 文件描述
-->
......@@ -36,7 +36,7 @@ export default {
})
request.post('/srv/?a=openid', {
code: res.code,
openid: 'h-002'
openid: 'h-008'
// openid: 'o5NFZ5cFQtLRy3aVHaZMLkjHFusI'
// openid: 'o5NFZ5TpgG4FwYursGCLjcUJH2ak'
// openid: 'o5NFZ5cqroPYwawCp8FEOxewtgnw'
......@@ -66,7 +66,7 @@ export default {
})
} else { // 其他页面分享跳首页
Taro.reLaunch({
url: `/pages/index/index?first_in=${wx.getStorageSync("first_in")}`
url: `/pages/index/index`
})
}
Taro.hideLoading();
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-04 14:53:07
* @LastEditTime: 2025-07-09 11:34:24
* @FilePath: /jgdl/src/pages/myAuthCar/index.vue
* @Description: 我的认证车页面
-->
......@@ -208,7 +208,7 @@ const initData = async () => {
loading.value = true
try {
const response = await apiService.getAuthCarsList(1, pageSize.value)
if (response.code === 200) {
if (response.code) {
authCars.value = response.data.list
hasMore.value = response.data.hasMore
currentPage.value = 1
......@@ -234,7 +234,7 @@ const loadMore = async () => {
const nextPage = currentPage.value + 1
const response = await apiService.getAuthCarsList(nextPage, pageSize.value)
if (response.code === 200) {
if (response.code) {
authCars.value.push(...response.data.list)
hasMore.value = response.data.hasMore
currentPage.value = nextPage
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-08 14:47:52
* @LastEditTime: 2025-07-09 11:35:02
* @FilePath: /jgdl/src/pages/myFavorites/index.vue
* @Description: 我的关注页面
-->
......@@ -132,7 +132,7 @@ const apiService = {
// 模拟API响应数据
return {
code: 200,
code: 1,
data: {
list: generateMockData(page, pageSize),
total: 50, // 模拟总数
......@@ -156,7 +156,7 @@ const apiService = {
// 模拟API响应
return {
code: 200,
code: 1,
data: null,
message: '取消关注成功'
}
......@@ -254,7 +254,7 @@ const initData = async () => {
loading.value = true
try {
const response = await apiService.getFavoritesList(1, pageSize.value)
if (response.code === 200) {
if (response.code) {
favorites.value = response.data.list
hasMore.value = response.data.hasMore
currentPage.value = 1
......@@ -280,7 +280,7 @@ const loadMore = async () => {
const nextPage = currentPage.value + 1
const response = await apiService.getFavoritesList(nextPage, pageSize.value)
if (response.code === 200) {
if (response.code) {
favorites.value.push(...response.data.list)
hasMore.value = response.data.hasMore
currentPage.value = nextPage
......@@ -325,7 +325,7 @@ const confirmUnfollow = async () => {
try {
const response = await apiService.unfollowCar(selectedId.value)
if (response.code === 200) {
if (response.code) {
// 从列表中移除该项
favorites.value = favorites.value.filter(item => item.id !== selectedId.value)
showToast('取消关注成功', 'success')
......
......@@ -154,6 +154,10 @@ import { Right } from '@nutui/icons-vue-taro'
import './index.less'
import BASE_URL from '@/utils/config';
import { updateProfileAPI, sendSmsCodeAPI } from '@/api/index';
import { useUserStore } from '@/stores/user';
// 用户状态管理
const userStore = useUserStore()
// 主题配置
const themeVars = {
......@@ -419,7 +423,7 @@ const validateForm = () => {
return false
}
if (!formData.gender) {
if (formData.gender === '') {
showToast('请选择性别', 'error')
return false
}
......@@ -451,7 +455,7 @@ const handleRegister = async () => {
const result = await updateProfileAPI(formData)
if (result.code !== 0) {
if (!result.code) {
Taro.showToast({
title: result.msg || '注册失败',
icon: 'error'
......@@ -459,19 +463,36 @@ const handleRegister = async () => {
return
}
Taro.showToast({
title: '注册成功',
icon: 'success'
// 更新用户状态
userStore.updateUserInfo({
...formData,
avatar: formData.avatar_url
})
userStore.isAuthenticated = true
setTimeout(() => {
// 注册成功后跳转到登录页面或首页
Taro.showToast({
title: '保存成功',
icon: 'success',
complete: () => {
// 获取页面栈信息
const pages = Taro.getCurrentPages()
// 如果页面栈中有多于1个页面,说明是从其他页面跳转过来的
if (pages.length > 1) {
// 返回上一页,权限状态已更新,用户可以正常使用功能
Taro.navigateBack()
}, 1500)
} else {
// 如果是直接访问注册页面,跳转到首页
Taro.reLaunch({
url: '/pages/index/index'
})
}
}
})
} catch (error) {
Taro.showToast({
title: '注册失败,请重试',
title: '保存失败,请重试',
icon: 'error'
})
} finally {
......
/*
* @Date: 2025-01-08 18:00:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-09 10:34:50
* @LastEditTime: 2025-07-09 11:22:03
* @FilePath: /jgdl/src/stores/user.js
* @Description: 用户状态管理
*/
......
/*
* @Date: 2025-01-08 18:00:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-09 10:49:50
* @LastEditTime: 2025-07-09 11:16:49
* @FilePath: /jgdl/src/utils/permission.js
* @Description: 权限控制工具函数
*/
......@@ -18,6 +18,8 @@ export const PERMISSION_TYPES = {
SELL_CAR: 'sell_car',
// 买车权限:需要完善基本信息
BUY_CAR: 'buy_car',
// 联系卖家权限:需要完善基本信息
CONTACT_SELLER: 'contact_seller',
// 个人中心权限:需要完善基本信息
PROFILE: 'profile',
// 订单管理权限:需要完善基本信息
......@@ -45,6 +47,11 @@ const PERMISSION_CONFIG = {
redirectUrl: '/pages/register/index',
checkFields: ['phone']
},
[PERMISSION_TYPES.CONTACT_SELLER]: {
message: '联系卖家需要先完善个人信息',
redirectUrl: '/pages/register/index',
checkFields: ['phone']
},
[PERMISSION_TYPES.PROFILE]: {
message: '访问个人中心需要先完善个人信息',
redirectUrl: '/pages/register/index',
......