<template>
  <!-- 物料明细表格容器 -->
  <div class="material-detail-container">
    <!-- 表格头部操作区域 -->
    <div class="material-detail-header">
      <div class="header-left">
        <span class="section-title">物料明细</span>
        <el-tag
          v-if="materialDetails.length > 0"
          type="info"
          size="small"
          class="count-tag"
        >
          共 {{ materialDetails.length }} 条
        </el-tag>
      </div>
      <div class="header-right">
        <!-- 物料选择区域 -->
        <div class="material-select-container">
          <el-select
            v-model="selectedMaterialId"
            placeholder="请选择物料"
            filterable
            remote
            reserve-keyword
            :remote-method="remoteSearchMaterial"
            :loading="materialLoading"
            size="small"
            style="width: 300px; margin-right: 8px;"
            clearable
          >
            <el-option
              v-for="item in materialOptions"
              :key="item.id"
              :label="`${item.itemName} (${item.itemCode})`"
              :value="item.id"
            >
              <span style="float: left">{{ item.itemName }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ item.itemCode }}</span>
            </el-option>
          </el-select>
          <el-button
            type="primary"
            icon="el-icon-plus"
            size="small"
            :disabled="!selectedMaterialId"
            @click="handleImportSelectedMaterial"
          >
            导入
          </el-button>
        </div>
      </div>
    </div>

    <!-- 物料明细表格 -->
    <div class="material-detail-content">
      <avue-crud
        ref="materialDetailCrud"
        :data="currentPageData"
        :option="tableOption"
        :page.sync="page"
        @refresh-change="handleRefresh"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        @row-del="handleRowDelete"
        @row-update="handleRowUpdate"
      >
        <!-- 可用数量自定义模板 -->
        <template slot="availableQuantity" slot-scope="scope">
          <span>{{ formatFloatNumber(scope.row.availableQuantity) }}</span>
        </template>

        <!-- 确认数量自定义模板 -->
        <template slot="confirmQuantity" slot-scope="scope">
          <span>{{ formatFloatNumber(scope.row.confirmQuantity) }}</span>
        </template>

        <!-- 单价自定义模板 -->
        <template slot="unitPrice" slot-scope="scope">
          <el-input
            v-if="editMode && isRowEditable(scope.row)"
            v-model="scope.row.unitPrice"
            size="mini"
            style="width: 100%"
            placeholder="请输入单价"
            :disabled="true"
            @input="validateFloatInput($event, scope.row, 'unitPrice')"
            @blur="handleUnitPriceBlur(scope.row, scope.$index)"
          />
          <span v-else>{{ formatUnitPrice(scope.row.unitPrice) }}</span>
        </template>
        <!-- 订单数量自定义模板 -->
        <template slot="orderQuantity" slot-scope="scope">
          <el-input
            v-if="editMode && isRowEditable(scope.row)"
            v-model="scope.row.orderQuantity"
            size="mini"
            style="width: 100%"
            placeholder="请输入订单数量"
            @input="validateIntegerInput($event, scope.row, 'orderQuantity')"
            @blur="handleQuantityBlur(scope.row, scope.$index)"
          />
          <span v-else>{{ formatIntegerNumber(scope.row.orderQuantity) }}</span>
        </template>

        <!-- 税率自定义模板 -->
        <template slot="taxRate" slot-scope="scope">
          <el-input
            v-if="editMode && isRowEditable(scope.row)"
            v-model="scope.row.taxRate"
            size="mini"
            style="width: 100%"
            placeholder="请输入税率"
            :disabled="true"
            @input="validateFloatInput($event, scope.row, 'taxRate', 0, 100)"
            @blur="validateAndFormatFloatOnBlur(scope.row, 'taxRate', 0, 100); handleTaxRateChange(scope.row, scope.$index)"
          />
          <span v-else>{{ formatTaxRate(scope.row.taxRate, false) }}%</span>
        </template>

        <!-- 税额自定义模板 -->
        <template slot="taxAmount" slot-scope="scope">
          <el-input
            v-if="editMode && isRowEditable(scope.row)"
            v-model="scope.row.taxAmount"
            size="mini"
            style="width: 100%"
            placeholder="请输入税额"
            :disabled="true"
            @input="validateFloatInput($event, scope.row, 'taxAmount')"
            @blur="validateAndFormatFloatOnBlur(scope.row, 'taxAmount'); handleTaxAmountChange(scope.row, scope.$index)"
          />
          <span v-else>{{ formatAmount(scope.row.taxAmount, false) }}</span>
        </template>

        <!-- 总金额自定义模板 -->
        <template slot="totalAmount" slot-scope="scope">
          <el-input
            v-if="editMode && isRowEditable(scope.row)"
            v-model="scope.row.totalAmount"
            size="mini"
            style="width: 100%"
            placeholder="请输入总金额"
            :disabled="true"
            @input="validateFloatInput($event, scope.row, 'totalAmount')"
            @blur="validateAndFormatFloatOnBlur(scope.row, 'totalAmount'); handleTotalAmountChange(scope.row, scope.$index)"
          />
          <span v-else>{{ formatAmount(scope.row.totalAmount, false) }}</span>
        </template>

        <!-- 明细状态列自定义渲染 -->
        <template slot="status" slot-scope="{ row }">
          <el-tag
            :type="getStatusTagType(row.itemStatus)"
            size="mini"
          >
            {{ getStatusText(row.itemStatus) }}
          </el-tag>
        </template>

        <!-- 操作列自定义渲染 -->
        <template slot="menu" slot-scope="{ row, index }">
          <el-button
            v-if="row.isDeletable"
            type="text"
            size="mini"
            icon="el-icon-delete"
            class="delete-btn"
            @click="handleDeleteMaterial(row, index)"
          >
            删除
          </el-button>
        </template>
      </avue-crud>
    </div>




  </div>
