<!-- 空间直角坐标转大地坐标工具组件 -->
<template>
  <div class="spatial-to-geodetic-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="commonParams.projectionHeight" 
            size="small" 
            style="width: 120px;"
            @change="onParamsChange">
          </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.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 }} 条数据
          <span v-if="calculationResults.length > 0" style="margin-left: 10px;">
            | 坐标系：{{ commonParams.coordinateSystem }} | 投影面高程：{{ commonParams.projectionHeight }}m
          </span>
        </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="spatialX" label="空间直角坐标 X(m)" width="150" align="center">
          <template slot-scope="scope">
            <span>{{ formatNumber(scope.row.spatialX, 4) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="spatialY" label="空间直角坐标 Y(m)" width="150" align="center">
          <template slot-scope="scope">
            <span>{{ formatNumber(scope.row.spatialY, 4) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="spatialZ" label="空间直角坐标 Z(m)" width="150" align="center">
          <template slot-scope="scope">
            <span>{{ formatNumber(scope.row.spatialZ, 4) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="longitude" label="大地经度(° ′ ″)" width="150" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.longitude" class="result-value">{{ formatNumber(scope.row.longitude, 10) }}</span>
            <span v-else class="empty-cell">-</span>
          </template>
        </el-table-column>
        <el-table-column prop="longitudePosition" label="经度位置" width="150" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.longitudePosition" class="result-value">{{ scope.row.longitudePosition }}</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" class="result-value">{{ formatNumber(scope.row.latitude, 10) }}</span>
            <span v-else class="empty-cell">-</span>
          </template>
        </el-table-column>
        <el-table-column prop="latitudePosition" label="纬度位置" width="150" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.latitudePosition" class="result-value">{{ scope.row.latitudePosition }}</span>
            <span v-else class="empty-cell">-</span>
          </template>
        </el-table-column>
        <el-table-column prop="height" label="大地高(m)" width="120" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.height" class="result-value">{{ formatNumber(scope.row.height, 4) }}</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="mappingDialogVisible" width="500px">
      <div class="mapping-tips">
        <el-alert
          title="字段映射说明"
          type="info"
          :closable="false"
          show-icon>
          请将Excel中的列映射到对应的坐标字段。
        </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" size="small">
            <el-option label="请选择" value=""></el-option>
            <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.spatialX" class="mapping-select" size="small">
            <el-option label="请选择" value=""></el-option>
            <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.spatialY" class="mapping-select" size="small">
            <el-option label="请选择" value=""></el-option>
            <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">空间Z坐标字段</label>
          <el-select v-model="fieldMapping.spatialZ" class="mapping-select" size="small">
            <el-option label="请选择" value=""></el-option>
            <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/spatialtogeodetic'

export default {
  name: 'SpatialToGeodeticTool',
  data() {
    return {
      importedData: [],        // 导入的原始数据
      calculationResults: [],  // 计算结果
      importDialogVisible: false,
      importLoading: false,
      importFile: null,
      calculating: false,
      
      // 公共参数
      commonParams: {
        projectionHeight: 0,
        coordinateSystem: 'WGS84',
        outputFormat: 'dms'
      },
      
      // 分页相关
      currentPage: 1,
      pageSize: 100,
      
      // 字段映射相关
      mappingDialogVisible: false,
      excelColumns: [],
      fieldMapping: {
        pointNumber: '',
        spatialX: '',
        spatialY: '',
        spatialZ: ''
      },
      rawImportedData: []
    }
  },
  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)
      
      try {
        const response = await importExcel(formData)
        
        if (response.code === 200) {
          const result = response.data
          
          // 获取Excel列名
          this.excelColumns = result.columns || this.extractColumns(result.data)
          
          // 保存原始数据
          this.rawImportedData = result.data || []
          
          // 清空之前的计算结果
          this.calculationResults = []
          
          // 自动匹配字段
          this.autoMatchFields()
          
          // 显示字段映射对话框
          this.mappingDialogVisible = true
          
          this.$message.success(`${response.msg}`)
          this.importDialogVisible = false
          this.importLoading = false
        } else {
          this.$message.error(response.msg)
          this.importLoading = false
        }
      } catch (error) {
        this.$message.error('导入失败')
        this.importLoading = false
      }
    },
    
    // 提取列名
    extractColumns(data) {
      if (!data || data.length === 0) return []
      return Object.keys(data[0])
    },
    
    // 自动匹配字段
    autoMatchFields() {
      this.resetFieldMapping()
      
      const keywordMap = {
        pointNumber: ['点号', '待求点', '点', '编号', '序号', 'ID'],
        spatialX: ['空间直角坐标X', '空间X', 'X坐标', 'X', 'x'],
        spatialY: ['空间直角坐标Y', '空间Y', 'Y坐标', 'Y', 'y'],
        spatialZ: ['空间直角坐标Z', '空间Z', 'Z坐标', 'Z', 'z']
      }
      
      this.excelColumns.forEach(col => {
        const lowerCol = col.toLowerCase()
        Object.keys(keywordMap).forEach(field => {
          if (!this.fieldMapping[field]) {
            keywordMap[field].forEach(keyword => {
              if (col.includes(keyword) || lowerCol.includes(keyword.toLowerCase())) {
                this.fieldMapping[field] = col
              }
            })
          }
        })
      })
    },
    
    // 确认字段映射
    confirmMapping() {
      if (!this.validateMapping) {
        this.$message.warning('请完成所有必填字段的映射')
        return
      }
      
      // 根据映射转换数据
      this.importedData = this.rawImportedData.map(item => ({
        pointNumber: item[this.fieldMapping.pointNumber],
        spatialX: item[this.fieldMapping.spatialX],
        spatialY: item[this.fieldMapping.spatialY],
        spatialZ: item[this.fieldMapping.spatialZ]
      }))
      
      this.mappingDialogVisible = false
      this.resetFieldMapping()
    },
    
    // 取消字段映射
    cancelMapping() {
      this.mappingDialogVisible = false
      this.resetFieldMapping()
      this.rawImportedData = []
    },
    
    // 重置字段映射
    resetFieldMapping() {
      this.fieldMapping = {
        pointNumber: '',
        spatialX: '',
        spatialY: '',
        spatialZ: ''
      }
    },
    
    // 参数变化时清空计算结果
    onParamsChange() {
      if (this.calculationResults.length > 0) {
        this.calculationResults = []
        this.$message.info('参数已更新，请重新执行计算')
      }
    },
    
    // 下载模板
    handleDownloadTemplate() {
      this.download('/calculate/spatialToGeodetic/template', {}, '空间转大地模板.xlsx')
    },
    
    // 执行计算
    async handleCalculate() {
      if (!this.importedData || this.importedData.length === 0) {
        this.$message.warning('没有数据可计算')
        return
      }
      
      this.calculating = true
      
      // 构建请求参数
      const requestData = this.importedData.map(item => ({
        pointNumber: item.pointNumber,
        projectionHeight: parseFloat(this.commonParams.projectionHeight) || 0,
        coordinateSystem: this.commonParams.coordinateSystem,
        spatialX: parseFloat(item.spatialX),
        spatialY: parseFloat(item.spatialY),
        spatialZ: parseFloat(item.spatialZ),
        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,
          spatialX: item.spatialX,
          spatialY: item.spatialY,
          spatialZ: item.spatialZ,
          longitude: item.longitude,
          latitude: item.latitude,
          height: item.height,
          coordinateSystem: item.coordinateSystem,
          longitudePosition: item.longitudePosition,
          latitudePosition: item.latitudePosition,
          projectionHeight: item.projectionHeight,
        }))
        
        const successCount = results.filter(r => r.longitude !== undefined && r.longitude !== -1).length
        const failCount = results.length - successCount
        
        this.$message.success(`计算完成，成功 ${successCount} 条${failCount > 0 ? `，失败 ${failCount} 条` : ''}`)
      } else {
        this.$message.error(response.msg)
      }
      
      this.calculating = false
    },
    
    // 导出结果
    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()
      }
    },
    
    // 格式化数字显示
    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
    },
    
    // 获取坐标系标签类型
    getCoordinateType(system) {
      const types = {
        'WGS84': 'primary',
        'CGCS2000': 'success',
        'Beijing54': 'warning',
        'Xian80': 'info'
      }
      return types[system] || 'info'
    }
  },
  
  computed: {
    // 验证字段映射
    validateMapping() {
      if (!this.fieldMapping) {
        return false
      }
      return this.fieldMapping.pointNumber && 
             this.fieldMapping.spatialX && 
             this.fieldMapping.spatialY && 
             this.fieldMapping.spatialZ
    },
    
    // 显示数据：优先显示计算结果，否则显示导入数据
  displayData() {
    let data = []
    if (this.calculationResults.length > 0) {
      data = this.calculationResults.map(item => ({
        pointNumber: item.pointNumber,
        spatialX: item.spatialX,
        spatialY: item.spatialY,
        spatialZ: item.spatialZ,
        longitude: item.longitude,
        latitude: item.latitude,
        height: item.height,
        longitudePosition: item.longitudePosition,
        latitudePosition: item.latitudePosition,
      }))
    } else if (this.importedData.length > 0) {
      data = this.importedData.map(item => ({
        pointNumber: item.pointNumber,
        spatialX: item.spatialX,
        spatialY: item.spatialY,
        spatialZ: item.spatialZ,
        longitude: undefined,
        latitude: undefined,
        height: 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>
.spatial-to-geodetic-tool {
  width: 100%;
}

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

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

.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;
}

.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;
}

/* 参数设置区域样式 */
.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-row + .params-row {
  margin-top: 12px;
}

.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;
}

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

/* 字段映射对话框样式 */
.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: 120px;
  font-weight: 500;
  color: #606266;
}

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

/* 分页组件样式 */
.pagination-wrapper {
  padding: 12px 16px;
  background: #fff;
  border-radius: 0 0 8px 8px;
  border: 1px solid #e4e7ed;
  border-top: none;
  display: flex;
  justify-content: flex-end;
}
</style>