<!-- 高斯反算工具组件 -->
<template>
  <div class="gauss-negative-tool">
    <!-- 操作按钮区 -->
    <div class="tool-header">
      <div class="card-header-buttons">
        <el-button type="primary" @click="handleImport" size="small" icon="el-icon-upload">
          导入Excel
        </el-button>

        <el-button 
          type="warning" 
          @click="handleCalculate" 
          size="small" 
          :disabled="!importedData || importedData.length === 0 || calculating"
          :loading="calculating"
          icon="el-icon-caret-right">
          {{ calculating ? '计算中...' : '执行计算' }}
        </el-button>
        <el-button 
          type="danger" 
          @click="clearAll" 
          size="small" 
          :disabled="(!importedData || importedData.length === 0) && calculationResults.length === 0"
          plain
          icon="el-icon-delete">
          清空全部
        </el-button>
      </div>
    </div>
    
    <!-- 参数设置区域 -->
    <div class="params-area">
      <div class="params-row">
        <div class="params-group">
          <label class="param-label">投影面高程</label>
          <el-input 
            v-model="projectionHeight" 
            size="small" 
            style="width: 120px;">
          </el-input>
          <span class="unit">米 (m)</span>
        </div>
        
        <div class="params-group">
          <label class="param-label">坐标系</label>
          <el-select v-model="commonParams.coordinateSystem" size="small" style="width: 140px;" @change="onParamsChange">
            <el-option label="WGS84" value="WGS84"></el-option>
            <el-option label="CGCS2000" value="CGCS2000"></el-option>
            <el-option label="Beijing54" value="Beijing54"></el-option>
            <el-option label="Xian80" value="Xian80"></el-option>
          </el-select>
        </div>
        
        <div class="params-group">
          <label class="param-label">经度位置</label>
          <el-select v-model="commonParams.longitudePosition" size="small" style="width: 80px;" @change="onParamsChange">
            <el-option label="E" value="E"></el-option>
            <el-option label="W" value="W"></el-option>
          </el-select>
        </div>
        
        <div class="params-group">
          <label class="param-label">纬度位置</label>
          <el-select v-model="commonParams.latitudePosition" size="small" style="width: 80px;" @change="onParamsChange">
            <el-option label="N" value="N"></el-option>
            <el-option label="S" value="S"></el-option>
          </el-select>
        </div>
        
        <div class="params-group">
          <label class="param-label">带号</label>
          <el-input-number v-model="commonParams.band" size="small" :precision="3" :step="0.1" :controls="false" style="width: 80px;" placeholder="带号" @change="onParamsChange"></el-input-number>
        </div>
        
        <div class="params-group">
          <label class="param-label">带宽</label>
          <el-select v-model="commonParams.bandwidth" size="small" style="width: 80px;" @change="onParamsChange">
            <el-option label="3" :value="3"></el-option>
            <el-option label="6" :value="6"></el-option>
          </el-select>
        </div>
        
        <div class="params-group">
          <label class="param-label">输出格式</label>
          <el-select v-model="commonParams.outputFormat" size="small" style="width: 120px;">
            <el-option label="度分秒" value="dms"></el-option>
            <el-option label="度" value="degree"></el-option>
          </el-select>
        </div>
      </div>
    </div>

    <!-- 数据展示区 -->
    <div v-if="displayData.length > 0" class="result-section">
      <div class="section-header">
        <span class="section-title">
          <i class="el-icon-tickets"></i>
          {{ calculationResults.length > 0 ? '计算结果' : '导入数据' }}
        </span>
        <span class="section-info">
          共 {{ displayData.length }} 条数据 | 坐标系：{{ commonParams.coordinateSystem }} | 带号：{{ commonParams.band }} | 带宽：{{ commonParams.bandwidth }}
        </span>
        <el-button v-if="calculationResults.length > 0" type="text" size="small" @click="handleExport" icon="el-icon-download">
          导出结果
        </el-button>
      </div>
      
      <el-table :data="displayData" style="width: 100%" border stripe>
        <el-table-column prop="pointNumber" label="待求点号" width="120" align="center"></el-table-column>
        <el-table-column prop="gaussX" label="高斯X坐标(m)" width="180" align="center">
          <template slot-scope="scope">
            {{ formatNumber(scope.row.gaussX, 4) }}
          </template>
        </el-table-column>
        <el-table-column prop="gaussY" label="高斯Y坐标(m)" width="180" align="center">
          <template slot-scope="scope">
            {{ formatNumber(scope.row.gaussY, 4) }}
          </template>
        </el-table-column>
        <el-table-column prop="longitude" label="大地经度" width="150" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.longitude !== undefined" class="result-value">{{ formatNumber(scope.row.longitude, 9) }}</span>
            <span v-else class="empty-cell">-</span>
          </template>
        </el-table-column>
        <el-table-column prop="latitude" label="大地纬度" width="150" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.latitude !== undefined" class="result-value">{{ formatNumber(scope.row.latitude, 9) }}</span>
            <span v-else class="empty-cell">-</span>
          </template>
        </el-table-column>
      </el-table>
      
      <!-- 分页组件 -->
      <div class="pagination-wrapper">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[100, 200, 500]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="totalData">
        </el-pagination>
      </div>
    </div>
    
    <!-- 空状态 -->
    <div v-else class="empty-state">
      <i class="el-icon-document"></i>
      <p>暂无数据</p>
      <p class="empty-tip">请先导入Excel数据，然后点击"执行计算"</p>
    </div>
    
    <!-- 导入Excel对话框 -->
    <el-dialog title="导入Excel" :visible.sync="importDialogVisible" width="550px" @close="resetImport">
      <div style="text-align: center;">
        <el-upload
          class="upload-area"
          :action="''"
          :auto-upload="false"
          :on-change="handleFileChange"
          :show-file-list="true"
          accept=".xlsx,.xls"
          drag
          ref="upload">
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将Excel文件拖到此处，或<em>点击选择</em></div>
          <div class="el-upload__tip" slot="tip">
            支持.xlsx和.xls格式文件
          </div>
        </el-upload>
      </div>
      
      <span slot="footer" class="dialog-footer">
        <el-button @click="importDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitImport" :loading="importLoading" :disabled="!importFile">
          确认导入
        </el-button>
      </span>
    </el-dialog>
    
    <!-- 字段映射对话框 -->
    <el-dialog title="字段映射" :visible.sync="fieldMappingVisible" width="500px" @close="cancelMapping">
      <div class="mapping-tips">
        <el-alert
          title="字段映射说明"
          type="info"
          :closable="false"
          show-icon>
          <p>请将Excel中的列映射到对应的坐标字段。</p>
        </el-alert>
      </div>
      
      <!-- 字段映射区域 -->
      <div class="mapping-section">
        <div class="mapping-row">
          <label class="mapping-label">点号字段：</label>
          <el-select v-model="fieldMapping.pointNumber" class="mapping-select" placeholder="请选择点号列">
            <el-option v-for="col in excelColumns" :key="col" :label="col" :value="col"></el-option>
          </el-select>
        </div>
        <div class="mapping-row">
          <label class="mapping-label">高斯X字段：</label>
          <el-select v-model="fieldMapping.gaussX" class="mapping-select" placeholder="请选择高斯X列">
            <el-option v-for="col in excelColumns" :key="col" :label="col" :value="col"></el-option>
          </el-select>
        </div>
        <div class="mapping-row">
          <label class="mapping-label">高斯Y字段：</label>
          <el-select v-model="fieldMapping.gaussY" class="mapping-select" placeholder="请选择高斯Y列">
            <el-option v-for="col in excelColumns" :key="col" :label="col" :value="col"></el-option>
          </el-select>
        </div>
      </div>
      
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancelMapping">取消</el-button>
        <el-button type="primary" @click="confirmMapping" :disabled="!validateMapping">
          确认映射
        </el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { calculate, importExcel,exportExcel,downloadTemplate } from '@/api/calculate/gaussnegative'

