<template>
  <div class="product-detail"  v-loading="productDetailLoading">
    <div v-if="loading" class="loading">
      <i class="el-icon-loading" aria-label="加载中" role="img"></i>
      加载中...
    </div>
      
    <div v-else-if="product" class="detail-container">  
      <h2 style="margin: 10px; text-align: left;margin-top: 28px;">商品详情-选择矿机</h2>
      <section class="pay-methods" aria-label="支付方式">
        <div class="pay-label" tabindex="0" aria-label="支付方式标签">支付方式：</div>
        <ul class="pay-list" role="list" aria-label="支付方式列表">
          <li
            v-for="(item, index) in paymentMethodList"
            :key="index"
            class="pay-item"
            :aria-label="`支付方式： ${item.payChain}`"
          >
        
            <el-tooltip :content="formatPayTooltip(item)" placement="top" :open-delay="80">
              <img
                class="pay-icon"
                :src="getPayImageUrl(item)"
                :alt="`${(item.payChain || '').toUpperCase()} ${(item.payCoin || '').toUpperCase()}`.trim()"
                :title="formatPayTooltip(item)"
                tabindex="0"
                role="img"
                @keydown.enter.prevent="handlePayIconKeyDown(item)"
                @keydown.space.prevent="handlePayIconKeyDown(item)"
              />
            </el-tooltip>
          </li>
        </ul>
      </section>
      <!-- 筛选栏 -->
      <section class="filter-bar" aria-label="筛选条件">
        <div class="filter-grid">
          <!-- 矿机种类：放在支付方式筛选前面 -->
          <div class="filter-cell">
            <label class="filter-title">矿机种类</label>
            <div style="display:inline-flex;align-items:center;">
              <el-radio-group v-model="machineType" size="small" @change="handleMachineTypeChange">
                <el-radio-button :label="1">GPU</el-radio-button>
                <el-radio-button :label="0">ASIC</el-radio-button>
              </el-radio-group>
            </div>
          </div>
          <!-- 支付方式筛选：选择即触发查询 -->
          <div class="filter-cell">
            <label class="filter-title" for="payFilter">支付方式筛选</label>
            <el-select
              id="payFilter"
              v-model="selectedPayKey"
              placeholder="全部"
              clearable
              filterable
              size="small"
              class="filter-control"
              @change="handlePayFilterChange"
              style="max-width: 260px;"
            >
              <template #prefix>
                <img
                  v-if="getSelectedPayIcon()"
                  :src="getSelectedPayIcon()"
                  alt=""
                  style="width:16px;height:16px;border-radius:3px;margin-right:6px;"
                />
              </template>
              <el-option
                v-for="(opt, i) in paymentMethodList"
                :key="i"
                :label="formatPayTooltip(opt)"
                :value="`${opt.payChain || ''}|${opt.payCoin || ''}`"
              >
                <div class="pay-opt">
                  <img :src="getPayImageUrl(opt)" class="pay-icon" alt="" />
                  <span>{{ (opt.payChain || '').toUpperCase() }} - {{ (opt.payCoin || '').toUpperCase() }}</span>
                </div>
              </el-option>
            </el-select>
          </div>

          <!-- 价格区间 -->
          <div class="filter-cell center-title">
            <label class="filter-title">单价区间<span v-if="getPriceCoinSymbol()">（{{ getPriceCoinSymbol() }}）</span></label>
            <div class="range-controls">
              <el-input-number v-model="filters.minPrice" :min="0" :step="1" :precision="0" :controls="false" size="small" class="filter-control" />
              <span class="filter-sep">-</span>
              <el-input-number v-model="filters.maxPrice" :min="0" :step="1" :precision="0" :controls="false" size="small" class="filter-control" />
            </div>
          </div>

          <!-- 操作按钮 -->
          <div class="filter-cell filter-actions">
            <div class="action-row">
                <el-button type="primary" size="small" @click="handleSearchFilters" aria-label="执行筛选">筛选查询</el-button>
                <el-button size="small" @click="handleResetFilters" aria-label="重置筛选">重置</el-button>
              </div>
            </div>
          </div>
      </section>
      <!-- 动态表格（基于后端返回的 columns/rows 渲染） -->
      <section v-if="dynamicColumns && dynamicColumns.length" class="dynamic-hashrate" aria-label="动态收益表">
        <el-table
          :data="dynamicRows"
          border
          stripe
          size="small"
          class="dynamic-table"
          :header-cell-style="{ textAlign: 'left' }"
          :cell-style="{ textAlign: 'left' }"
        >
          <!-- 勾选框列（首列） -->
          <el-table-column width="46" fixed="left">
            <template #default="{ row }">
              <el-checkbox
                v-model="row._selected"
                :title="isRowDisabled(row) ? (row && (row.saleState === 1 || row.saleState === 2) ? '该机器已售出或售出中，无法选择' : '该机器暂无价格，无法选择') : '选择该矿机'"
                :disabled="isRowDisabled(row)"
                @change="checked => handleManualSelectFlat(row, checked)"
              />
            </template>
          </el-table-column>
          <el-table-column
            v-for="(col, colIdx) in getRenderedColumns()"
            :key="col.key || colIdx"
            :prop="col.key"
            :label="col.label"
            :fixed="col.fixed || false"
            show-overflow-tooltip
          >
            <template #header>
              <div class="col-header" :title="col.label">
                <img v-if="col.icon" :src="col.icon" class="col-icon" alt="" />
                <span>{{ col.label }}</span>
                <!-- 算力列标题不再展示单位，仅展示图标和名称 -->
                <el-button
                  v-if="isLastHashrateColumn(colIdx)"
                  type="text"
                  class="more-action"
                  @click.stop="handleOpenDynamicSearch"
                >更多</el-button>
              </div>
            </template>
            <template #default="{ row }">
              <span :class="getCellClass(col)">
                <el-tooltip
                  v-if="formatDynamicCell(row, col).truncated"
                  :content="formatDynamicCell(row, col).full"
                  placement="top"
                >
                  <span>{{ formatDynamicCell(row, col).text }}</span>
                </el-tooltip>
                <span v-else>{{ formatDynamicCell(row, col).text }}</span>
              </span>
            </template>
          </el-table-column>
          <!-- 仅在 ASIC 时显示：总机器数量、已售数量 -->
          <el-table-column v-if="machineType === 0" prop="saleNumbers" label="总机器数">
            <template #default="scope">
              <span>{{ scope.row.saleNumbers != null ? scope.row.saleNumbers : '—' }}</span>
            </template>
          </el-table-column>
          <el-table-column v-if="machineType === 0" prop="saleOutNumbers" label="已售数量">
            <template #default="scope">
              <span>{{ scope.row.saleOutNumbers != null ? scope.row.saleOutNumbers : '—' }}</span>
            </template>
          </el-table-column>
      
          <!-- 租赁天数：始终显示，用户手动填写 -->
          <el-table-column prop="leaseTime" label="租赁天数(天)">
            <template #default="scope">
              <el-input-number
                class="input-full"
                v-model="scope.row.leaseTime"
                :min="1"
                :max="getRowMaxLeaseDays(scope.row)"
                :precision="0"
                :step="1"
                :controls="false"
                size="mini"
                @change="val => handleLeaseDaysChange(scope.row, val)"
              />
            </template>
          </el-table-column>
              <!-- ASIC 专用：购买数量，用户输入 -->
              <el-table-column v-if="machineType === 0" prop="purchaseQuantity" label="购买数量">
            <template #default="scope">
              <el-input-number
                class="input-full"
                v-model="scope.row.purchaseQuantity"
                :min="1"
                :max="getRowMaxPurchase(scope.row)"
                :precision="0"
                :step="1"
                :controls="false"
                size="mini"
                :disabled="getRowMaxPurchase(scope.row) <= 0"
                @change="val => handlePurchaseQuantityChange(scope.row, val)"
              />
            </template>
          </el-table-column>
          <!-- 总价：ASIC=价格*天数*购买数量；GPU=价格*天数 -->
          <el-table-column prop="totalAmount" label="总价" header-align="left" align="left">
            <template #default="scope">
              <span class="price-strong">{{ formatConfirmTotalText(scope.row) }}</span>
            </template>
          </el-table-column>
        </el-table>

        <!-- 动态表格 - 搜索弹窗 -->
        <el-dialog
          title="搜索币种/算法"
          :visible.sync="dynamicSearch.visible"
          width="420px"
        >
          <div class="dynamic-search-bar" style="display:flex;gap:10px;align-items:center;">
            <el-input
              v-model="dynamicSearch.keyword"
              placeholder="输入币种代码或算法关键词"
              clearable
              @keyup.enter.native="handleConfirmDynamicSearch"
            />
            <el-button type="primary" @click="handleConfirmDynamicSearch">搜索</el-button>
        </div>
        </el-dialog>
      </section>


      <div style="margin: 18px; text-align: right;">
        <el-button type="primary" size="small" @click="handleOpenAddToCartDialog">加入购物车</el-button>
      </div>

      <!-- 确认加入购物车弹窗 -->
      <el-dialog :visible.sync="confirmAddDialog.visible" width="70vw" :title="`确认加入购物车（共 ${confirmAddDialog.items.length} 台）`">
        <div>
          <el-table :data="confirmAddDialog.items" height="360" border stripe :header-cell-style="{ textAlign: 'left' }" :cell-style="{ textAlign: 'left' }">
            <el-table-column prop="model" label="型号" header-align="left" align="left" />
            <el-table-column prop="price" label="价格" header-align="left" align="left">
              <template #default="scope">
                <span class="price-strong">
                  <el-tooltip
                    v-if="formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).truncated"
                    :content="formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).full"
                    placement="top"
                  >
                    <span>{{ formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).text }}</span>
                  </el-tooltip>
                  <span v-else>{{ formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).text }}</span>
                </span>
              </template>
            </el-table-column>
            <el-table-column prop="leaseTime" label="租赁天数(天)" header-align="left" align="left">
              <template #default="scope">{{ Number(scope.row.leaseTime || 1) }}</template>
            </el-table-column>
            <el-table-column v-if="machineType === 0" prop="purchaseQuantity" label="购买数量" header-align="left" align="left">
              <template #default="scope">{{ Number(scope.row.purchaseQuantity || 0) }}</template>
            </el-table-column>
            <el-table-column prop="totalAmount" label="总价" header-align="left" align="left">
              <template #default="scope">
                <span class="price-strong">{{ formatConfirmTotalText(scope.row) }}</span>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <template #footer>
          <el-button @click="confirmAddDialog.visible = false">取消</el-button>
          <el-button type="primary" @click="handleConfirmAddSelectedToCart">确认加入</el-button>
        </template>
      </el-dialog>

      <el-row style="margin-bottom: 20px;">
        <el-col :span="24" style="display: flex; justify-content: center">
          <el-pagination
            style="margin: 0 auto; margin-top: 10px"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page.sync="currentPage"
            :page-sizes="pageSizes"
            :page-size="params.pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
          >
          </el-pagination>
        </el-col>
      </el-row>
    </div>

    <div v-else class="not-found">
      <h2>商品不存在</h2>
      <p>抱歉，您查找的商品不存在或已被删除。</p>
      <button @click="handleBack" class="back-btn">返回商品列表</button>
    </div>
  </div>
