feat():档案全周期开发

qzc-dev
李神峰 2026-01-28 17:57:00 +08:00
parent 34546864f4
commit b57adda8e5
15 changed files with 715 additions and 68 deletions

View File

@ -238,6 +238,22 @@ input:-webkit-autofill:active {
&:not(.ant-select-disabled):hover .ant-select-selector {
border-color: #3b7cff !important;
}
// Multiple Select Tags
&.ant-select-multiple .ant-select-selection-item {
background: rgba(0, 160, 233, 0.2); // Light blue transparent
border: 1px solid #00a0e9;
color: #fff;
margin-top: 2px;
margin-bottom: 2px;
.ant-select-selection-item-remove {
color: rgba(255, 255, 255, 0.7);
&:hover {
color: #fff;
}
}
}
}
// Dropdowns (Select, DatePicker, etc.)
@ -271,14 +287,42 @@ input:-webkit-autofill:active {
}
.ant-picker-cell {
color: rgba(255, 255, 255, 0.5); // Default inactive color
&:hover .ant-picker-cell-inner {
background: rgba(0, 160, 233, 0.3);
background: rgba(0, 160, 233, 0.3) !important;
}
&-in-view {
color: #fff; // Active month days
}
// Fix: Remove white background from cells
.ant-picker-cell-inner {
background: transparent !important;
color: inherit;
}
&-selected .ant-picker-cell-inner {
background: #00a0e9 !important; // Project Cyan
color: #fff;
}
&-selected .ant-picker-cell-inner {
background: #3b7cff !important;
&-today .ant-picker-cell-inner {
border: 1px solid #00a0e9;
&::before {
border: 1px solid #00a0e9 !important;
}
}
// Range Selection
&-in-range::before {
background: rgba(0, 160, 233, 0.2) !important;
}
&-range-start .ant-picker-cell-inner,
&-range-end .ant-picker-cell-inner {
background: #00a0e9 !important;
color: #fff;
}
}
@ -308,14 +352,76 @@ input:-webkit-autofill:active {
// 4. Button Component (Ghost Blue Style)
// ==============================================================================
.ant-btn-ghost-blue {
background: rgba(24, 144, 255, 0.3) !important; // Slight blue tint background
border: 1px solid #1890ff !important;
background: rgba(18, 56, 102, 0.6) !important;
border: 1px solid #00a0e9 !important;
color: #fff !important;
box-shadow: 0 0 8px rgba(24, 144, 255, 0.3) inset;
box-shadow: 0 0 8px rgba(0, 160, 233, 0.2) inset;
}
.ant-btn.ant-btn-ghost-blue,
.ant-btn.ant-btn-primary.ant-btn-ghost-blue {
background: rgba(18, 56, 102, 0.6) !important;
border-color: #00a0e9 !important;
color: #fff !important;
}
.ant-btn.ant-btn-ghost-blue:hover,
.ant-btn.ant-btn-ghost-blue:focus,
.ant-btn.ant-btn-primary.ant-btn-ghost-blue:hover,
.ant-btn.ant-btn-primary.ant-btn-ghost-blue:focus {
background: rgba(0, 160, 233, 0.3) !important;
border-color: #33b5ed !important;
color: #fff !important;
}
// ==============================================================================
// 5. Timeline Component
// ==============================================================================
.ant-timeline {
color: #fff;
.ant-timeline-item-label {
color: #fff;
width: calc(50% - 12px);
}
.ant-timeline-item-tail {
border-left: 2px solid rgba(0, 160, 233, 0.3);
}
.ant-timeline-item-head {
background-color: transparent;
border-color: #00a0e9;
}
.ant-timeline-item-head-blue {
color: #00a0e9;
border-color: #00a0e9;
}
}
// ==============================================================================
// 6. Button Component (Global Override for Dark Theme)
// ==============================================================================
.ant-btn {
&.ant-btn-primary {
background: #00a0e9; // Project Theme Cyan
border-color: #00a0e9;
&:hover, &:focus {
background: #33b5ed;
border-color: #33b5ed;
}
}
// Default button style in dark mode
&:not(.ant-btn-primary):not(.ant-btn-link):not(.ant-btn-text):not(.ant-btn-danger) {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.3);
color: #fff;
&:hover, &:focus {
background: rgba(24, 144, 255, 0.3) !important;
border-color: #40a9ff !important;
color: #fff !important;
color: #00a0e9;
border-color: #00a0e9;
}
}
}

4
src/config/index.js Normal file
View File

@ -0,0 +1,4 @@
export const config = {
ip: 'http://223.75.53.141:83',
minioIp:"http://223.75.53.141:9100/gs-ss"
}

View File

@ -24,7 +24,11 @@ const apiurl = {
qth: {
rainList: {
list:service + '/attResBase/rainBasinDivision/queryStPptnDetails/list',
}
},
},
qzq: {
list: service + '/projectEvents/doc/page',
export: service + '/projectEvents/export'
}
}
}

