Преглед изворни кода

refactor(admin): 高频页 KPI 卡片迁移至全局 StatCard 并清理死亡样式

将 Tasks / TeacherDashboard / DanSettlement / TeacherOrders / TeacherPackages
5 张高频页的手写旧 stat-card 标记统一替换为全局注册的 <StatCard>,
收敛到 Ant Design 5 语义色令牌,并移除对应死亡 CSS。
- 旧色值(blue/green/orange/purple)由 StatCard.COLOR_MAP 自动映射
- DanSettlement 移除 .admin-page{padding:20px} 局部覆盖,改由 B 的 24px 统一留白承接
- 净删 330 行,组件复用度与视觉一致性提升
liaoxg пре 5 дана
родитељ
комит
6ce93751f3

+ 2 - 24
cfc-web/src/views/Tasks.vue

@@ -80,16 +80,10 @@
       <!-- 统计卡片 -->
       <el-row :gutter="20" style="margin-bottom: 20px">
         <el-col :span="6">
-          <el-card class="stat-card">
-            <div class="stat-label">总任务数</div>
-            <div class="stat-value">{{ stats.total || 0 }}</div>
-          </el-card>
+          <StatCard label="总任务数" :value="stats.total || 0" color="primary" icon="el-icon-tickets" />
         </el-col>
         <el-col :span="6">
-          <el-card class="stat-card">
-            <div class="stat-label">今日任务</div>
-            <div class="stat-value">{{ stats.today || 0 }}</div>
-          </el-card>
+          <StatCard label="今日任务" :value="stats.today || 0" color="success" icon="el-icon-date" />
         </el-col>
       </el-row>
 
