WholeProcessPlatform/frontend-sjgl/src/views/monitorData/Export/index.vue
2026-09-02 10:44:17 +08:00

531 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="export-container body_one">
<a-form
ref="formRef"
:model="formData"
:labelCol="{ span: 2 }"
:wrapperCol="{ span: 18 }"
class="export-form"
>
<!-- 时间维度 -->
<a-form-item label="时间维度" name="timeDimension">
<a-radio-group v-model:value="formData.timeDimension">
<a-radio value="month">月度统计</a-radio>
<a-radio value="year">年统计</a-radio>
<a-radio value="day">日统计</a-radio>
<a-radio value="hour">时统计</a-radio>
</a-radio-group>
</a-form-item>
<!-- 月度统计 -->
<template v-if="formData.timeDimension !== 'year'">
<a-form-item label="统计监测要素" name="monitorElements">
<a-checkbox-group v-model:value="formData.monitorElements">
<a-checkbox
v-for="item in dataFieldOption"
:value="item.itemCode"
>{{ item.dictName }}</a-checkbox
>
</a-checkbox-group>
</a-form-item>
<a-form-item label="选择水电站">
<a-row :gutter="16">
<a-col :span="6">
<a-select
v-model:value="formData.rvcd"
placeholder="请选择水电基地"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="rvcdLoading"
@change="handleRvcdChange"
style="width: 100%"
:max-tag-count="2"
>
<a-select-option
v-for="item in rvcdOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-col>
<a-col :span="6">
<a-select
v-model:value="formData.stations"
placeholder="请选择水电站"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="stationLoading"
style="width: 100%"
:max-tag-count="2"
>
<a-select-option
v-for="item in stationOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-col>
</a-row>
</a-form-item>
<a-form-item label="统计月份" name="statMonths">
<a-tree-select
v-model:value="formData.statMonths"
:tree-data="monthTreeData"
placeholder="请选择统计月份"
tree-checkable
:fieldNames="{
label: 'title',
value: 'value',
children: 'children'
}"
tree-node-filter-prop="title"
show-search
allow-clear
style="width: 400px"
/>
</a-form-item>
<a-form-item
label="数据来源"
name="dataSource"
v-if="formData.timeDimension === 'month'"
>
<a-radio-group v-model:value="formData.dataSource">
<a-radio value="true">日统计表</a-radio>
<a-radio value="false">小时表</a-radio>
</a-radio-group>
</a-form-item>
</template>
<!-- 年统计 -->
<template v-if="formData.timeDimension === 'year'">
<a-form-item label="统计内容" name="yearStatContent">
<a-checkbox-group v-model:value="formData.yearStatContent">
<a-checkbox value="wq">水质</a-checkbox>
<a-checkbox value="qec">生态流量达标率</a-checkbox>
</a-checkbox-group>
</a-form-item>
<a-form-item label="统计年份" name="statYears">
<a-select
v-model:value="formData.statYears"
placeholder="请选择统计年份"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
style="width: 300px"
:max-tag-count="2"
>
<a-select-option
v-for="item in yearOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="统计维度与内容" name="dimensionStat">
<a-checkbox-group
v-model:value="formData.yearDimContent"
style="width: 100%"
>
<a-row>
<a-col :span="24" style="margin-bottom: 10px">
<div style="display: flex; align-items: center">
<a-checkbox value="stcd">电站:</a-checkbox>
<a-select
v-model:value="formData.rvcd"
placeholder="请选择水电基地"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="rvcdLoading"
@change="handleRvcdChange"
style="width: 200px; margin-right: 10px"
:max-tag-count="2"
>
<a-select-option
v-for="item in rvcdOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
<a-select
v-model:value="formData.stations"
placeholder="请选择水电站"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="stationLoading"
style="width: 300px"
:max-tag-count="2"
>
<a-select-option
v-for="item in stationOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</div>
</a-col>
<a-col :span="24" style="margin-bottom: 10px">
<div style="display: flex; align-items: center">
<a-checkbox value="baseId">基地:</a-checkbox>
<a-select
v-model:value="formData.rvcd"
placeholder="请选择水电基地"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="rvcdLoading"
@change="handleRvcdChange"
style="width: 200px; margin-right: 10px"
:max-tag-count="2"
>
<a-select-option
v-for="item in rvcdOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</div>
</a-col>
<a-col :span="24">
<div style="display: flex; align-items: center">
<a-checkbox value="ly">流域</a-checkbox>
<a-select
v-model:value="formData.lyRvcd"
placeholder="请选择流域"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="lyLoading"
style="width: 200px; margin-right: 10px"
:max-tag-count="2"
>
<a-select-option
v-for="item in lyOptions"
:key="item.value"
:value="item.value"
:label="item.label"
>
{{ item.label }}
</a-select-option>
</a-select>
</div>
</a-col>
</a-row>
</a-checkbox-group>
</a-form-item>
</template>
<!-- 导出按钮 -->
<a-form-item :wrapperCol="{ offset: 6, span: 18 }">
<a-button type="primary" :loading="exportLoading" @click="handleExport">
导出
</a-button>
</a-form-item>
</a-form>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue';
import { message } from 'ant-design-vue';
import {
getSelectForDropdown,
getEngInfoDropdown,
qgcExportCreate,
qgcExportstatus,
qgcExportdownload
} from '@/api/select';
import { getDictItemsByCode } from '@/api/dict';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
const formRef = ref<any>();
const exportLoading = ref(false);
const rvcdLoading = ref(false);
const stationLoading = ref(false);
const JidiSelectEventStore = useJidiSelectEventStore();
// 流域下拉选项
const rvcdOptions = ref<{ label: string; value: string }[]>([]);
// 水电站下拉选项
const stationOptions = ref<{ label: string; value: string }[]>([]);
// 流域下拉选项
const lyOptions = ref<{ label: string; value: string }[]>([]);
const lyLoading = ref(false);
// 表单数据
const formData = reactive({
timeDimension: 'month',
// 月度统计
monitorElements: [] as string[],
rvcd: [] as string[],
stations: [] as string[],
statMonths: [] as string[],
dataSource: 'true',
// 年统计
yearStatContent: [] as string[],
statYears: [] as string[],
yearDimContent: [] as string[],
lyRvcd: [] as string[],
dimensionStat: '',
content: ''
});
// 统计月份树数据当前年往前26年
const monthTreeData = computed(() => {
const currentYear = new Date().getFullYear();
const years: any[] = [];
for (let y = currentYear; y >= currentYear - 26; y--) {
years.push({
title: `${y}`,
value: `year_${y}`,
children: Array.from({ length: 12 }, (_, i) => ({
title: `${y}-${i + 1}`,
value: `${y}-${String(i + 1).padStart(2, '0')}`
}))
});
}
return years;
});
// 默认选中当前年月
const getDefaultStatMonths = () => {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
return [`${year}-${String(month).padStart(2, '0')}`];
};
// 统计年份选项当前年往前26年
const yearOptions = computed(() => {
const currentYear = new Date().getFullYear();
const years: { label: string; value: string }[] = [];
for (let y = currentYear; y >= currentYear - 26; y--) {
years.push({ label: `${y}`, value: `${y}` });
}
return years;
});
// 搜索过滤
const filterOption = (input: string, option: any) => {
return (option?.label || '').toLowerCase().includes(input.toLowerCase());
};
// 加载水电站数据
const loadStationOptions = async (rvcds?: string[]) => {
stationLoading.value = true;
try {
const res = await getEngInfoDropdown({ baseIds: rvcds || [] });
if (res?.data) {
stationOptions.value = (res.data || []).map((item: any) => ({
label: item.ennm || item.stnm || item.label || item.name,
value: item.stcd || item.engId || item.value || item.id
}));
// 默认全选所有电站
formData.stations = stationOptions.value.map(item => item.value);
}
} catch (e) {
console.error('获取水电站列表失败', e);
} finally {
stationLoading.value = false;
}
};
// 加载基地数据(监听 store 数据就绪后执行一次)
const initDone = ref(false);
watch(
() => JidiSelectEventStore.jidiData,
val => {
if (initDone.value) return;
const data = (val || []).filter((item: any) => item.wbsCode !== 'all');
if (data.length === 0) return;
rvcdOptions.value = data.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}));
formData.rvcd = [rvcdOptions.value[0].value];
loadStationOptions(formData.rvcd);
initDone.value = true;
},
{ immediate: true }
);
// 流域变化时重新加载水电站
const handleRvcdChange = (values: string[]) => {
formData.stations = [];
loadStationOptions(values);
};
// 加载流域数据
const loadLyOptions = async () => {
lyLoading.value = true;
try {
const res = await getSelectForDropdown({});
if (res?.data) {
lyOptions.value = (res.data || []).map((item: any) => ({
label: item.rvnm,
value: item.rvcd
}));
// 默认选中第一条
if (lyOptions.value.length > 0) {
formData.lyRvcd = [lyOptions.value[0].value];
}
}
} catch (e) {
console.error('获取流域列表失败', e);
} finally {
lyLoading.value = false;
}
};
const dataOptions = ref([
{ itemCode: 'month', dictName: '月度报表' },
{ itemCode: 'year', dictName: '年度报表' },
{ itemCode: 'day', dictName: '日度报表' },
{ itemCode: 'hour', dictName: '小时报表' }
]);
const getExstatus = async (taskId, exportParams) => {
let res1: any = await qgcExportstatus({ taskId: taskId });
if (res1.status == 'PROCESSING') {
setTimeout(() => {
getExstatus(taskId, exportParams);
}, 5000);
} else if (res1.status == 'DONE') {
const blob: any = await qgcExportdownload({
taskId: taskId,
...exportParams
});
// 触发浏览器下载
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const matched = dataOptions.value.find((item:any) => item.itemCode == formData.timeDimension);
a.download =`${matched.dictName}.zip`;
a.click();
window.URL.revokeObjectURL(url);
exportLoading.value = false;
message.success('导出成功');
} else {
message.error('导出失败');
}
};
// 导出
const handleExport = async () => {
exportLoading.value = true;
try {
if (formData.timeDimension !== 'year') {
const params: any = {
tmDimension: formData.timeDimension,
dataField: formData.monitorElements.join(','),
months: formData.statMonths.join(','),
stcd: formData.stations.join(','),
sysId: 'qgc',
isCalcQec: true
};
if (formData.timeDimension === 'month') {
params.isDailyDimension = formData.dataSource === 'day';
}
console.log(`${formData.timeDimension}统计导出参数:`, params);
let res: any = await qgcExportCreate(params);
if (res.taskId) {
getExstatus(res.taskId, params);
}
} else {
const params: any = {
tmDimension: 'year',
yearStatType: formData.yearStatContent.join(','),
year: formData.statYears.join(','),
sysId: 'qgc'
};
// 只传选中项的数据
if (formData.yearDimContent.includes('stcd')) {
params.stcd = formData.stations.join(',');
}
if (formData.yearDimContent.includes('baseId')) {
params.baseId = formData.rvcd.join(',');
}
if (formData.yearDimContent.includes('ly')) {
params.hbRvcd = formData.lyRvcd.join(',');
}
console.log('年统计导出参数:', params);
let res: any = await qgcExportCreate(params);
if (res.taskId) {
getExstatus(res.taskId, params);
}
}
message.success('导出任务已提交');
} catch (e) {
message.error('导出失败');
} finally {
// exportLoading.value = false;
}
};
const dataFieldOption = ref([]);
const getDict = async () => {
let res = await getDictItemsByCode({ dictCode: 'dataField' });
dataFieldOption.value = res.data;
formData.monitorElements = dataFieldOption.value.map(item => item.itemCode);
};
onMounted(() => {
getDict();
formData.statMonths = getDefaultStatMonths();
formData.yearStatContent = ['wq', 'qec'];
formData.yearDimContent = ['stcd', 'baseId'];
formData.statYears = [String(new Date().getFullYear())];
loadLyOptions();
});
</script>
<style scoped lang="scss">
.export-container {
padding: 20px;
// max-width: 800px;
width: 100%;
.export-form {
:deep(.ant-form-item) {
margin-bottom: 20px;
}
}
}
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
// .export-container{
// }
</style>