feat(user): 在用户页面新增角色展示功能
- 新增 state 用于存储用户角色列表 - 登录后调用 listUserRole 接口获取用户角色数据 - 在用户昵称下方展示用户角色,样式为蓝色圆角徽章 - 支持多角色展示,采用 flex-wrap 实现多行换行 - 下拉刷新时同步刷新用户角色信息 - 处理登录、退出及接口异常等边界情况,确保展示稳定
This commit is contained in:
8
.workbuddy/memory/2026-07-03.md
Normal file
8
.workbuddy/memory/2026-07-03.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 2026-07-03
|
||||||
|
|
||||||
|
## 用户页面新增角色展示
|
||||||
|
- 在 `src/pages/user/user.tsx` 用户信息卡片中新增当前登录用户的系统角色展示
|
||||||
|
- 通过 `listUserRole` API (`GET /system/user-role?userId=xxx`) 获取用户角色列表
|
||||||
|
- 角色以蓝色圆角徽章形式展示在昵称下方,与会员等级徽章并排
|
||||||
|
- 支持多角色展示(flex-wrap),支持下拉刷新同步更新
|
||||||
|
- 登录/退出/API失败等边界情况均已处理
|
||||||
@@ -6,6 +6,8 @@ import { useScrollHeight } from '@/hooks/useScrollHeight'
|
|||||||
import { useRequest } from '@/hooks/useRequest'
|
import { useRequest } from '@/hooks/useRequest'
|
||||||
import { getUserCardStats, getUserOrderStats, type UserCardStats, type UserOrderStats } from '@/api/shop/shopUserCard'
|
import { getUserCardStats, getUserOrderStats, type UserCardStats, type UserOrderStats } from '@/api/shop/shopUserCard'
|
||||||
import { getMyClerk } from '@/api/shop/shopStoreUser'
|
import { getMyClerk } from '@/api/shop/shopStoreUser'
|
||||||
|
import { listUserRole } from '@/api/system/userRole'
|
||||||
|
import type { UserRole } from '@/api/system/userRole/model'
|
||||||
import MemberBadge from '@/components/business/MemberBadge'
|
import MemberBadge from '@/components/business/MemberBadge'
|
||||||
|
|
||||||
const UserPage: React.FC = () => {
|
const UserPage: React.FC = () => {
|
||||||
@@ -15,6 +17,8 @@ const UserPage: React.FC = () => {
|
|||||||
|
|
||||||
// 查询门店关联信息
|
// 查询门店关联信息
|
||||||
const [storeInfo, setStoreInfo] = useState<any>(null)
|
const [storeInfo, setStoreInfo] = useState<any>(null)
|
||||||
|
// 用户角色列表
|
||||||
|
const [userRoles, setUserRoles] = useState<UserRole[]>([])
|
||||||
|
|
||||||
// 获取用户卡片统计(余额/积分/优惠券/礼品卡)
|
// 获取用户卡片统计(余额/积分/优惠券/礼品卡)
|
||||||
// 使用 cacheKey 缓存 30s,页面返回时先显示缓存数据再静默刷新
|
// 使用 cacheKey 缓存 30s,页面返回时先显示缓存数据再静默刷新
|
||||||
@@ -38,8 +42,11 @@ const UserPage: React.FC = () => {
|
|||||||
runOrderStats()
|
runOrderStats()
|
||||||
// 查询门店关联
|
// 查询门店关联
|
||||||
getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null))
|
getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null))
|
||||||
|
// 查询用户角色
|
||||||
|
listUserRole({ userId: user?.userId }).then(data => setUserRoles(data || [])).catch(() => setUserRoles([]))
|
||||||
} else {
|
} else {
|
||||||
setStoreInfo(null)
|
setStoreInfo(null)
|
||||||
|
setUserRoles([])
|
||||||
}
|
}
|
||||||
}, [isLoggedIn])
|
}, [isLoggedIn])
|
||||||
|
|
||||||
@@ -53,6 +60,11 @@ const UserPage: React.FC = () => {
|
|||||||
runOrderStats()
|
runOrderStats()
|
||||||
// 刷新门店关联
|
// 刷新门店关联
|
||||||
getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null))
|
getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null))
|
||||||
|
// 刷新用户角色
|
||||||
|
const userId = Taro.getStorageSync('UserId')
|
||||||
|
if (userId) {
|
||||||
|
listUserRole({ userId }).then(data => setUserRoles(data || [])).catch(() => {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -88,12 +100,17 @@ const UserPage: React.FC = () => {
|
|||||||
// 下拉刷新状态
|
// 下拉刷新状态
|
||||||
const [refreshing, setRefreshing] = useState(false)
|
const [refreshing, setRefreshing] = useState(false)
|
||||||
|
|
||||||
// 下拉刷新:同时刷新用户信息、卡片统计、订单统计
|
// 下拉刷新:同时刷新用户信息、卡片统计、订单统计、角色
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
if (!isLoggedIn) { setRefreshing(false); return }
|
if (!isLoggedIn) { setRefreshing(false); return }
|
||||||
setRefreshing(true)
|
setRefreshing(true)
|
||||||
try {
|
try {
|
||||||
await Promise.all([refreshUser(), runCardStats(), runOrderStats()])
|
await Promise.all([refreshUser(), runCardStats(), runOrderStats()])
|
||||||
|
// 刷新角色
|
||||||
|
const uid = user?.userId
|
||||||
|
if (uid) {
|
||||||
|
listUserRole({ userId: uid }).then(data => setUserRoles(data || [])).catch(() => {})
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setRefreshing(false)
|
setRefreshing(false)
|
||||||
}
|
}
|
||||||
@@ -116,8 +133,17 @@ const UserPage: React.FC = () => {
|
|||||||
<Text className='text-lg font-medium text-gray-800 block'>
|
<Text className='text-lg font-medium text-gray-800 block'>
|
||||||
{isLoggedIn ? (user?.nickname || user?.phone || '用户') : '点击登录'}
|
{isLoggedIn ? (user?.nickname || user?.phone || '用户') : '点击登录'}
|
||||||
</Text>
|
</Text>
|
||||||
<View className='flex items-center gap-2 mt-1'>
|
<View className='flex items-center gap-2 mt-1 flex-wrap'>
|
||||||
{isLoggedIn && <MemberBadge levelName={(user as any)?.memberLevelName} />}
|
{isLoggedIn && <MemberBadge levelName={(user as any)?.memberLevelName} />}
|
||||||
|
{userRoles.map(role => (
|
||||||
|
<View
|
||||||
|
key={role.roleId}
|
||||||
|
className='inline-flex items-center rounded-full text-xs px-2 py-0.5'
|
||||||
|
style={{ background: '#eff6ff', color: '#1d4ed8', border: '1px solid #bfdbfe' }}
|
||||||
|
>
|
||||||
|
<Text>{role.roleName}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{isLoggedIn && <Text className='text-gray-300 text-sm'>{'>'}</Text>}
|
{isLoggedIn && <Text className='text-gray-300 text-sm'>{'>'}</Text>}
|
||||||
|
|||||||
Reference in New Issue
Block a user