import { useState } from 'react'; import { Button, Field, Input, Select, Textarea } from '../components/ui.jsx'; import { Icon, PageTitle, Toolbar, Panel, ApiNotice, Modal, ConfirmDialog, SimpleTable, KeyValue } from '../components/layout.jsx'; import { gateways } from '../fixtures/devFixtures.js'; import { explainApiError } from '../api.js'; export function CustomersPage({ customerRows, setCustomerRows, addRechargeRecord, apiLoading, apiError, refreshApi, can = () => true, onCreateCustomer, onUpdateCustomer, onToggleCustomerStatus, onDeleteCustomer, onRechargeCustomer }) { const [showCreateCustomer, setShowCreateCustomer] = useState(false); const [editingCustomer, setEditingCustomer] = useState(null); const [rechargeCustomer, setRechargeCustomer] = useState(null); const [deleteCustomerTarget, setDeleteCustomerTarget] = useState(null); const [statusCustomerTarget, setStatusCustomerTarget] = useState(null); const [newCustomer, setNewCustomer] = useState({ name: '', contact: '', phone: '', email: '' }); const [editCustomerForm, setEditCustomerForm] = useState({ name: '', contact: '', phone: '', email: '' }); const [rechargeForm, setRechargeForm] = useState({ amount: '', remark: '' }); const [actionError, setActionError] = useState(''); const canManageCustomers = can('customers.manage'); const canManageRecharges = can('recharges.manage'); const openEditCustomer = (customer) => { setEditingCustomer(customer); setEditCustomerForm({ name: customer.name || '', contact: customer.contact === '-' ? '' : customer.contact || '', phone: customer.phone === '-' ? '' : customer.phone || '', email: customer.email === '-' ? '' : customer.email || '', }); }; const closeEditCustomer = () => { setEditingCustomer(null); setEditCustomerForm({ name: '', contact: '', phone: '', email: '' }); }; const openRechargeCustomer = (customer) => { setRechargeCustomer(customer); setRechargeForm({ amount: '', remark: '' }); }; const closeRechargeCustomer = () => { setRechargeCustomer(null); setRechargeForm({ amount: '', remark: '' }); }; const parseMoney = (value) => Number(String(value).replace(/[^\d.-]/g, '')) || 0; const formatMoney = (value) => `¥${value.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; const submitCustomer = async (event) => { event.preventDefault(); if (!newCustomer.name.trim()) return; setActionError(''); try { if (onCreateCustomer) { await onCreateCustomer({ name: newCustomer.name.trim(), contactName: newCustomer.contact.trim() || undefined, phone: newCustomer.phone.trim() || undefined, email: newCustomer.email.trim() || undefined, billingMode: 'PREPAID', creditLimit: '0.000000', minBalance: '0.000000', }); } else { const nextIndex = customerRows.length + 1; setCustomerRows([...customerRows, { id: `C${String(1000 + nextIndex)}`, name: newCustomer.name.trim(), contact: newCustomer.contact.trim() || '-', phone: newCustomer.phone.trim() || '-', email: newCustomer.email.trim() || '-', domain: '-', auth: '待配置', status: '启用', balance: '¥0.00', credit: '¥0', billing: '待配置', routeGroup: '待配置', gateways: 0, createdAt: '2026-06-18' }]); } setNewCustomer({ name: '', contact: '', phone: '', email: '' }); setShowCreateCustomer(false); } catch (error) { setActionError(explainApiError(error)); } }; const submitEditCustomer = async (event) => { event.preventDefault(); if (!editCustomerForm.name.trim() || !editingCustomer) return; setActionError(''); try { if (onUpdateCustomer) { await onUpdateCustomer(editingCustomer.id, { name: editCustomerForm.name.trim(), contactName: editCustomerForm.contact.trim() || null, phone: editCustomerForm.phone.trim() || null, email: editCustomerForm.email.trim() || null, }); } else { setCustomerRows(customerRows.map((customer) => ( customer.id === editingCustomer.id ? { ...customer, name: editCustomerForm.name.trim(), contact: editCustomerForm.contact.trim() || '-', phone: editCustomerForm.phone.trim() || '-', email: editCustomerForm.email.trim() || '-' } : customer ))); } closeEditCustomer(); } catch (error) { setActionError(explainApiError(error)); } }; const submitRecharge = async (event) => { event.preventDefault(); const amount = Number(rechargeForm.amount); if (!rechargeCustomer || !Number.isFinite(amount) || amount <= 0) return; setActionError(''); try { if (onRechargeCustomer) { await onRechargeCustomer(rechargeCustomer.id, { amount: amount.toFixed(2), remark: rechargeForm.remark.trim() || undefined, }); } else { const beforeBalance = parseMoney(rechargeCustomer.balance); const afterBalance = beforeBalance + amount; setCustomerRows(customerRows.map((customer) => ( customer.id === rechargeCustomer.id ? { ...customer, balance: formatMoney(afterBalance) } : customer ))); addRechargeRecord({ id: `RCG-${Date.now()}`, type: 'customer', owner: rechargeCustomer.name, amount: formatMoney(amount), beforeBalance: formatMoney(beforeBalance), afterBalance: formatMoney(afterBalance), remark: rechargeForm.remark.trim() || '-', operator: '运营管理员', time: new Date().toLocaleString('zh-CN', { hour12: false }), status: '成功' }); } closeRechargeCustomer(); } catch (error) { setActionError(explainApiError(error)); } }; const deleteCustomer = async (customer) => { setActionError(''); try { if (onDeleteCustomer) { await onDeleteCustomer(customer.id); } else { if ((customer.gateways ?? 0) > 0) { throw new Error('该客户仍有关联客户网关,不能删除。'); } setCustomerRows((rows) => rows.filter((item) => item.id !== customer.id)); } setDeleteCustomerTarget(null); } catch (error) { setActionError(explainApiError(error)); } }; const toggleCustomerStatus = async (customer) => { setActionError(''); try { if (onToggleCustomerStatus) { await onToggleCustomerStatus(customer); } else { setCustomerRows((rows) => rows.map((item) => ( item.id === customer.id ? { ...item, status: item.status === '启用' ? '停用' : '启用' } : item ))); } setStatusCustomerTarget(null); } catch (error) { setActionError(explainApiError(error)); } }; return ( <> } onClick={() => setShowCreateCustomer(true)}>新增客户 : null} /> 全部状态启用停用 }>查询 ( {canManageCustomers ? openEditCustomer(row)}>编辑 : null} {canManageRecharges ? openRechargeCustomer(row)}>充值 : null} {canManageCustomers ? ( setStatusCustomerTarget(row)}> {row.status === '启用' ? '禁用' : '启用'} ) : null} {canManageCustomers ? setDeleteCustomerTarget(row)}>删除 : null} {!canManageCustomers && !canManageRecharges ? '-' : null} ), }, ]} /> {showCreateCustomer ? ( setShowCreateCustomer(false)} size="sm"> 客户名称 *}> setNewCustomer({ ...newCustomer, name: event.target.value })} placeholder="请输入企业名称" required /> setNewCustomer({ ...newCustomer, contact: event.target.value })} placeholder="请输入联系人" /> setNewCustomer({ ...newCustomer, phone: event.target.value })} placeholder="请输入联系电话" /> setNewCustomer({ ...newCustomer, email: event.target.value })} placeholder="请输入邮箱" /> setShowCreateCustomer(false)}>取消 保存客户 ) : null} {rechargeCustomer ? ( 充值金额 *}> setRechargeForm({ ...rechargeForm, amount: event.target.value })} placeholder="请输入充值金额" required /> setRechargeForm({ ...rechargeForm, remark: event.target.value })} placeholder="请输入备注" /> 取消 确认充值 ) : null} {editingCustomer ? ( 客户名称 *}> setEditCustomerForm({ ...editCustomerForm, name: event.target.value })} placeholder="请输入客户名称" required /> setEditCustomerForm({ ...editCustomerForm, contact: event.target.value })} placeholder="请输入联系人" /> setEditCustomerForm({ ...editCustomerForm, phone: event.target.value })} placeholder="请输入联系电话" /> setEditCustomerForm({ ...editCustomerForm, email: event.target.value })} placeholder="请输入邮箱" /> 取消 保存修改 ) : null} {deleteCustomerTarget ? ( setDeleteCustomerTarget(null)} onConfirm={() => void deleteCustomer(deleteCustomerTarget)} > 确认删除客户「{deleteCustomerTarget.name}」吗?删除后该客户将不再出现在客户列表中。 ) : null} {statusCustomerTarget ? ( setStatusCustomerTarget(null)} onConfirm={() => void toggleCustomerStatus(statusCustomerTarget)} > 确认{statusCustomerTarget.status === '启用' ? '禁用' : '启用'}客户「{statusCustomerTarget.name}」吗? ) : null} > ); }
确认删除客户「{deleteCustomerTarget.name}」吗?删除后该客户将不再出现在客户列表中。
确认{statusCustomerTarget.status === '启用' ? '禁用' : '启用'}客户「{statusCustomerTarget.name}」吗?