import { useEffect, useState, type ReactNode } from "react"; import { Search, Plus, MapPin, Building2, User, Phone, X, Clock, FileText, Mail, Calendar } from "lucide-react"; import { motion, AnimatePresence } from "motion/react"; import { createChannelExpansion, createExpansionFollowUp, createSalesExpansion, getExpansionMeta, getExpansionOverview, updateChannelExpansion, updateSalesExpansion, type ChannelExpansionItem, type CreateChannelExpansionPayload, type CreateExpansionFollowUpPayload, type CreateSalesExpansionPayload, type DepartmentOption, type ExpansionFollowUp, type SalesExpansionItem, } from "@/lib/auth"; type ExpansionItem = SalesExpansionItem | ChannelExpansionItem; type ExpansionTab = "sales" | "channel"; const defaultSalesForm: CreateSalesExpansionPayload = { candidateName: "", mobile: "", email: "", industry: "", title: "", intentLevel: "medium", stage: "initial_contact", hasDesktopExp: false, inProgress: true, employmentStatus: "active", expectedJoinDate: "", remark: "", }; const defaultChannelForm: CreateChannelExpansionPayload = { channelName: "", province: "", industry: "", contactName: "", contactTitle: "", contactMobile: "", stage: "initial_contact", landedFlag: false, expectedSignDate: "", remark: "", }; function toDateTimeLocalValue(date = new Date()) { const timezoneOffset = date.getTimezoneOffset() * 60000; return new Date(date.getTime() - timezoneOffset).toISOString().slice(0, 16); } const defaultFollowUpForm: CreateExpansionFollowUpPayload = { followUpType: "电话沟通", content: "", nextAction: "", followUpTime: toDateTimeLocalValue(), }; function ModalShell({ title, subtitle, onClose, children, footer, }: { title: string; subtitle: string; onClose: () => void; children: ReactNode; footer: ReactNode; }) { return ( <>

{title}

{subtitle}

{children}
{footer}
); } export default function Expansion() { const [activeTab, setActiveTab] = useState("sales"); const [selectedItem, setSelectedItem] = useState(null); const [keyword, setKeyword] = useState(""); const [salesData, setSalesData] = useState([]); const [channelData, setChannelData] = useState([]); const [departments, setDepartments] = useState([]); const [refreshTick, setRefreshTick] = useState(0); const [createOpen, setCreateOpen] = useState(false); const [editOpen, setEditOpen] = useState(false); const [followUpOpen, setFollowUpOpen] = useState(false); const [submitting, setSubmitting] = useState(false); const [createError, setCreateError] = useState(""); const [editError, setEditError] = useState(""); const [followUpError, setFollowUpError] = useState(""); const [salesForm, setSalesForm] = useState(defaultSalesForm); const [channelForm, setChannelForm] = useState(defaultChannelForm); const [editSalesForm, setEditSalesForm] = useState(defaultSalesForm); const [editChannelForm, setEditChannelForm] = useState(defaultChannelForm); const [followUpForm, setFollowUpForm] = useState(defaultFollowUpForm); const hasForegroundModal = createOpen || editOpen || followUpOpen; useEffect(() => { let cancelled = false; async function loadMeta() { try { const data = await getExpansionMeta(); if (!cancelled) { setDepartments(data.departments ?? []); } } catch { if (!cancelled) { setDepartments([]); } } } void loadMeta(); return () => { cancelled = true; }; }, []); useEffect(() => { let cancelled = false; async function loadExpansionData() { try { const data = await getExpansionOverview(keyword); if (cancelled) { return; } setSalesData(data.salesItems ?? []); setChannelData(data.channelItems ?? []); setSelectedItem(null); } catch { if (!cancelled) { setSalesData([]); setChannelData([]); setSelectedItem(null); } } } void loadExpansionData(); return () => { cancelled = true; }; }, [keyword, refreshTick]); const followUpRecords: ExpansionFollowUp[] = selectedItem?.followUps ?? []; const handleSalesChange = (key: K, value: CreateSalesExpansionPayload[K]) => { setSalesForm((current) => ({ ...current, [key]: value })); }; const handleChannelChange = (key: K, value: CreateChannelExpansionPayload[K]) => { setChannelForm((current) => ({ ...current, [key]: value })); }; const handleEditSalesChange = (key: K, value: CreateSalesExpansionPayload[K]) => { setEditSalesForm((current) => ({ ...current, [key]: value })); }; const handleEditChannelChange = (key: K, value: CreateChannelExpansionPayload[K]) => { setEditChannelForm((current) => ({ ...current, [key]: value })); }; const handleFollowUpChange = (key: K, value: CreateExpansionFollowUpPayload[K]) => { setFollowUpForm((current) => ({ ...current, [key]: value })); }; const resetCreateState = () => { setCreateOpen(false); setCreateError(""); setSalesForm(defaultSalesForm); setChannelForm(defaultChannelForm); }; const resetEditState = () => { setEditOpen(false); setEditError(""); setEditSalesForm(defaultSalesForm); setEditChannelForm(defaultChannelForm); }; const resetFollowUpState = () => { setFollowUpOpen(false); setFollowUpError(""); setFollowUpForm({ ...defaultFollowUpForm, followUpTime: toDateTimeLocalValue(), }); }; const handleOpenCreate = () => { setCreateError(""); setCreateOpen(true); }; const handleOpenEdit = () => { if (!selectedItem) { return; } setEditError(""); if (selectedItem.type === "sales") { setEditSalesForm({ candidateName: selectedItem.name ?? "", mobile: selectedItem.phone === "无" ? "" : selectedItem.phone ?? "", email: selectedItem.email === "无" ? "" : selectedItem.email ?? "", targetDeptId: selectedItem.targetDeptId, industry: selectedItem.industry === "无" ? "" : selectedItem.industry ?? "", title: selectedItem.title === "无" ? "" : selectedItem.title ?? "", intentLevel: selectedItem.intentLevel ?? "medium", stage: selectedItem.stageCode ?? "initial_contact", hasDesktopExp: Boolean(selectedItem.hasExp), inProgress: Boolean(selectedItem.inProgress), employmentStatus: selectedItem.employmentStatus ?? "active", expectedJoinDate: selectedItem.expectedJoinDate === "无" ? "" : selectedItem.expectedJoinDate ?? "", remark: selectedItem.notes === "无" ? "" : selectedItem.notes ?? "", }); } else { setEditChannelForm({ channelName: selectedItem.name ?? "", province: selectedItem.province === "无" ? "" : selectedItem.province ?? "", industry: selectedItem.industry === "无" ? "" : selectedItem.industry ?? "", annualRevenue: selectedItem.annualRevenue ? Number(selectedItem.annualRevenue) : undefined, staffSize: selectedItem.size ?? undefined, contactName: selectedItem.contact === "无" ? "" : selectedItem.contact ?? "", contactTitle: selectedItem.contactTitle === "无" ? "" : selectedItem.contactTitle ?? "", contactMobile: selectedItem.phone === "无" ? "" : selectedItem.phone ?? "", stage: selectedItem.stageCode ?? "initial_contact", landedFlag: Boolean(selectedItem.landed), expectedSignDate: selectedItem.expectedSignDate === "无" ? "" : selectedItem.expectedSignDate ?? "", remark: selectedItem.notes === "无" ? "" : selectedItem.notes ?? "", }); } setEditOpen(true); }; const handleOpenFollowUp = () => { if (!selectedItem) { return; } setFollowUpError(""); setFollowUpForm({ followUpType: "电话沟通", content: "", nextAction: "", followUpTime: toDateTimeLocalValue(), }); setFollowUpOpen(true); }; const handleCreateSubmit = async () => { if (submitting) { return; } setSubmitting(true); setCreateError(""); try { if (activeTab === "sales") { await createSalesExpansion({ ...salesForm, expectedJoinDate: salesForm.expectedJoinDate || undefined, targetDeptId: salesForm.targetDeptId || undefined, }); } else { await createChannelExpansion({ ...channelForm, annualRevenue: channelForm.annualRevenue || undefined, staffSize: channelForm.staffSize || undefined, expectedSignDate: channelForm.expectedSignDate || undefined, }); } resetCreateState(); setRefreshTick((current) => current + 1); } catch (error) { setCreateError(error instanceof Error ? error.message : "新增失败"); } finally { setSubmitting(false); } }; const handleEditSubmit = async () => { if (!selectedItem || submitting) { return; } setSubmitting(true); setEditError(""); try { if (selectedItem.type === "sales") { await updateSalesExpansion(selectedItem.id, { ...editSalesForm, expectedJoinDate: editSalesForm.expectedJoinDate || undefined, targetDeptId: editSalesForm.targetDeptId || undefined, }); } else { await updateChannelExpansion(selectedItem.id, { ...editChannelForm, annualRevenue: editChannelForm.annualRevenue || undefined, staffSize: editChannelForm.staffSize || undefined, expectedSignDate: editChannelForm.expectedSignDate || undefined, }); } resetEditState(); setSelectedItem(null); setRefreshTick((current) => current + 1); } catch (error) { setEditError(error instanceof Error ? error.message : "编辑失败"); } finally { setSubmitting(false); } }; const handleFollowUpSubmit = async () => { if (!selectedItem || submitting) { return; } setSubmitting(true); setFollowUpError(""); try { await createExpansionFollowUp(selectedItem.type, selectedItem.id, { ...followUpForm, nextAction: followUpForm.nextAction || undefined, followUpTime: new Date(followUpForm.followUpTime).toISOString(), }); resetFollowUpState(); setSelectedItem(null); setRefreshTick((current) => current + 1); } catch (error) { setFollowUpError(error instanceof Error ? error.message : "新增跟进失败"); } finally { setSubmitting(false); } }; const renderEmpty = () => (
暂无
); const handleTabChange = (tab: ExpansionTab) => { setActiveTab(tab); setSelectedItem(null); }; const renderSalesForm = ( form: CreateSalesExpansionPayload, onChange: (key: K, value: CreateSalesExpansionPayload[K]) => void, ) => (