Selaa lähdekoodia

新安江流域模块数据文件上传功能更新

dumingliang 21 tuntia sitten
vanhempi
commit
2b87e82b58
29 muutettua tiedostoa jossa 3953 lisäystä ja 1194 poistoa
  1. 924 0
      docs/js/xaj_data.js
  2. 14 1
      gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/StXajBController.java
  3. 10 0
      gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/StXajDataController.java
  4. 44 0
      gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/WwCityGdpXajController.java
  5. 159 0
      gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/XajDocFileController.java
  6. 24 0
      gw-gx/src/main/java/com/goldenwater/xajgl/domain/StXajData.java
  7. 165 0
      gw-gx/src/main/java/com/goldenwater/xajgl/domain/WwCityGdpXaj.java
  8. 69 0
      gw-gx/src/main/java/com/goldenwater/xajgl/domain/XajDocFile.java
  9. 5 1
      gw-gx/src/main/java/com/goldenwater/xajgl/mapper/StXajDataMapper.java
  10. 18 0
      gw-gx/src/main/java/com/goldenwater/xajgl/mapper/WwCityGdpXajMapper.java
  11. 33 0
      gw-gx/src/main/java/com/goldenwater/xajgl/mapper/XajDocFileMapper.java
  12. 5 1
      gw-gx/src/main/java/com/goldenwater/xajgl/service/IStXajDataService.java
  13. 17 0
      gw-gx/src/main/java/com/goldenwater/xajgl/service/IWwCityGdpXajService.java
  14. 17 0
      gw-gx/src/main/java/com/goldenwater/xajgl/service/IXajDocFileService.java
  15. 13 2
      gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/StXajDataServiceImpl.java
  16. 25 0
      gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/WwCityGdpXajServiceImpl.java
  17. 40 0
      gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/XajDocFileServiceImpl.java
  18. 78 11
      gw-gx/src/main/resources/mapper/xajgl/StXajDataMapper.xml
  19. 67 0
      gw-gx/src/main/resources/mapper/xajgl/WwCityGdpXajMapper.xml
  20. 50 0
      gw-gx/src/main/resources/mapper/xajgl/XajDocFileMapper.xml
  21. 1 1
      gw-gx/src/main/resources/mapper/xajgl/XajUnitMapper.xml
  22. 33 0
      gw-ui/src/api/xajgl/docFile.js
  23. 18 0
      gw-ui/src/api/xajgl/gdp.js
  24. 20 2
      gw-ui/src/api/xajgl/station.js
  25. 11 1175
      gw-ui/src/views/front/Xaj.vue
  26. 76 0
      gw-ui/src/views/front/xaj/FeedbackModule.vue
  27. 634 0
      gw-ui/src/views/front/xaj/GisModule.vue
  28. 1289 0
      gw-ui/src/views/front/xaj/QueryModule.vue
  29. 94 0
      gw-ui/src/views/front/xaj/ShareModule.vue

+ 924 - 0
docs/js/xaj_data.js

