diff --git a/web/src/pages/admin/Tenants.tsx b/web/src/pages/admin/Tenants.tsx index a0a05ef..9f0d836 100644 --- a/web/src/pages/admin/Tenants.tsx +++ b/web/src/pages/admin/Tenants.tsx @@ -1,6 +1,131 @@ -const Tenants = () => ( -
-
租户管理
开发中...
-
-) +import { useState } from 'react' +import { Table, Input, Select, Tag, Button, Drawer, Form, InputNumber, Switch, Space, message, Popconfirm, Descriptions } from 'antd' +import { PlusOutlined, SearchOutlined, EditOutlined, ReloadOutlined, PauseCircleOutlined, EyeOutlined } from '@ant-design/icons' + +interface Tenant { + id: string + name: string + contact: string + phone: string + email: string + plan: string + seats: number + startDate: string + expireDate: string + status: 'normal' | 'expiring' | 'suspended' | 'expired' +} + +const mockTenants: Tenant[] = [ + { id: '1', name: '赵六科技', contact: '赵总', phone: '138****1111', email: 'zhao@tech.com', plan: '企业版', seats: 30, startDate: '2026-01-15', expireDate: '2027-01-15', status: 'normal' }, + { id: '2', name: '李四商贸', contact: '李经理', phone: '139****2222', email: 'li@trade.com', plan: '专业版', seats: 10, startDate: '2026-03-01', expireDate: '2026-09-01', status: 'normal' }, + { id: '3', name: '王五集团', contact: '王总', phone: '137****3333', email: 'wang@group.com', plan: '企业版', seats: 50, startDate: '2025-06-01', expireDate: '2026-07-20', status: 'expiring' }, + { id: '4', name: '孙八信息', contact: '孙经理', phone: '136****4444', email: 'sun@info.com', plan: '基础版', seats: 2, startDate: '2026-04-01', expireDate: '2027-04-01', status: 'suspended' }, + { id: '5', name: '周九科技', contact: '周总', phone: '135****5555', email: 'zhou@tech.com', plan: '专业版', seats: 8, startDate: '2025-01-01', expireDate: '2026-06-30', status: 'expired' }, + { id: '6', name: '吴十教育', contact: '吴校长', phone: '134****6666', email: 'wu@edu.com', plan: '基础版', seats: 3, startDate: '2026-07-01', expireDate: '2027-07-01', status: 'normal' }, + { id: '7', name: '郑十一医疗', contact: '郑主任', phone: '133****7777', email: 'zheng@med.com', plan: '企业版', seats: 20, startDate: '2026-05-15', expireDate: '2026-08-15', status: 'expiring' }, +] + +const statusConfig: Record = { + normal: { color: 'green', text: '正常' }, + expiring: { color: 'orange', text: '即将到期' }, + suspended: { color: 'red', text: '已暂停' }, + expired: { color: 'default', text: '已过期' }, +} + +const Tenants = () => { + const [search, setSearch] = useState('') + const [statusFilter, setStatusFilter] = useState() + const [planFilter, setPlanFilter] = useState() + const [drawerOpen, setDrawerOpen] = useState(false) + const [detailOpen, setDetailOpen] = useState(false) + const [selectedTenant, setSelectedTenant] = useState(null) + const [form] = Form.useForm() + + const filtered = mockTenants.filter(t => { + if (search && !t.name.includes(search) && !t.contact.includes(search)) return false + if (statusFilter && t.status !== statusFilter) return false + if (planFilter && t.plan !== planFilter) return false + return true + }) + + const columns = [ + { title: '公司名称', dataIndex: 'name', key: 'name', render: (text: string) => {text} }, + { title: '联系人', dataIndex: 'contact', key: 'contact' }, + { title: '手机号', dataIndex: 'phone', key: 'phone', render: (t: string) => {t} }, + { title: '套餐', dataIndex: 'plan', key: 'plan', render: (p: string) => {p} }, + { title: '坐席数', dataIndex: 'seats', key: 'seats', align: 'center' as const }, + { title: '开通日期', dataIndex: 'startDate', key: 'startDate', render: (t: string) => {t} }, + { title: '到期日期', dataIndex: 'expireDate', key: 'expireDate', render: (t: string) => {t} }, + { title: '状态', dataIndex: 'status', key: 'status', render: (s: string) => {statusConfig[s].text} }, + { title: '操作', key: 'actions', width: 220, render: (_: unknown, record: Tenant) => ( + + + + {record.status === 'normal' && ( + e?.stopPropagation()} onCancel={(e) => e?.stopPropagation()}> + + + )} + {(record.status === 'suspended' || record.status === 'expired') && ( + + )} + + )}, + ] + + return ( +
+
+

租户管理

+ +
+ +
+ } placeholder="搜索公司名称或联系人" value={search} onChange={e => setSearch(e.target.value)} className="w-56" allowClear /> + ({ value: v, label: v }))} /> +
+ +
+ `共 ${t} 个租户` }} /> + + + {/* 开通新账号 */} + setDrawerOpen(false)} width={480}> +
{ setDrawerOpen(false); message.success('租户开通成功') }}> + + + + + +