Split customer management modules

This commit is contained in:
hectorzhao
2026-06-30 17:24:12 +08:00
parent 2f3c274a30
commit b2e42ebd82
7 changed files with 1587 additions and 8 deletions
@@ -0,0 +1,189 @@
import { useMemo, useState } from 'react';
import { Edit3, Plus, Trash2 } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import { Button, Modal, Table, Tabs, Tag, type TableColumn } from '@/components/ui';
type SmsApp = {
id: string;
name: string;
enterprise: string;
appId: string;
enabled: boolean;
sentToday: number;
deliveryRate: number;
unitPrice: number;
cmppStatus: 'connected' | 'disconnected' | 'inactive';
};
type MmsApp = Omit<SmsApp, 'cmppStatus'> & {
pointPrice: number;
};
type AppKind = 'sms' | 'mms';
const initialSmsApps: SmsApp[] = [
{ id: 'app-1', name: '营销推广平台', enterprise: '上海XXXXX科技有限公司', appId: 'AK_2024010912345678', enabled: true, sentToday: 1500, deliveryRate: 95, unitPrice: 0.05, cmppStatus: 'connected' },
{ id: 'app-2', name: '客户服务系统', enterprise: '重庆进载数智', appId: 'AK_2024010987654321', enabled: true, sentToday: 800, deliveryRate: 90, unitPrice: 0.06, cmppStatus: 'disconnected' },
{ id: 'app-3', name: '验证码服务', enterprise: '超感世纪互三网', appId: 'AK_2024010811223344', enabled: false, sentToday: 0, deliveryRate: 0, unitPrice: 0.04, cmppStatus: 'inactive' },
];
const initialMmsApps: MmsApp[] = [
{ id: 'mms-app-1', name: '营销活动彩信', enterprise: '上海XXXXX科技有限公司', appId: 'MMS_2024020112345678', enabled: true, sentToday: 320, deliveryRate: 92, unitPrice: 0.15, pointPrice: 50 },
{ id: 'mms-app-2', name: '节日祝福彩信', enterprise: '重庆进载数智', appId: 'MMS_2024020187654321', enabled: true, sentToday: 180, deliveryRate: 88, unitPrice: 0.12, pointPrice: 30 },
{ id: 'mms-app-3', name: '会员权益彩信', enterprise: '四川骠骑企业管理', appId: 'MMS_2024020199001122', enabled: false, sentToday: 0, deliveryRate: 0, unitPrice: 0.18, pointPrice: 60 },
];
function enabledTag(enabled: boolean) {
return <Tag tone={enabled ? 'success' : 'neutral'}>{enabled ? '启用' : '停用'}</Tag>;
}
function ConfirmModal({ message, danger, onCancel, onConfirm }: { message: string; danger?: boolean; onCancel: () => void; onConfirm: () => void }) {
return (
<Modal
footer={(
<>
<Button onClick={onCancel} variant="ghost"></Button>
<Button onClick={onConfirm} variant={danger ? 'danger' : 'primary'}></Button>
</>
)}
onClose={onCancel}
open
title="操作确认"
>
<p className="admin-confirm-text">{message}</p>
</Modal>
);
}
export function AdminEnterpriseApplicationsPage() {
const navigate = useNavigate();
const [smsApps, setSmsApps] = useState(initialSmsApps);
const [mmsApps, setMmsApps] = useState(initialMmsApps);
const [confirmAction, setConfirmAction] = useState<
| { action: 'toggle'; kind: AppKind; id: string; name: string; enabled: boolean }
| { action: 'delete'; kind: AppKind; id: string; name: string }
| null
>(null);
function confirmToggle(kind: AppKind, id: string) {
if (kind === 'sms') {
setSmsApps((current) => current.map((item) => item.id === id ? { ...item, enabled: !item.enabled } : item));
return;
}
setMmsApps((current) => current.map((item) => item.id === id ? { ...item, enabled: !item.enabled } : item));
}
function confirmDelete(kind: AppKind, id: string) {
if (kind === 'sms') {
setSmsApps((current) => current.filter((item) => item.id !== id));
} else {
setMmsApps((current) => current.filter((item) => item.id !== id));
}
}
function runConfirmedAction() {
if (!confirmAction) {
return;
}
if (confirmAction.action === 'toggle') {
confirmToggle(confirmAction.kind, confirmAction.id);
} else {
confirmDelete(confirmAction.kind, confirmAction.id);
}
setConfirmAction(null);
}
const smsColumns = useMemo<Array<TableColumn<SmsApp>>>(() => [
{ key: 'name', title: '应用名称', width: '180px', render: (record) => <strong>{record.name}</strong> },
{ key: 'enterprise', title: '企业名称', width: '220px', render: (record) => record.enterprise },
{ key: 'appId', title: 'AppID', width: '220px', render: (record) => record.appId },
{ key: 'sentToday', title: '今日发送', width: '120px', render: (record) => `${record.sentToday.toLocaleString('zh-CN')}` },
{ key: 'deliveryRate', title: '到达率', width: '110px', render: (record) => `${record.deliveryRate}%` },
{ key: 'unitPrice', title: '单价', width: '100px', render: (record) => `${record.unitPrice.toFixed(3)}` },
{
key: 'cmppStatus',
title: 'CMPP状态',
width: '130px',
render: (record) => (
<Tag tone={record.cmppStatus === 'connected' ? 'success' : record.cmppStatus === 'disconnected' ? 'danger' : 'neutral'}>
{record.cmppStatus === 'connected' ? '已连接' : record.cmppStatus === 'disconnected' ? '已断开' : '未开通'}
</Tag>
),
},
{ key: 'enabled', title: '状态', width: '100px', render: (record) => enabledTag(record.enabled) },
{
key: 'actions',
title: '操作',
align: 'right',
width: '190px',
render: (record) => (
<div className="table-actions">
<Button icon={<Edit3 size={15} />} onClick={() => navigate(`/admin/customers/2763/sms-apps/${record.id}/edit`)} size="sm" variant="ghost"></Button>
<Button onClick={() => setConfirmAction({ action: 'toggle', kind: 'sms', id: record.id, name: record.name, enabled: record.enabled })} size="sm" variant="secondary">
{record.enabled ? '停用' : '启用'}
</Button>
<Button icon={<Trash2 size={15} />} onClick={() => setConfirmAction({ action: 'delete', kind: 'sms', id: record.id, name: record.name })} size="sm" variant="danger"></Button>
</div>
),
},
], [navigate]);
const mmsColumns = useMemo<Array<TableColumn<MmsApp>>>(() => [
{ key: 'name', title: '应用名称', width: '180px', render: (record) => <strong>{record.name}</strong> },
{ key: 'enterprise', title: '企业名称', width: '220px', render: (record) => record.enterprise },
{ key: 'appId', title: 'AppID', width: '220px', render: (record) => record.appId },
{ key: 'sentToday', title: '今日发送', width: '120px', render: (record) => `${record.sentToday.toLocaleString('zh-CN')}` },
{ key: 'deliveryRate', title: '到达率', width: '110px', render: (record) => `${record.deliveryRate}%` },
{ key: 'unitPrice', title: '单价', width: '100px', render: (record) => `${record.unitPrice.toFixed(3)}` },
{ key: 'pointPrice', title: '点数', width: '100px', render: (record) => `${record.pointPrice}` },
{ key: 'enabled', title: '状态', width: '100px', render: (record) => enabledTag(record.enabled) },
{
key: 'actions',
title: '操作',
align: 'right',
width: '190px',
render: (record) => (
<div className="table-actions">
<Button icon={<Edit3 size={15} />} onClick={() => navigate(`/admin/customers/2763/mms-apps/${record.id}/edit`)} size="sm" variant="ghost"></Button>
<Button onClick={() => setConfirmAction({ action: 'toggle', kind: 'mms', id: record.id, name: record.name, enabled: record.enabled })} size="sm" variant="secondary">
{record.enabled ? '停用' : '启用'}
</Button>
<Button icon={<Trash2 size={15} />} onClick={() => setConfirmAction({ action: 'delete', kind: 'mms', id: record.id, name: record.name })} size="sm" variant="danger"></Button>
</div>
),
},
], [navigate]);
return (
<section className="page-stack admin-customer-split-page">
<div className="page-heading">
<div>
<div className="breadcrumb-line"> / <strong></strong></div>
<h1></h1>
</div>
<Button icon={<Plus size={16} />} onClick={() => navigate('/admin/customers/2763/sms-apps/new')}></Button>
</div>
<div className="surface section-stack">
<Tabs
items={[
{ label: '短信应用', value: 'sms', content: <Table columns={smsColumns} data={smsApps} rowKey="id" /> },
{ label: '彩信应用', value: 'mms', content: <Table columns={mmsColumns} data={mmsApps} rowKey="id" /> },
]}
/>
</div>
{confirmAction ? (
<ConfirmModal
danger={confirmAction.action === 'delete'}
message={confirmAction.action === 'delete'
? `确认删除应用“${confirmAction.name}”吗?`
: `确认${confirmAction.enabled ? '停用' : '启用'}应用“${confirmAction.name}”吗?`}
onCancel={() => setConfirmAction(null)}
onConfirm={runConfirmedAction}
/>
) : null}
</section>
);
}