Browse Source

Merge branch 'ding'

# Conflicts:
#	components.d.ts
#	src/views/User/HmOutFlux/irrigationWater/irriWaterInputFlux.vue
yangtaodemon 1 day ago
parent
commit
113818a838

+ 1 - 1
auto-imports.d.ts

@@ -68,6 +68,6 @@ declare global {
 // for type re-export
 declare global {
   // @ts-ignore
-  export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
+  export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
   import('vue')
 }

+ 1 - 3
components.d.ts

@@ -2,6 +2,7 @@
 // @ts-nocheck
 // Generated by unplugin-vue-components
 // Read more: https://github.com/vuejs/core/pull/3399
+// biome-ignore lint: disable
 export {}
 
 /* prettier-ignore */
@@ -15,8 +16,6 @@ declare module 'vue' {
     ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
-    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCol: typeof import('element-plus/es')['ElCol']
     ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
@@ -32,7 +31,6 @@ declare module 'vue' {
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
-    ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']

+ 1 - 1
package-lock.json

@@ -6293,7 +6293,7 @@
     },
     "node_modules/coordtransform": {
       "version": "2.1.2",
-      "resolved": "https://registry.npmmirror.com/coordtransform/-/coordtransform-2.1.2.tgz",
+      "resolved": "https://registry.npmjs.org/coordtransform/-/coordtransform-2.1.2.tgz",
       "integrity": "sha512-0xLJApBlrUP+clyLJWIaqg4GXE5JTbAJb5d/CDMqebIksAMMze8eAyO6YfHEIxWJ+c42mXoMHBzWTeUrG7RFhw==",
       "license": "MIT"
     },

+ 418 - 51
src/views/User/HmOutFlux/agriInput/prodInputFlux.vue

@@ -1,72 +1,73 @@
 <template>
   <div class="fertilizer-input-form">
-    <el-card shadow="always" class="form-card">
+    <!-- 输入表单部分 -->
+    <el-card v-if="showInputForm" shadow="always" class="form-card">
       <div class="card-content">
         <div class="input-section">
           <el-form label-width="250px" label-position="top">
             <div class="form-section">
-              <div class="input-group">
+                      <div class="input-group">
                 <el-form-item label="氮肥镉含量平均值 (mg/kg)" class="form-item">
-                  <el-input v-model="nitrogenCdContent" placeholder="0.05"></el-input>
+                  <el-input v-model="formData.f3_nitrogen_cd_content" placeholder="0.05"></el-input>
                 </el-form-item>
                 <el-form-item label="氮肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="nitrogenUsage" placeholder="0.05"></el-input>
+                  <el-input v-model="formData.nf_nitrogen_usage" placeholder="0.05"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="磷肥镉含量平均值 (mg/kg)" class="form-item">
-                  <el-input v-model="phosphorusCdContent" placeholder="0.158"></el-input>
+                  <el-input v-model="formData.f4_phosphorus_cd_content" placeholder="0.158"></el-input>
                 </el-form-item>
                 <el-form-item label="磷肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="phosphorusUsage" placeholder="0.158"></el-input>
+                  <el-input v-model="formData.pf_phosphorus_usage" placeholder="0.158"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="钾肥镉含量平均值 (mg/kg)" class="form-item">
-                  <el-input v-model="potassiumCdContent" placeholder="0.06"></el-input>
+                  <el-input v-model="formData.f5_potassium_cd_content" placeholder="0.06"></el-input>
                 </el-form-item>
                 <el-form-item label="钾肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="potassiumUsage" placeholder="0.06"></el-input>
+                  <el-input v-model="formData.kf_potassium_usage" placeholder="0.06"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="复合肥镉含量平均值 (mg/kg)" class="form-item">
-                  <el-input v-model="compoundFertilizerCdContent" placeholder="0.065"></el-input>
+                  <el-input v-model="formData.f6_compound_cd_content" placeholder="0.065"></el-input>
                 </el-form-item>
                 <el-form-item label="复合肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="compoundFertilizerUsage" placeholder="0.065"></el-input>
+                  <el-input v-model="formData.cf_compound_usage" placeholder="0.065"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="有机肥镉含量平均值 (mg/kg)" class="form-item">
-                  <el-input v-model="organicFertilizerCdContent" placeholder="0.6"></el-input>
+                  <el-input v-model="formData.f7_organic_cd_content" placeholder="0.6"></el-input>
                 </el-form-item>
                 <el-form-item label="有机肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="organicFertilizerUsage" placeholder="0.6"></el-input>
+                  <el-input v-model="formData.of_organic_usage" placeholder="0.6"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="农药镉含量 (mg/kg)" class="form-item">
-                  <el-input v-model="pesticideCdContent" placeholder="0.25"></el-input>
+                  <el-input v-model="formData.f8_pesticide_cd_content" placeholder="0.25"></el-input>
                 </el-form-item>
                 <el-form-item label="农药单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="pesticideUsage" placeholder="0.25"></el-input>
+                  <el-input v-model="formData.p_pesticide_usage" placeholder="0.25"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="农家肥镉含量 (mg/kg)" class="form-item">
-                  <el-input v-model="farmYardManureCdContent" placeholder="0.35"></el-input>
+                  <el-input v-model="formData.f9_farmyard_cd_content" placeholder="0.35"></el-input>
                 </el-form-item>
                 <el-form-item label="农家肥单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="farmYardManureUsage" placeholder="0.35"></el-input>
+                  <el-input v-model="formData.ff_farmyard_usage" placeholder="0.35"></el-input>
                 </el-form-item>
               </div>
               <div class="input-group">
                 <el-form-item label="农膜镉含量 (mg/kg)" class="form-item">
-                  <el-input v-model="agriFilmCdContent" placeholder="0.25"></el-input>
+                  <el-input v-model="formData.f10_film_cd_content" placeholder="0.25"></el-input>
                 </el-form-item>
                 <el-form-item label="农膜(存留)单位面积使用量 (t/ha/a)" class="form-item">
-                  <el-input v-model="agriFilmResidueUsage" placeholder="0.6"></el-input>
+                  <el-input v-model="formData.af_film_usage" placeholder="0.6"></el-input>
                 </el-form-item>
               </div>
             </div>
@@ -74,50 +75,348 @@
         </div>
         
         <div class="button-section">
-          <!-- 按钮区域背景图 -->
           <div class="button-bg"></div>
-          <!-- 底部半透明层 -->
           <div class="bottom-overlay"></div>
-          <el-button class="calculate-btn">
+          <el-button 
+            class="calculate-btn" 
+            @click="calculateAll"
+            :loading="loading"
+          >
             <span class="btn-text">农产品输入通量计算</span>
           </el-button>
         </div>
       </div>
     </el-card>
+    
+    <!-- 结果页面部分 -->
+    <div v-if="!showInputForm" class="results-page">
+      <!-- 返回按钮 -->
+      <el-button 
+        type="primary" 
+        class="back-button"
+        @click="showInputForm = true"
+      >
+        返回计算
+      </el-button>
+      <!-- 结果页面标题 -->
+      <h2 class="results-title">农业输入通量计算结果</h2>
+      
+      <!-- 自定义数据计算结果卡片 -->
+      <el-card class="result-card" v-if="customResult.success">
+        <h3>当前地区农业投入Cd通量计算结果</h3>
+        <p>总通量: {{ customResult.data.total_cd_flux }} g/ha/a</p>
+        <el-table :data="customResultDetails" border>
+          <el-table-column prop="type" label="投入类型"></el-table-column>
+          <el-table-column prop="flux" label="Cd通量(g/ha/a)"></el-table-column>
+        </el-table>
+        <div class="chart-container">
+            <div ref="customPieChart" style="width: 100%; height: 400px;"></div>
+          </div>
+      </el-card>
+      
+      <!-- 所有地区统计结果卡片 -->
+      <el-card class="result-card" v-if="allAreasResult.success">
+        <h3>所有地区农业投入Cd通量统计结果</h3>
+        <p>平均通量: {{ allAreasResult.data.summary.average_cd_flux }} g/ha/a</p>
+        <p>最高通量: {{ allAreasResult.data.summary.max_cd_flux.total_cd_flux }} g/ha/a ({{ allAreasResult.data.summary.max_cd_flux.area }})</p>
+        <p>最低通量: {{ allAreasResult.data.summary.min_cd_flux.total_cd_flux }} g/ha/a ({{ allAreasResult.data.summary.min_cd_flux.area }})</p>
+        
+        <el-table :data="allAreasList" border>
+          <el-table-column prop="area" label="地区"></el-table-column>
+          <el-table-column prop="total_cd_flux" label="Cd通量(g/ha/a)"></el-table-column>
+        </el-table>
+        <div class="chart-container">
+            <div ref="allAreasPieChart" style="width: 100%; height: 400px;"></div>
+          </div>
+      </el-card>
+    </div>
   </div>
 </template>
 
 <script>
+import axios from 'axios';
+import * as echarts from 'echarts'; 
+
 export default {
   data() {
     return {
-      nitrogenCdContent: '0.05',
-      nitrogenUsage: '0.05',
-      phosphorusCdContent: '0.158',
-      phosphorusUsage: '0.158',
-      potassiumCdContent: '0.06',
-      potassiumUsage: '0.06',
-      compoundFertilizerCdContent: '0.065',
-      compoundFertilizerUsage: '0.065',
-      organicFertilizerCdContent: '0.6',
-      organicFertilizerUsage: '0.6',
-      pesticideCdContent: '0.25',
-      pesticideUsage: '0.25',
-      farmYardManureCdContent: '0.35',
-      farmYardManureUsage: '0.35',
-      agriFilmCdContent: '0.25',
-      agriFilmResidueUsage: '0.6'
+      // 控制显示输入表单或结果页面
+      showInputForm: true,
+      
+      // 表单数据 - 使用API定义的字段名
+      formData: {
+        f3_nitrogen_cd_content: "0.12",
+        f4_phosphorus_cd_content: "0.85",
+        f5_potassium_cd_content: "0.05",
+        f6_compound_cd_content: "0.45",
+        f7_organic_cd_content: "0.22",
+        f8_pesticide_cd_content: "0.08",
+        f9_farmyard_cd_content: "0.15",
+        f10_film_cd_content: "0.03",
+        nf_nitrogen_usage: "0.25",
+        pf_phosphorus_usage: "0.15",
+        kf_potassium_usage: "0.12",
+        cf_compound_usage: "0.30",
+        of_organic_usage: "2.50",
+        p_pesticide_usage: "0.02",
+        ff_farmyard_usage: "1.80",
+        af_film_usage: "0.05",
+        description: "自定义数据计算结果"
+      },
+      
+      // 结果数据
+      loading: false,
+      customResult: {},
+      allAreasResult: {},
+
+      // ECharts实例
+      customPieChart: null,
+      allAreasPieChart: null
     };
+  },
+  computed: {
+    // 将自定义数据结果详情转换为表格数据
+    customResultDetails() {
+      if (!this.customResult.data || !this.customResult.data.details) return [];
+      return Object.entries(this.customResult.data.details).map(([type, flux]) => ({
+        type: this.getTypeName(type),
+        flux: flux
+      }));
+    },
+    
+    // 获取所有地区列表
+    allAreasList() {
+      if (!this.allAreasResult.data || !this.allAreasResult.data.results) return [];
+      return this.allAreasResult.data.results.map(area => ({
+        area: area.area,
+        total_cd_flux: area.total_cd_flux
+      }));
+    },
+    // 获取当前地区饼图数据
+    customPieData() {
+      if (!this.customResult.data || !this.customResult.data.details) return [];
+      return Object.entries(this.customResult.data.details).map(([type, value]) => ({
+        name: this.getTypeName(type),
+        value: value
+      }));
+    },
+    
+    // 获取所有地区饼图数据(取前8个地区)
+    allAreasPieData() {
+      if (!this.allAreasList || this.allAreasList.length === 0) return [];
+      
+      // 复制并排序
+      const sortedAreas = [...this.allAreasList].sort((a, b) => b.total_cd_flux - a.total_cd_flux);
+      
+      // 取前8个地区
+      return sortedAreas.slice(0, 8).map(area => ({
+        name: area.area,
+        value: area.total_cd_flux
+      }));
+    }
+  },
+  methods: {
+    // 计算所有数据
+    async calculateAll() {
+      try {
+        this.loading = true;
+        
+        // 准备自定义数据请求体
+        const requestBody = {
+          ...this.formData,
+          // 将字符串值转换为数字
+          f3_nitrogen_cd_content: parseFloat(this.formData.f3_nitrogen_cd_content),
+          f4_phosphorus_cd_content: parseFloat(this.formData.f4_phosphorus_cd_content),
+          f5_potassium_cd_content: parseFloat(this.formData.f5_potassium_cd_content),
+          f6_compound_cd_content: parseFloat(this.formData.f6_compound_cd_content),
+          f7_organic_cd_content: parseFloat(this.formData.f7_organic_cd_content),
+          f8_pesticide_cd_content: parseFloat(this.formData.f8_pesticide_cd_content),
+          f9_farmyard_cd_content: parseFloat(this.formData.f9_farmyard_cd_content),
+          f10_film_cd_content: parseFloat(this.formData.f10_film_cd_content),
+          nf_nitrogen_usage: parseFloat(this.formData.nf_nitrogen_usage),
+          pf_phosphorus_usage: parseFloat(this.formData.pf_phosphorus_usage),
+          kf_potassium_usage: parseFloat(this.formData.kf_potassium_usage),
+          cf_compound_usage: parseFloat(this.formData.cf_compound_usage),
+          of_organic_usage: parseFloat(this.formData.of_organic_usage),
+          p_pesticide_usage: parseFloat(this.formData.p_pesticide_usage),
+          ff_farmyard_usage: parseFloat(this.formData.ff_farmyard_usage),
+          af_film_usage: parseFloat(this.formData.af_film_usage)
+        };
+        
+        // 同时调用两个API
+        const [customResponse, allAreasResponse] = await Promise.all([
+          axios.post(
+            'http://localhost:8000/api/agricultural-input/calculate-with-custom-data', 
+            requestBody
+          ),
+          axios.get(
+            'http://localhost:8000/api/agricultural-input/calculate-all-areas'
+          )
+        ]);
+        
+        // 处理自定义数据结果
+        this.customResult = customResponse.data;
+        if (!this.customResult.success) {
+          this.$message.error(this.customResult.message || '自定义数据计算失败');
+        }
+        
+        // 处理所有地区结果
+        this.allAreasResult = allAreasResponse.data;
+        if (!this.allAreasResult.success) {
+          this.$message.error(this.allAreasResult.message || '计算所有地区失败');
+        }
+        
+        // 切换到结果页面
+        this.showInputForm = false;
+
+         // 等待DOM更新
+        this.$nextTick(() => {
+          this.initCharts();
+        });
+      } catch (error) {
+        console.error('API调用错误:', error);
+        this.$message.error('计算失败,请检查网络连接');
+      } finally {
+        this.loading = false;
+      }
+    },
+    
+    // 获取类型的中文名称
+    getTypeName(type) {
+      const typeNames = {
+        'nitrogen_fertilizer': '氮肥',
+        'phosphorus_fertilizer': '磷肥',
+        'potassium_fertilizer': '钾肥',
+        'compound_fertilizer': '复合肥',
+        'organic_fertilizer': '有机肥',
+        'pesticide': '农药',
+        'farmyard_manure': '农家肥',
+        'agricultural_film': '农膜'
+      };
+      return typeNames[type] || type;
+    },
+     // 初始化图表
+    initCharts() {
+      // 销毁已有实例
+      if (this.customPieChart) {
+        this.customPieChart.dispose();
+      }
+      if (this.allAreasPieChart) {
+        this.allAreasPieChart.dispose();
+      }
+      
+      // 创建新的图表实例
+      this.customPieChart = echarts.init(this.$refs.customPieChart);
+      this.allAreasPieChart = echarts.init(this.$refs.allAreasPieChart);
+      
+      // 设置图表选项
+      this.customPieChart.setOption(this.getPieChartOption('当前地区各项投入通量占比', this.customPieData));
+      this.allAreasPieChart.setOption(this.getPieChartOption('各地区通量占比', this.allAreasPieData));
+      
+      // 响应窗口大小变化
+      window.addEventListener('resize', this.onResize);
+    },
+    
+    // 获取饼图配置
+    getPieChartOption(title, data) {
+      return {
+        title: {
+          text: title,
+          left: 'center',
+          textStyle: {
+            fontSize: 16,
+            fontWeight: 'bold'
+          }
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: '{a} <br/>{b}: {c} g/ha/a ({d}%)'
+        },
+        legend: {
+          orient: 'vertical',
+          right: 10,
+          top: 'center',
+          data: data.map(item => item.name)
+        },
+        series: [
+          {
+            name: title,
+            type: 'pie',
+            radius: ['40%', '70%'],
+            center: ['40%', '50%'],
+            avoidLabelOverlap: false,
+            itemStyle: {
+              borderRadius: 10,
+              borderColor: '#fff',
+              borderWidth: 2
+            },
+            label: {
+              show: false,
+              position: 'center'
+            },
+            emphasis: {
+              label: {
+                show: true,
+                fontSize: '16',
+                fontWeight: 'bold',
+                formatter: '{b}\n{c} g/ha/a\n{d}%'
+              }
+            },
+            labelLine: {
+              show: false
+            },
+            data: data
+          }
+        ]
+      };
+    },
+    
+    // 响应窗口大小变化
+    onResize() {
+      if (this.customPieChart) {
+        this.customPieChart.resize();
+      }
+      if (this.allAreasPieChart) {
+        this.allAreasPieChart.resize();
+      }
+    }
+  },
+  watch: {
+    // 当结果数据变化时更新图表
+    customPieData() {
+      if (this.customPieChart) {
+        this.customPieChart.setOption(this.getPieChartOption('当前地区各项投入通量占比', this.customPieData));
+      }
+    },
+    allAreasPieData() {
+      if (this.allAreasPieChart) {
+        this.allAreasPieChart.setOption(this.getPieChartOption('各地区通量占比', this.allAreasPieData));
+      }
+    }
+  },
+  beforeUnmount() {
+    // 组件销毁前移除事件监听
+    window.removeEventListener('resize', this.onResize);
+    
+    // 销毁图表实例
+    if (this.customPieChart) {
+      this.customPieChart.dispose();
+    }
+    if (this.allAreasPieChart) {
+      this.allAreasPieChart.dispose();
+    }
   }
 };
 </script>
 
 <style scoped>
+/* 原有样式保持不变 */
 .fertilizer-input-form {
   padding: 20px;
   display: flex;
-  justify-content: center;
-  background-color: rgba(255, 255, 255, 0.8); /* 半透明背景 */
+  flex-direction: column;
+  align-items: center;
+  background-color: rgba(255, 255, 255, 0.8);
 }
 
 .form-card {
@@ -152,20 +451,17 @@ export default {
   overflow: hidden;
 }
 
-/* 按钮区域背景图 - 使用本地图片 */
 .button-bg {
   position: absolute;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
-  /* 请替换为您的本地图片路径 */
   background: url('@/assets/images/fertilizer-bg.jpg') no-repeat center center;
   background-size: cover;
   z-index: 0;
 }
 
-/* 底部半透明层 */
 .bottom-overlay {
   position: absolute;
   left: 0;
@@ -210,28 +506,23 @@ export default {
   width: 100%;
 }
 
-/* 使用 :deep() 替代已弃用的 >>> */
 :deep(.el-input) .el-input__inner {
   width: 100% !important;
   padding: 12px 0;
   border: none;
   border-radius: 0;
   background: transparent;
-  /* 底部边框效果 */
   border-bottom: 1px solid #dcdfe6;
-  /* 底部阴影效果 */
   box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05);
   transition: all 0.3s ease;
 }
 
 :deep(.el-input) .el-input__inner:focus {
   border-bottom: 2px solid #409EFF;
-  /* 聚焦时底部阴影加强 */
   box-shadow: 0 2px 0 rgba(64, 158, 255, 0.2);
   background: rgba(64, 158, 255, 0.03);
 }
 
-/* 占位符样式 */
 :deep(.el-input) .el-input__inner::placeholder {
   color: #a0a0a0;
   font-style: italic;
@@ -247,11 +538,8 @@ export default {
   font-weight: bold;
   transition: all 0.4s ease;
   position: relative;
-  z-index: 2; /* 确保按钮在覆盖层之上 */
-  
-  /* 渐变背景色 */
+  z-index: 2;
   background: linear-gradient(to right, #8DF9F0, #26B046);
-  /* 按钮整体阴影 */
   box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15),
               0 4px 10px rgba(38, 176, 70, 0.3) inset;
 }
@@ -280,4 +568,83 @@ export default {
   text-align: center;
   line-height: 1.4;
 }
+
+/* 结果页面样式 */
+.results-page {
+  width: 90%;
+  max-width: 1200px;
+  padding: 30px;
+  background: linear-gradient(135deg, #FAFDFF, #FFFAA2);
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.results-title {
+  text-align: center;
+  color: #333;
+  margin-bottom: 30px;
+  font-size: 28px;
+}
+
+/* 结果卡片样式 */
+.result-card {
+  width: 90%;
+  max-width: 1200px;
+  margin: 0 auto;
+  background: linear-gradient(135deg, #FAFDFF, #FFFAA2);
+  border: 1px solid #e6e6e6;
+  border-radius: 12px;
+  overflow: hidden;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+}
+
+.result-card h3 {
+  text-align: center;
+  margin-bottom: 20px;
+  color: #333;
+}
+
+.result-card p {
+  margin: 10px 0;
+  font-size: 16px;
+}
+
+/* 表格样式 */
+.result-table {
+  padding: 20px;
+}
+
+.result-table .el-table {
+  width: 100%;
+  margin-top: 15px;
+  margin-bottom: 20px;
+}
+
+/* 图表容器 */
+.chart-container {
+  margin-top: 20px;
+  border: 1px solid #eee;
+  border-radius: 8px;
+  padding: 10px;
+  background: #f9f9f9;
+}
+
+/* 返回按钮样式 */
+.back-button {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  width: 120px;
+  font-size: 16px;
+  padding: 10px;
+  background: linear-gradient(to right, #8DF9F0, #26B046);
+  color: white;
+  border: none;
+  border-radius: 20px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+
+.back-button:hover {
+  background: linear-gradient(to right, #7de8df, #20a03d);
+}
 </style>

+ 499 - 158
src/views/User/HmOutFlux/irrigationWater/irriWaterInputFlux.vue

@@ -1,149 +1,301 @@
 <template>
-  <div class="compact-container">
-    <el-card shadow="always" class="compact-card">
-      <!-- 紧凑标题区域 -->
-      <div class="compact-title-section">
-        <h2 class="compact-main-title">灌溉水输入通量计算</h2>
-        <p class="compact-sub-title">选择土地类型并输入灌溉参数</p>
-      </div>
-      
-      <!-- 紧凑参数输入区域 -->
-      <div class="compact-input-section">
-        <!-- 水地参数输入 -->
-        <div class="compact-land-section">
-          <el-checkbox v-model="waterLand" class="compact-land-checkbox">
-            <span class="compact-land-label">水地</span>
-          </el-checkbox>
-          <div class="compact-input-group">
-            <div class="compact-input-label">灌溉水用量 (m³)</div>
-            <el-input
-              v-model="irrigationWaterUsage"
-              placeholder="用量"
-              :disabled="!waterLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
-          <div class="compact-input-group">
-            <div class="compact-input-label">有效利用率 (%)</div>
-            <el-input
-              v-model="irrigationEfficiency"
-              placeholder="利用率"
-              :disabled="!waterLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
+  <div class="irrigation-management">
+    <!-- 计算页面 -->
+    <div v-if="showCalculation">
+      <el-card shadow="always" class="gradient-card">
+        <el-radio-group v-model="selectedLandType" style="width: 100%;">
+          <!-- 水地 -->
+          <el-row :gutter="20" style="margin-bottom: 10px; align-items: center;">
+            <el-col :span="6">
+              <div class="radio-container">
+                <el-radio label="water" border>水田</el-radio>
+              </div>
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水用量 (m³/亩/年)</div>
+              <el-input
+                v-model="irrigationWaterUsage"
+                placeholder="请输入灌溉水用量"
+                :disabled="selectedLandType !== 'water'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水有效利用率 (%)</div>
+              <el-input
+                v-model="irrigationEfficiency"
+                placeholder="请输入灌溉水有效利用率"
+                :disabled="selectedLandType !== 'water'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+          </el-row>
+
+          <!-- 水浇地 -->
+          <el-row :gutter="20" style="margin-bottom: 10px; align-items: center;">
+            <el-col :span="6">
+              <div class="radio-container">
+                <el-radio label="irrigated" border>水浇地</el-radio>
+              </div>
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水用量 (m³/亩/年)</div>
+              <el-input
+                v-model="irrigatedWaterUsage"
+                placeholder="请输入灌溉水用量"
+                :disabled="selectedLandType !== 'irrigated'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水有效利用率 (%)</div>
+              <el-input
+                v-model="irrigatedEfficiency"
+                placeholder="请输入灌溉水有效利用率"
+                :disabled="selectedLandType !== 'irrigated'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+          </el-row>
+
+          <!-- 旱地 -->
+          <el-row :gutter="20" style="margin-bottom: 10px; align-items: center;">
+            <el-col :span="6">
+              <div class="radio-container">
+                <el-radio label="dry" border>旱地</el-radio>
+              </div>
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水用量 (m³/亩/年)</div>
+              <el-input
+                v-model="dryWaterUsage"
+                placeholder="请输入灌溉水用量"
+                :disabled="selectedLandType !== 'dry'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+            <el-col :span="9">
+              <div class="input-title">灌溉水有效利用率 (%)</div>
+              <el-input
+                v-model="dryEfficiency"
+                placeholder="请输入灌溉水有效利用率"
+                :disabled="selectedLandType !== 'dry'"
+                style="margin-top: 10px;"
+              />
+            </el-col>
+          </el-row>
+        </el-radio-group>
+
+        <el-row justify="center" style="margin-top: 20px;">
+          <el-button
+            class="calculate-btn"
+            @click="calculateFlux"
+            :loading="loading"
+          >
+            计算灌溉水输入通量
+          </el-button>
+        </el-row>
+      </el-card>
+    </div>
+
+    <!-- 结果页面 -->
+    <div v-if="showResults">
+      <el-card shadow="always" class="results-card">
+        <div class="results-header">
+          <el-button 
+          type="primary" 
+          @click="backToCalculation"
+          class="back-button">
+            返回计算
+          </el-button>
+          <div class="result-title">计算结果</div>
         </div>
-
-        <!-- 水浇地参数输入 -->
-        <div class="compact-land-section">
-          <el-checkbox v-model="irrigatedLand" class="compact-land-checkbox">
-            <span class="compact-land-label">水浇地</span>
-          </el-checkbox>
-          <div class="compact-input-group">
-            <div class="compact-input-label">灌溉水用量 (m³)</div>
-            <el-input
-              v-model="irrigatedWaterUsage"
-              placeholder="用量"
-              :disabled="!irrigatedLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
-          <div class="compact-input-group">
-            <div class="compact-input-label">有效利用率 (%)</div>
-            <el-input
-              v-model="irrigatedEfficiency"
-              placeholder="利用率"
-              :disabled="!irrigatedLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
-        </div>
-
-        <!-- 旱地参数输入 -->
-        <div class="compact-land-section">
-          <el-checkbox v-model="dryLand" class="compact-land-checkbox">
-            <span class="compact-land-label">旱地</span>
-          </el-checkbox>
-          <div class="compact-input-group">
-            <div class="compact-input-label">灌溉水用量 (m³)</div>
-            <el-input
-              v-model="dryWaterUsage"
-              placeholder="用量"
-              :disabled="!dryLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
-          <div class="compact-input-group">
-            <div class="compact-input-label">有效利用率 (%)</div>
-            <el-input
-              v-model="dryEfficiency"
-              placeholder="利用率"
-              :disabled="!dryLand"
-              size="small"
-              class="compact-input"
-            />
-          </div>
+        
+        <div class="results-container">
+          <el-row :gutter="20" style="margin-top: 30px;">
+            <el-col :span="12">
+              <div class="result-subtitle">Cd含量地图</div>
+              <img v-if="mapImageUrl" :src="mapImageUrl" alt="Cd含量地图" class="result-image">
+              <div v-else class="image-placeholder">地图加载中...</div>
+            </el-col>
+            <el-col :span="12">
+              <div class="result-subtitle">Cd含量直方图</div>
+              <img v-if="histogramImageUrl" :src="histogramImageUrl" alt="Cd含量直方图" class="result-image">
+              <div v-else class="image-placeholder">直方图加载中...</div>
+            </el-col>
+          </el-row>
+          
+          <el-row style="margin-top: 30px;">
+            <el-col :span="24">
+              <div class="result-subtitle">统计结果</div>
+              <div class="statistics-container">
+                <!-- 基础统计表格 -->
+                <el-table
+                  v-if="statisticsData"
+                  :data="[statisticsData]"
+                  border
+                  size="small"
+                  style="width: 100%; margin-bottom: 20px;"
+                >
+                  <el-table-column prop="土地类型" label="土地类型" align="center"></el-table-column>
+                  <el-table-column prop="数据更新时间" label="数据更新时间" align="center"></el-table-column>
+                  <el-table-column prop="数据点总数" label="数据点总数" align="center"></el-table-column>
+                  <el-table-column prop="均值" label="均值" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="中位数" label="中位数" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="标准差" label="标准差" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="最小值" label="最小值" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="最大值" label="最大值" align="center" :formatter="formatNumber"></el-table-column>
+                </el-table>
+                
+                <!-- 分位数和形态统计表格 -->
+                <el-table
+                  v-if="statisticsData"
+                  :data="[statisticsData]"
+                  border
+                  size="small"
+                  style="width: 100%; margin-bottom: 20px;"
+                >
+                  <el-table-column prop="25%分位数" label="25%分位数" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="75%分位数" label="75%分位数" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="偏度" label="偏度" align="center" :formatter="formatNumber"></el-table-column>
+                  <el-table-column prop="峰度" label="峰度" align="center" :formatter="formatNumber"></el-table-column>
+                </el-table>
+              </div>
+            </el-col>
+          </el-row>
         </div>
-      </div>
-
-      <!-- 紧凑计算按钮 -->
-      <div class="compact-button-section">
-        <el-button
-          class="compact-calculate-btn"
-          @click="calculateFlux"
-        >
-          <i class="fas fa-calculator"></i> 计算输入通量
-        </el-button>
-      </div>
-
-      <!-- 紧凑计算结果 -->
-      <div v-if="fluxResult !== null" class="compact-result-section">
-        <div class="compact-result-title">计算结果</div>
-        <div class="compact-flux-value">{{ fluxResult.toFixed(2) }} <span class="compact-unit">m³</span></div>
-        <p class="compact-result-description">灌溉水输入通量</p>
-      </div>
-    </el-card>
+      </el-card>
+    </div>
   </div>
 </template>
 
 <script>
 import { ref } from 'vue';
-import { ElCheckbox, ElInput, ElButton, ElMessage, ElCard } from 'element-plus';
+import axios from 'axios';
+import { 
+  ElRadio, 
+  ElRadioGroup, 
+  ElInput, 
+  ElButton, 
+  ElMessage, 
+  ElCard, 
+  ElRow, 
+  ElCol, 
+  ElTable, 
+  ElTableColumn 
+} from 'element-plus';
+
+// 土地类型映射
+const landTypeMap = {
+  water: '水田',
+  irrigated: '水浇地',
+  dry: '旱地'
+};
 
 export default {
   components: {
-    ElCheckbox,
+    ElRadio,
+    ElRadioGroup,
     ElInput,
     ElButton,
     ElMessage,
-    ElCard
+    ElCard,
+    ElRow,
+    ElCol,
+    ElTable,
+    ElTableColumn
   },
   setup() {
-    const waterLand = ref(false);
-    const irrigatedLand = ref(false);
-    const dryLand = ref(false);
-
-    const irrigationWaterUsage = ref('');
-    const irrigationEfficiency = ref('');
+    const selectedLandType = ref('water'); // 默认选择水田
+    
+    // 设置默认值
+    const irrigationWaterUsage = ref('711');
+    const irrigationEfficiency = ref('0.524');
 
-    const irrigatedWaterUsage = ref('');
-    const irrigatedEfficiency = ref('');
+    const irrigatedWaterUsage = ref('427');
+    const irrigatedEfficiency = ref('0.599');
 
-    const dryWaterUsage = ref('');
-    const dryEfficiency = ref('');
+    const dryWaterUsage = ref('200');
+    const dryEfficiency = ref('0.7');
 
     const fluxResult = ref(null);
+    const showCalculation = ref(true); // 显示计算页面
+    const showResults = ref(false); // 显示结果页面
+    const loading = ref(false);
+    
+    // 结果展示数据
+    const mapImageUrl = ref('');
+    const histogramImageUrl = ref('');
+    const statisticsData = ref(null);
+
+    // 格式化数字显示(保留4位小数)
+    const formatNumber = (row, column, cellValue) => {
+      if (typeof cellValue === 'number') {
+        return cellValue.toFixed(4);
+      }
+      return cellValue;
+    };
+
+    // 获取默认地图
+    const fetchDefaultMap = async (landTypeChinese) => {
+      try {
+        const response = await axios.get('http://localhost:8000/api/water/default-map', {
+          params: { land_type: landTypeChinese },
+          responseType: 'blob' // 接收二进制数据
+        });
+        
+        // 创建对象URL
+        return URL.createObjectURL(response.data);
+      } catch (error) {
+        console.error('获取默认地图失败:', error);
+        ElMessage.error('获取地图失败,请重试');
+        return '';
+      }
+    };
 
-    const calculateFlux = () => {
+    // 获取默认直方图
+    const fetchDefaultHistogram = async (landTypeChinese) => {
+      try {
+        const response = await axios.get('http://localhost:8000/api/water/default-histogram', {
+          params: { land_type: landTypeChinese },
+          responseType: 'blob' // 接收二进制数据
+        });
+        
+        // 创建对象URL
+        return URL.createObjectURL(response.data);
+      } catch (error) {
+        console.error('获取默认直方图失败:', error);
+        ElMessage.error('获取直方图失败,请重试');
+        return '';
+      }
+    };
+
+    // 获取统计数据
+    const fetchStatistics = async (landTypeChinese) => {
+      try {
+        const response = await axios.get('http://localhost:8000/api/water/statistics', {
+          params: { land_type: landTypeChinese }
+        });
+        return response.data;
+      } catch (error) {
+        console.error('获取统计数据失败:', error);
+        ElMessage.error('获取统计数据失败,请重试');
+        return null;
+      }
+    };
+
+    // 返回计算页面
+    const backToCalculation = () => {
+      showCalculation.value = true;
+      showResults.value = false;
+    };
+
+    const calculateFlux = async () => {
       let totalFlux = 0;
       let valid = true;
+      let currentLandType = '';
 
-      if (waterLand.value) {
+      if (selectedLandType.value === 'water') {
         if (!irrigationWaterUsage.value || !irrigationEfficiency.value) {
           ElMessage.warning('请输入水地的灌溉水用量和有效利用率');
           valid = false;
@@ -158,12 +310,12 @@ export default {
             ElMessage.error('有效利用率应在0-100%之间');
             valid = false;
           } else {
-            totalFlux += usage * efficiency;
+            totalFlux = usage * efficiency;
+            currentLandType = 'water';
           }
         }
-      }
-
-      if (irrigatedLand.value) {
+      } 
+      else if (selectedLandType.value === 'irrigated') {
         if (!irrigatedWaterUsage.value || !irrigatedEfficiency.value) {
           ElMessage.warning('请输入水浇地的灌溉水用量和有效利用率');
           valid = false;
@@ -178,12 +330,12 @@ export default {
             ElMessage.error('有效利用率应在0-100%之间');
             valid = false;
           } else {
-            totalFlux += usage * efficiency;
+            totalFlux = usage * efficiency;
+            currentLandType = 'irrigated';
           }
         }
-      }
-
-      if (dryLand.value) {
+      } 
+      else if (selectedLandType.value === 'dry') {
         if (!dryWaterUsage.value || !dryEfficiency.value) {
           ElMessage.warning('请输入旱地的灌溉水用量和有效利用率');
           valid = false;
@@ -198,33 +350,79 @@ export default {
             ElMessage.error('有效利用率应在0-100%之间');
             valid = false;
           } else {
-            totalFlux += usage * efficiency;
+            totalFlux = usage * efficiency;
+            currentLandType = 'dry';
           }
         }
+      } 
+      else {
+        ElMessage.warning('请选择一种土地类型');
+        valid = false;
       }
 
       if (valid) {
+        loading.value = true;
         fluxResult.value = totalFlux;
-        ElMessage.success(`灌溉水输入通量: ${totalFlux.toFixed(2)} m³`);
+        
+        try {
+          // 获取土地类型中文名称
+          const landTypeChinese = landTypeMap[currentLandType];
+          
+          // 第一步:调用calculate接口进行计算
+          const formData = new FormData();
+          formData.append('land_type', landTypeChinese);
+          formData.append('param1', totalFlux);
+          formData.append('param2', parseFloat(irrigationEfficiency.value || irrigatedEfficiency.value || dryEfficiency.value));
+          formData.append('color_map_name', "绿-黄-红-紫");
+          formData.append('output_size', 8);
+
+          await axios.post('http://localhost:8000/api/water/calculate', formData, {
+            headers: {
+              'Content-Type': 'multipart/form-data'
+            }
+          });
+          
+          // 第二步:获取默认地图
+          mapImageUrl.value = await fetchDefaultMap(landTypeChinese);
+          
+          // 第三步:获取默认直方图
+          histogramImageUrl.value = await fetchDefaultHistogram(landTypeChinese);
+          
+          // 第四步:获取统计数据
+          statisticsData.value = await fetchStatistics(landTypeChinese);
+          
+          // 切换到结果页面
+          showCalculation.value = false;
+          showResults.value = true;
+          
+          ElMessage.success('计算完成,结果已展示');
+        } catch (error) {
+          console.error('获取结果失败:', error);
+          ElMessage.error('获取结果失败,请重试');
+        } finally {
+          loading.value = false;
+        }
       }
     };
 
     return {
-      waterLand,
-      irrigatedLand,
-      dryLand,
-
+      selectedLandType,
       irrigationWaterUsage,
       irrigationEfficiency,
-
       irrigatedWaterUsage,
       irrigatedEfficiency,
-
       dryWaterUsage,
       dryEfficiency,
-
       calculateFlux,
-      fluxResult
+      fluxResult,
+      showCalculation,
+      showResults,
+      loading,
+      mapImageUrl,
+      histogramImageUrl,
+      statisticsData,
+      formatNumber,
+      backToCalculation
     };
   }
 };
@@ -235,19 +433,73 @@ export default {
   display: flex;
   justify-content: center;
   align-items: center;
-  padding: 10px;
+  flex-direction: column;
 }
 
-.compact-card {
-  background: linear-gradient(135deg,
-      rgba(250, 253, 255, 0.8),
-      rgba(137, 223, 252, 0.8));
-  padding: 20px;
-  border: 1px solid #e0f7fa;
+.gradient-card {
+  /* 半透明渐变背景 */
+  background: linear-gradient(
+    135deg, 
+    rgba(250, 253, 255, 0.8), 
+    rgba(137, 223, 252, 0.8)
+  );
+  width: 80%;
+  max-width: 800px;
+  padding: 25px;
+  box-sizing: border-box;
   border-radius: 12px;
-  width: 100%;
-  max-width: 650px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  border: none;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+  backdrop-filter: blur(5px); /* 添加模糊效果增强半透明感 */
+}
+
+.results-card {
+ background: linear-gradient(
+    135deg, 
+    rgba(250, 253, 255, 0.8), 
+    rgba(137, 223, 252, 0.8)
+  );
+  width: 90%;
+  max-width: 1200px;
+  padding: 30px;
+  box-sizing: border-box;
+  border-radius: 12px;
+  border: none;
+  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
+}
+
+.results-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding-bottom: 15px;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.result-title {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+  text-align: center;
+  flex-grow: 1;
+}
+
+/* 输入框标题样式 */
+.input-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #606266;
+  margin-bottom: 5px;
+  text-align: left;
+}
+
+/* 单选框容器 */
+.radio-container {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  height: 100%;
 }
 
 .compact-title-section {
@@ -325,18 +577,18 @@ export default {
   box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
 }
 
-:deep(.compact-input .el-input__inner:disabled) {
-  background-color: #f5f7fa;
-  opacity: 0.7;
+:deep(.el-radio) {
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  text-align: left;
 }
 
-.compact-button-section {
-  display: flex;
-  justify-content: center;
-  margin: 15px 0;
+:deep(.el-radio__label) {
+  text-align: left;
 }
 
-.compact-calculate-btn {
+.calculate-btn {
   width: 100%;
   max-width: 300px;
   height: 42px;
@@ -395,4 +647,93 @@ export default {
   color: #555;
   margin-top: 5px;
 }
+
+/* 结果区域样式 */
+.results-container {
+  margin-top: 20px;
+}
+
+.result-subtitle {
+  text-align: center;
+  font-weight: bold;
+  font-size: 20px;
+  margin-bottom: 15px;
+  color: #333;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #eee;
+}
+
+.result-image {
+  width: 100%;
+  max-height: 400px;
+  object-fit: contain;
+  border-radius: 8px;
+  border: 1px solid #e4e7ed;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  background-color: #f8f8f8;
+}
+
+.image-placeholder {
+  height: 400px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border: 1px dashed #dcdfe6;
+  border-radius: 8px;
+  background-color: #f5f7fa;
+  color: #909399;
+  font-style: italic;
+  font-size: 18px;
+}
+
+.statistics-container {
+  background-color: rgba(255, 255, 255, 0.7);
+  border-radius: 12px;
+  padding: 25px;
+  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
+  margin-top: 20px;
+}
+
+/* 表格样式增强 */
+:deep(.el-table) {
+  margin-bottom: 25px;
+  border-radius: 10px;
+  overflow: hidden;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+:deep(.el-table__header) {
+  background-color: #f0f8ff;
+}
+
+:deep(.el-table th) {
+  background-color: #f0f8ff;
+  font-weight: bold;
+  color: #2c3e50;
+  font-size: 16px;
+}
+
+:deep(.el-table td) {
+  font-size: 15px;
+}
+
+/* 返回按钮样式 */
+.back-button {
+  position: absolute;
+  top: 20px;
+  left: 20px; /* 从right改为left */
+  width: 120px;
+  font-size: 16px;
+  padding: 10px;
+  background: linear-gradient(to right, #8DF9F0, #26B046);
+  color: white;
+  border: none;
+  border-radius: 20px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+  z-index: 10; /* 确保按钮在顶层 */
+}
+
+.back-button:hover {
+  background: linear-gradient(to right, #7de8df, #20a03d);
+}
 </style>