Files
shop-toy/settlement-redesign-plan.md

8.9 KiB
Raw Permalink Blame History

应结账款页面重构方案

需求概述

  1. 将商户卡片中的"批量消账"按钮改为"消账"
  2. 移除每个订单的"申请消账"按钮
  3. 点击"消账"按钮后,进入选择模式,可以选择该商户下的多个订单
  4. 选择订单后,按钮文本变为"进行消账(X)"X为选择的订单数量
  5. 添加全选/取消全选功能
  6. 显示已选订单的汇总金额
  7. 限制只能选择未结和逾期状态的订单
  8. 点击"进行消账"后,执行批量消账逻辑

数据结构设计

新增状态变量

// 选择模式状态
const selectionMode = ref<Record<string, boolean>>({}) // 记录每个商户是否处于选择模式
const selectedOrders = ref<Record<string, string[]>>({}) // 记录每个商户选中的订单ID列表

计算属性

// 计算每个商户选中的订单数量
const selectedCount = computed(() => {
  return (merchantId: string) => selectedOrders.value[merchantId]?.length || 0
})

// 计算每个商户选中的订单总金额
const selectedAmount = computed(() => {
  return (merchantId: string) => {
    const group = groupedByMerchant.value.find(g => g.merchantId === merchantId)
    if (!group) return 0
    
    const selectedIds = selectedOrders.value[merchantId] || []
    return group.settlements
      .filter(item => selectedIds.includes(item.id))
      .reduce((sum, item) => sum + item.amount, 0)
  }
})

// 计算每个商户是否全选
const isAllSelected = computed(() => {
  return (merchantId: string) => {
    const group = groupedByMerchant.value.find(g => g.merchantId === merchantId)
    if (!group) return false
    
    const selectableOrders = group.settlements.filter(
      item => item.status === SettlementStatus.UNSETTLED || item.status === SettlementStatus.OVERDUE
    )
    const selectedIds = selectedOrders.value[merchantId] || []
    
    return selectableOrders.length > 0 && selectableOrders.every(item => selectedIds.includes(item.id))
  }
})

UI 设计

1. 商户头部修改

<!-- 商户头部 -->
<view class="merchant-header">
  <!-- 原有商户信息保持不变 -->
  
  <!-- 头部操作区域 -->
  <view v-if="currentTab === 0" class="header-action">
    <!-- 非选择模式 -->
    <view v-if="!selectionMode[group.merchantId]" class="batch-btn-small" @click.stop="enterSelectionMode(group.merchantId)">
      <text class="i-carbon-checkmark-outline" />
      <text>消账</text>
    </view>
    
    <!-- 选择模式 -->
    <template v-else>
      <view class="selection-controls">
        <view class="select-all-btn" @click.stop="toggleSelectAll(group.merchantId)">
          <text class="i-carbon-checkmark-filled" v-if="isAllSelected(group.merchantId)" />
          <text class="i-carbon-checkmark-outline" v-else />
          <text>全选</text>
        </view>
        <view class="selected-info">
          <text>已选 {{ selectedCount(group.merchantId) }} </text>
          <text class="amount">¥{{ selectedAmount(group.merchantId).toFixed(2) }}</text>
        </view>
        <view 
          v-if="selectedCount(group.merchantId) > 0" 
          class="batch-btn-small active" 
          @click.stop="handleBatchWriteOff(group.merchantId)"
        >
          <text class="i-carbon-checkmark-outline" />
          <text>进行消账({{ selectedCount(group.merchantId) }})</text>
        </view>
        <view v-else class="cancel-btn" @click.stop="exitSelectionMode(group.merchantId)">
          <text>取消</text>
        </view>
      </view>
    </template>
  </view>
</view>

2. 订单列表修改

<!-- 订单列表 -->
<view class="order-list">
  <view 
    v-for="item in group.settlements" 
    :key="item.id" 
    class="order-item"
    :class="{ 
      'selection-mode': selectionMode[group.merchantId],
      'selected': selectedOrders[group.merchantId]?.includes(item.id),
      'disabled': item.status !== SettlementStatus.UNSETTLED && item.status !== SettlementStatus.OVERDUE
    }"
    @click="handleOrderClick(group.merchantId, item.id, item.status)"
  >
    <!-- 选择框 -->
    <view v-if="selectionMode[group.merchantId]" class="checkbox">
      <text class="i-carbon-checkmark-filled" v-if="selectedOrders[group.merchantId]?.includes(item.id)" />
      <text class="i-carbon-checkmark-outline" v-else />
    </view>
    
    <!-- 订单内容 -->
    <view class="order-content">
      <!-- 原有订单头部和内容保持不变 -->
      <!-- 移除订单操作区域 -->
    </view>
  </view>
