refactor(credit): 重构客户列表筛选逻辑并优化性能
- 移除未使用的 Copy 图标导入 - 提取筛选逻辑到独立的 filterCustomers 函数 - 添加 FilterValues 类型定义 - 使用 useRef 保存筛选状态避免依赖循环 - 修改 reload 函数支持覆盖筛选参数 - 将筛选参数传递给 API 调用 - 修复复制电话按钮功能禁用 - 更新地区、步骤和状态筛选的重载逻辑 - 修改员工查询参数从 isAdmin 到 isStaff
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
SearchBar,
|
||||
Tag
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import { Copy, Phone } from '@nutui/icons-react-taro'
|
||||
import { Phone } from '@nutui/icons-react-taro'
|
||||
|
||||
import RegionData from '@/api/json/regions-data.json'
|
||||
import { getCreditMpCustomer, pageCreditMpCustomer, updateCreditMpCustomer } from '@/api/credit/creditMpCustomer'
|
||||
@@ -107,6 +107,39 @@ const getStepTagType = (code: number | null): any => {
|
||||
return 'primary'
|
||||
}
|
||||
|
||||
type FilterValues = {
|
||||
cityText: string
|
||||
statusText: string
|
||||
stepCode: number | null
|
||||
}
|
||||
|
||||
const filterCustomers = (incoming: CreditMpCustomer[], filters: FilterValues) => {
|
||||
const city = filters.cityText === '全部' ? '' : filters.cityText
|
||||
const status = filters.statusText === '全部' ? '' : filters.statusText
|
||||
const step = filters.stepCode == null ? null : filters.stepCode
|
||||
|
||||
return incoming.filter(c => {
|
||||
if (c?.deleted === 1) return false
|
||||
|
||||
if (city) {
|
||||
const full = [c.province, c.city, c.region].filter(Boolean).join(' ')
|
||||
if (!full.includes(city) && String(c.city || '') !== city) return false
|
||||
}
|
||||
|
||||
if (status) {
|
||||
const txt = getRowStatus(c)
|
||||
if (!txt.includes(status)) return false
|
||||
}
|
||||
|
||||
if (step != null) {
|
||||
const code = getStepCode(c)
|
||||
if (code == null || code !== step) return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
export default function CreditCompanyPage() {
|
||||
const serverPageRef = useRef(1)
|
||||
const staffLoadingPromiseRef = useRef<Promise<User[]> | null>(null)
|
||||
@@ -120,12 +153,15 @@ export default function CreditCompanyPage() {
|
||||
|
||||
const [cityVisible, setCityVisible] = useState(false)
|
||||
const [cityText, setCityText] = useState<string>('全部')
|
||||
const cityTextRef = useRef(cityText)
|
||||
|
||||
const [stepVisible, setStepVisible] = useState(false)
|
||||
const [stepCode, setStepCode] = useState<number | null>(null)
|
||||
const stepCodeRef = useRef(stepCode)
|
||||
|
||||
const [statusVisible, setStatusVisible] = useState(false)
|
||||
const [statusText, setStatusText] = useState<string>('全部')
|
||||
const statusTextRef = useRef(statusText)
|
||||
|
||||
const [selectMode, setSelectMode] = useState(false)
|
||||
const [selectedIds, setSelectedIds] = useState<number[]>([])
|
||||
@@ -171,38 +207,12 @@ export default function CreditCompanyPage() {
|
||||
return map
|
||||
}, [staffList])
|
||||
|
||||
const applyFilters = useCallback(
|
||||
(incoming: CreditMpCustomer[]) => {
|
||||
const city = cityText === '全部' ? '' : cityText
|
||||
const status = statusText === '全部' ? '' : statusText
|
||||
const step = stepCode == null ? null : stepCode
|
||||
|
||||
return incoming.filter(c => {
|
||||
if (c?.deleted === 1) return false
|
||||
|
||||
if (city) {
|
||||
const full = [c.province, c.city, c.region].filter(Boolean).join(' ')
|
||||
if (!full.includes(city) && String(c.city || '') !== city) return false
|
||||
}
|
||||
|
||||
if (status) {
|
||||
const txt = getRowStatus(c)
|
||||
if (!txt.includes(status)) return false
|
||||
}
|
||||
|
||||
if (step != null) {
|
||||
const code = getStepCode(c)
|
||||
if (code == null || code !== step) return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
},
|
||||
[cityText, statusText, stepCode]
|
||||
)
|
||||
cityTextRef.current = cityText
|
||||
statusTextRef.current = statusText
|
||||
stepCodeRef.current = stepCode
|
||||
|
||||
const reload = useCallback(
|
||||
async (resetPage = false) => {
|
||||
async (resetPage = false, override?: Partial<FilterValues>) => {
|
||||
if (loading) return
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
@@ -217,6 +227,11 @@ export default function CreditCompanyPage() {
|
||||
let nextList = resetPage ? [] : list
|
||||
let page = serverPageRef.current
|
||||
let serverHasMore = true
|
||||
const filters: FilterValues = {
|
||||
cityText: override?.cityText ?? cityTextRef.current,
|
||||
statusText: override?.statusText ?? statusTextRef.current,
|
||||
stepCode: override?.stepCode ?? stepCodeRef.current
|
||||
}
|
||||
|
||||
// 当筛选条件较严格时,可能需要多拉几页才能拿到“至少一条匹配数据”
|
||||
const MAX_PAGE_TRIES = 8
|
||||
@@ -233,7 +248,7 @@ export default function CreditCompanyPage() {
|
||||
|
||||
const res = await pageCreditMpCustomer(params as CreditMpCustomerParam)
|
||||
const incoming = (res?.list || []) as CreditMpCustomer[]
|
||||
const filtered = applyFilters(incoming)
|
||||
const filtered = filterCustomers(incoming, filters)
|
||||
|
||||
if (resetPage) {
|
||||
nextList = filtered
|
||||
@@ -265,7 +280,7 @@ export default function CreditCompanyPage() {
|
||||
setLoading(false)
|
||||
}
|
||||
},
|
||||
[applyFilters, list, loading, searchValue]
|
||||
[list, loading, searchValue]
|
||||
)
|
||||
|
||||
const handleRefresh = useCallback(async () => {
|
||||
@@ -366,7 +381,7 @@ export default function CreditCompanyPage() {
|
||||
|
||||
const p = (async () => {
|
||||
try {
|
||||
const res = await listUsers({ isAdmin: true } as any)
|
||||
const res = await listUsers({ isStaff: true } as any)
|
||||
const arr = (res || []) as User[]
|
||||
setStaffList(arr)
|
||||
return arr
|
||||
@@ -471,9 +486,9 @@ export default function CreditCompanyPage() {
|
||||
{/* {statusText === '全部' ? '状态' : statusText}*/}
|
||||
{/*</Button>*/}
|
||||
<View className="flex-1" />
|
||||
<Button size="small" fill="outline" icon={<Copy />} onClick={copyPhones}>
|
||||
复制电话
|
||||
</Button>
|
||||
{/*<Button size="small" fill="outline" icon={<Copy />} onClick={copyPhones}>*/}
|
||||
{/* 复制电话*/}
|
||||
{/*</Button>*/}
|
||||
</View>
|
||||
|
||||
{!!error && (
|
||||
@@ -668,9 +683,10 @@ export default function CreditCompanyPage() {
|
||||
title="选择地区(到城市)"
|
||||
onChange={(value: any[]) => {
|
||||
const txt = value.filter(Boolean).slice(0, 2).join(' ')
|
||||
setCityText(txt || '全部')
|
||||
const nextCityText = txt || '全部'
|
||||
setCityText(nextCityText)
|
||||
setCityVisible(false)
|
||||
reload(true).then()
|
||||
reload(true, { cityText: nextCityText }).then()
|
||||
}}
|
||||
onClose={() => setCityVisible(false)}
|
||||
/>
|
||||
@@ -688,9 +704,10 @@ export default function CreditCompanyPage() {
|
||||
key="ALL"
|
||||
title={<Text className={stepCode == null ? 'text-blue-600' : ''}>全部</Text>}
|
||||
onClick={() => {
|
||||
setStepCode(null)
|
||||
const nextStep = null
|
||||
setStepCode(nextStep)
|
||||
setStepVisible(false)
|
||||
reload(true).then()
|
||||
reload(true, { stepCode: nextStep }).then()
|
||||
}}
|
||||
/>
|
||||
{STEP_OPTIONS.map(s => (
|
||||
@@ -698,9 +715,10 @@ export default function CreditCompanyPage() {
|
||||
key={s.code}
|
||||
title={<Text className={s.code === stepCode ? 'text-blue-600' : ''}>{s.text}</Text>}
|
||||
onClick={() => {
|
||||
setStepCode(s.code)
|
||||
const nextStep = s.code
|
||||
setStepCode(nextStep)
|
||||
setStepVisible(false)
|
||||
reload(true).then()
|
||||
reload(true, { stepCode: nextStep }).then()
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -722,9 +740,10 @@ export default function CreditCompanyPage() {
|
||||
key={s}
|
||||
title={<Text className={s === statusText ? 'text-blue-600' : ''}>{s}</Text>}
|
||||
onClick={() => {
|
||||
setStatusText(s)
|
||||
const nextStatus = s
|
||||
setStatusText(nextStatus)
|
||||
setStatusVisible(false)
|
||||
reload(true).then()
|
||||
reload(true, { statusText: nextStatus }).then()
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user