refactor(credit): 重构客户列表筛选逻辑并优化性能

- 移除未使用的 Copy 图标导入
- 提取筛选逻辑到独立的 filterCustomers 函数
- 添加 FilterValues 类型定义
- 使用 useRef 保存筛选状态避免依赖循环
- 修改 reload 函数支持覆盖筛选参数
- 将筛选参数传递给 API 调用
- 修复复制电话按钮功能禁用
- 更新地区、步骤和状态筛选的重载逻辑
- 修改员工查询参数从 isAdmin 到 isStaff
This commit is contained in:
2026-03-20 00:55:30 +08:00
parent 495a9c8bbf
commit b14d85fb00

View File

@@ -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()
}}
/>
))}