</template>

<script>
/**
 * @fileoverview 物料明细表格组件
 * @description 基于AvueJS的物料明细数据展示和操作组件，支持分页、搜索、删除等功能
 * @typedef {import('./types').MaterialDetailTableComponent} MaterialDetailTableComponent
 */

import { getMaterialDetailOption, DEFAULT_PAGINATION_CONFIG } from './material-detail-option'
import {
  MaterialDetailStatus,
  getOrderItemStatusLabel as getMaterialDetailStatusLabel,
  getOrderItemStatusTagType as getMaterialDetailStatusTagType,
  getOrderItemStatusColor as getMaterialDetailStatusColor,
  MaterialDetailDataSource
} from '@/constants/order'
import { MATERIAL_DETAIL_EVENTS, DIALOG_EVENTS } from './events'
import { getMaterialFullList } from '@/api/order/sales-order'
import {
  formatAmount,
  formatFloatNumber,
  formatIntegerNumber,
  formatUnitPrice,
  formatTaxRate,
  preciseMultiply,
  preciseDivide,
  preciseRound,
  validateNumber,
  NUMBER_TYPES
} from './number-format-utils'

/**
 * @typedef {import('./types').MaterialDetailRecord} MaterialDetailRecord
 * @typedef {import('./types').MaterialUpdateEventData} MaterialUpdateEventData
 * @typedef {import('./types').MaterialDeleteEventData} MaterialDeleteEventData
 * @typedef {import('./types').MaterialDetailQueryParams} MaterialDetailQueryParams
 * @typedef {import('smallwei__avue/crud').AvueCrudOption} AvueCrudOption
 * @typedef {import('smallwei__avue/crud').AvueCrudColumn} AvueCrudColumn
 * @typedef {import('smallwei__avue/crud').PageOption} PageOption
 */



// 使用@types/smallwei__avue/crud中的PageOption类型代替PaginationConfig

/**
 * 组件数据类型定义
 * @typedef {Object} MaterialDetailTableData
 * @property {Partial<MaterialDetailRecord>} formData - 表单数据
 * @property {PageOption} page - 分页配置
 * @property {boolean} importDialogVisible - 导入弹窗显示状态
 */

// 状态处理已统一使用明细管理中的工具函数，无需本地映射常量

/**
 * 物料明细表格组件
 * @description 用于展示和编辑订单的物料明细信息，支持物料导入和实时编辑功能
 * 当物料数量、单价、税率等字段变更时，自动计算总金额和税额，并触发父组件重新计算订单总计
 * @emits {MaterialDetailRecord[]} material-import - 物料导入事件
 * @emits {Object} material-update - 物料明细更新事件，包含更新的行数据和索引
 * @emits {Object} material-delete - 物料明细删除事件
 * @emits {void} refresh - 刷新事件
 */