@@ -0,0 +1,924 @@
+var jyzf = ['AH_SL_YL', 'ZJ_SL_YL', 'AH_SL_ZF'];
+var jl = ['TBA_SW_XAJ', 'AH_SL_JL', 'ZJ_SL_JL'];
+var slgc = ['DW_XAJ_ST', 'FD_XAJ', 'HS_SK_XAJ', 'CA_SK_XAJ'];
+var qsh = ['AH_SL_WIU', 'ZJ_SL_WIU'];
+var gxdata = {
+    init: function (table, $, layer, form) {
+        form.on('select(xaj-sel-unit)', function (data) {
+            var selIndex = data.elem.selectedIndex;
+            var selunit = data.elem[data.elem.selectedIndex].getAttribute("id");
+            $('.tba-unit-button').hide();
+            $('#' + selunit + '-buttons').show();
+            var bizCode = "TBA_SW_XAJ";
+            var tp = "0";
+            //水文数据范围:太湖流域管理局
+            if (selIndex == 0) {
+                bizCode = "TBA_SW_XAJ";
+            } else if (selIndex == 1) {
+                //安徽省水利厅
+                bizCode = 'AH_SL_YL';
+            } else if (selIndex == 2) {
+                //浙江省水利厅
+                bizCode = 'ZJ_SL_YL';
+            } else if (selIndex == 3) {
+                //国家电网有限公司华东分部
+                bizCode = 'DW_XAJ_ST';
+            } else if (selIndex == 4) {
+                //新安江水力发电厂
+                bizCode = 'FD_XAJ';
+            } else if (selIndex == 5) {
+                //黄山市水利局
+                bizCode = 'HS_SK_XAJ';
+            } else if (selIndex == 6) {
+                //淳安县水利水电局
+                bizCode = 'CA_SK_XAJ';
+            } else if (selIndex == 7) {
+                //各地区政府
+                bizCode = 'GDP_XAJ';
+            } else {
+                //新安江流域
+                bizCode = 'DRP';
+                tp = "DRP";
+            }
+            window.location.href = ctx + "web/xaj-data.html?page=" + pageParam + "&bizCode=" + bizCode + "&unit=" + selunit + "&tp=" + tp;
+        });
+        form.on('select(xaj-sel-tp)', function (data) {
+            let bizCode = data.value;
+            window.location.href = ctx + "web/xaj-data.html?page=" + pageParam + "&bizCode=" + bizCode + "&unit=all_xaj" + "&tp=" + bizCode;
+        });
+        $(document).on('click', '.tba-btn', function () {
+            var bizCodeParam = $(this).attr("id");
+            window.location.href = ctx + "web/xaj-data.html?page=" + pageParam + "&bizCode=" + bizCodeParam + "&unit=" + unitParam + "&tp=0";
+            return false;
+        });
+        $("#szSearchBtn").click(function () {
+            table.reload('rtuDataGrid', {
+                where: {
+                    startTime: $("#startTime").val(),
+                    endTime: $("#endTime").val(),
+                } //设定异步数据接口的额外参数
+            });
+        })
+        $("#szSearchBtn1").click(function () {
+            table.reload('rtuDataGrid1', {
+                where: {
+                    startTime: $("#startTime1").val(),
+                    endTime: $("#endTime1").val(),
+                } //设定异步数据接口的额外参数
+            });
+        })
+    },
+    format0data: function (rows) {
+        if (rows && Array.isArray(rows)) {
+            for (var i = 0; i < rows.length; i++) {
+                var row = rows[i];
+                for (var key in row) {
+                    if (row[key] != null) {
+                        if (key == 'drp' || key == 'dyp' || key == 'q' || key == 'inq' || key == 'outq' || key == 'z' || key == 'dwz') {
+                            row[key] = Number(row[key]).toFixed(1);
+                        }
+                        if (key == 'peoCitySum' || key == 'peoCountySum' || key == 'pepSum' || key == 'peoRadio' || key == 'gdpSum'
+                            || key == 'insduAdd' || key == 'gdArea') {
+                            row[key] = Number(row[key]).toFixed(2);
+                        }
+                        if (key == 'w' || key == 'ww') {
+                            row[key] = Number(row[key]).toFixed(3);
+                        }
+                    }
+                    // if ((typeof row[key]) == "string") {
+                    //     var fVal = parseFloat(row[key]);
+                    //     if (fVal && fVal < 1 && fVal >= 0) {
+                    //         if (row[key].substr(0, 1) != "0") {
+                    //             row[key] = "0" + row[key];
+                    //         }
+                    //     }
+                    // }
+                }
+            }
+        }
+        return rows;
+    },
+    getDataDefine: function (bizCode) {
+        switch (bizCode) {
+            case 'DRP':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?tp=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?tp=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?tp=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'drp', title: '降雨量(mm)', align: 'center', width: 150,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200}
+                        , {field: 'drp', title: '降雨量(mm)', align: 'center', width: 150, templet: '#UPZTpl'}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["mm"],
+                        series: [
+                            {
+                                name: '降雨量',
+                                field: 'drp',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'ZZ':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?tp=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?tp=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?tp=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'q', title: '径流量(m³/s)', align: 'center', width: 200,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'q', title: '径流量(m³/s)', align: 'center', width: 200}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["m", "m³/s"],
+                        series: [
+                            {name: '水位', field: 'z', type: "line", color: "#49af4d", yAxisIndex: 0, selected: true},
+                            {name: '径流量', field: 'q', type: 'bar', color: "#5793F3", yAxisIndex: 1, selected: true},
+                        ]
+                    }
+                }
+                break;
+            case 'DYP':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?tp=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?tp=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?tp=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'dyp', title: '蒸发量(mm)', align: 'center', width: 300,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'dyp', title: '蒸发量(mm)', align: 'center', width: 150, templet: '#UPZTpl'}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["mm"],
+                        series: [
+                            {
+                                name: '蒸发量',
+                                field: 'dyp',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'WIU':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?tp=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?tp=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?tp=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '取用水户名称', fixed: 'left', align: 'center', width: 450}
+                        , {field: 'uscc', title: '社会信用代码', align: 'center', width: 300}
+                        , {field: 'tradTp', title: '取水户类型', align: 'center', width: 120}
+                        , {field: 'prov', title: '省份', align: 'center', width: 120}
+                        , {field: 'city', title: '城市', align: 'center', width: 120}
+                        , {field: 'county', title: '县级市', align: 'center', width: 120}
+                    ],
+                }
+                break;
+            // case 'SK':
+            //     return {
+            //         newestDataUrl: ctx + 'gx/xaj/skswList?tp=' + bizCode,
+            //         listDataUrl: ctx + 'gx/xaj/skswList?tp=' + bizCode,
+            //         downloadUrl: ctx + 'gx/xaj/skswList?tp=' + bizCode,
+            //         timeBetween: 1,
+            //         layuiTable: [
+            //             {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+            //             , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+            //             , {field: 'tm', title: '时间', fixed: 'left', align: 'center', width: 250}
+            //             , {field: 'z', title: '水位', align: 'center', width: 200}
+            //             , {field: 'w', title: '蓄水量(万m³)', align: 'center', width: 200}
+            //         ],
+            //         chartTable: [
+            //             {field: 'tm', title: '时间', align: 'center', width: 150}
+            //             , {field: 'z', title: '水位', align: 'center', width: 150}
+            //             , {field: 'w', title: '蓄水量(万m³)', align: 'center', width: 150}
+            //         ],
+            //         chart: {
+            //             title: '水库蓄水变化过程图',
+            //             xCategory: 'tm',
+            //             yAxis: ["m", "万m³"],
+            //             series: [
+            //                 {
+            //                     name: '水位',
+            //                     field: 'z',
+            //                     type: 'line',
+            //                     color: "#3adbe0",
+            //                     yAxisIndex: 0,
+            //                     selected: true
+            //                 },
+            //                 {
+            //                     name: '蓄水量',
+            //                     field: 'w',
+            //                     type: 'bar',
+            //                     color: "#5793F3",
+            //                     yAxisIndex: 1,
+            //                     selected: true
+            //                 }
+            //             ]
+            //         }
+            //     }
+            //     break;
+            case 'TBA_SW_XAJ':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'q', title: '下泄流量(m³/s)', align: 'center', width: 200,}
+                        , {field: 'gurdinfo', title: '保障情况', align: 'center', width: 500}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'q', title: '下泄流量(m³/s)', align: 'center', width: 150, templet: '#UPZTpl'}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["m³/s"],
+                        series: [
+                            {name: '下泄流量', field: 'q', type: 'bar', color: "#5793F3", selected: true},
+                        ]
+                    }
+                }
+                break;
+            case 'AH_SL_JL':
+            case 'ZJ_SL_JL':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'q', title: '径流量(m³/s)', align: 'center', width: 200,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'q', title: '径流量(m³/s)', align: 'center', width: 200}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["m", "m³/s"],
+                        series: [
+                            {name: '水位', field: 'z', type: "line", color: "#49af4d", yAxisIndex: 0, selected: true},
+                            {name: '径流量', field: 'q', type: 'bar', color: "#5793F3", yAxisIndex: 1, selected: true},
+                        ]
+                    }
+                }
+                break;
+            case 'AH_SL_YL':
+            case 'ZJ_SL_YL':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'drp', title: '降雨量(mm)', align: 'center', width: 150,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200}
+                        , {field: 'drp', title: '降雨量(mm)', align: 'center', width: 150, templet: '#UPZTpl'}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["mm"],
+                        series: [
+                            {
+                                name: '降雨量',
+                                field: 'drp',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'AH_SL_ZF':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '断面名称', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'tm', title: '时间', align: 'center', fixed: 'left', width: 200, templet: '#timeTpl'}
+                        , {field: 'dyp', title: '蒸发量(mm)', align: 'center', width: 300,}
+                        , {field: 'prov', title: '省份', align: 'center', width: 150}
+                        , {field: 'city', title: '城市', align: 'center', width: 150}
+                        , {field: 'county', title: '县级市', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'dyp', title: '蒸发量(mm)', align: 'center', width: 150, templet: '#UPZTpl'}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["mm"],
+                        series: [
+                            {
+                                name: '蒸发量',
+                                field: 'dyp',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'AH_SL_WIU':
+            case 'ZJ_SL_WIU':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '取用水户名称', fixed: 'left', align: 'center', width: 450}
+                        , {field: 'uscc', title: '社会信用代码', align: 'center', width: 300}
+                        , {field: 'tradTp', title: '取水户类型', align: 'center', width: 120}
+                        , {field: 'prov', title: '省份', align: 'center', width: 120}
+                        , {field: 'city', title: '城市', align: 'center', width: 120}
+                        , {field: 'county', title: '县级市', align: 'center', width: 120}
+                    ],
+                }
+                break;
+            case 'DW_XAJ_ST':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {
+                            field: 'tm',
+                            title: '时间',
+                            fixed: 'left',
+                            align: 'center',
+                            width: 150,
+                            templet: '#timeTpl'
+                        }
+                        , {field: 'z', title: '坝上水位(m)', align: 'center', width: 150}
+                        , {field: 'inq', title: '入库流量(m³/s)', align: 'center', width: 150}
+                        , {field: 'outq', title: '出库流量(m³/s)', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 150, templet: '#timeTpl'}
+                        , {field: 'z', title: '坝上水位(m)', align: 'center', width: 150}
+                        , {field: 'inq', title: '入库流量(m³/s)', align: 'center', width: 150}
+                        , {field: 'outq', title: '出库流量(m³/s)', align: 'center', width: 150}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["m", "m³/s"],
+                        series: [
+                            {
+                                name: '坝上水位',
+                                field: 'z',
+                                type: 'line',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                            {
+                                name: '入库流量',
+                                field: 'inq',
+                                type: 'bar',
+                                color: "#30AF30",
+                                yAxisIndex: 1,
+                                selected: true
+                            },
+                            {
+                                name: '出库流量',
+                                field: 'outq',
+                                type: 'bar',
+                                color: "#368BFF",
+                                yAxisIndex: 1,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'FD_XAJ':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {
+                            field: 'tm',
+                            title: '时间',
+                            fixed: 'left',
+                            align: 'center',
+                            width: 200,
+                            templet: '#timeTpl'
+                        }
+                        , {field: 'z', title: '坝上水位(m)', align: 'center', width: 200}
+                        , {field: 'dwz', title: '坝下水位(m)', align: 'center', width: 200}
+                        , {field: 'inq', title: '入库流量(m³/s)', align: 'center', width: 200}
+                        , {field: 'outq', title: '出库流量(m³/s)', align: 'center', width: 200}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 150, templet: '#timeTpl'}
+                        , {field: 'inq', title: '入库流量(m³/s)', align: 'center', width: 150}
+                        , {field: 'outq', title: '出库流量(m³/s)', align: 'center', width: 150}
+                        , {field: 'z', title: '坝上水位(m)', align: 'center', width: 150}
+                        , {field: 'dwz', title: '坝下水位(m)', align: 'center', width: 150}
+
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["m", "m³/s"],
+                        series: [
+                            {
+                                name: '坝上水位',
+                                field: 'z',
+                                type: 'line',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                            {
+                                name: '坝下水位',
+                                field: 'dwz',
+                                type: 'line',
+                                color: "#4F5FCBCC",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                            {
+                                name: '入库流量',
+                                field: 'inq',
+                                type: 'bar',
+                                color: "#30AF30",
+                                yAxisIndex: 1,
+                                selected: true
+                            },
+                            {
+                                name: '出库流量',
+                                field: 'outq',
+                                type: 'bar',
+                                color: "#368BFF",
+                                yAxisIndex: 1,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'FD_XAJ_FILE':
+            case 'HS_SK_XAJ_FILE':
+            case 'CA_SK_XAJ_FILE':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/file/list?bizCode=' + bizCode,
+                    // listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    // downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        // , {field: 'stcd', title: '站码', align: 'center', width: 120}
+                        , {field: 'stnm', title: '站点名称', align: 'center', width: 200}
+                        , {field: 'fileName', title: '文件名称', align: 'center', width: 700}
+                        , {field: 'fileTime', title: '上传时间', align: 'center', width: 150}
+                        , {
+                            field: 'filePath', title: '操作', align: 'center', width: 200, templet: function (e) {
+                                let url = ctx + "doc/" + e.filePath + "/" + e.fileName + "' download='" + ctx + "doc/" + e.filePath + "/" + e.fileName;
+                                // return "<a type=\"button\" href='" + url.replace("[", "%5B").replace("]", "%5D") + "' class=\"layui-btn layui-btn-sm layui-btn-primary\">\n" +
+                                //     "下载</a>";
+                                return "<button type=\"button\" onclick='downLoad(\"" + e.fileId + "\")' class=\"layui-btn layui-btn-sm layui-btn-primary\">\n" +
+                                    "下载" +
+                                    "</button>";
+                            }
+                        }
+                    ],
+                }
+                break;
+            case 'HS_SK_XAJ':
+            case 'CA_SK_XAJ':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/newest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/list?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'tm', title: '时间', align: 'center', width: 200, templet: '#timeTpl'}
+                        , {field: 'ww', title: '下泄水量(万m³)', align: 'center', width: 200}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', sort: true, width: 200, templet: '#timeTpl'}
+                        , {field: 'ww', title: '下泄水量(万m³)', align: 'center', width: 200}
+                    ],
+                    chart: {
+                        title: '水文监测',
+                        xCategory: 'tm',
+                        yAxis: ["万m³"],
+                        series: [
+                            {
+                                name: '下泄水量',
+                                field: 'ww',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                        ]
+                    }
+                }
+                break;
+            case 'DW_XAJ_ST_KR':
+            case 'HS_SK_XAJ_KR':
+            case 'CA_SK_XAJ_KR':
+            case 'FD_XAJ_KR':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/krList?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/krList?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/xaj/krList?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'z', title: '水位(m)', fixed: 'left', align: 'center', width: 200}
+                        , {field: 'w', title: '库容(万m³)', align: 'center', width: 200}
+                    ],
+                    chartTable: [
+                        {field: 'z', title: '水位(m)', align: 'center', width: 150}
+                    ],
+                    chart: {
+                        title: '库容曲线',
+                        xCategory: 'kr',
+                        yAxis: ["m³"],
+                        series: [
+                            {
+                                name: '水位',
+                                field: 'z',
+                                type: 'line',
+                                color: "#5793F3",
+                                yAxisIndex: 0,
+                                selected: true
+                            }
+                        ]
+                    }
+                }
+                break;
+            case 'DW_XAJ_ST_XS':
+            case 'HS_SK_XAJ_XS':
+            case 'CA_SK_XAJ_XS':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'tm', title: '时间', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'w', title: '蓄水量(万m³)', align: 'center', width: 200}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', width: 150}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 150}
+                        , {field: 'w', title: '蓄水量(万m³)', align: 'center', width: 150}
+                    ],
+                    chart: {
+                        title: '水库蓄水变化过程图',
+                        xCategory: 'tm',
+                        yAxis: ["m", "万m³"],
+                        series: [
+                            {
+                                name: '水位',
+                                field: 'z',
+                                type: 'line',
+                                color: "#3adbe0",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                            {
+                                name: '蓄水量',
+                                field: 'w',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 1,
+                                selected: true
+                            }
+                        ]
+                    }
+                }
+                break;
+            case 'FD_XAJ_XS':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/xaj/skswList?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'stnm', title: '站点名称', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'tm', title: '时间', fixed: 'left', align: 'center', width: 250}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 200}
+                        , {field: 'w', title: '蓄水量(亿m³)', align: 'center', width: 200}
+                    ],
+                    chartTable: [
+                        {field: 'tm', title: '时间', align: 'center', width: 150}
+                        , {field: 'z', title: '水位(m)', align: 'center', width: 150}
+                        , {field: 'w', title: '蓄水量(亿m³)', align: 'center', width: 150}
+                    ],
+                    chart: {
+                        title: '水库蓄水变化过程图',
+                        xCategory: 'tm',
+                        yAxis: ["m", "亿m³"],
+                        series: [
+                            {
+                                name: '水位',
+                                field: 'z',
+                                type: 'line',
+                                color: "#3adbe0",
+                                yAxisIndex: 0,
+                                selected: true
+                            },
+                            {
+                                name: '蓄水量',
+                                field: 'w',
+                                type: 'bar',
+                                color: "#5793F3",
+                                yAxisIndex: 1,
+                                selected: true
+                            }
+                        ]
+                    }
+                }
+                break;
+            case 'WIU_XAJ':
+                return {
+                    listDataUrl: ctx + 'gx/xaj/wiuMonthList?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 80, templet: '#xuhao'}
+                        , {field: 'tm', title: '时间', fixed: 'left', align: 'center', width: 150}
+                        , {field: 'gongshuiWW', title: '公共供水企业用水量', align: 'center', width: 150}
+                        , {field: 'fwWW', title: '服务业自备水源用水量', align: 'center', width: 150}
+                        , {field: 'insdutryWW', title: '工业自备水源用水量', align: 'center', width: 150}
+                    ],
+                    chartTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 80, templet: '#xuhao'}
+                        , {field: 'tm', title: '时间', fixed: 'left', align: 'center', width: 150}
+                        , {field: 'gongshuiWW', title: '公共供水企业用水量', align: 'center', width: 150}
+                        , {field: 'fwWW', title: '服务业自备水源用水量', align: 'center', width: 150}
+                        , {field: 'insdutryWW', title: '工业自备水源用水量', align: 'center', width: 150}
+                    ],
+                    chart: {
+                        title: '分行业月度用水量',
+                        xCategory: 'tm',
+                        yAxis: ["万m³"],
+                        series: [
+                            {
+                                field: 'gongshuiWW',
+                                name: '公共供水企业用水量',
+                                type: 'bar',
+                                stack: 'tradTp',
+                                color: "#FCD521",
+                                selected: true
+                            }
+                            , {
+                                field: 'fwWW',
+                                name: '服务业自备水源用水量',
+                                type: 'bar',
+                                stack: 'tradTp',
+                                color: "#6F17FF",
+                                selected: true
+                            }
+                            , {
+                                field: 'insdutryWW',
+                                name: '工业自备水源用水量',
+                                type: 'bar',
+                                stack: 'tradTp',
+                                color: "#0277F4",
+                                selected: true
+                            }
+                        ]
+                    }
+                }
+                break;
+            case 'GDP_XAJ':
+                return {
+                    newestDataUrl: ctx + 'gx/xaj/gdpnewest?bizCode=' + bizCode,
+                    listDataUrl: ctx + 'gx/xaj/gdpList?bizCode=' + bizCode,
+                    downloadUrl: ctx + 'gx/sw/gcdd/download?bizCode=' + bizCode,
+                    timeBetween: 1,
+                    layuiTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'prov', title: '省份', fixed: 'left', align: 'center', width: 80}
+                        , {field: 'city', title: '城市', fixed: 'left', align: 'center', width: 80}
+                        , {field: 'county', title: '县区', fixed: 'left', align: 'center', width: 80}
+                        , {field: 'yr', title: '年份', fixed: 'left', align: 'center', width: 80}
+                        , {field: 'peoCitySum', title: '城市人口总数(万人)', align: 'center', width: 180}
+                        , {field: 'peoCountySum', title: '农村人口总数(万人)', align: 'center', width: 180}
+                        , {field: 'pepSum', title: '人口总数(万人)', align: 'center', width: 150}
+                        , {field: 'peoRadio', title: '城镇化率(%)', align: 'center', width: 150}
+                        // , {field: 'gdp1Sum', title: '一产', align: 'center', width: 80}
+                        // , {field: 'gdp2Sum', title: '二产', align: 'center', width: 80}
+                        // , {field: 'gdp3Sum', title: '三产', align: 'center', width: 80}
+                        , {field: 'gdpSum', title: '国内(地区)生产总值(亿元)', align: 'center', width: 250}
+                        , {field: 'insduAdd', title: '工业增加值(亿元)', align: 'center', width: 190}
+                        //, {field: 'effectIrrArea', title: '农田有效灌溉面积(万亩)', align: 'center', width: 120}
+                        , {field: 'gdArea', title: '耕地面积(万亩)', align: 'center', width: 190}
+                    ],
+                    chartTable: [
+                        {field: 'id', title: '序号', fixed: 'left', align: 'center', width: 100, templet: '#xuhao'}
+                        , {field: 'yr', title: '年份', fixed: 'left', align: 'center', width: 80}
+                        , {field: 'peoCitySum', title: '城市人口总数(万人)', align: 'center', width: 180}
+                        , {field: 'peoCountySum', title: '农村人口总数(万人)', align: 'center', width: 180}
+                        , {field: 'pepSum', title: '人口总数(万人)', align: 'center', width: 150}
+                        , {field: 'peoRadio', title: '城镇化率(%)', align: 'center', width: 150}
+                        , {field: 'gdpSum', title: '国内(地区)生产总值(亿元)', align: 'center', width: 250}
+                        , {field: 'insduAdd', title: '工业增加值(亿元)', align: 'center', width: 190}
+                        // , {field: 'effectIrrArea', title: '农田有效灌溉面积(万亩)', align: 'center', width: 100}
+                        , {field: 'gdArea', title: '耕地面积(万亩)', align: 'center', width: 190}
+                    ],
+                    chart: {
+                        title: 'GDP监测',
+                        xCategory: 'yr',
+                        yAxis: ["万人", "%", "亿元", "万亩"],
+                        series: [
+                            , {
+                                field: 'peoCitySum',
+                                name: '城市人口总数(万人)',
+                                type: 'bar',
+                                stack: 'peoTp',
+                                yAxisIndex: 0,
+                                selected: false
+                            }
+                            , {
+                                field: 'peoCountySum',
+                                name: '农村人口总数(万人)',
+                                type: 'bar',
+                                stack: 'peoTp',
+                                yAxisIndex: 0,
+                                selected: false
+                            }
+                            , {
+                                field: 'pepSum',
+                                name: '人口总数(万人)',
+                                type: 'line',
+                                stack: 'peoTp1',
+                                yAxisIndex: 0,
+                                selected: false
+                            }
+                            , {field: 'peoRadio', name: '城镇化率(%)', type: 'bar', yAxisIndex: 1, selected: false}
+                            , {
+                                field: 'gdpSum',
+                                name: '国内(地区)生产总值(亿元)',
+                                type: 'bar',
+                                yAxisIndex: 2,
+                                selected: true
+                            }
+                            , {field: 'insduAdd', name: '工业增加值(亿元)', type: 'bar', yAxisIndex: 2, selected: false}
+                            , {field: 'gdArea', name: '耕地面积(万亩)', type: 'bar', yAxisIndex: 3, selected: false}
+                        ]
+                    }
+                }
+                break;
+        }
+    }
+}
+
+function isblank(str) {
+    return str == '' || str == undefined || str == null;
+}
+
+function arrSUM(arr) {
+    var s = 0;
+    arr.forEach(function (val, idx, arr) {
+        if (val) {
+            s += val;
+        }
+    }, 0);
+    return s;
+}
+
+function downLoad(fileId) {
+    window.location.href = ctx + "biz/doc/file/downloadFile?fileId=" + fileId;
+}
+
+
+//罗桐埠和街口生态断面指标数据
+function stTargetData(stcd) {
+    switch (stcd) {
+        case '70112100'://罗桐埠
+            return [
+                {
+                    silent: false, label: {
+                        position: 'middle', // 文字位置
+                        formatter: '预警线  22.7m³/s',  //文字
+                        color: '#FA4009'
+                    }, yAxis: 22.7, lineStyle: {type: 'solid', color: "#FA4009", width: 1}
+                }
+            ];
+        case '70111400'://街口
+            return [
+                {
+                    silent: false, label: {
+                        position: 'middle', // 文字位置
+                        formatter: '蓝色预警线  9.2m³/s',  //文字
+                        color: '#0C57D0'
+                    }, yAxis: 9.2, lineStyle: {type: 'solid', color: "#0C57D0", width: 1}
+                },
+                {
+                    silent: false, label: {
+                        position: 'middle', // 文字位置
+                        formatter: '橙色预警线  7.7m³/s',  //文字
+                        color: '#FFAF0F'
+                    }, yAxis: 7.7, lineStyle: {type: 'solid', color: "#FFAF0F", width: 1}
+                },
+                {
+                    silent: false, label: {
+                        position: 'middle', // 文字位置
+                        formatter: '红色预警线  6.2m³/s',  //文字
+                        color: '#FA4009'
+                    }, yAxis: 6.2, lineStyle: {type: 'solid', color: "#FA4009", width: 1}
+                }
+            ];
+    }
+
+}

