Browse Source

完善客户/商家结算与订单列表的检索与列表交互样式。

- 统一检索区 label 字号
- 待结算列表工具条增加“已选 N 项”提示
- 客户结算待结算列表调整列展示与顺序,并对齐二级展开图标样式

Made-with: Cursor
zlwu 6 months ago
parent
commit
4526d6b308

+ 522 - 274
web-admin/src/views/system/client-settlement/index.vue

@@ -1,16 +1,15 @@
 <template>
   <div class="page-container">
     <div class="page-head">
-      <div>
-        <h2>客户结算</h2>
-        <p>按区域管理待结算订单与结算单记录</p>
-      </div>
+      <h1>客户结算管理</h1>
+      <p class="page-desc">按区域管理待结算订单与结算单记录,支持结算、查看和编辑结算单。</p>
     </div>
-    <div class="region-tabs">
-      <div class="tab-button-group">
+    <div class="region-tabs region-tab-strip">
+      <div class="tab-button-group region-tab-group">
         <el-button
           v-for="r in regionList"
           :key="r.id"
+          class="region-tab-btn"
           :type="activeRegionId === r.id ? 'primary' : 'default'"
           @click="selectRegion(r.id)"
         >
@@ -19,72 +18,77 @@
       </div>
     </div>
 
-    <el-tabs v-model="activeTab" @tab-change="onTabChange">
+    <el-tabs v-model="activeTab" class="settlement-page-tabs" @tab-change="onTabChange">
       <el-tab-pane label="待结算订单" name="pending">
-        <el-card shadow="never" class="search-card">
-          <el-form :inline="true" :model="searchForm">
-            <el-form-item label="客户">
-              <el-select
-                v-model="searchForm.clientId"
-                filterable
-                clearable
-                placeholder="请选择客户"
-                style="width: 220px"
-              >
-                <el-option
-                  v-for="u in clientOptions"
-                  :key="u.id"
-                  :label="u.realName || u.username"
-                  :value="u.id"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="订单号">
-              <el-input
-                v-model="searchForm.keyword"
-                clearable
-                placeholder="请输入订单号"
-                style="width: 220px"
-              />
-            </el-form-item>
-            <el-form-item label="日期区间">
-              <el-date-picker
-                v-model="dateRange"
-                type="daterange"
-                value-format="YYYY-MM-DDTHH:mm:ss"
-                range-separator="至"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-              />
-            </el-form-item>
-            <el-form-item>
-              <el-button class="btn-main" @click="handleSearch">搜索</el-button>
-              <el-button class="btn-ghost" @click="handleReset">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
+        <section class="panel">
+          <div class="panel-top">
+            <h2>
+              <el-icon class="title-ic"><Setting /></el-icon>
+              <span>待结算订单</span>
+            </h2>
+          </div>
 
