<template>
  <div class="jd-order-list-root">
    <list-layout>
      <!-- 搜索区域 -->
      <template #search>
        <div class="jd-order-search-panel">
        <!-- 移动端：搜索表单部分 -->
        <mobile-search-form
          :model="queryParams"
          @search="handleQuery"
          @reset="resetQuery"
          @quick-search="handleQuickSearch"
        >
          <template #form="{ expanded }">
            <el-form 
              :model="queryParams" 
              :inline="true"
              class="jd-order-filter-form"
              label-width="76px"
              label-position="left"
            >
              <div v-if="isDesktopFilterCompact && showDesktopExpandedFilters" class="jd-filter-compact-collapse-row">
                <el-button type="text" size="small" class="jd-filter-compact-collapse-row__btn" @click="showDesktopExpandedFilters = false">
                  <i class="el-icon-arrow-up" />
                  收起筛选（基础条件 / 跟进状态 / 查询）
                </el-button>
              </div>

              <div v-if="isDesktopFilterCompact && !showDesktopExpandedFilters" class="jd-filter-compact-minimal">
                <el-input
                  v-model="queryParams.orderSearch"
                  placeholder="订单号 / 第三方单号 / 分销标识"
                  clearable
                  size="small"
                  class="jd-filter-compact-minimal__search"
                  @keyup.enter.native="handleQuery"
                />
                <div class="jd-filter-compact-minimal__actions">
                  <el-button type="primary" plain size="small" icon="el-icon-search" class="jd-filter-act-btn jd-filter-act-btn--primary" @click="handleQuery">搜索</el-button>
                  <el-button class="jd-tb-muted jd-filter-act-btn" plain size="small" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
                  <el-button class="jd-tb-muted jd-filter-act-btn" plain size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button>
                  <el-button type="text" size="small" class="jd-filter-compact-expand-btn" @click="showDesktopExpandedFilters = true">
                    <i class="el-icon-arrow-down" />
                    展开全部筛选
                  </el-button>
                </div>
              </div>

              <div
                v-show="!isDesktopFilterCompact || showDesktopExpandedFilters"
                class="jd-filter-group jd-filter-group--basic"
              >
                <div class="jd-filter-group-head">
                  <span class="jd-filter-group-title">基础条件</span>
                </div>
                <div class="jd-filter-group-body">
                  <el-form-item label="备注">
                    <el-input v-model="queryParams.remark" placeholder="单据备注" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="订单号">
                    <el-input v-model="queryParams.orderSearch" placeholder="订单号/第三方单号/分销标识" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="分销标记">
                    <el-input v-model="queryParams.distributionMark" placeholder="分销标记" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="型号">
                    <el-input v-model="queryParams.modelNumber" placeholder="型号（含店铺拼接也可搜）" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="店铺">
                    <el-select v-model="queryParams.modelShop" placeholder="全部" clearable filterable size="small" style="width: 140px">
                      <el-option v-for="opt in shopOptions" :key="opt.prefix" :label="opt.label" :value="opt.prefix" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="型号不含">
                    <el-input v-model="queryParams.modelNumberExclude" placeholder="多个用逗号或空格，如 130,645,90" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="下单人">
                    <el-input v-model="queryParams.buyer" placeholder="下单人" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="地址">
                    <el-input v-model="queryParams.address" placeholder="收货地址" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="状态">
                    <el-input v-model="queryParams.status" placeholder="备注/状态" clearable size="small" @keyup.enter.native="handleQuery" />
                  </el-form-item>
                  <el-form-item label="下单时间">
                    <el-date-picker
                      v-model="dateRange"
                      type="daterange"
                      start-placeholder="开始日期"
                      end-placeholder="结束日期"
                      value-format="yyyy-MM-dd"
                      size="small"
                      range-separator="至"
                      @change="handleDateRangeChange"
                    />
                  </el-form-item>
                  <el-form-item label="完成日期">
                    <el-checkbox v-model="queryParams.hasFinishTime" @change="handleQuery">仅显示已完成订单</el-checkbox>
                  </el-form-item>
                </div>
              </div>

              <div
                v-show="!isDesktopFilterCompact || showDesktopExpandedFilters"
                class="jd-filter-group jd-filter-group--status"
              >
                <div class="jd-filter-group-head">
                  <span class="jd-filter-group-title">跟进状态</span>
                </div>
                <div class="jd-filter-group-body jd-filter-group-body--status">
                  <el-form-item label="退款状态">
                    <el-select v-model="queryParams.isRefunded" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已退款" :value="1" />
                      <el-option label="未退款" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="退款到账">
                    <el-select v-model="queryParams.isRefundReceived" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已到账" :value="1" />
                      <el-option label="未到账" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="后返到账">
                    <el-select v-model="queryParams.isRebateReceived" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已到账" :value="1" />
                      <el-option label="未到账" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="点过价保">
                    <el-select v-model="queryParams.isPriceProtected" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已点价保" :value="1" />
                      <el-option label="未点价保" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="开过专票">
                    <el-select v-model="queryParams.isInvoiceOpened" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已开专票" :value="1" />
                      <el-option label="未开专票" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="晒过评价">
                    <el-select v-model="queryParams.isReviewPosted" placeholder="全部" clearable size="small" class="jd-filter-status-select">
                      <el-option label="已晒评价" :value="1" />
                      <el-option label="未晒评价" :value="0" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="后返表">
                    <el-select
                      v-model="rebateRemarkScreen"
                      placeholder="全部"
                      clearable
                      size="small"
                      class="jd-filter-rebate-select"
                      @change="onRebateRemarkScreenChange"
                    >
                      <el-option label="有导入记录" value="any" />
                      <el-option label="含异常项" value="abnormal" />
                      <el-option label="无异常项" value="ok" />
                      <el-option label="未关联后返表" value="noUploadLink" />
                    </el-select>
                  </el-form-item>
                </div>
              </div>

              <div
                v-show="!isDesktopFilterCompact || showDesktopExpandedFilters"
                class="jd-filter-group jd-filter-group--extra"
              >
                <div class="jd-filter-group-head">
                  <span class="jd-filter-group-title">查询</span>
                </div>
                <div class="jd-filter-group-body">
                  <el-form-item class="jd-filter-actions">
                    <el-button type="primary" plain size="small" icon="el-icon-search" class="jd-filter-act-btn jd-filter-act-btn--primary" @click="handleQuery">搜索</el-button>
                    <el-button class="jd-tb-muted jd-filter-act-btn" plain size="small" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
                    <el-button class="jd-tb-muted jd-filter-act-btn" plain size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button>
                  </el-form-item>
                </div>
              </div>
            </el-form>
          </template>
        </mobile-search-form>
        
        <!-- 操作按钮区域（移动端单独显示） -->
        <div v-if="actionButtons.length" class="action-buttons-section mobile-only">
          <mobile-button-group
            :buttons="actionButtons"
            :primary-count="2"
          />
        </div>
        
        <!-- 桌面端：克制的工具栏（低饱和 + plain） -->
        <div class="desktop-action-buttons desktop-only jd-order-toolbar">
          <div class="jd-toolbar-buttons">
          <el-button class="jd-tb-muted" plain size="small" icon="el-icon-setting" @click="showAutoWriteConfig = true" title="配置H-TF订单自动写入腾讯文档">腾峰文档配置</el-button>
          <el-button  type="primary"  plain size="small" icon="el-icon-monitor" @click="showPushMonitor = true" title="查看推送监控和历史记录">推送监控</el-button>
          <el-button class="jd-tb-muted" plain size="small" icon="el-icon-user" @click="showTouserConfig = true" title="配置分销标识对应的企业微信接收人">接收人配置</el-button>
          <el-button v-if="!isMobile" class="jd-tb-muted" plain size="small" icon="el-icon-scissors" :loading="modelShopMigrateLoading" @click="handleMigrateModelShop" title="按已配置店铺选项，将型号末尾前缀拆到「型号店铺」字段">拆分型号店铺</el-button>
          <el-button class="jd-tb-muted" plain size="small" icon="el-icon-check" @click="handleBatchMarkRebateReceived" :loading="batchMarkLoading" title="批量将赔付金额大于0的订单标记为后返到账（仅执行一次）">批量标记后返到账</el-button>
          <el-button v-if="!isMobile" type="primary" plain size="small" icon="el-icon-upload2" @click="rebateImportDialogVisible = true" title="可一次选多个 Excel，提交后由后台依次导入；详情见后返上传记录">导入后返表</el-button>
          <el-button v-if="!isMobile" class="jd-tb-muted" plain size="small" icon="el-icon-folder-opened" @click="openRebateUploadRecordDialog" title="查看历史上传的后返表原件并可重新下载">后返上传记录</el-button>
          <!-- <el-button class="jd-tb-muted" plain size="small" icon="el-icon-sort" @click="handleReverseSyncThirdPartyOrderNo" :loading="reverseSyncLoading" title="从腾讯文档第850行开始，通过物流链接反向匹配订单，将腾讯文档的单号列值写入到订单的第三方单号字段">反向同步第三方单号</el-button> -->
          <el-button v-if="!isMobile" type="primary" plain size="small" icon="el-icon-document-copy" @click="handleBatchCopyExcelText" :disabled="selectedRows.length === 0" title="批量复制选中订单的录单格式（Excel可粘贴）">批量复制录单格式</el-button>

          <el-button v-if="!isMobile" class="jd-tb-muted" plain size="small" icon="el-icon-document-copy" @click="handleBatchCopyRebateText" :disabled="selectedRows.length === 0" title="批量复制选中订单的后返录表格式（Excel可粘贴）">批量复制后返录表</el-button>
          <el-button v-if="!isMobile" class="jd-tb-muted" plain size="small" icon="el-icon-document-copy" @click="handleBatchCopySichuanCommerceText" :disabled="selectedRows.length === 0" title="批量复制选中订单的四川商贸录表格式（日期	型号	数量	地址	价格	备注	是否安排	物流）">四川商贸录表</el-button>
          <el-button v-if="!isMobile" class="jd-tb-muted" plain size="small" icon="el-icon-refresh" @click="handleBatchRecalcProfit" :disabled="selectedRows.length === 0" title="清除售价/利润手动锁定并按规则重算（依赖型号配置与当前付款、后返）">批量重算利润</el-button>
          </div>
        </div>
        </div>
      </template>

      <!-- 表格区域 -->
      <template #table>
        <div class="jd-order-table-page" :class="{ 'jd-order-table-page--mobile': isMobile }">
        <!-- 移动端卡片列表 -->
        <div v-if="isMobile" class="mobile-order-list" v-loading="loading">
          <div class="profit-summary-bar mobile-profit-summary">
            <div class="profit-summary-bar__main">
              <div>统计：<b>{{ profitSummaryLabel }}</b></div>
              <div>后返合计 <b>{{ toYuan(profitSummaryRebateTotal) }}</b> · 利润合计 <b>{{ profitSummaryProfitTotal === '' ? '—' : toYuan(profitSummaryProfitTotal) }}</b><span class="profit-summary-hint">（不含已退款）</span></div>
            </div>
            <div class="profit-summary-bar__status">
              <span class="order-status-stat">总 <b>{{ orderStatusStatTotal }}</b></span>
              <span class="order-status-stat order-status-stat--refund">退款 <b>{{ orderStatusStatRefunded }}</b></span>
              <span class="order-status-stat order-status-stat--shipped">已发货 <b>{{ orderStatusStatShipped }}</b></span>
              <span class="order-status-stat order-status-stat--pending">待发货 <b>{{ orderStatusStatPending }}</b></span>
            </div>
          </div>
          <div
            v-for="row in list"
            :key="row.id"
            class="mobile-order-card"
            :class="{ 'is-expanded': mobileExpandedOrderId === row.id }"
          >
            <!-- 卡片头部：点击左侧展开/收起详情 -->
            <div class="card-header">
              <div class="header-left header-left--tappable" @click="toggleMobileOrderExpand(row)">
                <i
                  class="mobile-card-chevron el-icon-arrow-right"
                  :class="{ 'is-open': mobileExpandedOrderId === row.id }"
                  aria-hidden="true"
                />
                <div class="header-title-block">
                  <div class="order-id">{{ row.orderId }}</div>
                  <el-tag 
                    v-if="row.orderStatus != null"
                    :type="getOrderStatusType(row.orderStatus)" 
                    size="mini">
                    {{ getOrderStatusText(row.orderStatus) }}
                  </el-tag>
                </div>
              </div>
              <div class="header-right" @click.stop>
                <el-dropdown 
                  trigger="click" 
                  placement="left"
                  @command="handleActionCommand"
                  :popper-class="'mobile-action-dropdown'">
                  <el-button 
                    type="primary" 
                    size="mini" 
                    icon="el-icon-more"
                    circle
                    class="mobile-action-btn"
                    @click.stop>
                  </el-button>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item 
                      :command="{action: 'copyOrderId', row: row}"
                      icon="el-icon-copy-document">
                      复制订单号
                    </el-dropdown-item>
                    <el-dropdown-item 
                      v-if="row.thirdPartyOrderNo"
                      :command="{action: 'copyThirdParty', row: row}"
                      icon="el-icon-copy-document">
                      复制第三方单号
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyAddress', row: row}"
                      icon="el-icon-copy-document">
                      复制地址
                    </el-dropdown-item>
                    <el-dropdown-item 
                      v-if="row.logisticsLink"
                      :command="{action: 'copyLogistics', row: row}"
                      icon="el-icon-copy-document">
                      复制物流链接
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyBasketShip', row: row}"
                      icon="el-icon-document-copy">
                      篮子发货摘要
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyReturn', row: row}"
                      icon="el-icon-document-copy">
                      退货复制
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyExcel', row: row}"
                      icon="el-icon-document-copy"
                      :class="{'is-copied': isExcelTextCopied(row.id)}">
                      {{ isExcelTextCopied(row.id) ? '✓ 录单格式（已复制）' : '录单格式' }}
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyRebate', row: row}"
                      icon="el-icon-document-copy">
                      后返录表
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'fetchLogistics', row: row}"
                      icon="el-icon-truck"
                      style="color: #67C23A;">
                      刷新物流
                    </el-dropdown-item>
                    <el-dropdown-item divided>
                      <div style="display: flex; align-items: center; justify-content: space-between; padding: 0 10px;">
                        <span>统计</span>
                        <el-switch
                          v-model="row.isCountEnabled"
                          :active-value="1"
                          :inactive-value="0"
                          @change="handleCountEnabledChange(row)"
                          size="mini"
                          style="margin-left: 10px;">
                        </el-switch>
                      </div>
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'delete', row: row}"
                      icon="el-icon-delete"
                      divided
                      style="color: #f56c6c;">
                      删除
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
              </div>
            </div>

            <div
              v-show="mobileExpandedOrderId !== row.id"
              class="card-summary-compact"
              @click="toggleMobileOrderExpand(row)"
            >
              <span class="card-summary-line">
                <template v-if="row.distributionMark">
                  <span
                    class="card-distribution-mark-highlight jd-dist-mark-summary-pill"
                    :style="distributionMarkDisplayStyle(row.distributionMark)"
                    role="button"
                    tabindex="0"
                    title="点击编辑分销标识"
                    @click.stop="openDistributionMarkEditDialog(row)"
                    @keydown.enter.prevent.stop="openDistributionMarkEditDialog(row)"
                  >{{ row.distributionMark }}</span>
                  <span class="card-summary-sep"> · </span>
                </template>
                <span class="card-summary-meta">{{ fullModelNumber(row) || '—' }} · 付{{ toYuan(row.paymentAmount) }} · 返{{ toYuan(row.rebateAmount) }}</span>
              </span>
            </div>

            <!-- 不使用 el-collapse-transition：避免展开后部分 WebView 上 height/overflow 异常导致无法聚焦输入框 -->
            <div v-show="mobileExpandedOrderId === row.id" class="card-content">
              <div class="field-row">
                <span class="field-label">订单号</span>
                <span class="field-value">{{ row.orderId }}</span>
              </div>
              <div class="field-row field-row--third-party">
                <span class="field-label">第三方单号</span>
                <template v-if="row.thirdPartyOrderNo">
                  <span class="field-value">{{ row.thirdPartyOrderNo }}</span>
                </template>
                <div v-else class="field-value field-value--third-party-edit">
                  <el-input
                    v-model="row.thirdPartyOrderNo"
                    size="small"
                    clearable
                    placeholder="可粘贴，失焦或点保存写入"
                    @blur="onThirdPartyOrderNoBlur(row)"
                  />
                  <el-button type="primary" size="mini" plain @click="onThirdPartyOrderNoSave(row)">保存</el-button>
                </div>
              </div>
              <div class="field-row field-row--distribution-mark">
                <span class="field-label">分销标识</span>
                <div
                  class="field-value jd-dist-mark-mobile-tap"
                  title="点击编辑"
                  @click.stop="openDistributionMarkEditDialog(row)"
                >
                  <span
                    class="jd-dist-mark-mobile-pill"
                    :class="[distributionMarkDisplayClass(row.distributionMark)]"
                    :style="distributionMarkDisplayStyle(row.distributionMark)"
                  >{{ distributionMarkCellLabel(row.distributionMark) }}</span>
                  <i class="el-icon-edit-outline jd-dist-mark-edit-ico" aria-hidden="true" />
                </div>
              </div>
              <div class="field-row field-row--model" @click.stop>
                <span class="field-label">型号</span>
                <div class="field-value field-value--third-party-edit jd-mobile-model-edit">
                  <el-input
                    v-model="row.modelNumber"
                    class="jd-mobile-model-input"
                    size="small"
                    clearable
                    placeholder="型号本体"
                    @blur="onModelNumberBlur(row)"
                  />
                  <el-select
                    v-model="row.modelShop"
                    class="jd-mobile-model-shop"
                    size="small"
                    clearable
                    filterable
                    placeholder="店铺"
                    @change="onModelShopChange(row)"
                  >
                    <el-option v-for="opt in shopOptions" :key="opt.prefix" :label="opt.label" :value="opt.prefix" />
                  </el-select>
                  <el-button type="primary" size="mini" plain @click="onModelNumberSave(row)">保存</el-button>
                </div>
              </div>
              <div class="field-row">
                <span class="field-label">地址</span>
                <span class="field-value address-text">{{ row.address || '-' }}</span>
              </div>
              <div class="field-row field-row--logistics-refresh">
                <span class="field-label">物流</span>
                <span class="field-value">
                  <el-button type="primary" plain size="mini" icon="el-icon-truck" @click="handleFetchLogistics(row)">手动刷新物流</el-button>
                  <el-button v-if="row.logisticsLink" type="text" size="mini" @click="copyToClipboard(row.logisticsLink)">复制物流链接</el-button>
                  <el-button type="warning" plain size="mini" icon="el-icon-document-copy" @click.stop="copyBasketShipSummary(row)">篮子摘要</el-button>
                </span>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">付款金额</span>
                <div class="field-value field-value--pricing-control">
                  <el-input-number
                    v-model="row.paymentAmount"
                    :min="0"
                    :step="1"
                    :precision="2"
                    size="small"
                    controls-position="right"
                    class="mobile-pricing-input"
                    @change="onOrderPaymentOrRebateChange(row)"
                  />
                </div>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">后返金额</span>
                <div class="field-value field-value--pricing-control">
                  <el-input-number
                    v-model="row.rebateAmount"
                    :min="0"
                    :step="1"
                    :precision="2"
                    size="small"
                    controls-position="right"
                    class="mobile-pricing-input"
                    @change="onOrderPaymentOrRebateChange(row)"
                  />
                </div>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">额外成本</span>
                <div class="field-value field-value--pricing-control">
                  <el-input-number
                    v-model="row.extraCost"
                    :min="0"
                    :step="1"
                    :precision="2"
                    size="small"
                    controls-position="right"
                    class="mobile-pricing-input"
                    @change="onOrderExtraCostChange(row)"
                  />
                </div>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">售价渠道</span>
                <span class="field-value field-value--pricing-control">
                  <el-select v-model="row.sellingPriceType" placeholder="渠道" size="small" clearable class="mobile-pricing-select" @change="onOrderSellingPriceTypeChange(row)">
                    <el-option label="直款" value="direct" />
                    <el-option label="闲鱼" value="xianyu" />
                  </el-select>
                </span>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">售价</span>
                <span class="field-value field-value--pricing-control">
                  <div class="mobile-pricing-num-wrap">
                    <el-input-number v-model="row.sellingPrice" :min="0" :step="1" :precision="2" size="small" controls-position="right" class="mobile-pricing-input" @change="onOrderSellingPriceChange(row)" />
                    <el-tag v-if="row.sellingPriceManual === 1" type="info" size="mini" class="mobile-pricing-tag">手填</el-tag>
                  </div>
                </span>
              </div>
              <div class="field-row field-row--pricing">
                <span class="field-label">利润</span>
                <span class="field-value field-value--pricing-control">
                  <div class="mobile-pricing-num-wrap">
                    <el-input-number v-model="row.profit" :step="0.01" :precision="2" size="small" controls-position="right" class="mobile-pricing-input" @change="onOrderProfitChange(row)" />
                    <el-tag v-if="row.profitManual === 1" type="warning" size="mini" class="mobile-pricing-tag">手填</el-tag>
                  </div>
                </span>
              </div>
              <div class="field-row">
                <span class="field-label">快捷</span>
                <span class="field-value">
                  <el-button v-if="isFanDistributionMark(row.distributionMark)" type="text" size="mini" @click="fillSellingPriceFromConfig(row)">按型号填价</el-button>
                  <el-button type="text" size="mini" @click="recalcOrderProfitOnly(row)">重算利润</el-button>
                </span>
              </div>
              <div class="field-row">
                <span class="field-label">下单人</span>
                <span class="field-value">{{ row.buyer || '-' }}</span>
              </div>
              
              <!-- 跟进状态（含后返表关联） -->
              <div class="field-row refund-status">
                <span class="field-label">跟进状态</span>
                <div class="field-value status-tags">
                  <el-tag 
                    :type="row.isRefunded === 1 ? 'warning' : 'info'" 
                    size="mini"
                    @click.native="toggleRefunded(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isRefunded === 1 ? '已退款' : '未退款' }}
                  </el-tag>
                  <el-tag 
                    :type="row.isRefundReceived === 1 ? 'success' : 'info'" 
                    size="mini"
                    @click.native="toggleRefundReceived(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isRefundReceived === 1 ? '退款到账' : '未到账' }}
                  </el-tag>
                  <el-tag 
                    :type="row.isRebateReceived === 1 ? 'success' : 'info'" 
                    size="mini"
                    @click.native="toggleRebateReceived(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isRebateReceived === 1 ? '后返到账' : '未到账' }}
                  </el-tag>
                  <el-tag 
                    :type="row.isPriceProtected === 1 ? 'warning' : 'info'" 
                    size="mini"
                    @click.native="togglePriceProtected(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isPriceProtected === 1 ? '点过价保' : '未点价保' }}
                  </el-tag>
                  <el-tag 
                    :type="row.isInvoiceOpened === 1 ? 'success' : 'info'" 
                    size="mini"
                    @click.native="toggleInvoiceOpened(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isInvoiceOpened === 1 ? '开过专票' : '未开专票' }}
                  </el-tag>
                  <el-tag 
                    :type="row.isReviewPosted === 1 ? 'success' : 'info'" 
                    size="mini"
                    @click.native="toggleReviewPosted(row)"
                    style="cursor: pointer; margin-right: 8px;">
                    {{ row.isReviewPosted === 1 ? '晒过评价' : '未晒评价' }}
                  </el-tag>
                  <span class="mobile-rebate-remark-inline">
                    <span class="mobile-rebate-remark-hint">后返表</span>
                    <template v-if="!row.rebateRemarkJson">
                      <span style="color: #c0c4cc;">—</span>
                    </template>
                    <template v-else>
                      <el-tag v-if="row.rebateRemarkHasAbnormal === 1" type="danger" size="mini">异常</el-tag>
                      <el-tag v-else-if="row.rebateRemarkHasAbnormal === 0" type="success" size="mini">正常</el-tag>
                      <span style="margin-left: 6px; color: #64748b; font-size: 12px;">{{ rebateRemarkCount(row) }} 条</span>
                    </template>
                  </span>
                </div>
              </div>
              
              <div class="field-row">
                <span class="field-label">创建时间</span>
                <span class="field-value">{{ parseTime(row.createTime) }}</span>
              </div>
              <div class="field-row" v-if="row.finishTime">
                <span class="field-label">完成时间</span>
                <span class="field-value">{{ parseTime(row.finishTime) }}</span>
              </div>
              <div class="field-row" v-if="row.status">
                <span class="field-label">备注/状态</span>
                <span class="field-value">{{ row.status }}</span>
              </div>
            </div>
          </div>

          <p v-if="isMobile && !loading && total > list.length" class="mobile-order-list-cap-hint">
            共 <b>{{ total }}</b> 条，当前已加载 <b>{{ list.length }}</b> 条（单次上限 {{ queryParams.pageSize }}）。其余请缩小日期/筛选或在电脑端查看。
          </p>

          <el-empty v-if="!loading && list.length === 0" description="暂无数据" :image-size="100" />
        </div>

        <!-- 桌面端：统计条 + 表格（height 固定表头，滚动条在表体） -->
        <div v-else class="jd-order-table-wrap">
        <div ref="profitSummaryBar" class="profit-summary-bar sticky-summary">
          <div class="profit-summary-bar__left">
            <span class="profit-summary-item">统计范围：<b>{{ profitSummaryLabel }}</b></span>
            <span class="profit-summary-item">后返合计：<b>{{ toYuan(profitSummaryRebateTotal) }}</b><span class="profit-summary-hint">（不含已退款）</span></span>
            <span class="profit-summary-item">利润合计：<b>{{ profitSummaryProfitTotal === '' ? '—' : toYuan(profitSummaryProfitTotal) }}</b><span class="profit-summary-hint">（不含已退款）</span></span>
          </div>
          <div class="profit-summary-bar__status">
            <span class="order-status-stat">总 <b>{{ orderStatusStatTotal }}</b></span>
            <span class="order-status-stat order-status-stat--refund">退款 <b>{{ orderStatusStatRefunded }}</b></span>
            <span class="order-status-stat order-status-stat--shipped">已发货 <b>{{ orderStatusStatShipped }}</b></span>
            <span class="order-status-stat order-status-stat--pending">待发货 <b>{{ orderStatusStatPending }}</b></span>
          </div>
        </div>
        <el-table
          :data="list"
          v-loading="loading"
          border
          stripe
          height="100%"
          :default-sort="{prop: 'createTime', order: 'descending'}"
          @sort-change="handleSortChange"
          @selection-change="handleSelectionChange"
          style="width: 100%;"
          class="order-table jd-order-el-table">
          <!-- 多选列（仅桌面端显示） -->
          <el-table-column v-if="!isMobile" type="selection" width="55" fixed="left" align="center"/>
          <!-- 分销标识列置首：相同标识稳定同色 -->
          <el-table-column label="分销标识" prop="distributionMark" min-width="112" align="center" fixed="left" class-name="jd-col-distribution-mark">
            <template slot-scope="scope">
              <div
                :class="['jd-dist-mark-cell', 'jd-dist-mark-cell--tap', distributionMarkDisplayClass(scope.row.distributionMark)]"
                :style="distributionMarkDisplayStyle(scope.row.distributionMark)"
                role="button"
                tabindex="0"
                title="点击编辑分销标识"
                @click.stop="openDistributionMarkEditDialog(scope.row)"
                @keydown.enter.prevent.stop="openDistributionMarkEditDialog(scope.row)"
              >
                <span class="jd-dist-mark-text">{{ distributionMarkCellLabel(scope.row.distributionMark) }}</span>
              </div>
            </template>
          </el-table-column>
          <!-- 核心信息列 -->
          <el-table-column label="订单号" prop="orderId" width="160" :fixed="isMobile ? false : 'left'"/>
          <el-table-column label="第三方单号" prop="thirdPartyOrderNo" min-width="188">
            <template slot-scope="scope">
              <template v-if="scope.row.thirdPartyOrderNo">
                <span>{{ scope.row.thirdPartyOrderNo }}</span>
              </template>
              <div v-else class="jd-third-party-empty">
                <el-input
                  v-model="scope.row.thirdPartyOrderNo"
                  size="mini"
                  clearable
                  placeholder="粘贴后失焦保存"
                  @blur="onThirdPartyOrderNoBlur(scope.row)"
                />
              </div>
            </template>
          </el-table-column>

          <!-- 业务信息列：型号单行撑满列宽，约 20 字以内不挤；更长在输入框内横向滚动，不换行以免行高乱跳 -->
          <el-table-column label="型号" prop="modelNumber" min-width="280" class-name="jd-col-model">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--model jd-model-edit-row">
                <el-input
                  v-model="scope.row.modelNumber"
                  class="jd-order-input-model"
                  size="mini"
                  clearable
                  placeholder="型号本体"
                  @blur="onModelFieldBlur(scope.row)"
                  @keyup.enter.native="onModelFieldBlur(scope.row)"
                />
                <el-select
                  v-model="scope.row.modelShop"
                  class="jd-order-model-shop"
                  size="mini"
                  clearable
                  filterable
                  placeholder="店铺"
                  @change="onModelShopChange(scope.row)"
                >
                  <el-option v-for="opt in shopOptions" :key="opt.prefix" :label="opt.label" :value="opt.prefix" />
                </el-select>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="地址" prop="address" min-width="220" show-overflow-tooltip class-name="address-cell">
            <template slot-scope="scope">
              <span style="font-weight: bold; display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ scope.row.address }}</span>
            </template>
          </el-table-column>

          <!-- 金额信息列 -->
          <el-table-column label="付款金额" prop="paymentAmount" min-width="118" align="right" class-name="jd-col-money jd-col-money--payment">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--num">
                <el-input-number
                  v-model="scope.row.paymentAmount"
                  :min="0"
                  :step="1"
                  :precision="2"
                  size="mini"
                  controls-position="right"
                  class="jd-order-input-money jd-order-input-money--payment"
                  @change="onOrderPaymentOrRebateChange(scope.row)"
                />
              </div>
            </template>
          </el-table-column>
          <el-table-column label="后返金额" prop="rebateAmount" min-width="118" align="right" class-name="jd-col-money jd-col-money--rebate">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--num">
                <el-input-number
                  v-model="scope.row.rebateAmount"
                  :min="0"
                  :step="1"
                  :precision="2"
                  size="mini"
                  controls-position="right"
                  class="jd-order-input-money jd-order-input-money--rebate"
                  @change="onOrderPaymentOrRebateChange(scope.row)"
                />
              </div>
            </template>
          </el-table-column>
          <el-table-column label="售价渠道" prop="sellingPriceType" min-width="120" align="center" class-name="jd-col-channel">
            <template slot-scope="scope">
              <div class="jd-cell-stretch">
                <el-select v-model="scope.row.sellingPriceType" placeholder="—" size="mini" clearable class="jd-cell-select-full" @change="onOrderSellingPriceTypeChange(scope.row)">
                  <el-option label="直款" value="direct" />
                  <el-option label="闲鱼" value="xianyu" />
                </el-select>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="售价" prop="sellingPrice" min-width="150" align="right" class-name="jd-col-money jd-col-money--selling">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--num">
                <el-input-number v-model="scope.row.sellingPrice" :min="0" :step="1" :precision="2" size="mini" controls-position="right" class="jd-order-input-money jd-order-input-money--selling" @change="onOrderSellingPriceChange(scope.row)" />
              </div>
            </template>
          </el-table-column>
          <el-table-column label="额外成本" prop="extraCost" min-width="112" align="right" class-name="jd-col-money jd-col-money--extra-cost">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--num">
                <el-input-number v-model="scope.row.extraCost" :min="0" :step="1" :precision="2" size="mini" controls-position="right" class="jd-order-input-money jd-order-input-money--rebate" @change="onOrderExtraCostChange(scope.row)" />
              </div>
            </template>
          </el-table-column>
          <el-table-column label="利润" prop="profit" min-width="118" align="right" class-name="jd-col-money jd-col-money--profit">
            <template slot-scope="scope">
              <div class="jd-cell-stretch jd-cell-stretch--num">
                <el-input-number v-model="scope.row.profit" :step="0.01" :precision="2" size="mini" controls-position="right" class="jd-order-input-money jd-order-input-money--profit" @change="onOrderProfitChange(scope.row)" />
              </div>
            </template>
          </el-table-column>
          <el-table-column label="快捷操作" width="90" align="center">
            <template slot-scope="scope">
              <el-button v-if="isFanDistributionMark(scope.row.distributionMark)" type="text" size="mini" @click="fillSellingPriceFromConfig(scope.row)">填价</el-button>
              <el-button type="text" size="mini" @click="recalcOrderProfitOnly(scope.row)">重算</el-button>
            </template>
          </el-table-column>
          <el-table-column label="备注/状态" prop="status" min-width="100" show-overflow-tooltip/>
          <el-table-column label="下单人" prop="buyer" width="80"/>

          <!-- 跟进状态：退款/价保/票/评价 + 后返到账 + 后返表导入明细 -->
          <el-table-column label="跟进状态" min-width="268" align="left" class-name="refund-status-column">
            <template slot-scope="scope">
              <div class="refund-status-stack">
                <div class="refund-status-col">
                  <div class="refund-status-row">
                    <span class="refund-status-label">是否退款</span>
                    <el-tag
                      :type="scope.row.isRefunded === 1 ? 'warning' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isRefunded === 1 && scope.row.refundDate ? '退款日期：' + parseTime(scope.row.refundDate) : ''"
                      @click.native="toggleRefunded(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isRefunded === 1 ? '已退款' : '未退款' }}
                    </el-tag>
                  </div>
                  <div class="refund-status-row">
                    <span class="refund-status-label">退款到账</span>
                    <el-tag
                      :type="scope.row.isRefundReceived === 1 ? 'success' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isRefundReceived === 1 && scope.row.refundReceivedDate ? '退款到账日期：' + parseTime(scope.row.refundReceivedDate) : ''"
                      @click.native="toggleRefundReceived(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isRefundReceived === 1 ? '已到账' : '未到账' }}
                    </el-tag>
                  </div>
                  <div class="refund-status-row">
                    <span class="refund-status-label">后返到账</span>
                    <el-tag
                      :type="scope.row.isRebateReceived === 1 ? 'success' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isRebateReceived === 1 && scope.row.rebateReceivedDate ? '后返到账日期：' + parseTime(scope.row.rebateReceivedDate) : ''"
                      @click.native="toggleRebateReceived(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isRebateReceived === 1 ? '已到账' : '未到账' }}
                    </el-tag>
                  </div>
                </div>
                <div class="refund-status-col">
                  <div class="refund-status-row">
                    <span class="refund-status-label">价保</span>
                    <el-tag
                      :type="scope.row.isPriceProtected === 1 ? 'warning' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isPriceProtected === 1 && scope.row.priceProtectedDate ? '价保日期：' + parseTime(scope.row.priceProtectedDate) : ''"
                      @click.native="togglePriceProtected(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isPriceProtected === 1 ? '已点' : '未点' }}
                    </el-tag>
                  </div>
                  <div class="refund-status-row">
                    <span class="refund-status-label">专票</span>
                    <el-tag
                      :type="scope.row.isInvoiceOpened === 1 ? 'success' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isInvoiceOpened === 1 && scope.row.invoiceOpenedDate ? '开票日期：' + parseTime(scope.row.invoiceOpenedDate) : ''"
                      @click.native="toggleInvoiceOpened(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isInvoiceOpened === 1 ? '已开' : '未开' }}
                    </el-tag>
                  </div>
                  <div class="refund-status-row">
                    <span class="refund-status-label">评价</span>
                    <el-tag
                      :type="scope.row.isReviewPosted === 1 ? 'success' : 'info'"
                      size="mini"
                      effect="plain"
                      :title="scope.row.isReviewPosted === 1 && scope.row.reviewPostedDate ? '评价日期：' + parseTime(scope.row.reviewPostedDate) : ''"
                      @click.native="toggleReviewPosted(scope.row)"
                      class="refund-status-tag">
                      {{ scope.row.isReviewPosted === 1 ? '已晒' : '未晒' }}
                    </el-tag>
                  </div>
                </div>
              </div>
              <div class="jd-rebate-remark-strip">
                <span class="jd-rebate-remark-strip-label">后返表</span>
                <div class="jd-rebate-remark-strip-body">
                  <template v-if="!scope.row.rebateRemarkJson">
                    <span class="jd-rebate-remark-empty">—</span>
                  </template>
                  <template v-else>
                    <el-tag v-if="scope.row.rebateRemarkHasAbnormal === 1" type="danger" size="mini">异常</el-tag>
                    <el-tag v-else-if="scope.row.rebateRemarkHasAbnormal === 0" type="success" size="mini">正常</el-tag>
                    <el-popover trigger="click" placement="left" width="420">
                      <div class="rebate-remark-popover">
                        <div
                          v-for="(it, idx) in parseRebateRemarks(scope.row)"
                          :key="idx"
                          class="rebate-remark-item"
                        >
                          <div class="rebate-remark-title">
                            <b>{{ it.documentTitle || '（未命名）' }}</b>
                            <span class="rebate-remark-time">{{ formatRebateRemarkTime(it.uploadTime) }}</span>
                          </div>
                          <div>是否返现：{{ it.whetherRebate !== undefined && it.whetherRebate !== '' ? it.whetherRebate : '（空）' }}
                            <el-tag v-if="it.abnormal" type="danger" size="mini">异常</el-tag>
                            <el-tag v-else type="success" size="mini">正常</el-tag>
                          </div>
                          <div>返现金额：{{ it.rebateAmount !== undefined && it.rebateAmount !== '' ? it.rebateAmount : '-' }}</div>
                        </div>
                      </div>
                      <el-button slot="reference" type="text" size="small">明细（{{ rebateRemarkCount(scope.row) }}）</el-button>
                    </el-popover>
                  </template>
                </div>
              </div>
            </template>
          </el-table-column>

          <!-- 时间信息列 -->
          <el-table-column label="创建时间" prop="createTime" width="140" sortable="custom">
            <template slot-scope="scope">{{ parseTime(scope.row.createTime) }}</template>
          </el-table-column>
          <el-table-column label="完成时间" prop="finishTime" width="130">
            <template slot-scope="scope">{{ parseTime(scope.row.finishTime) || '-' }}</template>
          </el-table-column>

          <!-- 其他信息列（可折叠） -->
          <el-table-column label="订单状态" prop="orderStatus" width="80" align="center">
            <template slot-scope="scope">
              <el-tag
                v-if="scope.row.orderStatus != null"
                :type="getOrderStatusType(scope.row.orderStatus)"
                size="small">
                {{ getOrderStatusTextShort(scope.row.orderStatus) }}
              </el-tag>
              <span v-else style="color: #999;">-</span>
            </template>
          </el-table-column>

          <!-- 操作列（统一放在最右侧） -->
          <el-table-column label="操作" fixed="right" :width="isMobile ? 60 : 300" align="center" class-name="action-column">
            <template slot-scope="scope">
              <!-- 移动端：悬浮操作按钮 -->
              <div v-if="isMobile" class="mobile-action-wrapper">
                <el-dropdown 
                  trigger="click" 
                  placement="left"
                  @command="handleActionCommand"
                  :popper-class="'mobile-action-dropdown'">
                  <el-button 
                    type="primary" 
                    size="mini" 
                    icon="el-icon-more"
                    circle
                    class="mobile-action-btn">
                  </el-button>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item 
                      :command="{action: 'copyOrderId', row: scope.row}"
                      icon="el-icon-copy-document">
                      复制订单号
                    </el-dropdown-item>
                    <el-dropdown-item 
                      v-if="scope.row.thirdPartyOrderNo"
                      :command="{action: 'copyThirdParty', row: scope.row}"
                      icon="el-icon-copy-document">
                      复制第三方单号
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyAddress', row: scope.row}"
                      icon="el-icon-copy-document">
                      复制地址
                    </el-dropdown-item>
                    <el-dropdown-item 
                      v-if="scope.row.logisticsLink"
                      :command="{action: 'copyLogistics', row: scope.row}"
                      icon="el-icon-copy-document">
                      复制物流链接
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyBasketShip', row: scope.row}"
                      icon="el-icon-document-copy">
                      篮子发货摘要
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyReturn', row: scope.row}"
                      icon="el-icon-document-copy">
                      退货复制
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyExcel', row: scope.row}"
                      icon="el-icon-document-copy"
                      :class="{'is-copied': isExcelTextCopied(scope.row.id)}">
                      {{ isExcelTextCopied(scope.row.id) ? '✓ 录单格式（已复制）' : '录单格式' }}
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'copyRebate', row: scope.row}"
                      icon="el-icon-document-copy">
                      后返录表
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'fetchLogistics', row: scope.row}"
                      icon="el-icon-truck"
                      style="color: #67C23A;">
                      刷新物流
                    </el-dropdown-item>
                    <el-dropdown-item divided>
                      <div style="display: flex; align-items: center; justify-content: space-between; padding: 0 10px;">
                        <span>统计</span>
                        <el-switch
                          v-model="scope.row.isCountEnabled"
                          :active-value="1"
                          :inactive-value="0"
                          @change="handleCountEnabledChange(scope.row)"
                          size="mini"
                          style="margin-left: 10px;">
                        </el-switch>
                      </div>
                    </el-dropdown-item>
                    <el-dropdown-item 
                      :command="{action: 'delete', row: scope.row}"
                      icon="el-icon-delete"
                      divided
                      style="color: #f56c6c;">
                      删除
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
              </div>
              
              <!-- 桌面端：分行 + 轻量链接样式，降低杂乱感 -->
              <div v-else class="desktop-action-buttons-wrapper jd-action-cell">
                <div class="jd-action-row jd-action-row--copy">
                  <el-button type="text" size="mini" class="jd-act-link" icon="el-icon-copy-document" @click="copyToClipboard(scope.row.orderId)" title="复制订单号">单号</el-button>
                  <el-button v-if="scope.row.thirdPartyOrderNo" type="text" size="mini" class="jd-act-link" icon="el-icon-copy-document" @click="copyToClipboard(scope.row.thirdPartyOrderNo)" title="复制第三方单号">三方</el-button>
                  <el-button type="text" size="mini" class="jd-act-link" icon="el-icon-copy-document" @click="copyToClipboard(scope.row.address)" title="复制地址">地址</el-button>
                  <el-button v-if="scope.row.logisticsLink" type="text" size="mini" class="jd-act-link" icon="el-icon-copy-document" @click="copyToClipboard(scope.row.logisticsLink)" title="复制物流链接">物流</el-button>
                  <el-button type="text" size="mini" class="jd-act-link" icon="el-icon-document-copy" @click="copyBasketShipSummary(scope.row)" title="复制篮子发货摘要（型号、地址、物流）">篮子</el-button>
                  <el-button type="text" size="mini" class="jd-act-link" @click="copyReturnInfo(scope.row)" title="复制退货信息">退货</el-button>
                </div>
                <div class="jd-action-row jd-action-row--doc">
                  <el-button type="text" size="mini" class="jd-act-link jd-act-link--accent" :class="{ 'jd-act-done': isExcelTextCopied(scope.row.id) }" icon="el-icon-document-copy" @click="copySingleOrderExcelText(scope.row)" :title="isExcelTextCopied(scope.row.id) ? '已复制录单格式' : '复制录单格式'">录单</el-button>
                  <el-button type="text" size="mini" class="jd-act-link jd-act-link--accent" icon="el-icon-document-copy" @click="copyRebateRecordText(scope.row)" title="复制后返录表">后返</el-button>
                  <el-button type="text" size="mini" class="jd-act-link jd-act-link--success" @click="handleFetchLogistics(scope.row)" title="按物流链接调用扫描服务拉取最新轨迹">刷新物流</el-button>
                </div>
                <div class="jd-action-row jd-action-row--meta">
                  <div class="jd-count-pill" title="是否参与利润等汇总统计">
                    <span class="jd-count-pill-label">统计</span>
                    <el-switch
                      v-model="scope.row.isCountEnabled"
                      :active-value="1"
                      :inactive-value="0"
                      @change="handleCountEnabledChange(scope.row)"
                      class="jd-count-el-switch"
                      size="mini" />
                  </div>
                  <el-button type="text" size="mini" class="jd-act-link jd-act-link--danger" icon="el-icon-delete" @click="handleDelete(scope.row)" title="删除订单">删除</el-button>
                </div>
              </div>
            </template>
          </el-table-column>
        </el-table>
        </div>
        </div>
      </template>

      <!-- 分页区域 -->
      <template #pagination>
        <pagination
          v-show="total > 0"
          :total="total"
          :page.sync="queryParams.pageNum"
          :limit.sync="queryParams.pageSize"
          @pagination="handleMainPagination"
          class="list-pagination"
        />
      </template>
    </list-layout>

    <!-- 获取物流信息对话框（挂到 body，避免被 ListLayout overflow/层叠上下文裁切导致「只见消息不见窗」） -->
    <el-dialog
      title="刷新物流信息"
      :visible.sync="fetchLogisticsDialogVisible"
      width="800px"
      append-to-body
      :close-on-click-modal="false"
    >
      <div v-loading="fetchLogisticsLoading">
        <el-alert
          v-if="fetchLogisticsResult"
          :title="fetchLogisticsResult.success ? '获取成功' : '获取失败'"
          :type="fetchLogisticsResult.success ? 'success' : 'error'"
          :closable="false"
          style="margin-bottom: 20px;"
        />
        <el-form label-width="120px" v-if="fetchLogisticsResult">
          <el-form-item label="错误信息" v-if="fetchLogisticsResult.error">
            <el-alert
              :title="fetchLogisticsResult.error"
              type="error"
              :closable="false"
            />
          </el-form-item>
          <el-form-item label="订单ID" v-if="fetchLogisticsResult.orderId">
            <span>{{ fetchLogisticsResult.orderId }}</span>
          </el-form-item>
          <el-form-item label="订单号" v-if="fetchLogisticsResult.orderNo">
            <span>{{ fetchLogisticsResult.orderNo }}</span>
          </el-form-item>
          <el-form-item label="分销标识" v-if="fetchLogisticsResult.distributionMark">
            <span>{{ fetchLogisticsResult.distributionMark }}</span>
          </el-form-item>
          <el-form-item label="物流链接" v-if="fetchLogisticsResult.logisticsLink">
            <el-input 
              :value="fetchLogisticsResult.logisticsLink" 
              readonly 
              type="textarea" 
              :rows="2"
            />
          </el-form-item>
          <el-form-item label="请求URL" v-if="fetchLogisticsResult.requestUrl">
            <el-input 
              :value="fetchLogisticsResult.requestUrl" 
              readonly 
              type="textarea" 
              :rows="2"
            />
          </el-form-item>
          <el-form-item label="返回数据（原始）" v-if="fetchLogisticsResult.responseRaw || fetchLogisticsResult.responseData">
            <el-input 
              :value="fetchLogisticsResult.responseRaw || JSON.stringify(fetchLogisticsResult.responseData, null, 2)" 
              readonly 
              type="textarea" 
              :rows="10"
              style="font-family: monospace; font-size: 12px;"
            />
          </el-form-item>
          <el-form-item label="返回数据（解析后）" v-if="fetchLogisticsResult.responseData">
            <el-input 
              :value="JSON.stringify(fetchLogisticsResult.responseData, null, 2)" 
              readonly 
              type="textarea" 
              :rows="10"
              style="font-family: monospace; font-size: 12px;"
            />
          </el-form-item>
        </el-form>
        <div v-else style="text-align: center; padding: 40px;">
          <span style="color: #999;">正在获取物流信息...</span>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="fetchLogisticsDialogVisible = false">关闭</el-button>
        <el-button 
          type="primary" 
          @click="copyFetchLogisticsResult"
          v-if="fetchLogisticsResult"
        >
          复制结果
        </el-button>
      </div>
    </el-dialog>

    <!-- 同步物流对话框 -->
    <el-dialog
      title="同步物流到腾讯文档"
      :visible.sync="syncLogisticsDialogVisible"
      width="600px"
      :close-on-click-modal="false"
    >
      <el-form :model="syncLogisticsForm" label-width="140px">
        <el-form-item label="文件ID" required>
          <el-input
            v-model="syncLogisticsForm.fileId"
            placeholder="从腾讯文档URL中获取，例如：Dxxxxxxxxxxxxx"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="工作表ID" required>
          <el-input
            v-model="syncLogisticsForm.sheetId"
            placeholder="从腾讯文档URL中获取，例如：BB08J2"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="表头行号">
          <el-input-number
            v-model="syncLogisticsForm.headerRow"
            :min="1"
            style="width: 100%"
          />
          <div style="font-size: 12px; color: #999; margin-top: 4px;">
            表头所在行号（默认第1行）
          </div>
        </el-form-item>
        <el-form-item label="单号列索引（可选）">
          <el-input-number
            v-model="syncLogisticsForm.orderNoColumn"
            :min="0"
            style="width: 100%"
            placeholder="不填写则自动识别"
          />
          <div style="font-size: 12px; color: #999; margin-top: 4px;">
            单号列的索引（从0开始），不填写则自动识别
          </div>
        </el-form-item>
        <el-form-item label="物流链接列索引（可选）">
          <el-input-number
            v-model="syncLogisticsForm.logisticsLinkColumn"
            :min="0"
            style="width: 100%"
            placeholder="不填写则自动识别"
          />
          <div style="font-size: 12px; color: #999; margin-top: 4px;">
            物流链接列的索引（从0开始），不填写则自动识别
          </div>
        </el-form-item>
        <el-form-item label="说明">
          <div style="font-size: 12px; color: #666; line-height: 1.6;">
            <p>1. 点击"同步物流"时，如果没有token会自动打开授权页面</p>
            <p>2. 完成授权后，点击"开始同步"即可自动刷新token并同步数据</p>
            <p>3. 文件ID和工作表ID可以从腾讯文档URL中获取</p>
            <p>4. 系统会自动从上次处理的最大行数-100开始读取，避免重复处理历史数据</p>
            <p>5. 配置会自动保存，下次使用时无需重新填写</p>
          </div>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="syncLogisticsDialogVisible = false">取消</el-button>
        <el-button
          type="primary"
          :loading="syncLogisticsLoading"
          @click="handleSyncLogisticsSubmit"
        >
          开始同步
        </el-button>
      </div>
    </el-dialog>

    <!-- H-TF订单自动写入配置 -->
    <tencent-doc-auto-write-config v-model="showAutoWriteConfig" @config-updated="handleAutoConfigUpdated" />

    <!-- 腾讯文档推送监控 -->
    <tencent-doc-push-monitor v-model="showPushMonitor" />

    <!-- 分销标识接收人配置 -->
    <distribution-mark-touser-config v-model="showTouserConfig" @config-updated="handleTouserConfigUpdated" />

    <!-- 分销标识：点击列表单元格后编辑（非行内快捷编辑） -->
    <el-dialog
      title="编辑分销标识"
      :visible.sync="distributionMarkEditDialogVisible"
      width="440px"
      append-to-body
      :close-on-click-modal="false"
      @closed="onDistributionMarkEditDialogClosed"
    >
      <p v-if="distributionMarkEditRow" style="margin:0 0 12px;color:#909399;font-size:13px;">
        订单号：{{ distributionMarkEditRow.orderId }}
      </p>
      <el-input
        v-model="distributionMarkEditDraft"
        placeholder="分销标识"
        clearable
        @keyup.enter.native="confirmDistributionMarkEdit"
      />
      <div slot="footer" class="dialog-footer">
        <el-button @click="distributionMarkEditDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmDistributionMarkEdit">保存</el-button>
      </div>
    </el-dialog>

    <!-- 导入跟团返现 / 后返 Excel（支持多文件，一次提交后台依次处理） -->
    <el-dialog
      title="导入后返表（跟团返现等）"
      :visible.sync="rebateImportDialogVisible"
      width="520px"
      append-to-body
      @closed="onRebateImportDialogClosed"
    >
      <p style="color: #909399; font-size: 13px; margin: 0 0 12px;">
        表头需包含「单号」或「订单号」、「是否返现」、返现金额列（优先「总共返现」）。可选<strong>多个</strong> Excel，点「提交后台处理」后由服务端依次导入；不弹逐条结果，请到「后返上传记录」查看。
      </p>
      <el-form label-width="88px" size="small">
        <el-form-item label="文档标题">
          <el-input
            v-model="rebateImportTitle"
            placeholder="仅选 1 个文件时可用；多文件时各文件用各自文件名"
            clearable
          />
        </el-form-item>
        <el-form-item label="Excel">
          <el-upload
            ref="rebateExcelUploader"
            drag
            multiple
            :show-file-list="true"
            :limit="30"
            :auto-upload="false"
            accept=".xlsx,.xls"
            :disabled="rebateImportLoading"
            :on-exceed="onRebateExcelExceed"
          >
            <i class="el-icon-upload" />
            <div class="el-upload__text">拖到此处，或<em>点击选择</em>（可多选）</div>
            <div slot="tip" class="el-upload__tip">单次最多 30 个文件；仅解析每个文件的第一个工作表</div>
          </el-upload>
          <el-button
            type="primary"
            size="small"
            :loading="rebateImportLoading"
            style="margin-top: 10px"
            @click="submitRebateExcelBatch"
          >提交后台处理</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!-- 后返表上传记录（含重新下载） -->
    <el-dialog
      title="后返表上传记录"
      :visible.sync="rebateUploadRecordDialogVisible"
      width="960px"
      append-to-body
      @open="fetchRebateUploadList"
    >
      <el-table v-loading="rebateUploadLoading" :data="rebateUploadList" border size="small" max-height="420">
        <el-table-column label="ID" prop="id" width="70" />
        <el-table-column label="文档标题" prop="documentTitle" min-width="140" show-overflow-tooltip />
        <el-table-column label="原始文件名" prop="originalFilename" min-width="160" show-overflow-tooltip />
        <el-table-column label="大小" width="88" align="right">
          <template slot-scope="scope">{{ formatUploadFileSize(scope.row.fileSize) }}</template>
        </el-table-column>
        <el-table-column label="状态" width="100" align="center">
          <template slot-scope="scope">
            <el-tag v-if="scope.row.importStatus === 2" type="success" size="mini">已处理</el-tag>
            <el-tag v-else type="info" size="mini">未成功</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="数据行" prop="dataRows" width="72" align="center" />
        <el-table-column label="更新订单" prop="updatedOrders" width="88" align="center" />
        <el-table-column label="未匹配" prop="notFoundCount" width="72" align="center" />
        <el-table-column label="上传人" prop="createBy" width="100" show-overflow-tooltip />
        <el-table-column label="时间" prop="createTime" width="155" />
        <el-table-column label="操作" width="148" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button
              type="text"
              size="small"
              :disabled="!scope.row.filePath"
              @click="downloadRebateUploadFile(scope.row)"
            >下载</el-button>
            <el-button
              type="text"
              size="small"
              @click="confirmDeleteRebateUpload(scope.row)"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="rebateUploadTotal > 0"
        :total="rebateUploadTotal"
        :page.sync="rebateUploadQuery.pageNum"
        :limit.sync="rebateUploadQuery.pageSize"
        @pagination="fetchRebateUploadList"
      />
    </el-dialog>
  </div>
