168 lines
4.5 KiB
TypeScript
168 lines
4.5 KiB
TypeScript
import { sitecontrollerAll } from '@/servers/api/site';
|
|
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
|
|
import { request } from '@umijs/max';
|
|
import { App, Image, Select } from 'antd';
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
const MediaPage: React.FC = () => {
|
|
const { message } = App.useApp();
|
|
const [sites, setSites] = useState<any[]>([]);
|
|
const [selectedSiteId, setSelectedSiteId] = useState<number | undefined>();
|
|
const [mediaList, setMediaList] = useState<any[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [pagination, setPagination] = useState({
|
|
current: 1,
|
|
pageSize: 20,
|
|
total: 0,
|
|
});
|
|
|
|
// Fetch sites
|
|
useEffect(() => {
|
|
const fetchSites = async () => {
|
|
try {
|
|
const res = await sitecontrollerAll();
|
|
if (res.success && res.data) {
|
|
setSites(res.data);
|
|
if (res.data.length > 0) {
|
|
setSelectedSiteId(res.data[0].id);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
message.error('获取站点列表失败');
|
|
}
|
|
};
|
|
fetchSites();
|
|
}, []);
|
|
|
|
// Fetch media
|
|
const fetchMedia = async (siteId: number, page: number, pageSize: number) => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await request('/media/list', {
|
|
params: { siteId, page, pageSize },
|
|
});
|
|
if (res.success) {
|
|
setMediaList(res.data.items || []);
|
|
setPagination({
|
|
current: page,
|
|
pageSize: pageSize,
|
|
total: res.data.total || 0,
|
|
});
|
|
} else {
|
|
message.error(res.message || '获取媒体库失败');
|
|
}
|
|
} catch (error) {
|
|
message.error('获取媒体库失败');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (selectedSiteId) {
|
|
fetchMedia(selectedSiteId, 1, pagination.pageSize);
|
|
}
|
|
}, [selectedSiteId]);
|
|
|
|
const handlePageChange = (page: number, pageSize: number) => {
|
|
if (selectedSiteId) {
|
|
fetchMedia(selectedSiteId, page, pageSize);
|
|
}
|
|
};
|
|
|
|
const formatSize = (bytes: number) => {
|
|
if (!bytes) return '-';
|
|
if (bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
};
|
|
|
|
const columns: ProColumns<any>[] = [
|
|
{
|
|
title: '展示',
|
|
dataIndex: 'source_url',
|
|
hideInSearch: true,
|
|
render: (_, record) => (
|
|
<Image
|
|
src={record.media_details?.sizes?.thumbnail?.source_url || record.source_url}
|
|
style={{ width: 60, height: 60, objectFit: 'contain', background: '#f0f0f0' }}
|
|
fallback="https://via.placeholder.com/60?text=No+Img"
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: '名称',
|
|
dataIndex: ['title', 'rendered'],
|
|
copyable: true,
|
|
ellipsis: true,
|
|
width: 200,
|
|
},
|
|
{
|
|
title: '宽高',
|
|
dataIndex: 'media_details',
|
|
hideInSearch: true,
|
|
render: (_, record) => {
|
|
const width = record.media_details?.width;
|
|
const height = record.media_details?.height;
|
|
return width && height ? `${width} x ${height}` : '-';
|
|
},
|
|
},
|
|
{
|
|
title: '地址',
|
|
dataIndex: 'source_url',
|
|
copyable: true,
|
|
ellipsis: true,
|
|
hideInSearch: true,
|
|
},
|
|
{
|
|
title: '文件大小',
|
|
dataIndex: 'media_details',
|
|
hideInSearch: true,
|
|
render: (_, record) => formatSize(record.media_details?.filesize),
|
|
},
|
|
{
|
|
title: '素材类型',
|
|
dataIndex: 'mime_type',
|
|
width: 120,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<PageContainer
|
|
header={{
|
|
title: '媒体库',
|
|
extra: [
|
|
<Select
|
|
key="site-select"
|
|
style={{ width: 200 }}
|
|
placeholder="选择站点"
|
|
value={selectedSiteId}
|
|
onChange={setSelectedSiteId}
|
|
options={sites.map(site => ({ label: site.name, value: site.id }))}
|
|
/>
|
|
]
|
|
}}
|
|
>
|
|
<ProTable
|
|
rowKey="id"
|
|
columns={columns}
|
|
dataSource={mediaList}
|
|
loading={loading}
|
|
search={false}
|
|
pagination={{
|
|
current: pagination.current,
|
|
pageSize: pagination.pageSize,
|
|
total: pagination.total,
|
|
onChange: handlePageChange,
|
|
showSizeChanger: true,
|
|
}}
|
|
options={false}
|
|
/>
|
|
</PageContainer>
|
|
);
|
|
};
|
|
|
|
export default MediaPage;
|