+ 14 - 1
gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/StXajBController.java

@@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import jakarta.annotation.Resource;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -95,9 +96,21 @@ public class StXajBController extends BaseController {
     @PreAuthorize("@ss.hasPermi('xajgl:station:query')")
     public AjaxResult dataList(
             @Parameter(description = "测站代码") @RequestParam("stcd") String stcd,
+            @Parameter(description = "业务域编码") @RequestParam("bizCode") String bizCode,
             @Parameter(description = "开始时间") @RequestParam(value = "startTm", required = false) String startTm,
             @Parameter(description = "结束时间") @RequestParam(value = "endTm", required = false) String endTm) {
-        List<StXajData> list = stXajDataService.selectStXajDataByStcd(stcd, startTm, endTm);
+        List<StXajData> list = stXajDataService.selectStXajDataByStcd(bizCode, stcd, startTm, endTm);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 按业务域查询站点最新数据
+     */
+    @GetMapping("/latestByBiz")
+    @Operation(summary = "按业务域查询最新数据", description = "根据业务域编码查询每个站点的最新监测数据")
+    @PreAuthorize("@ss.hasPermi('xajgl:station:query')")
+    public AjaxResult latestByBiz(@Parameter(description = "业务域编码") @RequestParam("bizCode") String bizCode) {
+        List<StXajData> list = stXajDataService.selectLatestDataByBiz(bizCode);
         return AjaxResult.success(list);
     }
 

+ 10 - 0
gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/StXajDataController.java

@@ -70,4 +70,14 @@ public class StXajDataController extends BaseController {
         ExcelUtil<StXajData> util = new ExcelUtil<StXajData>(StXajData.class);
         util.exportExcel(response, list, "新安江监测数据");
     }
+
+    /**
+     * 填报数据(手动或Excel导入)
+     */
+    @PostMapping("/importData")
+    @Operation(summary = "填报数据", description = "手动填报或Excel导入监测数据")
+    @PreAuthorize("@ss.hasPermi('xajgl:data:add')")
+    public AjaxResult importData(@RequestBody StXajData stXajData) {
+        return toAjax(stXajDataService.insertStXajData(stXajData));
+    }
 }

+ 44 - 0
gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/WwCityGdpXajController.java

@@ -0,0 +1,44 @@
+package com.goldenwater.web.controller.xajgl;
+
+import com.goldenwater.common.annotation.Log;
+import com.goldenwater.common.core.controller.BaseController;
+import com.goldenwater.common.core.domain.AjaxResult;
+import com.goldenwater.common.enums.BusinessType;
+import com.goldenwater.xajgl.domain.WwCityGdpXaj;
+import com.goldenwater.xajgl.service.IWwCityGdpXajService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+
+@RestController
+@RequestMapping("/xajgl/gdp")
+@Tag(name = "新安江GDP数据管理", description = "地方人民政府GDP数据管理接口")
+public class WwCityGdpXajController extends BaseController {
+
+    @Autowired
+    private IWwCityGdpXajService wwCityGdpXajService;
+
+    /**
+     * 查询各县区最新年份数据
+     */
+    @GetMapping("/latestByCounty")
+    @Operation(summary = "查询各县区最新年份数据", description = "获取每个区县最新年份的GDP等数据")
+    public AjaxResult selectLatestByCounty() {
+        List<WwCityGdpXaj> list = wwCityGdpXajService.selectLatestByCounty();
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 查询指定县区历史数据
+     */
+    @GetMapping("/historyByCounty")
+    @Operation(summary = "查询指定县区历史数据", description = "根据区县名称查询历史年份GDP数据")
+    public AjaxResult selectHistoryByCounty(
+            @Parameter(description = "区县名称") @RequestParam(value = "county") String county) {
+        List<WwCityGdpXaj> list = wwCityGdpXajService.selectHistoryByCounty(county);
+        return AjaxResult.success(list);
+    }
+}

+ 159 - 0
gw-admin/src/main/java/com/goldenwater/web/controller/xajgl/XajDocFileController.java

@@ -0,0 +1,159 @@
+package com.goldenwater.web.controller.xajgl;
+
+import com.goldenwater.common.annotation.Log;
+import com.goldenwater.common.config.RuoYiConfig;
+import com.goldenwater.common.core.controller.BaseController;
+import com.goldenwater.common.core.domain.AjaxResult;
+import com.goldenwater.common.enums.BusinessType;
+import com.goldenwater.xajgl.domain.XajDocFile;
+import com.goldenwater.xajgl.service.IXajDocFileService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.List;
+
+@RestController
+@RequestMapping("/xajgl/docFile")
+@Tag(name = "文件管理", description = "新安江文件管理接口")
+public class XajDocFileController extends BaseController {
+
+    @Autowired
+    private IXajDocFileService xajDocFileService;
+
+    /**
+     * 查询业务域下的文件列表
+     */
+    @GetMapping("/list")
+    @Operation(summary = "查询文件列表", description = "根据业务域编码查询文件列表")
+    public AjaxResult list(
+            @Parameter(description = "业务域编码") @RequestParam(value = "bizCode") String bizCode) {
+        List<XajDocFile> list = xajDocFileService.selectByBizCode(bizCode);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 上传文件
+     */
+    @PostMapping("/upload")
+    @Operation(summary = "上传文件", description = "上传文件并保存记录")
+    @Log(title = "文件上传", businessType = BusinessType.IMPORT)
+    public AjaxResult upload(@RequestParam("file") MultipartFile file,
+                             @RequestParam("bizCode") String bizCode,
+                             @RequestParam(value = "fileDesc", required = false) String fileDesc) {
+        try {
+            if (file.isEmpty()) {
+                return AjaxResult.error("上传文件不能为空");
+            }
+
+            String originalName = file.getOriginalFilename();
+            String suffix = "";
+            if (originalName != null && originalName.contains(".")) {
+                suffix = originalName.substring(originalName.lastIndexOf(".") + 1);
+            }
+
+            // 生成文件ID(时间戳)
+            String fileId = String.valueOf(System.currentTimeMillis());
+            // 保存路径
+            String saveDir = RuoYiConfig.getUploadPath() + File.separator + bizCode;
+            File dir = new File(saveDir);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+            String savePath = saveDir + File.separator + fileId + "." + suffix;
+            File dest = new File(savePath);
+            file.transferTo(dest);
+
+            // 保存记录
+            XajDocFile docFile = new XajDocFile();
+            docFile.setFileId(fileId);
+            docFile.setFileName(originalName);
+            docFile.setFileUser(getUsername());
+            docFile.setFileTime(new Date());
+            docFile.setBizCode(bizCode);
+            docFile.setFileType(suffix);
+            docFile.setFilePath(savePath);
+            docFile.setFileSize(BigDecimal.valueOf(file.getSize()));
+            docFile.setFileDesc(fileDesc);
+            xajDocFileService.insert(docFile);
+
+            return AjaxResult.success("上传成功");
+        } catch (Exception e) {
+            return AjaxResult.error("上传失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 下载文件
+     */
+    @GetMapping("/download")
+    @Operation(summary = "下载文件", description = "根据文件ID下载文件")
+    @Log(title = "文件下载", businessType = BusinessType.EXPORT)
+    public void download(@RequestParam("fileId") String fileId, HttpServletResponse response) {
+        try {
+            XajDocFile docFile = xajDocFileService.selectByFileId(fileId);
+            if (docFile == null) {
+                response.setContentType("application/json;charset=utf-8");
+                response.getWriter().write("{\"code\":500,\"msg\":\"文件不存在\"}");
+                return;
+            }
+
+            File file = new File(docFile.getFilePath());
+            if (!file.exists()) {
+                response.setContentType("application/json;charset=utf-8");
+                response.getWriter().write("{\"code\":500,\"msg\":\"文件已被删除\"}");
+                return;
+            }
+
+            // 更新下载次数
+            xajDocFileService.updateDownTimes(fileId);
+
+            // 设置响应头
+            String encodedName = URLEncoder.encode(docFile.getFileName(), StandardCharsets.UTF_8).replace("+", "%20");
+            response.setContentType("application/octet-stream");
+            response.setHeader("Content-Disposition", "attachment; filename=" + encodedName);
+            response.setContentLengthLong(file.length());
+
+            try (InputStream is = new FileInputStream(file);
+                 OutputStream os = response.getOutputStream()) {
+                byte[] buffer = new byte[4096];
+                int len;
+                while ((len = is.read(buffer)) != -1) {
+                    os.write(buffer, 0, len);
+                }
+                os.flush();
+            }
+        } catch (Exception e) {
+            logger.error("文件下载失败", e);
+        }
+    }
+
+    /**
+     * 删除文件
+     */
+    @DeleteMapping("/{fileId}")
+    @Operation(summary = "删除文件", description = "根据文件ID删除文件")
+    @Log(title = "文件删除", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@PathVariable("fileId") String fileId) {
+        XajDocFile docFile = xajDocFileService.selectByFileId(fileId);
+        if (docFile == null) {
+            return AjaxResult.error("文件不存在");
+        }
+        // 删除物理文件
+        File file = new File(docFile.getFilePath());
+        if (file.exists()) {
+            file.delete();
+        }
+        return toAjax(xajDocFileService.deleteByFileId(fileId));
+    }
+}

+ 24 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/domain/StXajData.java

@@ -68,4 +68,28 @@ public class StXajData extends BaseEntity {
     /** 蓄水量 */
     @Excel(name = "蓄水量")
     private BigDecimal w;
+
+    /** 省份 */
+    @Excel(name = "省份")
+    private String prov;
+
+    /** 地市名称 */
+    @Excel(name = "地市名称")
+    private String city;
+
+    /** 区县名称 */
+    @Excel(name = "区县名称")
+    private String county;
+
+    /** 区县分类 */
+    @Excel(name = "区县分类")
+    private String county1;
+
+    /** 社会信用编码 */
+    @Excel(name = "社会信用编码")
+    private String uscc;
+
+    /** 取水户类型 */
+    @Excel(name = "取水户类型")
+    private String tradTp;
 }

+ 165 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/domain/WwCityGdpXaj.java

@@ -0,0 +1,165 @@
+package com.goldenwater.xajgl.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+public class WwCityGdpXaj implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 省份 */
+    private String prov;
+
+    /** 年份 */
+    private String yr;
+
+    /** 地市 */
+    private String city;
+
+    /** 区县 */
+    private String county;
+
+    /** 城市人口总数(万人) */
+    private BigDecimal peoCitySum;
+
+    /** 农村人口总数(万人) */
+    private BigDecimal peoCountySum;
+
+    /** 人口总数(万人) */
+    private BigDecimal pepSum;
+
+    /** 一产(亿元) */
+    private BigDecimal gdp1Sum;
+
+    /** 二产(亿元) */
+    private BigDecimal gdp2Sum;
+
+    /** 三产(亿元) */
+    private BigDecimal gdp3Sum;
+
+    /** 合计(亿元) */
+    private BigDecimal gdpSum;
+
+    /** 农田有效灌溉面积(万亩) */
+    private BigDecimal effectIrrArea;
+
+    /** 城镇化率(%) */
+    private BigDecimal peoRadio;
+
+    /** 耕地面积(万亩) */
+    private BigDecimal gdArea;
+
+    /** 耕地有效灌溉面积(万亩) */
+    private BigDecimal effectGdArea;
+
+    /** 实际灌溉面积-耕地(万亩) */
+    private BigDecimal effectGgGd;
+
+    /** 实际灌溉面积-林地(万亩) */
+    private BigDecimal effectGgLd;
+
+    /** 实际灌溉面积-园地(万亩) */
+    private BigDecimal effectGgYd;
+
+    /** 实际灌溉面积-牧草地(万亩) */
+    private BigDecimal effectGgMcd;
+
+    /** 鱼塘补水面积(万亩) */
+    private BigDecimal ytbsArea;
+
+    /** 大牲畜(万头) */
+    private BigDecimal scBig;
+
+    /** 小牲畜(万头) */
+    private BigDecimal scSmall;
+
+    /** 牲畜合计(万头) */
+    private BigDecimal scSum;
+
+    /** 工业增加值(亿元) */
+    private BigDecimal insduAdd;
+
+    /** 粮食产量(万t) */
+    private BigDecimal argicuTt;
+
+    /** 顺序 */
+    private BigDecimal orderNm;
+
+    public String getProv() { return prov; }
+    public void setProv(String prov) { this.prov = prov; }
+
+    public String getYr() { return yr; }
+    public void setYr(String yr) { this.yr = yr; }
+
+    public String getCity() { return city; }
+    public void setCity(String city) { this.city = city; }
+
+    public String getCounty() { return county; }
+    public void setCounty(String county) { this.county = county; }
+
+    public BigDecimal getPeoCitySum() { return peoCitySum; }
+    public void setPeoCitySum(BigDecimal peoCitySum) { this.peoCitySum = peoCitySum; }
+
+    public BigDecimal getPeoCountySum() { return peoCountySum; }
+    public void setPeoCountySum(BigDecimal peoCountySum) { this.peoCountySum = peoCountySum; }
+
+    public BigDecimal getPepSum() { return pepSum; }
+    public void setPepSum(BigDecimal pepSum) { this.pepSum = pepSum; }
+
+    public BigDecimal getGdp1Sum() { return gdp1Sum; }
+    public void setGdp1Sum(BigDecimal gdp1Sum) { this.gdp1Sum = gdp1Sum; }
+
+    public BigDecimal getGdp2Sum() { return gdp2Sum; }
+    public void setGdp2Sum(BigDecimal gdp2Sum) { this.gdp2Sum = gdp2Sum; }
+
+    public BigDecimal getGdp3Sum() { return gdp3Sum; }
+    public void setGdp3Sum(BigDecimal gdp3Sum) { this.gdp3Sum = gdp3Sum; }
+
+    public BigDecimal getGdpSum() { return gdpSum; }
+    public void setGdpSum(BigDecimal gdpSum) { this.gdpSum = gdpSum; }
+
+    public BigDecimal getEffectIrrArea() { return effectIrrArea; }
+    public void setEffectIrrArea(BigDecimal effectIrrArea) { this.effectIrrArea = effectIrrArea; }
+
+    public BigDecimal getPeoRadio() { return peoRadio; }
+    public void setPeoRadio(BigDecimal peoRadio) { this.peoRadio = peoRadio; }
+
+    public BigDecimal getGdArea() { return gdArea; }
+    public void setGdArea(BigDecimal gdArea) { this.gdArea = gdArea; }
+
+    public BigDecimal getEffectGdArea() { return effectGdArea; }
+    public void setEffectGdArea(BigDecimal effectGdArea) { this.effectGdArea = effectGdArea; }
+
+    public BigDecimal getEffectGgGd() { return effectGgGd; }
+    public void setEffectGgGd(BigDecimal effectGgGd) { this.effectGgGd = effectGgGd; }
+
+    public BigDecimal getEffectGgLd() { return effectGgLd; }
+    public void setEffectGgLd(BigDecimal effectGgLd) { this.effectGgLd = effectGgLd; }
+
+    public BigDecimal getEffectGgYd() { return effectGgYd; }
+    public void setEffectGgYd(BigDecimal effectGgYd) { this.effectGgYd = effectGgYd; }
+
+    public BigDecimal getEffectGgMcd() { return effectGgMcd; }
+    public void setEffectGgMcd(BigDecimal effectGgMcd) { this.effectGgMcd = effectGgMcd; }
+
+    public BigDecimal getYtbsArea() { return ytbsArea; }
+    public void setYtbsArea(BigDecimal ytbsArea) { this.ytbsArea = ytbsArea; }
+
+    public BigDecimal getScBig() { return scBig; }
+    public void setScBig(BigDecimal scBig) { this.scBig = scBig; }
+
+    public BigDecimal getScSmall() { return scSmall; }
+    public void setScSmall(BigDecimal scSmall) { this.scSmall = scSmall; }
+
+    public BigDecimal getScSum() { return scSum; }
+    public void setScSum(BigDecimal scSum) { this.scSum = scSum; }
+
+    public BigDecimal getInsduAdd() { return insduAdd; }
+    public void setInsduAdd(BigDecimal insduAdd) { this.insduAdd = insduAdd; }
+
+    public BigDecimal getArgicuTt() { return argicuTt; }
+    public void setArgicuTt(BigDecimal argicuTt) { this.argicuTt = argicuTt; }
+
+    public BigDecimal getOrderNm() { return orderNm; }
+    public void setOrderNm(BigDecimal orderNm) { this.orderNm = orderNm; }
+}

+ 69 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/domain/XajDocFile.java

@@ -0,0 +1,69 @@
+package com.goldenwater.xajgl.domain;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+public class XajDocFile implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 文件ID */
+    private String fileId;
+
+    /** 文件名称 */
+    private String fileName;
+
+    /** 上传人 */
+    private String fileUser;
+
+    /** 上传时间 */
+    private Date fileTime;
+
+    /** 业务域编码 */
+    private String bizCode;
+
+    /** 文件后缀 */
+    private String fileType;
+
+    /** 保存路径 */
+    private String filePath;
+
+    /** 下载次数 */
+    private BigDecimal downTimes;
+
+    /** 文件大小 */
+    private BigDecimal fileSize;
+
+    /** 文件描述 */
+    private String fileDesc;
+
+    public String getFileId() { return fileId; }
+    public void setFileId(String fileId) { this.fileId = fileId; }
+
+    public String getFileName() { return fileName; }
+    public void setFileName(String fileName) { this.fileName = fileName; }
+
+    public String getFileUser() { return fileUser; }
+    public void setFileUser(String fileUser) { this.fileUser = fileUser; }
+
+    public Date getFileTime() { return fileTime; }
+    public void setFileTime(Date fileTime) { this.fileTime = fileTime; }
+
+    public String getBizCode() { return bizCode; }
+    public void setBizCode(String bizCode) { this.bizCode = bizCode; }
+
+    public String getFileType() { return fileType; }
+    public void setFileType(String fileType) { this.fileType = fileType; }
+
+    public String getFilePath() { return filePath; }
+    public void setFilePath(String filePath) { this.filePath = filePath; }
+
+    public BigDecimal getDownTimes() { return downTimes; }
+    public void setDownTimes(BigDecimal downTimes) { this.downTimes = downTimes; }
+
+    public BigDecimal getFileSize() { return fileSize; }
+    public void setFileSize(BigDecimal fileSize) { this.fileSize = fileSize; }
+
+    public String getFileDesc() { return fileDesc; }
+    public void setFileDesc(String fileDesc) { this.fileDesc = fileDesc; }
+}

+ 5 - 1
gw-gx/src/main/java/com/goldenwater/xajgl/mapper/StXajDataMapper.java

@@ -16,9 +16,13 @@ public interface StXajDataMapper {
 
     List<StXajData> selectStXajDataList(StXajData stXajData);
 
-    List<StXajData> selectStXajDataByStcd(@Param("stcd") String stcd,
+    List<StXajData> selectStXajDataByStcd(@Param("bizCode") String bizCode, @Param("stcd") String stcd,
                                           @Param("startTm") String startTm,
                                           @Param("endTm") String endTm);
 
     int deleteStXajDataByStcd(@Param("stcd") String stcd);
+
+    List<StXajData> selectLatestDataByBiz(@Param("bizCode") String bizCode);
+
+    int insertStXajData(StXajData stXajData);
 }

+ 18 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/mapper/WwCityGdpXajMapper.java

@@ -0,0 +1,18 @@
+package com.goldenwater.xajgl.mapper;
+
+import com.goldenwater.xajgl.domain.WwCityGdpXaj;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+public interface WwCityGdpXajMapper {
+
+    /**
+     * 查询各县区最新年份数据
+     */
+    List<WwCityGdpXaj> selectLatestByCounty();
+
+    /**
+     * 查询指定县区历史数据
+     */
+    List<WwCityGdpXaj> selectHistoryByCounty(@Param("county") String county);
+}

+ 33 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/mapper/XajDocFileMapper.java

@@ -0,0 +1,33 @@
+package com.goldenwater.xajgl.mapper;
+
+import com.goldenwater.xajgl.domain.XajDocFile;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+public interface XajDocFileMapper {
+
+    /**
+     * 根据业务域编码查询文件列表
+     */
+    List<XajDocFile> selectByBizCode(@Param("bizCode") String bizCode);
+
+    /**
+     * 根据文件ID查询
+     */
+    XajDocFile selectByFileId(@Param("fileId") String fileId);
+
+    /**
+     * 新增文件记录
+     */
+    int insert(XajDocFile xajDocFile);
+
+    /**
+     * 更新下载次数
+     */
+    int updateDownTimes(@Param("fileId") String fileId);
+
+    /**
+     * 删除文件记录
+     */
+    int deleteByFileId(@Param("fileId") String fileId);
+}

+ 5 - 1
gw-gx/src/main/java/com/goldenwater/xajgl/service/IStXajDataService.java

@@ -13,7 +13,11 @@ public interface IStXajDataService {
 
     List<StXajData> selectStXajDataList(StXajData stXajData);
 
-    List<StXajData> selectStXajDataByStcd(String stcd, String startTm, String endTm);
+    List<StXajData> selectStXajDataByStcd(String bizCode,String stcd, String startTm, String endTm);
 
     int deleteStXajDataByStcd(String stcd);
+
+    List<StXajData> selectLatestDataByBiz(String bizCode);
+
+    int insertStXajData(StXajData stXajData);
 }

+ 17 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/service/IWwCityGdpXajService.java

@@ -0,0 +1,17 @@
+package com.goldenwater.xajgl.service;
+
+import com.goldenwater.xajgl.domain.WwCityGdpXaj;
+import java.util.List;
+
+public interface IWwCityGdpXajService {
+
+    /**
+     * 查询各县区最新年份数据
+     */
+    List<WwCityGdpXaj> selectLatestByCounty();
+
+    /**
+     * 查询指定县区历史数据
+     */
+    List<WwCityGdpXaj> selectHistoryByCounty(String county);
+}

+ 17 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/service/IXajDocFileService.java

@@ -0,0 +1,17 @@
+package com.goldenwater.xajgl.service;
+
+import com.goldenwater.xajgl.domain.XajDocFile;
+import java.util.List;
+
+public interface IXajDocFileService {
+
+    List<XajDocFile> selectByBizCode(String bizCode);
+
+    XajDocFile selectByFileId(String fileId);
+
+    int insert(XajDocFile xajDocFile);
+
+    int updateDownTimes(String fileId);
+
+    int deleteByFileId(String fileId);
+}

+ 13 - 2
gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/StXajDataServiceImpl.java

@@ -6,6 +6,7 @@ import com.goldenwater.xajgl.service.IStXajDataService;
 import org.springframework.stereotype.Service;
 
 import jakarta.annotation.Resource;
+
 import java.util.List;
 
 /**
@@ -25,12 +26,22 @@ public class StXajDataServiceImpl implements IStXajDataService {
     }
 
     @Override
-    public List<StXajData> selectStXajDataByStcd(String stcd, String startTm, String endTm) {
-        return stXajDataMapper.selectStXajDataByStcd(stcd, startTm, endTm);
+    public List<StXajData> selectStXajDataByStcd(String bizCode, String stcd, String startTm, String endTm) {
+        return stXajDataMapper.selectStXajDataByStcd(bizCode, stcd, startTm, endTm);
     }
 
     @Override
     public int deleteStXajDataByStcd(String stcd) {
         return stXajDataMapper.deleteStXajDataByStcd(stcd);
     }
+
+    @Override
+    public List<StXajData> selectLatestDataByBiz(String bizCode) {
+        return stXajDataMapper.selectLatestDataByBiz(bizCode);
+    }
+
+    @Override
+    public int insertStXajData(StXajData stXajData) {
+        return stXajDataMapper.insertStXajData(stXajData);
+    }
 }

+ 25 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/WwCityGdpXajServiceImpl.java

@@ -0,0 +1,25 @@
+package com.goldenwater.xajgl.service.impl;
+
+import com.goldenwater.xajgl.domain.WwCityGdpXaj;
+import com.goldenwater.xajgl.mapper.WwCityGdpXajMapper;
+import com.goldenwater.xajgl.service.IWwCityGdpXajService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import java.util.List;
+
+@Service("wwCityGdpXajService")
+public class WwCityGdpXajServiceImpl implements IWwCityGdpXajService {
+
+    @Resource
+    private WwCityGdpXajMapper wwCityGdpXajMapper;
+
+    @Override
+    public List<WwCityGdpXaj> selectLatestByCounty() {
+        return wwCityGdpXajMapper.selectLatestByCounty();
+    }
+
+    @Override
+    public List<WwCityGdpXaj> selectHistoryByCounty(String county) {
+        return wwCityGdpXajMapper.selectHistoryByCounty(county);
+    }
+}

+ 40 - 0
gw-gx/src/main/java/com/goldenwater/xajgl/service/impl/XajDocFileServiceImpl.java

@@ -0,0 +1,40 @@
+package com.goldenwater.xajgl.service.impl;
+
+import com.goldenwater.xajgl.domain.XajDocFile;
+import com.goldenwater.xajgl.mapper.XajDocFileMapper;
+import com.goldenwater.xajgl.service.IXajDocFileService;
+import org.springframework.stereotype.Service;
+import jakarta.annotation.Resource;
+import java.util.List;
+
+@Service("xajDocFileService")
+public class XajDocFileServiceImpl implements IXajDocFileService {
+
+    @Resource
+    private XajDocFileMapper xajDocFileMapper;
+
+    @Override
+    public List<XajDocFile> selectByBizCode(String bizCode) {
+        return xajDocFileMapper.selectByBizCode(bizCode);
+    }
+
+    @Override
+    public XajDocFile selectByFileId(String fileId) {
+        return xajDocFileMapper.selectByFileId(fileId);
+    }
+
+    @Override
+    public int insert(XajDocFile xajDocFile) {
+        return xajDocFileMapper.insert(xajDocFile);
+    }
+
+    @Override
+    public int updateDownTimes(String fileId) {
+        return xajDocFileMapper.updateDownTimes(fileId);
+    }
+
+    @Override
+    public int deleteByFileId(String fileId) {
+        return xajDocFileMapper.deleteByFileId(fileId);
+    }
+}

+ 78 - 11
gw-gx/src/main/resources/mapper/xajgl/StXajDataMapper.xml

@@ -16,6 +16,12 @@
         <result property="ww"       column="WW"        />
         <result property="bizCode"  column="BIZ_CODE"  />
         <result property="w"        column="W"         />
+        <result property="prov"     column="PROV"      />
+        <result property="city"     column="CITY"      />
+        <result property="county"   column="COUNTY"    />
+        <result property="county1"  column="COUNTY1"   />
+        <result property="uscc"     column="USCC"      />
+        <result property="tradTp"   column="TRAD_TP"   />
         <result property="createBy"   column="CREATE_BY"  />
         <result property="createTime" column="CREATE_TIME"/>
         <result property="updateBy"   column="UPDATE_BY"  />
@@ -36,48 +42,109 @@
                CAST(NULLIF(TRIM(d.WW), '') AS DECIMAL(15,3)) as WW,
                d.BIZ_CODE,
                CAST(NULLIF(TRIM(d.W), '') AS DECIMAL(15,3)) as W,
+               b.PROV, b.CITY, b.COUNTY, b.COUNTY1, b.USCC, b.TRAD_TP,
                d.CREATE_BY, d.CREATE_TIME, d.UPDATE_BY, d.UPDATE_TIME, d.REMARK
         from ST_XAJ_DATA d
         left join ST_XAJ_B b on d.STCD = b.STCD
     </sql>
 
     <select id="selectStXajDataList" parameterType="com.goldenwater.xajgl.domain.StXajData" resultMap="StXajDataResult">
-        <include refid="selectStXajDataVo"/>
+        select distinct STCD, STNM, TM, DRP, Z, Q, DYP, DWZ, INQ, OUTQ, WW, BIZ_CODE, W,
+               PROV, CITY, COUNTY, COUNTY1, USCC, TRAD_TP,
+               CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, REMARK
+        from (
+            <include refid="selectStXajDataVo"/>
+        ) t
         <where>
             <if test="stcd != null and stcd != ''">
-                and d.STCD like concat('%', #{stcd}, '%')
+                and t.STCD like concat('%', #{stcd}, '%')
             </if>
             <if test="bizCode != null and bizCode != ''">
-                and d.BIZ_CODE = #{bizCode}
+                and t.BIZ_CODE = #{bizCode}
             </if>
             <if test="params.beginTime != null and params.beginTime != ''">
-                and d.TM &gt;= TO_DATE(#{params.beginTime}, 'YYYY-MM-DD HH24:MI:SS')
+                and t.TM &gt;= TO_DATE(#{params.beginTime}, 'YYYY-MM-DD HH24:MI:SS')
             </if>
             <if test="params.endTime != null and params.endTime != ''">
-                and d.TM &lt;= TO_DATE(CONCAT(#{params.endTime}, ' 23:59:59'), 'YYYY-MM-DD HH24:MI:SS')
+                and t.TM &lt;= TO_DATE(CONCAT(#{params.endTime}, ' 23:59:59'), 'YYYY-MM-DD HH24:MI:SS')
             </if>
         </where>
-        order by d.TM desc
+        order by t.TM desc
     </select>
 
     <select id="selectStXajDataByStcd" resultMap="StXajDataResult">
-        <include refid="selectStXajDataVo"/>
+        select distinct STCD, STNM, TM, DRP, Z, Q, DYP, DWZ, INQ, OUTQ, WW, BIZ_CODE, W,
+               PROV, CITY, COUNTY, COUNTY1, USCC, TRAD_TP,
+               CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, REMARK
+        from (
+            <include refid="selectStXajDataVo"/>
+        ) t
         <where>
             <if test="stcd != null and stcd != ''">
-                and d.STCD = #{stcd}
+                and t.STCD = #{stcd}
+            </if>
+            <if test="bizCode != null and bizCode != ''">
+                and t.BIZ_CODE = #{bizCode}
             </if>
             <if test="startTm != null and startTm != ''">
-                and d.TM &gt;= TO_DATE(#{startTm}, 'YYYY-MM-DD HH24:MI:SS')
+                and t.TM &gt;= TO_DATE(#{startTm}, 'YYYY-MM-DD HH24:MI:SS')
             </if>
             <if test="endTm != null and endTm != ''">
-                and d.TM &lt;= TO_DATE(CONCAT(#{endTm}, ' 23:59:59'), 'YYYY-MM-DD HH24:MI:SS')
+                and t.TM &lt;= TO_DATE(CONCAT(#{endTm}, ' 23:59:59'), 'YYYY-MM-DD HH24:MI:SS')
             </if>
         </where>
-        order by d.TM desc
+        order by t.TM desc
     </select>
 
     <delete id="deleteStXajDataByStcd" parameterType="String">
         delete from ST_XAJ_DATA where STCD = #{stcd}
     </delete>
 
+    <select id="selectLatestDataByBiz" resultMap="StXajDataResult">
+        select STCD, STNM, TM, DRP, Z, Q, DYP, DWZ, INQ, OUTQ, WW, BIZ_CODE, W,
+               PROV, CITY, COUNTY, COUNTY1, USCC, TRAD_TP,
+               CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, REMARK
+        from (
+            select d.STCD, d.TM,
+                   b.STNM,
+                   CAST(NULLIF(TRIM(d.DRP), '') AS DECIMAL(15,3)) as DRP,
+                   CAST(NULLIF(TRIM(d.Z), '') AS DECIMAL(15,3)) as Z,
+                   CAST(NULLIF(TRIM(d.Q), '') AS DECIMAL(15,3)) as Q,
+                   CAST(NULLIF(TRIM(d.DYP), '') AS DECIMAL(15,3)) as DYP,
+                   CAST(NULLIF(TRIM(d.DWZ), '') AS DECIMAL(15,3)) as DWZ,
+                   CAST(NULLIF(TRIM(d.INQ), '') AS DECIMAL(15,3)) as INQ,
+                   CAST(NULLIF(TRIM(d.OUTQ), '') AS DECIMAL(15,3)) as OUTQ,
+                   CAST(NULLIF(TRIM(d.WW), '') AS DECIMAL(15,3)) as WW,
+                   d.BIZ_CODE,
+                   CAST(NULLIF(TRIM(d.W), '') AS DECIMAL(15,3)) as W,
+                   b.PROV, b.CITY, b.COUNTY, b.COUNTY1, b.USCC, b.TRAD_TP,
+                   d.CREATE_BY, d.CREATE_TIME, d.UPDATE_BY, d.UPDATE_TIME, d.REMARK,
+                   ROW_NUMBER() OVER (PARTITION BY d.STCD ORDER BY d.TM DESC) as rn
+            from ST_XAJ_DATA d
+            left join ST_XAJ_B b on d.STCD = b.STCD
+            where d.BIZ_CODE = #{bizCode}
+        ) t
+        where t.rn = 1
+        order by t.STCD
+    </select>
+
+    <insert id="insertStXajData" parameterType="com.goldenwater.xajgl.domain.StXajData">
+        INSERT INTO ST_XAJ_DATA (STCD, TM, DRP, Z, Q, DYP, DWZ, INQ, OUTQ, WW, BIZ_CODE, W, CREATE_TIME)
+        VALUES (
+            #{stcd},
+            #{tm},
+            #{drp},
+            #{z},
+            #{q},
+            #{dyp},
+            #{dwz},
+            #{inq},
+            #{outq},
+            #{ww},
+            #{bizCode},
+            #{w},
+            SYSDATE
+        )
+    </insert>
+
 </mapper>

+ 67 - 0
gw-gx/src/main/resources/mapper/xajgl/WwCityGdpXajMapper.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.goldenwater.xajgl.mapper.WwCityGdpXajMapper">
+
+    <resultMap type="com.goldenwater.xajgl.domain.WwCityGdpXaj" id="WwCityGdpXajMap">
+        <result property="prov" column="PROV"/>
+        <result property="yr" column="YR"/>
+        <result property="city" column="CITY"/>
+        <result property="county" column="COUNTY"/>
+        <result property="peoCitySum" column="PEO_CITY_SUM"/>
+        <result property="peoCountySum" column="PEO_COUNTY_SUM"/>
+        <result property="pepSum" column="PEP_SUM"/>
+        <result property="gdp1Sum" column="GDP_1_SUM"/>
+        <result property="gdp2Sum" column="GDP_2_SUM"/>
+        <result property="gdp3Sum" column="GDP_3_SUM"/>
+        <result property="gdpSum" column="GDP_SUM"/>
+        <result property="effectIrrArea" column="EFFECT_IRR_AREA"/>
+        <result property="peoRadio" column="PEO_RADIO"/>
+        <result property="gdArea" column="GD_AREA"/>
+        <result property="effectGdArea" column="EFFECT_GD_AREA"/>
+        <result property="effectGgGd" column="EFFECT_GG_GD"/>
+        <result property="effectGgLd" column="EFFECT_GG_LD"/>
+        <result property="effectGgYd" column="EFFECT_GG_YD"/>
+        <result property="effectGgMcd" column="EFFECT_GG_MCD"/>
+        <result property="ytbsArea" column="YTBS_AREA"/>
+        <result property="scBig" column="SC_BIG"/>
+        <result property="scSmall" column="SC_SMALL"/>
+        <result property="scSum" column="SC_SUM"/>
+        <result property="insduAdd" column="INSDU_ADD"/>
+        <result property="argicuTt" column="ARGICU_TT"/>
+        <result property="orderNm" column="ORDER_NM"/>
+    </resultMap>
+
+    <select id="selectLatestByCounty" resultMap="WwCityGdpXajMap">
+        select t.PROV, t.YR, t.CITY, t.COUNTY,
+               t.PEO_CITY_SUM, t.PEO_COUNTY_SUM, t.PEP_SUM,
+               t.GDP_1_SUM, t.GDP_2_SUM, t.GDP_3_SUM, t.GDP_SUM,
+               t.EFFECT_IRR_AREA, t.PEO_RADIO, t.GD_AREA,
+               t.EFFECT_GD_AREA, t.EFFECT_GG_GD, t.EFFECT_GG_LD,
+               t.EFFECT_GG_YD, t.EFFECT_GG_MCD, t.YTBS_AREA,
+               t.SC_BIG, t.SC_SMALL, t.SC_SUM,
+               t.INSDU_ADD, t.ARGICU_TT, t.ORDER_NM
+        from WW_CITY_GDP_XAJ t
+        inner join (
+            select COUNTY, MAX(YR) as MAX_YR
+            from WW_CITY_GDP_XAJ
+            group by COUNTY
+        ) m on t.COUNTY = m.COUNTY and t.YR = m.MAX_YR
+        order by t.ORDER_NM
+    </select>
+
+    <select id="selectHistoryByCounty" resultMap="WwCityGdpXajMap">
+        select PROV, YR, CITY, COUNTY,
+               PEO_CITY_SUM, PEO_COUNTY_SUM, PEP_SUM,
+               GDP_1_SUM, GDP_2_SUM, GDP_3_SUM, GDP_SUM,
+               EFFECT_IRR_AREA, PEO_RADIO, GD_AREA,
+               EFFECT_GD_AREA, EFFECT_GG_GD, EFFECT_GG_LD,
+               EFFECT_GG_YD, EFFECT_GG_MCD, YTBS_AREA,
+               SC_BIG, SC_SMALL, SC_SUM,
+               INSDU_ADD, ARGICU_TT, ORDER_NM
+        from WW_CITY_GDP_XAJ
+        where COUNTY = #{county}
+        order by YR
+    </select>
+
+</mapper>

+ 50 - 0
gw-gx/src/main/resources/mapper/xajgl/XajDocFileMapper.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.goldenwater.xajgl.mapper.XajDocFileMapper">
+
+    <resultMap type="com.goldenwater.xajgl.domain.XajDocFile" id="XajDocFileMap">
+        <result property="fileId" column="FILE_ID"/>
+        <result property="fileName" column="FILE_NAME"/>
+        <result property="fileUser" column="FILE_USER"/>
+        <result property="fileTime" column="FILE_TIME"/>
+        <result property="bizCode" column="BIZ_CODE"/>
+        <result property="fileType" column="FILE_TYPE"/>
+        <result property="filePath" column="FILE_PATH"/>
+        <result property="downTimes" column="DOWN_TIMES"/>
+        <result property="fileSize" column="FILE_SIZE"/>
+        <result property="fileDesc" column="FILE_DESC"/>
+    </resultMap>
+
+    <select id="selectByBizCode" resultMap="XajDocFileMap">
+        SELECT FILE_ID, FILE_NAME, FILE_USER, FILE_TIME, BIZ_CODE,
+               FILE_TYPE, FILE_PATH, DOWN_TIMES, FILE_SIZE, FILE_DESC
+        FROM XAJ_DOC_FILE
+        WHERE BIZ_CODE = #{bizCode}
+        ORDER BY FILE_TIME DESC
+    </select>
+
+    <select id="selectByFileId" resultMap="XajDocFileMap">
+        SELECT FILE_ID, FILE_NAME, FILE_USER, FILE_TIME, BIZ_CODE,
+               FILE_TYPE, FILE_PATH, DOWN_TIMES, FILE_SIZE, FILE_DESC
+        FROM XAJ_DOC_FILE
+        WHERE FILE_ID = #{fileId}
+    </select>
+
+    <insert id="insert" parameterType="com.goldenwater.xajgl.domain.XajDocFile">
+        INSERT INTO XAJ_DOC_FILE (FILE_ID, FILE_NAME, FILE_USER, FILE_TIME, BIZ_CODE,
+                                  FILE_TYPE, FILE_PATH, DOWN_TIMES, FILE_SIZE, FILE_DESC)
+        VALUES (#{fileId}, #{fileName}, #{fileUser}, #{fileTime}, #{bizCode},
+                #{fileType}, #{filePath}, 0, #{fileSize}, #{fileDesc})
+    </insert>
+
+    <update id="updateDownTimes">
+        UPDATE XAJ_DOC_FILE SET DOWN_TIMES = NVL(DOWN_TIMES, 0) + 1
+        WHERE FILE_ID = #{fileId}
+    </update>
+
+    <delete id="deleteByFileId">
+        DELETE FROM XAJ_DOC_FILE WHERE FILE_ID = #{fileId}
+    </delete>
+
+</mapper>

+ 1 - 1
gw-gx/src/main/resources/mapper/xajgl/XajUnitMapper.xml

@@ -24,7 +24,7 @@
 
     <select id="selectXajUnitList" parameterType="com.goldenwater.xajgl.domain.XajUnit" resultMap="XajUnitResult">
         SELECT UNIT_CODE, UNIT_NAME, TYPE, ADDR, LINKMAN, TELE, MAIL, FAX, URL, NOTE,
-               CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, REMARK, DEL_FLAG
+               ORDER_NUM, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, REMARK, DEL_FLAG
         FROM ST_XAJ_UNIT
         WHERE DEL_FLAG = '0'
         <if test="unitCode != null and unitCode != ''">

+ 33 - 0
gw-ui/src/api/xajgl/docFile.js

@@ -0,0 +1,33 @@
+import request from '@/utils/request'
+
+// 查询业务域下的文件列表
+export function listDocFiles(bizCode) {
+  return request({
+    url: '/xajgl/docFile/list',
+    method: 'get',
+    params: { bizCode }
+  })
+}
+
+// 上传文件
+export function uploadDocFile(data) {
+  return request({
+    url: '/xajgl/docFile/upload',
+    method: 'post',
+    headers: { 'Content-Type': 'multipart/form-data' },
+    data
+  })
+}
+
+// 删除文件
+export function deleteDocFile(fileId) {
+  return request({
+    url: '/xajgl/docFile/' + fileId,
+    method: 'delete'
+  })
+}
+
+// 下载文件URL
+export function downloadDocFileUrl(fileId) {
+  return '/xajgl/docFile/download?fileId=' + fileId
+}

+ 18 - 0
gw-ui/src/api/xajgl/gdp.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// 查询各县区最新年份GDP数据
+export function getLatestGdpByCounty() {
+  return request({
+    url: '/xajgl/gdp/latestByCounty',
+    method: 'get'
+  })
+}
+
+// 查询指定县区历史GDP数据
+export function getGdpHistoryByCounty(county) {
+  return request({
+    url: '/xajgl/gdp/historyByCounty',
+    method: 'get',
+    params: { county }
+  })
+}

+ 20 - 2
gw-ui/src/api/xajgl/station.js

@@ -46,11 +46,11 @@ export function listQx(stcd) {
 }
 
 // 查询监测数据(图表用)
-export function listData(stcd, startTm, endTm) {
+export function listData(stcd, startTm, endTm, bizCode) {
   return request({
     url: '/xajgl/station/dataList',
     method: 'get',
-    params: { stcd, startTm, endTm }
+    params: { stcd, startTm, endTm, bizCode }
   })
 }
 
@@ -63,6 +63,15 @@ export function getLatestData(stcd) {
   })
 }
 
+// 按业务域查询站点最新数据(使用MAX语法)
+export function getLatestDataByBiz(bizCode) {
+  return request({
+    url: '/xajgl/station/latestByBiz',
+    method: 'get',
+    params: { bizCode }
+  })
+}
+
 // 新增站点
 export function addStation(data) {
   return request({
@@ -119,3 +128,12 @@ export function importStationTemplate() {
     responseType: 'blob'
   })
 }
+
+// 填报数据(手动或Excel导入)
+export function importData(data) {
+  return request({
+    url: '/xajgl/data/importData',
+    method: 'post',
+    data
+  })
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11 - 1175
gw-ui/src/views/front/Xaj.vue


+ 76 - 0
gw-ui/src/views/front/xaj/FeedbackModule.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="feedback-module">
+    <div class="feedback-container">
+      <h3>意见反馈</h3>
+      <el-form :model="feedbackForm" label-width="100px" class="feedback-form">
+        <el-form-item label="反馈类型">
+          <el-select v-model="feedbackForm.type" placeholder="请选择反馈类型">
+            <el-option label="功能建议" value="suggestion" />
+            <el-option label="问题反馈" value="bug" />
+            <el-option label="其他" value="other" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="反馈内容">
+          <el-input
+            v-model="feedbackForm.content"
+            type="textarea"
+            :rows="6"
+            placeholder="请输入您的反馈内容..."
+          />
+        </el-form-item>
+        <el-form-item label="联系方式">
+          <el-input v-model="feedbackForm.contact" placeholder="请输入联系方式(选填)" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="submitFeedback">提交反馈</el-button>
+          <el-button @click="resetFeedback">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script setup name="FeedbackModule">
+import { reactive } from 'vue'
+import { ElMessage } from 'element-plus'
+
+const feedbackForm = reactive({ type: '', content: '', contact: '' })
+
+function submitFeedback() {
+  ElMessage.success('反馈提交成功,感谢您的宝贵意见!')
+  resetFeedback()
+}
+
+function resetFeedback() {
+  feedbackForm.type = ''
+  feedbackForm.content = ''
+  feedbackForm.contact = ''
+}
+</script>
+
+<style scoped>
+.feedback-module {
+  flex: 1;
+  padding: 16px;
+  overflow: auto;
+}
+
+.feedback-container {
+  background: #fff;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+}
+
+.feedback-container h3 {
+  margin: 0 0 20px 0;
+  font-size: 16px;
+  color: #303133;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.feedback-form {
+  max-width: 600px;
+}
+</style>

+ 634 - 0
gw-ui/src/views/front/xaj/GisModule.vue

@@ -0,0 +1,634 @@
+<template>
+  <div class="gis-module">
+    <el-tabs v-model="activeTab" class="xaj-tabs">
+      <el-tab-pane label="水资源情势" name="situation">
+        <div class="map-wrapper">
+          <div ref="mapContainer" class="map-container"></div>
+
+          <div class="stats-panel">
+            <div class="panel-title">水资源情势统计情况</div>
+            <div class="stat-item">
+              <div class="stat-label">新安江流域平均降雨量</div>
+              <div class="stat-value-row">
+                <span class="stat-value">累计降雨 <b>1393.4mm</b></span>
+                <span class="stat-compare less">较多年平均 -3.20%</span>
+              </div>
+            </div>
+            <div class="stat-item">
+              <div class="stat-label">新安江水库罗桐埠断面</div>
+              <div class="stat-value-row">
+                <span class="stat-value">实际下泄量 <b>56.85亿m³</b></span>
+                <span class="stat-compare">年度计划 <b>77.90亿m³</b></span>
+              </div>
+            </div>
+            <div class="stat-item">
+              <div class="stat-label">浙皖省界接口断面</div>
+              <div class="stat-value-row">
+                <span class="stat-value">实际下泄量 <b>55.99亿m³</b></span>
+                <span class="stat-compare more">年度计划 <b>42.00亿m³</b></span>
+              </div>
+            </div>
+          </div>
+
+          <div class="legend-panel legend-left">
+            <div class="legend-title">数据对比</div>
+            <div class="legend-item" v-for="item in compareLegend" :key="item.color">
+              <span class="legend-dot" :style="{ background: item.color }"></span>
+              <span class="legend-text">{{ item.label }}</span>
+            </div>
+          </div>
+
+          <div class="legend-panel legend-right">
+            <div class="legend-title">站点类型</div>
+            <div class="legend-item" v-for="item in typeLegend" :key="item.label">
+              <span
+                class="legend-marker"
+                :class="item.shape"
+                :style="{ background: item.color }"
+              ></span>
+              <span class="legend-text">{{ item.label }}</span>
+            </div>
+          </div>
+
+          <div class="coord-display">
+            经度: {{ coordDisplay.lng }} 纬度: {{ coordDisplay.lat }}
+          </div>
+
+          <div v-if="tooltipData.visible" class="map-tooltip" :style="tooltipStyle">
+            <div class="tooltip-title">{{ tooltipData.stnm }}</div>
+            <div class="tooltip-row">站码:<b>{{ tooltipData.stcd }}</b></div>
+            <div class="tooltip-row">共享单位:{{ tooltipData.unit }}</div>
+            <div class="tooltip-row">监测时间:{{ tooltipData.loading ? '加载中...' : tooltipData.tm }}</div>
+            <template v-if="!tooltipData.loading && tooltipData.values.length">
+              <div class="tooltip-row" v-for="v in tooltipData.values" :key="v.label">
+                {{ v.label }}:<b>{{ v.value }}</b> {{ v.unit }}
+              </div>
+            </template>
+            <div v-else-if="!tooltipData.loading" class="tooltip-row tooltip-empty">暂无监测数据</div>
+          </div>
+        </div>
+      </el-tab-pane>
+
+      <el-tab-pane label="开发利用情况" name="utilization">
+        <div class="utilization-placeholder">
+          <el-icon :size="48" color="#c0c4cc"><DataLine /></el-icon>
+          <p>开发利用情况数据展示区域</p>
+          <el-empty description="暂无开发利用数据" />
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup name="GisModule">
+import { ref, reactive, onMounted, onUnmounted, nextTick, watch } from 'vue'
+import { Map as OlMap, View } from 'ol'
+import { XYZ, Vector as VectorSource } from 'ol/source'
+import TileLayer from 'ol/layer/Tile'
+import VectorLayer from 'ol/layer/Vector'
+import { fromLonLat, toLonLat } from 'ol/proj'
+import { Feature } from 'ol'
+import { Point } from 'ol/geom'
+import { Style, Fill, Stroke, Icon, Circle as CircleStyle } from 'ol/style'
+import GeoJSON from 'ol/format/GeoJSON'
+import 'ol/ol.css'
+import { DataLine } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { xajfqGeoJson } from '@/assets/mapJSON/xajfq_geojson'
+import { listMapStations, getLatestData } from '@/api/xajgl/station'
+
+const props = defineProps({
+  active: { type: Boolean, default: false }
+})
+
+const emit = defineEmits(['open-station-dialog'])
+
+const activeTab = ref('situation')
+const mapContainer = ref(null)
+
+const stationColorMap = {
+  DRP: '#17c2c7',
+  ZZ: '#1c97e7',
+  DYP: '#e6a23c',
+  SK: '#e6a23c'
+}
+
+const compareLegend = [
+  { color: '#f56c6c', label: '比多年平均偏少50%' },
+  { color: '#e6a23c', label: '比多年平均偏少20%' },
+  { color: '#909399', label: '与多年平均接近' },
+  { color: '#67c23a', label: '比多年平均偏多20%' },
+  { color: '#1c97e7', label: '比多年平均偏多50%' }
+]
+
+const typeLegend = [
+  { label: '重要工程', color: '#e6a23c', shape: 'triangle' },
+  { label: '水文站', color: '#1c97e7', shape: 'circle' },
+  { label: '雨量站', color: '#17c2c7', shape: 'circle' },
+  { label: '蒸发站', color: '#e6a23c', shape: 'circle' }
+]
+
+let olMap = null
+let areaLayer = null
+let stationLayer = null
+let resizeObserver = null
+let currentHoverStcd = null
+
+const coordDisplay = reactive({ lng: '119.0500', lat: '29.5000' })
+
+const tooltipData = reactive({
+  visible: false,
+  stnm: '',
+  stcd: '',
+  unit: '-',
+  tm: '',
+  values: [],
+  loading: false
+})
+const tooltipStyle = ref({})
+
+const latestDataCache = {}
+
+function createStationStyle(tp) {
+  const color = stationColorMap[tp] || '#1c97e7'
+  if (tp === 'SK') {
+    const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><polygon points="12,3 22,21 2,21" fill="${color}" stroke="#fff" stroke-width="1.5"/></svg>`
+    const src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg)))
+    return new Style({
+      image: new Icon({ src, scale: 1.2, anchor: [0.5, 0.5] })
+    })
+  }
+  return new Style({
+    image: new CircleStyle({
+      radius: 6,
+      fill: new Fill({ color }),
+      stroke: new Stroke({ color: '#fff', width: 1.5 })
+    })
+  })
+}
+
+function initMap() {
+  if (!mapContainer.value) return
+
+  olMap = new OlMap({
+    target: mapContainer.value,
+    view: new View({
+      center: fromLonLat([119.05, 29.5]),
+      zoom: 9,
+      minZoom: 8,
+      maxZoom: 18
+    }),
+    layers: [
+      new TileLayer({
+        source: new XYZ({
+          url: 'https://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=5c5a468d333dbb827f134fb64818aa65'
+        })
+      }),
+      new TileLayer({
+        source: new XYZ({
+          url: 'https://t{0-7}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=5c5a468d333dbb827f134fb64818aa65'
+        })
+      })
+    ]
+  })
+
+  areaLayer = new VectorLayer({ source: new VectorSource() })
+  stationLayer = new VectorLayer({ source: new VectorSource() })
+  olMap.addLayer(areaLayer)
+  olMap.addLayer(stationLayer)
+
+  loadAreaGeoJson()
+  loadStations()
+
+  olMap.on('click', handleMapClick)
+  olMap.on('pointermove', handlePointerMove)
+}
+
+function loadAreaGeoJson() {
+  const source = areaLayer.getSource()
+  try {
+    const format = new GeoJSON()
+    const features = format.readFeatures(xajfqGeoJson, {
+      dataProjection: 'EPSG:4490',
+      featureProjection: 'EPSG:3857'
+    })
+    features.forEach(f => {
+      f.setStyle(new Style({
+        fill: new Fill({ color: 'rgba(28, 151, 231, 0.12)' }),
+        stroke: new Stroke({ color: 'rgba(28, 151, 231, 0.7)', width: 2 })
+      }))
+    })
+    source.addFeatures(features)
+  } catch (e) {
+    console.error('加载子流域GeoJSON失败', e)
+  }
+}
+
+async function loadStations() {
+  try {
+    const res = await listMapStations()
+    if (res.code === 200) {
+      const rows = (res.rows || []).filter(s =>
+        ['DRP', 'SK', 'ZZ', 'DYP'].includes(s.tp) && s.lgtd && s.lttd
+      )
+      renderStations(rows)
+    }
+  } catch (e) {
+    ElMessage.error('加载站点失败')
+  }
+}
+
+function renderStations(stations) {
+  const source = stationLayer.getSource()
+  stations.forEach(station => {
+    const coord = fromLonLat([Number(station.lgtd), Number(station.lttd)])
+    const feature = new Feature({
+      geometry: new Point(coord),
+      station: station
+    })
+    feature.setStyle(createStationStyle(station.tp))
+    source.addFeature(feature)
+  })
+}
+
+async function getLatestDataWithCache(stcd) {
+  if (latestDataCache[stcd]) return latestDataCache[stcd]
+  try {
+    const res = await getLatestData(stcd)
+    const data = res.data && res.data.length > 0 ? res.data[0] : null
+    latestDataCache[stcd] = data
+    return data
+  } catch (e) {
+    return null
+  }
+}
+
+function buildLatestValues(tp, data) {
+  const values = []
+  if (tp === 'DRP') {
+    values.push({ label: '降雨量', value: data.drp, unit: 'mm' })
+  } else if (tp === 'ZZ') {
+    values.push({ label: '水位', value: data.z, unit: 'm' })
+    values.push({ label: '流量', value: data.q, unit: 'm³/s' })
+  } else if (tp === 'DYP') {
+    values.push({ label: '蒸发量', value: data.dyp, unit: 'mm' })
+  } else if (tp === 'SK') {
+    values.push({ label: '水位', value: data.z, unit: 'm' })
+    values.push({ label: '下泄水量', value: data.ww, unit: '万m³' })
+  }
+  return values.filter(v => v.value != null && v.value !== '')
+}
+
+function handleMapClick(event) {
+  const feature = olMap.forEachFeatureAtPixel(event.pixel, f => f, {
+    layerFilter: l => l === stationLayer
+  })
+  if (feature) {
+    const station = feature.get('station')
+    if (station) emit('open-station-dialog', station)
+  }
+}
+
+function handlePointerMove(event) {
+  const coord = toLonLat(event.coordinate)
+  coordDisplay.lng = coord[0].toFixed(4)
+  coordDisplay.lat = coord[1].toFixed(4)
+
+  const feature = olMap.forEachFeatureAtPixel(event.pixel, f => f, {
+    layerFilter: l => l === stationLayer
+  })
+  if (feature) {
+    const station = feature.get('station')
+    if (station) {
+      tooltipStyle.value = {
+        left: event.pixel[0] + 14 + 'px',
+        top: event.pixel[1] + 14 + 'px'
+      }
+      if (currentHoverStcd !== station.stcd) {
+        currentHoverStcd = station.stcd
+        tooltipData.stnm = station.stnm
+        tooltipData.stcd = station.stcd
+        tooltipData.unit = station.unit || '-'
+        tooltipData.tm = ''
+        tooltipData.values = []
+        tooltipData.loading = true
+        tooltipData.visible = true
+        loadTooltipData(station)
+      } else {
+        tooltipData.visible = true
+      }
+      olMap.getTarget().style.cursor = 'pointer'
+    }
+  } else {
+    currentHoverStcd = null
+    tooltipData.visible = false
+    olMap.getTarget().style.cursor = ''
+  }
+}
+
+async function loadTooltipData(station) {
+  const data = await getLatestDataWithCache(station.stcd)
+  if (currentHoverStcd !== station.stcd) return
+  if (data) {
+    tooltipData.tm = data.tm || '-'
+    tooltipData.values = buildLatestValues(station.tp, data)
+  } else {
+    tooltipData.tm = '暂无数据'
+    tooltipData.values = []
+  }
+  tooltipData.loading = false
+}
+
+onMounted(() => {
+  nextTick(() => {
+    if (mapContainer.value) initMap()
+  })
+  nextTick(() => {
+    if (mapContainer.value) {
+      resizeObserver = new ResizeObserver(() => {
+        if (olMap) olMap.updateSize()
+      })
+      resizeObserver.observe(mapContainer.value)
+    }
+  })
+})
+
+onUnmounted(() => {
+  if (olMap) {
+    olMap.setTarget(undefined)
+    olMap = null
+  }
+  if (resizeObserver) {
+    resizeObserver.disconnect()
+    resizeObserver = null
+  }
+})
+
+watch(() => props.active, (val) => {
+  if (val) {
+    nextTick(() => { if (olMap) olMap.updateSize() })
+  }
+})
+
+watch(activeTab, (val) => {
+  if (val === 'situation') {
+    nextTick(() => { if (olMap) olMap.updateSize() })
+  }
+})
+</script>
+
+<style scoped>
+.gis-module {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  padding: 16px;
+  overflow: hidden;
+}
+
+.xaj-tabs {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.xaj-tabs :deep(.el-tabs__content) {
+  flex: 1;
+  overflow: hidden;
+}
+
+.xaj-tabs :deep(.el-tab-pane) {
+  height: 100%;
+}
+
+.xaj-tabs :deep(.el-tabs__item.is-active) {
+  color: #1c97e7;
+}
+
+.xaj-tabs :deep(.el-tabs__active-bar) {
+  background-color: #1c97e7;
+}
+
+.map-wrapper {
+  position: relative;
+  height: 100%;
+  border-radius: 8px;
+  overflow: hidden;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
+}
+
+.map-container {
+  width: 100%;
+  height: 100%;
+  min-height: 500px;
+}
+
+.stats-panel {
+  position: absolute;
+  top: 16px;
+  right: 16px;
+  background: rgba(255, 255, 255, 0.98);
+  border-radius: 8px;
+  padding: 16px 20px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
+  width: 340px;
+  z-index: 100;
+  backdrop-filter: blur(8px);
+}
+
+.panel-title {
+  font-size: 15px;
+  font-weight: 600;
+  color: #1c97e7;
+  margin-bottom: 14px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #ebeef5;
+  text-align: center;
+}
+
+.stat-item {
+  margin-bottom: 16px;
+  padding: 10px 0;
+  border-bottom: 1px dashed #ebeef5;
+}
+
+.stat-item:last-child {
+  margin-bottom: 0;
+  border-bottom: none;
+}
+
+.stat-label {
+  font-size: 13px;
+  color: #303133;
+  margin-bottom: 8px;
+  font-weight: 500;
+}
+
+.stat-value-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 10px;
+  font-size: 12px;
+}
+
+.stat-value {
+  color: #606266;
+}
+
+.stat-value b {
+  color: #1c97e7;
+  font-size: 16px;
+  font-weight: 600;
+  margin-left: 2px;
+}
+
+.stat-compare {
+  color: #67c23a;
+  font-size: 13px;
+  font-weight: 500;
+}
+
+.stat-compare.less {
+  color: #f56c6c;
+}
+
+.stat-compare.more {
+  color: #67c23a;
+}
+
+.legend-panel {
+  position: absolute;
+  bottom: 16px;
+  background: rgba(255, 255, 255, 0.95);
+  border-radius: 8px;
+  padding: 12px 16px;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
+  z-index: 100;
+}
+
+.legend-left {
+  left: 16px;
+}
+
+.legend-right {
+  right: 16px;
+}
+
+.legend-panel .legend-title {
+  font-size: 13px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 8px;
+  padding-bottom: 4px;
+  border-bottom: 1px solid #ebeef5;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 5px;
+  font-size: 12px;
+  color: #606266;
+}
+
+.legend-dot {
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  flex-shrink: 0;
+}
+
+.legend-marker {
+  width: 12px;
+  height: 12px;
+  flex-shrink: 0;
+}
+
+.legend-marker.triangle {
+  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
+}
+
+.legend-marker.circle {
+  border-radius: 50%;
+}
+
+.coord-display {
+  position: absolute;
+  bottom: 8px;
+  right: 50%;
+  transform: translateX(50%);
+  background: rgba(0, 0, 0, 0.5);
+  color: #fff;
+  font-size: 12px;
+  padding: 4px 12px;
+  border-radius: 4px;
+  z-index: 100;
+  pointer-events: none;
+}
+
+.map-tooltip {
+  position: absolute;
+  background: rgba(0, 0, 0, 0.82);
+  color: #fff;
+  padding: 10px 14px;
+  border-radius: 6px;
+  font-size: 12px;
+  pointer-events: none;
+  z-index: 150;
+  white-space: nowrap;
+  min-width: 180px;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
+}
+
+.map-tooltip .tooltip-title {
+  font-size: 13px;
+  font-weight: 600;
+  margin-bottom: 6px;
+  padding-bottom: 6px;
+  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
+  color: #1c97e7;
+}
+
+.map-tooltip .tooltip-row {
+  line-height: 1.8;
+  color: #e8e8e8;
+}
+
+.map-tooltip .tooltip-row b {
+  color: #fff;
+  margin: 0 2px;
+}
+
+.map-tooltip .tooltip-empty {
+  color: #c2c2c2;
+  font-style: italic;
+}
+
+.utilization-placeholder {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  min-height: 400px;
+  background: #fff;
+  border-radius: 8px;
+}
+
+.utilization-placeholder p {
+  color: #909399;
+  margin: 12px 0;
+}
+
+@media (max-width: 768px) {
+  .stats-panel {
+    width: 260px;
+  }
+  .legend-panel {
+    flex-direction: column;
+    gap: 10px;
+  }
+}
+</style>

+ 1289 - 0
gw-ui/src/views/front/xaj/QueryModule.vue

@@ -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>

+ 94 - 0
gw-ui/src/views/front/xaj/ShareModule.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="share-module">
+    <div class="share-container">
+      <div class="share-header">
+        <h3>共享目录 - 数据共享单位信息</h3>
+      </div>
+      <div class="unit-list">
+        <el-table :data="unitList" stripe border style="width: 100%">
+          <el-table-column type="index" label="序号" width="60" align="center" />
+          <el-table-column prop="unitName" label="单位名称" min-width="200" show-overflow-tooltip />
+          <el-table-column prop="dataFreq" label="共享频率" width="150" align="center">
+            <template #default="{ row }">
+              <el-tag type="success">及时动态更新</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="note" label="备注说明" min-width="300" show-overflow-tooltip />
+          <el-table-column prop="linkman" label="联系人" width="100" align="center" />
+          <el-table-column prop="tele" label="联系电话" width="130" align="center" />
+        </el-table>
+        <el-empty v-if="unitList.length === 0" description="暂无共享单位信息" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup name="ShareModule">
+import { ref, onMounted } from 'vue'
+import { listXajUnitFront } from '@/api/xajgl/unit'
+
+const unitList = ref([])
+
+onMounted(() => {
+  listXajUnitFront().then(res => {
+    unitList.value = res.data || []
+  })
+})
+</script>
+
+<style scoped>
+.share-module {
+  flex: 1;
+  padding: 16px;
+  overflow: auto;
+}
+
+.share-container {
+  background: #fff;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+}
+
+.share-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.share-header h3 {
+  margin: 0;
+  font-size: 16px;
+  color: #303133;
+}
+
+.unit-list {
+  margin-top: 16px;
+}
+
+.unit-list .el-table {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.unit-list .el-table th {
+  background-color: #f5f7fa;
+  color: #606266;
+  font-weight: 600;
+}
+
+.unit-list .el-table--striped .el-table__body tr.el-table__row--striped td {
+  background-color: #fafafa;
+}
+
+.unit-list .el-table td {
+  padding: 12px 0;
+}
+
+.unit-list .el-tag {
+  font-size: 12px;
+}
+</style>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä