公共弹框添加生态流量,修改公共表格插槽
This commit is contained in:
parent
ebf6a57a31
commit
3ecf5c99d3
@ -3,7 +3,7 @@ NODE_ENV='production'
|
||||
|
||||
VITE_APP_TITLE = 'qgc-buji-web'
|
||||
VITE_APP_PORT = 3000
|
||||
VITE_APP_BASE_API = '/'
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
## 生产环境API地址
|
||||
VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||
## 生产环境导入预览地址
|
||||
|
||||
@ -62,3 +62,19 @@ export function getMonitorData(data: any) {
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量 -限制范围查询
|
||||
export function getEngLimit(data: any) {
|
||||
return request({
|
||||
url: '/eq/data/getEngLimit',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量 - 限制范围查询 - 日
|
||||
export function getEngLimitDay(data: any) {
|
||||
return request({
|
||||
url: '/eq/interval/qgc/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
@ -11,16 +11,27 @@
|
||||
:row-key="rowKey"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<!-- 透传插槽,支持自定义列内容 -->
|
||||
<template v-for="slot in Object.keys($slots)" #[slot]="scope" :key="slot">
|
||||
<slot :name="slot" v-bind="scope"></slot>
|
||||
<!-- 使用 bodyCell 插槽透传自定义列内容 -->
|
||||
<template #bodyCell="{ column, text, record, index }">
|
||||
<template v-for="slotName in customSlotNames" :key="slotName">
|
||||
<slot
|
||||
v-if="
|
||||
column._slotName === slotName || column.dataIndex === slotName
|
||||
"
|
||||
:name="slotName"
|
||||
:column="column"
|
||||
:text="text"
|
||||
:record="record"
|
||||
:index="index"
|
||||
></slot>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch, nextTick, h } from 'vue';
|
||||
import { ref, computed, onMounted, watch, nextTick, h, useSlots } from 'vue';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { calcTableScrollY } from '@/utils/index';
|
||||
|
||||
@ -129,6 +140,15 @@ const paginationConfig = computed(() => ({
|
||||
pageSizeOptions: ['20', '50', '100']
|
||||
}));
|
||||
|
||||
const $slots = useSlots();
|
||||
|
||||
// --- 自定义插槽名称列表 ---
|
||||
const customSlotNames = computed(() => {
|
||||
return Object.keys($slots).filter(
|
||||
name => name !== 'bodyCell' && name !== 'headerCell'
|
||||
);
|
||||
});
|
||||
|
||||
// --- Methods ---
|
||||
const getList = async (filter?: Record<string, any>) => {
|
||||
if (props.data.length > 0) return;
|
||||
@ -242,18 +262,34 @@ const processData = (records: any[]) => {
|
||||
});
|
||||
};
|
||||
|
||||
// --- 列配置增强(超出隐藏 + Tooltip)---
|
||||
// --- 列配置增强(超出隐藏 + Tooltip + 插槽兼容)---
|
||||
const enhancedColumns = computed(() => {
|
||||
if (!props.enableEllipsis) return props.columns;
|
||||
|
||||
return props.columns.map(col => {
|
||||
if (col.customRender) {
|
||||
return col; // 如果已有自定义渲染,则不覆盖
|
||||
// 如果有 slots.customRender,移除 slots(由 bodyCell 处理),保留 dataIndex 用于匹配
|
||||
if (col.slots?.customRender) {
|
||||
const { slots, ...restCol } = col;
|
||||
return {
|
||||
...restCol,
|
||||
// 保留 slotName 供 bodyCell 模板匹配使用
|
||||
_slotName: slots.customRender,
|
||||
...(props.enableEllipsis ? { ellipsis: true } : {})
|
||||
};
|
||||
}
|
||||
|
||||
// 如果已有 customRender 函数,直接返回
|
||||
if (col.customRender) {
|
||||
return {
|
||||
...col,
|
||||
...(props.enableEllipsis && !col.ellipsis ? { ellipsis: true } : {})
|
||||
};
|
||||
}
|
||||
|
||||
// 普通列,添加 ellipsis 和 tooltip
|
||||
if (!props.enableEllipsis) return col;
|
||||
|
||||
return {
|
||||
...col,
|
||||
ellipsis: true, // 启用 Ant Design Vue 原生的 ellipsis 支持
|
||||
ellipsis: true,
|
||||
customRender: ({ text }: any) => {
|
||||
const content = String(text ?? props.emptyPlaceholder);
|
||||
return h(Tooltip, { title: content }, () =>
|
||||
|
||||
@ -1,12 +1,550 @@
|
||||
<template>
|
||||
<div>
|
||||
生态流量
|
||||
<div class="ecological-flow">
|
||||
<!-- 顶部信息区 -->
|
||||
<div class="top-section">
|
||||
<div class="top-bar">
|
||||
<div class="info-row">
|
||||
<div class="info-item">
|
||||
<span class="label">累计不达标次数:</span>
|
||||
<span class="value" :style="{ color: '#1890ff' }">{{
|
||||
unqualifiedCount ?? '-'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">生态流量达标率:</span>
|
||||
<span class="value">{{
|
||||
complianceRate ? complianceRate + '%' : '-'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">生态流量限值{{ limitInfo || ':-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-row">
|
||||
<a-select
|
||||
v-model:value="timeType"
|
||||
style="width: 120px"
|
||||
:options="timeTypeOptions"
|
||||
/>
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
:format="dateFormat"
|
||||
:show-time="showTime ? showTimeConfig : false"
|
||||
:allowClear="false"
|
||||
style="margin-left: 12px"
|
||||
:presets="datePresets"
|
||||
/>
|
||||
<a-button
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="handleQuery"
|
||||
>查询</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部图表区 -->
|
||||
<div class="bottom-section">
|
||||
<a-spin :spinning="isChartLoading" tip="加载中...">
|
||||
<div class="chart-wrapper" ref="chartRef"></div>
|
||||
</a-spin>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref, onMounted, computed, watch, onUnmounted, nextTick } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { getEngLimit, getEngLimitDay } from '@/api/mapModal';
|
||||
import { useModelStore } from '@/store/modules/model';
|
||||
import { DateSetting } from '@/utils/enumeration';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const modelStore = useModelStore();
|
||||
|
||||
const props = defineProps({
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const hasLoaded = ref<boolean>(false); // 是否加载完成
|
||||
const isChartLoading = ref<boolean>(false);
|
||||
const unqualifiedCount = ref<number>(0);
|
||||
const complianceRate = ref<string>('');
|
||||
const limitInfo = ref<string>('');
|
||||
|
||||
// 筛选条件
|
||||
const timeType = ref<string>('day');
|
||||
const timeTypeOptions = [
|
||||
{ label: '日', value: 'day' },
|
||||
{ label: '小时', value: 'hour' }
|
||||
];
|
||||
|
||||
// 日期初始化:默认前一个月到当前
|
||||
const initDateRange = (): [dayjs.Dayjs, dayjs.Dayjs] => {
|
||||
const endDate = dayjs();
|
||||
const startDate = dayjs().subtract(1, 'month');
|
||||
return [startDate, endDate];
|
||||
};
|
||||
|
||||
const dateRange = ref<[dayjs.Dayjs, dayjs.Dayjs] | undefined>(initDateRange());
|
||||
|
||||
// 时间选择器配置
|
||||
const showTime = computed(() => timeType.value === 'hour');
|
||||
const dateFormat = computed(() =>
|
||||
timeType.value === 'hour' ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'
|
||||
);
|
||||
const datePresets = computed(() =>
|
||||
timeType.value === 'day'
|
||||
? DateSetting.RangeButton.month1
|
||||
: DateSetting.RangeButton.hour
|
||||
);
|
||||
const showTimeConfig = {
|
||||
format: 'HH:mm',
|
||||
hourStep: 1,
|
||||
minuteStep: 5,
|
||||
secondStep: 60
|
||||
};
|
||||
|
||||
// 获取日期范围参数
|
||||
const getDateRange = (): { startTime: string; endTime: string } => {
|
||||
if (dateRange.value) {
|
||||
return {
|
||||
startTime: dateRange.value[0].format('YYYY-MM-DD HH:mm:ss'),
|
||||
endTime: dateRange.value[1].format('YYYY-MM-DD HH:mm:ss')
|
||||
};
|
||||
}
|
||||
return {
|
||||
startTime: dayjs().startOf('month').format('YYYY-MM-DD HH:mm:ss'),
|
||||
endTime: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||
};
|
||||
};
|
||||
|
||||
// 查询限值信息
|
||||
const fetchLimitInfo = async () => {
|
||||
try {
|
||||
const stcd = modelStore.params.stcd;
|
||||
const { startTime, endTime } = getDateRange();
|
||||
|
||||
const res = await getEngLimit({
|
||||
filter: {
|
||||
logic: 'and',
|
||||
filters: [
|
||||
{ field: 'stcd', operator: 'eq', dataType: 'string', value: stcd },
|
||||
{
|
||||
field: 'startTime',
|
||||
operator: 'gte',
|
||||
dataType: 'date',
|
||||
value: startTime
|
||||
},
|
||||
{
|
||||
field: 'endTime',
|
||||
operator: 'gte',
|
||||
dataType: 'date',
|
||||
value: endTime
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
if (res?.data) {
|
||||
limitInfo.value = res.data.eqmnStr || '';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取限值信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 查询达标率和累计不达标次数
|
||||
const fetchDayData = async () => {
|
||||
try {
|
||||
const stcd = modelStore.params.stcd;
|
||||
const { startTime, endTime } = getDateRange();
|
||||
|
||||
const res = await getEngLimitDay({
|
||||
filter: {
|
||||
logic: 'and',
|
||||
filters: [
|
||||
{ field: 'stcd', operator: 'eq', dataType: 'string', value: stcd },
|
||||
{
|
||||
field: 'tm',
|
||||
operator: 'gte',
|
||||
dataType: 'date',
|
||||
value: startTime
|
||||
},
|
||||
{
|
||||
field: 'tm',
|
||||
operator: 'lte',
|
||||
dataType: 'date',
|
||||
value: endTime
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
if (res?.data && res?.data?.data && res?.data?.data[0]) {
|
||||
const record = res.data?.data[0]?.lastTmEngEqDataVo || res.data?.data[0];
|
||||
if (
|
||||
res.data?.data[0]?.qecRate !== null &&
|
||||
res.data?.data[0]?.qecRate !== undefined
|
||||
) {
|
||||
complianceRate.value = Number(res.data?.data[0]?.qecRate).toFixed(2);
|
||||
}
|
||||
if (record.qecC !== null && record.qecC !== undefined) {
|
||||
unqualifiedCount.value = record.qecC;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取日数据失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== 图表相关 ====================
|
||||
const chartRef = ref<HTMLDivElement | null>(null);
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
|
||||
// 生成模拟数据
|
||||
const getMockData = () => {
|
||||
const now = dayjs();
|
||||
const data: any[] = [];
|
||||
const count = timeType.value === 'hour' ? 48 : 30; // 小时显示48条,日显示30条
|
||||
for (let i = count - 1; i >= 0; i--) {
|
||||
const tm =
|
||||
timeType.value === 'hour'
|
||||
? now.subtract(i, 'hour').format('YYYY-MM-DD HH:mm:ss')
|
||||
: now.subtract(i, 'day').format('YYYY-MM-DD HH:mm:ss');
|
||||
data.push({
|
||||
tm,
|
||||
qi: Math.round(Math.random() * 100 + 150), // 入库流量 150-250
|
||||
qec: Math.round(Math.random() * 50 + 100), // 生态流量 100-150
|
||||
qecLimit: 145, // 生态流量限值固定
|
||||
qecSameLastYear: Math.round(Math.random() * 60 + 90) // 去年同期生态流量 90-150
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
// 更新图表
|
||||
const updateChart = (data: any[]) => {
|
||||
if (!chartInstance) return;
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
chartInstance.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// 按时间升序
|
||||
const sorted = [...data].sort(
|
||||
(a, b) => new Date(a.tm).getTime() - new Date(b.tm).getTime()
|
||||
);
|
||||
|
||||
const xAxisData = sorted.map(item => dayjs(item.tm).format('MM-DD HH:mm'));
|
||||
const qiData = sorted.map(item => item.qi);
|
||||
const qecData = sorted.map(item => item.qec);
|
||||
const qecLimitData = sorted.map(item => item.qecLimit);
|
||||
const qecSameLastYearData = sorted.map(item => item.qecSameLastYear);
|
||||
|
||||
// 计算 Y 轴最大值
|
||||
const flowValues = [
|
||||
...qiData,
|
||||
...qecData,
|
||||
...qecLimitData,
|
||||
...qecSameLastYearData
|
||||
].filter(v => v !== null && v !== undefined);
|
||||
const flowMax = flowValues.length > 0 ? Math.max(...flowValues) : 200;
|
||||
const flowYMax = Math.ceil(flowMax * 1.1);
|
||||
const flowYMin = Math.floor(Math.min(...flowValues) * 0.9);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(50, 50, 50, 0.9)',
|
||||
textStyle: { color: '#fff', fontSize: 12 },
|
||||
axisPointer: { type: 'cross' },
|
||||
formatter: (params: any) => {
|
||||
if (!params || params.length === 0) return '';
|
||||
const dataIndex = params[0].dataIndex;
|
||||
const fullTime = sorted[dataIndex]?.tm
|
||||
? dayjs(sorted[dataIndex].tm).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '';
|
||||
let html = `<div style="font-size:16px;margin-bottom:8px;">${fullTime}</div>`;
|
||||
// 系列名称对应的格式化规则
|
||||
const formatRules: Record<
|
||||
string,
|
||||
{ format: (v: number) => string; unit: string }
|
||||
> = {
|
||||
入库流量: { format: v => String(Math.round(v)), unit: '(m³/s)' },
|
||||
生态流量: { format: v => v.toFixed(1), unit: '(m³/s)' },
|
||||
生态流量限值: { format: v => v.toFixed(1), unit: '(m³/s)' },
|
||||
去年同期生态流量: { format: v => v.toFixed(1), unit: '(m³/s)' }
|
||||
};
|
||||
params.forEach((param: any) => {
|
||||
if (param.value == null) return;
|
||||
const rule = Object.entries(formatRules).find(([key]) =>
|
||||
param.seriesName.includes(key)
|
||||
);
|
||||
const displayValue = rule
|
||||
? rule[1].format(Number(param.value))
|
||||
: param.value;
|
||||
const unit = rule ? rule[1].unit : '';
|
||||
html += `
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin:4px 0;">
|
||||
<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:8px;"></span>
|
||||
<span style="flex:1;font-size:14px;text-align:left;margin-right:6px;">${param.seriesName}: </span>
|
||||
<span style="font-size:14px;min-width:60px;text-align:right;"><strong>${displayValue}</strong> ${unit}</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
return html;
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
type: 'scroll',
|
||||
top: 10,
|
||||
data: ['入库流量', '生态流量', '生态流量限值', '去年同期生态流量'],
|
||||
textStyle: { fontSize: 14, color: '#000' }
|
||||
},
|
||||
grid: {
|
||||
left: 60,
|
||||
right: 40,
|
||||
top: 80,
|
||||
bottom: 60
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
axisLine: { lineStyle: { color: '#000000' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
fontSize: 12
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: { color: '#bfbfbf', type: 'solid' }
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
name: '流量(m³/s)',
|
||||
type: 'value',
|
||||
position: 'left',
|
||||
axisLine: { lineStyle: { color: '#000000' } },
|
||||
scale: true,
|
||||
splitNumber: 9,
|
||||
boundaryGap: ['10%', 0]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '入库流量',
|
||||
type: 'line',
|
||||
data: qiData,
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4,
|
||||
lineStyle: { color: '#4B79AB', width: 2 },
|
||||
itemStyle: { color: '#4B79AB' }
|
||||
},
|
||||
{
|
||||
name: '生态流量',
|
||||
type: 'line',
|
||||
data: qecData,
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4,
|
||||
lineStyle: { color: '#00A050', width: 2 },
|
||||
itemStyle: { color: '#00A050' }
|
||||
},
|
||||
{
|
||||
name: '生态流量限值',
|
||||
type: 'line',
|
||||
data: qecLimitData,
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4,
|
||||
lineStyle: { color: '#F7A737', width: 2 },
|
||||
itemStyle: { color: '#F7A737' }
|
||||
},
|
||||
{
|
||||
name: '去年同期生态流量',
|
||||
type: 'line',
|
||||
data: qecSameLastYearData,
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4,
|
||||
lineStyle: { color: '#F1AFFF', width: 2 },
|
||||
itemStyle: { color: '#F1AFFF' }
|
||||
}
|
||||
],
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
xAxisIndex: [0],
|
||||
throttle: 50,
|
||||
start: 0,
|
||||
end: 100
|
||||
}
|
||||
],
|
||||
toolbox: {
|
||||
show: true,
|
||||
feature: {
|
||||
saveAsImage: { title: '保存为图片', type: 'png', pixelRatio: 2 }
|
||||
},
|
||||
right: 20,
|
||||
top: 10
|
||||
}
|
||||
};
|
||||
|
||||
chartInstance.setOption(option, true);
|
||||
};
|
||||
|
||||
const initChart = () => {
|
||||
console.log(chartRef.value);
|
||||
if (!chartRef.value) return;
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose();
|
||||
}
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
};
|
||||
|
||||
const handleResize = () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.resize();
|
||||
}
|
||||
};
|
||||
|
||||
const destroyChart = () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose();
|
||||
chartInstance = null;
|
||||
}
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
|
||||
// 请求图表数据(预留接口调用)
|
||||
const fetchChartData = async () => {
|
||||
isChartLoading.value = true;
|
||||
try {
|
||||
// TODO: 替换为实际接口调用
|
||||
// const stcd = modelStore.params.stcd;
|
||||
// const { startTime, endTime } = getDateRange();
|
||||
// const res = await getEngChartList({ ... });
|
||||
// updateChart(res?.data?.data || []);
|
||||
|
||||
// 模拟 2 秒 loading
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// 使用模拟数据
|
||||
const mockData = getMockData();
|
||||
updateChart(mockData);
|
||||
hasLoaded.value = true;
|
||||
} catch (error) {
|
||||
console.error('获取图表数据失败:', error);
|
||||
} finally {
|
||||
isChartLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 查询按钮
|
||||
const handleQuery = () => {
|
||||
fetchLimitInfo();
|
||||
fetchDayData();
|
||||
fetchChartData();
|
||||
};
|
||||
|
||||
// 监听 timeType 切换时重置日期范围
|
||||
watch(timeType, () => {
|
||||
dateRange.value = initDateRange();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.isActive,
|
||||
active => {
|
||||
if (active && !hasLoaded.value) {
|
||||
fetchLimitInfo();
|
||||
fetchDayData();
|
||||
// 初始化图表
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
initChart();
|
||||
fetchChartData();
|
||||
}, 2000);
|
||||
});
|
||||
window.addEventListener('resize', handleResize);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onMounted(() => {});
|
||||
|
||||
onUnmounted(() => {
|
||||
destroyChart();
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ecological-flow {
|
||||
.top-section {
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
|
||||
.top-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.info-item {
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-section {
|
||||
height: 530px;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
:deep(.ant-spin-nested-loading) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
:deep(.ant-spin-container) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -10,6 +10,7 @@
|
||||
:format="dateFormat"
|
||||
:show-time="showTime ? showTimeConfig : false"
|
||||
:allowClear="false"
|
||||
:presets="DateSetting.RangeButton.month1"
|
||||
:disabled-date="disabledDate"
|
||||
>
|
||||
</a-range-picker>
|
||||
@ -49,6 +50,7 @@ import dayjs, { Dayjs } from 'dayjs';
|
||||
import { getMonitorData } from '@/api/mapModal';
|
||||
import { useModelStore } from '@/store/modules/model';
|
||||
import BasicTable from '@/components/BasicTable/index.vue';
|
||||
import { DateSetting } from '@/utils/enumeration';
|
||||
|
||||
const modelStore = useModelStore();
|
||||
|
||||
@ -298,13 +300,33 @@ const updateChart = (data: any[]) => {
|
||||
const fullTime = sorted[dataIndex]?.tm
|
||||
? dayjs(sorted[dataIndex].tm).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '';
|
||||
let html = `<div style="font-size:14px;margin-bottom:8px;">${fullTime}</div>`;
|
||||
let html = `<div style="font-size:16px;margin-bottom:8px;">${fullTime}</div>`;
|
||||
// 系列名称对应的格式化规则(与表格保持一致)
|
||||
const formatRules: Record<
|
||||
string,
|
||||
{ format: (v: number) => string; unit: string }
|
||||
> = {
|
||||
坝上水位: { format: v => v.toFixed(2), unit: '(m)' },
|
||||
坝下水位: { format: v => v.toFixed(2), unit: '(m)' },
|
||||
入库流量: { format: v => String(Math.round(v)), unit: '(m³/s)' },
|
||||
出库流量: { format: v => String(Number(v)), unit: '(m³/s)' },
|
||||
生态流量: { format: v => v.toFixed(1), unit: '(m³/s)' },
|
||||
生态流量限值: { format: v => v.toFixed(1), unit: '(m³/s)' }
|
||||
};
|
||||
params.forEach((param: any) => {
|
||||
const value = param.value != null ? param.value : '-';
|
||||
if (param.value == null) return;
|
||||
const rule = Object.entries(formatRules).find(([key]) =>
|
||||
param.seriesName.includes(key)
|
||||
);
|
||||
const displayValue = rule
|
||||
? rule[1].format(Number(param.value))
|
||||
: param.value;
|
||||
const unit = rule ? rule[1].unit : '';
|
||||
html += `
|
||||
<div style="display:flex;align-items:center;margin:4px 0;">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin:4px 0;">
|
||||
<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:8px;"></span>
|
||||
<span style="font-size:14px;">${param.seriesName}: ${value}</span>
|
||||
<span style="flex:1;font-size:14px;text-align:left;margin-right:6px;">${param.seriesName}: </span>
|
||||
<span style="font-size:14px;min-width:60px;text-align:right;"><strong>${displayValue}</strong> ${unit}</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
@ -464,7 +486,7 @@ const updateChart = (data: any[]) => {
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 4,
|
||||
lineStyle: { color: '#F7A737', width: 2, type: 'dashed' },
|
||||
lineStyle: { color: '#F7A737', width: 2 },
|
||||
itemStyle: { color: '#F7A737' },
|
||||
markPoint: {
|
||||
data: [
|
||||
|
||||
@ -19,24 +19,8 @@
|
||||
:disabled-date="disabledDate"
|
||||
:allow-clear="false"
|
||||
@change="handleDateChange"
|
||||
>
|
||||
<template #renderExtraFooter>
|
||||
<div class="quick-date-options">
|
||||
<a-button size="small" @click="setQuickRange(7)"
|
||||
>最近七天</a-button
|
||||
>
|
||||
<a-button size="small" @click="setQuickRange(30)"
|
||||
>最近一个月</a-button
|
||||
>
|
||||
<a-button size="small" @click="setQuickRange(90)"
|
||||
>最近三个月</a-button
|
||||
>
|
||||
<a-button size="small" @click="setQuickRange(180)"
|
||||
>最近六个月</a-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</a-range-picker>
|
||||
:presets="DateSetting.RangeButton.month1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body_body">
|
||||
@ -79,6 +63,7 @@ import dayjs, { Dayjs } from 'dayjs';
|
||||
import { useModelStore } from '@/store/modules/model';
|
||||
import { infoGetKendoListCust, fishGetKendoListCust } from '@/api/sw';
|
||||
import BasicTable from '@/components/BasicTable/index.vue';
|
||||
import { DateSetting } from '@/utils/enumeration';
|
||||
const modelStore = useModelStore();
|
||||
const selectOption = ref([]);
|
||||
const selectValue = ref([]);
|
||||
|
||||
@ -9,6 +9,14 @@
|
||||
:destroyOnClose="true"
|
||||
class="map-modal"
|
||||
>
|
||||
<!-- 问题:
|
||||
1.基础信息图片展示是什么逻辑
|
||||
2. 电站专题展示逻辑
|
||||
3. 实时视频回放 少接口
|
||||
4. 预警提示 少接口
|
||||
5. 生态流量 达标率查询不对
|
||||
6. 鱼类适应性繁殖同期对比NAN (王)
|
||||
-->
|
||||
<div v-if="modelStore.showStcdSelector" class="stcd-selector-wrapper">
|
||||
<a-select
|
||||
v-model:value="modelStore.params.stcd"
|
||||
@ -65,6 +73,11 @@
|
||||
:tabs-items="getTabChildren('tableTabs')"
|
||||
:is-active="currentActiveKey === 'tableTabs'"
|
||||
/>
|
||||
<!-- 生态流量 -->
|
||||
<EcologicalFlow
|
||||
v-show="currentActiveKey === 'EcologicalFlow'"
|
||||
:is-active="currentActiveKey === 'EcologicalFlow'"
|
||||
/>
|
||||
<!-- 鱼类繁殖适宜性分析 -->
|
||||
<WaterTemperatureRep
|
||||
v-show="currentActiveKey === 'WaterTemperatureRep'"
|
||||
@ -99,6 +112,7 @@ import VideoInfo from './components/videoInfo.vue'; // 实时视频
|
||||
import PanoramaInfo from './components/PanoramaInfo.vue'; // 全景影像
|
||||
import MonitorInfo from './components/MonitorInfo.vue'; // 监测数据
|
||||
import EarlyWarningAlert from './components/EarlyWarningAlert.vue'; // 预警提示
|
||||
import EcologicalFlow from './components/EcologicalFlow.vue'; // 生态流量
|
||||
import Attachment from './components/Attachment.vue'; // 查看报告/批复文件
|
||||
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; // 水温对比数据
|
||||
import { useModelStore } from '@/store/modules/model';
|
||||
|
||||
@ -108,90 +108,95 @@ const ENGTabs: Array<any> = [
|
||||
// }
|
||||
].filter(Boolean);
|
||||
// // 水电站生态流量 √
|
||||
// const ENGEQTabs: Array<any> = [
|
||||
// {
|
||||
// name: '基础信息',
|
||||
// key: 'basicInfo',
|
||||
// type: 'basic',
|
||||
// url: '/bbi/siteBipc/getSiteBasicInfo'
|
||||
// },
|
||||
// {
|
||||
// name: '实时视频',
|
||||
// key: 'videoInfo',
|
||||
// type: 'video',
|
||||
// url: '/video/dataStcdFrame/getVideoMonitorList'
|
||||
// },
|
||||
// {
|
||||
// name: '全景影像',
|
||||
// key: 'panoramaInfo',
|
||||
// type: 'panorama'
|
||||
// },
|
||||
// {
|
||||
// name: '监测数据',
|
||||
// key: 'monitorInfo',
|
||||
// type: 'tabsWithTwo',
|
||||
// code: 'dzxq.tabs.jcsj'
|
||||
// },
|
||||
// {
|
||||
// name: '预警提示',
|
||||
// key: 'tableTabs',
|
||||
// type: 'tableTabs',
|
||||
// code: 'dzxq-yjts',
|
||||
// tabs: [
|
||||
// {
|
||||
// name: '设计参数变更提示',
|
||||
// key: 'DesignParameterChangePrompt',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/GetKendoList'
|
||||
// },
|
||||
// {
|
||||
// name: '施工期环保措施落实预警',
|
||||
// key: 'ImplementEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/sgqhbss/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '环保设施建设预警',
|
||||
// key: 'ConstructionEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/hbssjs/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '环保设施运行预警',
|
||||
// key: 'RunEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/hbssyx/GetKendoListCust'
|
||||
// },
|
||||
// {
|
||||
// name: '鱼类放流预警',
|
||||
// key: 'ReleaseEarlyWarning',
|
||||
// type: 'table',
|
||||
// hiddenChart: true,
|
||||
// tableUrl: '/dec-lygk-base-server/base/engWarning/ylfl/GetKendoListCust'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// name: '生态流量',
|
||||
// key: 'EcologicalFlow',
|
||||
// type: 'EcologicalFlow'
|
||||
// },
|
||||
// Session.getAppCode() === 'hbb' ? {
|
||||
// name: '查看报告',
|
||||
// key: 'attachment',
|
||||
// type: 'attachment'
|
||||
// } : null,
|
||||
// {
|
||||
// name: '批复文件',
|
||||
// key: 'approval',
|
||||
// type: 'approval'
|
||||
// },
|
||||
|
||||
// ].filter(Boolean)
|
||||
const ENGEQTabs: Array<any> = [
|
||||
{
|
||||
name: '基础信息',
|
||||
key: 'basicInfo',
|
||||
type: 'basic',
|
||||
url: '/api/dec-lygk-base-server/base/msstbprpt/getStcdInfo',
|
||||
default: true // 默认显示
|
||||
},
|
||||
{
|
||||
name: '实时视频',
|
||||
key: 'videoInfo',
|
||||
type: 'video',
|
||||
url: '/video/dataStcdFrame/getVideoMonitorList'
|
||||
},
|
||||
{
|
||||
name: '全景影像',
|
||||
key: 'panoramaInfo',
|
||||
type: 'panorama'
|
||||
},
|
||||
{
|
||||
name: '监测数据',
|
||||
key: 'monitorInfo',
|
||||
type: 'tabsWithTwo',
|
||||
code: 'dzxq.tabs.jcsj'
|
||||
},
|
||||
{
|
||||
name: '预警提示',
|
||||
key: 'tableTabs',
|
||||
type: 'tableTabs',
|
||||
code: 'dzxq-yjts',
|
||||
tabs: [
|
||||
{
|
||||
name: '设计参数变更提示',
|
||||
key: 'DesignParameterChangePrompt',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl: '/dec-lygk-base-server/base/engWarning/GetKendoList'
|
||||
},
|
||||
{
|
||||
name: '施工期环保措施落实预警',
|
||||
key: 'ImplementEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/sgqhbss/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '环保设施建设预警',
|
||||
key: 'ConstructionEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/hbssjs/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '环保设施运行预警',
|
||||
key: 'RunEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl:
|
||||
'/dec-lygk-base-server/base/engWarning/hbssyx/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '鱼类放流预警',
|
||||
key: 'ReleaseEarlyWarning',
|
||||
type: 'table',
|
||||
hiddenChart: true,
|
||||
tableUrl: '/dec-lygk-base-server/base/engWarning/ylfl/GetKendoListCust'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '生态流量',
|
||||
key: 'EcologicalFlow',
|
||||
type: 'EcologicalFlow'
|
||||
},
|
||||
{
|
||||
name: '查看报告',
|
||||
key: 'attachment',
|
||||
type: 'attachment',
|
||||
url: '/eq/fid/GetKendoListCust'
|
||||
},
|
||||
{
|
||||
name: '批复文件',
|
||||
key: 'approval',
|
||||
type: 'approval',
|
||||
url: '/eng/base/eiaapproval/GetKendoList'
|
||||
}
|
||||
].filter(Boolean);
|
||||
|
||||
// // 水电站生态流量 - 江局单独看 √
|
||||
// const ENGEQTabsJuangJu: Array<any> = [
|
||||
@ -1199,7 +1204,11 @@ const handleTabs = (modaldata: any) => {
|
||||
console.log('sttp', sttp);
|
||||
switch (sttp) {
|
||||
case 'ENG':
|
||||
return ENGTabs;
|
||||
if (modaldata?.eqtp == 'QEC') {
|
||||
return ENGEQTabs;
|
||||
} else {
|
||||
return ENGTabs;
|
||||
}
|
||||
case 'WT_POINT':
|
||||
return WTTabs;
|
||||
case 'FH_WQ_POINT':
|
||||
@ -1239,15 +1248,16 @@ const handleTabs = (modaldata: any) => {
|
||||
return DEVICETABS;
|
||||
case 'DW_1':
|
||||
return DEVICETABS;
|
||||
//
|
||||
// if (modaldata?.eqtp == 'QEC') {
|
||||
// const { page } = Utility.parseQueryString()
|
||||
// if (page == 'shengTaiLiuLiangManZuQingKuangJiangJu') {
|
||||
// return ENGEQTabsJuangJu
|
||||
// } else {
|
||||
// return ENGEQTabs
|
||||
// }
|
||||
// } else {
|
||||
//
|
||||
if (modaldata?.eqtp == 'QEC') {
|
||||
// const { page } = Utility.parseQueryString()
|
||||
// if (page == 'shengTaiLiuLiangManZuQingKuangJiangJu') {
|
||||
// return ENGEQTabsJuangJu
|
||||
// } else {
|
||||
return ENGEQTabs;
|
||||
// }
|
||||
}
|
||||
// else {
|
||||
// return Session.getAppCode() === 'hbb' ? ENGTabs.filter((e) => e.name !== '阶段属性') : ENGTabs
|
||||
// }
|
||||
// case 'ENG_ALARM':
|
||||
|
||||
@ -281,6 +281,38 @@ namespace DateSetting {
|
||||
value: [getStartTime().subtract(1, 'year'), getStartTime()]
|
||||
}
|
||||
],
|
||||
month1: [
|
||||
{
|
||||
label: '最近7天',
|
||||
value: [getStartTime().subtract(6, 'day'), getStartTime()]
|
||||
},
|
||||
{
|
||||
label: '最近1个月',
|
||||
value: [getStartTime().subtract(1, 'month'), getStartTime()]
|
||||
},
|
||||
{
|
||||
label: '最近3个月',
|
||||
value: [getStartTime().subtract(3, 'month'), getStartTime()]
|
||||
},
|
||||
{
|
||||
label: '最近6个月',
|
||||
value: [getStartTime().subtract(6, 'month'), getStartTime()]
|
||||
}
|
||||
],
|
||||
hour: [
|
||||
{
|
||||
label: '最近7小时',
|
||||
value: [getStartTime().subtract(7, 'hour'), getStartTime()]
|
||||
},
|
||||
{
|
||||
label: '最近24小时',
|
||||
value: [getStartTime().subtract(24, 'hour'), getStartTime()]
|
||||
},
|
||||
{
|
||||
label: '最近一周',
|
||||
value: [getStartTime().subtract(7, 'day'), getStartTime()]
|
||||
}
|
||||
],
|
||||
season: [
|
||||
{
|
||||
label: '第一季度',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user