import { useCallback, useMemo, useState } from 'react' import Taro, { useDidShow, useRouter } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import { Button, ConfigProvider, Empty, Loading } from '@nutui/nutui-react-taro' import { Setting } from '@nutui/icons-react-taro' import dayjs from 'dayjs' import { getCreditCompany } from '@/api/credit/creditCompany' import type { CreditCompany } from '@/api/credit/creditCompany/model' type CustomerStatus = '保护期内' | '已签约' | '已完成' | '保护期外' type FollowPerson = { name: string time?: string isCurrent?: boolean } const splitPhones = (raw?: string) => { const text = String(raw || '').trim() if (!text) return [] return text .split(/[\s,,;;、\n\r]+/g) .map(s => s.trim()) .filter(Boolean) } const uniq = (arr: T[]) => Array.from(new Set(arr)) const getCompanyIndustry = (c?: CreditCompany) => { if (!c) return '' return String( c.nationalStandardIndustryCategories6 || c.nationalStandardIndustryCategories2 || c.nationalStandardIndustryCategories || c.institutionType || '' ).trim() } const parseContactFromComments = (comments?: string) => { const txt = String(comments || '').trim() if (!txt) return '' const m = txt.match(/联系人:([^;;]+)/) return String(m?.[1] || '').trim() } const getStatusTextClass = (s: CustomerStatus) => { if (s === '保护期内') return 'text-green-600' if (s === '已签约') return 'text-orange-500' if (s === '已完成') return 'text-blue-600' return 'text-gray-500' } const normalizeFollowPeople = (company: CreditCompany): FollowPerson[] => { // 兼容后端可能下发多种字段;未下发时给出静态示例,保证 UI/逻辑可演示。 const anyCompany = company as any const incoming: FollowPerson[] = [] const arr1 = anyCompany?.followPeople as Array | undefined if (Array.isArray(arr1) && arr1.length) { for (const it of arr1) { const name = String(it?.name || it?.realName || it?.userRealName || '').trim() if (!name) continue incoming.push({ name, time: it?.time || it?.date, isCurrent: !!it?.isCurrent }) } } const arr2 = anyCompany?.followHistory as Array | undefined if (Array.isArray(arr2) && arr2.length) { for (const it of arr2) { const name = String(it?.name || it?.realName || it?.userRealName || it || '').trim() if (!name) continue incoming.push({ name, time: it?.time || it?.date, isCurrent: !!it?.isCurrent }) } } const currentName = String( anyCompany?.followRealName || anyCompany?.userRealName || anyCompany?.realName || '' ).trim() if (currentName) incoming.push({ name: currentName, isCurrent: true }) const cleaned = incoming.filter(x => x?.name).map(x => ({ ...x, name: String(x.name).trim() })) const deduped: FollowPerson[] = [] const seen = new Set() for (const p of cleaned) { const k = p.name if (seen.has(k)) continue seen.add(k) deduped.push(p) } if (deduped.length) { // 规则:往期跟进人(灰色)按时间顺序在前;当前跟进人(蓝色)放在最后。 const current = deduped.filter(p => p.isCurrent) const history = deduped.filter(p => !p.isCurrent) history.sort((a, b) => { const at = a.time ? dayjs(a.time).valueOf() : 0 const bt = b.time ? dayjs(b.time).valueOf() : 0 return at - bt }) // 多个 current 时取最后一个为“当前” const currentOne = current.length ? current[current.length - 1] : undefined return currentOne ? history.concat([{ ...currentOne, isCurrent: true }]) : history } // 无真实跟进人信息:尽量展示一个可识别的占位,避免“凭空造历史数据”造成误导。 const uid = Number(company?.userId) if (Number.isFinite(uid) && uid > 0) return [{ name: `员工${uid}`, isCurrent: true }] return [] } const getAssignDateText = (company?: CreditCompany) => { const anyCompany = company as any const raw = anyCompany?.assignDate || anyCompany?.assignTime || anyCompany?.updateTime || anyCompany?.createTime const t = String(raw || '').trim() if (!t) return '' const d = dayjs(t) if (!d.isValid()) return t return d.format('YYYY-MM-DD') } export default function CreditCompanyDetailPage() { const router = useRouter() const companyId = useMemo(() => { const id = Number((router?.params as any)?.id) return Number.isFinite(id) && id > 0 ? id : undefined }, [router?.params]) const statusBarHeight = useMemo(() => { try { const info = Taro.getSystemInfoSync() return Number(info?.statusBarHeight || 0) } catch (_e) { return 0 } }, []) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [company, setCompany] = useState(null) const reload = useCallback(async () => { setError(null) setLoading(true) try { if (!companyId) throw new Error('缺少客户ID') const res = await getCreditCompany(companyId) setCompany(res as CreditCompany) } catch (e) { console.error('加载客户详情失败:', e) setCompany(null) setError(String((e as any)?.message || '加载失败')) } finally { setLoading(false) } }, [companyId]) useDidShow(() => { reload().then() }) const name = useMemo(() => { const c = company || ({} as CreditCompany) return String(c.matchName || c.name || '').trim() }, [company]) const code = useMemo(() => String(company?.code || '').trim(), [company?.code]) const industry = useMemo(() => getCompanyIndustry(company || undefined), [company]) const contact = useMemo(() => parseContactFromComments(company?.comments), [company?.comments]) const phones = useMemo(() => { const arr = [...splitPhones(company?.tel), ...splitPhones(company?.moreTel)] return uniq(arr) }, [company?.moreTel, company?.tel]) const address = useMemo(() => { const c = company || ({} as CreditCompany) const region = [c.province, c.city, c.region].filter(Boolean).join('') const addr = String(c.address || '').trim() return (region + addr).trim() || region || addr }, [company]) const followPeople = useMemo(() => (company ? normalizeFollowPeople(company) : []), [company]) const assignDate = useMemo(() => getAssignDateText(company || undefined), [company]) const customerStatus = useMemo(() => { const anyCompany = company as any const raw = String(anyCompany?.customerStatus || anyCompany?.statusText || '').trim() const allowed: CustomerStatus[] = ['保护期内', '已签约', '已完成', '保护期外'] if (allowed.includes(raw as any)) return raw as CustomerStatus return '保护期内' }, [company]) const headerOffset = statusBarHeight + 80 return ( 12:00 信号 Wi-Fi 电池 Taro.navigateBack()}> 返回 客户详情 { try { const res = await Taro.showActionSheet({ itemList: ['编辑客户', '刷新'] }) if (res.tapIndex === 0 && companyId) Taro.navigateTo({ url: `/credit/company/edit?id=${companyId}` }) if (res.tapIndex === 1) reload() } catch (e) { const msg = String((e as any)?.errMsg || (e as any)?.message || e || '') if (msg.includes('cancel')) return } }} > ... Taro.showToast({ title: '设置(示意)', icon: 'none' })} > {loading ? ( 加载中... ) : error ? ( {error} ) : !company ? ( ) : ( {name || '—'} 统一代码 {code || '—'} 所属行业 {industry || '—'} 客户联系人 {contact || '—'} 客户联系方式 {phones.length ? ( {phones.join(',')} ) : ( )} 地址 {address || '—'} 跟进人 {followPeople.length ? ( followPeople.map((p, idx) => ( {idx === followPeople.length - 1 ? p.name : `${p.name},`} )) ) : ( )} 分配日期 {assignDate || '—'} 客户状态 {customerStatus} )} ) }