</view>

功能实现

1. 进入选择模式

function enterSelectionMode(merchantId: string) {
  selectionMode.value[merchantId] = true
  selectedOrders.value[merchantId] = []
}

2. 退出选择模式

function exitSelectionMode(merchantId: string) {
  selectionMode.value[merchantId] = false
  selectedOrders.value[merchantId] = []
}

3. 处理订单点击

function handleOrderClick(merchantId: string, orderId: string, status: SettlementStatus) {
  // 只有在选择模式下且订单状态为未结或逾期时才能选择
  if (!selectionMode.value[merchantId]) return
  if (status !== SettlementStatus.UNSETTLED && status !== SettlementStatus.OVERDUE) return
  
  const selected = selectedOrders.value[merchantId] || []
  const index = selected.indexOf(orderId)
  
  if (index > -1) {
    // 取消选择
    selected.splice(index, 1)
  } else {
    // 添加选择
    selected.push(orderId)
  }
  
  selectedOrders.value[merchantId] = selected
}

4. 全选/取消全选

function toggleSelectAll(merchantId: string) {
  const group = groupedByMerchant.value.find(g => g.merchantId === merchantId)
  if (!group) return
  
  const selectableOrders = group.settlements.filter(
    item => item.status === SettlementStatus.UNSETTLED || item.status === SettlementStatus.OVERDUE
  )
  
  if (isAllSelected.value(merchantId)) {
    // 取消全选
    selectedOrders.value[merchantId] = []
  } else {
    // 全选
    selectedOrders.value[merchantId] = selectableOrders.map(item => item.id)
  }
}

5. 批量消账

function handleBatchWriteOff(merchantId: string) {
  const selectedIds = selectedOrders.value[merchantId] || []
  if (selectedIds.length === 0) return
  
  const group = groupedByMerchant.value.find(g => g.merchantId === merchantId)
  if (!group) return
  
  // 获取选中的订单
  const selectedSettlements = group.settlements.filter(item => selectedIds.includes(item.id))
  
  currentSettlement.value = null
  currentMerchantSettlements.value = selectedSettlements
  isBatchMode.value = true
  writeOffVisible.value = true
  
  // 退出选择模式
  exitSelectionMode(merchantId)
}

样式设计

1. 选择模式样式

.order-item {
  &.selection-mode {
    display: flex;
    align-items: flex-start;
    gap: 20rpx;
    padding: 24rpx;
    
    .checkbox {
      width: 40rpx;
      height: 40rpx;
      border-radius: 50%;
      border: 2rpx solid #ddd;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-top: 10rpx;
      flex-shrink: 0;
      
      .i-carbon-checkmark-outline {
        font-size: 24rpx;
        color: #999;
      }
      
      .i-carbon-checkmark-filled {
        font-size: 24rpx;
        color: $primary;
      }
    }
    
    &.selected .checkbox {
      background: rgba($primary, 0.1);
      border-color: $primary;
    }
    
    &.disabled {
      opacity: 0.5;
      pointer-events: none;
    }
    
    .order-content {
      flex: 1;
    }
  }
}

2. 选择控制区域样式

.selection-controls {
  display: flex;
  flex-direction: column;
  gap: 12rpx;
  align-items: flex-end;
  
  .select-all-btn {
    display: flex;
    align-items: center;
    gap: 6rpx;
    padding: 8rpx 16rpx;
    background: rgba($primary, 0.05);
    border-radius: 20rpx;
    color: $primary;
    font-size: 22rpx;
    
    .i-carbon-checkmark-outline,
    .i-carbon-checkmark-filled {
      font-size: 24rpx;
    }
  }
  
  .selected-info {
    text-align: right;
    font-size: 22rpx;
    
    .amount {
      display: block;
      font-size: 26rpx;
      font-weight: 600;
      color: $danger;
    }
  }
  
  .cancel-btn {
    padding: 8rpx 20rpx;
    background: rgba($text-2, 0.1);
    border-radius: 20rpx;
    color: $text-2;
    font-size: 24rpx;
  }
  
  .batch-btn-small.active {
    background: $primary;
    color: white;
  }
}

交互流程

  1. 用户点击商户头部的"消账"按钮
  2. 进入选择模式,显示选择框和全选按钮
  3. 用户可以选择/取消选择符合条件的订单
  4. 选择订单后,显示已选数量和汇总金额
  5. 点击"进行消账"按钮,打开消账弹窗
  6. 消账完成后退出选择模式,刷新列表

注意事项

  1. 只有未结和逾期状态的订单才能被选择
  2. 选择模式下,其他商户的卡片保持正常状态
  3. 消账弹窗需要支持批量处理多个订单
  4. 需要处理选择状态的响应式更新