@@ -390,22 +384,6 @@ export default {
 </script>
 
 <style scoped>
-.stat-card {
-  text-align: center;
-}
-
-.stat-label {
-  color: #909399;
-  font-size: 14px;
-  margin-bottom: 10px;
-}
-
-.stat-value {
-  font-size: 28px;
-  font-weight: bold;
-  color: #409EFF;
-}
-
 .sort-header {
   cursor: pointer;
   user-select: none;

+ 4 - 41
cfc-web/src/views/TeacherDashboard.vue

@@ -3,48 +3,16 @@
     <!-- 统计卡片 -->
     <el-row :gutter="24" class="td-stat-row">
       <el-col :span="6">
-        <div class="td-stat-card">
-          <div class="td-stat-icon" style="background: #1677FF">
-            <i class="el-icon-user-solid"></i>
-          </div>
-          <div class="td-stat-content">
-            <div class="td-stat-value">{{ teacherStats.serviceFamilyCount }}</div>
-            <div class="td-stat-label">服务家庭</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-user-solid" label="服务家庭" :value="teacherStats.serviceFamilyCount" :thousand="true" />
       </el-col>
       <el-col :span="6">
-        <div class="td-stat-card">
-          <div class="td-stat-icon" style="background: #52C41A">
-            <i class="el-icon-s-data"></i>
-          </div>
-          <div class="td-stat-content">
-            <div class="td-stat-value">{{ teacherStats.activeFamilyCount }}</div>
-            <div class="td-stat-label">活跃家庭</div>
-          </div>
-        </div>
+        <StatCard color="success" icon="el-icon-s-data" label="活跃家庭" :value="teacherStats.activeFamilyCount" :thousand="true" />
       </el-col>
       <el-col :span="6">
-        <div class="td-stat-card">
-          <div class="td-stat-icon" style="background: #FAAD14">
-            <i class="el-icon-coin"></i>
-          </div>
-          <div class="td-stat-content">
-            <div class="td-stat-value">{{ formatPriceWithSymbol(teacherStats.monthlySales) }}</div>
-            <div class="td-stat-label">本月销售额</div>
-          </div>
-        </div>
+        <StatCard color="warning" icon="el-icon-coin" label="本月销售额" :value="formatPriceWithSymbol(teacherStats.monthlySales)" />
       </el-col>
       <el-col :span="6">
-        <div class="td-stat-card">
-          <div class="td-stat-icon" style="background: #1677FF">
-            <i class="el-icon-wallet"></i>
-          </div>
-          <div class="td-stat-content">
-            <div class="td-stat-value">{{ formatPriceWithSymbol(teacherStats.myCommission) }}</div>
-            <div class="td-stat-label">我的佣金</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-wallet" label="我的佣金" :value="formatPriceWithSymbol(teacherStats.myCommission)" />
       </el-col>
     </el-row>
 
@@ -317,11 +285,6 @@ export default {
 /* ===== Teacher Dashboard Styles ===== */
 .teacher-dashboard-wrapper { padding: 0; }
 .td-stat-row { margin-bottom: 24px; }
-.td-stat-card { display: flex; align-items: center; padding: 20px 24px; background: #FFFFFF; border-radius: 16px; box-shadow: 0 2px 12px rgba(59,130,246,0.08); border: none; transition: all 0.3s; }
-.td-stat-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(59,130,246,0.12); }
-.td-stat-icon { width: 56px; height: 56px; border-radius: 14px; display: flex; align-items: center; justify-content: center; margin-right: 16px; font-size: 24px; color: #FFFFFF; flex-shrink: 0; }
-.td-stat-value { font-size: 28px; font-weight: 700; color: #1E293B; line-height: 1.2; }
-.td-stat-label { font-size: 14px; color: #64748B; margin-top: 4px; }
 .td-section-row { margin-bottom: 24px; }
 .td-card-header { display: flex; justify-content: space-between; align-items: center; }
 .td-card-title { font-size: 16px; font-weight: 600; color: #1E293B; }

+ 3 - 102
cfc-web/src/views/admin/DanSettlement.vue

@@ -3,46 +3,13 @@
     <!-- 统计卡片 -->
     <el-row :gutter="20" style="margin-bottom: 20px;">
       <el-col :span="8">
-        <el-card shadow="hover">
-          <div class="stat-card">
-            <div class="stat-icon-wrap total">
-              <i class="el-icon-money"></i>
-            </div>
-            <div class="stat-info">
-              <div class="stat-label">总结算金额</div>
-              <div class="stat-value">¥{{ (stats.totalAmount / 100).toFixed(2) }}</div>
-              <div class="stat-desc">共 {{ stats.totalCount }} 笔</div>
-            </div>
-          </div>
-        </el-card>
+        <StatCard color="primary" icon="el-icon-money" label="总结算金额({{ stats.totalCount }} 笔)" :value="'¥' + (stats.totalAmount / 100).toFixed(2)" />
       </el-col>
       <el-col :span="8">
-        <el-card shadow="hover">
-          <div class="stat-card">
-            <div class="stat-icon-wrap pending">
-              <i class="el-icon-time"></i>
-            </div>
-            <div class="stat-info">
-              <div class="stat-label">待结算金额</div>
-              <div class="stat-value pending">¥{{ (stats.pendingAmount / 100).toFixed(2) }}</div>
-              <div class="stat-desc">共 {{ stats.pendingCount }} 笔</div>
-            </div>
-          </div>
-        </el-card>
+        <StatCard color="warning" icon="el-icon-time" label="待结算金额({{ stats.pendingCount }} 笔)" :value="'¥' + (stats.pendingAmount / 100).toFixed(2)" />
       </el-col>
       <el-col :span="8">
-        <el-card shadow="hover">
-          <div class="stat-card">
-            <div class="stat-icon-wrap settled">
-              <i class="el-icon-circle-check"></i>
-            </div>
-            <div class="stat-info">
-              <div class="stat-label">已结算金额</div>
-              <div class="stat-value settled">¥{{ (stats.settledAmount / 100).toFixed(2) }}</div>
-              <div class="stat-desc">共 {{ stats.settledCount }} 笔</div>
-            </div>
-          </div>
-        </el-card>
+        <StatCard color="success" icon="el-icon-circle-check" label="已结算金额({{ stats.settledCount }} 笔)" :value="'¥' + (stats.settledAmount / 100).toFixed(2)" />
       </el-col>
     </el-row>
 
@@ -342,9 +309,6 @@ export default {
 </script>
 
 <style scoped>
-.admin-page {
-  padding: 20px;
-}
 .sort-header {
   cursor: pointer;
   user-select: none;
@@ -371,69 +335,6 @@ export default {
   align-items: center;
 }
 
-.stat-card {
-  display: flex;
-  align-items: center;
-  padding: 10px 0;
-}
-
-.stat-icon-wrap {
-  width: 56px;
-  height: 56px;
-  border-radius: 14px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 16px;
-  flex-shrink: 0;
-}
-
-.stat-icon-wrap i {
-  font-size: 28px;
-  color: #fff;
-}
-
-.stat-icon-wrap.total {
-  background: #1677FF;
-}
-
-.stat-icon-wrap.pending {
-  background: #FAAD14;
-}
-
-.stat-icon-wrap.settled {
-  background: #52C41A;
-}
-
-.stat-info {
-  flex: 1;
-}
-
-.stat-label {
-  font-size: 13px;
-  color: #909399;
-  margin-bottom: 6px;
-}
-
-.stat-value {
-  font-size: 24px;
-  font-weight: bold;
-  color: #303133;
-  margin-bottom: 4px;
-}
-
-.stat-value.pending {
-  color: #e6a23c;
-}
-
-.stat-value.settled {
-  color: #67c23a;
-}
-
-.stat-desc {
-  font-size: 12px;
-  color: #909399;
-}
 
 .status-cell {
   display: flex;

+ 4 - 79
cfc-web/src/views/teacher/TeacherOrders.vue

@@ -16,48 +16,16 @@
     <!-- 佣金概览卡片 -->
     <el-row :gutter="24" class="stats-row">
       <el-col :span="6">
-        <div class="stat-card accent-blue">
-          <div class="stat-icon-bg">
-            <i class="el-icon-document"></i>
-          </div>
-          <div class="stat-content">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.totalRevenue) }}</div>
-            <div class="stat-label">累计收入</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-document" label="累计收入" :value="formatPriceWithSymbol(stats.totalRevenue)" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card accent-green">
-          <div class="stat-icon-bg">
-            <i class="el-icon-circle-check"></i>
-          </div>
-          <div class="stat-content">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.completedRevenue) }}</div>
-            <div class="stat-label">已到账</div>
-          </div>
-        </div>
+        <StatCard color="success" icon="el-icon-circle-check" label="已到账" :value="formatPriceWithSymbol(stats.completedRevenue)" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card accent-orange">
-          <div class="stat-icon-bg">
-            <i class="el-icon-time"></i>
-          </div>
-          <div class="stat-content">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.pendingAmount) }}</div>
-            <div class="stat-label">待到账</div>
-          </div>
-        </div>
+        <StatCard color="warning" icon="el-icon-time" label="待到账" :value="formatPriceWithSymbol(stats.pendingAmount)" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card accent-purple">
-          <div class="stat-icon-bg">
-            <i class="el-icon-wallet"></i>
-          </div>
-          <div class="stat-content">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.actualCommission) }}</div>
-            <div class="stat-label">实际佣金</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-wallet" label="实际佣金" :value="formatPriceWithSymbol(stats.actualCommission)" />
       </el-col>
     </el-row>
 
