feat(dealer): 添加客户搜索功能并优化订单展示
- 在客户页面添加搜索栏,支持防抖搜索- 增加搜索结果统计展示-优化订单列表展示逻辑 - 调整订单状态文案及金额显示 - 更新收益统计标题- 添加订单备注字段支持 - 过滤已失效订单数据
This commit is contained in:
@@ -30,6 +30,8 @@ export interface ShopDealerOrder {
|
|||||||
isSettled?: number;
|
isSettled?: number;
|
||||||
// 结算时间
|
// 结算时间
|
||||||
settleTime?: number;
|
settleTime?: number;
|
||||||
|
// 订单备注
|
||||||
|
comments?: string;
|
||||||
// 商城ID
|
// 商城ID
|
||||||
tenantId?: number;
|
tenantId?: number;
|
||||||
// 创建时间
|
// 创建时间
|
||||||
@@ -47,5 +49,7 @@ export interface ShopDealerOrderParam extends PageParam {
|
|||||||
secondUserId?: number;
|
secondUserId?: number;
|
||||||
thirdUserId?: number;
|
thirdUserId?: number;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
isInvalid?: number;
|
||||||
|
isSettled?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {useState, useEffect, useCallback} from 'react'
|
import {useState, useEffect, useCallback} from 'react'
|
||||||
import {View, Text} from '@tarojs/components'
|
import {View, Text} from '@tarojs/components'
|
||||||
import Taro, {useDidShow} from '@tarojs/taro'
|
import Taro, {useDidShow} from '@tarojs/taro'
|
||||||
import {Loading, InfiniteLoading, Empty, Space, Tabs, TabPane, Tag, Button} from '@nutui/nutui-react-taro'
|
import {Loading, InfiniteLoading, Empty, Space, Tabs, TabPane, Tag, Button, SearchBar} from '@nutui/nutui-react-taro'
|
||||||
import {Phone, AngleDoubleLeft} from '@nutui/icons-react-taro'
|
import {Phone, AngleDoubleLeft} from '@nutui/icons-react-taro'
|
||||||
import type {ShopDealerApply, ShopDealerApply as UserType} from "@/api/shop/shopDealerApply/model";
|
import type {ShopDealerApply, ShopDealerApply as UserType} from "@/api/shop/shopDealerApply/model";
|
||||||
import {
|
import {
|
||||||
@@ -26,7 +26,8 @@ const CustomerIndex = () => {
|
|||||||
const [list, setList] = useState<CustomerUser[]>([])
|
const [list, setList] = useState<CustomerUser[]>([])
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const [activeTab, setActiveTab] = useState<CustomerStatus>('all')
|
const [activeTab, setActiveTab] = useState<CustomerStatus>('all')
|
||||||
const [searchValue, _] = useState<string>('')
|
const [searchValue, setSearchValue] = useState<string>('')
|
||||||
|
const [displaySearchValue, setDisplaySearchValue] = useState<string>('')
|
||||||
const [page, setPage] = useState(1)
|
const [page, setPage] = useState(1)
|
||||||
const [hasMore, setHasMore] = useState(true)
|
const [hasMore, setHasMore] = useState(true)
|
||||||
|
|
||||||
@@ -227,13 +228,22 @@ const CustomerIndex = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 防抖搜索功能
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setDisplaySearchValue(searchValue);
|
||||||
|
}, 300); // 300ms 防抖
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [searchValue]);
|
||||||
|
|
||||||
// 根据搜索条件筛选数据(状态筛选已在API层面处理)
|
// 根据搜索条件筛选数据(状态筛选已在API层面处理)
|
||||||
const getFilteredList = () => {
|
const getFilteredList = () => {
|
||||||
let filteredList = list;
|
let filteredList = list;
|
||||||
|
|
||||||
// 按搜索关键词筛选
|
// 按搜索关键词筛选
|
||||||
if (searchValue.trim()) {
|
if (displaySearchValue.trim()) {
|
||||||
const keyword = searchValue.trim().toLowerCase();
|
const keyword = displaySearchValue.trim().toLowerCase();
|
||||||
filteredList = filteredList.filter(customer =>
|
filteredList = filteredList.filter(customer =>
|
||||||
(customer.realName && customer.realName.toLowerCase().includes(keyword)) ||
|
(customer.realName && customer.realName.toLowerCase().includes(keyword)) ||
|
||||||
(customer.dealerName && customer.dealerName.toLowerCase().includes(keyword)) ||
|
(customer.dealerName && customer.dealerName.toLowerCase().includes(keyword)) ||
|
||||||
@@ -466,56 +476,81 @@ const CustomerIndex = () => {
|
|||||||
// 渲染客户列表
|
// 渲染客户列表
|
||||||
const renderCustomerList = () => {
|
const renderCustomerList = () => {
|
||||||
const filteredList = getFilteredList();
|
const filteredList = getFilteredList();
|
||||||
|
const isSearching = displaySearchValue.trim().length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="p-4" style={{
|
<View className="flex-1">
|
||||||
height: '90vh',
|
{/* 搜索结果统计 */}
|
||||||
overflowY: 'auto',
|
{isSearching && (
|
||||||
overflowX: 'hidden'
|
<View className="bg-white px-4 py-2 border-b border-gray-100">
|
||||||
}}>
|
<Text className="text-sm text-gray-600">
|
||||||
<InfiniteLoading
|
搜索 "{displaySearchValue}" 的结果,共找到 {filteredList.length} 条记录
|
||||||
target="scroll"
|
</Text>
|
||||||
hasMore={hasMore}
|
</View>
|
||||||
onLoadMore={reloadMore}
|
)}
|
||||||
onScroll={() => {
|
|
||||||
// 滚动事件处理
|
<View className="p-4" style={{
|
||||||
}}
|
height: isSearching ? 'calc(90vh - 40px)' : '90vh',
|
||||||
onScrollToUpper={() => {
|
overflowY: 'auto',
|
||||||
// 滚动到顶部事件处理
|
overflowX: 'hidden'
|
||||||
}}
|
}}>
|
||||||
loadingText={
|
<InfiniteLoading
|
||||||
<>
|
target="scroll"
|
||||||
加载中...
|
hasMore={hasMore}
|
||||||
</>
|
onLoadMore={reloadMore}
|
||||||
}
|
onScroll={() => {
|
||||||
loadMoreText={
|
// 滚动事件处理
|
||||||
filteredList.length === 0 ? (
|
}}
|
||||||
<Empty
|
onScrollToUpper={() => {
|
||||||
style={{backgroundColor: 'transparent'}}
|
// 滚动到顶部事件处理
|
||||||
description={loading ? "加载中..." : "暂无客户数据"}
|
}}
|
||||||
/>
|
loadingText={
|
||||||
) : (
|
<>
|
||||||
<View className={'h-3 flex items-center justify-center'}>
|
加载中...
|
||||||
<Text className="text-gray-500 text-sm">没有更多了</Text>
|
</>
|
||||||
|
}
|
||||||
|
loadMoreText={
|
||||||
|
filteredList.length === 0 ? (
|
||||||
|
<Empty
|
||||||
|
style={{backgroundColor: 'transparent'}}
|
||||||
|
description={loading ? "加载中..." : "暂无客户数据"}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<View className={'h-3 flex items-center justify-center'}>
|
||||||
|
<Text className="text-gray-500 text-sm">没有更多了</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{loading && filteredList.length === 0 ? (
|
||||||
|
<View className="flex items-center justify-center py-8">
|
||||||
|
<Loading/>
|
||||||
|
<Text className="text-gray-500 mt-2 ml-2">加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
) : (
|
||||||
}
|
filteredList.map(renderCustomerItem)
|
||||||
>
|
)}
|
||||||
{loading && filteredList.length === 0 ? (
|
</InfiniteLoading>
|
||||||
<View className="flex items-center justify-center py-8">
|
</View>
|
||||||
<Loading/>
|
|
||||||
<Text className="text-gray-500 mt-2 ml-2">加载中...</Text>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
filteredList.map(renderCustomerItem)
|
|
||||||
)}
|
|
||||||
</InfiniteLoading>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="min-h-screen bg-gray-50">
|
<View className="min-h-screen bg-gray-50">
|
||||||
|
{/* 搜索栏 */}
|
||||||
|
<View className="bg-white py-2 border-b border-gray-100">
|
||||||
|
<SearchBar
|
||||||
|
value={searchValue}
|
||||||
|
placeholder="搜索客户名称、手机号"
|
||||||
|
onChange={(value) => setSearchValue(value)}
|
||||||
|
onClear={() => {
|
||||||
|
setSearchValue('');
|
||||||
|
setDisplaySearchValue('');
|
||||||
|
}}
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* 顶部Tabs */}
|
{/* 顶部Tabs */}
|
||||||
<View className="bg-white">
|
<View className="bg-white">
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const DealerIndex: React.FC = () => {
|
|||||||
{dealerUser && (
|
{dealerUser && (
|
||||||
<View className="mx-4 -mt-6 rounded-xl p-4 relative z-10" style={cardGradients.elevated}>
|
<View className="mx-4 -mt-6 rounded-xl p-4 relative z-10" style={cardGradients.elevated}>
|
||||||
<View className="mb-4">
|
<View className="mb-4">
|
||||||
<Text className="font-semibold text-gray-800">佣金统计</Text>
|
<Text className="font-semibold text-gray-800">收益统计</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="grid grid-cols-3 gap-3">
|
<View className="grid grid-cols-3 gap-3">
|
||||||
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const DealerOrders: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await pageShopDealerOrder({
|
const result = await pageShopDealerOrder({
|
||||||
|
isInvalid: 0,
|
||||||
page,
|
page,
|
||||||
limit: 10
|
limit: 10
|
||||||
})
|
})
|
||||||
@@ -91,7 +92,7 @@ const DealerOrders: React.FC = () => {
|
|||||||
}, [fetchOrders])
|
}, [fetchOrders])
|
||||||
|
|
||||||
const getStatusText = (isSettled?: number, isInvalid?: number) => {
|
const getStatusText = (isSettled?: number, isInvalid?: number) => {
|
||||||
if (isInvalid === 1) return '已失效'
|
if (isInvalid === 1) return '未签约'
|
||||||
if (isSettled === 1) return '已结算'
|
if (isSettled === 1) return '已结算'
|
||||||
return '待结算'
|
return '待结算'
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ const DealerOrders: React.FC = () => {
|
|||||||
<View key={order.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
|
<View key={order.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
|
||||||
<View className="flex justify-between items-start mb-1">
|
<View className="flex justify-between items-start mb-1">
|
||||||
<Text className="font-semibold text-gray-800">
|
<Text className="font-semibold text-gray-800">
|
||||||
订单号:{order.orderNo}
|
电费收益
|
||||||
</Text>
|
</Text>
|
||||||
<Tag type={getStatusColor(order.isSettled, order.isInvalid)}>
|
<Tag type={getStatusColor(order.isSettled, order.isInvalid)}>
|
||||||
{getStatusText(order.isSettled, order.isInvalid)}
|
{getStatusText(order.isSettled, order.isInvalid)}
|
||||||
@@ -115,19 +116,19 @@ const DealerOrders: React.FC = () => {
|
|||||||
|
|
||||||
<View className="flex justify-between items-center mb-1">
|
<View className="flex justify-between items-center mb-1">
|
||||||
<Text className="text-sm text-gray-400">
|
<Text className="text-sm text-gray-400">
|
||||||
订单金额:¥{order.orderPrice || '0.00'}
|
结算金额:¥{order.orderPrice || '0.00'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-sm text-orange-500 font-semibold">
|
<Text className="text-lg text-orange-500 font-semibold">
|
||||||
我的佣金:¥{order.userCommission}
|
¥{(Number(order.orderPrice) * 10).toFixed(2)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className="flex justify-between items-center">
|
<View className="flex justify-between items-center">
|
||||||
<Text className="text-sm text-gray-400">
|
<Text className="text-sm text-gray-400">
|
||||||
客户:{order.customerName}
|
客户:{order.comments}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-sm text-gray-400">
|
<Text className="text-sm text-gray-400">
|
||||||
{order.createTime}
|
{order.settleTime}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user