|
|
@@ -0,0 +1,1289 @@
|
|
|
+<template>
|
|
|
+ <div class="query-module">
|
|
|
+ <div class="query-container">
|
|
|
+ <!-- 搜索栏 -->
|
|
|
+ <div class="search-bar">
|
|
|
+ <div class="search-left">
|
|
|
+ <span class="search-label">单位名称:</span>
|
|
|
+ <el-select v-model="selectedUnit" placeholder="请选择共享单位" @change="handleUnitChange" class="unit-select">
|
|
|
+ <el-option v-for="unit in unitList" :key="unit.unitCode" :label="unit.unitName" :value="unit.unitCode" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="search-center">
|
|
|
+ <div class="biz-buttons">
|
|
|
+ <el-button
|
|
|
+ v-for="biz in bizList"
|
|
|
+ :key="biz.bizCode"
|
|
|
+ :class="{ active: selectedBiz === biz.bizCode }"
|
|
|
+ @click="handleBizClick(biz.bizCode)"
|
|
|
+ size="default"
|
|
|
+ >
|
|
|
+ {{ biz.bizName }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="search-right">
|
|
|
+ <el-button v-if="showReportBtn" type="success" icon="Edit" @click="openReportDialog">填报</el-button>
|
|
|
+ <el-button v-if="isFileBiz" type="success" icon="Upload" @click="openFileUploadDialog">上传文件</el-button>
|
|
|
+ <el-input v-model="searchKeyword" placeholder="请输入站名/站码" @keyup.enter="handleDataQuery" clearable style="width: 200px">
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon><Search /></el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 数据表格 -->
|
|
|
+ <div class="table-container">
|
|
|
+ <el-table :data="filteredTableData" v-loading="queryLoading" stripe border style="width: 100%" max-height="calc(100vh - 300px)">
|
|
|
+ <el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
|
|
|
+ <template v-for="col in currentColumns" :key="col.prop">
|
|
|
+ <el-table-column
|
|
|
+ :prop="col.prop"
|
|
|
+ :label="col.label"
|
|
|
+ :width="col.width"
|
|
|
+ :min-width="col.minWidth"
|
|
|
+ :formatter="col.formatter"
|
|
|
+ :align="col.align || 'center'"
|
|
|
+ show-overflow-tooltip
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <el-table-column v-if="showHistoryBtn" label="操作" width="100" fixed="right" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link @click="openDataDialog(row)">历史数据</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column v-if="isGdpBiz" label="操作" width="120" fixed="right" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link @click="openGdpHistoryDialog(row)">历史GDP数据</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column v-if="isFileBiz" label="操作" width="140" fixed="right" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link icon="Download" @click="handleDownloadFile(row)">下载</el-button>
|
|
|
+ <el-button type="danger" link icon="Delete" @click="handleDeleteFile(row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div v-if="filteredTableData.length === 0 && !queryLoading" class="empty-state">
|
|
|
+ <el-icon class="empty-icon"><DataAnalysis /></el-icon>
|
|
|
+ <p>暂无数据</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 历史数据弹框 -->
|
|
|
+ <el-dialog v-model="historyDialogVisible" :title="historyDialogTitle" width="85%" append-to-body>
|
|
|
+ <div class="history-content">
|
|
|
+ <!-- 左侧表格 -->
|
|
|
+ <div class="history-left">
|
|
|
+ <el-table :data="historyData" v-loading="historyLoading" stripe border style="width: 100%" height="100%">
|
|
|
+ <el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
|
|
|
+ <template v-for="col in currentColumns" :key="col.prop">
|
|
|
+ <el-table-column
|
|
|
+ :prop="col.prop"
|
|
|
+ :label="col.label"
|
|
|
+ :width="col.width"
|
|
|
+ :min-width="col.minWidth"
|
|
|
+ :formatter="col.formatter"
|
|
|
+ :align="col.align || 'center'"
|
|
|
+ show-overflow-tooltip
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ <div v-if="historyData.length === 0 && !historyLoading" class="empty-state">
|
|
|
+ <el-icon class="empty-icon"><DataAnalysis /></el-icon>
|
|
|
+ <p>暂无历史数据</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 右侧图表 -->
|
|
|
+ <div class="history-right">
|
|
|
+ <div class="chart-header">
|
|
|
+ <span class="toolbar-label">时间范围:</span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="historyDateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="-"
|
|
|
+ start-placeholder="开始"
|
|
|
+ end-placeholder="结束"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ @change="loadHistoryData"
|
|
|
+ size="default"
|
|
|
+ style="width: 260px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div ref="historyChartRef" class="history-chart"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 填报弹框 -->
|
|
|
+ <el-dialog v-model="reportDialogVisible" :title="reportDialogTitle" width="700px" append-to-body>
|
|
|
+ <el-tabs v-model="reportTab">
|
|
|
+ <el-tab-pane label="手动填报" name="manual">
|
|
|
+ <el-form ref="reportFormRef" :model="reportForm" :rules="reportRules" label-width="100px">
|
|
|
+ <el-form-item label="站点" prop="stcd">
|
|
|
+ <el-select v-model="reportForm.stcd" placeholder="请选择站点" style="width: 100%" disabled>
|
|
|
+ <el-option v-for="s in reportStationList" :key="s.stcd" :label="s.stnm" :value="s.stcd" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="时间" prop="tm">
|
|
|
+ <el-date-picker v-model="reportForm.tm" type="datetime" placeholder="请选择时间" value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="坝上水位(m)" prop="z">
|
|
|
+ <el-input-number v-model="reportForm.z" :precision="3" :min="-9999" :max="9999" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="isFdXaj" label="坝下水位(m)" prop="dwz">
|
|
|
+ <el-input-number v-model="reportForm.dwz" :precision="3" :min="-9999" :max="9999" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="入库流量(m³/s)" prop="inq">
|
|
|
+ <el-input-number v-model="reportForm.inq" :precision="3" :min="0" :max="99999" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="出库流量(m³/s)" prop="outq">
|
|
|
+ <el-input-number v-model="reportForm.outq" :precision="3" :min="0" :max="99999" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="Excel上传" name="excel">
|
|
|
+ <div class="upload-tip">
|
|
|
+ <p>{{ reportUploadTip }}</p>
|
|
|
+ <el-button type="primary" link icon="Download" @click="downloadReportTemplate">下载模板</el-button>
|
|
|
+ </div>
|
|
|
+ <el-upload
|
|
|
+ ref="reportUploadRef"
|
|
|
+ :auto-upload="false"
|
|
|
+ :limit="1"
|
|
|
+ accept=".xlsx,.xls"
|
|
|
+ :on-change="handleReportFileChange"
|
|
|
+ :on-exceed="handleReportExceed"
|
|
|
+ drag
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon--upload"><Upload /></el-icon>
|
|
|
+ <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">仅支持 .xlsx / .xls 文件</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="reportDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" :loading="reportSubmitting" @click="submitReport">{{ reportTab === 'excel' ? '上传并导入' : '提 交' }}</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 文件上传弹框 -->
|
|
|
+ <el-dialog v-model="fileUploadDialogVisible" title="上传文件" width="500px" append-to-body>
|
|
|
+ <el-form label-width="100px">
|
|
|
+ <el-form-item label="关联站点" required>
|
|
|
+ <el-select v-model="fileUploadStation" placeholder="请选择共享站点" style="width: 100%">
|
|
|
+ <el-option v-for="s in fileStationList" :key="s.stcd" :label="s.stnm" :value="s.stnm" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="选择文件" required>
|
|
|
+ <el-upload
|
|
|
+ ref="fileUploadRef"
|
|
|
+ :auto-upload="false"
|
|
|
+ :limit="1"
|
|
|
+ :show-file-list="true"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :on-remove="handleFileRemove"
|
|
|
+ accept="*"
|
|
|
+ >
|
|
|
+ <el-button type="primary" icon="Upload">选择文件</el-button>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="fileUploadDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" :loading="uploading" @click="submitFileUpload">上 传</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- GDP历史数据弹框 -->
|
|
|
+ <el-dialog v-model="gdpDialogVisible" :title="gdpDialogTitle" width="85%" append-to-body>
|
|
|
+ <div class="history-content">
|
|
|
+ <div class="history-left">
|
|
|
+ <el-table :data="gdpHistoryData" v-loading="gdpLoading" stripe border style="width: 100%" height="100%">
|
|
|
+ <el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
|
|
|
+ <template v-for="col in gdpColumns" :key="col.prop">
|
|
|
+ <el-table-column
|
|
|
+ :prop="col.prop"
|
|
|
+ :label="col.label"
|
|
|
+ :width="col.width"
|
|
|
+ :align="col.align || 'center'"
|
|
|
+ show-overflow-tooltip
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div class="history-right">
|
|
|
+ <div class="history-chart-header">
|
|
|
+ <span class="chart-title">GDP趋势图</span>
|
|
|
+ </div>
|
|
|
+ <div ref="gdpChartRef" class="history-chart"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup name="QueryModule">
|
|
|
+import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
|
|
+import * as echarts from 'echarts'
|
|
|
+import { Search, DataAnalysis, Upload, Download } from '@element-plus/icons-vue'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import { listMapStations, getLatestData, getLatestDataByBiz, listData, importData } from '@/api/xajgl/station'
|
|
|
+import { listXajUnitFront } from '@/api/xajgl/unit'
|
|
|
+import { listXajBizFront } from '@/api/xajgl/biz'
|
|
|
+import { getLatestGdpByCounty, getGdpHistoryByCounty } from '@/api/xajgl/gdp'
|
|
|
+import { listDocFiles, uploadDocFile, deleteDocFile, downloadDocFileUrl } from '@/api/xajgl/docFile'
|
|
|
+
|
|
|
+const emit = defineEmits(['open-station-dialog'])
|
|
|
+
|
|
|
+const selectedUnit = ref('')
|
|
|
+const selectedBiz = ref('')
|
|
|
+const bizList = ref([])
|
|
|
+const searchKeyword = ref('')
|
|
|
+const queryResult = ref([])
|
|
|
+const queryLoading = ref(false)
|
|
|
+const unitList = ref([])
|
|
|
+
|
|
|
+// 历史数据弹框
|
|
|
+const historyDialogVisible = ref(false)
|
|
|
+const historyDialogTitle = ref('')
|
|
|
+const historyData = ref([])
|
|
|
+const historyLoading = ref(false)
|
|
|
+const historyDateRange = ref([])
|
|
|
+const currentStation = ref(null)
|
|
|
+const historyChartRef = ref(null)
|
|
|
+let historyChart = null
|
|
|
+
|
|
|
+// 填报弹框
|
|
|
+const reportDialogVisible = ref(false)
|
|
|
+const reportTab = ref('manual')
|
|
|
+const reportSubmitting = ref(false)
|
|
|
+const reportFormRef = ref(null)
|
|
|
+const reportUploadRef = ref(null)
|
|
|
+const reportStationList = ref([])
|
|
|
+const reportFile = ref(null)
|
|
|
+const reportForm = ref({ stcd: '', tm: '', z: null, dwz: null, inq: null, outq: null })
|
|
|
+const reportRules = {
|
|
|
+ stcd: [{ required: true, message: '请选择站点', trigger: 'change' }],
|
|
|
+ tm: [{ required: true, message: '请选择时间', trigger: 'change' }]
|
|
|
+}
|
|
|
+
|
|
|
+// GDP历史弹框
|
|
|
+const gdpDialogVisible = ref(false)
|
|
|
+const gdpDialogTitle = ref('')
|
|
|
+const gdpHistoryData = ref([])
|
|
|
+const gdpLoading = ref(false)
|
|
|
+const gdpChartRef = ref(null)
|
|
|
+let gdpChart = null
|
|
|
+const gdpColumns = [
|
|
|
+ { prop: 'yr', label: '年份', width: 80 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '地市', width: 100 },
|
|
|
+ { prop: 'county', label: '区县', width: 120 },
|
|
|
+ { prop: 'pepSum', label: '人口总数(万人)', width: 140 },
|
|
|
+ { prop: 'peoCitySum', label: '城市人口(万人)', width: 140 },
|
|
|
+ { prop: 'peoCountySum', label: '农村人口(万人)', width: 140 },
|
|
|
+ { prop: 'peoRadio', label: '城镇化率(%)', width: 120 },
|
|
|
+ { prop: 'gdpSum', label: 'GDP合计(亿元)', width: 140 },
|
|
|
+ { prop: 'gdp1Sum', label: '一产(亿元)', width: 120 },
|
|
|
+ { prop: 'gdp2Sum', label: '二产(亿元)', width: 120 },
|
|
|
+ { prop: 'gdp3Sum', label: '三产(亿元)', width: 120 },
|
|
|
+ { prop: 'effectIrrArea', label: '有效灌溉面积(万亩)', width: 160 },
|
|
|
+ { prop: 'gdArea', label: '耕地面积(万亩)', width: 140 }
|
|
|
+]
|
|
|
+
|
|
|
+// 业务域字段配置
|
|
|
+const BIZ_COLUMN_CONFIG = {
|
|
|
+ // 水文数据 - 新安江流域管理局
|
|
|
+ TBA_SW_XAJ: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'q', label: '下泄流量(m³/s)', width: 150 },
|
|
|
+ { prop: 'gurdinfo', label: '保障情况', width: 400, showOverflowTooltip: true }
|
|
|
+ ],
|
|
|
+ historyChart: ['q']
|
|
|
+ },
|
|
|
+ // 雨量数据 - 安徽省水利厅
|
|
|
+ AH_SL_YL: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'drp', label: '降雨量(mm)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['drp']
|
|
|
+ },
|
|
|
+ // 雨量数据 - 浙江省水利厅
|
|
|
+ ZJ_SL_YL: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'drp', label: '降雨量(mm)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['drp']
|
|
|
+ },
|
|
|
+ // 蒸发数据 - 安徽省水利厅
|
|
|
+ AH_SL_ZF: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'dyp', label: '蒸发量(mm)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['dyp']
|
|
|
+ },
|
|
|
+ // 径流数据 - 安徽省水利厅
|
|
|
+ AH_SL_JL: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 120 },
|
|
|
+ { prop: 'q', label: '径流量(m³/s)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'q']
|
|
|
+ },
|
|
|
+ // 径流数据 - 浙江省水利厅
|
|
|
+ ZJ_SL_JL: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 120 },
|
|
|
+ { prop: 'q', label: '径流量(m³/s)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'q']
|
|
|
+ },
|
|
|
+ // 国家电网华东分部 - 水文数据
|
|
|
+ DW_XAJ_ST: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '坝上水位(m)', width: 130 },
|
|
|
+ { prop: 'inq', label: '入库流量(m³/s)', width: 130 },
|
|
|
+ { prop: 'outq', label: '出库流量(m³/s)', width: 130 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'inq', 'outq']
|
|
|
+ },
|
|
|
+ // 新安江水力发电厂 - 水文数据
|
|
|
+ FD_XAJ: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '坝上水位(m)', width: 130 },
|
|
|
+ { prop: 'dwz', label: '坝下水位(m)', width: 130 },
|
|
|
+ { prop: 'inq', label: '入库流量(m³/s)', width: 130 },
|
|
|
+ { prop: 'outq', label: '出库流量(m³/s)', width: 130 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'dwz', 'inq', 'outq']
|
|
|
+ },
|
|
|
+ // 黄山市水利局 - 水库数据
|
|
|
+ HS_SK_XAJ: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'ww', label: '下泄水量(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['ww']
|
|
|
+ },
|
|
|
+ // 淳安县水利水电局 - 水库数据
|
|
|
+ CA_SK_XAJ: {
|
|
|
+ type: 'st_xaj_data',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'ww', label: '下泄水量(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['ww']
|
|
|
+ },
|
|
|
+ // 蓄水变化 - 国家电网华东分部
|
|
|
+ DW_XAJ_ST_XS: {
|
|
|
+ type: 'st_xaj_sk',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '蓄水量(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'w']
|
|
|
+ },
|
|
|
+ // 蓄水变化 - 新安江水力发电厂
|
|
|
+ FD_XAJ_XS: {
|
|
|
+ type: 'st_xaj_sk',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '蓄水量(亿m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'w']
|
|
|
+ },
|
|
|
+ // 蓄水变化 - 黄山市水利局
|
|
|
+ HS_SK_XAJ_XS: {
|
|
|
+ type: 'st_xaj_sk',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '蓄水量(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'w']
|
|
|
+ },
|
|
|
+ // 蓄水变化 - 淳安县水利水电局
|
|
|
+ CA_SK_XAJ_XS: {
|
|
|
+ type: 'st_xaj_sk',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '蓄水量(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'w']
|
|
|
+ },
|
|
|
+ // 库容曲线 - 国家电网华东分部
|
|
|
+ DW_XAJ_ST_KR: {
|
|
|
+ type: 'st_xaj_kr',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '库容(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z']
|
|
|
+ },
|
|
|
+ // 库容曲线 - 新安江水力发电厂
|
|
|
+ FD_XAJ_KR: {
|
|
|
+ type: 'st_xaj_kr',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '库容(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z']
|
|
|
+ },
|
|
|
+ // 库容曲线 - 黄山市水利局
|
|
|
+ HS_SK_XAJ_KR: {
|
|
|
+ type: 'st_xaj_kr',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '库容(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z']
|
|
|
+ },
|
|
|
+ // 库容曲线 - 淳安县水利水电局
|
|
|
+ CA_SK_XAJ_KR: {
|
|
|
+ type: 'st_xaj_kr',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '站点名称', width: 250, fixed: 'left' },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 130 },
|
|
|
+ { prop: 'w', label: '库容(万m³)', width: 150 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z']
|
|
|
+ },
|
|
|
+ // 取用水户 - 安徽省水利厅
|
|
|
+ AH_SL_WIU: {
|
|
|
+ type: 'st_xaj_b',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '取用水户名称', width: 400, fixed: 'left' },
|
|
|
+ { prop: 'uscc', label: '社会信用代码', width: 250 },
|
|
|
+ { prop: 'tradTp', label: '取水户类型', width: 120 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: []
|
|
|
+ },
|
|
|
+ // 取用水户 - 浙江省水利厅
|
|
|
+ ZJ_SL_WIU: {
|
|
|
+ type: 'st_xaj_b',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '取用水户名称', width: 400, fixed: 'left' },
|
|
|
+ { prop: 'uscc', label: '社会信用代码', width: 250 },
|
|
|
+ { prop: 'tradTp', label: '取水户类型', width: 120 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: []
|
|
|
+ },
|
|
|
+ // 雨量站
|
|
|
+ DRP: {
|
|
|
+ type: 'st_xaj_b',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'drp', label: '降雨量(mm)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['drp']
|
|
|
+ },
|
|
|
+ // 水文站
|
|
|
+ ZZ: {
|
|
|
+ type: 'st_xaj_b',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'z', label: '水位(m)', width: 120 },
|
|
|
+ { prop: 'q', label: '径流量(m³/s)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['z', 'q']
|
|
|
+ },
|
|
|
+ // 蒸发站
|
|
|
+ DYP: {
|
|
|
+ type: 'st_xaj_b',
|
|
|
+ columns: [
|
|
|
+ { prop: 'stnm', label: '断面名称', width: 200, fixed: 'left' },
|
|
|
+ { prop: 'tm', label: '时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'dyp', label: '蒸发量(mm)', width: 130 },
|
|
|
+ { prop: 'prov', label: '省份', width: 100 },
|
|
|
+ { prop: 'city', label: '城市', width: 100 },
|
|
|
+ { prop: 'county', label: '县级市', width: 100 }
|
|
|
+ ],
|
|
|
+ historyChart: ['dyp']
|
|
|
+ },
|
|
|
+ // 地方人民政府 - GDP数据
|
|
|
+ XAJ_GDP: {
|
|
|
+ type: 'ww_city_gdp_xaj',
|
|
|
+ columns: [
|
|
|
+ { prop: 'prov', label: '省份', width: 100, fixed: 'left' },
|
|
|
+ { prop: 'city', label: '地市', width: 100, fixed: 'left' },
|
|
|
+ { prop: 'county', label: '区县', width: 120, fixed: 'left' },
|
|
|
+ { prop: 'yr', label: '年份', width: 80 },
|
|
|
+ { prop: 'pepSum', label: '人口总数(万人)', width: 140 },
|
|
|
+ { prop: 'gdpSum', label: 'GDP合计(亿元)', width: 140 },
|
|
|
+ { prop: 'gdp1Sum', label: '一产(亿元)', width: 120 },
|
|
|
+ { prop: 'gdp2Sum', label: '二产(亿元)', width: 120 },
|
|
|
+ { prop: 'gdp3Sum', label: '三产(亿元)', width: 120 },
|
|
|
+ { prop: 'peoRadio', label: '城镇化率(%)', width: 120 },
|
|
|
+ { prop: 'gdArea', label: '耕地面积(万亩)', width: 140 },
|
|
|
+ { prop: 'effectIrrArea', label: '有效灌溉面积(万亩)', width: 160 }
|
|
|
+ ],
|
|
|
+ historyChart: ['gdpSum', 'pepSum']
|
|
|
+ },
|
|
|
+ // 新安江水力发电厂 - 文件资料
|
|
|
+ FD_XAJ_FILE: {
|
|
|
+ type: 'xaj_doc_file',
|
|
|
+ bizName: '新安江水力发电厂',
|
|
|
+ columns: [
|
|
|
+ { prop: 'fileName', label: '文件名称', width: 350, fixed: 'left' },
|
|
|
+ { prop: 'fileType', label: '文件类型', width: 100 },
|
|
|
+ { prop: 'fileSize', label: '文件大小', width: 120, formatter: fmtFileSize },
|
|
|
+ { prop: 'fileUser', label: '上传人', width: 100 },
|
|
|
+ { prop: 'fileTime', label: '上传时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'downTimes', label: '下载次数', width: 100 },
|
|
|
+ { prop: 'fileDesc', label: '描述', minWidth: 200 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ // 黄山市水利局 - 文件资料
|
|
|
+ HS_SK_XAJ_FILE: {
|
|
|
+ type: 'xaj_doc_file',
|
|
|
+ bizName: '黄山市水利局',
|
|
|
+ columns: [
|
|
|
+ { prop: 'fileName', label: '文件名称', width: 350, fixed: 'left' },
|
|
|
+ { prop: 'fileType', label: '文件类型', width: 100 },
|
|
|
+ { prop: 'fileSize', label: '文件大小', width: 120, formatter: fmtFileSize },
|
|
|
+ { prop: 'fileUser', label: '上传人', width: 100 },
|
|
|
+ { prop: 'fileTime', label: '上传时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'downTimes', label: '下载次数', width: 100 },
|
|
|
+ { prop: 'fileDesc', label: '描述', minWidth: 200 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ // 淳安县水利水电局 - 文件资料
|
|
|
+ CA_SK_XAJ_FILE: {
|
|
|
+ type: 'xaj_doc_file',
|
|
|
+ bizName: '淳安县水利水电局',
|
|
|
+ columns: [
|
|
|
+ { prop: 'fileName', label: '文件名称', width: 350, fixed: 'left' },
|
|
|
+ { prop: 'fileType', label: '文件类型', width: 100 },
|
|
|
+ { prop: 'fileSize', label: '文件大小', width: 120, formatter: fmtFileSize },
|
|
|
+ { prop: 'fileUser', label: '上传人', width: 100 },
|
|
|
+ { prop: 'fileTime', label: '上传时间', width: 180, formatter: fmtDateTime },
|
|
|
+ { prop: 'downTimes', label: '下载次数', width: 100 },
|
|
|
+ { prop: 'fileDesc', label: '描述', minWidth: 200 }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const currentConfig = computed(() => BIZ_COLUMN_CONFIG[selectedBiz.value] || { columns: [] })
|
|
|
+const currentColumns = computed(() => currentConfig.value.columns || [])
|
|
|
+
|
|
|
+// 取用水户类型、地方人民政府、文件业务域不显示历史数据按钮
|
|
|
+const showHistoryBtn = computed(() => {
|
|
|
+ const hideBizCodes = ['AH_SL_WIU', 'ZJ_SL_WIU', 'WIU', 'XAJ_GDP', 'FD_XAJ_FILE', 'HS_SK_XAJ_FILE', 'CA_SK_XAJ_FILE']
|
|
|
+ return !hideBizCodes.includes(selectedBiz.value)
|
|
|
+})
|
|
|
+
|
|
|
+// 地方人民政府业务域,表格行可点击
|
|
|
+const isGdpBiz = computed(() => selectedBiz.value === 'XAJ_GDP')
|
|
|
+
|
|
|
+// 文件业务域
|
|
|
+const isFileBiz = computed(() => currentConfig.value.type === 'xaj_doc_file')
|
|
|
+
|
|
|
+// 填报按钮显示条件
|
|
|
+const showReportBtn = computed(() => ['DW_XAJ_ST', 'FD_XAJ'].includes(selectedBiz.value))
|
|
|
+
|
|
|
+// 文件上传相关
|
|
|
+const fileUploadRef = ref(null)
|
|
|
+const uploading = ref(false)
|
|
|
+const fileUploadDialogVisible = ref(false)
|
|
|
+const fileUploadStation = ref('')
|
|
|
+const fileStationList = ref([])
|
|
|
+const fileUploadRaw = ref(null)
|
|
|
+
|
|
|
+// 当前填报业务是否为FD_XAJ(新安江水力发电厂,含坝下水位)
|
|
|
+const isFdXaj = computed(() => selectedBiz.value === 'FD_XAJ')
|
|
|
+
|
|
|
+// 填报弹框标题
|
|
|
+const reportDialogTitle = computed(() => isFdXaj.value ? '新安江水力发电厂数据填报' : '富春江水库数据填报')
|
|
|
+
|
|
|
+// 上传提示
|
|
|
+const reportUploadTip = computed(() => {
|
|
|
+ const cols = isFdXaj.value ? '站码、时间、坝上水位、坝下水位、入库流量、出库流量' : '站码、时间、坝上水位、入库流量、出库流量'
|
|
|
+ return `请按模板格式上传Excel文件,包含以下列:${cols}`
|
|
|
+})
|
|
|
+
|
|
|
+const filteredTableData = computed(() => {
|
|
|
+ if (!searchKeyword.value) return queryResult.value
|
|
|
+ const kw = searchKeyword.value.toLowerCase()
|
|
|
+ return queryResult.value.filter(item => {
|
|
|
+ const name = (item.stnm || item.county || item.fileName || '').toLowerCase()
|
|
|
+ const code = (item.stcd || item.prov || item.city || '').toLowerCase()
|
|
|
+ return name.includes(kw) || code.includes(kw)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+// 格式化日期时间
|
|
|
+function fmtDateTime(row, col, val) {
|
|
|
+ if (!val) return '-'
|
|
|
+ const d = new Date(val)
|
|
|
+ if (isNaN(d)) return String(val)
|
|
|
+ const pad = n => n < 10 ? '0' + n : String(n)
|
|
|
+ return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`
|
|
|
+}
|
|
|
+
|
|
|
+// 格式化文件大小
|
|
|
+function fmtFileSize(row, col, val) {
|
|
|
+ if (!val) return '-'
|
|
|
+ const size = Number(val)
|
|
|
+ if (size < 1024) return size + ' B'
|
|
|
+ if (size < 1024 * 1024) return (size / 1024).toFixed(1) + ' KB'
|
|
|
+ return (size / 1024 / 1024).toFixed(1) + ' MB'
|
|
|
+}
|
|
|
+
|
|
|
+// 加载单位列表
|
|
|
+function loadUnitList() {
|
|
|
+ listXajUnitFront().then(res => {
|
|
|
+ unitList.value = res.data || []
|
|
|
+ if (unitList.value.length > 0 && !selectedUnit.value) {
|
|
|
+ selectedUnit.value = unitList.value[0].unitCode
|
|
|
+ loadBizList(selectedUnit.value)
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function handleUnitChange(val) {
|
|
|
+ selectedBiz.value = ''
|
|
|
+ queryResult.value = []
|
|
|
+ loadBizList(val)
|
|
|
+}
|
|
|
+
|
|
|
+function loadBizList(unitCode) {
|
|
|
+ listXajBizFront(unitCode).then(res => {
|
|
|
+ bizList.value = res.data || []
|
|
|
+ if (bizList.value.length > 0) {
|
|
|
+ selectedBiz.value = bizList.value[0].bizCode
|
|
|
+ handleBizClick(selectedBiz.value)
|
|
|
+ } else {
|
|
|
+ selectedBiz.value = ''
|
|
|
+ queryResult.value = []
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function handleBizClick(bizCode) {
|
|
|
+ selectedBiz.value = bizCode
|
|
|
+ loadQueryData()
|
|
|
+}
|
|
|
+
|
|
|
+function loadQueryData() {
|
|
|
+ if (!selectedBiz.value) return
|
|
|
+ queryLoading.value = true
|
|
|
+ const config = BIZ_COLUMN_CONFIG[selectedBiz.value]
|
|
|
+ if (!config) {
|
|
|
+ queryLoading.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 地方人民政府使用GDP接口
|
|
|
+ if (config.type === 'ww_city_gdp_xaj') {
|
|
|
+ getLatestGdpByCounty().then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ queryResult.value = res.data || []
|
|
|
+ } else {
|
|
|
+ queryResult.value = []
|
|
|
+ }
|
|
|
+ queryLoading.value = false
|
|
|
+ }).catch(() => {
|
|
|
+ queryResult.value = []
|
|
|
+ queryLoading.value = false
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 文件业务域使用文件接口
|
|
|
+ if (config.type === 'xaj_doc_file') {
|
|
|
+ listDocFiles(selectedBiz.value).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ queryResult.value = res.data || []
|
|
|
+ } else {
|
|
|
+ queryResult.value = []
|
|
|
+ }
|
|
|
+ queryLoading.value = false
|
|
|
+ }).catch(() => {
|
|
|
+ queryResult.value = []
|
|
|
+ queryLoading.value = false
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用新API按业务域查询站点最新数据
|
|
|
+ getLatestDataByBiz(selectedBiz.value).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ queryResult.value = res.data || []
|
|
|
+ } else {
|
|
|
+ queryResult.value = []
|
|
|
+ }
|
|
|
+ queryLoading.value = false
|
|
|
+ }).catch(() => {
|
|
|
+ queryResult.value = []
|
|
|
+ queryLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function handleDataQuery() {
|
|
|
+ // 搜索关键字过滤是通过 computed 属性 filteredTableData 实现的
|
|
|
+}
|
|
|
+
|
|
|
+// 格式化日期
|
|
|
+function formatDate(date) {
|
|
|
+ const y = date.getFullYear()
|
|
|
+ const m = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const d = String(date.getDate()).padStart(2, '0')
|
|
|
+ return `${y}-${m}-${d}`
|
|
|
+}
|
|
|
+
|
|
|
+function openDataDialog(row) {
|
|
|
+ currentStation.value = row
|
|
|
+ historyDialogTitle.value = `${row.stnm} - 历史数据`
|
|
|
+ // 默认7天
|
|
|
+ const end = new Date()
|
|
|
+ const start = new Date()
|
|
|
+ start.setDate(start.getDate() - 7)
|
|
|
+ historyDateRange.value = [formatDate(start), formatDate(end)]
|
|
|
+ historyData.value = []
|
|
|
+ historyDialogVisible.value = true
|
|
|
+ loadHistoryData()
|
|
|
+}
|
|
|
+
|
|
|
+// 文件上传弹框
|
|
|
+function openFileUploadDialog() {
|
|
|
+ fileUploadStation.value = ''
|
|
|
+ fileUploadRaw.value = null
|
|
|
+ fileUploadDialogVisible.value = true
|
|
|
+ // 去除_FILE后缀,匹配ST_XAJ_B的biz_code
|
|
|
+ const baseBizCode = selectedBiz.value.replace('_FILE', '')
|
|
|
+ getLatestDataByBiz(baseBizCode).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ const list = res.data || []
|
|
|
+ // 去重
|
|
|
+ const map = new Map()
|
|
|
+ list.forEach(item => {
|
|
|
+ if (item.stcd && item.stnm && !map.has(item.stcd)) {
|
|
|
+ map.set(item.stcd, { stcd: item.stcd, stnm: item.stnm })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ fileStationList.value = Array.from(map.values())
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function handleFileChange(file) {
|
|
|
+ fileUploadRaw.value = file.raw
|
|
|
+}
|
|
|
+
|
|
|
+function handleFileRemove() {
|
|
|
+ fileUploadRaw.value = null
|
|
|
+}
|
|
|
+
|
|
|
+function submitFileUpload() {
|
|
|
+ if (!fileUploadStation.value) {
|
|
|
+ ElMessage.warning('请选择关联站点')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!fileUploadRaw.value) {
|
|
|
+ ElMessage.warning('请选择要上传的文件')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uploading.value = true
|
|
|
+ const fd = new window.FormData()
|
|
|
+ fd.append('file', fileUploadRaw.value)
|
|
|
+ fd.append('bizCode', selectedBiz.value)
|
|
|
+ fd.append('fileDesc', fileUploadStation.value)
|
|
|
+ uploadDocFile(fd).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ ElMessage.success('上传成功')
|
|
|
+ fileUploadDialogVisible.value = false
|
|
|
+ loadQueryData()
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.msg || '上传失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ ElMessage.error('上传失败')
|
|
|
+ }).finally(() => {
|
|
|
+ uploading.value = false
|
|
|
+ if (fileUploadRef.value) {
|
|
|
+ fileUploadRef.value.clearFiles()
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 文件下载
|
|
|
+function handleDownloadFile(row) {
|
|
|
+ const url = downloadDocFileUrl(row.fileId)
|
|
|
+ window.open(url, '_blank')
|
|
|
+}
|
|
|
+
|
|
|
+// 文件删除
|
|
|
+function handleDeleteFile(row) {
|
|
|
+ ElMessageBox.confirm('确定要删除文件"' + row.fileName + '"吗?', '确认删除', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ deleteDocFile(row.fileId).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ ElMessage.success('删除成功')
|
|
|
+ loadQueryData()
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.msg || '删除失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ ElMessage.error('删除失败')
|
|
|
+ })
|
|
|
+ }).catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+function loadHistoryData() {
|
|
|
+ if (!currentStation.value || !historyDateRange.value || historyDateRange.value.length !== 2) return
|
|
|
+ historyLoading.value = true
|
|
|
+ const [startTm, endTm] = historyDateRange.value
|
|
|
+ listData(currentStation.value.stcd, startTm, endTm, selectedBiz.value).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ historyData.value = res.data || []
|
|
|
+ } else {
|
|
|
+ historyData.value = []
|
|
|
+ }
|
|
|
+ historyLoading.value = false
|
|
|
+ nextTick(() => initHistoryChart())
|
|
|
+ }).catch(() => {
|
|
|
+ historyData.value = []
|
|
|
+ historyLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function initHistoryChart() {
|
|
|
+ if (!historyChartRef.value) return
|
|
|
+ if (!historyChart) {
|
|
|
+ historyChart = echarts.init(historyChartRef.value)
|
|
|
+ }
|
|
|
+ if (!historyData.value || historyData.value.length === 0) {
|
|
|
+ historyChart.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const config = BIZ_COLUMN_CONFIG[selectedBiz.value]
|
|
|
+ if (!config || !config.historyChart || config.historyChart.length === 0) {
|
|
|
+ historyChart.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const chartFields = config.historyChart
|
|
|
+ const sortedData = [...historyData.value].sort((a, b) => new Date(a.tm) - new Date(b.tm))
|
|
|
+ const xData = sortedData.map(d => fmtDateTime(null, null, d.tm))
|
|
|
+ const series = chartFields.map(field => {
|
|
|
+ const col = currentColumns.value.find(c => c.prop === field)
|
|
|
+ return {
|
|
|
+ name: col ? col.label : field,
|
|
|
+ type: 'line',
|
|
|
+ data: sortedData.map(d => d[field] ?? null),
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 4,
|
|
|
+ lineStyle: { width: 2 }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const option = {
|
|
|
+ tooltip: { trigger: 'axis' },
|
|
|
+ legend: { data: series.map(s => s.name), bottom: 0 },
|
|
|
+ grid: { left: '10%', right: '5%', top: '10%', bottom: '15%' },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: xData,
|
|
|
+ axisLabel: { rotate: 30, fontSize: 11 }
|
|
|
+ },
|
|
|
+ yAxis: { type: 'value' },
|
|
|
+ series
|
|
|
+ }
|
|
|
+ historyChart.setOption(option, true)
|
|
|
+}
|
|
|
+
|
|
|
+// GDP历史弹框
|
|
|
+function openGdpHistoryDialog(row) {
|
|
|
+ gdpDialogTitle.value = `${row.county} - 历史GDP数据`
|
|
|
+ gdpHistoryData.value = []
|
|
|
+ gdpDialogVisible.value = true
|
|
|
+ gdpLoading.value = true
|
|
|
+ getGdpHistoryByCounty(row.county).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ gdpHistoryData.value = res.data || []
|
|
|
+ } else {
|
|
|
+ gdpHistoryData.value = []
|
|
|
+ }
|
|
|
+ gdpLoading.value = false
|
|
|
+ nextTick(() => initGdpChart())
|
|
|
+ }).catch(() => {
|
|
|
+ gdpHistoryData.value = []
|
|
|
+ gdpLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function initGdpChart() {
|
|
|
+ if (!gdpChartRef.value) return
|
|
|
+ if (!gdpChart) {
|
|
|
+ gdpChart = echarts.init(gdpChartRef.value)
|
|
|
+ }
|
|
|
+ if (!gdpHistoryData.value || gdpHistoryData.value.length === 0) {
|
|
|
+ gdpChart.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const sortedData = [...gdpHistoryData.value].sort((a, b) => {
|
|
|
+ return parseInt(a.yr) - parseInt(b.yr)
|
|
|
+ })
|
|
|
+ const xData = sortedData.map(d => d.yr)
|
|
|
+ const option = {
|
|
|
+ tooltip: { trigger: 'axis' },
|
|
|
+ legend: { data: ['GDP合计(亿元)', '人口总数(万人)'], bottom: 0 },
|
|
|
+ grid: { left: '10%', right: '5%', top: '10%', bottom: '15%' },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: xData,
|
|
|
+ axisLabel: { fontSize: 11 }
|
|
|
+ },
|
|
|
+ yAxis: [
|
|
|
+ { type: 'value', name: 'GDP(亿元)', position: 'left' },
|
|
|
+ { type: 'value', name: '人口(万人)', position: 'right' }
|
|
|
+ ],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: 'GDP合计(亿元)',
|
|
|
+ type: 'bar',
|
|
|
+ data: sortedData.map(d => d.gdpSum ?? 0),
|
|
|
+ itemStyle: { color: '#1c97e7' },
|
|
|
+ barWidth: '40%'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '人口总数(万人)',
|
|
|
+ type: 'line',
|
|
|
+ yAxisIndex: 1,
|
|
|
+ data: sortedData.map(d => d.pepSum ?? 0),
|
|
|
+ smooth: true,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 6,
|
|
|
+ lineStyle: { width: 2, color: '#ff8562' },
|
|
|
+ itemStyle: { color: '#ff8562' }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ gdpChart.setOption(option, true)
|
|
|
+}
|
|
|
+
|
|
|
+// 填报相关函数
|
|
|
+function openReportDialog() {
|
|
|
+ reportForm.value = { stcd: '', tm: '', z: null, dwz: null, inq: null, outq: null }
|
|
|
+ reportFile.value = null
|
|
|
+ reportTab.value = 'manual'
|
|
|
+ // 从当前已加载的业务域数据中提取站点列表
|
|
|
+ const stationMap = new Map()
|
|
|
+ queryResult.value.forEach(item => {
|
|
|
+ if (item.stcd && item.stnm && !stationMap.has(item.stcd)) {
|
|
|
+ stationMap.set(item.stcd, { stcd: item.stcd, stnm: item.stnm })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ reportStationList.value = Array.from(stationMap.values())
|
|
|
+ if (reportStationList.value.length > 0) {
|
|
|
+ reportForm.value.stcd = reportStationList.value[0].stcd
|
|
|
+ }
|
|
|
+ reportDialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+function submitReport() {
|
|
|
+ const bizCode = selectedBiz.value
|
|
|
+ if (reportTab.value === 'manual') {
|
|
|
+ reportFormRef.value.validate(valid => {
|
|
|
+ if (!valid) return
|
|
|
+ reportSubmitting.value = true
|
|
|
+ importData({
|
|
|
+ stcd: reportForm.value.stcd,
|
|
|
+ tm: reportForm.value.tm,
|
|
|
+ z: reportForm.value.z,
|
|
|
+ dwz: reportForm.value.dwz,
|
|
|
+ inq: reportForm.value.inq,
|
|
|
+ outq: reportForm.value.outq,
|
|
|
+ bizCode
|
|
|
+ }).then(() => {
|
|
|
+ ElMessage.success('填报成功')
|
|
|
+ reportDialogVisible.value = false
|
|
|
+ loadQueryData()
|
|
|
+ }).catch(() => {
|
|
|
+ ElMessage.error('填报失败')
|
|
|
+ }).finally(() => {
|
|
|
+ reportSubmitting.value = false
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ if (!reportFile.value) {
|
|
|
+ ElMessage.warning('请选择要上传的Excel文件')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ reportSubmitting.value = true
|
|
|
+ const fd = new window.FormData()
|
|
|
+ fd.append('file', reportFile.value)
|
|
|
+ fd.append('bizCode', bizCode)
|
|
|
+ importData(fd).then(() => {
|
|
|
+ ElMessage.success('导入成功')
|
|
|
+ reportDialogVisible.value = false
|
|
|
+ reportUploadRef.value?.clearFiles()
|
|
|
+ loadQueryData()
|
|
|
+ }).catch(() => {
|
|
|
+ ElMessage.error('导入失败')
|
|
|
+ }).finally(() => {
|
|
|
+ reportSubmitting.value = false
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function handleReportFileChange(file) {
|
|
|
+ reportFile.value = file.raw
|
|
|
+}
|
|
|
+
|
|
|
+function handleReportExceed() {
|
|
|
+ ElMessage.warning('只能上传一个文件,请先删除已选文件')
|
|
|
+}
|
|
|
+
|
|
|
+function downloadReportTemplate() {
|
|
|
+ const BOM = '\uFEFF'
|
|
|
+ let header, example, filename
|
|
|
+ if (selectedBiz.value === 'FD_XAJ') {
|
|
|
+ header = '站码,时间,坝上水位(m),坝下水位(m),入库流量(m³/s),出库流量(m³/s)'
|
|
|
+ example = 'XAJ001,2026-08-01 08:00:00,108.500,65.200,800.000,500.000'
|
|
|
+ filename = '新安江水力发电厂数据填报模板.csv'
|
|
|
+ } else {
|
|
|
+ header = '站码,时间,坝上水位(m),入库流量(m³/s),出库流量(m³/s)'
|
|
|
+ example = 'FCJ001,2026-08-01 08:00:00,100.500,500.000,300.000'
|
|
|
+ filename = '富春江水库数据填报模板.csv'
|
|
|
+ }
|
|
|
+ const csv = BOM + header + '\n' + example
|
|
|
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
|
|
|
+ const link = document.createElement('a')
|
|
|
+ link.href = URL.createObjectURL(blob)
|
|
|
+ link.download = filename
|
|
|
+ link.click()
|
|
|
+ URL.revokeObjectURL(link.href)
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ loadUnitList()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.query-module {
|
|
|
+ flex: 1;
|
|
|
+ padding: 16px;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.query-container {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 20px;
|
|
|
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.search-bar {
|
|
|
+ padding: 15px 0;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 12px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-left { flex-shrink: 0; display: flex; align-items: center; gap: 8px; }
|
|
|
+.search-label { font-size: 14px; color: #606266; font-weight: 500; white-space: nowrap; }
|
|
|
+.unit-select { width: 220px; }
|
|
|
+
|
|
|
+.search-center {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ padding: 0 20px;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.biz-buttons {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.biz-buttons :deep(.el-button) {
|
|
|
+ padding: 6px 16px;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ color: #606266;
|
|
|
+ border-color: #dcdfe6;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+}
|
|
|
+.biz-buttons :deep(.el-button:hover) {
|
|
|
+ background: #ecf5ff;
|
|
|
+ border-color: #b3d8ff;
|
|
|
+ color: #1c97e7;
|
|
|
+}
|
|
|
+.biz-buttons :deep(.el-button.active) {
|
|
|
+ background: #1c97e7;
|
|
|
+ color: #fff;
|
|
|
+ border-color: #1c97e7;
|
|
|
+}
|
|
|
+
|
|
|
+.search-right { flex-shrink: 0; }
|
|
|
+
|
|
|
+.table-container {
|
|
|
+ flex: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ position: relative;
|
|
|
+ min-height: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.table-container :deep(.el-table tr:hover) {
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-icon {
|
|
|
+ font-size: 48px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.history-content {
|
|
|
+ display: flex;
|
|
|
+ gap: 16px;
|
|
|
+ height: 520px;
|
|
|
+}
|
|
|
+
|
|
|
+.history-left {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.history-right {
|
|
|
+ width: 45%;
|
|
|
+ flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.chart-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.chart-header .toolbar-label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 500;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.history-chart {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-tip {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ padding: 12px 16px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-tip p {
|
|
|
+ margin: 0 0 8px 0;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+</style>
|