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