- 新增 .editorconfig、.eslintrc、.gitignore 配置文件 - 添加管理员文章管理页面配置和功能实现 - 添加经销商申请注册页面配置和功能实现 - 添加经销商银行卡管理页面配置和功能实现 - 添加经销商客户管理页面配置和功能实现 - 添加用户地址管理页面配置和功能实现 - 添加用户聊天消息页面配置和功能实现 - 添加用户礼品管理页面配置和功能实现
320 lines
8.9 KiB
TypeScript
320 lines
8.9 KiB
TypeScript
import React, {useState, useEffect, useCallback} from 'react'
|
||
import {View, Text} from '@tarojs/components'
|
||
import {
|
||
Space,
|
||
Tabs,
|
||
Tag,
|
||
Empty,
|
||
Loading,
|
||
PullToRefresh,
|
||
Button,
|
||
Dialog,
|
||
Image,
|
||
ImagePreview,
|
||
TextArea
|
||
} from '@nutui/nutui-react-taro'
|
||
import Taro from '@tarojs/taro'
|
||
import {useDealerUser} from '@/hooks/useDealerUser'
|
||
import {pageUserVerify, updateUserVerify} from '@/api/system/userVerify'
|
||
import type {ShopDealerWithdraw} from '@/api/shop/shopDealerWithdraw/model'
|
||
import {UserVerify} from "@/api/system/userVerify/model";
|
||
|
||
const UserVeirfyAdmin: React.FC = () => {
|
||
const [activeTab, setActiveTab] = useState<string | number>(0)
|
||
const [loading, setLoading] = useState<boolean>(false)
|
||
const [refreshing, setRefreshing] = useState<boolean>(false)
|
||
const [list, setList] = useState<UserVerify[]>([])
|
||
const [rejectDialogVisible, setRejectDialogVisible] = useState<boolean>(false)
|
||
const [rejectReason, setRejectReason] = useState<string>('')
|
||
const [currentRecord, setCurrentRecord] = useState<ShopDealerWithdraw | null>(null)
|
||
const [showPreview, setShowPreview] = useState(false)
|
||
const [showPreview2, setShowPreview2] = useState(false)
|
||
|
||
const {dealerUser} = useDealerUser()
|
||
|
||
// Tab 切换处理函数
|
||
const handleTabChange = (value: string | number) => {
|
||
console.log('Tab切换到:', value)
|
||
setActiveTab(value)
|
||
// activeTab变化会自动触发useEffect重新获取数据,无需手动调用
|
||
}
|
||
|
||
// 获取审核记录
|
||
const fetchWithdrawRecords = useCallback(async () => {
|
||
if (!dealerUser?.userId) return
|
||
|
||
try {
|
||
setLoading(true)
|
||
const currentStatus = Number(activeTab)
|
||
const result = await pageUserVerify({
|
||
page: 1,
|
||
limit: 100,
|
||
status: currentStatus // 后端筛选,提高性能
|
||
})
|
||
|
||
if (result?.list) {
|
||
const processedRecords = result.list.map(record => ({
|
||
...record
|
||
}))
|
||
setList(processedRecords)
|
||
}
|
||
} catch (error) {
|
||
console.error('获取审核记录失败:', error)
|
||
Taro.showToast({
|
||
title: '获取审核记录失败',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}, [dealerUser?.userId, activeTab])
|
||
|
||
|
||
// 刷新数据
|
||
const handleRefresh = async () => {
|
||
setRefreshing(true)
|
||
await Promise.all([fetchWithdrawRecords()])
|
||
setRefreshing(false)
|
||
}
|
||
|
||
// 审核通过
|
||
const handleApprove = async (record: ShopDealerWithdraw) => {
|
||
try {
|
||
await updateUserVerify({
|
||
...record,
|
||
status: 1, // 审核通过
|
||
})
|
||
|
||
Taro.showToast({
|
||
title: '审核通过',
|
||
icon: 'success'
|
||
})
|
||
|
||
await fetchWithdrawRecords()
|
||
} catch (error: any) {
|
||
if (error !== 'cancel') {
|
||
console.error('审核通过失败:', error)
|
||
Taro.showToast({
|
||
title: error.message || '操作失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
// 驳回申请
|
||
const handleReject = (record: ShopDealerWithdraw) => {
|
||
setCurrentRecord(record)
|
||
setRejectReason('')
|
||
setRejectDialogVisible(true)
|
||
}
|
||
|
||
// 确认驳回
|
||
const confirmReject = async () => {
|
||
if (!rejectReason.trim()) {
|
||
Taro.showToast({
|
||
title: '请输入驳回原因',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
try {
|
||
await updateUserVerify({
|
||
...currentRecord!,
|
||
status: 2, // 驳回
|
||
comments: rejectReason.trim()
|
||
})
|
||
|
||
Taro.showToast({
|
||
title: '已驳回',
|
||
icon: 'success'
|
||
})
|
||
|
||
setRejectDialogVisible(false)
|
||
setCurrentRecord(null)
|
||
setRejectReason('')
|
||
await fetchWithdrawRecords()
|
||
} catch (error: any) {
|
||
console.error('驳回失败:', error)
|
||
Taro.showToast({
|
||
title: error.message || '操作失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
|
||
|
||
// 初始化加载数据
|
||
useEffect(() => {
|
||
if (dealerUser?.userId) {
|
||
fetchWithdrawRecords().then()
|
||
}
|
||
}, [fetchWithdrawRecords])
|
||
|
||
const getStatusText = (status?: number) => {
|
||
switch (status) {
|
||
case 0:
|
||
return '待审核'
|
||
case 1:
|
||
return '审核通过'
|
||
case 2:
|
||
return '已驳回'
|
||
default:
|
||
return '未知'
|
||
}
|
||
}
|
||
|
||
const getStatusColor = (status?: number) => {
|
||
switch (status) {
|
||
case 0:
|
||
return 'warning'
|
||
case 1:
|
||
return 'success'
|
||
case 2:
|
||
return 'danger'
|
||
default:
|
||
return 'default'
|
||
}
|
||
}
|
||
|
||
const renderWithdrawRecords = () => {
|
||
console.log('渲染审核记录:', {loading, recordsCount: list.length, dealerUserId: dealerUser?.userId})
|
||
|
||
return (
|
||
<PullToRefresh
|
||
disabled={refreshing}
|
||
onRefresh={handleRefresh}
|
||
>
|
||
<View>
|
||
{loading ? (
|
||
<View className="text-center py-8">
|
||
<Loading/>
|
||
<Text className="text-gray-500 mt-2">加载中...</Text>
|
||
</View>
|
||
) : list.length > 0 ? (
|
||
list.map(record => (
|
||
<View key={record.id} className="rounded-lg bg-gray-50 p-4 mb-3 shadow-sm">
|
||
<View className="flex justify-between items-start mb-3">
|
||
<Space direction={'vertical'}>
|
||
<Text className="font-semibold text-gray-800">
|
||
{record.realName}
|
||
</Text>
|
||
<Text className="font-normal text-sm text-gray-500">
|
||
{record.phone}
|
||
</Text>
|
||
<Text className="font-normal text-sm text-gray-500">
|
||
身份证号码:{record.idCard}
|
||
</Text>
|
||
</Space>
|
||
<Tag type={getStatusColor(record.status)}>
|
||
{getStatusText(record.status)}
|
||
</Tag>
|
||
</View>
|
||
|
||
<View className="flex gap-2 mb-2">
|
||
<Image src={record.sfz1} height={100} onClick={() => setShowPreview(true)}/>
|
||
<Image src={record.sfz2} height={100} onClick={() => setShowPreview2(true)}/>
|
||
</View>
|
||
<ImagePreview
|
||
autoPlay
|
||
images={[{src: `${record.sfz1}`}]}
|
||
visible={showPreview}
|
||
onClose={() => setShowPreview(false)}
|
||
/>
|
||
<ImagePreview
|
||
autoPlay
|
||
images={[{src: `${record.sfz1}`}]}
|
||
visible={showPreview2}
|
||
onClose={() => setShowPreview2(false)}
|
||
/>
|
||
|
||
<View className="text-xs text-gray-400">
|
||
<Text>申请时间:{record.createTime}</Text>
|
||
{record.status == 1 && (
|
||
<Text className="block mt-1">
|
||
审核时间:{record.updateTime}
|
||
</Text>
|
||
)}
|
||
{record.status == 2 && (
|
||
<Text className="block mt-1 text-red-500">
|
||
驳回原因:{record.comments}
|
||
</Text>
|
||
)}
|
||
</View>
|
||
|
||
{/* 操作按钮 */}
|
||
{record.status === 0 && (
|
||
<View className="flex gap-2 mt-3">
|
||
<Button
|
||
type="success"
|
||
size="small"
|
||
className="flex-1"
|
||
onClick={() => handleApprove(record)}
|
||
>
|
||
审核通过
|
||
</Button>
|
||
<Button
|
||
type="danger"
|
||
size="small"
|
||
className="flex-1"
|
||
onClick={() => handleReject(record)}
|
||
>
|
||
驳回
|
||
</Button>
|
||
</View>
|
||
)}
|
||
|
||
</View>
|
||
))
|
||
) : (
|
||
<Empty description="暂无申请记录"/>
|
||
)}
|
||
</View>
|
||
</PullToRefresh>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<View className="bg-gray-50 min-h-screen">
|
||
<Tabs value={activeTab} onChange={handleTabChange}>
|
||
<Tabs.TabPane title="待审核" value="0">
|
||
{renderWithdrawRecords()}
|
||
</Tabs.TabPane>
|
||
|
||
<Tabs.TabPane title="已通过" value="1">
|
||
{renderWithdrawRecords()}
|
||
</Tabs.TabPane>
|
||
|
||
<Tabs.TabPane title="已驳回" value="2">
|
||
{renderWithdrawRecords()}
|
||
</Tabs.TabPane>
|
||
</Tabs>
|
||
|
||
{/* 驳回原因对话框 */}
|
||
<Dialog
|
||
visible={rejectDialogVisible}
|
||
title="驳回原因"
|
||
onCancel={() => {
|
||
setRejectDialogVisible(false)
|
||
setCurrentRecord(null)
|
||
setRejectReason('')
|
||
}}
|
||
onConfirm={confirmReject}
|
||
>
|
||
<View className="p-4">
|
||
<TextArea
|
||
placeholder="请输入驳回原因"
|
||
value={rejectReason}
|
||
onChange={(value) => setRejectReason(value)}
|
||
maxLength={200}
|
||
rows={4}
|
||
/>
|
||
</View>
|
||
</Dialog>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
export default UserVeirfyAdmin
|