Files
template-10560/src/dealer/orders/index.tsx
赵忠林 77d9687cef feat(dealer): 优化经销商相关功能与代码细节
- 移除客户添加表单中公司名称输入框的maxLength限制
- 更新联系方式1标签为联系方式
- 在提现管理中引入Image组件并替换原生img标签
- 实现上传打款凭证的新逻辑,支持选择和上传图片
- 配置开发环境API基础URL为本地地址
- 修改订单查询条件,管理员可查看所有用户订单
- 注释掉不再使用的getResourceId方法
- 启用request.ts中的本地开发环境baseUrl配置
2025-12-02 08:51:26 +08:00

454 lines
14 KiB
TypeScript
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.

import React, {useState, useEffect, useCallback} from 'react'
import {View, Text, ScrollView} from '@tarojs/components'
import {Empty, PullToRefresh, Space, Loading, DatePicker, Button, Picker} from '@nutui/nutui-react-taro'
import {ArrowDown} from '@nutui/icons-react-taro'
import Taro from '@tarojs/taro'
import {pageShopDealerOrder} from '@/api/shop/shopDealerOrder'
import {useDealerUser} from '@/hooks/useDealerUser'
import type {ShopDealerOrder} from '@/api/shop/shopDealerOrder/model'
import {useUser} from "@/hooks/useUser";
import {pageShopDealerReferee} from "@/api/shop/shopDealerReferee";
interface OrderWithDetails extends ShopDealerOrder {
orderNo?: string
customerName?: string
userCommission?: string
}
interface PickerOption {
text: string | number
value: string | number
disabled?: boolean
children?: PickerOption[]
className?: string | number
}
const DealerOrder: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false)
const d = new Date()
const currMonth = `${d.getFullYear()}${d.getMonth() + 1}`;
const currDate = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
const [date, setDate] = useState(currMonth)
const [show1, setShow1] = useState(false)
const [refreshing, setRefreshing] = useState<boolean>(false)
const [loadingMore, setLoadingMore] = useState<boolean>(false)
const [orders, setOrders] = useState<OrderWithDetails[]>([])
const [currentPage, setCurrentPage] = useState<number>(1)
const [hasMore, setHasMore] = useState<boolean>(true)
const [users, setUsers] = useState<any[]>([])
const [users2, setUsers2] = useState<any[]>([])
const [visible1, setVisible1] = useState(false)
const [text1, setText1] = useState('')
const [selectedUserId, setSelectedUserId] = useState<number | undefined>(undefined)
const [visible2, setVisible2] = useState(false)
const [text2, setText2] = useState('')
const [selectedFirstUserId, setSelectedFirstUserId] = useState<number | undefined>(undefined)
const [visible3, setVisible3] = useState(false)
// const [text3, setText3] = useState('')
const [selectedSecondUserId, setSelectedSecondUserId] = useState<number | undefined>(undefined)
const {dealerUser} = useDealerUser()
const {user} = useUser()
// 获取订单数据
const fetchOrders = useCallback(async (page: number = 1, isRefresh: boolean = false) => {
if (!dealerUser?.userId) return
try {
if (isRefresh) {
setRefreshing(true)
} else if (page === 1) {
setLoading(true)
} else {
setLoadingMore(true)
}
let where = {
userId: selectedUserId,
firstUserId: selectedSecondUserId,
secondUserId: selectedSecondUserId,
isInvalid: 0,
isSettled: 1,
resourceId: user?.userId,
month: date,
page,
limit: 10
};
if (hasRole('superAdmin') || hasRole('admin')) {
console.log('>>>>>>>>>>>>是管理员')
where = {...where, resourceId: undefined}
}
if(selectedUserId){
where = {...where,userId: selectedUserId}
}
if(selectedFirstUserId){
where = {...where,secondUserId: selectedFirstUserId}
}
const result = await pageShopDealerOrder(where)
if (result?.list) {
const newOrders = result.list.map(order => ({
...order,
orderNo: `${order.orderNo}`,
customerName: `用户${order.userId}`,
userCommission: order.firstMoney || '0.00'
}))
if (page === 1) {
setOrders(newOrders)
} else {
setOrders(prev => [...prev, ...newOrders])
}
setHasMore(newOrders.length === 10)
setCurrentPage(page)
}
} catch (error) {
console.error('获取分销订单失败:', error)
Taro.showToast({
title: '获取订单失败',
icon: 'error'
})
} finally {
setLoading(false)
setRefreshing(false)
setLoadingMore(false)
}
}, [dealerUser?.userId, date, selectedUserId, selectedFirstUserId, selectedSecondUserId])
// 下拉刷新
const handleRefresh = async () => {
await fetchOrders(1, true)
}
// 加载更多
const handleLoadMore = async () => {
if (!loadingMore && hasMore) {
await fetchOrders(currentPage + 1)
}
}
// const getResourceId = () => {
// if (hasRole('superAdmin')) {
// return undefined
// }
// if (hasRole('admin')) {
// return user?.userId
// }
// return user?.userId;
// }
// 检查是否有特定角色
const hasRole = (roleCode: string) => {
if (!user || !user.roles) {
return false;
}
return user.roles.some(role => role.roleCode === roleCode);
}
const confirmPicker1 = (
options: PickerOption[],
values: (string | number)[]
) => {
if(values && values.length > 0){
const userId = Number(values[0])
options.forEach((option: any) => {
setText1(`${option.text}`)
})
// 清空其他两个筛选条件
setSelectedFirstUserId(undefined)
setSelectedSecondUserId(undefined)
setText2('')
// setText3('')
// 设置业务员筛选条件
setSelectedUserId(userId)
// 关闭选择器
setVisible1(false)
}
}
const confirmPicker2 = (
options: PickerOption[],
values: (string | number)[]
) => {
if(values && values.length > 0){
const firstUserId = Number(values[0])
options.forEach((option: any) => {
setText2(`${option.text}`)
})
// 清空其他两个筛选条件
// setSelectedUserId(undefined)
// setSelectedSecondUserId(undefined)
// setText1('')
// setText3('')
// 设置渠道一筛选条件
setSelectedFirstUserId(firstUserId)
// 关闭选择器
setVisible2(false)
}
}
const confirmPicker3 = (
_: PickerOption[],
values: (string | number)[]
) => {
if(values && values.length > 0){
const secondUserId = Number(values[0])
// options.forEach((option: any) => {
// setText3(`${option.text}`)
// })
// 清空其他两个筛选条件
setSelectedUserId(undefined)
setSelectedFirstUserId(undefined)
setText1('')
setText2('')
// 设置渠道二筛选条件
setSelectedSecondUserId(secondUserId)
// 关闭选择器
setVisible3(false)
}
}
const getStatusText = (isSettled?: number, isInvalid?: number) => {
if (isInvalid === 1) return '未签约'
if (isSettled === 1) return '已结算'
return '待结算'
}
function fetchUsers() {
pageShopDealerReferee({
dealerId: selectedFirstUserId || Taro.getStorageSync('UserId'),
isAdmin: true,
limit: 100
}).then(res => {
const data = res?.list.map(d => {
return {
text: d.nickname,
value: d.userId,
disabled: false,
children: [],
className: ''
}
})
setUsers(data || [])
})
pageShopDealerReferee({
dealerId: selectedUserId || Taro.getStorageSync('UserId'),
limit: 100
}).then(res => {
const data = res?.list.map(d => {
return {
text: d.nickname,
value: d.userId,
disabled: false,
children: [],
className: ''
}
})
setUsers2(data || [])
})
}
// 初始化加载数据
useEffect(() => {
if (dealerUser?.userId) {
fetchOrders(1).then()
}
fetchUsers()
}, [fetchOrders, date])
useEffect(() => {
},[])
const renderOrderItem = (order: OrderWithDetails) => (
<View key={order.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
<View className="flex justify-between items-start mb-1">
<Text className="font-semibold text-gray-800">
{order.orderNo}
</Text>
</View>
<View className="flex justify-between items-center mb-1">
<Text className="text-sm text-gray-400">
{order.title}
</Text>
</View>
{/* 添加收益用户信息显示 */}
<View className="flex justify-between items-center mb-1 mt-2">
<Text className="text-sm text-gray-400">
</Text>
</View>
<View className="mb-1">
{/* 一级佣金30 */}
{(hasRole('superAdmin') || hasRole('admin') || Taro.getStorageSync('UserId') != order.thirdUserId) && (
<>
{Taro.getStorageSync('UserId') != order.secondUserId && (
<>
{(order.firstNickname || order.firstUserId) && (
<Text className="text-sm text-gray-400 block">
{order.firstNickname || `用户${order.firstUserId}`} (¥{order.firstMoney || '0.00'})
</Text>
)}
</>
)}
{(order.secondUserId || order.secondUserId) && (
<Text className="text-sm text-gray-400 block">
{order.secondNickname || `用户${order.secondUserId}`} (¥{order.secondMoney || '0.00'})
</Text>
)}
</>
)}
{/* 三级分销商 */}
{(order.thirdUserId !== undefined && order.thirdUserId > 0) && (
<Text className="text-sm text-gray-400 block">
{order.thirdNickname || `用户${order.thirdUserId}`} (¥{order.thirdMoney || '0.00'})
</Text>
)}
</View>
<View className="flex justify-between items-center mt-2">
<Text className="text-sm text-gray-400">
{order.degreePrice}
</Text>
<Text className="text-sm text-gray-400">
{order.settledPrice}
</Text>
</View>
<View className="flex justify-between items-center mb-1">
<Text className="text-sm text-gray-400">
{order.price}
</Text>
<Text className="text-sm text-gray-400">
{order.rate}
</Text>
</View>
<View className="flex justify-between items-center mb-1">
<Text className="text-sm text-gray-400">
{order.payPrice}
</Text>
<Text className="text-sm text-gray-400">
{order.month}
</Text>
</View>
<View className="flex justify-between items-center mb-1">
<Text className="text-sm text-gray-400">
{getStatusText(order.isSettled, order.isInvalid)}
</Text>
<Text className="text-sm text-gray-400">
{order.settleTime}
</Text>
</View>
</View>
)
return (
<View className="min-h-screen bg-gray-50">
<PullToRefresh
onRefresh={handleRefresh}
disabled={refreshing}
pullingText="下拉刷新"
canReleaseText="释放刷新"
refreshingText="刷新中..."
completeText="刷新完成"
>
<ScrollView
scrollY
className={'h-screen'}
onScrollToLower={handleLoadMore}
lowerThreshold={50}
>
{/*筛选工具条*/}
<View
className={'p-4 flex items-center justify-between'}
>
<View className={'select-month'}>
<Text className={'text-sm mx-1'} onClick={() => setShow1(true)}>{date ? `${date}` : '请选择'}</Text>
<ArrowDown size={10} className={'text-gray-400'} onClick={() => setShow1(true)}/>
</View>
<Space className={'select-user'}>
<Button size={'mini'} onClick={() => setVisible1(!visible1)}>{text1 || '业务员'}</Button>
{/*{selectedUserId && <Button size={'mini'} onClick={() => setVisible2(!visible2)}>{text2 || '渠道员'}</Button>}*/}
<Button size={'mini'} onClick={() => setVisible2(!visible3)}>{text2 || '渠道员'}</Button>
</Space>
</View>
{/*账单列表*/}
<View className="px-4">
{loading && orders.length === 0 ? (
<View className="text-center py-8">
<Loading/>
<Text className="text-gray-500 mt-2">...</Text>
</View>
) : orders.length > 0 ? (
<>
{orders.map(renderOrderItem)}
{loadingMore && (
<View className="text-center py-4">
<Loading/>
<Text className="text-gray-500 mt-1 text-sm">...</Text>
</View>
)}
{!hasMore && orders.length > 0 && (
<View className="text-center py-4">
<Text className="text-gray-400 text-sm"></Text>
</View>
)}
</>
) : (
<Empty description="暂无电费订单" style={{
backgroundColor: 'transparent'
}}/>
)}
</View>
</ScrollView>
</PullToRefresh>
<DatePicker
title="日期选择"
visible={show1}
pickerProps={{
popupProps: {zIndex: 1220},
}}
type={'year-month'}
defaultValue={new Date(`${currDate}`)}
showChinese
onCancel={() => setShow1(false)}
onConfirm={(_, values) => {
setShow1(false)
setDate(`${values[0]}${values[1]}`)
}}
/>
<Picker
title="请选择"
visible={visible1}
options={users}
onConfirm={(list, values) => confirmPicker1(list, values)}
onClose={() => setVisible1(false)}
/>
<Picker
title="请选择"
visible={visible2}
options={users2}
onConfirm={(list, values) => confirmPicker2(list, values)}
onClose={() => setVisible2(false)}
/>
<Picker
title="请选择"
visible={visible3}
options={users}
onConfirm={(list, values) => confirmPicker3(list, values)}
onClose={() => setVisible3(false)}
/>
</View>
)
}
export default DealerOrder