对接通知中心与政策法规,包括多语言维护
This commit is contained in:
@ -1,121 +1,22 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, Menu, Row, Col, Pagination, Button, Typography, Space, message } from 'antd';
|
||||
import { FileOutlined, BookOutlined, DownloadOutlined } from '@ant-design/icons';
|
||||
import { useIntl, FormattedMessage } from 'umi';
|
||||
import styles from './download.less';
|
||||
import { downloadFile } from './service';
|
||||
import { downloadFile, getDownloadList, DownloadRecord } from '@/servers/api/download';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
// 模拟模板文件数据
|
||||
const mockTemplateFiles = [
|
||||
{
|
||||
id: '1',
|
||||
title: '公开招标操作手册',
|
||||
description: '公开招标各角色操作手册',
|
||||
publishDate: '2025年2月3日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '公开招标操作手册.pdf',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: '询价采购模板',
|
||||
description: '标准询价采购流程文档模板',
|
||||
publishDate: '2025年1月15日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '询价采购模板.docx',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: '竞争性谈判模板',
|
||||
description: '竞争性谈判标准文档模板',
|
||||
publishDate: '2024年12月20日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '竞争性谈判模板.docx',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: '单一来源采购模板',
|
||||
description: '单一来源采购申请及实施模板',
|
||||
publishDate: '2024年12月5日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '单一来源采购模板.docx',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: '供应商评估表格',
|
||||
description: '供应商资质与能力评估标准表格',
|
||||
publishDate: '2024年11月18日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '供应商评估表格.xlsx',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: '合同范本模板',
|
||||
description: '标准采购合同范本',
|
||||
publishDate: '2024年11月1日',
|
||||
type: 'template',
|
||||
icon: <FileOutlined />,
|
||||
fileName: '合同范本模板.docx',
|
||||
},
|
||||
];
|
||||
|
||||
// 模拟操作手册数据
|
||||
const mockManuals = [
|
||||
{
|
||||
id: '7',
|
||||
title: '供应商注册指南',
|
||||
description: '供应商平台注册及资质提交操作指南',
|
||||
publishDate: '2025年1月25日',
|
||||
type: 'manual',
|
||||
icon: <BookOutlined />,
|
||||
fileName: '供应商注册指南.pdf',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
title: '投标操作指南',
|
||||
description: '电子投标全流程操作手册',
|
||||
publishDate: '2025年1月10日',
|
||||
type: 'manual',
|
||||
icon: <BookOutlined />,
|
||||
fileName: '投标操作指南.pdf',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
title: '在线开标指南',
|
||||
description: '在线开标会议参与指南',
|
||||
publishDate: '2024年12月15日',
|
||||
type: 'manual',
|
||||
icon: <BookOutlined />,
|
||||
fileName: '在线开标指南.pdf',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
title: '评标专家操作手册',
|
||||
description: '评标专家系统使用指南',
|
||||
publishDate: '2024年11月28日',
|
||||
type: 'manual',
|
||||
icon: <BookOutlined />,
|
||||
fileName: '评标专家操作手册.pdf',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
title: '合同签署指南',
|
||||
description: '电子合同签署流程指南',
|
||||
publishDate: '2024年11月10日',
|
||||
type: 'manual',
|
||||
icon: <BookOutlined />,
|
||||
fileName: '合同签署指南.pdf',
|
||||
},
|
||||
];
|
||||
// 模拟模板文件数据 - 后期将通过API获取分类
|
||||
const mockCategories: { [key: string]: string } = {
|
||||
template: '模板文件',
|
||||
manual: '操作手册'
|
||||
};
|
||||
|
||||
const DownloadPage: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [activeMenu, setActiveMenu] = useState<string>('template');
|
||||
const [downloadData, setDownloadData] = useState<any[]>([]);
|
||||
const [downloadData, setDownloadData] = useState<DownloadRecord[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [pagination, setPagination] = useState({
|
||||
current: 1,
|
||||
@ -123,51 +24,75 @@ const DownloadPage: React.FC = () => {
|
||||
total: 0,
|
||||
});
|
||||
|
||||
// 根据当前选中的菜单加载对应的下载数据
|
||||
useEffect(() => {
|
||||
// 加载下载数据
|
||||
const loadDownloadData = async (page: number, pageSize: number) => {
|
||||
setLoading(true);
|
||||
// 模拟API请求
|
||||
setTimeout(() => {
|
||||
const data = activeMenu === 'template' ? mockTemplateFiles : mockManuals;
|
||||
setDownloadData(data);
|
||||
setPagination((prevPagination) => ({
|
||||
...prevPagination,
|
||||
total: data.length,
|
||||
current: 1,
|
||||
}));
|
||||
try {
|
||||
const response = await getDownloadList({
|
||||
pageNo: page.toString(),
|
||||
pageSize: pageSize.toString()
|
||||
});
|
||||
|
||||
if (response.code === 200 && response.success) {
|
||||
// 根据当前选中的菜单过滤数据
|
||||
// 目前没有分类的API,暂时都显示,后期可以根据columnType进行过滤
|
||||
const data = response.data.records;
|
||||
|
||||
setDownloadData(data);
|
||||
setPagination({
|
||||
current: response.data.current,
|
||||
pageSize: response.data.size,
|
||||
total: response.data.total,
|
||||
});
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'download.message.getListFailed' }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取下载列表出错:', error);
|
||||
message.error(intl.formatMessage({ id: 'download.message.getListError' }));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
}, [activeMenu]);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始加载和分页变化时加载数据
|
||||
useEffect(() => {
|
||||
loadDownloadData(pagination.current, pagination.pageSize);
|
||||
}, [pagination.current, activeMenu]);
|
||||
|
||||
// 处理菜单切换
|
||||
const handleMenuClick = (e: any) => {
|
||||
setActiveMenu(e.key);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current: 1, // 切换分类时重置页码
|
||||
});
|
||||
};
|
||||
|
||||
// 处理分页变化
|
||||
const handlePageChange = (page: number, pageSize?: number) => {
|
||||
const newPageSize = pageSize || pagination.pageSize;
|
||||
setPagination({
|
||||
...pagination,
|
||||
current: page,
|
||||
pageSize: pageSize || pagination.pageSize,
|
||||
pageSize: newPageSize,
|
||||
});
|
||||
};
|
||||
|
||||
// 处理下载按钮点击
|
||||
const handleDownload = async (id: string, fileName: string) => {
|
||||
const handleDownload = async (item: DownloadRecord) => {
|
||||
try {
|
||||
await downloadFile(id, fileName);
|
||||
window.open(item.fileUrl, '_blank');
|
||||
// await downloadFile(id, fileName);
|
||||
} catch (error) {
|
||||
message.error('下载失败,请稍后重试');
|
||||
message.error(intl.formatMessage({ id: 'download.message.downloadFailed' }));
|
||||
}
|
||||
};
|
||||
|
||||
// 计算当前页显示的数据
|
||||
const getCurrentPageData = () => {
|
||||
const { current, pageSize } = pagination;
|
||||
const startIndex = (current - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
return downloadData.slice(startIndex, endIndex);
|
||||
// 获取文件图标
|
||||
const getFileIcon = (fileType: string) => {
|
||||
// 根据文件类型返回不同图标,可以进一步完善
|
||||
return <FileOutlined />;
|
||||
};
|
||||
|
||||
return (
|
||||
@ -181,55 +106,78 @@ const DownloadPage: React.FC = () => {
|
||||
className={styles.downloadMenu}
|
||||
>
|
||||
<Menu.Item key="template" icon={<FileOutlined />}>
|
||||
模板文件
|
||||
<FormattedMessage id="download.menu.template" />
|
||||
</Menu.Item>
|
||||
<Menu.Item key="manual" icon={<BookOutlined />}>
|
||||
操作手册
|
||||
<FormattedMessage id="download.menu.manual" />
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Col>
|
||||
|
||||
<Col span={20}>
|
||||
<div className={styles.downloadContent}>
|
||||
<Title level={4}>{activeMenu === 'template' ? '模板文件' : '操作手册'}</Title>
|
||||
<Title level={4}>
|
||||
<FormattedMessage id={`download.menu.${activeMenu}`} defaultMessage={intl.formatMessage({ id: 'download.title' })} />
|
||||
</Title>
|
||||
|
||||
<Row gutter={[16, 16]} className={styles.downloadCardList}>
|
||||
{getCurrentPageData().map((item) => (
|
||||
<Col xs={24} sm={12} md={8} key={item.id}>
|
||||
<Card
|
||||
hoverable
|
||||
className={styles.downloadCard}
|
||||
loading={loading}
|
||||
>
|
||||
<Space direction="vertical" size="small" style={{ width: '100%' }}>
|
||||
<div className={styles.cardTitle}>
|
||||
<span className={styles.downloadIcon}>{item.icon}</span>
|
||||
{item.title}
|
||||
</div>
|
||||
<div className={styles.cardDate}>{item.publishDate}</div>
|
||||
<Text type="secondary" ellipsis={{ tooltip: true }}>{item.description}</Text>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<DownloadOutlined />}
|
||||
className={styles.downloadButton}
|
||||
onClick={() => handleDownload(item.id, item.fileName)}
|
||||
>
|
||||
下载
|
||||
</Button>
|
||||
</Space>
|
||||
</Card>
|
||||
{loading ? (
|
||||
Array(6).fill(null).map((_, index) => (
|
||||
<Col xs={24} sm={12} md={8} key={`loading-${index}`}>
|
||||
<Card loading={true} className={styles.downloadCard}></Card>
|
||||
</Col>
|
||||
))
|
||||
) : downloadData.length > 0 ? (
|
||||
downloadData.map((item) => (
|
||||
<Col xs={24} sm={12} md={8} key={item.id}>
|
||||
<Card
|
||||
hoverable
|
||||
className={styles.downloadCard}
|
||||
>
|
||||
<Space direction="vertical" size="small" style={{ width: '100%' }}>
|
||||
<div className={styles.cardTitle}>
|
||||
<span className={styles.downloadIcon}>{getFileIcon(item.fileType)}</span>
|
||||
{item.name}
|
||||
</div>
|
||||
<div className={styles.cardDate}>
|
||||
{intl.formatMessage(
|
||||
{ id: 'download.card.date' },
|
||||
{ publishTime: item.publishTime || '' }
|
||||
)}
|
||||
</div>
|
||||
<Text type="secondary" ellipsis={{ tooltip: true }}>{item.keywords || ''}</Text>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<DownloadOutlined />}
|
||||
className={styles.downloadButton}
|
||||
onClick={() => handleDownload(item)}
|
||||
>
|
||||
<FormattedMessage id="download.button" />
|
||||
</Button>
|
||||
</Space>
|
||||
</Card>
|
||||
</Col>
|
||||
))
|
||||
) : (
|
||||
<Col span={24} style={{ textAlign: 'center', margin: '30px 0' }}>
|
||||
<Text type="secondary"><FormattedMessage id="download.empty" /></Text>
|
||||
</Col>
|
||||
))}
|
||||
)}
|
||||
</Row>
|
||||
|
||||
<Pagination
|
||||
current={pagination.current}
|
||||
pageSize={pagination.pageSize}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
showTotal={(total) => `共 ${total} 条记录`}
|
||||
style={{ marginTop: 24, textAlign: 'right' }}
|
||||
/>
|
||||
{downloadData.length > 0 && (
|
||||
<Pagination
|
||||
current={pagination.current}
|
||||
pageSize={pagination.pageSize}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
showTotal={(total) => intl.formatMessage(
|
||||
{ id: 'download.list.total' },
|
||||
{ total }
|
||||
)}
|
||||
style={{ marginTop: 24, textAlign: 'right' }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -1,75 +0,0 @@
|
||||
import { message } from 'antd';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 获取下载中心文件列表
|
||||
* @param params 查询参数
|
||||
*/
|
||||
export async function getDownloadList(params: {
|
||||
type: string;
|
||||
current: number;
|
||||
pageSize: number;
|
||||
}) {
|
||||
try {
|
||||
// 实际项目中应该通过API获取数据
|
||||
// return request('/api/download/list', {
|
||||
// method: 'GET',
|
||||
// params,
|
||||
// });
|
||||
|
||||
// 模拟API请求返回数据
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
data: {
|
||||
list: [],
|
||||
total: 0,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
message.error('获取下载列表失败');
|
||||
return {
|
||||
success: false,
|
||||
data: {
|
||||
list: [],
|
||||
total: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param fileId 文件ID
|
||||
* @param fileName 文件名称
|
||||
*/
|
||||
export async function downloadFile(fileId: string, fileName: string) {
|
||||
try {
|
||||
// 实际项目中应该通过API下载文件
|
||||
// const response = await request(`/api/download/file/${fileId}`, {
|
||||
// method: 'GET',
|
||||
// responseType: 'blob',
|
||||
// });
|
||||
|
||||
// 创建下载链接
|
||||
// const blob = new Blob([response]);
|
||||
// const url = window.URL.createObjectURL(blob);
|
||||
// const link = document.createElement('a');
|
||||
// link.href = url;
|
||||
// link.download = fileName;
|
||||
// document.body.appendChild(link);
|
||||
// link.click();
|
||||
// window.URL.revokeObjectURL(url);
|
||||
// document.body.removeChild(link);
|
||||
|
||||
// 模拟下载成功
|
||||
message.success(`文件"${fileName}"开始下载`);
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
} catch (error) {
|
||||
message.error(`下载文件"${fileName}"失败`);
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user