View File

@ -49,6 +49,15 @@ async function send(url, options) {
return {};
}
async function sendFile(url, options) {
try {
const res = await request(url, options,'blob');
return res;
} catch (e) {
message.error(e);
}
return {};
}
export function httpget(url, data = {}) {
const params = [];
@ -106,7 +115,7 @@ export function ry_httpget(url, data = {}) {
}
export function httppost(url, data = {}) {
export function httppost(url, data = {},type) {
const options = {
method: 'POST',
headers: {
@ -117,8 +126,8 @@ export function httppost(url, data = {}) {
},
body: JSON.stringify(data),
};
return send(url, options);
const fun = type == 'blob' ? sendFile(url, options) : send(url, options);
return fun;
}
export function httpPostFile(url, data = {}) {

View File

@ -19,6 +19,22 @@ export function objType(obj) {
}
return typeof obj === 'object' || typeof obj === 'function' ? class2type[toString.call(obj)] || 'object' : typeof obj;
}
export const exportFile = (name, res) => {
// 创建a标签
let blob = new Blob([res],{ type: 'application/octet-stream' })
// 创建下载链接
const downloadUrl = URL.createObjectURL(blob);
// 创建下载链接的 <a> 元素
const downloadLink = document.createElement("a");
downloadLink.href = downloadUrl;
downloadLink.download = name;
// 模拟点击下载链接
downloadLink.click();
// 清理创建的 URL 对象
URL.revokeObjectURL(downloadUrl);
}
/**
* 是否数组
* @param {object} obj 需要判断的对象

View File

@ -41,12 +41,12 @@ const AllWeatherControl = () => {
// Reservoir Data
const reservoirData = [
{ label: '主坝坝前', value: '103.17', unit: 'm', isPrimary: true, showArrow: true, underline: true },
{ label: '主坝坝前', value: '103.17', unit: 'm', showArrow: true, underline: true },
{ label: '汛限水位', value: '104.50', unit: 'm' },
{ label: '距汛限', value: '-1.67', unit: 'm', isNegative: true },
{ label: '副坝坝前', value: '104.17', unit: 'm' },
{ label: '当前库容', value: '3867.0', unit: '万m³', isPrimary: true },
{ label: '有效库容', value: '2867.0', unit: '万m³', isPrimary: true },
{ label: '当前库容', value: '3867.0', unit: '万m³'},
{ label: '有效库容', value: '2867.0', unit: '万m³'},
];
const getRainList = async () => {

View File

@ -138,7 +138,7 @@
color: #fff;
}
&.primary { color: #00eaff; }
&.positive { color: #ff4d52; }
&.negative { color: #68c639; }
}

View File

@ -0,0 +1,116 @@
import React, { useEffect, useMemo, useState } from 'react';
import { DatePicker, Button, Table } from 'antd';
import ReactEcharts from 'echarts-for-react';
import usePageTable from '@/components/crud/usePageTable';
import { createCrudService } from '@/components/crud/_';
import apiurl from '@/service/apiurl';
import './index.less';
const { RangePicker } = DatePicker;
const RainPanel = () => {
const { tableProps, search } = usePageTable(createCrudService(apiurl.sq.qth.rainList).find);
const [range, setRange] = useState();
useEffect(() => {
search({ search: {} });
}, []);
const columns = [
{ title: '时间', dataIndex: 'tm', key: 'tm', width: 140, align: 'center' },
{ title: '小时雨量(mm)', dataIndex: 'drp', key: 'drp', align: 'center' },
];
const option = useMemo(() => ({
title: { text: '雨量趋势', left: 'center', textStyle: { color: '#fff' } },
tooltip: { trigger: 'axis' },
grid: { left: '8%', right: '4%', bottom: '10%', top: '15%' },
xAxis: { type: 'category', data: (tableProps.dataSource || []).map(i => i.tm), axisLabel: { color: '#fff' } },
yAxis: { type: 'value', axisLabel: { color: '#fff' }, splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.2)' } } },
series: [{ type: 'line', smooth: true, data: (tableProps.dataSource || []).map(i => i.drp), areaStyle: { color: 'rgba(0,160,233,0.25)' }, lineStyle: { color: '#00a0e9' } }],
}), [tableProps.dataSource]);
return (
<div className="awm-grid">
<div className="awm-left">
<div className="awm-toolbar">
<RangePicker value={range} onChange={setRange} />
<Button type="primary" className="ant-btn-ghost-blue" onClick={() => search({ search: { range } })}>查询</Button>
</div>
<Table columns={columns} {...tableProps} size="small" pagination={false} scroll={{ y: 360 }} />
</div>
<div className="awm-right">
<ReactEcharts option={option} style={{ height: '100%', width: '100%' }} />
</div>
</div>
);
};
const ReservoirPanel = () => {
const columns = [
{ title: '时间', dataIndex: 'tm', key: 'tm', width: 140, align: 'center' },
{ title: '水位(m)', dataIndex: 'rz', key: 'rz', align: 'center' },
{ title: '库容(万m³)', dataIndex: 'w', key: 'w', align: 'center' },
];
const data = [];
const option = {
title: { text: '水位趋势', left: 'center', textStyle: { color: '#fff' } },
grid: { left: '8%', right: '4%', bottom: '10%', top: '15%' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: data.map(i => i.tm), axisLabel: { color: '#fff' } },
yAxis: { type: 'value', axisLabel: { color: '#fff' }, splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.2)' } } },
series: [{ type: 'line', smooth: true, data: data.map(i => i.rz), lineStyle: { color: '#00a0e9' } }],
};
return (
<div className="awm-grid">
<div className="awm-left">
<Table columns={columns} dataSource={data} size="small" pagination={false} scroll={{ y: 360 }} />
</div>
<div className="awm-right">
<ReactEcharts option={option} style={{ height: '100%', width: '100%' }} />
</div>
</div>
);
};
const FlowPanel = () => {
const columns = [
{ title: '时间', dataIndex: 'tm', key: 'tm', width: 140, align: 'center' },
{ title: '入库(m³/s)', dataIndex: 'qin', key: 'qin', align: 'center' },
{ title: '出库(m³/s)', dataIndex: 'qout', key: 'qout', align: 'center' },
];
const data = [];
const option = {
title: { text: '出入库流量', left: 'center', textStyle: { color: '#fff' } },
grid: { left: '8%', right: '4%', bottom: '10%', top: '15%' },
tooltip: { trigger: 'axis' },
legend: { data: ['入库', '出库'], textStyle: { color: '#fff' } },
xAxis: { type: 'category', data: data.map(i => i.tm), axisLabel: { color: '#fff' } },
yAxis: { type: 'value', axisLabel: { color: '#fff' }, splitLine: { show: true, lineStyle: { color: 'rgba(255,255,255,0.2)' } } },
series: [
{ name: '入库', type: 'line', data: data.map(i => i.qin), lineStyle: { color: '#00a0e9' } },
{ name: '出库', type: 'line', data: data.map(i => i.qout), lineStyle: { color: '#3b7cff' } },
],
};
return (
<div className="awm-grid">
<div className="awm-left">
<Table columns={columns} dataSource={data} size="small" pagination={false} scroll={{ y: 360 }} />
</div>
<div className="awm-right">
<ReactEcharts option={option} style={{ height: '100%', width: '100%' }} />
</div>
</div>
);
};
const SafetyPanel = () => {
return (
<div className="awm-empty">内容待接入</div>
);
};
const AllWeatherModal = ({ active }) => {
if (active === 'rain') return <RainPanel />;
if (active === 'reservoir') return <ReservoirPanel />;
if (active === 'flow') return <FlowPanel />;
return <SafetyPanel />;
};
export default AllWeatherModal;

View File

@ -0,0 +1,32 @@
.all-weather-modal {
height: 100%;
display: flex;
flex-direction: column;
}
.awm-grid {
height: calc(100% - 48px);
display: flex;
gap: 16px;
}
.awm-left {
flex: 0 0 420px;
display: flex;
flex-direction: column;
gap: 10px;
}
.awm-toolbar {
display: flex;
align-items: center;
gap: 10px;
}
.awm-right {
flex: 1;
min-width: 0;
}
.awm-empty {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255,255,255,0.6);
}

View File

@ -0,0 +1,187 @@
import React, { useState, useEffect } from 'react';
import { Timeline, Select, DatePicker, Button, Tag, Image, Tooltip } from 'antd';
import { SearchOutlined, ReloadOutlined, DownloadOutlined, FilePdfOutlined, FileOutlined } from '@ant-design/icons';
import apiurl from '@/service/apiurl';
import usePageTable from '@/components/crud/usePageTable';
import { createCrudService } from '@/components/crud/_';
import { exportFile } from '@/utils/tools'
import { httppost } from '@/utils/request';
import { config } from '@/config';
import PdfView from '@/views/Home/components/UI/PdfView';
import './index.less';
const { RangePicker } = DatePicker;
const CycleArchive = () => {
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.sq.qzq.list).find);
const [keyword, setKeyword] = useState([]);
const [dates, setDates] = useState();
const [pdfInfo, setPdfInfo] = useState({ visible: false, title: '', fileId: '' });
useEffect(() => {
search({ search: {} });
}, []);
const handleSearch = () => {
const params = {
search: {
types: keyword.length > 0 ? keyword : undefined,
dateSo: dates ? {
start: dates[0]?.format('YYYY-MM-DD'),
end: dates[1]?.format('YYYY-MM-DD')
} : undefined
}
};
search(params);
};
const handleReset = () => {
setKeyword([]);
setDates(undefined);
search({ search: {} });
};
const onExport = () => {
let params = {
search: {
types: keyword.length > 0 ? keyword : undefined,
dateSo: dates ? {
start: dates[0]?.format('YYYY-MM-DD'),
end: dates[1]?.format('YYYY-MM-DD')
} : undefined
},
pageSo:{
pageNum:1,pageSize:9999
}
}
httppost(apiurl.sq.qzq.export, params,'blob').then(res => {
exportFile(`全周期档案.xlsx`,res.data)
})
}
const handleFileClick = (file) => {
const fileType = file.fileName?.split('.').pop()?.toLowerCase();
if (fileType === 'pdf') {
setPdfInfo({
visible: true,
title: file.fileName,
fileId: file.fileId
});
} else {
// Download for non-pdf files
window.open(config.minioIp + file.filePath, '_blank');
}
};
const renderFileIcon = (file) => {
const fileType = file.fileName?.split('.').pop()?.toLowerCase();
const isImage = ['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(fileType);
if (isImage) {
return (
<Image
width={60}
height={60}
src={config.minioIp + file.filePath}
style={{ objectFit: 'cover', borderRadius: '4px' }}
/>
);
} else if (fileType === 'pdf') {
return <FilePdfOutlined style={{ fontSize: '40px', color: '#ff4d4f' }} />;
} else {
return <FileOutlined style={{ fontSize: '40px', color: '#1890ff' }} />;
}
};
return (
<div className="cycle-archive-container">
{/* Filters */}
<div className="filter-bar">
<div className="filter-item">
<span className="label">类型</span>
<Select
options={[
{value:1,label:'大事记'}, {value:2,label:'调度指令'}, {value:3,label:'维修养护'},{value:4,label:'安全鉴定'}, {value:5,label:"除险加固"}
]}
allowClear
placeholder="请输入类型"
style={{ width: 200 }}
value={keyword}
onChange={(e) => setKeyword(e)}
mode='multiple'
maxTagCount='responsive'
/>
</div>
<div className="filter-item">
<span className="label">发生日期</span>
<RangePicker
style={{ width: 300 }}
value={dates}
onChange={(val) => setDates(val)}
/>
</div>
<div className="action-buttons">
<Button type="primary" className="ant-btn-ghost-blue" icon={<SearchOutlined />} onClick={handleSearch}>查询</Button>
<Button icon={<ReloadOutlined />} onClick={handleReset}>重置</Button>
<Button type="primary" icon={<DownloadOutlined />} className="ant-btn-ghost-blue" onClick={onExport}>导出</Button>
</div>
</div>
{/* Timeline Content */}
<div className="timeline-content">
<Timeline>
{tableProps.dataSource?.map((item, index) => (
<Timeline.Item
key={index}
label={
<div className="timeline-label-content">
<div className="date">{item.eventsDate}</div>
<Tag color="cyan" className="custom-tag">{item.typeName}</Tag>
</div>
}
>
<div className="timeline-item-content">
<div className="item-header">
<span className="title">{item.eventsDesc}</span>
</div>
<div className="item-body">
<div className="attachment-label">附件</div>
<div className="image-grid">
{item.files?.length > 0 && item.files.map((file, idx) => (
<div
key={idx}
className="image-item"
onClick={() => !['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(file.fileName?.split('.').pop()?.toLowerCase()) && handleFileClick(file)}
style={{ cursor: 'pointer' }}
>
<Tooltip title={file.fileName}>
<div className="file-preview">
{renderFileIcon(file)}
</div>
</Tooltip>
<span className="image-name">{file.fileName}</span>
</div>
))}
</div>
</div>
</div>
</Timeline.Item>
))}
</Timeline>
</div>
{pdfInfo.visible && (
<PdfView
visible={pdfInfo.visible}
onClose={() => setPdfInfo({ ...pdfInfo, visible: false })}
title={pdfInfo.title}
fileId={pdfInfo.fileId}
url={"/gunshiApp/ss/projectEvents/file/download/"}
/>
)}
</div>
);
};
export default CycleArchive;

View File

@ -0,0 +1,163 @@
.cycle-archive-container {
padding: 0px;
height: 100%;
display: flex;
flex-direction: column;
.filter-bar {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
.filter-item {
display: flex;
align-items: center;
.label {
color: #fff;
margin-right: 10px;
white-space: nowrap;
}
}
.action-buttons {
display: flex;
gap: 10px;
}
}
.timeline-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden; // Prevent horizontal scrollbar
padding: 20px;
.ant-timeline-item {
padding-bottom: 20px;
}
.ant-timeline-item-label {
color: #00a0e9;
font-size: 16px;
width: 120px !important; // Fixed width for label
position: absolute !important;
left: 0 !important;
text-align: right;
padding-right: 15px;
top: 0;
}
.timeline-label-content {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 5px;
.date {
color: #fff;
font-size: 16px;
line-height: 1;
}
.custom-tag {
margin: 0;
border: none;
color: #fff;
background: #00a0e9; // Match theme
font-weight: normal;
text-align: center;
width: fit-content;
font-size: 14px;
padding: 0 5px;
border-radius: 2px;
}
}
.ant-timeline-item-tail {
border-left: 2px solid rgba(0, 160, 233, 0.3);
left: 126px !important; // 120px (label) + ~6px (center of gap)
height: calc(100% - 10px);
}
.ant-timeline-item-head {
background-color: transparent;
border-color: #00a0e9;
left: 126px !important; // Match tail
}
.ant-timeline-item-content {
margin-left: 140px !important; // 126px + padding
width: calc(100% - 140px) !important; // Take remaining width
top: 0;
padding-top: 0; // Align with label
min-height: auto;
}
.timeline-item-content {
background: transparent;
// border: 1px solid rgba(255, 255, 255, 0.1); // Removed border as per "clean" look
border-radius: 4px;
padding: 0;
width: 100%;
.item-header {
margin-bottom: 5px;
.title {
font-size: 16px;
color: #fff;
}
}
.item-body {
.attachment-label {
color: rgba(255, 255, 255, 0.6);
margin-bottom: 10px;
font-size: 14px;
}
.image-grid {
display: flex;
flex-wrap: wrap;
gap: 15px;
.image-item {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.05);
padding: 8px;
border-radius: 4px;
gap: 10px;
width: 280px;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.3s;
&:hover {
background: rgba(255, 255, 255, 0.1);
border-color: #00a0e9;
}
.file-preview {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
flex-shrink: 0;
}
.image-name {
color: rgba(255, 255, 255, 0.9);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
}
}
}
}
}
}

View File

@ -8,6 +8,8 @@ import EngineeringElements from './components/ModalComponents/EngineeringElement
import DownstreamElements from './components/ModalComponents/DownstreamElements';
import AllWeatherControl from './components/AllWeatherControl';
import ManagementCycle from './components/ManagementCycle';
import CycleArchive from './components/ModalComponents/CycleArchive';
import AllWeatherModal from './components/ModalComponents/AllWeatherModal';
import CommonModal from '../../UI/CommonModal';
import { httppost } from '@/utils/request';
import apiurl from '@/service/apiurl';
@ -16,6 +18,7 @@ import './index.less';
const SiQuan = () => {
const [modalVisible, setModalVisible] = useState(false);
const [modalType, setModalType] = useState('monitor'); // 'monitor' | 'cycle' | 'allweather'
const [infos, setInfos] = useState({});
const [activeTab, setActiveTab] = useState('kqys'); // Default active tab
@ -24,6 +27,12 @@ const SiQuan = () => {
{ label: '工程要素', value: 'gcys' },
{ label: '下游要素', value: 'xyys' },
];
const tabsAllWeather = [
{ label: '雨情监测', value: 'rain' },
{ label: '水库水情', value: 'reservoir' },
{ label: '出入库流量', value: 'flow' },
{ label: '安全监测', value: 'safety' },
];
const getInfo = async () => {
try {
@ -42,6 +51,17 @@ const SiQuan = () => {
}, []);
const handleOpenModal = () => {
setModalType('monitor');
setModalVisible(true);
};
const handleOpenCycleModal = () => {
setModalType('cycle');
setModalVisible(true);
};
const handleOpenAllWeatherModal = () => {
setModalType('allweather');
setActiveTab('rain');
setModalVisible(true);
};
@ -76,11 +96,15 @@ const SiQuan = () => {
<CommonCard
title="管控全天候"
className="panel-card card-1"
headerExtra={<ThreeDots onClick={() => console.log('管控全天候 clicked')} />}
headerExtra={<ThreeDots onClick={handleOpenAllWeatherModal} />}
>
<AllWeatherControl />
</CommonCard>
<CommonCard title="管理全周期" className="panel-card card-3">
<CommonCard
title="管理全周期"
className="panel-card card-3"
headerExtra={<ThreeDots onClick={handleOpenCycleModal} />}
>
<ManagementCycle />
</CommonCard>
</div>
@ -89,17 +113,23 @@ const SiQuan = () => {
<CommonModal
visible={modalVisible}
onClose={handleCloseModal}
title="掌握全要素"
tabs={tabs}
title={modalType === 'monitor' ? "掌握全要素" : (modalType === 'cycle' ? "全周期档案" : "管控全天候")}
tabs={modalType === 'monitor' ? tabs : (modalType === 'allweather' ? tabsAllWeather : [])}
activeTab={activeTab}
onTabChange={handleTabChange}
width={modalType === 'cycle' ? '70%': undefined}
>
{/* Content changes based on activeTab */}
<div style={{color: '#fff', height: '100%' }}>
{modalType === 'monitor' && (
<>
{activeTab === 'kqys' && <ReservoirAreaElements />}
{activeTab === 'gcys' && <EngineeringElements data={infos} />}
{activeTab === 'xyys' && <DownstreamElements />}
{/* {activeTab === 'glys' && <ManagementElements />} */}
</>
)}
{modalType === 'cycle' && <CycleArchive />}
{modalType === 'allweather' && <AllWeatherModal active={activeTab} />}
</div>
</CommonModal>
</div>

View File

@ -4,7 +4,7 @@ import { CloseOutlined } from '@ant-design/icons';
import titleBg from '@/assets/images/modal/title.png';
import './index.less';
const CommonModal = ({ visible, onClose, title, children, width, tabs = [], activeTab, onTabChange }) => {
const CommonModal = ({ visible, onClose, title, children, width, tabs = [], activeTab, onTabChange, bodyStyle = {} }) => {
useEffect(() => {
if (visible) {
//当弹框打开时如果不加这行代码用户滚动鼠标滚轮时背后的页面Home 页)也会跟着滚动
@ -45,7 +45,7 @@ const CommonModal = ({ visible, onClose, title, children, width, tabs = [], acti
<CloseOutlined />
</div>
</div>
<div className="modal-body">
<div className="modal-body" style={bodyStyle}>
{children}
</div>
</div>

View File

@ -1,34 +1,15 @@
import React from "react";
import { CloseOutlined } from '@ant-design/icons';
import CommonModal from '../CommonModal';
const PdfView = ({ visible, title, onClose, url, fileId }) => {
if (!visible) return null;
return (
<div style={{
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 2000,
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}}>
<div style={{ width: '60%', height: '80vh', display: 'flex', flexDirection: 'column', position: 'relative' }}>
<CloseOutlined
onClick={onClose}
style={{
position: 'absolute',
top: '-30px',
right: 0,
color: '#fff',
fontSize: '18px',
cursor: 'pointer'
}}
/>
<CommonModal
visible={visible}
title={title}
onClose={onClose}
width="60%"
bodyStyle={{ padding: 0, overflow: 'hidden' }}
>
<iframe
style={{
height: '100%',
@ -39,8 +20,7 @@ const PdfView = ({ visible, title, onClose, url, fileId }) => {
src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(url + fileId)}`}
title={title}
/>
</div>
</div>
</CommonModal>
)
}
export default PdfView