import { useCallback, useMemo, useState } from 'react' import Taro, { useDidShow, useRouter } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import { Button, ConfigProvider, Empty, Loading, TextArea } 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 Intention = '无意向' | '有意向' type FollowStep1Draft = { submitted: boolean submittedAt: string companyId: number contact: string phone: string audioSelected: boolean smsShots: number callShots: number remark: string intention: Intention // 业务规则模拟: // 多次沟通 + 有意向 => 无需审核(可直接进入下一步,下一步不在本页实现) // 多次沟通 + 无意向 => 需管理员审核 communicationCount: number needApproval: boolean isApproved: 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 parseContactFromComments = (comments?: string) => { const txt = String(comments || '').trim() if (!txt) return '' const m = txt.match(/联系人:([^;;]+)/) return String(m?.[1] || '').trim() } const makeThumb = () => ({ id: `${Date.now()}-${Math.random().toString(16).slice(2)}` }) const getDraftKey = (companyId: number) => `credit_company_follow_step1:${companyId}` const getCountKey = (companyId: number) => `credit_company_follow_comm_count:${companyId}` const safeParseJSON = (v: any): T | null => { try { if (!v) return null if (typeof v === 'object') return v as T if (typeof v === 'string') return JSON.parse(v) as T return null } catch (_e) { return null } } export default function CreditCompanyFollowStep1Page() { 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 [submitted, setSubmitted] = useState(false) const [audioSelected, setAudioSelected] = useState(false) const [smsShots, setSmsShots] = useState>([]) const [callShots, setCallShots] = useState>([]) const [remark, setRemark] = useState('') const [intention, setIntention] = useState(undefined) const loadDraft = useCallback(() => { if (!companyId) return const raw = Taro.getStorageSync(getDraftKey(companyId)) const saved = safeParseJSON(raw) if (!saved?.submitted) return setSubmitted(true) setAudioSelected(!!saved.audioSelected) setSmsShots(Array.from({ length: Math.max(0, Math.min(6, Number(saved.smsShots || 0))) }, makeThumb)) setCallShots(Array.from({ length: Math.max(0, Math.min(6, Number(saved.callShots || 0))) }, makeThumb)) setRemark(String(saved.remark || '')) setIntention(saved.intention) }, [companyId]) const reloadCompany = 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(() => { reloadCompany().then() loadDraft() }) const contact = useMemo(() => parseContactFromComments(company?.comments), [company?.comments]) const phone = useMemo(() => { const arr = uniq([...splitPhones(company?.tel), ...splitPhones(company?.moreTel)]) return String(arr[0] || '').trim() }, [company?.moreTel, company?.tel]) const canEdit = !submitted const addSmsShot = () => { if (!canEdit) return if (smsShots.length >= 6) { Taro.showToast({ title: '短信截图已达上限(6张)', icon: 'none' }) return } setSmsShots(prev => prev.concat(makeThumb())) } const addCallShot = () => { if (!canEdit) return if (callShots.length >= 6) { Taro.showToast({ title: '电话沟通截图已达上限(6张)', icon: 'none' }) return } setCallShots(prev => prev.concat(makeThumb())) } const chooseAudio = async () => { if (!canEdit) return // 本步骤仅做“选择录音文件”的交互模拟 setAudioSelected(true) Taro.showToast({ title: '已选择录音文件(模拟)', icon: 'none' }) } const submit = async () => { if (!companyId) { Taro.showToast({ title: '缺少客户ID', icon: 'none' }) return } if (!intention) { Taro.showToast({ title: '请选择意向(无意向/有意向)', icon: 'none' }) return } if (!remark.trim()) { Taro.showToast({ title: '请填写沟通情况', icon: 'none' }) return } if (!smsShots.length && !callShots.length) { Taro.showToast({ title: '建议至少上传1张截图(非必填)', icon: 'none' }) } const prevCountRaw = Taro.getStorageSync(getCountKey(companyId)) const prevCount = Number(prevCountRaw || 0) const communicationCount = (Number.isFinite(prevCount) ? prevCount : 0) + 1 Taro.setStorageSync(getCountKey(companyId), communicationCount) const needApproval = communicationCount > 1 && intention === '无意向' const isApproved = false // 模拟:默认未审核;后续步骤可检查该标志 const payload: FollowStep1Draft = { submitted: true, submittedAt: dayjs().format('YYYY-MM-DD HH:mm:ss'), companyId, contact, phone, audioSelected, smsShots: smsShots.length, callShots: callShots.length, remark: remark.trim(), intention, communicationCount, needApproval, isApproved } Taro.setStorageSync(getDraftKey(companyId), payload) setSubmitted(true) await Taro.showModal({ title: '提示', content: '跟进信息已提交\n请等待管理员审核', showCancel: false }) } const headerOffset = statusBarHeight + 80 return ( 12:00 信号 Wi-Fi 电池 Taro.navigateBack()}> 返回 客户跟进 { try { const res = await Taro.showActionSheet({ itemList: ['刷新'] }) if (res.tapIndex === 0) reloadCompany() } catch (e) { const msg = String((e as any)?.errMsg || (e as any)?.message || e || '') if (msg.includes('cancel')) return } }} > ... {loading ? ( 加载中... ) : error ? ( {error} ) : !company ? ( ) : ( 加微信前沟通 联系人 {contact || '—'} 联系电话 {phone || '—'} 电话录音 短信截图 {smsShots.length}/6 {smsShots.map((x, idx) => ( 图{idx + 1} ))} = 6 ? 'border-gray-200 text-gray-200' : 'border-gray-300 text-gray-400' }`} onClick={addSmsShot} > + 电话沟通截图 {callShots.length}/6 {callShots.map((x, idx) => ( 图{idx + 1} ))} = 6 ? 'border-gray-200 text-gray-200' : 'border-gray-300 text-gray-400' }`} onClick={addCallShot} > + 沟通情况*