实现套餐管理页面:三档套餐卡片、权益对比表、定价规则、上架/下架
This commit is contained in:
@@ -1,6 +1,122 @@
|
||||
const Plans = () => (
|
||||
<div className="h-full flex items-center justify-center text-neutral-400 text-center">
|
||||
<div><div className="text-lg mb-1">套餐管理</div><div className="text-sm">开发中...</div></div>
|
||||
</div>
|
||||
)
|
||||
import { Card, Tag, Switch, Button, Table, message } from 'antd'
|
||||
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'
|
||||
|
||||
const plans = [
|
||||
{
|
||||
key: 'basic', name: '基础版', price: 299, color: '#64748b',
|
||||
features: { seats: '2 坐席', history: '30 天', knowledge: '50 条', stats: '基础报表', api: false, channels: ['网页'], brand: false, dedicated: false },
|
||||
tenants: 68, active: true,
|
||||
},
|
||||
{
|
||||
key: 'pro', name: '专业版', price: 699, color: '#2563eb', recommended: true,
|
||||
features: { seats: '10 坐席', history: '180 天', knowledge: '500 条', stats: '高级报表', api: true, channels: ['网页', '微信', 'APP'], brand: true, dedicated: false },
|
||||
tenants: 52, active: true,
|
||||
},
|
||||
{
|
||||
key: 'enterprise', name: '企业版', price: 1999, color: '#7c3aed',
|
||||
features: { seats: '50(可扩展)', history: '永久', knowledge: '不限', stats: '自定义报表', api: true, channels: ['全渠道'], brand: true, dedicated: true },
|
||||
tenants: 36, active: true,
|
||||
},
|
||||
]
|
||||
|
||||
const compareData = [
|
||||
{ label: '月费', basic: '¥299/月', pro: '¥699/月', enterprise: '¥1999/月' },
|
||||
{ label: '坐席数量', basic: '2', pro: '10', enterprise: '50(可扩展)' },
|
||||
{ label: '对话记录保存', basic: '30 天', pro: '180 天', enterprise: '永久' },
|
||||
{ label: '知识库容量', basic: '50 条', pro: '500 条', enterprise: '不限' },
|
||||
{ label: '数据统计', basic: '基础报表', pro: '高级报表', enterprise: '自定义报表' },
|
||||
{ label: 'API 接口', basic: '不支持', pro: '基础 API', enterprise: '完整 API' },
|
||||
{ label: '渠道', basic: '网页', pro: '网页+微信+APP', enterprise: '全渠道' },
|
||||
{ label: '自定义品牌', basic: '不支持', pro: '支持', enterprise: '支持' },
|
||||
{ label: '专属客服', basic: '不支持', pro: '不支持', enterprise: '支持' },
|
||||
]
|
||||
|
||||
const Plans = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-5">
|
||||
<h2 className="text-lg font-semibold text-neutral-800">套餐管理</h2>
|
||||
<Button type="primary" onClick={() => message.success('保存成功')}>保存配置</Button>
|
||||
</div>
|
||||
|
||||
{/* 套餐卡片 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-5 mb-8">
|
||||
{plans.map(plan => (
|
||||
<Card
|
||||
key={plan.key}
|
||||
className={`!rounded-xl ${plan.recommended ? 'ring-2 ring-blue-500 shadow-lg' : ''}`}
|
||||
bordered={false}
|
||||
title={
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-base font-semibold" style={{ color: plan.color }}>{plan.name}</span>
|
||||
{plan.recommended && <Tag color="blue" className="text-xs">推荐</Tag>}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="text-center mb-4">
|
||||
<span className="text-3xl font-bold text-neutral-800">¥{plan.price}</span>
|
||||
<span className="text-sm text-neutral-400">/月</span>
|
||||
</div>
|
||||
<div className="space-y-2.5 mb-4">
|
||||
{[
|
||||
{ label: '坐席数量', value: plan.features.seats },
|
||||
{ label: '对话记录', value: plan.features.history },
|
||||
{ label: '知识库', value: plan.features.knowledge },
|
||||
{ label: '统计报表', value: plan.features.stats },
|
||||
{ label: 'API 接口', value: plan.features.api ? '支持' : '不支持' },
|
||||
{ label: '渠道', value: plan.features.channels.join('、') },
|
||||
{ label: '自定义品牌', value: plan.features.brand ? '支持' : '不支持' },
|
||||
{ label: '专属客服', value: plan.features.dedicated ? '支持' : '不支持' },
|
||||
].map((item, i) => (
|
||||
<div key={i} className="flex justify-between text-sm">
|
||||
<span className="text-neutral-400">{item.label}</span>
|
||||
<span className="text-neutral-700 font-medium">{item.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center justify-between pt-3 border-t border-neutral-100">
|
||||
<span className="text-sm text-neutral-400">{plan.tenants} 个租户使用</span>
|
||||
<Switch defaultChecked={plan.active} checkedChildren="上架" unCheckedChildren="下架" />
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 对比表 */}
|
||||
<Card title="套餐权益对比" className="!rounded-lg" bordered={false}>
|
||||
<Table
|
||||
dataSource={compareData}
|
||||
rowKey="label"
|
||||
pagination={false}
|
||||
size="middle"
|
||||
columns={[
|
||||
{ title: '权益项', dataIndex: 'label', key: 'label', width: 160, render: (t: string) => <span className="font-medium text-neutral-700">{t}</span> },
|
||||
{ title: '基础版', dataIndex: 'basic', key: 'basic', render: (t: string) => <RenderCell text={t} /> },
|
||||
{ title: '专业版', dataIndex: 'pro', key: 'pro', render: (t: string) => <RenderCell text={t} /> },
|
||||
{ title: '企业版', dataIndex: 'enterprise', key: 'enterprise', render: (t: string) => <RenderCell text={t} /> },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* 定价规则 */}
|
||||
<Card title="定价规则" className="!rounded-lg mt-4" bordered={false}>
|
||||
<ul className="text-sm text-neutral-600 space-y-2 ml-4">
|
||||
<li>按月订阅,年付享受 <span className="text-blue-600 font-medium">8 折</span> 优惠</li>
|
||||
<li>超出套餐坐席按 <span className="text-blue-600 font-medium">¥49/月/坐席</span> 额外计费</li>
|
||||
<li>下架后新租户不可购买该套餐,已购买租户可正常续费</li>
|
||||
<li>企业版支持自定义报价,请联系销售团队</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function RenderCell({ text }: { text: string }) {
|
||||
if (text === '不支持') return <CloseCircleOutlined className="text-neutral-300" />
|
||||
if (text === '支持') return <CheckCircleOutlined className="text-green-500" />
|
||||
return <span className="text-sm text-neutral-600">{text}</span>
|
||||
}
|
||||
|
||||
export default Plans
|
||||
|
||||
Reference in New Issue
Block a user