export default {
  name: 'MaterialDetailTable',
  components: {},

  /**
   * 组件属性定义
   * @description 定义组件接收的外部属性
   */
  props: {
    /**
     * 是否为编辑模式 - 控制表格是否可编辑
     * @type {boolean}
     */
    editMode: {
      type: Boolean,
      default: false
    },
    /**
     * 订单ID - 关联的订单唯一标识符
     * @type {string|number|null}
     */
    orderId: {
      type: [String, Number],
      default: null,
      validator: (value) => value === null || value === undefined || (typeof value === 'string' && value.length > 0) || (typeof value === 'number' && value > 0)
    },

    /**
     * 物料明细列表 - 要展示的物料明细数据
     * @type {MaterialDetailRecord[]} 物料明细数据数组，每个元素包含物料的详细信息
     */
    materialDetails: {
      type: Array,
      required: true,
      default: () => [],
      validator: (value) => Array.isArray(value) && value.every(item =>
        typeof item === 'object' && item !== null &&
        typeof item.id === 'string' &&
        typeof item.itemCode === 'string'
      )
    }
  },

  /**
   * 组件数据
   * @returns {MaterialDetailTableData} 组件响应式数据对象
   * @this {MaterialDetailTableComponent}
   */
  data() {
    return {
      /**
       * 表单数据 - 当前编辑行的数据
       * @type {Partial<MaterialDetailRecord>} 物料明细表单数据对象
       */
      formData: {},

      /**
       * 分页配置 - AvueJS表格分页相关配置
       * @type {PaginationConfig} 包含currentPage、pageSize、total等属性的分页配置对象
       */
      page: {
        currentPage: 1,
        pageSize: DEFAULT_PAGINATION_CONFIG.pageSize,
        total: 0
      },

      /**
       * 选中的物料ID - 当前在下拉框中选中的物料ID
       * @type {string|null}
       */
      selectedMaterialId: null,

      /**
       * 物料选项列表 - 远程搜索返回的物料选项
       * @type {ItemRecord[]}
       */
      materialOptions: [],

      /**
       * 物料搜索加载状态 - 控制远程搜索时的加载状态
       * @type {boolean}
       */
      materialLoading: false,

      /**
       * 搜索防抖定时器 - 用于防抖处理远程搜索
       * @type {number|null}
       */
      searchTimer: null,

      /**
       * 事件常量
       */
      DIALOG_EVENTS,

      /**
       * 正在编辑的行数据 - 用于记录编辑前的状态
       * @type {MaterialDetailRecord|null}
       */
      editingRow: null,

      /**
       * 正在编辑的属性名 - 用于记录当前编辑的字段
       * @type {string|null}
       */
      editingProp: null
    }
  },

  /**
   * 计算属性
   * @this {MaterialDetailTableComponent}
   */
  computed: {
    /**
     * 表格配置选项 - 获取AvueJS表格的配置对象
     * @returns {AvueCrudOption} AvueJS表格配置对象，根据编辑模式配置
     */
    tableOption() {
      return getMaterialDetailOption(this.editMode)
    },

    /**
     * 当前页显示的数据 - 根据分页配置计算当前页应显示的数据
     * @returns {MaterialDetailRecord[]} 当前页的物料明细数据
     */
    currentPageData() {
      const { currentPage, pageSize } = this.page
      const startIndex = (currentPage - 1) * pageSize
      const endIndex = startIndex + pageSize
      return this.materialDetails.slice(startIndex, endIndex)
    }
  },

  /**
   * 监听器
   * @this {MaterialDetailTableComponent}
   */
  watch: {
    /**
     * 监听物料明细变化
     * @param {MaterialDetailRecord[]} newVal - 新的物料明细列表
     * @returns {void}
     */
    materialDetails: {
      handler(newVal) {
        this.page.total = newVal.length
      },
      immediate: true
    }
  },

  /**
   * 组件方法
   * @this {MaterialDetailTableComponent}
   */
  methods: {
    /**
       * 验证整数输入
       * @param {string} value - 输入值
       * @param {Object} row - 当前行数据
       * @param {string} field - 字段名
       * @param {number} min - 最小值
       * @param {number} max - 最大值
       */
      validateIntegerInput(value, row, field, min = 0, max = 999999) {
        // 允许空值和部分输入（如正在输入的数字）
        if (value === '' || value === '-') {
          return
        }

        // 移除所有非数字字符（除了负号）
        let cleanValue = value.replace(/[^-\d]/g, '')

        // 确保负号只能在开头
        if (cleanValue.indexOf('-') > 0) {
          cleanValue = cleanValue.replace(/-/g, '')
        }

        // 如果有值，转换为整数
        if (cleanValue !== '' && cleanValue !== '-') {
          const numValue = parseInt(cleanValue, 10)

          // 检查范围
          if (numValue < min) {
            row[field] = min
          } else if (numValue > max) {
            row[field] = max
          } else {
            row[field] = numValue
          }
        }
      },

      /**
       * 验证浮点数输入（输入时验证）
       * @param {string} value - 输入值
       * @param {Object} row - 当前行数据
       * @param {string} field - 字段名
       * @param {number} min - 最小值
       * @param {number} max - 最大值
       */
      validateFloatInput(value, row, field, min = 0, max = 999999.99) {
        // 允许空值和部分输入（包括单独的小数点、负号等）
        if (value === '' || value === '-' || value === '.' || value === '-.') {
          row[field] = value
          return
        }

        // 移除无效字符，只保留数字、小数点和负号
        let cleanValue = value.replace(/[^-\d.]/g, '')

        // 确保负号只能在开头
        if (cleanValue.indexOf('-') > 0) {
          cleanValue = cleanValue.replace(/-/g, '')
        }

        // 确保只有一个小数点
        const parts = cleanValue.split('.')
        if (parts.length > 2) {
          cleanValue = parts[0] + '.' + parts.slice(1).join('')
        }

        // 限制小数位数为2位（但允许继续输入）
        if (parts.length === 2 && parts[1].length > 2) {
          cleanValue = parts[0] + '.' + parts[1].substring(0, 2)
        }

        // 更新字段值，但不进行范围检查（留到blur时处理）
        row[field] = cleanValue
      },

      /**
     * 验证并格式化浮点数（失焦时验证）
     * @param {Object} row - 当前行数据
     * @param {string} field - 字段名
     * @param {number} min - 最小值
     * @param {number} max - 最大值
     * @param {number} precision - 小数位数，默认2位
     */
    validateAndFormatFloatOnBlur(row, field, min = 0, max = 999999.99, precision = 2) {
      const value = row[field]

      // 如果是空值或无效输入，设置为最小值
      if (value === '' || value === '.' || value === '-' || value === '-.' || isNaN(parseFloat(value))) {
        row[field] = min
        return
      }

      const numValue = parseFloat(value)

      // 范围检查
      if (numValue < min) {
        row[field] = min
      } else if (numValue > max) {
        row[field] = max
      } else {
        // 格式化为指定小数位数
        const multiplier = Math.pow(10, precision)
        const roundedValue = Math.round(numValue * multiplier) / multiplier
        row[field] = roundedValue
      }
    },

    /**
     * 判断行是否可编辑
     * @description 根据数据来源判断物料明细行是否允许编辑，远程数据（订单ID获取）不可编辑
     * @param {MaterialDetailRecord} row - 物料明细行数据
     * @returns {boolean} 是否可编辑，true表示可编辑，false表示不可编辑
     */
    isRowEditable(row) {
      // 如果没有数据来源信息，默认可编辑
      if (!row || !row.dataSource) {
        return true
      }

      // 只有导入的物料可以编辑，远程数据（订单ID获取）不可编辑
      return row.dataSource === MaterialDetailDataSource.IMPORTED
    },

    /**
     * 远程搜索物料
     * @description 根据关键词远程搜索物料数据，支持防抖处理
     * @param {string} query - 搜索关键词
     * @returns {void}
     */
    remoteSearchMaterial(query) {
      // 清除之前的定时器
      if (this.searchTimer) {
        clearTimeout(this.searchTimer)
      }

      // 如果查询为空，清空选项
      if (!query) {
        this.materialOptions = []
        return
      }

      // 设置防抖定时器
      this.searchTimer = setTimeout(async () => {
        await this.searchMaterials(query)
      }, 300)
    },

    /**
     * 搜索物料数据
     * @description 调用API搜索物料数据
     * @param {string} keyword - 搜索关键词
     * @returns {Promise<void>}
     * @throws {Error} 当API调用失败时抛出异常
     */
    async searchMaterials(keyword) {
      try {
        this.materialLoading = true

        const response = await getMaterialFullList({
          itemName: keyword
        })

        if (response?.data?.success && response.data.data) {
          // 转换API返回的字段名称为组件所需的格式
          // getMaterialFullList返回的是SalesOrderItemListRecord[]数组
          this.materialOptions = response.data.data.map(item => ({
            id: item.id,
            itemId: item.Item_ID,
            itemCode: item.Item_Code,
            itemName: item.Item_Name,
            specs: item.Item_PECS || '',
            unit: item.InventoryInfo_Name,
            mainItemCategoryName: item.MainItemCategory_Name,
            mainItemCategoryId: item.MainItemCategory_ID,
            mainItemCategoryCode: item.MainItemCategory_Code,
            unitPrice: item.Item_Price || '0',
            description: item.Item_Description || '',
            warehouseId: item.Warehouse_ID,
            warehouseCode: item.Warehouse_Code,
            warehouseName: item.Warehouse_Name,
            orgId: item.ORG_ID,
            orgCode: item.ORG_CODE,
            orgName: item.ORG_NAME,
            // 保留原始数据以备后用
            _raw: item
          }))
        } else {
          this.materialOptions = []
          const errorMsg = response?.data?.msg || '搜索物料失败'
          this.$message.warning(errorMsg)
        }
      } catch (error) {
        this.materialOptions = []
        this.$message.error('网络错误，搜索物料失败')
      } finally {
        this.materialLoading = false
      }
    },

    /**
     * 处理导入选中物料
     * @description 将选中的物料导入到物料明细表中
     * @returns {void}
     */
    handleImportSelectedMaterial() {
      if (!this.selectedMaterialId) {
        this.$message.warning('请先选择要导入的物料')
        return
      }
  
      // 查找选中的物料数据
      const selectedMaterial = this.materialOptions.find(item => item.id === this.selectedMaterialId)
      if (!selectedMaterial) {
        this.$message.warning('未找到选中的物料数据')
        return
      }
  
      // 检查是否已存在相同物料
      const existingMaterial = this.materialDetails.find(item => item.itemCode === selectedMaterial.itemCode)
      if (existingMaterial) {
        this.$message.warning(`物料 ${selectedMaterial.itemName} 已存在，请勿重复导入`)
        return
      }
  
      // 构造物料明细数据
      let materialDetail = this.prepareMaterialDetailData(selectedMaterial)
      
      // 导入时自动计算金额
      materialDetail = this.calculateAmounts(materialDetail)
  
      // 触发导入事件
      this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_IMPORT, [materialDetail])
      this.$emit(MATERIAL_DETAIL_EVENTS.REFRESH)
  
      // 清空选择
      this.selectedMaterialId = null
      this.materialOptions = []
    },

    /**
     * 准备物料明细数据
     * @description 将选中的物料数据转换为物料明细表所需的格式
     * @param {import('@/api/types/order').SalesOrderItemListRecord} material - 物料数据（来自getMaterialFullList API）
     * @returns {MaterialDetailRecord} 格式化后的物料明细数据
     * @private
     */
    prepareMaterialDetailData(material) {
      return {
        id: this.generateUniqueId(),
        itemId: material.itemId,
        itemCode: material.itemCode,
        itemName: material.itemName,
        specs: material.specs || '',
        specification: material.specs || '',
        unit: material.unit || '',
        mainItemCategoryName: material.mainItemCategoryName || material.MainItemCategory_Name || '',
        mainItemCategoryId: material.mainItemCategoryId || material.MainItemCategory_ID,
        mainItemCategoryCode: material.mainItemCategoryCode || material.MainItemCategory_Code || '',
        description: material.description || '',
        warehouseId: material.warehouseId,
        warehouseCode: material.warehouseCode,
        warehouseName: material.warehouseName,
        orgId: material.orgId,
        orgCode: material.orgCode,
        orgName: material.orgName,
        unitPrice: material.unitPrice || 0,
        orderQuantity: 1,
        confirmQuantity: 1,
        availableQuantity: 0,
        taxRate: 0,
        taxAmount: 0,
        totalAmount: 0,
        itemStatus: MaterialDetailStatus.UNCONFIRMED,
        dataSource: MaterialDetailDataSource.IMPORTED,
        isDeletable: true,
        remark: ''
      }
    },

    /**
     * 生成唯一ID
     * @description 生成物料明细的唯一标识符
     * @returns {string} 唯一ID
     * @private
     */
    generateUniqueId() {
      return 'material_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
    },

    /**
     * 处理表格刷新事件
     * @description 触发刷新事件，通知父组件重新加载数据
     * @returns {void}
     * @emits refresh
     */
    handleRefresh() {
      this.$emit(MATERIAL_DETAIL_EVENTS.REFRESH)
    },



    /**
     * 处理分页页码变化事件
     * @description 当用户切换页码时触发，更新当前页码
     * @param {number} currentPage - 新的页码，从1开始
     * @returns {void}
     */
    handleCurrentChange(currentPage) {
      this.page.currentPage = currentPage
    },

    /**
     * 处理分页大小变化事件
     * @description 当用户改变每页显示条数时触发，重置到第一页
     * @param {number} pageSize - 新的每页显示条数
     * @returns {void}
     */
    handleSizeChange(pageSize) {
      this.page.pageSize = pageSize
      this.page.currentPage = 1
    },

    /**
     * 格式化浮点数显示
     * @description 格式化浮点数为4位小数的字符串
     * @param {number|string|null|undefined} value - 数值
     * @returns {string} 格式化后的字符串
     */
    formatFloatNumber(value) {
      return formatFloatNumber(value)
    },

    /**
     * 格式化金额显示
     * @description 格式化金额为带货币符号的字符串
     * @param {number|string|null|undefined} amount - 金额数值
     * @param {boolean} withSymbol - 是否显示货币符号
     * @returns {string} 格式化后的金额字符串
     */
    formatAmount(amount, withSymbol = true) {
      return formatAmount(amount, withSymbol)
    },

    formatUnitPrice,
    formatTaxRate,

    /**
     * 格式化整数显示
     * @description 格式化整数为字符串
     * @param {number|string|null|undefined} value - 整数数值
     * @returns {string} 格式化后的整数字符串
     */
    formatIntegerNumber(value) {
      return formatIntegerNumber(value)
    },

    /**
     * 获取状态标签类型
     * @description 根据物料明细状态值返回对应的Element UI标签类型
     * @param {typeof MaterialDetailStatus[keyof typeof MaterialDetailStatus]} itemStatus - 物料明细状态值
     * @returns {string} Element UI标签类型
     * @example
     * getStatusTagType(0) // 返回 'warning'
     * getStatusTagType(1) // 返回 'success'
     */
    getStatusTagType(itemStatus) {
      return getMaterialDetailStatusTagType(itemStatus)
    },

    /**
     * 获取状态文本
     * @description 根据物料明细状态值返回对应的中文描述
     * @param {number} itemStatus - 物料明细状态值
     * @returns {string} 状态的中文描述文本
     * @example
     * getStatusText(0) // 返回 '待确认'
     * getStatusText(1) // 返回 '已确认'
     */
    getStatusText(itemStatus) {
      return getMaterialDetailStatusLabel(itemStatus)
    },

    /**
      * 处理删除物料操作
      * @description 删除指定的物料明细记录，仅允许删除可删除的物料
      * @param {MaterialDetailRecord} row - 要删除的物料明细记录
      * @param {number} index - 记录在当前页的索引位置
      * @returns {void}
      * @emits material-delete
      */
     async handleDeleteMaterial(row, index) {
       try {
         await this.$confirm(
           `确定要删除物料 "${row.itemName}" 吗？`,
           '删除确认',
           {
             confirmButtonText: '确定',
             cancelButtonText: '取消',
             type: 'warning'
           }
         )

         // 触发删除事件，传递物料记录和索引
         this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_DELETE, { row, index })
         this.$message.success('物料删除成功')
       } catch (error) {
         // 用户取消删除操作
         if (error !== 'cancel') {
           this.$message.error('删除操作失败')
         }
       }
     },

    /**
     * 处理表格行删除事件
     * @description AvueJS表格的删除事件处理器，委托给自定义删除方法
     * @param {MaterialDetailRecord} row - 要删除的行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleRowDelete(row, index) {
      this.handleDeleteMaterial(row, index)
    },

    /**
     * 处理行更新事件
     * @description 当用户编辑表格行数据时触发，执行自动计算逻辑
     * @param {MaterialDetailRecord} row - 更新后的行数据
     * @param {number} index - 行索引
     * @param {boolean} done - 完成回调函数
     * @returns {void}
     * @emits material-update
     */
    async handleRowUpdate(row, index, done) {
      try {
        // 执行自动计算
        const calculatedRow = this.calculateAmounts(row)

        // 触发更新事件，传递计算后的数据
        this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_UPDATE, { row: calculatedRow, index })

        // 完成编辑
        done(calculatedRow)

        this.$message.success('物料明细更新成功')
      } catch (error) {
        this.$message.error('更新失败：' + error.message)
        done(false)
      }
    },

    /**
     * 处理订单数量失焦事件
     * @description 当订单数量输入框失焦时，触发数量变更处理
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleQuantityBlur(row, index) {
      // 如果 index 无效，尝试通过 row 数据找到正确的索引
      const actualIndex = this.findRowIndex(row, index)
      this.handleQuantityChange(row, actualIndex)
    },

    /**
     * 处理订单数量变更
     * @description 当订单数量发生变化时，自动计算总金额和税额，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleQuantityChange(row, index) {
      const calculatedRow = this.calculateAmounts(row)
      Object.assign(row, calculatedRow)
      this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_UPDATE, { row, index })
    },

    /**
     * 处理税率变更
     * @description 当税率发生变化时，重新计算税额，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleTaxRateChange(row, index) {
      this.calculateTaxAmount(row)
      this.$emit('material-update', { row, index })
    },

    /**
     * 处理单价失焦事件
     * @description 当单价输入框失焦时，先格式化数值，再计算总金额和税额，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleUnitPriceBlur(row, index) {
      // 先格式化数值
      this.validateAndFormatFloatOnBlur(row, 'unitPrice')
      // 如果 index 无效，尝试通过 row 数据找到正确的索引
      const actualIndex = this.findRowIndex(row, index)
      // 再处理单价变更
      this.handleUnitPriceChange(row, actualIndex)
    },

    /**
     * 处理单价变更
     * @description 当单价发生变化时，自动计算总金额和税额，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleUnitPriceChange(row, index) {
      const calculatedRow = this.calculateAmounts(row)
      Object.assign(row, calculatedRow)
      this.$emit('material-update', { row, index })
    },

    /**
     * 处理税额变更
     * @description 当税额手动修改时，反推税率，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleTaxAmountChange(row, index) {
      // 当税额手动修改时，反推税率
      if (row.totalAmount && row.totalAmount > 0) {
        row.taxRate = ((row.taxAmount || 0) / row.totalAmount * 100).toFixed(2)
      }
      this.$emit('material-update', { row, index })
    },

    /**
     * 处理总金额变更
     * @description 当总金额手动修改时，重新计算税额，并触发父组件重新计算订单总计
     * @param {MaterialDetailRecord} row - 行数据
     * @param {number} index - 行索引
     * @returns {void}
     */
    handleTotalAmountChange(row, index) {
      // 当总金额手动修改时，重新计算税额
      this.calculateTaxAmount(row)
      this.$emit('material-update', { row, index })
    },

    /**
     * 处理单元格编辑开始事件
     * @description 当用户开始编辑单元格时触发
     * @param {MaterialDetailRecord} row - 编辑的行数据
     * @param {string} prop - 编辑的属性名
     * @param {*} value - 当前值
     * @returns {void}
     */
    handleCellEditStart(row, prop, value) {
      // 记录编辑前的值，用于计算变化
      this.editingRow = { ...row }
      this.editingProp = prop
    },

    /**
     * 处理单元格编辑结束事件
     * @description 当用户结束编辑单元格时触发，执行实时计算
     * @param {MaterialDetailRecord} row - 编辑后的行数据
     * @param {string} prop - 编辑的属性名
     * @param {*} value - 新值
     * @returns {void}
     */
    handleCellEditEnd(row, prop, value) {
      // 如果编辑的是影响计算的字段，执行自动计算
      if (['orderQuantity', 'unitPrice', 'taxRate'].includes(prop)) {
        const calculatedRow = this.calculateAmounts(row)

        // 更新行数据
        Object.assign(row, calculatedRow)

        // 触发更新事件
        this.$emit(MATERIAL_DETAIL_EVENTS.MATERIAL_UPDATE, { row: calculatedRow, index: this.getCurrentRowIndex(row) })
      }
    },

    /**
     * 自动计算金额
     * @description 根据订单数量、单价和税率自动计算总金额和税额，使用精确计算避免浮点数精度问题
     * @param {MaterialDetailRecord} row - 物料明细记录
     * @returns {MaterialDetailRecord} 计算后的物料明细记录
     */
    calculateAmounts(row) {
      const calculatedRow = { ...row }

      // 验证并获取数值
      const quantityValidation = validateNumber(calculatedRow.orderQuantity)
      const priceValidation = validateNumber(calculatedRow.unitPrice)
      const rateValidation = validateNumber(calculatedRow.taxRate)

      const orderQuantity = quantityValidation.isValid ? Math.round(quantityValidation.value) : 0
      const unitPrice = priceValidation.isValid ? priceValidation.value : 0
      const taxRate = rateValidation.isValid ? rateValidation.value : 0

      // 使用精确计算：订单数量 * 单价
      const totalAmount = preciseMultiply(orderQuantity, unitPrice)
      calculatedRow.totalAmount = preciseRound(totalAmount, 2)

      // 使用精确计算：总金额 * 税率 / 100
      const taxAmount = preciseMultiply(totalAmount, preciseDivide(taxRate, 100))
      calculatedRow.taxAmount = preciseRound(taxAmount, 2)

      return calculatedRow
    },

    /**
     * 计算税额
     * @description 根据总金额和税率计算税额，使用精确计算避免浮点数精度问题
     * @param {MaterialDetailRecord} row - 物料明细记录
     * @returns {void}
     */
    calculateTaxAmount(row) {
      const amountValidation = validateNumber(row.totalAmount)
      const rateValidation = validateNumber(row.taxRate)

      if (amountValidation.isValid && rateValidation.isValid) {
        const totalAmount = amountValidation.value
        const taxRate = rateValidation.value

        // 使用精确计算：总金额 * 税率 / 100
        const taxAmount = preciseMultiply(totalAmount, preciseDivide(taxRate, 100))
        row.taxAmount = preciseRound(taxAmount, 2)
      } else {
        row.taxAmount = 0
      }
    },

    /**
     * 获取当前行索引
     * @description 根据行数据获取在当前页中的索引
     * @param {MaterialDetailRecord} row - 行数据
     * @returns {number} 行索引
     */
    getCurrentRowIndex(row) {
      return this.currentPageData.findIndex(item => item.id === row.id)
    },

    /**
      * 查找行索引
      * @description 根据行数据查找在物料明细列表中的正确索引
      * @param {MaterialDetailRecord} row - 行数据
      * @param {number} providedIndex - 提供的索引
      * @returns {number} 实际索引
      */
     findRowIndex(row, providedIndex) {
       // 如果提供的索引有效，直接使用
       if (providedIndex >= 0 && providedIndex < this.materialDetails.length) {
         return providedIndex
       }

       // 否则通过行数据查找索引
       const index = this.materialDetails.findIndex(item => {
         // 优先使用 id 进行匹配
         if (row.id && item.id) {
           return row.id === item.id
         }
         // 如果没有 id，使用物料编码进行匹配
         if (row.itemCode && item.itemCode) {
           return row.itemCode === item.itemCode
         }
         // 最后使用对象引用进行匹配
         return row === item
       })

       return index >= 0 ? index : -1
     }
  },

  /**
   * 组件销毁前的清理工作
   * @description 清除定时器，避免内存泄漏
   */
  beforeDestroy() {
    if (this.searchTimer) {
      clearTimeout(this.searchTimer)
      this.searchTimer = null
    }
  }
}
</script>

<style scoped>
.material-detail-container {
  padding: 20px;
}

.material-detail-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.section-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.count-tag {
  font-size: 12px;
}

.header-right {
  display: flex;
  gap: 8px;
}

.material-select-container {
  display: flex;
  align-items: center;
  gap: 8px;
}

.material-select-container .el-select {
  min-width: 300px;
}

.material-select-container .el-button {
  white-space: nowrap;
}

.material-detail-content {
  background-color: #ffffff;
  border-radius: 4px;
}

.delete-btn {
  color: #f56c6c;
}

.delete-btn:hover {
  color: #f78989;
}

.amount-text {
  font-weight: 600;
  color: #409eff;
}

.dialog-footer {
  text-align: right;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .material-detail-container {
    padding: 12px;
  }

  .material-detail-header {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }

  .header-right {
    width: 100%;
    justify-content: flex-end;
  }
}
</style>

