Просмотр исходного кода

style: balance store table columns and keep actions visible

彭峰 4 дней назад
Родитель
Сommit
4a1bd5de21

+ 4 - 2
projects/xiaoshu-admin/src/app/pages/operations-stores.component.html

@@ -28,13 +28,15 @@
 
 <section class="content-card">
   <header><div><lucide-icon [img]="icons.Building2" [size]="19"/><strong>门店名单</strong></div><span>{{page()?.total||0}} 家 · {{page()?.sync?.label||'已读取当前数据'}}</span></header>
-  <div class="table-scroll"><table class="data-table"><thead><tr><th>门店</th><th>上级门店</th><th>联系方式</th><th>会员</th><th title="学习状态为正在学习,且账号状态为正常">在学正常学员</th><th>陪练</th><th>今日排课</th><th>历史排课</th><th>最近排课</th><th>最后登录</th><th>状态</th><th>操作</th></tr></thead><tbody>
+  <div class="table-scroll"><table class="data-table">
+    <colgroup><col class="store-col"/><col class="parent-col"/><col class="contact-col"/><col class="count-col"/><col class="studying-col"/><col class="count-col"/><col class="schedule-col"/><col class="schedule-col"/><col class="date-col"/><col class="date-col"/><col class="status-col"/><col class="actions-col"/></colgroup>
+    <thead><tr><th>门店</th><th>上级门店</th><th>联系方式</th><th>会员</th><th title="学习状态为正在学习,且账号状态为正常">在学正常学员</th><th>陪练</th><th>今日排课</th><th>历史排课</th><th>最近排课</th><th>最后登录</th><th>状态</th><th>操作</th></tr></thead><tbody>
     @for(row of page()?.items||[];track row.objectId){<tr>
       <td><strong>{{row.storeName}}</strong><small>{{row.username}} · ID {{row.userId}}</small>@if(row.sourceLabel){<small class="source-note">{{row.sourceLabel}}</small>}</td>
       <td>{{row.parentStoreName||'总店/未归属'}}</td>
       <td>{{row.contactName||'未设置联系人'}}<small>{{row.mobile||row.mobileMasked||'未留手机号'}}</small></td>
       <td><strong>{{row.memberCount}}</strong> 人</td><td><strong>{{row.activeStudyingMemberCount ?? '—'}}</strong>@if(row.activeStudyingMemberCount != null){ 人}</td><td><strong>{{row.coachCount}}</strong> 人</td><td>{{row.todayAppointments}} 节</td><td>{{row.totalAppointments}} 节</td>
-      <td>{{row.lastAppointmentAt?(row.lastAppointmentAt|date:'yyyy-MM-dd HH:mm'):'暂无'}}</td><td>{{row.lastLoginAt?(row.lastLoginAt|date:'yyyy-MM-dd HH:mm'):'从未登录'}}</td>
+      <td>@if(row.lastAppointmentAt){<span>{{row.lastAppointmentAt|date:'yyyy-MM-dd'}}</span><small>{{row.lastAppointmentAt|date:'HH:mm'}}</small>}@else{暂无}</td><td>@if(row.lastLoginAt){<span>{{row.lastLoginAt|date:'yyyy-MM-dd'}}</span><small>{{row.lastLoginAt|date:'HH:mm'}}</small>}@else{从未登录}</td>
       <td><span class="badge" [class.muted]="row.status==='disabled'">{{row.statusLabel}}</span></td>
       <td><div class="row-actions">@if(!row.readOnly){<a class="icon-action" [routerLink]="['/admin/stores',row.objectId]" aria-label="查看门店经营详情" title="经营详情"><lucide-icon [img]="icons.Eye" [size]="16"/></a>}@else{<span class="readonly-label">待同步</span>}@if(page()?.canManage&&!row.readOnly){<button class="icon-action" type="button" (click)="openEdit(row)" aria-label="编辑门店" title="编辑"><lucide-icon [img]="icons.Pencil" [size]="16"/></button><button class="icon-action danger" type="button" (click)="openEdit(row,true)" aria-label="删除门店" title="删除"><lucide-icon [img]="icons.Trash2" [size]="16"/></button>}</div></td>
     </tr>}@empty{<tr><td colspan="12"><div class="empty">没有符合条件的门店</div></td></tr>}

+ 35 - 4
projects/xiaoshu-admin/src/app/pages/operations-stores.component.scss

@@ -50,8 +50,39 @@
 .summary-grid strong { display: block; margin: 7px 0 2px; color: #21352e; font-size: 29px; line-height: 1; }
 .summary-grid small { overflow: hidden; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
 
-.data-table { min-width: 1500px; }
-.row-actions { min-width: 122px; flex-wrap: nowrap; }
+// Allocate space by content instead of letting long dates push actions off-screen.
+.data-table { width: 100%; min-width: 1120px; table-layout: fixed; }
+.store-col { width: 13%; }
+.parent-col { width: 8%; }
+.contact-col { width: 10.5%; }
+.count-col { width: 5%; }
+.studying-col { width: 7%; }
+.schedule-col { width: 6%; }
+.status-col { width: 7%; }
+.date-col { width: 9%; }
+.actions-col { width: 14.5%; }
+.data-table th, .data-table td { padding: 16px 10px; vertical-align: middle; }
+.data-table th:first-child, .data-table td:first-child { padding-left: 20px; }
+.data-table td { overflow-wrap: anywhere; }
+.data-table th:nth-child(n+4):nth-child(-n+8),
+.data-table td:nth-child(n+4):nth-child(-n+8),
+.data-table th:nth-last-child(-n+2), .data-table td:nth-last-child(-n+2) { text-align: center; }
+.data-table td:nth-child(n+4):nth-child(-n+10) { font-variant-numeric: tabular-nums; }
+.data-table th:nth-child(n+4):nth-child(-n+8),
+.data-table td:nth-child(n+4):nth-child(-n+8) { padding-inline: 6px; }
+.data-table td:nth-child(n+4):nth-child(-n+8), .data-table .badge { white-space: nowrap; }
+.data-table th:last-child, .data-table td:last-child {
+  position: sticky;
+  right: 0;
+  z-index: 1;
+  padding-inline: 16px;
+  background: #fff;
+  box-shadow: -1px 0 0 #edf1ef;
+}
+.data-table th:last-child { background: #f6f9f7; }
+.row-actions { display: flex; min-width: 0; justify-content: center; gap: 8px; flex-wrap: nowrap; }
+.row-actions .icon-action { flex: 0 0 34px; }
+
 .store-editor { width: min(640px, 100%); }
 .store-editor header p { margin: 0; color: #258b68; font-size: 11px; font-weight: 800; letter-spacing: .16em; }
 .store-editor header h2 { margin: 5px 0 7px; }
@@ -66,8 +97,8 @@
 .read-only { color: #71817b; font-size: 12px; }
 
 @media (max-width: 1180px) { .summary-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
-@media (max-width: 1000px) {
-  .toolbar { grid-template-columns: minmax(220px, 1fr) minmax(160px, .55fr) auto auto; }
+@media (max-width: 1180px) {
+  .toolbar { grid-template-columns: minmax(0, 1fr) minmax(160px, .55fr) auto auto; }
   .toolbar .grow { min-width: 0; }
   .toolbar label:not(.grow) { min-width: 160px; }
 }