<template>
  <el-dialog v-model="dialogVisible" fullscreen :before-close="handleClose" destroy-on-close>
    <template #header>
      <div class="order-header">
        <div class="order-info flex gap-2 items-center">
          <div class="order-no font-bold text-lg">
            出库单编号：{{ order.orderNo }}
          </div>
          <dict-tag :options="out_order_status" :value="order.orderStatus" />
        </div>
        <div class="order-actions"></div>
      </div>
    </template>

    <div class="outbound-execution-container">
      <!-- 双栏布局 -->
      <div class="execution-layout">
        <!-- 左栏：出库单明细 -->
        <div class="detail-section">
          <div class="section-header">
            <h3><el-icon>
                <List />
              </el-icon> 出库单明细</h3>
          </div>

          <el-table ref="tableRef" :data="orderDetails" stripe highlight-current-row row-key="itemId"
            height="calc(100vh - 320px)" v-loading="loadingDetails" @expand-change="handleExpandChange"
            preserve-expanded-content>
            <el-table-column type="expand">
              <template #default="props">
                <el-table :data="props.row.inventoryRecords" height="400px">
                  <el-table-column label="批次号" align="center" prop="batchNo" width="120" />
                  <el-table-column label="仓库/库区/货架" align="center">
                    <template #default="scope">
                      {{ scope.row.warehouse?.warehouseName || '-' }}/{{ scope.row.area?.areaName || '-' }}/{{
                        scope.row.location?.locationName || '-' }}
                    </template>
                  </el-table-column>
                  <el-table-column label="RFID标签" align="center" prop="rfidCode" />
                  <el-table-column label="数量" align="center" prop="quantity" />
                  <el-table-column label="入库单价（元）" align="center" prop="unitCost" />
                  <el-table-column label="出库时间" align="center" prop="outboundTime">
                    <template #default="scope">
                      <span>{{ parseTime(scope.row.outboundTime, '{y}-{m}-{d}') }}</span>
                    </template>
                  </el-table-column>
                  <el-table-column label="是否撤销" align="center" prop="isCanceled">
                    <template #default="scope">
                      <dict-tag :options="is_cancel" :value="scope.row.isCanceled" />
                    </template>
                  </el-table-column>
                  <el-table-column label="撤销时间" align="center" prop="cancelTime">
                    <template #default="scope">
                      <span>{{ parseTime(scope.row.cancelTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
                    </template>
                  </el-table-column>
                  <!-- <el-table-column label="撤销人" align="center" prop="cancelBy" /> -->
                  <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
                    <template #default="scope">
                      <el-button link v-if="scope.row.isCanceled === '0'" type="primary"
                        @click="handleCancelByRelation(scope.row)">撤销</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </template>
            </el-table-column>
            <el-table-column prop="material.materialCode" label="物资编码" width="120" />
            <el-table-column prop="material.materialName" label="物资名称" width="120" />
            <el-table-column prop="material.specification" label="规格型号" />
            <el-table-column prop="unit" label="单位" width="80" />
            <el-table-column prop="planQuantity" label="计划出库" align="right" />
            <el-table-column prop="actualQuantity" label="已出库" align="right" />
            <el-table-column prop="amount" label="金额（元）" align="right" />
            <el-table-column prop="pickingStatus" label="拣货状态">
              <template #default="scope">
                <dict-tag :options="out_order_status" :value="scope.row.pickingStatus" />
              </template>
            </el-table-column>
            <el-table-column label="操作" width="120" align="center" fixed="right">
              <template #default="scope">
                <div>
                  <el-button v-if="scope.row.pickingStatus !== '0'" type="primary" size="small"
                    @click="handleCancel(scope.row)">
                    撤销
                  </el-button>
                </div>
                <div>
                  <el-button v-if="scope.row.pickingStatus !== '2'" type="success" size="small" @click="showBatchRecommendation(scope.row)">
                    <el-icon>
                      <MagicStick />
                    </el-icon>
                    智能推荐批次
                  </el-button>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </div>

        <!-- 右栏：扫码操作区 -->
        <div class="scan-section">
          <div class="section-header">
            <h3>
              <!-- <el-icon><Scan /></el-icon>  -->
              扫码出库
            </h3>

          </div>

          <!-- 扫码输入区域 -->
          <div class="scan-input-area">
            <div class="input-wrapper">
              <el-input v-model="scanInput" placeholder="请扫描RFID标签" size="large" clearable @keyup.enter="handleScan"
                @clear="clearScanResult" ref="scanInputRef">
                <template #prepend>
                  <el-icon>
                    <Search />
                  </el-icon>
                </template>
                <template #append>
                  <el-button type="primary" :loading="scanning" @click="handleScan">
                    确认
                  </el-button>
                </template>
              </el-input>
            </div>

            <!-- 扫描结果提示 -->
            <div v-if="scanMessage" class="scan-message" :class="scanMessage.type">
              <el-icon v-if="scanMessage.type === 'success'">
                <CircleCheck />
              </el-icon>
              <el-icon v-if="scanMessage.type === 'error'">
                <CircleClose />
              </el-icon>
              <el-icon v-if="scanMessage.type === 'warning'">
                <Warning />
              </el-icon>
              <span>{{ scanMessage.text }}</span>
            </div>
          </div>

          <!-- 批次信息展示 -->
          <div v-if="currentBatch" class="batch-info-card">
            <div class="batch-header">
              <h4>批次信息</h4>
              <el-tag type="info" size="small">
                库存: {{ currentBatch.availableQuantity }} {{ currentBatch.unit }}
              </el-tag>
            </div>
            <div class="batch-details">
              <div class="detail-row">
                <span class="label">批次号:</span>
                <span class="value batch-no">{{ currentBatch.batchNo }}</span>
              </div>
              <div class="detail-row">
                <span class="label">物资:</span>
                <span class="value">{{ currentBatch.materialId }}</span>
              </div>
              <div class="detail-row">
                <span class="label">货架:</span>
                <el-tag size="small" type="primary">
                  {{ currentBatch.locationId }}
                </el-tag>
              </div>
              <div class="detail-row">
                <span class="label">有效期:</span>
                <span class="value" :class="{
                  'expiry-warning': isNearExpiry(currentBatch.expirationDate)
                }">
                  {{ formatDate(currentBatch.expirationDate) }}
                  <el-icon v-if="isNearExpiry(currentBatch.expirationDate)" color="#e6a23c">
                    <Warning />
                  </el-icon>
                </span>
              </div>
            </div>

            <!-- 出库数量输入 -->
            <div class="quantity-input-section">
              <div class="input-row">
                <span class="label">本次出库数量:</span>
                <el-input-number v-model="outboundQuantity" :min="0" :precision="3" :step="1" size="large"
                  controls-position="right" style="width: 200px;" />
                <span class="unit">{{ currentBatch.unit }}</span>
              </div>
              <div class="quantity-tips">
                <span v-if="remainingNeed > 0">
                  还需出库: <strong>{{ remainingNeed }}</strong> {{ currentBatch.unit }}
                </span>
                <el-button type="text" size="small"
                  @click="outboundQuantity = Math.min(currentBatch.quantity, remainingNeed)">
                  填充所需数量
                </el-button>
                <el-button type="text" size="small" @click="outboundQuantity = currentBatch.quantity">
                  全部出库
                </el-button>
              </div>
            </div>

            <!-- 操作按钮 -->
            <div class="action-buttons">
              <el-button type="primary" size="large" :loading="processingOutbound" :disabled="!canOutbound"
                @click="handleOutbound">
                <el-icon>
                  <Check />
                </el-icon>
                确认出库
              </el-button>
              <el-button size="large" @click="clearScanResult">
                取消
              </el-button>
            </div>
          </div>

          <!-- 本次出库流水记录 -->
          <div class="transaction-section">
            <div class="section-header">
              <h4><el-icon>
                  <Document />
                </el-icon> 本次出库记录</h4>
              <!-- <el-button type="danger" size="small" :disabled="!lastTransaction" @click="handleUndoLast">
                <el-icon>
                  <Delete />
                </el-icon>
                撤销最后操作
              </el-button> -->
            </div>

            <el-table :data="recentTransactions" stripe height="200px" v-loading="loadingTransactions">
              <el-table-column label="时间" width="140">
                <template #default="{ row }">
                  {{ formatTime(row.relation?.outboundTime) }}
                </template>
              </el-table-column>
              <el-table-column prop="batchNo" label="批次号" width="150" />
              <el-table-column prop="materialName" label="物资">
                <template #default="{ row }">
                  {{ row.materialName }}
                </template>
              </el-table-column>
              <el-table-column label="出库数量" width="100" align="right">
                <template #default="{ row }">
                  {{ row.thisPickQuantity }}
                </template>
              </el-table-column>
              <el-table-column label="状态" width="100" align="right">
                <template #default="{ row }">
                  {{ row.message }}
                </template>
              </el-table-column>
              <!-- <el-table-column prop="locationId" label="货架" width="100" /> -->
            </el-table>
          </div>
        </div>
      </div>

      <!-- 批次详情对话框 -->
      <BatchDetailDialog v-model="showBatchDialog" :detail="selectedDetail" :transactions="detailTransactions" />

      <!-- 批次推荐对话框 -->
      <BatchRecommendationDialog ref="recommendationDialogRef" v-model="showRecommendationDialog" :detail="selectedDetail"
        @select-batch="handleSelectRecommendedBatch" @select-batch-all="handleSelectAllRecommendations" />
    </div>
  </el-dialog>
</template>

<script setup>
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  User,
  Calendar,
  Check,
  VideoPause,
  VideoPlay,
  List,
  Search,
  CircleCheck,
  CircleClose,
  Warning,
  Document,
  Delete,
  MagicStick
} from '@element-plus/icons-vue'
import BatchDetailDialog from './BatchDetailDialog.vue'
import BatchRecommendationDialog from './BatchRecommendationDialog.vue'
import { listWmsOutboundOrderItem, getWmsOutboundOrderItem, updateWmsOutboundOrderItem } from '@/api/ware/wmsOutboundOrderItem'
import { listWmsOperationRecord, addWmsOperationRecord } from '@/api/ware/wmsOperationRecord'
import { updateWmsOutboundOrder, confirmOutbound } from '@/api/ware/wmsOutboundOrder'
import useUserStore from '@/store/modules/user'
import { cancelByDetailId, cancelByRelationId } from '@/api/ware/wmsOutboundOrder'
import { listWmsInventory } from "@/api/ware/wmsInventory"
import { listWmsOutboundItemInventory } from "@/api/ware/wmsOutboundItemInventory"

const { proxy } = getCurrentInstance()

const { outbound_type, out_order_status, is_cancel } = proxy.useDict('outbound_type', 'out_order_status', 'is_cancel')

const props = defineProps({
  visible: Boolean,
  order: Object
})

const emit = defineEmits(['update:visible', 'order-updated', 'operation-log'])
const userStore = useUserStore()
// 响应式数据
const orderDetails = ref([])
const currentDetailId = ref('')
const tableRef = ref(null)
const expandedRows = ref(new Set())
const scanInput = ref('')
const scanMessage = ref(null)
const outboundQuantity = ref(0)
const recentTransactions = ref([])
const selectedDetail = ref(null)
const detailTransactions = ref([])
const lastTransaction = ref(null)
const currentBatch = ref(null)

// 对话框控制
const dialogVisible = computed({
  get() {
    return props.visible
  },
  set(value) {
    emit('update:visible', value)
  }
})

// 对话框关闭处理
const handleClose = () => {
  emit('update:visible', false)
}

// 状态标志
const loadingDetails = ref(false)
const scanning = ref(false)
const processingOutbound = ref(false)
const confirming = ref(false)
const loadingTransactions = ref(false)

// 对话框控制
const showBatchDialog = ref(false)
const showRecommendationDialog = ref(false)
const recommendationDialogRef = ref(null)
// 计算属性
const totalPlanned = computed(() => {
  return orderDetails.value.reduce((sum, detail) => sum + (detail.planQuantity || 0), 0)
})

const totalActual = computed(() => {
  return orderDetails.value.reduce((sum, detail) => sum + (detail.actualQuantity || 0), 0)
})

const completionRate = computed(() => {
  return totalPlanned.value > 0 ? Math.min((totalActual.value / totalPlanned.value) * 100, 100) : 0
})

const canConfirm = computed(() => {
  if (props.order.status !== 'EXECUTING') return false
  return orderDetails.value.every(detail => detail.actualQuantity > 0)
})

const remainingNeed = computed(() => {
  if (!currentDetailId.value || !currentBatch.value) return 0
  const detail = orderDetails.value.find(d => d.itemId === currentDetailId.value)
  if (!detail) return 0
  return Math.max(0, (detail.planQuantity || 0) - (detail.actualQuantity || 0))
})

const maxOutboundQuantity = computed(() => {
  if (!currentBatch.value) return 0
  return Math.min(currentBatch.value.availableQuantity, remainingNeed.value)
})

const canOutbound = computed(() => {
  return outboundQuantity.value > 0 &&
    outboundQuantity.value <= maxOutboundQuantity.value &&
    !processingOutbound.value
})

// 方法
const loadOrderDetails = async () => {
  loadingDetails.value = true
  try {
    const response = await listWmsOutboundOrderItem({ orderId: props.order.orderId, pageNum: 1, pageSize: 1000 })
    orderDetails.value = response.rows || []
  } catch (error) {
    ElMessage.error('加载明细失败')
  } finally {
    loadingDetails.value = false
  }
}

const loadOutboundItemInventory = async (row) => {
  try {
    const response = await listWmsOutboundItemInventory({
      itemId: row.itemId,
      pageNum: 1,
      pageSize: 1000
    })

    // 直接更新传入的row对象，保持对象引用不变
    row.inventoryRecords = response.rows || []

  } catch (error) {
    console.error('加载出库记录失败:', error)
    ElMessage.error('加载出库记录失败')
  }
}

const focusScanInput = () => {
  nextTick(() => {
    const input = document.querySelector('.scan-input-area input')
    if (input) {
      ; (input).focus()
    }
  })
}

const handleScan = async () => {
  if (!scanInput.value.trim()) {
    showScanMessage('请输入或扫描批次号', 'warning')
    return
  }

  scanning.value = true
  scanMessage.value = null

  try {

    // 调用扫描批次接口
    const scanResponse = await listWmsInventory({
      rfidTag: scanInput.value
    })

    const scanItem = scanResponse.rows?.length ? scanResponse.rows[0] : null;

    if (!scanItem) {
      showScanMessage('未找到对应的批次', 'error')
      return
    }

    // 检查该库存物资是否在出库的明细中
    const matchedDetail = orderDetails.value.find(d => d.materialId === scanItem.materialId)

    if (matchedDetail) {
      currentDetailId.value = matchedDetail.itemId

      currentBatch.value = scanItem
      // 自动设置出库数量
      const maxQty = Math.min(scanItem.availableQuantity, (matchedDetail.planQuantity || 0) - (matchedDetail.actualQuantity || 0))
      outboundQuantity.value = maxQty > 0 ? maxQty : 0

      showScanMessage(`成功匹配物资: ${matchedDetail.materialId}`, 'success')
    } else {
      showScanMessage('该物资不在出库单计划中', 'error')
      currentBatch.value = null
    }
  } catch (error) {
    showScanMessage(error.message || '扫描失败', 'error')
    currentBatch.value = null
  } finally {
    scanning.value = false
    scanInput.value = ''
    focusScanInput()
  }
}

const handleOutbound = async () => {
  if (!currentBatch.value || !currentDetailId.value) return

  processingOutbound.value = true

  try {
    // 获取当前明细
    const currentDetail = orderDetails.value.find(d => d.itemId === currentDetailId.value)
    if (!currentDetail) {
      showScanMessage('未找到对应的出库明细', 'error')
      return
    }

    // 确认出库
    const confirmResponse = await confirmOutbound({
      rfidTag: currentBatch.value.rfidTag,
      num: outboundQuantity.value,
      orderId: props.order.orderId,
      operatorId: userStore.id,
    })

    if (confirmResponse.code !== 200) {
      showScanMessage(confirmResponse.msg || '出库失败', 'error')
      return
    }

    recentTransactions.value.push(confirmResponse.data)

    lastTransaction.value = confirmResponse.data?.relation;

    // 检查当前行是否已展开
    if (expandedRows.value.has(currentDetail.itemId)) {
      // 先收缩行
      tableRef.value?.toggleRowExpansion(currentDetail, false)
      // 然后重新展开并加载最新数据
      nextTick(() => {
        tableRef.value?.toggleRowExpansion(currentDetail, true)
      })
    }else{
       tableRef.value?.toggleRowExpansion(currentDetail, true)
    }

    getWmsOutboundOrderItem(currentDetail.itemId).then(res => {
      if (res.code === 200) {
        currentDetail.actualQuantity = res.data.actualQuantity
        currentDetail.pickingStatus = res.data.pickingStatus
      }
    })

    showScanMessage(`出库成功: ${outboundQuantity.value} ${currentBatch.value.unit}`, 'success')


    // 清空当前批次
    clearScanResult()

    // 触发更新事件
    emit('order-updated')

  } catch (error) {
    showScanMessage(error.message || '出库失败', 'error')
  } finally {
    processingOutbound.value = false
  }
}

const handleExpandChange = (row, tableExpandedRows) => {
  // 维护expandedRows集合
  if (tableExpandedRows.includes(row)) {
    expandedRows.value.add(row.itemId)
    // 展开时加载交易记录
    loadOutboundItemInventory(row)
  } else {
    expandedRows.value.delete(row.itemId)
    // 收起时清空交易记录
    row.inventoryRecords = []
  }
}

const handleUndoLast = async () => {
  if (!lastTransaction.value) return

  try {
    // 获取最后一次操作记录
    const lastRecord = lastTransaction.value

    // 找到对应的出库单明细
    const currentDetail = orderDetails.value.find(d => d.itemId === lastRecord.itemId)
    if (!currentDetail) {
      ElMessage.error('未找到对应的出库明细')
      return
    }

    const cancelResponse = await cancelByRelationId(lastRecord.relationId)

    if (cancelResponse.code !== 200) {
      ElMessage.error(cancelResponse.msg || '撤销失败')
      return
    }

    // 更新明细的已出库数量
    currentDetail.actualQuantity = (currentDetail.actualQuantity || 0) - (lastRecord.quantity || 0);
    currentDetail.pickingStatus = currentDetail.actualQuantity === 0 ? '0' : '1'

    // 检查当前行是否已展开
    if (expandedRows.value.has(currentDetail.itemId)) {
      // 先收缩行
      tableRef.value?.toggleRowExpansion(currentDetail, false)
      // 然后重新展开并加载最新数据
      nextTick(() => {
        tableRef.value?.toggleRowExpansion(currentDetail, true)
      })
    }

    ElMessage.success('已撤销批次 ' + lastRecord.batchNo)


  } catch (error) {
    console.error('撤销失败:', error)
    ElMessage.error('撤销失败')
  }
}

const showBatchRecommendation = async (row) => {
  row.warehouseId = props.order.warehouseId
  selectedDetail.value = row
  showRecommendationDialog.value = true
  recommendationDialogRef.value?.open(row)
}

const handleSelectRecommendedBatch = (batch) => {
  currentBatch.value = batch
  scanInput.value = batch.rfidTag
  showRecommendationDialog.value = false
  // 自动触发扫描
  nextTick(() => {
    handleScan()
  })
}

const handleSelectAllRecommendations = (batches) => {
 
}


const clearScanResult = () => {
  currentBatch.value = null
  outboundQuantity.value = 0
  scanMessage.value = null
  focusScanInput()
}

const showScanMessage = (text, type = 'info') => {
  scanMessage.value = { text, type }
  setTimeout(() => {
    scanMessage.value = null
  }, 3000)
}

const formatDate = (date) => {
  return new Date(date).toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
  })
}

