import { Button, Card, Drawer, Form, Input, message, Popconfirm, Space, Table, Tag, Typography, DatePicker, Row, Col, Select } from "antd"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { createTenant, deleteTenant, listTenants, updateTenant } from "../api"; import { usePermission } from "../hooks/usePermission"; import { useDict } from "../hooks/useDict"; import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined, ReloadOutlined, ShopOutlined, CalendarOutlined, PhoneOutlined, UserOutlined } from "@ant-design/icons"; import type { SysTenant } from "../types"; import PageHeader from "../components/shared/PageHeader"; import dayjs from "dayjs"; const { Title, Text } = Typography; export default function Tenants() { const { t } = useTranslation(); const { can } = usePermission(); // Dictionaries const { items: statusDict } = useDict("sys_common_status"); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [data, setData] = useState([]); const [total, setTotal] = useState(0); const [params, setParams] = useState({ current: 1, size: 10, name: "", code: "" }); const [drawerOpen, setDrawerOpen] = useState(false); const [editing, setEditing] = useState(null); const [form] = Form.useForm(); const loadData = async (currentParams = params) => { setLoading(true); try { const result = await listTenants(currentParams); setData(result.records || []); setTotal(result.total || 0); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, [params.current, params.size]); const handleSearch = () => { setParams({ ...params, current: 1 }); loadData({ ...params, current: 1 }); }; const handleReset = () => { const resetParams = { current: 1, size: 10, name: "", code: "" }; setParams(resetParams); loadData(resetParams); }; const openCreate = () => { setEditing(null); form.resetFields(); form.setFieldsValue({ status: 1 }); setDrawerOpen(true); }; const openEdit = (record: SysTenant) => { setEditing(record); form.setFieldsValue({ ...record, expireTime: record.expireTime ? dayjs(record.expireTime) : null }); setDrawerOpen(true); }; const handleDelete = async (id: number) => { try { await deleteTenant(id); message.success(t('common.success')); loadData(); } catch (e) { // Handled by interceptor } }; const submit = async () => { try { const values = await form.validateFields(); setSaving(true); const payload = { ...values, expireTime: values.expireTime ? values.expireTime.format("YYYY-MM-DD HH:mm:ss") : null }; if (editing) { await updateTenant(editing.id, payload); message.success(t('common.success')); } else { await createTenant(payload); message.success(t('common.success')); } setDrawerOpen(false); loadData(); } catch (e) { // Handled by interceptor } finally { setSaving(false); } }; const columns = [ { title: t('tenants.tenantInfo'), key: "tenant", render: (_: any, record: SysTenant) => (
{record.tenantName}
{record.tenantCode}
), }, { title: t('tenants.contact'), key: "contact", render: (_: any, record: SysTenant) => (
{record.contactName || "-"}
{record.contactPhone || "-"}
) }, { title: t('common.status'), dataIndex: "status", width: 100, render: (status: number) => { const item = statusDict.find(i => i.itemValue === String(status)); return ( {item ? item.itemLabel : (status === 1 ? "正常" : "禁用")} ); }, }, { title: t('tenants.expireTime'), dataIndex: "expireTime", width: 180, render: (text: string) => ( {text ? text.substring(0, 10) : t('tenants.forever')} ) }, { title: t('common.action'), key: "action", width: 120, fixed: "right" as const, render: (_: any, record: SysTenant) => ( {can("sys_tenant:update") && ( )} /> } style={{ width: 200 }} value={params.name} onChange={e => setParams({ ...params, name: e.target.value })} allowClear /> setParams({ ...params, code: e.target.value })} allowClear /> setParams({ ...params, current: page, size }), showTotal: (total) => t('common.total', { total }) }} />