@@ -412,49 +380,6 @@ export default {
   margin-bottom: 24px;
 }
 
-.stat-card {
-  display: flex;
-  align-items: center;
-  padding: 24px;
-  border-radius: 16px;
-  position: relative;
-  overflow: hidden;
-}
-
-.stat-card.accent-blue {
-  background: #1677FF;
-}
-
-.stat-card.accent-green {
-  background: #52C41A;
-}
-
-.stat-card.accent-orange {
-  background: #FAAD14;
-}
-
-.stat-card.accent-purple {
-  background: #1677FF;
-}
-
-.stat-icon-bg {
-  font-size: 48px;
-  color: rgba(255, 255, 255, 0.3);
-  margin-right: 16px;
-}
-
-.stat-value {
-  font-size: 28px;
-  font-weight: 700;
-  color: #FFFFFF;
-  line-height: 1.2;
-}
-
-.stat-label {
-  font-size: 14px;
-  color: rgba(255, 255, 255, 0.85);
-  margin-top: 4px;
-}
 
 /* 佣金说明 */
 .commission-info-card {

+ 4 - 84
cfc-web/src/views/teacher/TeacherPackages.vue

@@ -17,48 +17,16 @@
     <!-- 统计卡片 -->
     <el-row :gutter="24" class="stats-row">
       <el-col :span="6">
-        <div class="stat-card">
-          <div class="stat-icon blue">
-            <i class="el-icon-box"></i>
-          </div>
-          <div class="stat-info">
-            <div class="stat-value">{{ stats.totalPackages }}</div>
-            <div class="stat-label">在售任务模板</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-box" label="在售任务模板" :value="stats.totalPackages" :thousand="true" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card">
-          <div class="stat-icon green">
-            <i class="el-icon-shopping-cart-full"></i>
-          </div>
-          <div class="stat-info">
-            <div class="stat-value">{{ stats.totalSales }}</div>
-            <div class="stat-label">总销量</div>
-          </div>
-        </div>
+        <StatCard color="success" icon="el-icon-shopping-cart-full" label="总销量" :value="stats.totalSales" :thousand="true" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card">
-          <div class="stat-icon orange">
-            <i class="el-icon-price-tag"></i>
-          </div>
-          <div class="stat-info">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.avgPrice) }}</div>
-            <div class="stat-label">平均价格</div>
-          </div>
-        </div>
+        <StatCard color="warning" icon="el-icon-price-tag" label="平均价格" :value="formatPriceWithSymbol(stats.avgPrice)" />
       </el-col>
       <el-col :span="6">