-        <div class="stats-row">
-          <el-card shadow="never"
-            ><div class="stat-title">可结算金额(元)(已完结·按售价)</div>
-            <div class="stat-value">¥{{ formatAmount(summary.pendingAmount) }}</div></el-card
-          >
-          <el-card shadow="never"
-            ><div class="stat-title">当前页·可结算售价(元)</div>
-            <div class="stat-value">¥{{ formatAmount(summary.currentPageAmount) }}</div></el-card
-          >
-          <el-card shadow="never"
-            ><div class="stat-title">已选订单数</div>
-            <div class="stat-value">{{ selectedCount }}</div></el-card
-          >
-          <el-card shadow="never"
-            ><div class="stat-title">已选结算金额(元)</div>
-            <div class="stat-value amount">¥{{ formatAmount(selectedAmount) }}</div></el-card
-          >
-        </div>
+          <div class="stats-row stats-row--compact">
+            <el-card shadow="never" class="stat-card"
+              ><div class="stat-title">可结算金额(元)(已完结·按售价)</div>
+              <div class="stat-value">¥{{ formatAmount(summary.pendingAmount) }}</div></el-card
+            >
+            <el-card shadow="never" class="stat-card"
+              ><div class="stat-title">当前页·可结算售价(元)</div>
+              <div class="stat-value">¥{{ formatAmount(summary.currentPageAmount) }}</div></el-card
+            >
+            <el-card shadow="never" class="stat-card"
+              ><div class="stat-title">已选订单数</div>
+              <div class="stat-value">{{ selectedCount }}</div></el-card
+            >
+            <el-card shadow="never" class="stat-card"
+              ><div class="stat-title">已选结算金额(元)</div>
+              <div class="stat-value amount">¥{{ formatAmount(selectedAmount) }}</div></el-card
+            >
+          </div>
+
+          <el-card shadow="never" class="pending-main-card">
+            <div class="filter-block">
+              <el-form :model="searchForm" class="filter-form" label-position="top">
+                <div class="filter-grid">
+                  <el-form-item label="客户">
+                    <el-select v-model="searchForm.clientId" filterable clearable placeholder="请选择客户">
+                      <el-option
+                        v-for="u in clientOptions"
+                        :key="u.id"
+                        :label="u.realName || u.username"
+                        :value="u.id"
+                      />
+                    </el-select>
+                  </el-form-item>
+                  <el-form-item label="订单号">
+                    <el-input v-model="searchForm.keyword" clearable placeholder="请输入订单号" />
+                  </el-form-item>
+                  <el-form-item label="日期区间">
+                    <el-date-picker
+                      v-model="dateRange"
+                      type="daterange"
+                      value-format="YYYY-MM-DDTHH:mm:ss"
+                      range-separator="至"
+                      start-placeholder="开始日期"
+                      end-placeholder="结束日期"
+                    />
+                  </el-form-item>
+                </div>
+                <div class="filter-actions-row">
+                  <div class="filter-actions-end">
+                    <el-button class="btn-ghost" @click="handleReset">重置</el-button>
+                    <el-button class="btn-main" type="primary" @click="handleSearch">搜索</el-button>
+                  </div>
+                </div>
+              </el-form>
+            </div>
 
-        <el-card shadow="never" class="list-table-card">
           <div class="toolbar">
+            <span class="list-toolbar-selected" aria-live="polite"
+              >已选<span class="sel-num">{{ selectedCount }}</span
+              >项</span
+            >
             <el-button class="btn-ghost" @click="handleSelectAllFiltered">全选可结算订单(已完结·跨分页)</el-button>
             <el-button class="btn-main" :disabled="!selectedCount" @click="openSettlementDialog"
               >结算</el-button
@@ -95,11 +99,12 @@
           </div>
           <el-table
             ref="tableRef"
+            class="client-settlement-table"
             :data="tableData"
             row-key="id"
             stripe
             v-loading="loading"
-            max-height="calc(100vh - 420px)"
+            max-height="calc(100vh - 440px)"
             @selection-change="handleSelectionChange"
             @expand-change="handleRowExpand"
           >
@@ -176,24 +181,14 @@
             </el-table-column>
             <el-table-column prop="clientName" label="客户名称" min-width="150" show-overflow-tooltip />
             <el-table-column prop="regionName" label="区域" min-width="120" show-overflow-tooltip />
-            <el-table-column prop="totalAmount" label="订单金额(元)" min-width="130" align="right">
-              <template #default="{ row }">
-                <span class="amount-text">¥{{ formatAmount(orderTotalAmount(row)) }}</span>
-              </template>
-            </el-table-column>
             <el-table-column prop="supplierReferenceTotal" label="供货总金额(元)" min-width="140" align="right">
               <template #default="{ row }">
                 <span class="amount-text">¥{{ formatAmount(row.supplierReferenceTotal) }}</span>
               </template>
             </el-table-column>
