import React, { useState, useEffect, useCallback, useRef } from 'react' import { View, Text, Image, ScrollView, Input } from '@tarojs/components' import Taro, { useDidShow } from '@tarojs/taro' import { pageUsers, updateUserStatus } from '@/api/system/user' import type { User } from '@/api/system/user/model' import { getCompressedImageUrl } from '@/utils/image' definePageConfig({ navigationBarTitleText: '用户管理', }) // ─── Tab 配置 ────────────────────────────────────────────────── type TabKey = 'all' | 'normal' | 'disabled' const TABS: { key: TabKey; label: string; status?: number }[] = [ { key: 'all', label: '全部' }, { key: 'normal', label: '正常', status: 0 }, { key: 'disabled', label: '已禁用', status: 1 }, ] // ─── 页面组件 ────────────────────────────────────────────────────── export default function StoreUsersPage() { const [activeTab, setActiveTab] = useState('all') // 用户列表与分页 const [userList, setUserList] = useState([]) const [page, setPage] = useState(1) const [hasMore, setHasMore] = useState(true) const [loading, setLoading] = useState(false) // 搜索 const [keyword, setKeyword] = useState('') const [searchText, setSearchText] = useState('') // 用户详情弹窗 const [showDetail, setShowDetail] = useState(false) const [detailUser, setDetailUser] = useState(null) const pageSize = 20 const loadingRef = useRef(false) /** 加载用户列表 */ const loadUsers = useCallback(async (tab: TabKey, pageNo: number = 1, append = false, kw?: string) => { if (loadingRef.current) return loadingRef.current = true setLoading(true) try { const tabConfig = TABS.find(t => t.key === tab) const params: any = { page: pageNo, limit: pageSize, } if (tabConfig?.status !== undefined) { params.status = tabConfig.status } const effectiveKw = kw !== undefined ? kw : keyword if (effectiveKw) params.keywords = effectiveKw const res = await pageUsers(params) const list = res?.list || [] setUserList(prev => append ? [...prev, ...list] : list) setPage(pageNo) setHasMore(list.length >= pageSize) } catch (e: any) { Taro.showToast({ title: e.message || '加载失败', icon: 'none' }) if (!append) setUserList([]) } finally { loadingRef.current = false setLoading(false) } }, [keyword]) // 切换 tab 时重新加载 useEffect(() => { loadUsers(activeTab, 1) }, [activeTab, loadUsers]) // 页面重新显示时刷新 useDidShow(() => { loadUsers(activeTab, 1) }) /** 加载更多 */ const handleLoadMore = () => { if (hasMore && !loadingRef.current) { loadUsers(activeTab, page + 1, true) } } /** 执行搜索 */ const handleSearch = () => { setKeyword(searchText) loadUsers(activeTab, 1, false, searchText) } /** 清除搜索 */ const handleClearSearch = () => { setSearchText('') setKeyword('') loadUsers(activeTab, 1, false, '') } /** 切换用户状态(禁用/启用) */ const handleToggleStatus = (user: User) => { const currentStatus = user.status ?? 0 const newStatus = currentStatus === 0 ? 1 : 0 const actionText = newStatus === 1 ? '禁用' : '启用' Taro.showModal({ title: '确认操作', content: `确定要${actionText}用户「${user.nickname || user.realName || user.phone || user.userId}」吗?${newStatus === 1 ? '禁用后该用户将无法登录。' : ''}`, confirmColor: newStatus === 1 ? '#ee0a24' : '#0e932e', success: async (res) => { if (!res.confirm) return try { Taro.showLoading({ title: `${actionText}中...` }) await updateUserStatus(user.userId, newStatus) Taro.hideLoading() Taro.showToast({ title: `${actionText}成功`, icon: 'success' }) // 更新列表和详情中的用户状态 setUserList(prev => prev.map(u => u.userId === user.userId ? { ...u, status: newStatus } : u )) if (detailUser?.userId === user.userId) { setDetailUser(prev => prev ? { ...prev, status: newStatus } : null) } } catch (e: any) { Taro.hideLoading() Taro.showToast({ title: e.message || `${actionText}失败`, icon: 'none' }) } }, }) } /** 打开用户详情 */ const openDetail = (user: User) => { setDetailUser(user) setShowDetail(true) } /** 格式化时间 */ const formatTime = (time?: string) => { if (!time) return '-' // 兼容各种时间格式 return time.replace('T', ' ').substring(0, 19) } /** 渲染单个用户卡片 */ const renderUserCard = (user: User) => { const isDisabled = user.status === 1 const displayName = user.nickname || user.realName || '未设置昵称' return ( openDetail(user)} > {/* 用户头部 */} {/* 头像 */} {user.avatar ? ( ) : ( 👤 )} {/* 信息 */} {displayName} {isDisabled ? '已禁用' : '正常'} {user.phone || user.mobile || '未绑定手机'} {/* 禁用/启用按钮 */} { e.stopPropagation() handleToggleStatus(user) }} > {isDisabled ? '启用' : '禁用'} {/* 附加信息 */} {user.memberLevelName && ( 会员: {user.memberLevelName} )} 注册: {formatTime(user.createTime)} {user.balance !== undefined && Number(user.balance) > 0 && ( 余额: ¥{user.balance} )} ) } return ( {/* 搜索栏 */} setSearchText(e.detail.value)} onConfirm={handleSearch} confirmType='search' /> {searchText ? ( × ) : null} 搜索 {/* Tab 栏 */} {TABS.map(tab => ( setActiveTab(tab.key)} > {tab.label} ))} {/* 用户列表 */} {loading && userList.length === 0 ? ( 加载中... ) : userList.length === 0 ? ( 暂无用户 ) : ( userList.map(renderUserCard) )} {loading && userList.length > 0 && ( 加载中... )} {!hasMore && userList.length > 0 && ( 没有更多了 )} {/* 用户详情弹窗 */} {showDetail && detailUser && ( {/* 遮罩 */} setShowDetail(false)} /> {/* 弹窗内容 */} {/* 标题 */} 用户详情 setShowDetail(false)}>× {/* 用户基本信息 */} {detailUser.avatar ? ( ) : ( 👤 )} {detailUser.nickname || detailUser.realName || '未设置昵称'} {detailUser.status === 1 ? '已禁用' : '正常'} ID: {detailUser.userId || detailUser.id} {/* 详细信息列表 */} {/* 手机号 */} 手机号 {detailUser.phone || detailUser.mobile || '-'} {/* 真实姓名 */} {detailUser.realName && ( 真实姓名 {detailUser.realName} )} {/* 性别 */} 性别 {detailUser.gender === 1 ? '男' : detailUser.gender === 2 ? '女' : '未知'} {/* 会员等级 */} {detailUser.memberLevelName && ( 会员等级 {detailUser.memberLevelName} )} {/* 余额 */} {detailUser.balance !== undefined && ( 余额 ¥{detailUser.balance || '0.00'} )} {/* 积分 */} {detailUser.points !== undefined && ( 积分 {detailUser.points || 0} )} {/* 邮箱 */} {detailUser.email && ( 邮箱 {detailUser.email} )} {/* 注册时间 */} 注册时间 {formatTime(detailUser.createTime)} {/* 操作按钮 */} setShowDetail(false)} > 关闭 handleToggleStatus(detailUser)} > {detailUser.status === 1 ? '启用用户' : '禁用用户'} )} ) }