WholeProcessPlatform/frontend-sjgl/src/views/monitorData/Export/index.vue

531 lines
17 KiB
Vue
Raw Normal View History

2026-07-20 16:02:51 +08:00
<template>
2026-07-31 11:13:49 +08:00
<div class="export-container body_one">
2026-07-20 16:02:51 +08:00
<a-form
ref="formRef"
2026-09-02 10:44:17 +08:00
:model="formData"
:labelCol="{ span: 2 }"
2026-07-20 16:02:51 +08:00
: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>
2026-07-20 16:02:51 +08:00
</a-radio-group>
</a-form-item>
<!-- 月度统计 -->
<template v-if="formData.timeDimension !== 'year'">
2026-07-20 16:02:51 +08:00
<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
>
2026-07-20 16:02:51 +08:00
</a-checkbox-group>
</a-form-item>
<a-form-item label="选择水电站">
<a-row :gutter="16">
<a-col :span="6">
2026-07-20 16:02:51 +08:00
<a-select
v-model:value="formData.rvcd"
placeholder="请选择水电基地"
2026-07-20 16:02:51 +08:00
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="rvcdLoading"
@change="handleRvcdChange"
style="width: 100%"
:max-tag-count="2"
2026-07-20 16:02:51 +08:00
>
<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">
2026-07-20 16:02:51 +08:00
<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"
2026-07-20 16:02:51 +08:00
>
<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"
2026-07-20 16:02:51 +08:00
/>
</a-form-item>
2026-09-02 10:44:17 +08:00
<a-form-item
label="数据来源"
name="dataSource"
v-if="formData.timeDimension === 'month'"
>
2026-07-20 16:02:51 +08:00
<a-radio-group v-model:value="formData.dataSource">
<a-radio value="true">日统计表</a-radio>
<a-radio value="false">小时表</a-radio>
2026-07-20 16:02:51 +08:00
</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>
2026-07-20 16:02:51 +08:00
</a-checkbox-group>
</a-form-item>
<a-form-item label="统计年份" name="statYears">
<a-select
2026-07-20 16:02:51 +08:00
v-model:value="formData.statYears"
placeholder="请选择统计年份"
mode="multiple"
2026-07-20 16:02:51 +08:00
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>
2026-07-20 16:02:51 +08:00
</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
2026-09-02 10:44:17 +08:00
v-model:value="formData.rvcd"
placeholder="请选择水电基地"
mode="multiple"
allow-clear
show-search
:filter-option="filterOption"
:loading="rvcdLoading"
2026-09-02 10:44:17 +08:00
@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>
2026-07-20 16:02:51 +08:00
</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';
2026-07-20 16:02:51 +08:00
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';
2026-07-20 16:02:51 +08:00
const formRef = ref<any>();
const exportLoading = ref(false);
const rvcdLoading = ref(false);
const stationLoading = ref(false);
const JidiSelectEventStore = useJidiSelectEventStore();
2026-07-20 16:02:51 +08:00
// 流域下拉选项
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);
2026-07-20 16:02:51 +08:00
// 表单数据
const formData = reactive({
timeDimension: 'month',
2026-07-20 16:02:51 +08:00
// 月度统计
monitorElements: [] as string[],
rvcd: [] as string[],
stations: [] as string[],
statMonths: [] as string[],
dataSource: 'true',
2026-07-20 16:02:51 +08:00
// 年统计
yearStatContent: [] as string[],
statYears: [] as string[],
yearDimContent: [] as string[],
lyRvcd: [] as string[],
2026-07-20 16:02:51 +08:00
dimensionStat: '',
content: ''
});
// 统计月份树数据当前年往前26年
2026-07-20 16:02:51 +08:00
const monthTreeData = computed(() => {
const currentYear = new Date().getFullYear();
const years: any[] = [];
for (let y = currentYear; y >= currentYear - 26; y--) {
2026-07-20 16:02:51 +08:00
years.push({
title: `${y}`,
2026-07-20 16:02:51 +08:00
value: `year_${y}`,
children: Array.from({ length: 12 }, (_, i) => ({
title: `${y}-${i + 1}`,
2026-07-20 16:02:51 +08:00
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')}`];
};
2026-07-20 16:02:51 +08:00
// 统计年份选项当前年往前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}` });
2026-07-20 16:02:51 +08:00
}
return years;
2026-07-20 16:02:51 +08:00
});
// 搜索过滤
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 || [] });
2026-07-20 16:02:51 +08:00
if (res?.data) {
stationOptions.value = (res.data || []).map((item: any) => ({
label: item.ennm || item.stnm || item.label || item.name,
2026-07-20 16:02:51 +08:00
value: item.stcd || item.engId || item.value || item.id
}));
// 默认全选所有电站
formData.stations = stationOptions.value.map(item => item.value);
2026-07-20 16:02:51 +08:00
}
} catch (e) {
console.error('获取水电站列表失败', e);
} finally {
stationLoading.value = false;
}
};
// 加载基地数据(监听 store 数据就绪后执行一次)
const initDone = ref(false);
watch(
() => JidiSelectEventStore.jidiData,
2026-09-02 10:44:17 +08:00
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 }
);
2026-07-20 16:02:51 +08:00
// 流域变化时重新加载水电站
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;
}
};
2026-09-02 10:44:17 +08:00
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') {
2026-09-02 10:44:17 +08:00
const blob: any = await qgcExportdownload({
taskId: taskId,
...exportParams
});
// 触发浏览器下载
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
2026-09-02 10:44:17 +08:00
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('导出失败');
}
};
2026-07-20 16:02:51 +08:00
// 导出
const handleExport = async () => {
2026-07-20 16:02:51 +08:00
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);
}
2026-07-20 16:02:51 +08:00
} 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(',');
}
2026-09-02 10:44:17 +08:00
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);
}
2026-07-20 16:02:51 +08:00
}
message.success('导出任务已提交');
} catch (e) {
message.error('导出失败');
} finally {
2026-09-02 10:44:17 +08:00
// exportLoading.value = false;
2026-07-20 16:02:51 +08:00
}
};
const dataFieldOption = ref([]);
const getDict = async () => {
let res = await getDictItemsByCode({ dictCode: 'dataField' });
dataFieldOption.value = res.data;
formData.monitorElements = dataFieldOption.value.map(item => item.itemCode);
};
2026-07-20 16:02:51 +08:00
onMounted(() => {
getDict();
formData.statMonths = getDefaultStatMonths();
formData.yearStatContent = ['wq', 'qec'];
formData.yearDimContent = ['stcd', 'baseId'];
formData.statYears = [String(new Date().getFullYear())];
loadLyOptions();
2026-07-20 16:02:51 +08:00
});
</script>
<style scoped lang="scss">
.export-container {
padding: 20px;
// max-width: 800px;
width: 100%;
2026-07-20 16:02:51 +08:00
.export-form {
:deep(.ant-form-item) {
margin-bottom: 20px;
}
}
}
2026-07-31 11:13:49 +08:00
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
2026-09-02 10:44:17 +08:00
// .export-container{
// }
2026-07-20 16:02:51 +08:00
</style>