import { useEffect, useState } from 'react'; import { Button, Form, Image, Input, InputNumber, Modal, Popconfirm, Select, Space, Table, Tag, Typography, message, } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { request, type Paginated } from '../lib/api'; import { MEDIA_TYPE_LABELS, RESOURCE_BIZ_TYPE_LABELS, RESOURCE_OWNER_TYPE_LABELS, RESOURCE_STATUS_LABELS, fmtTime, } from '../lib/constants'; import OssUpload from '../components/OssUpload'; type Row = { id: string; ownerType: string; ownerId: string; bizType: string; mediaType: string; ossBucket: string; ossKey: string; url: string; fileName?: string | null; sortOrder: number; status: string; createdAt: string; }; export default function ResourcesPage() { const [form] = Form.useForm(); const [createForm] = Form.useForm(); const [filters, setFilters] = useState>({}); const [data, setData] = useState | null>(null); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(20); const [createOpen, setCreateOpen] = useState(false); const [saving, setSaving] = useState(false); async function reload(p = page, ps = pageSize, f = filters) { setLoading(true); try { const qs = new URLSearchParams({ page: String(p), pageSize: String(ps) }); if (f.ownerType) qs.set('ownerType', f.ownerType); if (f.ownerId) qs.set('ownerId', f.ownerId); if (f.bizType) qs.set('bizType', f.bizType); if (f.status) qs.set('status', f.status); const res = await request>(`/common/resources?${qs}`); setData(res); } finally { setLoading(false); } } useEffect(() => { void reload(); }, []); const columns: ColumnsType = [ { title: 'ID', dataIndex: 'id', width: 80 }, { title: '归属', width: 140, render: (_, row) => ( {RESOURCE_OWNER_TYPE_LABELS[row.ownerType] || row.ownerType} / {row.ownerId} ), }, { title: '用途', dataIndex: 'bizType', width: 90, render: (v) => RESOURCE_BIZ_TYPE_LABELS[v] || v }, { title: '类型', dataIndex: 'mediaType', width: 70, render: (v) => MEDIA_TYPE_LABELS[v] || v }, { title: '预览', dataIndex: 'url', width: 90, render: (url, row) => row.mediaType === 'IMAGE' ? ( ) : ( 查看 ), }, { title: 'URL', dataIndex: 'url', ellipsis: true }, { title: 'OSS Key', dataIndex: 'ossKey', ellipsis: true, width: 160 }, { title: '排序', dataIndex: 'sortOrder', width: 60 }, { title: '状态', dataIndex: 'status', width: 80, render: (s) => {RESOURCE_STATUS_LABELS[s] || s}, }, { title: '创建', dataIndex: 'createdAt', width: 160, render: fmtTime }, { title: '操作', width: 80, render: (_, row) => ( { await request(`/common/resources/${row.id}`, { method: 'DELETE' }); message.success('已删除'); void reload(); }} > ), }, ]; return (
OSS 资源库
{ setFilters(v); setPage(1); void reload(1, pageSize, v); }} > ({ value, label }))} />
{ setPage(p); setPageSize(ps); void reload(p, ps); }, }} /> setCreateOpen(false)} onOk={async () => { const v = await createForm.validateFields(); setSaving(true); try { await request('/common/resources', { method: 'POST', body: JSON.stringify({ ownerType: v.ownerType, ownerId: v.ownerId, bizType: v.bizType, mediaType: v.mediaType, ossKey: v.ossKey, url: v.url, fileName: v.fileName, sortOrder: v.sortOrder ?? 0, }), }); message.success('已登记'); setCreateOpen(false); createForm.resetFields(); void reload(); } finally { setSaving(false); } }} width={520} >
({ value, label })), { value: 'FILE', label: '文件' }, ]} /> prev.mediaType !== cur.mediaType || prev.bizType !== cur.bizType}> {({ getFieldValue }) => { const mediaType = getFieldValue('mediaType') || 'IMAGE'; const bizType = getFieldValue('bizType') || 'COVER'; return ( { createForm.setFieldsValue({ ossKey: result.ossKey, url: result.url }); }} /> ); }}
); }