import React, { useEffect, useState } from 'react'; import { Button, Card, Drawer, Input, message, Modal, Popconfirm, Select, Space, Table, Tag, Typography } from 'antd'; import { CopyOutlined, EyeOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons'; import dayjs from 'dayjs'; import { createModelPricingRule, disableModelPricingRule, getModelPricingRules, publishModelPricingRule, updateModelPricingRule, } from '../api'; import type { ModelPricingRule, ModelPricingRulePayload } from '../types'; import PricingRuleForm from '../components/modelPricing/PricingRuleForm'; import PricingRulePreview from '../components/modelPricing/PricingRulePreview'; import { formatDate } from '../utils/formatDate'; const statusMap: Record = { draft: { color: 'default', text: '草稿' }, published: { color: 'green', text: '已发布' }, disabled: { color: 'red', text: '已停用' }, }; const modeMap: Record = { text_token_tiered: '文本分档 Token', image_per_output: '按成功输出图片', image_input_output_tiered: '输入图 + 输出像素', video_token_rate: '视频 Token', }; const AdminModelPricingRules: React.FC = () => { const [rows, setRows] = useState([]); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(50); const [modelName, setModelName] = useState(''); const [status, setStatus] = useState(''); const [category, setCategory] = useState(''); const [editing, setEditing] = useState(null); const [formOpen, setFormOpen] = useState(false); const [detail, setDetail] = useState(null); const load = async () => { setLoading(true); try { const res = await getModelPricingRules({ page, pageSize, modelName: modelName || undefined, publishStatus: status || undefined, modelCategory: category || undefined, }); setRows(res.items || []); setTotal(res.total || 0); } catch (e: any) { message.error(e?.message || '加载模型计价规则失败'); } finally { setLoading(false); } }; useEffect(() => { load(); }, [page, pageSize, modelName, status, category]); const submit = async (payload: ModelPricingRulePayload) => { setSaving(true); try { if (editing?.id && editing.publishStatus === 'draft') { await updateModelPricingRule(editing.id, payload); } else { await createModelPricingRule(payload); } message.success('价格草稿已保存'); setFormOpen(false); setEditing(null); await load(); } catch (e: any) { message.error(e?.message || '保存失败'); } finally { setSaving(false); } }; const cloneRule = (rule: ModelPricingRule) => { setEditing({ ...rule, id: '', publishStatus: 'draft', versionCode: `${rule.versionCode}_copy_${dayjs().format('YYYYMMDDHHmm')}`, effectiveFrom: dayjs().add(1, 'minute').toISOString(), effectiveTo: null, referencedCount: 0, }); setFormOpen(true); }; const columns = [ { title: '模型', dataIndex: 'modelName', width: 280, fixed: 'left' as const, render: (v: string, r: ModelPricingRule) =>
{v}
{r.provider} / {r.modelCategory}
}, { title: '价格版本', dataIndex: 'versionCode', width: 180 }, { title: '计价模式/计算器', key: 'calculator', width: 230, render: (_: any, r: ModelPricingRule) =>
{modeMap[r.billingMode] || r.billingMode}
{r.calculatorVersion}
}, { title: '生效时间', key: 'effective', width: 290, render: (_: any, r: ModelPricingRule) =>
{formatDate(r.effectiveFrom)}
至 {r.effectiveTo ? formatDate(r.effectiveTo) : '长期有效'}
}, { title: '状态', dataIndex: 'publishStatus', width: 100, render: (v: string) => {(statusMap[v] || {}).text || v} }, { title: '规则Hash/引用', key: 'hash', width: 190, render: (_: any, r: ModelPricingRule) =>
{r.ruleContentHash ? `${r.ruleContentHash.slice(0, 12)}…` : '-'}
{r.referencedCount || 0} 条引用
}, { title: '来源更新时间', dataIndex: 'sourceUpdatedAt', width: 170, render: (v: string) => v ? formatDate(v) : '-' }, { title: '操作', key: 'action', width: 310, fixed: 'right' as const, render: (_: any, r: ModelPricingRule) => {r.publishStatus === 'draft' && } {r.publishStatus === 'draft' && { await publishModelPricingRule(r.id); message.success('已发布'); load(); }}>} {r.publishStatus === 'published' && { await disableModelPricingRule(r.id); message.success('已停用'); load(); }}>} }, ]; return
{ setPage(1); setModelName(e.target.value); }} style={{ width: 260 }} /> { setPage(1); setStatus(v); }} style={{ width: 130 }} options={[{ value: '', label: '全部状态' }, { value: 'draft', label: '草稿' }, { value: 'published', label: '已发布' }, { value: 'disabled', label: '已停用' }]} />
{ setPage(p); setPageSize(ps); } }} /> { setFormOpen(false); setEditing(null); }}> { setFormOpen(false); setEditing(null); }} /> setDetail(null)}> {detail && <> {detail.provider}{detail.modelCategory}{modeMap[detail.billingMode] || detail.billingMode}{(statusMap[detail.publishStatus] || {}).text} 生效:{formatDate(detail.effectiveFrom)} ~ {detail.effectiveTo ? formatDate(detail.effectiveTo) : '长期有效'}
计算器:{detail.calculatorVersion}
规则 Hash:{detail.ruleContentHash || '-'}
来源:{detail.sourceUrl || '-'}
官方更新时间:{detail.sourceUpdatedAt ? formatDate(detail.sourceUpdatedAt) : '-'}
{JSON.stringify(detail.ruleJson, null, 2)}
}
; }; export default AdminModelPricingRules;