</template>

<script>

import Index from './index'
export default {
  name: 'ProductDetail',
  mixins: [Index],
  methods: {
    /**
     * 判断列是否为价格/金额相关列，以控制样式为红色
     * - 优先依据 col.type === 'amount'
     * - 其次依据 key 命名包含 'price' / 'amount'
     * - 再次依据 label 文案包含 '价' / '金额'
     * @param {Object} col
     * @returns {string} CSS 类名
     */
    getCellClass(col) {
      try {
        if (!col) return 'num-strong'
        if (String(col.type).toLowerCase() === 'amount') return 'price-strong'
        const key = String(col.key || '').toLowerCase()
        if (key.includes('price') || key.includes('amount')) return 'price-strong'
        const label = String(col.label || '')
        if (label.includes('价') || label.includes('金额')) return 'price-strong'
        return 'num-strong'
      } catch (e) {
        return 'num-strong'
      }
    },
    /**
     * 纯字符串方式相乘，避免浮点误差
     * @param {Array<string|number>} values
     * @returns {string} 不带单位的结果字符串，精确还原小数位
     */
    multiplyAsDecimal(values) {
      const toIntScale = (n) => {
        const s = String(n || 0).trim()
        if (!s.includes('.')) return { int: BigInt(s || '0'), scale: 0 }
        const [w, f] = s.split('.')
        const frac = (f || '').replace(/[^0-9]/g, '')
        const whole = (w || '0').replace(/[^0-9-]/g, '')
        const sign = whole.startsWith('-') ? '-' : ''
        const intStr = (sign ? whole.slice(1) : whole) + frac
        const safe = intStr.replace(/^0+(?=\d)/, '') || '0'
        return { int: BigInt(sign + safe), scale: frac.length }
      }
      let acc = 1n
      let scale = 0
      for (const v of values) {
        const { int, scale: sc } = toIntScale(v)
        acc = acc * int
        scale += sc
      }
      const neg = acc < 0n
      const absStr = (neg ? (-acc) : acc).toString()
      if (scale === 0) return (neg ? '-' : '') + absStr
      const pad = scale - absStr.length
      const s = pad > 0 ? ('0'.repeat(pad) + absStr) : absStr
      const i = s.length - scale
      let out = s.slice(0, i) + '.' + s.slice(i)
      // 去除多余的前导/尾随零
      out = out.replace(/^(-?)0+(?=\d)/, '$1')
      out = out.replace(/\.?0+$/, '')
      if (out.startsWith('.')) out = '0' + out
      if (out === '' || out === '-') out = '0'
      return (neg ? '-' : '') + out
    },
    /**
     * 截断到最多6位小数（不四舍五入）
     * @param {string} s
     * @param {number} maxDecimals
     * @returns {string}
     */
    truncateDecimalString(s, maxDecimals = 6) {
      const str = String(s || '0')
      if (!str.includes('.')) return str
      const [w, f] = str.split('.')
      if (f.length <= maxDecimals) return str
      return `${w}.${f.slice(0, maxDecimals)}`
    },
    /**
     * 确认弹窗“总价”展示（附币种）
     * ASIC: price*leaseTime*purchaseQuantity；GPU: price*leaseTime
     * 采用字符串整数相乘，避免精度问题；展示最多6位小数，截断不四舍五入
     */
    formatConfirmTotalText(row) {
      try {
        const price = this.getDisplayPrice ? this.getDisplayPrice(row) : (row && row.price)
        const coin = (this.getDisplayPriceCoin && this.getDisplayPriceCoin(row)) || ''
        const lease = Number(row && row.leaseTime) || 1
        const nums = [price, lease]
        if (this.machineType === 0) {
          const qty = Number(row && row.purchaseQuantity) || 1
          nums.push(qty)
        }
        const mul = this.multiplyAsDecimal(nums)
        const text = this.truncateDecimalString(mul, 6)
        const unit = (coin || '').toString().toUpperCase()
        return unit ? `${text} ${unit}` : text
      } catch (e) {
        return '—'
      }
    },
    /**
     * 获取该行可购买的最大数量（<= 总机器数）
     * @param {Object} row
     * @returns {number}
     */
    getRowMaxPurchase(row) {
      try {
        const n = Number(row && row.saleNumbers)
        if (!Number.isFinite(n) || n < 0) return 0
        return Math.floor(n)
      } catch (e) { return 0 }
    },
    /**
     * 购买数量变更时，强制校验区间 [1, max] 且取整
     * @param {Object} row
     * @param {number} value
     */
    handlePurchaseQuantityChange(row, value) {
      try {
        const max = this.getRowMaxPurchase(row)
        let v = Number(value)
        if (!Number.isFinite(v)) v = 1
        if (v < 1) v = 1
        if (max > 0 && v > max) v = max
        v = Math.floor(v)
        this.$set(row, 'purchaseQuantity', v)
      } catch (e) {
        this.$set(row, 'purchaseQuantity', 1)
      }
    },
    /**
     * 行是否存在任意价格（用于禁用勾选）
     * 规则：
     * - 若存在 priceList，任一项的 price 非 null/undefined 即视为有价格
     * - 否则回退 row.price 是否有效
     */
    hasAnyPrice(row) {
      try {
        if (!row) {
          console.log('[hasAnyPrice] 行数据为空')
          return false
        }
        if (Array.isArray(row.priceList) && row.priceList.length) {
          const hasValidPrice = row.priceList.some(it => it && it.price !== null && it.price !== undefined)
          if (!hasValidPrice) {
            console.log(`[hasAnyPrice] 机器ID ${row.id || 'unknown'} priceList 中无有效价格:`, row.priceList)
          }
          return hasValidPrice
        }
        const v = row.price
        const hasPrice = v !== null && v !== undefined && v !== ''
        if (!hasPrice) {
          console.log(`[hasAnyPrice] 机器ID ${row.id || 'unknown'} row.price 无效:`, v)
        }
        return hasPrice
      } catch (e) {
        console.error('[hasAnyPrice] 异常:', e, row)
        return false
      }
    },
    /**
     * 该行是否应禁用选择：已售出/售出中 或 无价格
     */
    isRowDisabled(row) {
      try {
        if (!row) {
          console.log('[isRowDisabled] 行数据为空')
          return true
        }
        if (row.saleState === 1 || row.saleState === 2) {
          console.log(`[isRowDisabled] 机器ID ${row.id || 'unknown'} 已售出或售出中, saleState:`, row.saleState)
          return true
        }
        const hasPrice = this.hasAnyPrice(row)
        if (!hasPrice) {
          console.log(`[isRowDisabled] 机器ID ${row.id || 'unknown'} 无价格:`, {
            priceList: row.priceList,
            price: row.price,
            hasPriceList: Array.isArray(row.priceList) && row.priceList.length > 0
          })
        }
        return !hasPrice
      } catch (e) {
        console.error('[isRowDisabled] 异常:', e, row)
        return true
      }
    },
    /**
     * 获取行的最大可租赁天数
     * 规则：优先 row.maxLeaseDays；否则回退 365；保证区间 [1, 365]
     */
    getRowMaxLeaseDays(row) {
      const raw = (row && (row.maxLeaseDays || row.maxLeaseDay || row.max_lease_days)) || 365
      const n = Number(raw)
      if (!Number.isFinite(n)) return 365
      if (n < 1) return 1
      if (n > 365) return 365
      return Math.floor(n)
    },
    /**
     * 处理支付方式图片 URL（去除服务端可能带入的换行/空白）
     * @param {Object} item
     */
    getPayImageUrl(item) {
      try {
        const src = (item && item.payCoinImage) ? String(item.payCoinImage) : ''
        return src.trim()
      } catch (e) {
        return ''
      }
    },
    /**
     * 当前下拉框选中值对应的图标（用于 el-select 前缀展示）
     * @returns {string}
     */
    getSelectedPayIcon() {
      try {
        const key = this.selectedPayKey
        if (!key) return ''
        const [chain, coin] = String(key).split('|')
        const list = Array.isArray(this.paymentMethodList) ? this.paymentMethodList : []
        const hit = list.find(
          it => String(it && it.payChain).toUpperCase() === String(chain).toUpperCase()
            && String(it && it.payCoin).toUpperCase() === String(coin).toUpperCase()
        )
        return this.getPayImageUrl(hit)
      } catch (e) { return '' }
    },
    /**
     * 支付方式下拉变更：选择/清空即触发请求
     * @param {{payChain?: string, payCoin?: string}|null} val
     */
    handlePayFilterChange(val) {
      try {
        const s = typeof val === 'string' ? val : ''
        if (!s) {
          this.filters.chain = ''
          this.filters.coin = ''
        } else {
          const [chain, coin] = s.split('|')
          this.filters.chain = (chain || '').trim()
          this.filters.coin = (coin || '').trim()
        }
        this.handleSearchFilters()
      } catch (e) { /* noop */ }
    },
    /**
     * 组合筛选参数并请求数据
     */
    handleSearchFilters() {
      const params = this.buildQueryParams()
      this.fetchGetMachineInfo(params)
    },
    /**
     * 重置筛选
     */
    handleResetFilters() {
      // 仅重置“单价区间”的值，不影响支付方式筛选及其它条件
      this.filters.minPrice = null
      this.filters.maxPrice = null
      this.handleSearchFilters()
    },
    /**
     * 获取列表第一个条目的币种，安全返回大写字符串
     * 用于表头显示币种，避免空数组时报错
     */
    getFirstCoinSymbol() {
      try {
        const list = Array.isArray(this.machineList) ? this.machineList : []
        const coin = list.length && list[0] && list[0].coin ? String(list[0].coin) : ''
        return coin ? coin.toUpperCase() : ''
      } catch (e) {
        return ''
      }
    },
    /**
     * 获取价格单位（优先读取每行的 payCoin 字段）
     */
    getPriceCoinSymbol() {
      try {
        const list = Array.isArray(this.machineList) ? this.machineList : []
        // 寻找第一个存在 payCoin 的条目
        const item = list.find(it => it && it.payCoin)
        const unit = item && item.payCoin ? String(item.payCoin) : ''
        return unit ? unit.toUpperCase() : ''
      } catch (e) {
        return ''
      }
    },
    /**
     * 限制并校验租赁天数：区间 [1, max]，并取整
     */
    handleLeaseDaysChange(row, value) {
      const max = this.getRowMaxLeaseDays(row)
      let v = Number(value)
      if (!Number.isFinite(v)) v = 1
      if (v < 1) v = 1
      if (v > max) v = max
      v = Math.floor(v)
      this.$set(row, 'leaseTime', v)
    },
    /**
     * 组合 tooltip 展示内容：payChain - payCoin
     * @param {Object} item - 支付方式对象
     * @returns {string}
     */
    formatPayTooltip(item) {
      try {
        if (!item) return ''
        const chain = (item.payChain || '').toString().trim()
        const coin = (item.payCoin || '').toString().trim()
        if (chain && coin) return `${chain} - ${coin}`
        return chain || coin || ''
      } catch (err) {
        // eslint-disable-next-line no-console
        console.error('formatPayTooltip error:', err)
        return ''
      }
    },
    /**
     * 支付方式图标键盘可达性处理
     * @param {Object} item - 支付方式对象
     */
    handlePayIconKeyDown(item) {
      // 仅用于可达性保障与监控打点，避免无事件时的报错
      try {
        if (!item) return;
        // 简单输出，后续可接入埋点系统
        // eslint-disable-next-line no-console
        console.debug('[pay-icon-keydown]', item.payChain);
      } catch (err) {
        // eslint-disable-next-line no-console
        console.error('handlePayIconKeyDown error:', err);
      }
    },
    /**
     * 单层：切换勾选
     * @param {Object} row - 当前机器行
     * @param {boolean} checked - 勾选状态
     */
    handleManualSelectFlat(row, checked) {
      try {
        if (!row) return
        if (row.saleState === 1 || row.saleState === 2) {
          this.$message.warning('该机器已售出或售出中，无法选择')
          this.$set(row, '_selected', false)
          return
        }
        this.$set(row, '_selected', !!checked)
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error('handleManualSelectFlat error:', e)
      }
    },
    /**
     * 单层：行样式（售出态高亮）
     */
    handleGetRowClass({ row }) {
      if (!row) return ''
      return (row.saleState === 1 || row.saleState === 2) ? 'sold-row' : ''
    },
    /**
     * 覆盖 mixin 的多层版本：基于单层勾选打开确认弹窗
     */
    handleOpenAddToCartDialog() {
      const list = Array.isArray(this.dynamicRows) ? this.dynamicRows : []
      const picked = list.filter(it => !!it && !!it._selected)
      if (!picked.length) {
        this.$message.warning('请先勾选至少一台矿机')
        return
      }
      this.confirmAddDialog.items = picked.map(r => ({
        ...r,
        leaseTime: Number(r.leaseTime || 1),
        purchaseQuantity: Number(r.purchaseQuantity || 0)
      }))
      this.confirmAddDialog.visible = true
    }
  }
}
</script>