-            <el-table-column prop="settlementAmount" label="售出总金额(元)" min-width="140" align="right">
-              <template #default="{ row }">
-                <span class="amount-text">¥{{ formatAmount(row.settlementAmount) }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="应收金额(元)" min-width="130" align="right">
+            <el-table-column prop="totalAmount" label="订单金额(元)" min-width="130" align="right">
               <template #default="{ row }">
-                <span class="amount-text">¥{{ formatAmount(orderReceivableAmount(row)) }}</span>
+                <span class="amount-text">¥{{ formatAmount(orderTotalAmount(row)) }}</span>
               </template>
             </el-table-column>
             <el-table-column label="订单状态" min-width="120">
@@ -254,55 +249,62 @@
               "
             />
           </div>
-        </el-card>
+          </el-card>
+        </section>
       </el-tab-pane>
 
       <el-tab-pane label="结算单记录" name="sheets">
-        <el-card shadow="never" class="search-card">
-          <el-form :inline="true" :model="sheetSearchForm">
-            <el-form-item label="客户">
-              <el-select
-                v-model="sheetSearchForm.clientId"
-                filterable
-                clearable
-                placeholder="全部"
-                style="width: 200px"
-              >
-                <el-option
-                  v-for="u in clientOptions"
-                  :key="u.id"
-                  :label="u.realName || u.username"
-                  :value="u.id"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="结算单号">
-              <el-input
-                v-model="sheetSearchForm.settlementNo"
-                clearable
-                placeholder="模糊查询"
-                style="width: 200px"
-              />
-            </el-form-item>
-            <el-form-item label="结算时间">
-              <el-date-picker
-                v-model="sheetDateRange"
-                type="daterange"
-                value-format="YYYY-MM-DDTHH:mm:ss"
-                range-separator="至"
-                start-placeholder="开始"
-                end-placeholder="结束"
-              />
-            </el-form-item>
-            <el-form-item>
-              <el-button class="btn-main" @click="handleSheetSearch">搜索</el-button>
-              <el-button class="btn-ghost" @click="handleSheetReset">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
+        <section class="panel">
+          <div class="panel-top">
+            <h2>
+              <el-icon class="title-ic"><Setting /></el-icon>
+              <span>结算单记录</span>
+            </h2>
+          </div>
+
+          <el-card shadow="never" class="sheet-main-card" v-loading="sheetLoading">
+            <div class="filter-block">
+              <el-form :model="sheetSearchForm" class="filter-form" label-position="top">
+                <div class="filter-grid">
+                  <el-form-item label="客户">
+                    <el-select v-model="sheetSearchForm.clientId" filterable clearable placeholder="全部">
+                      <el-option
+                        v-for="u in clientOptions"
+                        :key="u.id"
+                        :label="u.realName || u.username"
+                        :value="u.id"
+                      />
+                    </el-select>
+                  </el-form-item>
+                  <el-form-item label="结算单号">
+                    <el-input v-model="sheetSearchForm.settlementNo" clearable placeholder="模糊查询" />
+                  </el-form-item>
+                  <el-form-item label="结算时间">
+                    <el-date-picker
+                      v-model="sheetDateRange"
+                      type="daterange"
+                      value-format="YYYY-MM-DDTHH:mm:ss"
+                      range-separator="至"
+                      start-placeholder="开始"
+                      end-placeholder="结束"
+                    />
+                  </el-form-item>
+                </div>
+                <div class="filter-actions-row">
+                  <div class="filter-actions-end">
+                    <el-button class="btn-ghost" @click="handleSheetReset">重置</el-button>
+                    <el-button class="btn-main" type="primary" @click="handleSheetSearch">搜索</el-button>
+                  </div>
+                </div>
+              </el-form>
+            </div>
 
-        <el-card shadow="never" v-loading="sheetLoading">
-          <el-table :data="sheetTableData" stripe @expand-change="handleSheetRowExpand">
+          <el-table
+            class="client-settlement-sheet-table"
+            :data="sheetTableData"
+            stripe
+            @expand-change="handleSheetRowExpand"
+          >
             <el-table-column type="expand" width="48">
               <template #default="{ row }">
                 <div class="sheet-row-expand-wrap" v-loading="isSheetRowLoading(row.id)">
@@ -464,10 +466,10 @@
             </el-table-column>
             <el-table-column prop="settlementAt" label="结算时间" min-width="170" />
             <el-table-column prop="createName" label="操作人" width="100" />
-            <el-table-column label="操作" width="140" fixed="right">
+            <el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
               <template #default="{ row }">
-                <el-button class="btn-op-item primary" link @click="openSheetDetail(row.id)">详情</el-button>
-                <el-button class="btn-op-item" link @click="openSheetEdit(row)">编辑</el-button>
+                <el-button class="btn-op-item primary" @click="openSheetDetail(row.id)">详情</el-button>
+                <el-button class="btn-op-item" @click="openSheetEdit(row)">编辑</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -492,7 +494,8 @@
               "
             />
           </div>
-        </el-card>
+          </el-card>
+        </section>
       </el-tab-pane>
     </el-tabs>
 
@@ -502,6 +505,8 @@
       width="720px"
       destroy-on-close
       @closed="resetSettlementDialog"
+      class="client-settlement-dialog settlement-confirm-dialog"
+      modal-class="client-settlement-dialog-mask"
     >
       <el-alert type="info" :closable="false" class="mb-3">
         已选 {{ selectedCount }} 笔订单,合计
@@ -528,7 +533,14 @@
       </template>
     </el-dialog>
 
-    <el-dialog v-model="sheetDetailVisible" title="结算单详情" width="1040px" destroy-on-close>
+    <el-dialog
+      v-model="sheetDetailVisible"
+      title="结算单详情"
+      width="1240px"
+      destroy-on-close
+      class="client-settlement-dialog sheet-detail-dialog"
+      modal-class="client-settlement-dialog-mask"
+    >
       <SettlementSheetDetailPanel
         v-if="sheetDetail"
         :detail="sheetDetail"
@@ -543,23 +555,36 @@
       width="720px"
       destroy-on-close
       @closed="resetSheetEdit"
+      class="client-settlement-dialog sheet-edit-dialog"
+      modal-class="client-settlement-dialog-mask"
     >
-      <el-form label-width="100px">
-        <el-form-item label="结算备注">
-          <el-input
-            v-model="sheetEditForm.remark"
-            type="textarea"
-            :rows="3"
-            maxlength="500"
-            show-word-limit
+      <div class="dialog-scroll sheet-edit-dialog-scroll">
+        <div class="form-section">
+          <h4>结算信息</h4>
+          <el-form label-position="top">
+            <div class="form-grid-2">
+              <el-form-item label="结算备注" class="form-col-span-2">
+                <el-input
+                  v-model="sheetEditForm.remark"
+                  type="textarea"
+                  :rows="4"
+                  maxlength="500"
+                  show-word-limit
+                  placeholder="请输入结算备注(选填)"
+                />
+              </el-form-item>
+            </div>
+          </el-form>
+        </div>
+        <div class="form-section">
+          <h4>结算凭证</h4>
+          <VoucherMediaUploader
+            v-model="sheetEditForm.voucherUrls"
+            business-type="client_settlement"
+            :business-id="sheetEditId || 'temp'"
           />
-        </el-form-item>
-      </el-form>
-      <VoucherMediaUploader
-        v-model="sheetEditForm.voucherUrls"
-        business-type="client_settlement"
-        :business-id="sheetEditId || 'temp'"
-      />
+        </div>
+      </div>
       <template #footer>
         <el-button class="btn-ghost" @click="sheetEditVisible = false">取消</el-button>
         <el-button class="btn-main" :loading="sheetEditSaving" @click="saveSheetEdit">保存</el-button>
@@ -573,6 +598,7 @@
 <script setup lang="ts">
   import { computed, nextTick, onMounted, reactive, ref } from 'vue'
   import { ElMessage, ElMessageBox } from 'element-plus'
+  import { Setting } from '@element-plus/icons-vue'
   import {
     fetchCreateClientSettlement,
     fetchClientSettlementOrderList,
@@ -1113,11 +1139,13 @@
 
 <style lang="scss" scoped>
   .page-container {
-    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
   }
 
-  .search-card {
-    margin-bottom: 16px;
+  .settlement-page-tabs :deep(.el-tabs__header) {
+    margin-bottom: 12px;
   }
 
   .stats-row {
@@ -1127,146 +1155,345 @@
     margin-bottom: 16px;
   }
 
+  .stats-row--compact {
+    max-width: 980px;
+    margin-left: auto;
+    margin-right: auto;
+  }
+
+  .stats-row--compact .stat-card {
+    border: 0 !important;
+  }
+
   .stat-title {
-    color: #909399;
+    color: #64748b;
     font-size: 13px;
+    font-weight: 600;
+    line-height: 1.35;
   }
 
   .stat-value {
     margin-top: 6px;
     font-size: 24px;
-    font-weight: 600;
+    font-weight: 700;
+    line-height: 1.1;
   }
 
   .stat-value.amount {
     color: #dc2626;
   }
 
-  .toolbar {
-    display: flex;
-    align-items: center;
-    gap: 12px;
-    margin-bottom: 12px;
+  .pending-main-card,
+  .sheet-main-card,
+  .stat-card {
+    border: 1px solid var(--mint-border, #d9e8e2);
+    border-radius: 10px;
+    background: #fff;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+    overflow: hidden;
   }
 
-  .amount-text {
-    color: #dc2626;
-    font-weight: 600;
+  /* 客户结算管理 - 结算单记录主卡片:按需求去掉外边框 */
+  .sheet-main-card {
+    border: 0 !important;
   }
 
-  .pagination {
-    display: flex;
-    justify-content: flex-end;
-    margin-top: 16px;
+  .pending-main-card :deep(.el-card__body),
+  .sheet-main-card :deep(.el-card__body) {
+    padding: 0;
   }
 
-  .tab-button-group {
-    display: flex;
-    flex-wrap: wrap;
-    align-items: center;
-    gap: 10px;
+  .filter-block {
+    padding: 12px 16px 10px;
+    border-bottom: 1px solid #eef4f0;
+    background: #fff;
   }
 
-  .region-tabs {
-    margin-bottom: 16px;
+  .filter-form :deep(.el-form-item) {
+    margin-bottom: 0;
   }
 
-  .mb-3 {
-    margin-bottom: 12px;
+  .filter-form :deep(.el-form-item__label) {
+    font-size: 13px;
+    font-weight: 500;
+    color: var(--mint-text-muted, #64748b);
+    padding-bottom: 4px;
+    line-height: 1.2;
   }
 
-  .settlement-remark-form {
-    margin-top: 16px;
+  .filter-grid {
+    display: grid;
+    grid-template-columns: repeat(3, minmax(0, 1fr));
+    gap: 10px 14px;
   }
 
-  .voucher-list {
+  .filter-actions-row {
+    display: flex;
+    justify-content: flex-end;
+    margin-top: 10px;
+  }
+
+  .filter-actions-end {
     display: inline-flex;
     align-items: center;
     gap: 8px;
-    margin-left: 12px;
   }
 
-  .voucher-list--block {
+  .toolbar {
     display: flex;
-    flex-wrap: wrap;
-    margin-left: 0;
-    margin-top: 8px;
+    align-items: center;
+    gap: 12px;
+    padding: 8px 16px;
+    margin-bottom: 0;
+    border-bottom: 1px solid var(--mint-border, #d9e8e2);
+    background: #f8fafc;
   }
 
-  .text-muted {
-    color: #909399;
-    font-size: 12px;
-    margin-top: 2px;
+  .amount-text {
+    color: #dc2626;
+    font-weight: 600;
   }
 
-  .ml-1 {
-    margin-left: 6px;
+  .pagination {
+    display: flex;
+    justify-content: flex-end;
+    margin-top: 0;
+    padding: 10px 16px 12px;
+    border-top: 1px solid var(--mint-border, #d9e8e2);
+    background: #fff;
   }
 
-  .line-cell {
-    display: inline-flex;
-    align-items: center;
-    gap: 8px;
+  .order-row-expand-wrap {
+    padding: 0;
+    background: #f8fafc;
+    border-radius: 0;
+  }
+
+  .client-settlement-table :deep(td.el-table__expanded-cell),
+  .client-settlement-sheet-table :deep(td.el-table__expanded-cell),
+  .sheet-orders-table :deep(td.el-table__expanded-cell),
+  .client-settlement-table :deep(.el-table__body td.el-table__expanded-cell),
+  .client-settlement-sheet-table :deep(.el-table__body td.el-table__expanded-cell),
+  .sheet-orders-table :deep(.el-table__body td.el-table__expanded-cell) {
+    padding: 12px !important;
+    text-align: left !important;
+    vertical-align: top;
+    background: #f8fafc;
+    box-sizing: border-box;
+    overflow: hidden;
   }
 
-  .line-img {
-    width: 36px;
-    height: 36px;
-    border-radius: 6px;
-    flex-shrink: 0;
+  .client-settlement-table :deep(td.el-table__expanded-cell > .cell),
+  .client-settlement-sheet-table :deep(td.el-table__expanded-cell > .cell),
+  .sheet-orders-table :deep(td.el-table__expanded-cell > .cell) {
+    display: block !important;
+    padding: 0 !important;
+    text-align: left !important;
   }
 
-  .order-row-expand-wrap {
-    padding: 8px 12px;
-    background: #fafbfc;
+  /* 第二层:结算单展开后的“订单列表”容器 */
+  .sheet-row-expand-wrap {
+    margin: 0;
+    border-radius: 10px;
+    max-width: 100%;
+    box-sizing: border-box;
+    overflow: hidden;
+    overflow-x: auto;
+    position: relative;
+    padding: 12px 12px 14px 18px;
+    background: #f8fafc;
+  }
+
+  .sheet-row-expand-wrap::after {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 4px;
+    background: #10b981;
+    z-index: 2;
+    pointer-events: none;
+  }
+
+  .sheet-row-expand-wrap :deep(.sheet-orders-table) {
+    border: 1px solid var(--mint-border, #d9e8e2);
     border-radius: 8px;
+    overflow: hidden;
+    background: #fff;
+    position: relative;
+    z-index: 1;
   }
 
-  :deep(td.el-table__expanded-cell) {
-    padding: 0 !important;
-    text-align: left !important;
+  .sheet-row-expand-wrap :deep(.sheet-orders-table th.el-table__cell) {
+    background: #e2e8f0 !important;
+    color: var(--mint-text-muted, #64748b);
+    font-size: 11px;
+    font-weight: 600;
   }
 
-  :deep(td.el-table__expanded-cell > .cell) {
-    display: block !important;
-    padding: 0 !important;
-    text-align: left !important;
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table__cell) {
+    padding: 8px 10px;
   }
 
-  .order-row-expand-table {
-    width: max-content;
-    max-width: 100%;
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table__inner-wrapper),
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table__header-wrapper),
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table__body-wrapper) {
+    width: max-content !important;
+    min-width: 100% !important;
+  }
 
-    :deep(.el-table__body-wrapper) {
-      overflow-x: auto;
-    }
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table__body-wrapper),
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-scrollbar__wrap) {
+    overflow-x: auto !important;
+  }
+
+  .sheet-row-expand-wrap :deep(.sheet-orders-table.el-table),
+  .sheet-row-expand-wrap :deep(.sheet-orders-table .el-table) {
+    width: max-content !important;
+    min-width: 100% !important;
   }
 
   .settlement-row-expand-table-wrap {
-    display: inline-block;
-    width: fit-content;
+    display: block;
+    width: 100%;
     max-width: 100%;
-    overflow-x: auto;
-    overflow-y: hidden;
-    border-radius: 8px;
+    overflow: hidden;
+    border-radius: 0;
     text-align: left;
+    position: relative;
+    background: #f8fafc;
+    padding: 12px 12px 14px 16px;
 
     :deep(.el-table__inner-wrapper),
     :deep(.el-table__header-wrapper),
     :deep(.el-table__body-wrapper) {
-      width: max-content;
+      width: 100%;
     }
   }
 
-  .order-row-expand-summary {
-    margin-top: 10px;
+  .settlement-row-expand-table-wrap::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 3px;
+    background: #10b981;
+  }
+
+  /* 第三层:孙列表琥珀层级 */
+  .client-settlement-sheet-table :deep(.sheet-orders-table .settlement-row-expand-table-wrap) {
+    margin-top: 4px;
+    padding-left: 14px;
+    padding-top: 10px;
+    padding-right: 0;
+    padding-bottom: 0;
+    border-left: 3px solid #f59e0b;
+    background: linear-gradient(90deg, rgba(254, 243, 199, 0.35) 0%, transparent 12px);
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .settlement-row-expand-table-wrap::before) {
+    background: #f59e0b;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .order-row-expand-table) {
+    border-color: #fcd34d !important;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .order-row-expand-table th.el-table__cell) {
+    background: #fef3c7 !important;
+    color: #92400e !important;
+    font-size: 10px !important;
+    border-bottom: 1px solid #fcd34d !important;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .order-row-expand-table td.el-table__cell) {
+    font-size: 12px;
+    border-bottom: 1px solid #fef3c7 !important;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .order-row-expand-table .el-table__cell) {
+    padding: 6px 8px !important;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .order-row-expand-table tr:hover td.el-table__cell) {
+    background: #fffbeb !important;
+  }
+
+  .client-settlement-table :deep(td.el-table__cell.el-table__expand-column > .cell),
+  .client-settlement-sheet-table :deep(td.el-table__cell.el-table__expand-column > .cell),
+  .client-settlement-sheet-table :deep(.sheet-orders-table td.el-table__cell.el-table__expand-column > .cell) {
     display: flex;
-    gap: 20px;
-    justify-content: flex-end;
-    color: #606266;
-    font-size: 13px;
+    align-items: center;
+    justify-content: center;
+    font-size: 0;
+    line-height: 0;
+    overflow: hidden;
+  }
+
+  .client-settlement-table :deep(.el-table__expand-icon),
+  .client-settlement-sheet-table :deep(.el-table__expand-icon),
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon) {
+    width: 28px;
+    height: 28px;
+    border-radius: 6px;
+    border: 1px solid var(--mint-border, #d9e8e2);
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
+    color: var(--mint-text-muted, #64748b);
+    background: var(--mint-surface, #fff);
+    font-size: 0;
+    line-height: 0;
   }
 
+  .client-settlement-table :deep(.el-table__expand-icon:hover),
+  .client-settlement-sheet-table :deep(.el-table__expand-icon:hover),
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon:hover) {
+    background: var(--mint-primary-bg, #ecfdf5);
+    border-color: #10b981;
+    color: var(--mint-primary-dark, #059669);
+  }
+
+  .client-settlement-table :deep(.el-table__expand-icon--expanded),
+  .client-settlement-sheet-table :deep(.el-table__expand-icon--expanded),
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon--expanded) {
+    background: var(--mint-primary-bg, #ecfdf5);
+    border-color: #10b981;
+    color: var(--mint-primary-dark, #059669);
+  }
+
+  .client-settlement-table :deep(.el-table__expand-icon svg),
+  .client-settlement-sheet-table :deep(.el-table__expand-icon svg),
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon svg) {
+    transition: transform 0.15s ease;
+    width: 14px;
+    height: 14px;
+  }
+
+  .client-settlement-table :deep(.el-table__expand-icon--expanded svg),
+  .client-settlement-sheet-table :deep(.el-table__expand-icon--expanded svg),
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon--expanded svg) {
+    transform: rotate(180deg);
+  }
+
+  /* 二级子表 expand icon:强制与一级一致(避免 size="small" 影响) */
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon) {
+    width: 28px !important;
+    height: 28px !important;
+    min-width: 28px !important;
+    min-height: 28px !important;
+    border-radius: 6px !important;
+  }
+
+  .client-settlement-sheet-table :deep(.sheet-orders-table .el-table__expand-icon svg) {
+    width: 14px !important;
+    height: 14px !important;
+  }
+
+  /* 二/三级子表:商品缩略图尺寸对齐【商家结算管理】 */
   .expand-product-cell {
     display: inline-flex;
     align-items: center;
@@ -1306,79 +1533,100 @@
     white-space: nowrap;
   }
 
-  .sheet-row-expand-wrap {
-    padding: 10px 12px;
-    background: #fafbfc;
-    border-radius: 8px;
+</style>
+
+<!-- Teleport 到 body:弹窗内容需非 scoped 才能稳定命中 -->
+<style lang="scss">
+  .client-settlement-dialog.el-dialog {
+    display: flex;
+    flex-direction: column;
+    max-height: calc(100vh - 64px);
   }
 
-  .sheet-order-tree-table {
-    :deep(.el-table__body-wrapper) {
-      overflow-x: auto;
-    }
+  .client-settlement-dialog .el-dialog__header {
+    flex-shrink: 0;
+    background: linear-gradient(135deg, #ecfdf5 0%, #ffffff 70%);
+    border-bottom: 1px solid var(--mint-border, #d9e8e2);
   }
 
-  .sheet-orders-table {
-    :deep(.el-table__body-wrapper) {
-      overflow-x: auto;
-    }
+  .client-settlement-dialog .el-dialog__body {
+    flex: 1 1 auto;
+    min-height: 0;
+    padding: 0 !important;
+    overflow: hidden;
   }
 
-  .order-row-head {
-    display: flex;
-    align-items: center;
-    gap: 8px;
-    flex-wrap: wrap;
-    margin-bottom: 4px;
+  .client-settlement-dialog .dialog-scroll {
+    overflow-y: auto;
+    overflow-x: hidden;
+    padding: 20px 22px;
+    flex: 1;
   }
 
-  .order-row-meta {
-    font-size: 12px;
-    line-height: 1.5;
-    color: #606266;
+  .client-settlement-dialog .el-dialog__footer {
+    padding: 12px 22px !important;
+    border-top: 1px solid var(--mint-border, #d9e8e2);
+    background: #f8fafc;
+  }
 
-    &.muted {
-      color: #909399;
-    }
+  .client-settlement-dialog .el-dialog__footer .el-button {
+    height: 36px;
+    border-radius: 8px;
+    font-weight: 600;
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
   }
 
-  .line-product-cell {
-    display: flex;
-    align-items: flex-start;
-    gap: 10px;
+  .client-settlement-dialog-mask {
+    backdrop-filter: none !important;
   }
 
-  .line-thumb {
-    width: 44px;
-    height: 44px;
-    border-radius: 8px;
-    flex-shrink: 0;
+  .client-settlement-dialog.sheet-edit-dialog .form-section {
+    margin-bottom: 20px;
+    padding-bottom: 16px;
+    border-bottom: 1px dashed var(--mint-border, #d9e8e2);
   }
 
-  .line-thumb--ph {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    background: #ebeef5;
-    font-size: 11px;
-    color: #909399;
+  .client-settlement-dialog.sheet-edit-dialog .form-section:last-of-type {
+    margin-bottom: 0;
+    padding-bottom: 0;
+    border-bottom: none;
   }
 
-  .line-product-text {
-    display: flex;
-    flex-direction: column;
-    gap: 4px;
-    min-width: 0;
+  .client-settlement-dialog.sheet-edit-dialog .form-section h4 {
+    margin: 0 0 12px;
     font-size: 13px;
+    font-weight: 700;
+    color: var(--mint-text-muted, #64748b);
+    letter-spacing: 0.04em;
   }
 
-  .line-note {
-    font-size: 12px;
-    color: #909399;
+  .client-settlement-dialog.sheet-edit-dialog .form-grid-2 {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    gap: 12px 16px;
+  }
+
+  .client-settlement-dialog.sheet-edit-dialog .form-col-span-2 {
+    grid-column: 1 / -1;
   }
 
-  .cell-muted {
-    color: #c0c4cc;
+  .client-settlement-dialog.sheet-edit-dialog .el-form-item {
+    margin-bottom: 0;
   }
 
+  .client-settlement-dialog.sheet-edit-dialog .el-form-item__label {
+    color: var(--mint-text-muted, #64748b) !important;
+    font-weight: 600;
+    font-size: 12px;
+    line-height: 1.2;
+    padding-bottom: 6px;
+  }
+
+  @media (max-width: 760px) {
+    .client-settlement-dialog.sheet-edit-dialog .form-grid-2 {
+      grid-template-columns: 1fr;
+    }
+  }
 </style>

+ 1 - 1
web-admin/src/views/system/order/index.vue

@@ -2184,7 +2184,7 @@
   }
 
   .filter-form :deep(.el-form-item__label) {
-    font-size: 11px;
+    font-size: 13px;
     font-weight: 500;
     color: var(--mint-text-muted, #64748b);
     padding: 0 0 4px;

+ 10 - 1
web-admin/src/views/system/supplier-settlement/index.vue

@@ -85,6 +85,10 @@
           </div>
 
           <div class="toolbar">
+            <span class="list-toolbar-selected" aria-live="polite"
+              >已选<span class="sel-num">{{ selectedCount }}</span
+              >项</span
+            >
             <el-button class="btn-ghost" @click="handleSelectAllFiltered">全选可结算订单(已完结·跨分页)</el-button>
             <el-button class="btn-main" :disabled="!selectedCount" @click="openSettlementDialog">结算</el-button>
             <el-tag v-if="selectionMode === 'allFiltered'" type="warning">已启用跨分页全选,可取消少量订单</el-tag>
@@ -1141,6 +1145,11 @@
     overflow: hidden;
   }
 
+  /* 商家结算管理 - 结算单记录主卡片:按需求去掉外边框 */
+  .sheet-main-card {
+    border: 0 !important;
+  }
+
   .search-card :deep(.el-card__body) {
     padding: 12px 16px 12px;
   }
@@ -1345,7 +1354,7 @@
   }
 
   .filter-form :deep(.el-form-item__label) {
-    font-size: 11px;
+    font-size: 13px;
     font-weight: 500;
     color: var(--mint-text-muted, #64748b);
     padding-bottom: 4px;