</template>

<script>
import { listJDOrders, getJDOrder, updateJDOrder, normalizeJDOrderPutPayload, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcelBatch, listGroupRebateExcelUploads, deleteGroupRebateUpload, recalcProfitBatch, syncAutoProfitBatch, listQuickRecordShopOptions, migrateModelShopSplit } from '@/api/system/jdorder'
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
import { mapGetters } from 'vuex'
import ListLayout from '@/components/ListLayout'
import MobileSearchForm from '@/components/MobileSearchForm'
import MobileButtonGroup from '@/components/MobileButtonGroup'
import TencentDocAutoWriteConfig from './components/TencentDocAutoWriteConfig'
import TencentDocPushMonitor from './components/TencentDocPushMonitor'
import DistributionMarkTouserConfig from './components/DistributionMarkTouserConfig'

/** 移动端「下好的慢单」一次拉取条数（ListLayout 在窄屏隐藏分页，原先默认 50 条无法翻页） */
const MOBILE_JD_ORDER_PAGE_SIZE = 500

export default {
  name: 'JDOrderList',
  components: {
    ListLayout,
    TencentDocAutoWriteConfig,
    TencentDocPushMonitor,
    DistributionMarkTouserConfig,
    MobileSearchForm,
    MobileButtonGroup
  },
  data() {
    return {
      /** 列表加载时的分销标识快照，失焦保存时与当前值比较避免重复请求 */
      _distMarkBaseline: {},
      /** 列表加载时的型号快照，失焦保存时与当前值比较避免重复请求 */
      _modelNumberBaseline: {},
      /** 列表加载时的型号店铺快照 */
      _modelShopBaseline: {},
      shopOptions: [],
      modelShopMigrateLoading: false,
      loading: false,
      list: [],
      total: 0,
      dateRange: [],
      queryParams: {
        pageNum: 1,
        pageSize: 50,
        remark: undefined,
        orderSearch: undefined,
        distributionMark: undefined,
        modelNumber: undefined,
        modelShop: undefined,
        modelNumberExclude: undefined,
        link: undefined,
        buyer: undefined,
        address: undefined,
        status: undefined,
        beginTime: null,
        endTime: null,
        orderBy: 'create_time',
        isAsc: 'desc',
        hasFinishTime: false,
        isRefunded: undefined,
        isRefundReceived: undefined,
        isRebateReceived: undefined,
        isPriceProtected: undefined,
        isInvoiceOpened: undefined,
        isReviewPosted: undefined,
        hasRebateRemark: undefined,
        rebateRemarkHasAbnormal: undefined,
        rebateWithoutUploadLink: undefined
      },
      rebateRemarkScreen: undefined,
      rebateImportDialogVisible: false,
      rebateImportTitle: '',
      rebateImportLoading: false,
      rebateUploadRecordDialogVisible: false,
      rebateUploadLoading: false,
      rebateUploadList: [],
      rebateUploadTotal: 0,
      rebateUploadQuery: {
        pageNum: 1,
        pageSize: 10
      },
      // 同步物流对话框
      syncLogisticsDialogVisible: false,
      syncLogisticsLoading: false,
      syncLogisticsForm: {
        fileId: '',
        sheetId: '',
        headerRow: 1,
        orderNoColumn: null,
        logisticsLinkColumn: null
      },
      currentOrder: null,
      tokenValid: false,
      tokenStatusChecked: false,
      // H-TF订单自动写入配置
      showAutoWriteConfig: false,
      showPushMonitor: false,
      showTouserConfig: false,
      // 批量同步loading状态
      batchSyncLoading: false,
      // 批量标记后返到账loading状态
      batchMarkLoading: false,
      // 反向同步第三方单号loading状态
      reverseSyncLoading: false,
      // 获取物流信息对话框
      fetchLogisticsDialogVisible: false,
      fetchLogisticsLoading: false,
      fetchLogisticsResult: null,
      // 复制录单格式loading状态
      copyExcelTextLoading: false,
      // 已复制录单格式的订单ID集合（页面级缓存，刷新后消失）
      copiedExcelTextOrderIds: new Set(),
      // 选中的行数据
      selectedRows: [],
      // 列表加载后自动同步利润（防快速翻页乱序）
      syncAutoProfitSeq: 0,
      /** 延后拉单条详情的防抖句柄（字符串 id -> timeout id） */
      _patchRowTimers: null,
      /** 单行 PUT 防抖（避免 change+blur 连击触发若依重复提交拦截） */
      _persistOrderTimers: null,
      _persistOrderPendingMsg: null,
      /** 列表刚从接口赋值后的短时间内：忽略金额组件误触发的 change，避免误 PUT */
      _listHydrating: false,
      _hydrateUnlockTimer: null,
      /** 与后端 SameUrlDataInterceptor 对齐：极短时间内相同 JSON body 不重复发送 */
      _jdPutDedupeFingerprint: null,
      _jdPutDedupeAt: 0,
      /** 移动端卡片：当前展开的订单 id（null 表示全部收起，同时只展开一条） */
      mobileExpandedOrderId: null,
      /** 视口高度（桌面端用于矮窗口下自动收起「跟进状态」筛选） */
      viewportHeight: typeof window !== 'undefined' ? window.innerHeight : 900,
      /** 矮窗口下是否展开完整筛选（基础条件 / 跟进状态 / 查询） */
      showDesktopExpandedFilters: true,
      /** 分销标识弹窗编辑 */
      distributionMarkEditDialogVisible: false,
      distributionMarkEditRow: null,
      distributionMarkEditDraft: ''
    }
  },
  computed: {
    ...mapGetters(['device']),
    /** 桌面端且窗口高度较低：压缩筛选区，避免列表被挤出视口 */
    isDesktopFilterCompact() {
      return !this.isMobile && this.viewportHeight < 780
    },
    isMobile() {
      // 只在移动端返回true，桌面端严格返回false
      if (this.device === 'mobile') {
        return true
      }
      // 如果device不是mobile，检查窗口宽度（用于响应式）
      if (typeof window !== 'undefined' && window.innerWidth < 768) {
        return true
      }
      return false
    },
    /** 统计条范围：勾选优先，否则当前列表页 */
    orderStatusStatRows() {
      return (this.selectedRows && this.selectedRows.length > 0 ? this.selectedRows : this.list) || []
    },
    orderStatusStatTotal() {
      return this.orderStatusStatRows.length
    },
    orderStatusStatRefunded() {
      return this.orderStatusStatRows.filter(r => r.isRefunded === 1).length
    },
    orderStatusStatShipped() {
      return this.orderStatusStatRows.filter(r => r.isRefunded !== 1 && this.isOrderShipped(r)).length
    },
    orderStatusStatPending() {
      return this.orderStatusStatRows.filter(r => r.isRefunded !== 1 && this.isOrderPendingShip(r)).length
    },
    profitSummaryRows() {
      return this.orderStatusStatRows.filter(r => r.isRefunded !== 1)
    },
    profitSummaryLabel() {
      if (this.selectedRows && this.selectedRows.length > 0) {
        return `已选 ${this.selectedRows.length} 条`
      }
      if (this.isMobile) {
        const n = (this.list && this.list.length) || 0
        const t = this.total || 0
        return t > n ? `本批 ${n} 条（共 ${t} 条）` : `本批 ${n} 条`
      }
      return `本页 ${this.list.length} 条`
    },
    profitSummaryRebateTotal() {
      return this.profitSummaryRows.reduce((s, r) => s + (Number(r.rebateAmount) || 0), 0)
    },
    profitSummaryProfitTotal() {
      let has = false
      const t = this.profitSummaryRows.reduce((s, r) => {
        if (r.profit == null || r.profit === '') return s
        has = true
        return s + (Number(r.profit) || 0)
      }, 0)
      return has ? t : ''
    },
    /**
     * 本页 list 中出现的分销标识（规范化后）去重、排序，再映射为连续下标。
     * 同色只表示「本页内同一标识」，不同标识在本页一定不同色（色相按序号散开）。
     */
    distributionMarkToneIndexByKey() {
      const set = new Set()
      for (const row of this.list || []) {
        const k = this.normalizeDistributionMarkInput(row.distributionMark)
        if (k) set.add(k)
      }
      const sorted = Array.from(set).sort()
      const map = Object.create(null)
      sorted.forEach((k, i) => {
        map[k] = i
      })
      return map
    },
    actionButtons() {
      // 移动端不展示顶部工具按钮（统一用底部导航与各页内操作）
      if (this.isMobile) {
        return []
      }
      // 桌面端显示所有按钮
      return [
        { key: 'export', label: '导出', type: 'success', icon: 'el-icon-download', handler: () => this.handleExport() },
        { key: 'config', label: '腾峰文档配置', type: 'warning', icon: 'el-icon-setting', handler: () => { this.showAutoWriteConfig = true } },
        { key: 'monitor', label: '推送监控', type: 'success', icon: 'el-icon-monitor', handler: () => { this.showPushMonitor = true } },
        { key: 'touser', label: '接收人配置', type: 'warning', icon: 'el-icon-user', handler: () => { this.showTouserConfig = true } },
        // { key: 'sync', label: '一键发货到腾峰', type: 'warning', icon: 'el-icon-refresh-right', handler: () => this.handleBatchSyncLogistics(), loading: this.batchSyncLoading },
        // { key: 'mark', label: '批量标记后返到账', type: 'warning', icon: 'el-icon-check', handler: () => this.handleBatchMarkRebateReceived(), loading: this.batchMarkLoading },
        // { key: 'reverse', label: '反向同步第三方单号', type: 'warning', icon: 'el-icon-sort', handler: () => this.handleReverseSyncThirdPartyOrderNo(), loading: this.reverseSyncLoading }
      ]
    }
  },
  watch: {
    device(val, oldVal) {
      if (val === 'mobile' && oldVal !== 'mobile') {
        this.queryParams.pageSize = MOBILE_JD_ORDER_PAGE_SIZE
        this.queryParams.pageNum = 1
        this.getList()
      }
    }
  },
  created() {
    this.applyMobileSlowOrderPageSize()
    this._patchRowTimers = {}
    this._persistOrderTimers = {}
    this._persistOrderPendingMsg = {}
    this.setDefaultDateRange()
    this.applyRouteSearchQuery()
    this.getListWithFallback()
    this.loadShopOptions()
    this.handleOAuthMessage = (event) => {
      if (event.data && event.data.type === 'tendoc_oauth_callback') {
        if (event.data.success) {
          this.$message.success(event.data.message || '授权成功！')
          // 刷新token状态
          this.checkTokenStatus()
        } else {
          this.$message.error(event.data.message || '授权失败')
        }
      }
    }
    window.addEventListener('message', this.handleOAuthMessage)
  },
  mounted() {
    this.viewportHeight = window.innerHeight
    if (!this.isMobile && this.viewportHeight < 780) {
      this.showDesktopExpandedFilters = false
    }
    this._onJdFilterViewportResize = () => this.onJdFilterViewportResize()
    window.addEventListener('resize', this._onJdFilterViewportResize, { passive: true })
  },
  beforeDestroy() {
    // 移除消息监听器
    if (this.handleOAuthMessage) {
      window.removeEventListener('message', this.handleOAuthMessage)
    }
    if (this._onJdFilterViewportResize) {
      window.removeEventListener('resize', this._onJdFilterViewportResize)
    }
    if (this._syncAutoProfitTimer) {
      clearTimeout(this._syncAutoProfitTimer)
      this._syncAutoProfitTimer = null
    }
    if (this._patchRowTimers) {
      Object.keys(this._patchRowTimers).forEach(k => clearTimeout(this._patchRowTimers[k]))
    }
    if (this._persistOrderTimers) {
      Object.keys(this._persistOrderTimers).forEach(k => clearTimeout(this._persistOrderTimers[k]))
    }
    if (this._hydrateUnlockTimer) {
      clearTimeout(this._hydrateUnlockTimer)
      this._hydrateUnlockTimer = null
    }
  },
  methods: {
    onJdFilterViewportResize() {
      const prev = this.viewportHeight
      const h = window.innerHeight
      this.viewportHeight = h
      if (this.isMobile) return
      const nowCompact = h < 780
      const wasCompact = prev < 780
      if (nowCompact && !wasCompact) {
        this.showDesktopExpandedFilters = false
      } else if (!nowCompact && wasCompact) {
        this.showDesktopExpandedFilters = true
      }
    },
    /** 已发货：联盟 express_status≠10；无联盟数据时有物流链接视为已发货 */
    isOrderShipped(row) {
      if (!row || row.isRefunded === 1) return false
      if (row.expressStatus != null) return row.expressStatus !== 10
      const link = row.logisticsLink == null ? '' : String(row.logisticsLink).trim()
      return link.length > 0
    },
    /** 待发货：联盟 express_status=10；无联盟数据且无物流链接 */
    isOrderPendingShip(row) {
      if (!row || row.isRefunded === 1) return false
      if (row.expressStatus != null) return row.expressStatus === 10
      const link = row.logisticsLink == null ? '' : String(row.logisticsLink).trim()
      return link.length === 0
    },
    /** 凡系分销标识：历史 F 与 F-中文（如 F-王杰）等同 */
    isFanDistributionMark(mark) {
      if (mark == null || mark === '') return false
      const m = String(mark).trim()
      return m === 'F' || m.startsWith('F-')
    },
    distributionMarkCellLabel(mark) {
      const k = this.normalizeDistributionMarkInput(mark)
      return k || '点击编辑'
    },
    openDistributionMarkEditDialog(row) {
      if (!row || row.id == null) return
      this.distributionMarkEditRow = row
      this.distributionMarkEditDraft = row.distributionMark == null ? '' : String(row.distributionMark)
      this.distributionMarkEditDialogVisible = true
    },
    confirmDistributionMarkEdit() {
      const row = this.distributionMarkEditRow
      if (!row) return
      row.distributionMark = this.distributionMarkEditDraft
      this.saveDistributionMarkIfChanged(row, '分销标识已保存')
      this.distributionMarkEditDialogVisible = false
    },
    onDistributionMarkEditDialogClosed() {
      this.distributionMarkEditRow = null
      this.distributionMarkEditDraft = ''
    },
    /** 空标识：仅用灰色底 class */
    distributionMarkDisplayClass(mark) {
      return this.normalizeDistributionMarkInput(mark) ? '' : 'jd-dist-tone-empty'
    },
    /** 非空：用本页 distributionMarkToneIndexByKey + 黄金角色相，避免哈希撞车 */
    distributionMarkDisplayStyle(mark) {
      const key = this.normalizeDistributionMarkInput(mark)
      if (!key) return {}
      const idx = this.distributionMarkToneIndexByKey[key]
      if (idx == null) return {}
      const hue = Math.round((idx * 222.49223594960218) % 360)
      return {
        background: `hsl(${hue}, 46%, 91%)`,
        color: '#1e293b'
      }
    },
    handleMainPagination() {
      this.getList()
      this.$nextTick(() => {
        const el = this.$refs.profitSummaryBar
        if (el && typeof el.scrollIntoView === 'function') {
          el.scrollIntoView({ behavior: 'smooth', block: 'start' })
        } else if (typeof window !== 'undefined') {
          window.scrollTo({ top: 0, behavior: 'smooth' })
        }
      })
    },
    /** 移动端 ListLayout 隐藏分页栏，默认 pageSize 过小会导致无法看到后序订单 */
    applyMobileSlowOrderPageSize() {
      if (this.device === 'mobile' || (typeof window !== 'undefined' && window.innerWidth < 768)) {
        this.queryParams.pageSize = MOBILE_JD_ORDER_PAGE_SIZE
      }
    },
    /** 处理移动端操作菜单命令 */
    handleActionCommand({ action, row }) {
      switch (action) {
        case 'copyOrderId':
          this.copyToClipboard(row.orderId)
          break
        case 'copyThirdParty':
          this.copyToClipboard(row.thirdPartyOrderNo)
          break
        case 'copyAddress':
          this.copyToClipboard(row.address)
          break
        case 'copyLogistics':
          this.copyToClipboard(row.logisticsLink)
          break
        case 'copyBasketShip':
          this.copyBasketShipSummary(row)
          break
        case 'copyReturn':
          this.copyReturnInfo(row)
          break
        case 'copyExcel':
          this.copySingleOrderExcelText(row)
          break
        case 'copyRebate':
          this.copyRebateRecordText(row)
          break
        case 'fetchLogistics':
          this.handleFetchLogistics(row)
          break
        case 'delete':
          this.handleDelete(row)
          break
      }
    },
    /** 快速搜索 */
    handleQuickSearch(keyword) {
      if (!keyword) {
        this.handleQuery()
        return
      }
      // 快速搜索：在订单号、备注、下单人等字段中搜索
      this.queryParams.orderSearch = keyword
      this.queryParams.remark = keyword
      this.queryParams.buyer = keyword
      this.handleQuery()
    },
    /** 设置默认日期范围为今天 */
    setDefaultDateRange() {
      const today = new Date()
      const todayStr = this.formatDate(today)
      this.dateRange = [todayStr, todayStr]
      this.queryParams.beginTime = todayStr
      this.queryParams.endTime = todayStr
    },
    /** 从路由参数带入慢单搜索（京粉列表跳转） */
    applyRouteSearchQuery() {
      const q = this.$route.query || {}
      if (!q.orderSearch) {
        return
      }
      this.queryParams.orderSearch = q.orderSearch
      if (q.allDates === '1') {
        this.dateRange = []
        this.queryParams.beginTime = undefined
        this.queryParams.endTime = undefined
      }
    },
    /** 格式化日期为 yyyy-MM-dd 格式 */
    formatDate(date) {
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      return `${year}-${month}-${day}`
    },
    /** 列表行默认值（退款开关、利润手填标记等） */
    normalizeOrderListItem(item) {
      const dist = this.normalizeDistributionMarkInput(item.distributionMark)
      const modelNum = this.normalizeModelNumberInput(item.modelNumber)
      const modelShop = this.normalizeModelShopInput(item.modelShop)
      if (item.id != null) {
        this.$set(this._distMarkBaseline, item.id, dist)
        this.$set(this._modelNumberBaseline, item.id, modelNum)
        this.$set(this._modelShopBaseline, item.id, modelShop)
      }
      return {
        ...item,
        distributionMark: dist,
        modelNumber: modelNum,
        modelShop: modelShop,
        isRefunded: item.isRefunded != null ? item.isRefunded : 0,
        isRefundReceived: item.isRefundReceived != null ? item.isRefundReceived : 0,
        isRebateReceived: item.isRebateReceived != null ? item.isRebateReceived : 0,
        isPriceProtected: item.isPriceProtected != null ? item.isPriceProtected : 0,
        isInvoiceOpened: item.isInvoiceOpened != null ? item.isInvoiceOpened : 0,
        isReviewPosted: item.isReviewPosted != null ? item.isReviewPosted : 0,
        sellingPriceManual: item.sellingPriceManual != null ? item.sellingPriceManual : 0,
        profitManual: item.profitManual != null ? item.profitManual : 0,
        extraCost: item.extraCost != null ? Number(item.extraCost) : 0,
        /** null 库内也表示「参与统计」，Switch 只能绑 0/1，统一成整数避免挂载时抖动触发 change */
        isCountEnabled: item.isCountEnabled === 0 ? 0 : 1
      }
    },
    assignListFromResponse(res) {
      this._listHydrating = true
      if (this._hydrateUnlockTimer) {
        clearTimeout(this._hydrateUnlockTimer)
        this._hydrateUnlockTimer = null
      }
      if (this._persistOrderTimers) {
        Object.keys(this._persistOrderTimers).forEach(k => {
          clearTimeout(this._persistOrderTimers[k])
          delete this._persistOrderTimers[k]
        })
      }
      if (this._persistOrderPendingMsg) {
        Object.keys(this._persistOrderPendingMsg).forEach(k => delete this._persistOrderPendingMsg[k])
      }
      this._jdPutDedupeFingerprint = null
      this._jdPutDedupeAt = 0

      this._distMarkBaseline = {}
      this._modelNumberBaseline = {}
      this._modelShopBaseline = {}
      const list = (res.rows || res.data || [])
      this.list = list.map(item => this.normalizeOrderListItem(item))
      this.total = res.total || 0
      if (this.isMobile) {
        this.mobileExpandedOrderId = null
      }
      this.$nextTick(() => {
        this._hydrateUnlockTimer = setTimeout(() => {
          this._hydrateUnlockTimer = null
          this._listHydrating = false
        }, 120)
      })
    },
    toggleMobileOrderExpand(row) {
      if (!row || row.id == null) return
      this.mobileExpandedOrderId = this.mobileExpandedOrderId === row.id ? null : row.id
    },
    /** 用户正在保存或与保存相关的回补时，取消「列表加载后自动同步利润」的挂起任务，避免与 PUT/GET 并发触发限流 */
    invalidatePendingSyncAutoProfit() {
      this.syncAutoProfitSeq++
      if (this._syncAutoProfitTimer) {
        clearTimeout(this._syncAutoProfitTimer)
        this._syncAutoProfitTimer = null
      }
    },
    /** 保存成功后错峰拉单条（替代与列表/同步抢同一时刻的带宽） */
    schedulePatchOrderRowFromServer(id) {
      if (id == null || !this._patchRowTimers) return
      const sid = String(id)
      if (this._patchRowTimers[sid]) {
        clearTimeout(this._patchRowTimers[sid])
      }
      this._patchRowTimers[sid] = setTimeout(() => {
        delete this._patchRowTimers[sid]
        this.patchOrderRowFromServer(id)
      }, 420)
    },
    /**
     * 本页数据与库中规则对齐（未手填利润的订单后端可能微调）；必要时再静默拉列表。
     * 延迟较长并与 invalidatePendingSyncAutoProfit 递增的 seq 配合，避免与编辑保存 PUT、详情 GET 同一时间突发请求触发限流。
     */
    runSyncAutoProfitAfterListLoad() {
      const ids = this.list.map(r => r.id).filter(id => id != null)
      if (!ids.length) return
      const seq = ++this.syncAutoProfitSeq
      if (this._syncAutoProfitTimer) clearTimeout(this._syncAutoProfitTimer)
      this._syncAutoProfitTimer = setTimeout(() => {
        syncAutoProfitBatch(ids)
          .then(res => {
            if (seq !== this.syncAutoProfitSeq) return
            const u = res && res.data && typeof res.data.updated === 'number' ? res.data.updated : 0
            if (u <= 0) return
            return listJDOrders(this.queryParams).then(r2 => {
              if (seq !== this.syncAutoProfitSeq) return
              this.assignListFromResponse(r2)
            })
          })
          .catch(() => {})
      }, 650)
    },
    getList() {
      this.loading = true
      listJDOrders(this.queryParams).then(res => {
        this.assignListFromResponse(res)
        this.loading = false
        this.runSyncAutoProfitAfterListLoad()
      }).catch(() => { this.loading = false })
    },
    /** 智能查询列表，如果今天数据为空则查询昨天 */
    async getListWithFallback() {
      this.loading = true

      try {
        const res = await listJDOrders(this.queryParams)
        this.assignListFromResponse(res)

        // 如果今天的数据为空，且是默认查询（没有手动选择日期），则尝试查询昨天
        if (this.list.length === 0 && this.isDefaultQuery()) {
          this.$message.info('今天暂无慢单数据，正在查询昨天的数据...')

          // 获取昨天的日期
          const yesterday = new Date()
          yesterday.setDate(yesterday.getDate() - 1)
          const yesterdayStr = this.formatDate(yesterday)

          // 更新查询参数为昨天
          this.queryParams.beginTime = yesterdayStr
          this.queryParams.endTime = yesterdayStr
          this.dateRange = [yesterdayStr, yesterdayStr]

          // 查询昨天的数据
          const yesterdayRes = await listJDOrders(this.queryParams)
          this.assignListFromResponse(yesterdayRes)

          if (this.list.length > 0) {
            this.$message.success(`已查询到昨天(${yesterdayStr})的慢单数据`)
          } else {
            this.$message.warning('昨天也没有慢单数据')
          }
        }

        this.loading = false
        this.runSyncAutoProfitAfterListLoad()
      } catch (error) {
        this.loading = false
        this.$message.error('查询失败，请稍后重试')
      }
    },
    /** 判断是否为默认查询（今天的数据） */
    isDefaultQuery() {
      const today = new Date()
      const todayStr = this.formatDate(today)
      return this.queryParams.beginTime === todayStr && this.queryParams.endTime === todayStr
    },
    handleQuery() {
      this.prepareQueryParams()
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 后返备注列表筛选 */
    onRebateRemarkScreenChange(v) {
      this.queryParams.hasRebateRemark = undefined
      this.queryParams.rebateRemarkHasAbnormal = undefined
      this.queryParams.rebateWithoutUploadLink = undefined
      if (v === 'any') {
        this.queryParams.hasRebateRemark = true
      } else if (v === 'abnormal') {
        this.queryParams.rebateRemarkHasAbnormal = 1
      } else if (v === 'ok') {
        this.queryParams.hasRebateRemark = true
        this.queryParams.rebateRemarkHasAbnormal = 0
      } else if (v === 'noUploadLink') {
        this.queryParams.rebateWithoutUploadLink = true
      }
      this.queryParams.pageNum = 1
      this.prepareQueryParams()
      this.getList()
    },
    parseRebateRemarks(row) {
      if (!row || !row.rebateRemarkJson) return []
      try {
        const arr = JSON.parse(row.rebateRemarkJson)
        return Array.isArray(arr) ? arr : []
      } catch (e) {
        return []
      }
    },
    rebateRemarkCount(row) {
      return this.parseRebateRemarks(row).length
    },
    formatRebateRemarkTime(ts) {
      if (ts == null || ts === '') return ''
      const d = new Date(typeof ts === 'number' ? ts : Number(ts))
      if (Number.isNaN(d.getTime())) return ''
      const y = d.getFullYear()
      const m = String(d.getMonth() + 1).padStart(2, '0')
      const day = String(d.getDate()).padStart(2, '0')
      const h = String(d.getHours()).padStart(2, '0')
      const min = String(d.getMinutes()).padStart(2, '0')
      return `${y}-${m}-${day} ${h}:${min}`
    },
    clearRebateExcelUploaderFiles() {
      this.$nextTick(() => {
        const u = this.$refs.rebateExcelUploader
        if (u && typeof u.clearFiles === 'function') {
          u.clearFiles()
        }
      })
    },
    onRebateImportDialogClosed() {
      this.rebateImportTitle = ''
      this.clearRebateExcelUploaderFiles()
    },
    onRebateExcelExceed() {
      this.$message.warning('单次最多选择 30 个文件')
    },
    submitRebateExcelBatch() {
      const u = this.$refs.rebateExcelUploader
      const uploadFiles = (u && u.uploadFiles) ? u.uploadFiles : []
      const files = uploadFiles.map((f) => f.raw).filter(Boolean)
      if (!files.length) {
        this.$message.warning('请先选择 Excel 文件')
        return
      }
      const formData = new FormData()
      files.forEach((file) => formData.append('files', file))
      const title = (this.rebateImportTitle || '').trim()
      if (files.length === 1 && title) {
        formData.append('documentTitle', title)
      }
      this.rebateImportLoading = true
      importGroupRebateExcelBatch(formData)
        .then((res) => {
          const data = res.data || {}
          const msg = data.message || res.msg || '已处理'
          if (data.failCount > 0) {
            this.$message.warning(msg)
          } else {
            this.$message.success(msg)
          }
          this.clearRebateExcelUploaderFiles()
          this.rebateImportDialogVisible = false
          this.getList()
        })
        .catch((e) => {
          this.$message.error(e.message || '提交失败')
        })
        .finally(() => {
          this.rebateImportLoading = false
        })
    },
    openRebateUploadRecordDialog() {
      this.rebateUploadQuery.pageNum = 1
      this.rebateUploadRecordDialogVisible = true
    },
    fetchRebateUploadList() {
      this.rebateUploadLoading = true
      listGroupRebateExcelUploads(this.rebateUploadQuery).then(res => {
        this.rebateUploadList = res.rows || []
        this.rebateUploadTotal = res.total || 0
      }).finally(() => {
        this.rebateUploadLoading = false
      })
    },
    formatUploadFileSize(n) {
      if (n == null || n === '') return '-'
      const x = Number(n)
      if (Number.isNaN(x) || x < 0) return '-'
      if (x < 1024) return `${x} B`
      if (x < 1024 * 1024) return `${(x / 1024).toFixed(1)} KB`
      return `${(x / 1024 / 1024).toFixed(2)} MB`
    },
    downloadRebateUploadFile(row) {
      const name = row.originalFilename || `rebate_upload_${row.id}.xlsx`
      this.download(`/system/jdorder/groupRebateUpload/download/${row.id}`, {}, name)
    },
    confirmDeleteRebateUpload(row) {
      const title = row.documentTitle || row.originalFilename || ('ID ' + row.id)
      this.$confirm(
        `将删除上传记录「${title}」，并尝试从订单中移除本次导入写入的后返备注。历史导入（无上传批次标记）可能无法自动清除订单备注，是否继续？`,
        '删除后返上传记录',
        { type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' }
      ).then(() => {
        return deleteGroupRebateUpload(row.id)
      }).then((res) => {
        const data = res.data || {}
        const msg = data.message || res.msg || '已删除'
        this.$message.success(msg)
        this.fetchRebateUploadList()
        this.getList()
      }).catch((e) => {
        if (e !== 'cancel') {
          this.$message.error((e && e.message) || '删除失败')
        }
      })
    },
    resetQuery() {
      this.queryParams = {
        pageNum: 1,
        pageSize: this.isMobile ? MOBILE_JD_ORDER_PAGE_SIZE : 50,
        remark: undefined,
        orderSearch: undefined,
        distributionMark: undefined,
        modelNumber: undefined,
        modelShop: undefined,
        modelNumberExclude: undefined,
        link: undefined,
        buyer: undefined,
        address: undefined,
        status: undefined,
        beginTime: null,
        endTime: null,
        orderBy: 'create_time',
        isAsc: 'desc',
        hasFinishTime: false,
        isRefunded: undefined,
        isRefundReceived: undefined,
        isRebateReceived: undefined,
        isPriceProtected: undefined,
        isInvoiceOpened: undefined,
        isReviewPosted: undefined,
        hasRebateRemark: undefined,
        rebateRemarkHasAbnormal: undefined,
        rebateWithoutUploadLink: undefined
      }
      this.rebateRemarkScreen = undefined
      // 重置排序为默认降序
      this.queryParams.orderBy = 'create_time'
      this.queryParams.isAsc = 'desc'
      // 重置后重新设置默认日期为今天
      this.setDefaultDateRange()
      this.getListWithFallback()
    },
    /** 日期范围变化处理 */
    handleDateRangeChange(dates) {
      if (dates && dates.length === 2) {
        this.queryParams.beginTime = dates[0]
        this.queryParams.endTime = dates[1]
      } else {
        this.queryParams.beginTime = null
        this.queryParams.endTime = null
      }
    },
    /** 表格排序变化处理 */
    handleSortChange(sortInfo) {
      if (sortInfo && sortInfo.prop === 'createTime') {
        if (sortInfo.order === 'ascending') {
          this.queryParams.orderBy = 'create_time'
          this.queryParams.isAsc = 'asc'
        } else if (sortInfo.order === 'descending') {
          this.queryParams.orderBy = 'create_time'
          this.queryParams.isAsc = 'desc'
        } else {
          // 取消排序，恢复默认
          this.queryParams.orderBy = 'create_time'
          this.queryParams.isAsc = 'desc'
        }
        // 重新查询数据
        this.queryParams.pageNum = 1
        this.getList()
      }
    },
    toYuan(n) {
      if (n == null || n === '') return ''
      const num = Number(n)
      if (Number.isNaN(num)) return n
      return num.toFixed(2)
    },
    /** 录单 Excel：成本 = 下单付款 − 后返 + 额外成本（与后台自动利润口径一致） */
    formatExcelCost(row) {
      if (!row) return ''
      const hasPay = row.paymentAmount != null && row.paymentAmount !== ''
      const hasReb = row.rebateAmount != null && row.rebateAmount !== ''
      if (!hasPay && !hasReb) return ''
      const pay = hasPay ? Number(row.paymentAmount) : 0
      const reb = hasReb ? Number(row.rebateAmount) : 0
      const extra = row.extraCost != null && row.extraCost !== '' ? Number(row.extraCost) : 0
      return (pay - reb + extra).toFixed(2)
    },
    /** 保存后拉取单条，展示服务端重算后的利润/售价 */
    patchOrderRowFromServer(id) {
      if (id == null) return
      getJDOrder(id)
        .then(res => {
          const raw = res && res.data
          if (!raw) return
          const idx = this.list.findIndex(r => r.id === id)
          if (idx === -1) return
          const merged = this.normalizeOrderListItem({ ...this.list[idx], ...raw })
          this.$set(this.list, idx, merged)
        })
        .catch(() => {})
    },
    /**
     * 单行保存 PUT（防抖）：合并短时间内的多次触发，避免 ElementUI input-number 等在失焦时与 change 叠加，
     * 连续两次相同 URL 请求触发若依「请勿重复提交」。
     */
    persistOrderRow(row, successMsg) {
      if (!row || row.id == null) {
        return Promise.resolve()
      }
      if (this._listHydrating) {
        return Promise.resolve()
      }
      this.ensureMoneyFieldsForPersist(row)
      const sid = String(row.id)
      if (!this._persistOrderTimers) this._persistOrderTimers = {}
      if (!this._persistOrderPendingMsg) this._persistOrderPendingMsg = {}
      if (this._persistOrderTimers[sid]) {
        clearTimeout(this._persistOrderTimers[sid])
      }
      if (successMsg) {
        this._persistOrderPendingMsg[sid] = successMsg
      }
      this._persistOrderTimers[sid] = setTimeout(() => {
        this._persistOrderTimers[sid] = null
        const msg =
          this._persistOrderPendingMsg && this._persistOrderPendingMsg[sid] != null
            ? this._persistOrderPendingMsg[sid]
            : null
        delete this._persistOrderPendingMsg[sid]
        this.flushPersistOrderRow(row, msg)
      }, 340)
    },
    /**
     * PUT /system/jdorder：若依 SameUrlDataInterceptor 判定「同 URL + 同 body + 短间隔」为重复提交；
     * 移动端多张卡片内控件挂载时可能对同一行连发两次相同 payload，此处丢弃后者。
     */
    performJDOrderUpdate(row) {
      if (!row || row.id == null) {
        return Promise.reject(new Error('无效订单'))
      }
      const plain = normalizeJDOrderPutPayload(row)
      let serialized = ''
      try {
        serialized = JSON.stringify(plain)
      } catch (e) {
        serialized = ''
      }
      const fp = `${plain.id}\u0000${serialized}`
      const now = Date.now()
      const windowMs = 550
      if (
        fp === this._jdPutDedupeFingerprint &&
        now - this._jdPutDedupeAt < windowMs
      ) {
        return Promise.resolve({ skipped: true })
      }
      this._jdPutDedupeFingerprint = fp
      this._jdPutDedupeAt = now
      return updateJDOrder(row)
        .then(res => ({ skipped: false, res }))
        .catch(err => {
          if (`${plain.id}\u0000${serialized}` === this._jdPutDedupeFingerprint) {
            this._jdPutDedupeFingerprint = null
            this._jdPutDedupeAt = 0
          }
          return Promise.reject(err)
        })
    },
    flushPersistOrderRow(row, successMsg) {
      if (!row || row.id == null) {
        return
      }
      this.ensureMoneyFieldsForPersist(row)
      this.invalidatePendingSyncAutoProfit()
      this.performJDOrderUpdate(row)
        .then(pack => {
          if (pack.skipped) return
          if (successMsg) this.$message.success(successMsg)
          this.schedulePatchOrderRowFromServer(row.id)
        })
        .catch(() => {
          this.$message.error('保存失败')
          this.getList()
        })
    },
    /** 上传前兜底：避免出现 undefined/null 不入 JSON，后端跳过更新列 */
    ensureMoneyFieldsForPersist(row) {
      if (!row) return
      if (row.extraCost == null || row.extraCost === '') {
        row.extraCost = 0
      }
    },
    saveThirdPartyOrderNoIfFilled(row, successMsg) {
      const v = row.thirdPartyOrderNo == null ? '' : String(row.thirdPartyOrderNo).trim().replace(/\s+/g, '')
      if (!v) {
        row.thirdPartyOrderNo = ''
        return
      }
      row.thirdPartyOrderNo = v
      this.persistOrderRow(row, successMsg)
    },
    onThirdPartyOrderNoBlur(row) {
      this.saveThirdPartyOrderNoIfFilled(row)
    },
    onThirdPartyOrderNoSave(row) {
      this.saveThirdPartyOrderNoIfFilled(row, '第三方单号已保存')
    },
    /** 分销标识：去首尾空白、合并连续空白（与录单行习惯一致） */
    normalizeDistributionMarkInput(v) {
      if (v == null) return ''
      return String(v).trim().replace(/\s+/g, ' ')
    },
    /** 分销标识失焦或点保存时写入数据库（与基线一致则不调接口） */
    saveDistributionMarkIfChanged(row, successMsg) {
      if (row == null || row.id == null) return
      const next = this.normalizeDistributionMarkInput(row.distributionMark)
      row.distributionMark = next
      const base = this._distMarkBaseline[row.id] != null ? this._distMarkBaseline[row.id] : ''
      if (next === base) return
      this.persistOrderRow(row, successMsg)
    },
    /** 型号：去首尾空白（内部保留，避免误改版式） */
    normalizeModelNumberInput(v) {
      if (v == null) return ''
      return String(v).trim()
    },
    normalizeModelShopInput(v) {
      if (v == null) return ''
      return String(v).trim()
    },
    fullModelNumber(row) {
      if (!row) return ''
      const base = this.normalizeModelNumberInput(row.modelNumber)
      const shop = this.normalizeModelShopInput(row.modelShop)
      if (!base) return shop
      if (!shop) return base
      if (base.endsWith(shop)) return base
      return base + shop
    },
    async loadShopOptions() {
      try {
        const res = await listQuickRecordShopOptions()
        if (!(res && (res.code === 200 || res.msg === '操作成功'))) return
        const rows = Array.isArray(res.data) ? res.data : []
        this.shopOptions = rows
          .filter(o => o && String(o.prefix || '').trim())
          .map(o => ({
            prefix: String(o.prefix).trim(),
            label: o.label || o.prefix
          }))
          .sort((a, b) => b.prefix.length - a.prefix.length)
      } catch (e) {
        this.shopOptions = []
      }
    },
    parseModelWithShopFromOptions(fullModel) {
      const full = String(fullModel || '').trim()
      if (!full || !this.shopOptions.length) return { base: full, shop: '' }
      for (const opt of this.shopOptions) {
        const p = opt.prefix
        if (p && full.endsWith(p) && full.length > p.length) {
          return { base: full.slice(0, -p.length), shop: p }
        }
      }
      return { base: full, shop: '' }
    },
    /** 型号/店铺变更后写入数据库（与基线一致则不调接口） */
    saveModelFieldsIfChanged(row, successMsg) {
      if (row == null || row.id == null) return
      const parsed = this.parseModelWithShopFromOptions(row.modelNumber)
      if (parsed.prefix) {
        row.modelNumber = parsed.base
        row.modelShop = parsed.shop
      }
      const nextBase = this.normalizeModelNumberInput(row.modelNumber)
      const nextShop = this.normalizeModelShopInput(row.modelShop)
      row.modelNumber = nextBase
      row.modelShop = nextShop
      const baseNum = this._modelNumberBaseline[row.id] != null ? this._modelNumberBaseline[row.id] : ''
      const baseShop = this._modelShopBaseline[row.id] != null ? this._modelShopBaseline[row.id] : ''
      if (nextBase === baseNum && nextShop === baseShop) return
      this.persistOrderRow(row, successMsg)
    },
    onModelNumberBlur(row) {
      this.onModelFieldBlur(row)
    },
    onModelNumberSave(row) {
      this.saveModelFieldsIfChanged(row, '型号已保存')
    },
    onModelFieldBlur(row) {
      this.saveModelFieldsIfChanged(row)
    },
    onModelShopChange(row) {
      this.saveModelFieldsIfChanged(row, '型号店铺已保存')
    },
    handleMigrateModelShop() {
      this.$confirm('将按「快捷录单店铺选项」配置，扫描全部订单：若型号末尾匹配店铺前缀，则写入「型号店铺」并从型号中截掉。是否继续？', '拆分型号店铺', {
        type: 'warning'
      }).then(() => {
        this.modelShopMigrateLoading = true
        return migrateModelShopSplit()
      }).then(res => {
        const data = (res && res.data) || {}
        this.$message.success(data.message || '迁移完成')
        this.getList()
      }).catch(e => {
        if (e !== 'cancel') {
          this.$message.error((e && e.message) || '迁移失败')
        }
      }).finally(() => {
        this.modelShopMigrateLoading = false
      })
    },
    onOrderSellingPriceTypeChange(row) {
      row.sellingPriceManual = 0
      row.profitManual = 0
      this.persistOrderRow(row)
    },
    /** 付款/后返变更：按规则重算利润（解除利润手填；已退款订单后端会把利润置空） */
    onOrderPaymentOrRebateChange(row) {
      row.profitManual = 0
      this.persistOrderRow(row)
    },
    /** 额外成本变更：解除利润手填并按规则重算 */
    onOrderExtraCostChange(row) {
      row.profitManual = 0
      this.persistOrderRow(row)
    },
    onOrderSellingPriceChange(row) {
      row.sellingPriceManual = 1
      row.profitManual = 0
      this.persistOrderRow(row)
    },
    onOrderProfitChange(row) {
      row.profitManual = 1
      this.persistOrderRow(row)
    },
    fillSellingPriceFromConfig(row) {
      row.sellingPriceManual = 0
      row.profitManual = 0
      this.persistOrderRow(row, '已按型号配置回填售价并重算利润')
    },
    recalcOrderProfitOnly(row) {
      row.profitManual = 0
      this.persistOrderRow(row, '已重算利润')
    },
    handleBatchRecalcProfit() {
      if (!this.selectedRows || this.selectedRows.length === 0) {
        this.$message.warning('请先勾选订单')
        return
      }
      this.loading = true
      recalcProfitBatch(this.selectedRows.map(r => r.id))
        .then(() => {
          this.$message.success('批量重算完成')
          this.getList()
        })
        .catch((e) => {
          this.$message.error((e && e.message) || '批量重算失败')
        })
        .finally(() => {
          this.loading = false
        })
    },
    /** 复制篮子群「发货摘要」：型号 + 整段地址（去空白） + 物流短链 */
    buildBasketShipSummaryText(row) {
      if (!row) return ''
      const model = this.fullModelNumber(row) || '—'
      const addrRaw = row.address != null ? String(row.address).trim() : ''
      const addr = (addrRaw.replace(/\s+/g, '')) || '—'
      const url = this.normalizeBasketLogisticsUrl(row.logisticsLink)
      const sep = '————————————'
      return `「发货摘要」\n${sep}\n型号： ${model}\n地址：${addr}\n物流：${url}\n`
    },
    normalizeBasketLogisticsUrl(link) {
      if (link == null || !String(link).trim()) return '—'
      let u = String(link).trim()
      if (!/^https?:\/\//i.test(u)) {
        u = 'https://' + u.replace(/^\/+/, '')
      }
      return u
    },
    copyBasketShipSummary(row) {
      this.copyToClipboard(this.buildBasketShipSummaryText(row), '已复制篮子发货摘要')
    },
    /** 导出按钮操作 */
    handleExport() {
      this.prepareQueryParams()
      this.download('/system/jdorder/export', this.queryParams, `京东订单数据_${new Date().getTime()}.xlsx`)
    },
    /** 复制到剪贴板；successMsg 不传时用默认提示 */
    copyToClipboard(text, successMsg) {
      const tip = successMsg || '已复制到剪贴板'
      if (navigator.clipboard && window.isSecureContext) {
        // 使用现代 Clipboard API
        navigator.clipboard.writeText(text).then(() => {
          this.$message.success(tip)
        }).catch(() => {
          this.fallbackCopyTextToClipboard(text, tip)
        })
      } else {
        // 降级方案
        this.fallbackCopyTextToClipboard(text, tip)
      }
    },
    /** 降级复制方案 */
    fallbackCopyTextToClipboard(text, successMsg) {
      const tip = successMsg || '已复制到剪贴板'
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'fixed'
      textArea.style.left = '-999999px'
      textArea.style.top = '-999999px'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()

      try {
        const successful = document.execCommand('copy')
        if (successful) {
          this.$message.success(tip)
        } else {
          this.$message.error('复制失败，请手动复制')
        }
      } catch (err) {
        this.$message.error('复制失败，请手动复制')
      }

      document.body.removeChild(textArea)
    },
    /** 处理统计开关变化 */
    handleCountEnabledChange(row) {
      if (this._listHydrating) return
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的统计状态已更新为：${row.isCountEnabled ? '参与统计' : '不参与统计'}`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isCountEnabled = row.isCountEnabled ? 0 : 1
      })
    },
    /** 切换退款状态（标签点击） */
    toggleRefunded(row) {
      const oldValue = row.isRefunded
      row.isRefunded = row.isRefunded === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isRefunded === 1 && !row.refundDate) {
        row.refundDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRefunded === 0) {
        row.refundDate = null
      }
      this.invalidatePendingSyncAutoProfit()
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
        this.schedulePatchOrderRowFromServer(row.id)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRefunded = oldValue
        if (row.isRefunded === 0) {
          row.refundDate = null
        }
      })
    },
    /** 处理是否退款开关变化 */
    handleRefundedChange(row) {
      // 如果设置为"是"，自动设置当前日期
      if (row.isRefunded === 1 && !row.refundDate) {
        row.refundDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRefunded === 0) {
        row.refundDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRefunded = row.isRefunded ? 0 : 1
        if (row.isRefunded === 0) {
          row.refundDate = null
        }
      })
    },
    /** 切换退款到账状态（标签点击） */
    toggleRefundReceived(row) {
      const oldValue = row.isRefundReceived
      row.isRefundReceived = row.isRefundReceived === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isRefundReceived === 1 && !row.refundReceivedDate) {
        row.refundReceivedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRefundReceived === 0) {
        row.refundReceivedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRefundReceived = oldValue
        if (row.isRefundReceived === 0) {
          row.refundReceivedDate = null
        }
      })
    },
    /** 处理是否退款到账开关变化 */
    handleRefundReceivedChange(row) {
      // 如果设置为"是"，自动设置当前日期
      if (row.isRefundReceived === 1 && !row.refundReceivedDate) {
        row.refundReceivedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRefundReceived === 0) {
        row.refundReceivedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRefundReceived = row.isRefundReceived ? 0 : 1
        if (row.isRefundReceived === 0) {
          row.refundReceivedDate = null
        }
      })
    },
    /** 切换后返到账状态（标签点击） */
    toggleRebateReceived(row) {
      const oldValue = row.isRebateReceived
      row.isRebateReceived = row.isRebateReceived === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isRebateReceived === 1 && !row.rebateReceivedDate) {
        row.rebateReceivedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRebateReceived === 0) {
        row.rebateReceivedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRebateReceived = oldValue
        if (row.isRebateReceived === 0) {
          row.rebateReceivedDate = null
        }
      })
    },
    /** 处理后返到账开关变化 */
    handleRebateReceivedChange(row) {
      // 如果设置为"是"，自动设置当前日期
      if (row.isRebateReceived === 1 && !row.rebateReceivedDate) {
        row.rebateReceivedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isRebateReceived === 0) {
        row.rebateReceivedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isRebateReceived = row.isRebateReceived ? 0 : 1
        if (row.isRebateReceived === 0) {
          row.rebateReceivedDate = null
        }
      })
    },
    /** 切换点过价保状态（标签点击） */
    togglePriceProtected(row) {
      const oldValue = row.isPriceProtected
      row.isPriceProtected = row.isPriceProtected === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isPriceProtected === 1 && !row.priceProtectedDate) {
        row.priceProtectedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isPriceProtected === 0) {
        row.priceProtectedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的点过价保状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isPriceProtected = oldValue
        if (row.isPriceProtected === 0) {
          row.priceProtectedDate = null
        }
      })
    },
    /** 切换开过专票状态（标签点击） */
    toggleInvoiceOpened(row) {
      const oldValue = row.isInvoiceOpened
      row.isInvoiceOpened = row.isInvoiceOpened === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isInvoiceOpened === 1 && !row.invoiceOpenedDate) {
        row.invoiceOpenedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isInvoiceOpened === 0) {
        row.invoiceOpenedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的开过专票状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isInvoiceOpened = oldValue
        if (row.isInvoiceOpened === 0) {
          row.invoiceOpenedDate = null
        }
      })
    },
    /** 切换晒过评价状态（标签点击） */
    toggleReviewPosted(row) {
      const oldValue = row.isReviewPosted
      row.isReviewPosted = row.isReviewPosted === 1 ? 0 : 1
      // 如果设置为"是"，自动设置当前日期
      if (row.isReviewPosted === 1 && !row.reviewPostedDate) {
        row.reviewPostedDate = new Date()
      }
      // 如果设置为"否"，清空日期
      if (row.isReviewPosted === 0) {
        row.reviewPostedDate = null
      }
      // 调用后端API更新数据库
      this.performJDOrderUpdate(row).then(pack => {
        if (pack.skipped) return
        this.$message.success(`订单 ${row.remark} 的晒过评价状态已更新`)
      }).catch(() => {
        this.$message.error('更新失败，请稍后重试')
        // 恢复原状态
        row.isReviewPosted = oldValue
        if (row.isReviewPosted === 0) {
          row.reviewPostedDate = null
        }
      })
    },
    /** 删除单条记录（需输入随机确认码） */
    async handleDelete(row) {
      const code = String(Math.floor(100000 + Math.random() * 900000))
      try {
        await this.$prompt(`请输入确认码以删除该订单：${code}`, '删除确认', {
          confirmButtonText: '删除',
          cancelButtonText: '取消',
          inputPlaceholder: '请输入上方确认码',
          inputValidator: (value) => {
            if (value === code) return true
            return '确认码不匹配，请重新输入'
          },
          inputErrorMessage: '确认码不匹配',
          type: 'warning',
          dangerouslyUseHTMLString: false
        })
      } catch (e) {
        return
      }

      this.loading = true
      try {
        await delJDOrder(row.id)
        this.$message.success('删除成功')
        this.getList()
      } catch (e) {
        this.$message.error('删除失败，请稍后重试')
      } finally {
        this.loading = false
      }
    },
    
    /** 批量同步物流到腾讯文档 */
    async handleBatchSyncLogistics() {
      try {
        // 先检查配置是否完整
        const configRes = await getAutoWriteConfig()
        if (configRes.code !== 200 || !configRes.data || !configRes.data.isConfigured) {
          this.$confirm('检测到尚未完成H-TF自动写入配置，是否现在配置？', '提示', {
            type: 'warning'
          }).then(() => {
            this.showAutoWriteConfig = true
          })
          return
        }
        
        const config = configRes.data
        
        // 构建确认消息
        let confirmMsg = '批量同步将从腾讯文档中搜索订单并填充物流链接\n\n'
        confirmMsg += `文档: ${config.fileId}\n`
        confirmMsg += `工作表: ${config.sheetId}\n`
        confirmMsg += `表头行: ${config.headerRow}\n`
        confirmMsg += `数据起始行: ${config.startRow}\n`
        
        if (config.currentProgress) {
          confirmMsg += `\n表格行数: 第 ${config.currentProgress} 行（接口获取）\n`
          confirmMsg += (config.progressHint || '') + '\n'
        }
        
        confirmMsg += `\n防重推送: ${config.skipPushedOrders ? '已启用（跳过已推送订单）' : '已禁用'}\n`
        confirmMsg += '\n⚠️ 注意：\n'
        confirmMsg += '- 系统会自动跳过已有物流链接的行\n'
        confirmMsg += '- 系统会自动跳过已标记为"已推送"的订单\n'
        confirmMsg += '- 所有操作都会记录到操作日志\n'
        
        // 确认同步
        await this.$confirm(confirmMsg, '批量同步物流确认', {
          type: 'info',
          confirmButtonText: '开始同步',
          cancelButtonText: '取消'
        })
        
        this.batchSyncLoading = true
        
        // 调用批量同步API
        const res = await fillLogisticsByOrderNo({})
        
        if (res.code === 200) {
          const data = res.data || {}
          this.$notify({
            title: '批量同步完成',
            message: `✓ 成功填充: ${data.filledCount || 0} 条\n⊙ 跳过: ${data.skippedCount || 0} 条\n✗ 错误: ${data.errorCount || 0} 条\n\n${data.message || ''}`,
            type: 'success',
            duration: 10000,
            dangerouslyUseHTMLString: false
          })
        } else {
          this.$message.error(res.msg || '同步失败')
        }
      } catch (e) {
        if (e !== 'cancel') {
          this.$message.error('操作失败：' + (e.message || '未知错误'))
          console.error('批量同步失败', e)
        }
      } finally {
        this.batchSyncLoading = false
      }
    },
    
    /** 打开授权页面并等待授权完成 */
    async openAuthAndWait() {
      try {
        // 获取授权URL
        const authUrlRes = await getTencentDocAuthUrl()
        if (authUrlRes.code !== 200 || !authUrlRes.data) {
          this.$message.error('获取授权URL失败')
          return
        }
        
        const authUrl = authUrlRes.data
        
        // 打开授权页面
        this.$message.info('正在打开授权页面，请完成授权后继续...')
        const width = 600
        const height = 700
        const left = (window.screen.width - width) / 2
        const top = (window.screen.height - height) / 2
        
        const authWindow = window.open(
          authUrl,
          '腾讯文档授权',
          `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`
        )
        
        // 监听窗口关闭事件（备用方案，如果postMessage失效）
        const checkWindowClosed = setInterval(() => {
          if (authWindow.closed) {
            clearInterval(checkWindowClosed)
            // 等待1秒后检查token状态（作为备用验证）
            setTimeout(async () => {
              try {
                const tokenStatusRes = await getTokenStatus()
                if (tokenStatusRes.data && tokenStatusRes.data.hasToken) {
                  // 如果已经通过postMessage收到成功消息，这里不再重复提示
                } else {
                  // 如果没有收到postMessage，可能是授权失败
                  this.$message.warning('授权未完成，请重新尝试')
                }
              } catch (e) {
                // 静默处理，避免重复提示
              }
            }, 1000)
          }
        }, 1000)
        
      } catch (e) {
        this.$message.error('打开授权页面失败: ' + (e.message || '未知错误'))
        console.error('打开授权页面失败', e)
      }
    },
    
    /** 检查后端token状态 */
    async checkTokenStatus() {
      try {
        const res = await getTokenStatus()
        if (res.code === 200 && res.data) {
          this.tokenValid = res.data.hasToken === true
        } else {
          this.tokenValid = false
        }
      } catch (e) {
        console.error('检查token状态失败', e)
        this.tokenValid = false
      } finally {
        this.tokenStatusChecked = true
      }
    },
    
    /** 测试获取用户信息接口 */
    async handleTestUserInfo() {
      try {
        this.$message.info('正在测试用户信息接口...')
        const res = await testUserInfo()
        if (res.code === 200) {
          this.$message.success('测试成功！用户信息：' + JSON.stringify(res.data, null, 2))
          // 显示详细信息
          this.$alert(
            '<pre style="text-align: left; max-height: 400px; overflow: auto;">' + 
            JSON.stringify(res.data, null, 2) + 
            '</pre>',
            '用户信息测试结果',
            {
              dangerouslyUseHTMLString: true,
              confirmButtonText: '确定',
              type: 'success'
            }
          )
        } else {
          this.$message.error('测试失败：' + (res.msg || '未知错误'))
        }
      } catch (e) {
        this.$message.error('测试失败：' + (e.message || '未知错误'))
        console.error('测试用户信息失败', e)
      }
    },
    
    /** 同步物流链接 */
    async handleSyncLogisticsSubmit() {
      try {
        // 后端会自动从配置中读取 fileId、sheetId、startRow 等参数
        // 前端只需传递空对象即可
        const res = await fillLogisticsByOrderNo({})
        
        if (res.code === 200) {
          const data = res.data || {}
          this.$message.success(
            `同步成功！成功填充 ${data.filledCount || 0} 条，跳过 ${data.skippedCount || 0} 条，错误 ${data.errorCount || 0} 条`
          )
        } else {
          this.$message.error(res.msg || '同步失败')
        }
      } catch (e) {
        this.$message.error('同步失败：' + (e.message || '未知错误'))
        console.error('同步物流失败', e)
      }
    },
    
    /** 手动获取物流信息 */
    async handleFetchLogistics(row) {
      if (!row || !row.id) {
        return
      }
      this.fetchLogisticsDialogVisible = true
      this.fetchLogisticsLoading = true
      this.fetchLogisticsResult = null

      if (!row.logisticsLink || !row.logisticsLink.trim()) {
        this.fetchLogisticsLoading = false
        this.fetchLogisticsResult = {
          success: false,
          error: '该订单暂无物流链接，无法调用扫描服务。请先补充物流链接后再试。',
          orderId: row.id,
          orderNo: row.orderId
        }
        return
      }

      try {
        const res = await fetchLogisticsManually({ orderId: row.id })

        if (res.code === 200) {
          this.fetchLogisticsResult = {
            success: true,
            ...res.data
          }
          this.$message.success('获取物流信息成功，数据已记录到日志文件')
        } else {
          this.fetchLogisticsResult = {
            success: false,
            error: res.msg || '获取失败',
            orderId: row.id,
            orderNo: row.orderId
          }
          this.$message.error(res.msg || '获取物流信息失败')
        }
      } catch (e) {
        this.fetchLogisticsResult = {
          success: false,
          error: e.message || '请求异常',
          orderId: row.id,
          orderNo: row.orderId
        }
        this.$message.error('获取物流信息失败: ' + (e.message || '未知错误'))
        console.error('获取物流信息失败', e)
      } finally {
        this.fetchLogisticsLoading = false
      }
    },
    
    /** 复制获取物流信息的结果 */
    copyFetchLogisticsResult() {
      if (!this.fetchLogisticsResult) return
      
      const resultText = JSON.stringify(this.fetchLogisticsResult, null, 2)
      this.copyToClipboard(resultText)
    },

    /** H-TF订单自动写入配置更新后的回调 */
    handleAutoConfigUpdated() {
      this.$message.success('H-TF订单自动写入配置已更新')
    },

    /** 分销标识接收人配置更新后的回调 */
    handleTouserConfigUpdated() {
      this.$message.success('分销标识接收人配置已更新')
    },

    /** 批量标记后返到账（赔付金额>0的订单） */
    async handleBatchMarkRebateReceived() {
      try {
        // 确认操作
        await this.$confirm(
          '此操作将批量将赔付金额大于0的订单标记为后返到账。\n\n' +
          '⚠️ 注意：此操作只应执行一次，用于处理历史数据。\n\n' +
          '是否继续？',
          '批量标记后返到账',
          {
            type: 'warning',
            confirmButtonText: '确定执行',
            cancelButtonText: '取消'
          }
        )

        this.batchMarkLoading = true
        const res = await batchMarkRebateReceived()
        
        if (res && (res.code === 200 || res.msg === '操作成功' || res.msg === '查询成功')) {
          this.$message.success(res.msg || '批量标记后返到账完成，请查看控制台日志')
          // 刷新列表
          this.getList()
        } else {
          this.$message.error(res && res.msg ? res.msg : '批量标记失败')
        }
      } catch (e) {
        if (e !== 'cancel') {
          this.$message.error('批量标记失败: ' + (e.message || '未知错误'))
          console.error('批量标记后返到账失败', e)
        }
      } finally {
        this.batchMarkLoading = false
      }
    },

    /** 获取订单状态文本 */
    getOrderStatusText(status) {
      const statusMap = {
        '-100': '无变化',
        '-1': '未知',
        2: '无效-拆单',
        3: '无效-取消',
        4: '无效-京东帮帮主订单',
        5: '无效-账号异常',
        6: '无效-赠品类目不返佣',
        7: '无效-校园订单',
        8: '无效-企业订单',
        9: '无效-团购订单',
        11: '无效-乡村推广员下单',
        13: '违规订单-其他',
        14: '无效-来源与备案网址不符',
        15: '待付款',
        16: '已付款',
        17: '已完成',
        19: '无效-佣金比例为0',
        20: '无效-此复购订单对应的首购订单无效',
        21: '无效-云店订单',
        22: '无效-PLUS会员佣金比例为0',
        23: '无效-支付有礼',
        24: '已付定金',
        25: '违规订单-流量劫持',
        26: '违规订单-流量异常',
        27: '违规订单-违反京东平台规则',
        28: '违规订单-多笔交易异常',
        29: '无效-跨屏跨店',
        30: '无效-累计件数超出类目上限',
        31: '无效-黑名单sku',
        33: '超市卡充值订单',
        34: '无效-推卡订单无效'
      }
      return statusMap[status] || `状态${status}`
    },

    /** 获取订单状态文本（短版，用于表格窄列） */
    getOrderStatusTextShort(status) {
      const statusMap = {
        '-100': '无变化',
        '-1': '未知',
        2: '拆单',
        3: '取消',
        4: '帮帮主',
        5: '账号异常',
        6: '赠品不返',
        7: '校园单',
        8: '企业单',
        9: '团购单',
        11: '乡村推广',
        13: '违规其他',
        14: '网址不符',
        15: '待付款',
        16: '已付款',
        17: '已完成',
        19: '佣金0',
        20: '首购无效',
        21: '云店单',
        22: 'PLUS佣金0',
        23: '支付有礼',
        24: '已付定',
        25: '流量劫持',
        26: '流量异常',
        27: '违规规则',
        28: '交易异常',
        29: '跨屏跨店',
        30: '超上限',
        31: '黑名单',
        33: '超市卡',
        34: '推卡无效'
      }
      return statusMap[status] || `${status}`
    },

    /** 获取订单状态标签类型 */
    getOrderStatusType(status) {
      // 取消状态（优先级最高）
      if (status === 3) return 'danger' // 无效-取消（红色，优先级高于违规）
      // 正常状态
      if (status === 16) return 'success' // 已付款
      if (status === 17) return 'success' // 已完成
      if (status === 15) return 'warning' // 待付款
      if (status === 24) return 'warning' // 已付定金
      // 违规状态
      if ([13, 25, 26, 27, 28].includes(status)) return 'warning' // 违规订单（黄色，优先级低于取消）
      // 无效状态
      if ([2, 4, 5, 6, 7, 8, 9, 11, 14, 19, 20, 21, 22, 23, 29, 30, 31, 34].includes(status)) return 'info' // 无效订单
      if (status === 33) return 'success' // 超市卡充值订单
      return 'info' // 其他状态
    },

    /** 准备查询参数：仅去除空格，保留日期等所有搜索条件 */
    prepareQueryParams() {
      const textKeys = ['remark', 'orderSearch', 'distributionMark', 'modelNumber', 'link', 'buyer', 'address', 'status']

      textKeys.forEach(key => {
        const value = this.queryParams[key]
        if (typeof value === 'string') {
          const trimmed = value.trim()
          this.queryParams[key] = trimmed || undefined
        }
      })

      const exRaw = this.queryParams.modelNumberExclude
      if (typeof exRaw === 'string') {
        const trimmed = exRaw.trim()
        this.queryParams.modelNumberExclude = trimmed || undefined
      }
    },

    /** 退货复制 */
    copyReturnInfo(row) {
      const toLine = (v) => (v == null ? '' : String(v).trim())
      const parts = []
      // 既有顺序保持不变
      parts.push(toLine(row.remark))                  // 内部单号
      parts.push(toLine(row.orderId))                 // 订单号
      parts.push(toLine(this.fullModelNumber(row)))             // 型号
      parts.push(toLine(row.thirdPartyOrderNo))       // 第三方单号
      parts.push(toLine(row.distributionMark))        // 分销标记
      parts.push(toLine(row.address))                 // 地址
      // 新增：金额与物流
      parts.push(row.paymentAmount != null && row.paymentAmount !== '' ? this.toYuan(row.paymentAmount) : '') // 付款金额
      parts.push(row.rebateAmount != null && row.rebateAmount !== '' ? this.toYuan(row.rebateAmount) : '')    // 后返金额
      parts.push(toLine(row.logisticsLink))           // 物流链接
      // 末尾：下单人
      parts.push(toLine(row.buyer))                   // 下单人

      const text = parts.join('\n')
      this.copyToClipboard(text)
    },

    /** 复制单条订单的录单格式文本到剪贴板 */
    copySingleOrderExcelText(row) {
      try {
        // 日期（格式：yyyy/MM/dd）
        let dateStr = ''
        if (row.orderTime) {
          const date = new Date(row.orderTime)
          const year = date.getFullYear()
          const month = String(date.getMonth() + 1).padStart(2, '0')
          const day = String(date.getDate()).padStart(2, '0')
          dateStr = `${year}/${month}/${day}`
        }
        
        // 多多单号（第三方单号，如果没有则使用内部单号）
        const duoduoOrderNo = (row.thirdPartyOrderNo && row.thirdPartyOrderNo.trim()) 
          ? row.thirdPartyOrderNo : (row.remark || '')
        
        // 型号
        const modelNumber = this.fullModelNumber(row)
        
        // 数量（固定为1）
        const quantity = '1'
        
        // 地址
        const address = row.address || ''
        
        // 姓名（从地址中提取，地址格式通常是"姓名 电话 详细地址"）
        let buyer = ''
        if (address) {
          // 提取地址中的第一个词作为姓名
          const addressParts = address.trim().split(/\s+/)
          if (addressParts.length > 0) {
            buyer = addressParts[0]
          }
        }
        
        const sellingPriceStr = row.sellingPrice != null && row.sellingPrice !== '' ? Number(row.sellingPrice).toFixed(2) : '0'
        const costStr = this.formatExcelCost(row)
        const profitStr = row.profit != null && row.profit !== '' ? Number(row.profit).toFixed(2) : ''
        
        // 京东单号
        const orderId = row.orderId || ''
        
        // 物流链接
        const logisticsLink = row.logisticsLink || ''
        
        // 下单付款
        const paymentAmountStr = row.paymentAmount 
          ? row.paymentAmount.toFixed(2) : ''
        
        // 后返
        const rebateAmountStr = row.rebateAmount 
          ? row.rebateAmount.toFixed(2) : ''
        const shopName = ''
      
        
        // 按顺序拼接：日期、多多单号、型号、数量、姓名、地址、售价、成本、利润、京东单号、物流、下单付款、后返
        const text = [
          dateStr,
          duoduoOrderNo,
          shopName,
          modelNumber,
          quantity,
          buyer,
          address,
          sellingPriceStr,
          costStr,
          profitStr,
          orderId,
          logisticsLink,
          paymentAmountStr,
          rebateAmountStr
        ].join('\t')
        
        this.copyToClipboard(text)
        // 记录已复制的订单ID
        if (row.id) {
          this.copiedExcelTextOrderIds.add(row.id)
        }
        this.$message.success('已复制到剪贴板，可以直接粘贴到Excel')
      } catch (e) {
        this.$message.error('复制失败：' + (e.message || '未知错误'))
        console.error('复制单条订单录单格式失败', e)
      }
    },
    
    /** 检查订单是否已复制录单格式 */
    isExcelTextCopied(orderId) {
      return orderId && this.copiedExcelTextOrderIds.has(orderId)
    },

    /** 复制后返录表格式文本到剪贴板 */
    copyRebateRecordText(row) {
      try {
        // 前5列：空（发过运营、需要重发运营、已经重发、需要二次重发运营、二次重发）
        const emptyCols = []
        
        // 单号：orderId
        const orderId = row.orderId || ''
        
        // 型号：modelNumber
        const modelNumber = this.fullModelNumber(row)
        
        // 返现金额（团长）：空
        const leaderRebateAmount = ''
        
        // 晒单金额（主图没标）：空
        const reviewRebateAmount = ''
        
        // 总共返现：rebateAmount（整数格式）
        const totalRebateAmount = row.rebateAmount 
          ? Math.round(row.rebateAmount).toString() : ''
        
        // 确认收货日期：finishTime，格式yyyy/MM/dd
        let finishDateStr = ''
        if (row.finishTime) {
          const finishDate = new Date(row.finishTime)
          const year = finishDate.getFullYear()
          const month = String(finishDate.getMonth() + 1).padStart(2, '0')
          const day = String(finishDate.getDate()).padStart(2, '0')
          finishDateStr = `${year}/${month}/${day}`
        }
        
        // 认领人：buyer
        const buyer = row.buyer || ''
        
        // 下单日期：orderTime，格式yyyyMMdd
        let orderDateStr = ''
        if (row.orderTime) {
          const orderDate = new Date(row.orderTime)
          const year = orderDate.getFullYear()
          const month = String(orderDate.getMonth() + 1).padStart(2, '0')
          const day = String(orderDate.getDate()).padStart(2, '0')
          orderDateStr = `${year}${month}${day}`
        }
        
        // 按顺序拼接：发过运营、需要重发运营、已经重发、需要二次重发运营、二次重发、单号、型号、返现金额（团长）、晒单金额（主图没标）、总共返现、确认收货日期、认领人、下单日期
        const text = [
          ...emptyCols,
          orderId,
          modelNumber,
          leaderRebateAmount,
          reviewRebateAmount,
          totalRebateAmount,
          finishDateStr,
          buyer,
          orderDateStr
        ].join('\t')
        
        this.copyToClipboard(text)
        this.$message.success('已复制后返录表格式到剪贴板，可以直接粘贴到Excel')
      } catch (e) {
        this.$message.error('复制失败：' + (e.message || '未知错误'))
        console.error('复制后返录表格式失败', e)
      }
    },

    /** 复制录单格式文本到剪贴板（批量） */
    async handleCopyExcelText() {
      try {
        this.prepareQueryParams()
        this.copyExcelTextLoading = true
        
        // 调用后端接口生成Excel格式文本
        const res = await generateExcelText(this.queryParams)
        
        if (res.code === 200 && res.data) {
          // 复制到剪贴板
          const text = res.data
          if (text === '暂无订单数据') {
            this.$message.warning('暂无订单数据，请调整查询条件')
            return
          }
          
          this.copyToClipboard(text)
          this.$message.success('已复制到剪贴板，可以直接粘贴到Excel')
        } else {
          this.$message.error(res.msg || '生成失败')
        }
      } catch (e) {
        this.$message.error('复制失败：' + (e.message || '未知错误'))
        console.error('复制录单格式失败', e)
      } finally {
        this.copyExcelTextLoading = false
      }
    },

    /** 反向同步第三方单号 */
    async handleReverseSyncThirdPartyOrderNo() {
      try {
        // 先检查配置是否完整
        const configRes = await getAutoWriteConfig()
        if (configRes.code !== 200 || !configRes.data || !configRes.data.isConfigured) {
          this.$confirm('检测到尚未完成H-TF自动写入配置，是否现在配置？', '提示', {
            type: 'warning'
          }).then(() => {
            this.showAutoWriteConfig = true
          })
          return
        }
        
        const config = configRes.data
        
        // 构建确认消息
        let confirmMsg = '反向同步将从腾讯文档第850行开始读取物流单号列\n'
        confirmMsg += '通过物流链接匹配本地订单，将腾讯文档的单号列值写入到订单的第三方单号字段\n\n'
        confirmMsg += `文档: ${config.fileId}\n`
        confirmMsg += `工作表: ${config.sheetId}\n`
        confirmMsg += `起始行: 850\n`
        confirmMsg += `结束行: 2500\n`
        confirmMsg += `处理行数: 1651行\n`
        confirmMsg += '\n⚠️ 注意：\n'
        confirmMsg += '- 只更新订单的第三方单号字段，不会清除任何数据\n'
        confirmMsg += '- 跳过物流链接为空的行\n'
        confirmMsg += '- 跳过单号为空的行\n'
        confirmMsg += '- 如果订单已有第三方单号且与文档中的不同，将跳过\n'
        confirmMsg += '- 所有操作都会记录到操作日志\n'
        
        // 确认同步
        await this.$confirm(confirmMsg, '反向同步第三方单号确认', {
          type: 'info',
          confirmButtonText: '开始同步',
          cancelButtonText: '取消'
        })
        
        this.reverseSyncLoading = true
        
        // 调用反向同步API
        const res = await reverseSyncThirdPartyOrderNo({
          startRow: 850,
          endRow: 2500  // 从850行到2500行
        })
        
        if (res.code === 200) {
          const data = res.data || {}
          this.$notify({
            title: '反向同步完成',
            message: `✓ 成功: ${data.successCount || 0} 条\n⊙ 跳过: ${data.skippedCount || 0} 条\n✗ 错误: ${data.errorCount || 0} 条\n\n${data.message || ''}`,
            type: 'success',
            duration: 10000,
            dangerouslyUseHTMLString: false
          })
          // 刷新列表
          this.getList()
        } else {
          this.$message.error(res.msg || '同步失败')
        }
      } catch (e) {
        if (e !== 'cancel') {
          this.$message.error('操作失败：' + (e.message || '未知错误'))
          console.error('反向同步失败', e)
        }
      } finally {
        this.reverseSyncLoading = false
      }
    },

    /** 处理表格选择变化 */
    handleSelectionChange(selection) {
      this.selectedRows = selection
    },

    /** 批量复制录单格式 */
    handleBatchCopyExcelText() {
      if (!this.selectedRows || this.selectedRows.length === 0) {
        this.$message.warning('请先选择要复制的订单')
        return
      }

      try {
        const lines = []
        
        // 遍历选中的每一行，生成录单格式文本
        this.selectedRows.forEach(row => {
          // 日期（格式：yyyy/MM/dd）
          let dateStr = ''
          if (row.orderTime) {
            const date = new Date(row.orderTime)
            const year = date.getFullYear()
            const month = String(date.getMonth() + 1).padStart(2, '0')
            const day = String(date.getDate()).padStart(2, '0')
            dateStr = `${year}/${month}/${day}`
          }
          
          // 多多单号（第三方单号，如果没有则使用内部单号）
          const duoduoOrderNo = (row.thirdPartyOrderNo && row.thirdPartyOrderNo.trim()) 
            ? row.thirdPartyOrderNo : (row.remark || '')
          
          // 型号
          const modelNumber = this.fullModelNumber(row)
          
          // 数量（固定为1）
          const quantity = '1'
          
          // 地址
          const address = row.address || ''
          
          // 姓名（从地址中提取，地址格式通常是"姓名 电话 详细地址"）
          let buyer = ''
          if (address) {
            // 提取地址中的第一个词作为姓名
            const addressParts = address.trim().split(/\s+/)
            if (addressParts.length > 0) {
              buyer = addressParts[0]
            }
          }
          
          const sellingPriceStr = row.sellingPrice != null && row.sellingPrice !== '' ? Number(row.sellingPrice).toFixed(2) : '0'
          const costStr = this.formatExcelCost(row)
          const profitStr = row.profit != null && row.profit !== '' ? Number(row.profit).toFixed(2) : ''
          
          // 京东单号
          const orderId = row.orderId || ''
          
          // 物流链接
          const logisticsLink = row.logisticsLink || ''
          
          // 下单付款
          const paymentAmountStr = row.paymentAmount 
            ? row.paymentAmount.toFixed(2) : ''
          
          // 后返
          const rebateAmountStr = row.rebateAmount 
            ? row.rebateAmount.toFixed(2) : ''
          const shopName = ''
        
          // 按顺序拼接：日期、多多单号、型号、数量、姓名、地址、售价、成本、利润、京东单号、物流、下单付款、后返
          const text = [
            dateStr,
            duoduoOrderNo,
            shopName,
            modelNumber,
            quantity,
            buyer,
            address,
            sellingPriceStr,
            costStr,
            profitStr,
            orderId,
            logisticsLink,
            paymentAmountStr,
            rebateAmountStr
          ].join('\t')
          
          lines.push(text)
        })
        
        // 将所有行用换行符连接
        const finalText = lines.join('\n')
        
        this.copyToClipboard(finalText)
        
        // 记录已复制的订单ID
        this.selectedRows.forEach(row => {
          if (row.id) {
            this.copiedExcelTextOrderIds.add(row.id)
          }
        })
        
        this.$message.success(`已复制 ${this.selectedRows.length} 条订单的录单格式到剪贴板，可以直接粘贴到Excel`)
      } catch (e) {
        this.$message.error('批量复制失败：' + (e.message || '未知错误'))
        console.error('批量复制录单格式失败', e)
      }
    },

    /** 批量复制后返录表 */
    handleBatchCopyRebateText() {
      if (!this.selectedRows || this.selectedRows.length === 0) {
        this.$message.warning('请先选择要复制的订单')
        return
      }

      try {
        const lines = []
        
        // 遍历选中的每一行，生成后返录表格式文本
        this.selectedRows.forEach(row => {
          // 前5列：空（发过运营、需要重发运营、已经重发、需要二次重发运营、二次重发）
          const emptyCols = ['']
          
          // 单号：orderId
          const orderId = row.orderId || ''
          
          // 型号：modelNumber
          const modelNumber = this.fullModelNumber(row)
          
          // 返现金额（团长）：空
          const leaderRebateAmount = ''
          
          // 晒单金额（主图没标）：空
          const reviewRebateAmount = ''
          
          // 总共返现：rebateAmount（整数格式）
          const totalRebateAmount = row.rebateAmount 
            ? Math.round(row.rebateAmount).toString() : ''
          
          // 确认收货日期：finishTime，格式yyyy/MM/dd
          let finishDateStr = ''
          if (row.finishTime) {
            const finishDate = new Date(row.finishTime)
            const year = finishDate.getFullYear()
            const month = String(finishDate.getMonth() + 1).padStart(2, '0')
            const day = String(finishDate.getDate()).padStart(2, '0')
            finishDateStr = `${year}/${month}/${day}`
          }
          
          // 认领人：buyer
          const buyer = row.buyer || ''
          
          // 下单日期：orderTime，格式 yyyy/MM/dd（如 2020/03/03）
          let orderDateStr = ''
          if (row.orderTime) {
            const orderDate = new Date(row.orderTime)
            const year = orderDate.getFullYear()
            const month = String(orderDate.getMonth() + 1).padStart(2, '0')
            const day = String(orderDate.getDate()).padStart(2, '0')
            orderDateStr = `${year}/${month}/${day}`
          }
          
          // 按顺序拼接：发过运营、需要重发运营、已经重发、需要二次重发运营、二次重发、单号、型号、返现金额（团长）、晒单金额（主图没标）、总共返现、确认收货日期、认领人、下单日期
          const text = [
            orderId,
            modelNumber,
            leaderRebateAmount,
            reviewRebateAmount,
            totalRebateAmount,
            '',
            finishDateStr,
            buyer,
            orderDateStr
          ].join('\t')
          
          lines.push(text)
        })
        
        // 将所有行用换行符连接
        const finalText = lines.join('\n')
        
        this.copyToClipboard(finalText)
        this.$message.success(`已复制 ${this.selectedRows.length} 条订单的后返录表格式到剪贴板，可以直接粘贴到Excel`)
      } catch (e) {
        this.$message.error('批量复制失败：' + (e.message || '未知错误'))
        console.error('批量复制后返录表格式失败', e)
      }
    },

    /** 批量复制四川商贸录表（格式：日期	型号	数量	地址	价格	备注	是否安排	物流） */
    handleBatchCopySichuanCommerceText() {
      if (!this.selectedRows || this.selectedRows.length === 0) {
        this.$message.warning('请先选择要复制的订单')
        return
      }

      try {
        const header = ['日期', '型号', '数量', '地址', '价格', '备注', '是否安排', '物流'].join('\t')
        const lines = [header]

        this.selectedRows.forEach(row => {
          // 日期（格式：yyyy/MM/dd）
          let dateStr = ''
          if (row.orderTime) {
            const date = new Date(row.orderTime)
            const year = date.getFullYear()
            const month = String(date.getMonth() + 1).padStart(2, '0')
            const day = String(date.getDate()).padStart(2, '0')
            dateStr = `${year}/${month}/${day}`
          }

          const modelNumber = this.fullModelNumber(row)
          const quantity = (row.productCount != null && row.productCount !== '') ? String(row.productCount) : '1'
          const address = row.address || ''
          const priceStr = row.paymentAmount != null ? row.paymentAmount.toFixed(2) : ''
          const remark = row.remark || ''
          const arranged = '' // 是否安排，留空由用户填写
          const logistics = row.logisticsLink || ''

          const text = [dateStr, modelNumber, quantity, address, priceStr, remark, arranged, logistics].join('\t')
          lines.push(text)
        })

        const finalText = lines.join('\n')
        this.copyToClipboard(finalText)
        this.$message.success(`已复制 ${this.selectedRows.length} 条订单的四川商贸录表格式到剪贴板（含表头），可直接粘贴到Excel`)
      } catch (e) {
        this.$message.error('批量复制失败：' + (e.message || '未知错误'))
        console.error('批量复制四川商贸录表失败', e)
      }
    }

  }
}
</script>

<style scoped>

.jd-order-list-root {
  --jd-accent: #2563eb;
  --jd-accent-hover: #1d4ed8;
  --jd-warm-title: #c2410c;
  --jd-border: #e5e7eb;
  --jd-text: #111827;
  --jd-muted: #6b7280;
  --jd-surface: #ffffff;
  --jd-header: #f8fafc;
  --jd-row-hover: #fffbf5;
  --jd-row-stripe: #fafbfc;
  /* 表格「统计」胶囊：高度与边框对齐 plain 小按钮 */
  --jd-fn-chip-h: 32px;
  --jd-fn-chip-radius: 6px;
  --jd-fn-chip-border: var(--jd-border);
  --jd-fn-chip-bg: var(--jd-surface);
  --jd-fn-chip-text: var(--jd-muted);
}

/* 搜索区：略暖、分层底色 */
.jd-order-list-root ::v-deep .search-section {
  background: linear-gradient(165deg, #f4f8ff 0%, #fffaf5 42%, #ffffff 100%);
  border-bottom: 1px solid var(--jd-border);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  padding: 18px 20px 14px;
}
.jd-order-search-panel {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.jd-filter-compact-collapse-row {
  width: 100%;
  margin: 0 0 8px;
  padding: 0 2px;
  box-sizing: border-box;
}
.jd-filter-compact-collapse-row__btn {
  padding: 2px 0;
  color: var(--jd-accent);
  font-size: 13px;
}
.jd-filter-compact-collapse-row__btn i {
  margin-right: 4px;
}
.jd-filter-compact-minimal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin-bottom: 10px;
  padding: 8px 10px;
  box-sizing: border-box;
  border-radius: 8px;
  border: 1px dashed var(--jd-border);
  background: rgba(255, 255, 255, 0.85);
}
.jd-filter-compact-minimal__search {
  flex: 1 1 220px;
  min-width: 160px;
  max-width: 420px;
}
.jd-filter-compact-minimal__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
}
.jd-filter-compact-expand-btn {
  padding: 6px 4px;
  margin-left: 4px;
  color: var(--jd-accent);
  font-size: 13px;
}
.jd-filter-compact-expand-btn i {
  margin-right: 2px;
}
.jd-order-filter-form ::v-deep .el-form-item {
  margin-right: 14px;
  margin-bottom: 12px;
}
.jd-order-filter-form ::v-deep .el-form-item__label {
  color: var(--jd-muted);
  font-weight: 500;
  font-size: 13px;
}
.jd-order-filter-form ::v-deep .el-input__inner,
.jd-order-filter-form ::v-deep .el-range-input {
  border-radius: 6px;
}

/* 筛选分组卡片 */
.jd-filter-group {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--jd-border);
  gap: 4px 0;
}
.jd-filter-group:last-of-type {
  margin-bottom: 2px;
}
.jd-filter-group--basic {
  background: linear-gradient(135deg, #f5f9ff 0%, #ffffff 70%);
  border-color: #bfdbfe;
}
.jd-filter-group--status {
  background: linear-gradient(135deg, #fff8f0 0%, #fff4e6 45%, #ffffff 100%);
  border-color: #fdba74;
}
.jd-filter-group--extra {
  background: linear-gradient(135deg, #fafaf9 0%, #ffffff 90%);
  border-color: #d6d3d1;
}
.jd-filter-group-head {
  flex: 0 0 auto;
  min-width: 4.5em;
  padding-top: 0;
  margin-right: 8px;
  align-self: center;
}
.jd-filter-group-title {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--jd-text);
  line-height: 1.2;
  white-space: nowrap;
}
.jd-filter-group--status .jd-filter-group-title {
  color: var(--jd-warm-title);
}
.jd-filter-group-body {
  flex: 1;
  min-width: 240px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
}
.jd-order-filter-form ::v-deep .jd-filter-status-select {
  width: 118px;
}
.jd-order-filter-form ::v-deep .jd-filter-rebate-select {
  width: 188px;
  max-width: 100%;
}
.jd-order-filter-form ::v-deep .jd-filter-actions {
  margin-bottom: 0;
}
.jd-order-filter-form ::v-deep .jd-filter-actions .el-form-item__content {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  line-height: 1;
}
/* 与顶部工具栏一致的筛选区按钮（plain + 圆角） */
.jd-order-filter-form ::v-deep .jd-filter-act-btn {
  border-radius: 6px;
  font-weight: 500;
  letter-spacing: 0.01em;
}
.jd-order-filter-form ::v-deep .jd-filter-act-btn--primary.el-button--primary.is-plain {
  color: var(--jd-accent);
  border-color: #bfdbfe;
  background: #eff6ff;
}
.jd-order-filter-form ::v-deep .jd-filter-act-btn--primary.el-button--primary.is-plain:hover {
  color: #fff;
  background: var(--jd-accent);
  border-color: var(--jd-accent);
}
.jd-order-filter-form ::v-deep .jd-filter-actions .jd-tb-muted.is-plain {
  color: var(--jd-muted);
  border-color: var(--jd-border);
  background: var(--jd-surface);
}
.jd-order-filter-form ::v-deep .jd-filter-actions .jd-tb-muted.is-plain:hover {
  color: var(--jd-text);
  border-color: #cbd5e1;
  background: var(--jd-row-hover);
}
@media (max-width: 768px) {
  .jd-filter-group-head {
    flex: 1 1 100%;
    padding-top: 0;
    margin-bottom: 4px;
  }
  .jd-filter-group-body {
    min-width: 100%;
  }
}

/* 桌面工具栏：低饱和、统一圆角 */
.jd-order-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 8px 0 4px;
  border-top: 1px solid var(--jd-border);
  margin-top: 6px;
}
.jd-toolbar-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  flex: 1 1 220px;
  min-width: 0;
  align-items: center;
}
.jd-order-toolbar ::v-deep .el-button {
  border-radius: 6px;
  font-weight: 500;
  letter-spacing: 0.01em;
}
.jd-order-toolbar ::v-deep .el-button--primary.is-plain {
  color: var(--jd-accent);
  border-color: #bfdbfe;
  background: #eff6ff;
}
.jd-order-toolbar ::v-deep .el-button--primary.is-plain:hover {
  color: #fff;
  background: var(--jd-accent);
  border-color: var(--jd-accent);
}
.jd-order-toolbar ::v-deep .jd-tb-muted.is-plain {
  color: var(--jd-muted);
  border-color: var(--jd-border);
  background: var(--jd-surface);
}
.jd-order-toolbar ::v-deep .jd-tb-muted.is-plain:hover {
  color: var(--jd-text);
  border-color: #cbd5e1;
  background: var(--jd-row-hover);
}

/* 表格滚动条 */
.order-table ::v-deep .el-table__body-wrapper {
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 #f1f5f9;
}

.order-table ::v-deep .el-table__body-wrapper::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.order-table ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track {
  background: #f1f5f9;
  border-radius: 5px;
}

.order-table ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border-radius: 5px;
  border: 2px solid #f1f5f9;
}

.order-table ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
}

.order-table ::v-deep .el-tag {
  transition: background-color 0.15s, border-color 0.15s, color 0.15s;
  user-select: none;
  border-radius: 4px;
}

.order-table ::v-deep .el-tag:hover {
  filter: brightness(0.97);
}

.order-table ::v-deep .el-table {
  border-radius: 8px;
  /* 勿 overflow:hidden，否则会裁切 fixed-right 操作列 */
  overflow: visible;
  font-size: 13px;
  color: var(--jd-text);
  border: 1px solid var(--jd-border);
}

.order-table ::v-deep .el-table--border::after,
.order-table ::v-deep .el-table--group::after,
.order-table ::v-deep .el-table::before {
  background-color: var(--jd-border);
}

.order-table ::v-deep .el-table__fixed-right-patch {
  background: var(--jd-header);
}

.order-table ::v-deep .el-table__header-wrapper th {
  background: var(--jd-header) !important;
  color: #374151;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: none;
}

.order-table ::v-deep .el-table th.is-leaf {
  border-bottom: 1px solid var(--jd-border);
}

.order-table ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
  background: var(--jd-row-stripe) !important;
}

.order-table ::v-deep .el-table__body tr:hover > td {
  background-color: var(--jd-row-hover) !important;
}

.order-table ::v-deep .el-table__fixed-right {
  box-shadow: -4px 0 16px rgba(15, 23, 42, 0.06);
}

.order-table ::v-deep .el-table td {
  padding: 9px 0;
  border-color: var(--jd-border);
}

.order-table ::v-deep .el-table .address-cell {
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.order-table ::v-deep .el-table th {
  padding: 11px 0;
}

.order-table ::v-deep .el-table__fixed-left {
  box-shadow: 4px 0 16px rgba(15, 23, 42, 0.06);
}

/* 跟进状态：双列标签 + 下方后返表条 */
.refund-status-stack {
  display: flex;
  flex-direction: row;
  gap: 14px;
  align-items: flex-start;
}
.refund-status-col {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 0;
}
.refund-status-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.refund-status-label {
  flex-shrink: 0;
  width: 52px;
  font-size: 11px;
  font-weight: 500;
  color: var(--jd-muted);
  line-height: 1.2;
}
.refund-status-tag {
  cursor: pointer;
  flex: 0 1 auto;
  max-width: 72px;
  min-width: 52px;
  padding: 0 6px !important;
  height: 22px !important;
  line-height: 20px !important;
  font-size: 11px !important;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.order-table ::v-deep .jd-rebate-remark-strip {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 6px 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #f1f5f9;
}
.order-table ::v-deep .jd-rebate-remark-strip-label {
  flex-shrink: 0;
  width: 52px;
  font-size: 11px;
  font-weight: 500;
  color: var(--jd-muted);
  line-height: 22px;
}
.order-table ::v-deep .jd-rebate-remark-strip-body {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: 1;
}
.order-table ::v-deep .jd-rebate-remark-empty {
  color: #c0c4cc;
  font-size: 12px;
  line-height: 22px;
}

/* 操作列 */
.jd-action-cell {
  text-align: left;
  padding: 4px 0;
}
.jd-action-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 4px;
  margin-bottom: 4px;
}
.jd-action-row:last-child {
  margin-bottom: 0;
}
.order-table ::v-deep .jd-act-link {
  margin: 0 !important;
  padding: 2px 6px !important;
  border-radius: 4px;
  color: #64748b !important;
  font-size: 12px;
  font-weight: 500;
}
.order-table ::v-deep .jd-act-link:hover {
  color: var(--jd-text) !important;
  background: #f1f5f9 !important;
}
.order-table ::v-deep .jd-act-link--accent {
  color: var(--jd-accent) !important;
}
.order-table ::v-deep .jd-act-link--accent:hover {
  background: #eff6ff !important;
}
.order-table ::v-deep .jd-act-done {
  color: #059669 !important;
}
.order-table ::v-deep .jd-act-link--success {
  color: #059669 !important;
}
.order-table ::v-deep .jd-act-link--danger {
  color: #dc2626 !important;
}
.order-table ::v-deep .jd-act-link--danger:hover {
  background: #fef2f2 !important;
}
/* 操作列「统计」：与链接按钮同高的胶囊条 */
.order-table ::v-deep .jd-action-row--meta {
  align-items: center;
}
.order-table ::v-deep .jd-count-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  box-sizing: border-box;
  min-height: var(--jd-fn-chip-h);
  padding: 0 10px 0 12px;
  border-radius: var(--jd-fn-chip-radius);
  background: var(--jd-fn-chip-bg);
  border: 1px solid var(--jd-fn-chip-border);
  margin-right: 6px;
  flex-shrink: 0;
}
.order-table ::v-deep .jd-count-pill-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--jd-fn-chip-text);
  line-height: 1;
  user-select: none;
}
.order-table ::v-deep .jd-count-el-switch.el-switch {
  margin: 0;
  height: 22px;
}
.order-table ::v-deep .jd-count-el-switch.el-switch.is-checked .el-switch__core {
  border-color: var(--jd-accent);
  background-color: var(--jd-accent);
}

/* 表格内售价渠道 / 售价 / 利润：撑满单元格 */
.order-table ::v-deep .jd-cell-stretch {
  width: 100%;
  box-sizing: border-box;
  padding: 0 6px;
}
.order-table ::v-deep .jd-cell-stretch--num {
  display: block;
}
.order-table ::v-deep .jd-cell-stretch .jd-cell-select-full {
  width: 100% !important;
  max-width: 100%;
}
.order-table ::v-deep .jd-cell-stretch .jd-order-input-money,
.order-table ::v-deep .jd-cell-stretch .jd-order-input-money.el-input-number {
  width: 100% !important;
  max-width: 100%;
}
/* 型号：单行、撑满单元格，过长时仅在输入框内滚动 */
.order-table ::v-deep .jd-cell-stretch--model .jd-order-input-model {
  width: 100% !important;
  max-width: 100%;
}
.order-table ::v-deep .jd-cell-stretch--model .jd-order-input-model .el-input__inner {
  overflow-x: auto;
  text-overflow: clip;
  white-space: nowrap;
}
.order-table ::v-deep .jd-model-edit-row {
  display: flex;
  gap: 4px;
  align-items: center;
  width: 100%;
}
.order-table ::v-deep .jd-model-edit-row .jd-order-input-model {
  flex: 1;
  min-width: 0;
}
.order-table ::v-deep .jd-model-edit-row .jd-order-model-shop {
  width: 108px;
  flex-shrink: 0;
}
.jd-mobile-model-edit {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.jd-mobile-model-edit .jd-mobile-model-input {
  flex: 1;
  min-width: 120px;
}
.jd-mobile-model-edit .jd-mobile-model-shop {
  width: 100%;
}
.order-table ::v-deep td.jd-col-model .cell {
  padding-left: 4px;
  padding-right: 4px;
}
.order-table ::v-deep .jd-cell-stretch--num .jd-order-input-money .el-input__inner {
  text-align: right;
  padding-left: 8px;
  padding-right: 36px;
}
.order-table ::v-deep .jd-col-channel .cell,
.order-table ::v-deep .jd-col-money .cell {
  padding-left: 4px;
  padding-right: 4px;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}
/* 售价列略宽（约四位数价位）、利润列略窄（三位数+两位小数）已在列 min-width 区分 */
.order-table ::v-deep .jd-col-money .jd-cell-stretch--num .jd-order-input-money--selling .el-input__inner,
.order-table ::v-deep .jd-col-money .jd-cell-stretch--num .jd-order-input-money--profit .el-input__inner,
.order-table ::v-deep .jd-col-money .jd-cell-stretch--num .jd-order-input-money--payment .el-input__inner,
.order-table ::v-deep .jd-col-money .jd-cell-stretch--num .jd-order-input-money--rebate .el-input__inner {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* 桌面端：占满 ListLayout 表格区，内部表格滚动，表头固定 */
.jd-order-table-page {
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.jd-order-table-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}
.jd-order-el-table {
  flex: 1;
  min-height: 0;
}
.jd-order-table-wrap .profit-summary-bar {
  flex-shrink: 0;
}

/* 移动端：表格区占满中间高度，列表在内部滚动，避免只能看到极少卡片 */
.jd-order-table-page--mobile {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.jd-order-table-page--mobile .mobile-order-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* 移动端卡片列表样式 */
.mobile-order-list {
  padding: 12px;
  background: #f5f5f5;
  min-height: 300px;
  -webkit-overflow-scrolling: touch;
}

.mobile-order-card {
  background: #fff;
  border-radius: 12px;
  margin-bottom: 12px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.mobile-order-card:active {
  transform: scale(0.98);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}

.mobile-order-card:last-child {
  margin-bottom: 0;
}

.mobile-order-card .card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0;
  padding-bottom: 10px;
  border-bottom: 1px solid #f0f0f0;
}

.mobile-order-card .header-left.header-left--tappable {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

.mobile-order-card .header-title-block {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.mobile-order-card .mobile-card-chevron {
  flex-shrink: 0;
  font-size: 15px;
  color: #909399;
  transition: transform 0.2s ease;
}

.mobile-order-card .mobile-card-chevron.is-open {
  transform: rotate(90deg);
}

.mobile-order-card .order-id {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.mobile-order-card .header-right {
  flex-shrink: 0;
  margin-left: 12px;
}

.mobile-order-card .card-summary-compact {
  padding: 10px 0 2px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

.mobile-order-card .card-summary-line {
  display: block;
  font-size: 12px;
  color: #64748b;
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mobile-order-card .card-distribution-mark-highlight {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  display: inline-block;
  padding: 2px 6px;
  border-radius: 4px;
}

.mobile-order-card .jd-dist-mark-summary-pill {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.mobile-order-card .card-summary-sep {
  color: #94a3b8;
  font-weight: 400;
}

.mobile-order-card .card-content {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.mobile-order-card.is-expanded .card-content {
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid #f0f0f0;
}

.mobile-order-card .field-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  min-height: 24px;
}

.mobile-order-card .field-label {
  font-size: 13px;
  color: #909399;
  min-width: 80px;
  flex-shrink: 0;
  margin-right: 12px;
}

.mobile-order-card .field-value {
  flex: 1;
  font-size: 14px;
  color: #303133;
  text-align: right;
  word-break: break-all;
}

.mobile-order-card .field-value.address-text {
  font-weight: 500;
}

.mobile-order-card .field-value.amount {
  font-weight: 600;
  color: #e6a23c;
}

/* 移动端卡片：售价渠道 / 售价 / 利润 纵向全宽，便于点选 */
.mobile-order-card .field-row--pricing {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-height: 0;
  padding: 4px 0 12px;
}

/* 型号：与售价区一致纵向全宽，避免窄屏右列挤压到无法聚焦 */
.mobile-order-card .field-row--model {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-height: 0;
}
.mobile-order-card .field-row--model .field-label {
  margin-right: 0;
  min-width: 0;
  text-align: left;
  font-weight: 500;
  color: #606266;
}
.mobile-order-card .field-row--model .field-value {
  flex: none;
  width: 100%;
  min-width: 0;
  text-align: left;
}
.mobile-order-card .field-row--model ::v-deep .jd-mobile-model-input .el-input__inner {
  font-size: 16px;
  line-height: 1.4;
}

.mobile-order-card .field-row--pricing .field-label {
  margin-right: 0;
  min-width: 0;
  text-align: left;
  font-weight: 500;
  color: #606266;
}

.mobile-order-card .field-row--pricing .field-value--pricing-control {
  text-align: left;
  flex: none;
  width: 100%;
}

.mobile-order-card .mobile-pricing-select {
  width: 100%;
}

.mobile-order-card .mobile-pricing-select ::v-deep .el-input__inner {
  height: 38px;
  line-height: 38px;
  font-size: 15px;
}

.mobile-order-card .mobile-pricing-num-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.mobile-order-card .mobile-pricing-num-wrap ::v-deep .mobile-pricing-input.el-input-number {
  flex: 1;
  min-width: 0;
  width: auto !important;
}

.mobile-order-card .mobile-pricing-num-wrap ::v-deep .mobile-pricing-input .el-input__inner {
  height: 38px;
  line-height: 38px;
  font-size: 15px;
}

.mobile-order-card .mobile-pricing-tag {
  flex-shrink: 0;
}

.mobile-order-card .refund-status .field-value {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
  align-items: center;
}

.mobile-order-card .status-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}

.mobile-order-card .mobile-rebate-remark-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px dashed #e5e7eb;
  justify-content: flex-end;
}
.mobile-order-card .mobile-rebate-remark-hint {
  font-size: 11px;
  font-weight: 500;
  color: #909399;
  margin-right: auto;
}

.rebate-remark-popover .rebate-remark-item {
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
  font-size: 13px;
  line-height: 1.5;
}
.rebate-remark-popover .rebate-remark-item:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}
.rebate-remark-popover .rebate-remark-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.rebate-remark-popover .rebate-remark-time {
  color: #909399;
  font-size: 12px;
  font-weight: normal;
  flex-shrink: 0;
}

/* 移动端操作按钮样式 - 只在移动端生效 */
@media (max-width: 768px) {
  .mobile-action-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .mobile-action-btn {
    width: 36px;
    height: 36px;
    padding: 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  }

  /* 移动端下拉菜单样式 */
  ::v-deep .mobile-action-dropdown {
    min-width: 180px;
    max-width: 240px;
  }
  
  ::v-deep .mobile-action-dropdown .el-dropdown-menu__item {
    padding: 12px 20px;
    font-size: 14px;
    line-height: 1.5;
  }

  ::v-deep .mobile-action-dropdown .el-dropdown-menu__item.is-copied {
    color: #67C23A;
  }

  ::v-deep .mobile-action-dropdown .el-dropdown-menu__item--divided {
    border-top: 1px solid #e4e7ed;
    margin-top: 4px;
    padding-top: 8px;
  }

  /* 移动端隐藏操作列标题 */
  .order-table ::v-deep .action-column .el-table__column-filter-trigger,
  .order-table ::v-deep .action-column .cell {
    padding: 8px 4px;
  }
  
  .order-table ::v-deep .el-table__fixed-right {
    width: 60px !important;
  }

  /* 隐藏桌面端表格 */
  .order-table {
    display: none;
  }
}

/* 桌面端操作列：新布局为 jd-action-cell 多行，勿用单行强约束 */
.desktop-action-buttons-wrapper:not(.jd-action-cell) {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  padding: 0;
  box-sizing: border-box;
  flex-wrap: wrap;
  gap: 2px;
}

.desktop-action-buttons-wrapper:not(.jd-action-cell) .action-row-all {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
  line-height: 1.2;
}

.desktop-action-buttons-wrapper:not(.jd-action-cell) .el-button {
  padding: 3px 6px !important;
  font-size: 12px !important;
  white-space: nowrap !important;
  margin: 0 !important;
  height: 24px !important;
  line-height: 1.2 !important;
  min-height: 24px !important;
  border: none !important;
  flex-shrink: 0;
  display: inline-flex !important;
  align-items: center !important;
}

.desktop-action-buttons-wrapper:not(.jd-action-cell) .el-switch {
  margin-left: 4px !important;
  flex-shrink: 0;
}

.desktop-action-buttons-wrapper.jd-action-cell {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  flex-wrap: nowrap;
}

/* 桌面端下拉菜单样式 */
::v-deep .desktop-action-dropdown {
  min-width: 160px;
}

::v-deep .desktop-action-dropdown .el-dropdown-menu__item {
  padding: 10px 20px;
  font-size: 13px;
}

::v-deep .desktop-action-dropdown .el-dropdown-menu__item.is-copied {
  color: #67C23A;
}

/* 桌面端确保操作列正常显示（宽度与 el-table-column :width 一致；勿改 fixed-right-patch，否则会出现整块无意义空白列） */
@media (min-width: 769px) {
  .order-table ::v-deep .action-column {
    width: 300px !important;
    min-width: 300px !important;
  }

  .order-table ::v-deep .el-table__fixed-right {
    width: 300px !important;
    right: 0 !important;
    z-index: 4;
  }

  .order-table ::v-deep .el-table__fixed-right-patch {
    width: 300px !important;
  }

  /* 隐藏移动端按钮 */
  .mobile-action-wrapper {
    display: none !important;
  }
  
  /* 优化表格单元格高度和布局 */
  .order-table ::v-deep .action-column .cell {
    padding: 6px 4px !important;
    line-height: 1.3 !important;
    overflow: visible !important;
  }
  
  /* 确保操作按钮容器正确显示 */
  .order-table ::v-deep .action-column .desktop-action-buttons-wrapper {
    width: 100%;
    box-sizing: border-box;
  }
}

/* 操作按钮区域 */
.action-buttons-section {
  margin-top: 12px;
  margin-bottom: 12px;
}

/* 移动端和桌面端按钮组显示控制 */
@media (max-width: 768px) {
  .desktop-only {
    display: none !important;
  }
  
  .action-buttons-section.mobile-only {
    display: block;
  }
}

@media (min-width: 769px) {
  .mobile-only {
    display: none !important;
  }
  
  .desktop-action-buttons.desktop-only {
    display: block;
  }
}

.desktop-action-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

/* 移动端优化 */
@media (max-width: 768px) {
  .action-buttons-section.mobile-only {
    margin-top: 8px;
    margin-bottom: 8px;
    display: block;
  }
  
  .desktop-action-buttons.desktop-only {
    display: none !important;
  }
  
  /* 移动端隐藏分页或简化显示 */
  .list-pagination {
    display: none; /* 移动端隐藏分页，因为很少用 */
  }
}

/* 桌面端显示桌面按钮，隐藏移动端按钮 */
@media (min-width: 769px) {
  .action-buttons-section.mobile-only {
    display: none !important;
  }
  
  .desktop-action-buttons.desktop-only {
    display: flex !important;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 12px;
  }
}

.profit-summary-bar {
  margin: 0 0 12px 0;
  padding: 12px 16px;
  background: var(--jd-header, #f8fafc);
  border: 1px solid var(--jd-border, #e5e7eb);
  border-radius: 8px;
  font-size: 13px;
  color: var(--jd-muted, #6b7280);
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
}
.profit-summary-bar__left {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 0;
  min-width: 0;
  flex: 1;
}
.profit-summary-bar__main {
  min-width: 0;
  flex: 1;
}
.profit-summary-bar__status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 14px;
  flex-shrink: 0;
  margin-left: auto;
}
.order-status-stat {
  font-size: 13px;
  color: var(--jd-muted, #6b7280);
  white-space: nowrap;
}
.order-status-stat b {
  color: var(--jd-text, #111827);
  font-weight: 600;
  margin-left: 2px;
}
.order-status-stat--refund b {
  color: #e6a23c;
}
.order-status-stat--shipped b {
  color: #67c23a;
}
.order-status-stat--pending b {
  color: #909399;
}
.mobile-profit-summary.profit-summary-bar {
  flex-direction: column;
  align-items: stretch;
}
.mobile-profit-summary .profit-summary-bar__status {
  justify-content: flex-start;
  margin-left: 0;
  padding-top: 8px;
  border-top: 1px dashed var(--jd-border, #e5e7eb);
}
.profit-summary-bar b {
  color: var(--jd-text, #111827);
  font-weight: 600;
}
.sticky-summary {
  position: sticky;
  top: 0;
  z-index: 20;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06);
}
.profit-summary-item {
  margin-right: 20px;
}
.profit-summary-hint {
  margin-left: 4px;
  font-size: 12px;
  font-weight: 400;
  color: var(--jd-muted, #6b7280);
}
.mobile-profit-summary {
  font-size: 12px;
  line-height: 1.5;
}
.mobile-profit-summary div + div {
  margin-top: 4px;
}

.mobile-order-list-cap-hint {
  margin: 12px 4px 4px;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  color: #92400e;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 8px;
}

/* 本页：避免外层 .table-section 与表格内部双纵向滚动，横向滚动仍由表体承担 */
.jd-order-list-root ::v-deep .table-section {
  overflow-x: auto;
  overflow-y: hidden;
}

/* 第三方单号为空：表格内粘贴补录 */
.jd-third-party-empty {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
}
.jd-third-party-empty ::v-deep .el-input {
  flex: 1;
  min-width: 0;
}

/* 分销标识：单元格底色（本页同标识同色）；点击弹窗编辑 */
.jd-dist-mark-cell {
  padding: 3px 6px;
  border-radius: 4px;
  box-sizing: border-box;
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.jd-dist-mark-cell.jd-dist-tone-empty {
  background: #f4f4f5;
}
.jd-dist-mark-cell--tap {
  cursor: pointer;
  user-select: none;
}
.jd-dist-mark-text {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.4;
  text-align: center;
  word-break: break-all;
}

.jd-order-el-table ::v-deep td.jd-col-distribution-mark {
  vertical-align: middle;
}

.mobile-order-card .jd-dist-mark-mobile-tap {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mobile-order-card .jd-dist-mark-mobile-pill {
  font-size: 14px;
  font-weight: 400;
  padding: 2px 8px;
  border-radius: 4px;
  max-width: 100%;
  word-break: break-all;
}
.mobile-order-card .jd-dist-mark-edit-ico {
  flex-shrink: 0;
  color: #909399;
  font-size: 14px;
}

/* 移动端卡片：第三方单号 / 分销标识等可编辑字段 */
.field-value--third-party-edit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
}
.field-value--third-party-edit ::v-deep .el-button {
  align-self: flex-start;
}
.field-value--third-party-edit ::v-deep .jd-mobile-model-input {
  width: 100%;
}
.field-value--third-party-edit ::v-deep .jd-mobile-model-input .el-input__inner {
  overflow-x: auto;
  text-overflow: clip;
  white-space: nowrap;
}
</style>