-        <div class="stat-card">
-          <div class="stat-icon purple">
-            <i class="el-icon-wallet"></i>
-          </div>
-          <div class="stat-info">
-            <div class="stat-value">{{ formatPriceWithSymbol(stats.totalRevenue) }}</div>
-            <div class="stat-label">任务模板收入</div>
-          </div>
-        </div>
+        <StatCard color="primary" icon="el-icon-wallet" label="任务模板收入" :value="formatPriceWithSymbol(stats.totalRevenue)" />
       </el-col>
     </el-row>
 
@@ -434,54 +402,6 @@ export default {
   margin-bottom: 24px;
 }
 
-.stat-card {
-  display: flex;
-  align-items: center;
-  padding: 20px 24px;
-  background: #FFFFFF;
-  border-radius: 16px;
-  box-shadow: 0 2px 12px rgba(59, 130, 246, 0.08);
-}
-
-.stat-icon {
-  width: 52px;
-  height: 52px;
-  border-radius: 14px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 16px;
-  font-size: 22px;
-  color: #FFFFFF;
-}
-
-.stat-icon.blue {
-  background: #1677FF;
-}
-
-.stat-icon.green {
-  background: #52C41A;
-}
-
-.stat-icon.orange {
-  background: #FAAD14;
-}
-
-.stat-icon.purple {
-  background: #1677FF;
-}
-
-.stat-value {
-  font-size: 28px;
-  font-weight: 700;
-  color: #1E293B;
-}
-
-.stat-label {
-  font-size: 14px;
-  color: #64748B;
-  margin-top: 2px;
-}
 
 /* 表格卡片 */
 .table-card {