export default {
  name: 'GaussNegativeTool',    
  data() {
    return {
      importedData: [],        // 导入的原始数据
      calculationResults: [],  // 计算结果
      importDialogVisible: false,
      importLoading: false,
      importFile: null,
      calculating: false,
      projectionHeight: 0,
      heightTimer: null,
      
      // 字段映射相关
      fieldMappingVisible: false,
      fieldMapping: {
        pointNumber: '',
        gaussX: '',
        gaussY: ''
      },
      rawImportedData: [],
      excelColumns: [],
      
      // 公共参数
      commonParams: {
        coordinateSystem: 'CGCS2000',
        longitudePosition: 'E',
        latitudePosition: 'N',
        band: 0.0,
        bandwidth: 3,
        outputFormat: 'degree'
      },
      
      // 分页相关
      currentPage: 1,
      pageSize: 100,
    }
  },
  watch: {
    // 当投影面高程改变时，重新计算（如果已有数据）
    projectionHeight(newVal, oldVal) {
       // 清除之前的定时器
      if (this.heightTimer) {
        clearTimeout(this.heightTimer)
      }
      
      // 只有已有数据时才触发计算
      if (this.importedData.length > 0 && this.calculationResults.length > 0) {
        // 设置新的定时器，500ms 后执行
        this.heightTimer = setTimeout(() => {
          this.handleCalculate()
        }, 500)
      }
    }
  },
  methods: {
    // 打开导入对话框 
    handleImport() {
      this.importDialogVisible = true
    },
    
    // 文件选择变化
    handleFileChange(file) {
      this.importFile = file.raw
    },
    
    // 提交导入
    async submitImport() {
      if (!this.importFile) {
        this.$message.warning('请选择文件')
        return
      }
      
      this.importLoading = true
      
      const formData = new FormData()
      formData.append('file', this.importFile)
      
      const response = await importExcel(formData)
      
      if (response.code === 200) {
        const result = response.data
        
        // 保存原始数据和列名
        this.rawImportedData = result.data || []
        this.excelColumns = result.columns || []
        
        // 尝试自动匹配字段
        this.autoMatchFields()
        
        // 清空之前的计算结果
        this.calculationResults = []
        
        this.importDialogVisible = false
        this.importLoading = false
        this.fieldMappingVisible = true
      } else {
        this.$message.error(response.msg)
        this.importLoading = false
      }
    },
    
    // 自动匹配字段
    autoMatchFields() {
      const matchKeywords = {
        pointNumber: ['点号', '待求点', '点名', '名称', 'pointNumber', 'ID'],
        gaussX: ['高斯坐标x', 'X坐标', 'X', 'gaussX', 'x'],
        gaussY: ['高斯坐标y', 'Y坐标', 'Y', 'gaussY', 'y']
      }
      
      Object.keys(matchKeywords).forEach(key => {
        for (const keyword of matchKeywords[key]) {
          const matchedCol = this.excelColumns.find(col => 
            col.includes(keyword) || col.toLowerCase().includes(keyword.toLowerCase())
          )
          if (matchedCol) {
            this.fieldMapping[key] = matchedCol
            break
          }
        }
      })
    },
    
    // 确认映射
    confirmMapping() {
      if (!this.validateMapping) {
        this.$message.warning('请完成所有字段映射')
        return
      }
      
      // 根据映射关系转换数据
      this.importedData = this.rawImportedData.map(item => ({
        pointNumber: item[this.fieldMapping.pointNumber],
        gaussX: item[this.fieldMapping.gaussX],
        gaussY: item[this.fieldMapping.gaussY]
      }))
      
      this.fieldMappingVisible = false
      this.$message.success('数据导入成功')
    },
    
    // 取消映射
    cancelMapping() {
      this.fieldMappingVisible = false
      this.resetFieldMapping()
    },
    
    // 重置字段映射
    resetFieldMapping() {
      this.fieldMapping = {
        pointNumber: '',
        gaussX: '',
        gaussY: ''
      }
      this.commonParams = {
        coordinateSystem: 'CGCS2000',
        longitudePosition: 'E',
        latitudePosition: 'N',
        band: 3,
        bandwidth: 3,
        outputFormat: 'degree'
      }
    },
    
    // 参数变化时清除计算结果，提示用户重新计算
    onParamsChange() {
      if (this.calculationResults.length > 0) {
        this.calculationResults = []
        this.$message.info('参数已变更，请重新执行计算')
      }
    },
    
    // 下载模板
    handleDownloadTemplate() {
       this.download('/calculate/gaussNegative/template', {}, '高斯反算模板.xlsx')
    },
    
    
    // 执行计算
    async handleCalculate() {
      if (!this.importedData || this.importedData.length === 0) {
        this.$message.warning('没有数据可计算')
        return
      }
      
      this.calculating = true
      const results = []
      let successCount = 0
      let failCount = 0
      
      // 构建请求参数
      const requestData = this.importedData.map(item => ({
        pointNumber: item.pointNumber,
        coordinateSystem: this.commonParams.coordinateSystem,
        gaussX: item.gaussX,
        gaussY: item.gaussY,
        longitudePosition: this.commonParams.longitudePosition,
        latitudePosition: this.commonParams.latitudePosition,
        band: this.commonParams.band,
        bandwidth: this.commonParams.bandwidth,
        projectionHeight: this.projectionHeight,
        outputFormat: this.commonParams.outputFormat
      }))
      
      const response = await calculate(requestData)
      
      if (response.code === 200) {
        const results = response.data || []
        
        // 更新计算结果
        this.calculationResults = results.map(item => ({
          pointNumber: item.pointNumber,
          coordinateSystem: item.coordinateSystem,
          longitude: item.longitude,
          longitudePosition: item.longitudePosition,
          latitude: item.latitude,
          latitudePosition: item.latitudePosition,
          band: item.band,
          bandwidth: item.bandwidth,
          projectionHeight: this.projectionHeight,
          gaussX: item.gaussX,
          gaussY: item.gaussY
        }))
        
        // 更新导入数据的计算状态
        this.importedData.forEach(importItem => {
          const found = results.find(r => r.pointNumber === importItem.pointNumber)
          if (found && found.gaussX !== -1) {
            importItem.calculated = true
          }
        })
         const successCount = results.filter(r => r.longitude !== -1).length
        const failCount = results.length - successCount
        
        this.$message.success(`计算完成，成功 ${successCount} 条${failCount > 0 ? `，失败 ${failCount} 条` : ''}`)
        this.calculating = false
      } else {
        this.$message.error(response.msg)
        this.calculating = false
      }
    },

    // 格式化数字显示
    formatNumber(value, decimals = 3) {
      if (value === null || value === undefined) return '--'
      return Number(value).toFixed(decimals)
    },
    
    // 分页大小变化
    handleSizeChange(val) {
      this.pageSize = val
      this.currentPage = 1
    },
    
    // 当前页变化
    handleCurrentChange(val) {
      this.currentPage = val
    },
    
    // 导出结果
    async handleExport() {
      if (this.calculationResults.length === 0) {
        this.$message.warning('没有结果可导出')
        return
      }

      const response = await exportExcel(this.calculationResults)
      
      const blob = new Blob([response], { 
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      })
      
      const url = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = `高斯反算结果_${new Date().getTime()}.xlsx`
      link.click()
      window.URL.revokeObjectURL(url)
    },
    
    // 清空全部
    clearAll() {
    if ((!this.importedData || this.importedData.length === 0) && this.calculationResults.length === 0) {
      return
    }
    
    this.$confirm('确定清空所有数据吗？此操作不可恢复！', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      this.importedData = []
      this.calculationResults = []
      this.$message.success('已清空所有数据')
    }).catch(() => {})
  },
  
    // 重置导入状态
    resetImport() {
      this.importFile = null
      if (this.$refs.upload) {
        this.$refs.upload.clearFiles()
      }
    }
  },
  
  computed: {
    // 验证字段映射（只验证坐标字段）
    validateMapping() {
      if (!this.fieldMapping) {
        return false
      }
      return this.fieldMapping.pointNumber && 
             this.fieldMapping.gaussX && 
             this.fieldMapping.gaussY
    },
    
    // 显示数据：优先显示计算结果，否则显示导入数据
    displayData() {
      let data = []
      if (this.calculationResults.length > 0) {
        data = this.calculationResults.map(item => ({
          pointNumber: item.pointNumber,
          gaussX: item.gaussX,
          gaussY: item.gaussY,
          longitude: item.longitude,
          latitude: item.latitude
        }))
      } else if (this.importedData.length > 0) {
        data = this.importedData.map(item => ({
          pointNumber: item.pointNumber,
          gaussX: item.gaussX,
          gaussY: item.gaussY,
          longitude: undefined,
          latitude: undefined
        }))
      }
      
      // 分页处理
      const start = (this.currentPage - 1) * this.pageSize
      const end = start + this.pageSize
      return data.slice(start, end)
    },
    
    // 总数据条数（用于分页组件）
    totalData() {
      if (this.calculationResults.length > 0) {
        return this.calculationResults.length
      }
      return this.importedData.length
    }
  },
    
}
</script>