<style scoped>
.product-detail {
 width: 100%;
  margin: 0 auto;
}

/* 子表内：已在购物车的行高亮并禁用指针事件到复选框外区域，保留复选框样式显示为勾选 */
:deep(.in-cart-row) {
  background: #fafafa;
}

/* 强制让被标记为 in-cart 的行的复选框始终为勾选视觉，并禁用鼠标交互 */
:deep(.in-cart-row .el-checkbox.is-disabled .el-checkbox__inner) {
  background-color: #f5f7fa;
  border-color: #dcdfe6;
}

/* 内层表：已售出/售出中行禁用态高亮 */
:deep(.sold-row) {
  background: #fff5f5;
}


.loading {
  text-align: center;
  padding: 60px 20px;
  color: #666;
}

.back-section {
  margin-bottom: 24px;
  text-align: left;
  margin: 8px;
}

.back-btn {
  background: #6c757d;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s ease;
}

.back-btn:hover {
  background: #5a6268;
}

.detail-container {
  width: 100%;
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.product-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  padding: 40px;
}

.product-image-section {
  display: flex;
  justify-content: center;
  align-items: center;
}

.product-image {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.product-info-section {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.product-title {
  font-size: 28px;
  font-weight: 700;
  color: #2c3e50;
  margin: 0;
  line-height: 1.3;
}

.product-description {
  font-size: 16px;
  color: #666;
  line-height: 1.6;
  margin: 0;
}

.product-price-section {
  display: flex;
  align-items: center;
  gap: 12px;
}

.price-label {
  font-size: 16px;
  color: #666;
}

.product-price {
  font-size: 32px;
  font-weight: 700;
  color: #e74c3c;
}

.price-strong {
  font-weight: 700;
  color: #e74c3c;
}

.num-strong {
  font-weight: inherit;
  color: inherit;
}

/* 支付方式区域（视觉更友好 + 可达性） */
.pay-methods {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  margin: 8px 10px 16px 10px;
  background: #f8fafc;
  border: 1px solid #eef2f7;
  border-radius: 8px;
}

.pay-label {
  color: #34495e;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.pay-list {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pay-item {
  display: inline-flex;
  align-items: center;
}

.pay-icon {
  width: 24px;
  height: 24px;
  display: block;
  border-radius: 4px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.pay-item-inner { display: inline-flex; align-items: center; gap: 8px; }
.pay-text { font-size: 12px; color: #2c3e50; }

.pay-icon:hover {
  transform: translateY(-1px);
}

.pay-icon:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.2);
}

/* 筛选栏样式 */
.filter-bar {
  background: #ffffff;
  border: 1px solid #eef2f7;
  border-radius: 8px;
  padding: 12px 16px;
  margin: 0 10px 16px 10px;
}
.filter-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  align-items: flex-end;
  justify-content: flex-start;
}
.filter-cell {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 6px;
}
.filter-cell.center-title .filter-title { text-align: center; }

.filter-title {
  font-size: 14px;
  color: #34495E;
  font-weight: 600;
  margin-bottom: 8px;

}
.filter-control {
  width: 100%;
  max-width: 320px;
}
.range-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}
.range-controls :deep(.el-input-number) { width: 150px; }
.pay-opt { display: inline-flex; align-items: center; gap: 8px; }
.filter-sep {
  color: #9aa4b2;
}
.filter-actions {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.action-row { display: inline-flex; align-items: center; gap: 10px; }

.filter-actions-inline {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: 12px;
}

/* 动态表格样式 */
.dynamic-hashrate { 
  margin: 10px; 
  background: #fff; 
  border: 1px solid #eef2f7; 
  border-radius: 8px; 
  padding: 10px; 
}
.dynamic-table :deep(.el-table__header th) {
  background: #fafcff;
}
.col-header { display: inline-flex; align-items: center; gap: 6px; }
.col-icon { width: 16px; height: 16px; border-radius: 3px; }
.col-unit { color: #94a3b8; font-size: 12px; }
.more-action { margin-left: 8px; color: #2563eb; font-weight: 600; }
.more-action { 
  font-size: 12px; 
  padding: 0 4px; 
  height: auto; 
  line-height: 1; 
  border: none; 
}
.more-action:hover { 
  color: #1d4ed8; 
  text-decoration: underline; 
}
.dynamic-search-bar :deep(.el-input__inner) { 
  font-size: 12px; 
}
.el-dialog__title { 
  font-size: 16px !important; 
  font-weight: 600; 
}
.input-full { width: 100%; }
:deep(.el-input-number.input-full) { width: 100%; }

@media (max-width: 1200px) {
  .filter-grid { grid-template-columns: repeat(2, minmax(220px, 1fr)); }
  .filter-cell--span-2 { grid-column: 1 / span 1; }
  .filter-actions { grid-column: 1 / -1; justify-content: flex-end; }
}

@media (max-width: 768px) {
  .filter-grid {
    grid-template-columns: 1fr;
  }
  .filter-actions { grid-column: 1 / 2; justify-content: flex-end; }
}

  /* 外层系列行：整行可点击 + 视觉增强 */
  :deep(.series-clickable-row) {
    cursor: pointer;
  }
  :deep(.series-clickable-row > td) {
    background: #f9fbff; /* 淡蓝背景区分层级 */
    padding-top: 14px;   /* 增加行高 */
    padding-bottom: 14px;
    border-bottom: 1px solid #eef2f7; /* 更柔和的分割线 */
  }
  :deep(.series-clickable-row:hover > td) {
    background: #f0f6ff; /* 悬浮更亮一些 */
  }
  /* 展开的内层区域容器样式：与外层形成卡片层级 */
  :deep(.el-table__expanded-cell) {
    background: #ffffff;
  }
  :deep(.el-table__expanded-cell .el-table) {
    background: #fff;
    border: 1px solid #eef2f7;
    border-radius: 8px;
    /* 优化：表格内容自适应宽度，减少横向滚动 */
    width: 100%;
  }

/* 列表标题上色：与上方支付方式背景做区分 */
/* 仅给最外层系列表头上色；内层子表不受影响 */
.series-table :deep(.el-table__header th) {
  background: #f9fbff;
  color: #34495e;
  font-weight: 600;
}

.quantity-section {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* 租赁天数单元格：提示 + 输入并排 */
/* 已移除行内提示样式，保留空位便于将来复用（不影响现有布局） */

.quantity-label {
  font-size: 16px;
  color: #666;
  min-width: 60px;
}

.quantity-controls {
  display: flex;
  align-items: center;
  border: 1px solid #ddd;
  border-radius: 6px;
  overflow: hidden;
}

.quantity-btn {
  background: #f8f9fa;
  border: none;
  padding: 12px 16px;
  cursor: pointer;
  font-size: 18px;
  font-weight: 600;
  color: #495057;
  transition: background 0.3s ease;
}

.quantity-btn:hover:not(:disabled) {
  background: #e9ecef;
}

.quantity-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.quantity-input {
  width: 80px;
  padding: 12px;
  border: none;
  text-align: center;
  font-size: 16px;
  outline: none;
}

.quantity-input::-webkit-outer-spin-button,
.quantity-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.quantity-input[type=number] {
  /* 标准属性，隐藏默认的数字输入控件样式 */
  appearance: textfield;
  /* 浏览器前缀，兼容性处理 */
  -webkit-appearance: none;
  -moz-appearance: textfield;
}

.quantity-input:focus {
  background: #f8f9fa;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .product-content {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 24px;
  }
  
  .product-detail {
    padding: 16px;
  }
  
  .product-title {
    font-size: 24px;
  }
  
  .product-price {
    font-size: 28px;
  }
  
  .quantity-selector {
    width: 100px;
    height: 32px;
  }
  
  .quantity-btn {
    width: 32px;
    height: 32px;
  }
  
  .quantity-input {
    height: 32px;
    font-size: 13px;
  }
  
  .btn-icon {
    font-size: 16px;
  }
}

/* 排序表头视觉样式 */
.sortable {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  color: #334155; /* slate-700 */
}
.sortable:hover {
  color: #1e293b; /* slate-800 */
}
.sort-arrow {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}
.sort-arrow.asc {
  border-bottom: 7px solid #64748b; /* slate-500 */
}
.sort-arrow.desc {
  border-top: 7px solid #64748b;
}
.sortable.active { color: #2563eb; } /* 蓝色高亮 */
.sort-arrow.active.sort-arrow.asc { border-bottom-color: #2563eb; }
.sort-arrow.active.sort-arrow.desc { border-top-color: #2563eb; }

.amount-more {
  font-size: 12px;
  color: #94a3b8; /* slate-400 */
  margin-left: 4px;
}


::v-deep .el-input__prefix, .el-input__suffix{
  top:24%;
}

::v-deep .el-input--mini .el-input__icon{
  line-height: 0px;
}
</style> 