|
|
|
|
@ -1,13 +1,18 @@
|
|
|
|
|
import React, { useEffect, useRef } from 'react';
|
|
|
|
|
import { Card, Table, Tag, Space, Typography, Progress, Row, Col, Button } from 'antd';
|
|
|
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
|
|
|
import { Card, Table, Tag, Space, Typography, Progress, Row, Col, Button, Input, Select } from 'antd';
|
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
|
import StandardTable from '@/components/StandardTable';
|
|
|
|
|
import styles from './LicenseManagement.less';
|
|
|
|
|
import icon_echart from '@/assets/business_basic/icon_echart.svg';
|
|
|
|
|
|
|
|
|
|
const { Title } = Typography;
|
|
|
|
|
const { Search } = Input;
|
|
|
|
|
const { Option } = Select;
|
|
|
|
|
|
|
|
|
|
const LicenseManagement = () => {
|
|
|
|
|
const chartRef = useRef(null);
|
|
|
|
|
const [searchValue, setSearchValue] = useState('');
|
|
|
|
|
const [selectedType, setSelectedType] = useState('all');
|
|
|
|
|
|
|
|
|
|
// 图表数据
|
|
|
|
|
const chartData = [
|
|
|
|
|
@ -130,7 +135,7 @@ const LicenseManagement = () => {
|
|
|
|
|
id: 'HQ-XF-02-015',
|
|
|
|
|
authority: '第三方评估机构',
|
|
|
|
|
validUntil: '2025-09-10',
|
|
|
|
|
status: '15天后到期',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'warning'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
@ -154,6 +159,72 @@ const LicenseManagement = () => {
|
|
|
|
|
validUntil: '2025-09-10',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '5',
|
|
|
|
|
no: '05',
|
|
|
|
|
name: '消防验收合格证',
|
|
|
|
|
type: '消防证书',
|
|
|
|
|
id: 'HQ-XF-05-012',
|
|
|
|
|
authority: '消防局',
|
|
|
|
|
validUntil: '2026-03-15',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '6',
|
|
|
|
|
no: '06',
|
|
|
|
|
name: '职业健康安全管理体系认证',
|
|
|
|
|
type: '管理体系认证',
|
|
|
|
|
id: 'HQ-XF-06-008',
|
|
|
|
|
authority: '认证机构',
|
|
|
|
|
validUntil: '2026-06-20',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '7',
|
|
|
|
|
no: '07',
|
|
|
|
|
name: '环境管理体系认证',
|
|
|
|
|
type: '管理体系认证',
|
|
|
|
|
id: 'HQ-XF-07-009',
|
|
|
|
|
authority: '认证机构',
|
|
|
|
|
validUntil: '2026-08-25',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '8',
|
|
|
|
|
no: '08',
|
|
|
|
|
name: '特种设备使用登记证',
|
|
|
|
|
type: '特种设备证书',
|
|
|
|
|
id: 'HQ-XF-08-011',
|
|
|
|
|
authority: '质量技术监督局',
|
|
|
|
|
validUntil: '2026-12-10',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '9',
|
|
|
|
|
no: '09',
|
|
|
|
|
name: '危险化学品经营许可证',
|
|
|
|
|
type: '经营许可证',
|
|
|
|
|
id: 'HQ-XF-09-013',
|
|
|
|
|
authority: '应急管理局',
|
|
|
|
|
validUntil: '2027-01-30',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '10',
|
|
|
|
|
no: '10',
|
|
|
|
|
name: '辐射安全许可证',
|
|
|
|
|
type: '辐射安全证书',
|
|
|
|
|
id: 'HQ-XF-10-014',
|
|
|
|
|
authority: '生态环境部',
|
|
|
|
|
validUntil: '2027-04-18',
|
|
|
|
|
status: '有效',
|
|
|
|
|
statusType: 'success'
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
@ -200,45 +271,118 @@ const LicenseManagement = () => {
|
|
|
|
|
dataIndex: 'status',
|
|
|
|
|
key: 'status',
|
|
|
|
|
width: 120,
|
|
|
|
|
render: (text, record) => (
|
|
|
|
|
<Tag color={record.statusType === 'success' ? 'green' :
|
|
|
|
|
record.statusType === 'warning' ? 'orange' : 'red'}>
|
|
|
|
|
{text}
|
|
|
|
|
</Tag>
|
|
|
|
|
),
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
const getStatusStyle = (status) => {
|
|
|
|
|
if (status === '有效') {
|
|
|
|
|
return {
|
|
|
|
|
color: '#44BB5F',
|
|
|
|
|
backgroundColor: '#D8F7DE',
|
|
|
|
|
padding: '4px 8px',
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
fontSize: '12px',
|
|
|
|
|
display: 'inline-block'
|
|
|
|
|
};
|
|
|
|
|
} else if (status === '即将到期') {
|
|
|
|
|
return {
|
|
|
|
|
color: '#FF8800',
|
|
|
|
|
backgroundColor: '#FFF3E9',
|
|
|
|
|
padding: '4px 8px',
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
fontSize: '12px',
|
|
|
|
|
display: 'inline-block'
|
|
|
|
|
};
|
|
|
|
|
} else if (status === '已过期') {
|
|
|
|
|
return {
|
|
|
|
|
color: '#FF3E48',
|
|
|
|
|
backgroundColor: '#FFE0E2',
|
|
|
|
|
padding: '4px 8px',
|
|
|
|
|
borderRadius: '4px',
|
|
|
|
|
fontSize: '12px',
|
|
|
|
|
display: 'inline-block'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<span style={getStatusStyle(text)}>
|
|
|
|
|
{text}
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '操作',
|
|
|
|
|
dataIndex: 'action',
|
|
|
|
|
key: 'action',
|
|
|
|
|
width: 120,
|
|
|
|
|
render: () => (
|
|
|
|
|
<Space size="small">
|
|
|
|
|
<Button type="link" size="small">更新</Button>
|
|
|
|
|
<Button type="link" size="small">查看</Button>
|
|
|
|
|
</Space>
|
|
|
|
|
),
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
const handleEdit = (record) => {
|
|
|
|
|
console.log('编辑记录:', record);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDelete = (record) => {
|
|
|
|
|
console.log('删除记录:', record);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div style={{
|
|
|
|
|
display: 'flex',
|
|
|
|
|
gap: '8px',
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
alignItems: 'center'
|
|
|
|
|
}}>
|
|
|
|
|
<Button
|
|
|
|
|
onClick={() => handleEdit(record)}
|
|
|
|
|
style={{
|
|
|
|
|
color: '#2E4CD4',
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
// borderColor: '#E6E9FB',
|
|
|
|
|
fontSize: '12px',
|
|
|
|
|
height: '28px',
|
|
|
|
|
padding: '0 12px'
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
更新
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
onClick={() => handleDelete(record)}
|
|
|
|
|
style={{
|
|
|
|
|
color: '#2E4CD4',
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
// borderColor: '#E6E9FB',
|
|
|
|
|
fontSize: '12px',
|
|
|
|
|
height: '28px',
|
|
|
|
|
padding: '0 12px'
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
查看
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.licenseManagementContainer}>
|
|
|
|
|
<div className={styles.topSectionContainer}>
|
|
|
|
|
<div className={styles.topSectionContainer}>
|
|
|
|
|
|
|
|
|
|
<div className={styles.firstBlock}>
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
<div className={styles.colorBlock}></div>
|
|
|
|
|
<span className={styles.chartTitle}>证件类型分布</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.chartContainer}>
|
|
|
|
|
<div ref={chartRef} className={styles.chart}></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.firstBlock}>
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
<div className={styles.colorBlock}></div>
|
|
|
|
|
<span className={styles.chartTitle}>证件类型分布</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.chartContainer}>
|
|
|
|
|
<div ref={chartRef} className={styles.chart}></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className={styles.secondBlock}>
|
|
|
|
|
<div className={styles.secondBlock}>
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
<div className={styles.colorBlock}></div>
|
|
|
|
|
<span className={styles.chartTitle}>证件类型分布</span>
|
|
|
|
|
<span className={styles.chartTitle}>证件状态概览</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.chartContainer}>
|
|
|
|
|
{/* 上半部分:进度条和百分比 */}
|
|
|
|
|
@ -305,25 +449,25 @@ const LicenseManagement = () => {
|
|
|
|
|
<Row gutter={[16, 16]}>
|
|
|
|
|
<Col span={6}>
|
|
|
|
|
<div className={styles.statItem}>
|
|
|
|
|
<div className={styles.statNumber} style={{color: '#3C7DFF'}}>42</div>
|
|
|
|
|
<div className={styles.statNumber} style={{ color: '#3C7DFF' }}>42</div>
|
|
|
|
|
<div className={styles.statLabel}>总证照数</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col span={6}>
|
|
|
|
|
<div className={styles.statItem}>
|
|
|
|
|
<div className={styles.statNumber} style={{color: '#FFC403'}}>8</div>
|
|
|
|
|
<div className={styles.statNumber} style={{ color: '#FFC403' }}>8</div>
|
|
|
|
|
<div className={styles.statLabel}>即将过期</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col span={6}>
|
|
|
|
|
<div className={styles.statItem}>
|
|
|
|
|
<div className={styles.statNumber} style={{color: '#FF3E48'}}>6</div>
|
|
|
|
|
<div className={styles.statNumber} style={{ color: '#FF3E48' }}>6</div>
|
|
|
|
|
<div className={styles.statLabel}>已过期</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col span={6}>
|
|
|
|
|
<div className={styles.statItem}>
|
|
|
|
|
<div className={styles.statNumber} style={{color: '#FF8800'}}>6</div>
|
|
|
|
|
<div className={styles.statNumber} style={{ color: '#FF8800' }}>6</div>
|
|
|
|
|
<div className={styles.statLabel}>待审核材料</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
@ -367,8 +511,8 @@ const LicenseManagement = () => {
|
|
|
|
|
<div className={styles.licenseName}>施工资质证书</div>
|
|
|
|
|
<div className={styles.licenseNumber}>编号: SGZZ-2023-0089</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.expiryTag} style={{backgroundColor: '#FFE0E2'}}>
|
|
|
|
|
<span className={styles.expiryText} style={{color: '#FF2526'}}>7天后到期</span>
|
|
|
|
|
<div className={styles.expiryTag} style={{ backgroundColor: '#FFE0E2' }}>
|
|
|
|
|
<span className={styles.expiryText} style={{ color: '#FF2526' }}>7天后到期</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@ -377,35 +521,80 @@ const LicenseManagement = () => {
|
|
|
|
|
<div className={styles.licenseName}>应急预案</div>
|
|
|
|
|
<div className={styles.licenseNumber}>编号: YJYA-2023-0045</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.expiryTag} style={{backgroundColor: '#FFE0E2'}}>
|
|
|
|
|
<span className={styles.expiryText} style={{color: '#FF2526'}}>4天后到期</span>
|
|
|
|
|
<div className={styles.expiryTag} style={{ backgroundColor: '#FFE0E2' }}>
|
|
|
|
|
<span className={styles.expiryText} style={{ color: '#FF2526' }}>4天后到期</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 证照列表区域 */}
|
|
|
|
|
<div className={styles.listCard}>
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
<div className={styles.colorBlock}></div>
|
|
|
|
|
<span className={styles.chartTitle}>证照列表</span>
|
|
|
|
|
<div className={styles.headerLeft}>
|
|
|
|
|
<div className={styles.colorBlock}></div>
|
|
|
|
|
<span className={styles.chartTitle}>证照列表</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.headerRight}>
|
|
|
|
|
<Search
|
|
|
|
|
placeholder="搜索证照名称或编号..."
|
|
|
|
|
value={searchValue}
|
|
|
|
|
onChange={(e) => setSearchValue(e.target.value)}
|
|
|
|
|
onSearch={(value) => console.log('搜索:', value)}
|
|
|
|
|
className={styles.searchInput}
|
|
|
|
|
/>
|
|
|
|
|
<Select
|
|
|
|
|
value={selectedType}
|
|
|
|
|
onChange={setSelectedType}
|
|
|
|
|
className={styles.typeSelector}
|
|
|
|
|
>
|
|
|
|
|
<Option value="all">全部类型</Option>
|
|
|
|
|
<Option value="safety">安全生产许可证</Option>
|
|
|
|
|
<Option value="assessment">安全评估报告</Option>
|
|
|
|
|
<Option value="construction">施工资质证书</Option>
|
|
|
|
|
<Option value="emergency">应急预案</Option>
|
|
|
|
|
<Option value="other">其他</Option>
|
|
|
|
|
</Select>
|
|
|
|
|
<Button
|
|
|
|
|
type="primary"
|
|
|
|
|
className={styles.addButton}
|
|
|
|
|
onClick={() => console.log('新增证照')}
|
|
|
|
|
>
|
|
|
|
|
新增证照
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<Table
|
|
|
|
|
<StandardTable
|
|
|
|
|
columns={columns}
|
|
|
|
|
dataSource={tableData}
|
|
|
|
|
data={{
|
|
|
|
|
list: tableData, // ======== 表格数据列表 ========
|
|
|
|
|
pagination: { // ======== 分页配置 ========
|
|
|
|
|
currentPage: 1, // ======== 当前页码 ========
|
|
|
|
|
pageSize: 5, // ======== 每页显示5条数据 ========
|
|
|
|
|
total: tableData.length, // ======== 总数据条数 ========
|
|
|
|
|
} // ======== 分页配置结束 ========
|
|
|
|
|
}} // ======== 数据对象结束 ========
|
|
|
|
|
selectedRows={[]} // ======== 选中的行数据,初始为空数组 ========
|
|
|
|
|
onSelectRow={() => { }} // ======== 行选择事件处理函数 ========
|
|
|
|
|
onChange={() => { }} // ======== 表格变化事件处理函数 ========
|
|
|
|
|
pagination={{
|
|
|
|
|
current: 3,
|
|
|
|
|
total: 48,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
currentPage: 1,
|
|
|
|
|
pageSize: 5,
|
|
|
|
|
total: tableData.length,
|
|
|
|
|
showSizeChanger: false,
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
showTotal: (total) => `共${total}条`,
|
|
|
|
|
showTotal: (total, range) =>
|
|
|
|
|
`共 ${total} 条`,
|
|
|
|
|
locale: {
|
|
|
|
|
jump_to: '前往',
|
|
|
|
|
page: '页',
|
|
|
|
|
items_per_page: '条/页',
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
className={styles.licenseTable}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|