<style scoped>
.gauss-negative-tool {
  width: 100%;
}

.tool-header {
  margin-bottom: 20px;
}

.card-header-buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* 参数设置区域样式 */
.params-area {
  background: #f5f7fa;
  border-radius: 8px;
  padding: 16px 20px;
  margin-bottom: 20px;
  border: 1px solid #e4e7ed;
}

.params-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: center;
}

.params-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.param-label {
  font-weight: 500;
  color: #606266;
  min-width: 40px;
}

.unit {
  color: #909399;
  font-size: 13px;
}

.result-section {
  margin-top: 10px;
}

.section-header {
  padding: 12px 16px;
  background: #f5f7fa;
  border-radius: 8px 8px 0 0;
  border: 1px solid #e4e7ed;
  border-bottom: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.section-title {
  font-size: 14px;
  font-weight: bold;
  color: #303133;
}

.section-title i {
  margin-right: 8px;
  color: #11a983;
}

.section-info {
  font-size: 12px;
  color: #909399;
}

.result-value {
  color: #409eff;
  font-family: monospace;
  font-weight: 500;
}

.pagination-wrapper {
  display: flex;
  justify-content: flex-end;
  padding: 12px 16px;
  background: #f5f7fa;
  border-radius: 0 0 8px 8px;
  border: 1px solid #e4e7ed;
  border-top: none;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e4e7ed;
  color: #909399;
}

.empty-state i {
  font-size: 64px;
  margin-bottom: 16px;
}

.empty-tip {
  font-size: 12px;
  margin-top: 12px;
  color: #c0c4cc;
}

.import-tips {
  margin-bottom: 20px;
}

.template-info {
  margin-top: 12px;
}

.template-info ul {
  margin: 8px 0;
  padding-left: 20px;
}

.template-info li {
  margin: 4px 0;
  font-size: 13px;
}

.upload-area {
  margin-top: 10px;
}

.preview-info {
  margin-bottom: 15px;
  padding: 10px;
  background: #f5f7fa;
  border-radius: 4px;
  font-size: 14px;
  color: #606266;
}

.dialog-footer {
  width: 100%;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.template-download-wrapper {
  margin-top: 12px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px dashed #e4e7ed;
}

/* 字段映射对话框样式 */
.mapping-tips {
  margin-bottom: 20px;
}

.mapping-section {
  background: #f9fafb;
  border-radius: 8px;
  padding: 16px;
}

.mapping-row {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
}

.mapping-row:last-child {
  margin-bottom: 0;
}

.mapping-label {
  width: 80px;
  font-weight: 500;
  color: #606266;
}

.mapping-select {
  flex: 1;
  min-width: 200px;
}

.empty-cell {
  color: #C0C4CC;
  font-style: italic;
}
</style>