const formatTime = (date) => {
  return new Date(date).toLocaleString('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
}

const isNearExpiry = (expiryDate) => {
  const expiry = new Date(expiryDate)
  const now = new Date()
  const diffDays = Math.ceil((expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
  return diffDays <= 30 && diffDays > 0
}
/**
 * 撤销明细
 * @param row 明细行数据
 */
const handleCancel = async (row) => {
  try {
    const result = await cancelByDetailId(row, userStore.id)

    if (result.code !== 200) {
      ElMessage.error(result.msg || '撤销失败')
      return
    }

    // 更新出库明细
    const updatedDetail = orderDetails.value.find(d => d.itemId === row.itemId)
    if (updatedDetail) {
      updatedDetail.actualQuantity = 0
      updatedDetail.pickingStatus = '0'
    }

    ElMessage.success('已撤销成功')

    emit('order-updated')

    // 检查当前行是否已展开
    if (expandedRows.value.has(row.itemId)) {
      // 先收缩行
      tableRef.value?.toggleRowExpansion(row, false)
      // 然后重新展开并加载最新数据
      nextTick(() => {
        tableRef.value?.toggleRowExpansion(row, true)
      })
    }
  } catch (error) {
    console.error('撤销失败:', error)
    ElMessage.error('撤销失败')
  }
}
/**
 * 撤销关联流水
 * @param row 关联流水行数据
 */
const handleCancelByRelation = async (row) => {
  try {
    const result = await cancelByRelationId(row, userStore.id)

    if (result.code !== 200) {
      ElMessage.error(result.msg || '撤销失败')
      return
    }

    ElMessage.success('已撤销成功')

    const currentRow = orderDetails.value.find(d => d.itemId === row.itemId)

    getWmsOutboundOrderItem(currentRow.itemId).then(res => {
      if (res.code === 200) {
        currentRow.actualQuantity = res.data.actualQuantity
        currentRow.pickingStatus = res.data.pickingStatus
      }
    })
    emit('order-updated')

    // 检查当前行是否已展开
    if (expandedRows.value.has(currentRow.itemId)) {
      // 先收缩行
      tableRef.value?.toggleRowExpansion(currentRow, false)
      // 然后重新展开并加载最新数据
      nextTick(() => {
        tableRef.value?.toggleRowExpansion(currentRow, true)
      })
    }
  } catch (error) {
    console.error('撤销失败:', error)
    ElMessage.error('撤销失败')
  }
}

/**
 * 监听键盘空格键，确认出库
 */
const handleSpaceKeyDown = (e) => {
  if (e.key === 'Space') {
    handleOutbound()
  }
}

// 生命周期
onMounted(() => {
  focusScanInput();
  // 添加事件监听器
  document.addEventListener('keydown', handleSpaceKeyDown)
})

onBeforeUnmount(() => {
  // 移除事件监听器
  document.removeEventListener('keydown', handleSpaceKeyDown)
})

watch(() => props.order, async (newOrder) => {
  if (newOrder) {
    await loadOrderDetails()
  }
}, { deep: true })

</script>

<style scoped>
.outbound-execution-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  overflow: hidden;
}

.order-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 16px;
}

.order-info {
  flex: 1;
}

.order-title {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-bottom: 10px;
}

.order-title h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
}

.order-meta {
  display: flex;
  gap: 25px;
  font-size: 14px;
  opacity: 0.9;
}

.order-meta span {
  display: flex;
  align-items: center;
  gap: 5px;
}

.order-actions {
  display: flex;
  gap: 10px;
}

.execution-layout {
  flex: 1;
  display: flex;
  min-height: 0;
}

.detail-section,
.scan-section {
  flex: 1;
  padding: 20px;
  overflow: auto;
  border-right: 1px solid #ebeef5;
}

.scan-section {
  max-width: 700px;
  background: #f8fafc;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding-bottom: 10px;
  border-bottom: 2px solid #e4e7ed;
}

.section-header h3,
.section-header h4 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.section-header h3 {
  color: #303133;
}

.section-header h4 {
  color: #606266;
}

.summary-info {
  display: flex;
  align-items: center;
  font-size: 14px;
  color: #606266;
}

.material-name {
  font-weight: 500;
  color: #303133;
}

.material-spec {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.planned-quantity {
  font-weight: 600;
  color: #303133;
}

.actual-quantity {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.actual-quantity span {
  font-weight: 600;
}

.actual-quantity .completed {
  color: #67c23a;
}

.actual-quantity .warning {
  color: #e6a23c;
}

.scan-input-area {
  margin-bottom: 20px;
}

.input-wrapper {
  margin-bottom: 10px;
}

.scan-message {
  padding: 10px 15px;
  border-radius: 4px;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  animation: fadeIn 0.3s;
}

.scan-message.success {
  background: #f0f9eb;
  color: #67c23a;
  border: 1px solid #e1f3d8;
}

.scan-message.error {
  background: #fef0f0;
  color: #f56c6c;
  border: 1px solid #fde2e2;
}

.scan-message.warning {
  background: #fdf6ec;
  color: #e6a23c;
  border: 1px solid #faecd8;
}

.batch-info-card {
  background: white;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  animation: slideIn 0.3s;
}

.batch-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
}

.batch-header h4 {
  margin: 0;
  color: #303133;
}

.batch-details {
  margin-bottom: 20px;
}

.detail-row {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  font-size: 14px;
}

.detail-row .label {
  width: 80px;
  color: #909399;
  flex-shrink: 0;
}

.detail-row .value {
  flex: 1;
  color: #606266;
}

.batch-no {
  font-family: 'Monaco', 'Consolas', monospace;
  background: #f6f8fa;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid #e1e4e8;
}

.expiry-warning {
  color: #e6a23c !important;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 5px;
}

.quantity-input-section {
  margin: 20px 0;
  padding: 15px;
  background: #f8fafc;
  border-radius: 6px;
}

.input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.input-row .label {
  font-weight: 500;
  color: #303133;
}

.quantity-tips {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
  color: #606266;
}

.action-buttons {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.transaction-section {
  margin-top: 20px;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

:deep(.el-table__row.current-row) {
  background-color: #ecf5ff !important;
}

:deep(.el-table__row:hover) {
  background-color: #f5f7fa !important;
}
</style>