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

style(admin): B-29 铺开 StatusTag/PageHeader 至 21 页并删死 CSS

liaoxg пре 3 недеља
родитељ
комит
6aa068a32e

+ 0 - 12
cfc-web/src/views/admin/ButlerAssignments.vue

@@ -113,15 +113,3 @@ export default {
   }
 }
 </script>
-
-<style scoped>
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: var(--adm-primary);
-}
-</style>

+ 3 - 7
cfc-web/src/views/admin/ChallengeScoreConfig.vue

@@ -1,15 +1,12 @@
 <template>
   <div class="challenge-score-config admin-page">
-    <div class="header">
-      <h2>挑战评分配置</h2>
-      <div class="header-tip">家庭挑战 发起/同意/拒绝 的方向性关系评分与能量增减(可正可负)</div>
-    </div>
+    <PageHeader title="挑战评分配置" subtitle="家庭挑战 发起/同意/拒绝 的方向性关系评分与能量增减(可正可负)" />
 
         <div class="adm-table-wrap">
 <el-table :data="matrix" v-loading="loading" border stripe height="100%">
       <el-table-column label="动作" width="120">
         <template slot-scope="{ row }">
-          <el-tag size="mini" :type="row.action === 'reject' ? 'danger' : 'success'">{{ actionLabel(row.action) }}</el-tag>
+          <StatusTag size="mini" :type="row.action === 'reject' ? 'danger' : 'success'" :text="actionLabel(row.action)" />
         </template>
       </el-table-column>
       <el-table-column label="能量(行维度)" width="140">
@@ -110,6 +107,5 @@ export default {
 </script>
 
 <style scoped>
-.header-tip { color: #909399; font-size: 13px; margin-top: 4px; }
-.footer-tip { margin-top: 12px; color: #909399; font-size: 12px; line-height: 1.6; }
+.footer-tip { margin-top: 12px; color: var(--adm-text-45); font-size: 12px; line-height: 1.6; }
 </style>

+ 6 - 28
cfc-web/src/views/admin/Foods.vue

@@ -62,9 +62,7 @@
         </el-table-column>
         <el-table-column prop="category" label="分类" width="120" align="center" :class-name="sortClass('category')">
           <template slot-scope="{ row }">
-            <el-tag :type="categoryTagType(row.category)" size="mini" effect="plain">
-              {{ row.category }}
-            </el-tag>
+            <StatusTag size="mini" :type="categoryTagType(row.category) || 'primary'" effect="plain" :text="row.category" />
           </template>
           <template slot="header">
             <span class="sort-header" @click.stop="onSortClick('category',$event)" @dblclick.stop="onSortToggle('category')">分类<span v-if="sortIndex('category') !== null" class="sort-index" :class="sortClass('category') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('category') }}</span>{{ sortIcon('category') }}</span>
@@ -134,9 +132,7 @@
         </el-table-column>
         <el-table-column prop="status" label="状态" width="80" align="center" :class-name="sortClass('status')">
           <template slot-scope="{ row }">
-            <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="mini" effect="dark">
-              {{ row.status === 'active' ? '启用' : '停用' }}
-            </el-tag>
+            <StatusTag size="mini" :type="row.status === 'active' ? 'success' : 'info'" effect="dark" :text="row.status === 'active' ? '启用' : '停用'" />
           </template>
           <template slot="header">
             <span class="sort-header" @click.stop="onSortClick('status',$event)" @dblclick.stop="onSortToggle('status')">状态<span v-if="sortIndex('status') !== null" class="sort-index" :class="sortClass('status') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('status') }}</span>{{ sortIcon('status') }}</span>
@@ -151,7 +147,7 @@
               </el-button>
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item command="detail" icon="el-icon-view">查看详情</el-dropdown-item>
-                <el-dropdown-item command="delete" icon="el-icon-delete" divided style="color: #f56c6c;">删除</el-dropdown-item>
+                <el-dropdown-item command="delete" icon="el-icon-delete" divided style="color: var(--adm-error);">删除</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
           </template>
@@ -267,7 +263,7 @@
         <el-descriptions-item label="名称" :span="2">{{ detailData.name }}</el-descriptions-item>
         <el-descriptions-item label="分类">{{ detailData.category }}</el-descriptions-item>
         <el-descriptions-item label="状态">
-          <el-tag :type="detailData.status === 'active' ? 'success' : 'info'" size="mini">{{ detailData.status === 'active' ? '启用' : '停用' }}</el-tag>
+          <StatusTag size="mini" :type="detailData.status === 'active' ? 'success' : 'info'" :text="detailData.status === 'active' ? '启用' : '停用'" />
         </el-descriptions-item>
         <el-descriptions-item label="热量(kcal)">{{ detailData.calories || '-' }}</el-descriptions-item>
         <el-descriptions-item label="能量(kJ)">{{ detailData.energyKj || '-' }}</el-descriptions-item>
@@ -281,7 +277,7 @@
         <el-descriptions-item label="排序">{{ detailData.sortOrder != null ? detailData.sortOrder : '-' }}</el-descriptions-item>
         <el-descriptions-item label="应季月份" :span="2">
           <span v-if="detailData.months && detailData.months.length">{{ detailData.months.map(function(m) { return m + '月' }).join('、') }}</span>
-          <span v-else style="color:#999">未设置</span>
+          <span v-else style="color:var(--adm-text-45)">未设置</span>
         </el-descriptions-item>
       </el-descriptions>
     </el-dialog>
@@ -526,7 +522,7 @@ export default {
 
 .num-unit {
   font-size: 11px;
-  color: #999;
+  color: var(--adm-text-45);
   margin-left: 2px;
 }
 
@@ -538,22 +534,4 @@ export default {
 .el-descriptions {
   margin-top: 8px;
 }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-asc ::v-deep .el-table__header-wrapper th .cell,
-.sort-desc ::v-deep .el-table__header-wrapper th .cell {
-  color: #409eff;
-  font-weight: 600;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-}
 </style>

+ 1 - 15
cfc-web/src/views/admin/GrowthTaskManagement.vue

@@ -47,7 +47,7 @@
             <div v-if="row.rewardItems && row.rewardItems.length">
               <StatusTag size="mini" v-for="(ri, i) in row.rewardItems" :key="i" :text="ri.type + ':' + ri.value" style="margin:1px" />
             </div>
-            <span v-else style="color:#999">—</span>
+            <span v-else style="color:var(--adm-text-45)">—</span>
           </template>
         </el-table-column>
         <el-table-column label="状态" width="80">
@@ -366,18 +366,4 @@ export default {
 
 <style scoped>
 .growth-task { padding: 20px; }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: var(--adm-primary);
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
 </style>

+ 2 - 11
cfc-web/src/views/admin/HealthPlanManage.vue

@@ -257,7 +257,7 @@ export default {
       return map[s] || s || '-'
     },
     renderPlanContent(content) {
-      if (!content) return '<span style="color:#999">暂无内容</span>'
+      if (!content) return '<span style="color:var(--adm-text-45)">暂无内容</span>'
       return content
         .replace(/&/g, '&amp;')
         .replace(/</g, '&lt;')
@@ -271,7 +271,7 @@ export default {
 <style scoped>
 .health-plan-manage { padding: 20px; }
 .plan-content {
-  background: #f5f7fa;
+  background: var(--adm-bg-header);
   border-radius: 4px;
   padding: 16px;
   min-height: 80px;
@@ -279,13 +279,4 @@ export default {
   white-space: pre-wrap;
   font-size: 14px;
 }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: var(--adm-primary);
-}
 </style>

+ 3 - 12
cfc-web/src/views/admin/HealthReportReassign.vue

@@ -1,9 +1,8 @@
 <template>
   <div class="reassign-container">
-    <div class="page-header">
-      <span>报告归属管理</span>
+    <PageHeader title="报告归属管理">
       <el-button type="primary" size="small" icon="el-icon-refresh" @click="loadData">刷新</el-button>
-    </div>
+    </PageHeader>
 
     <!-- 家庭选择 -->
     <el-form :inline="true" class="filter-bar">
@@ -19,7 +18,7 @@
       <el-table-column prop="id" label="报告ID" width="100" />
       <el-table-column prop="reportType" label="报告类型" width="120">
         <template slot-scope="{ row }">
-          <el-tag size="small">{{ row.reportType === 'gut_flora' ? '菌群检测' : row.reportType === 'physical_exam' ? '体检报告' : row.reportType }}</el-tag>
+          <StatusTag size="small" type="primary" :text="row.reportType === 'gut_flora' ? '菌群检测' : row.reportType === 'physical_exam' ? '体检报告' : row.reportType" />
         </template>
       </el-table-column>
       <el-table-column label="报告对象" width="120">
@@ -161,14 +160,6 @@ export default {
 .reassign-container {
   padding: 16px;
 }
-.page-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  font-size: 16px;
-  font-weight: 600;
-  margin-bottom: 16px;
-}
 .filter-bar {
   margin-bottom: 12px;
 }

+ 9 - 19
cfc-web/src/views/admin/HomeBannerManage.vue

@@ -29,7 +29,7 @@
           <el-table-column prop="id" label="ID" width="60" />
           <el-table-column label="类型" width="80">
             <template slot-scope="{ row }">
-              <el-tag size="mini" :type="typeTag(row.bannerType)">{{ typeLabel(row.bannerType) }}</el-tag>
+              <StatusTag size="mini" :type="typeTag(row.bannerType) || 'primary'" :text="typeLabel(row.bannerType)" />
             </template>
           </el-table-column>
           <el-table-column label="标题" min-width="120" show-overflow-tooltip>
@@ -39,24 +39,24 @@
           <el-table-column label="关联内容" width="160">
             <template slot-scope="{ row }">
               <div v-if="row.bannerType === 'activity' && row.refId">
-                <el-tag size="mini" type="primary">活动 #{{ row.refId }}</el-tag>
+                <StatusTag size="mini" type="primary" :text="'活动 #' + row.refId" />
               </div>
               <div v-else-if="row.bannerType === 'product' && row.refId">
-                <el-tag size="mini" type="info">商品 #{{ row.refId }}</el-tag>
+                <StatusTag size="mini" type="info" :text="'商品 #' + row.refId" />
               </div>
               <div v-else-if="row.bannerType === 'article' && row.refId">
-                <el-tag size="mini" type="success">文章 #{{ row.refId }}</el-tag>
+                <StatusTag size="mini" type="success" :text="'文章 #' + row.refId" />
               </div>
               <div v-else-if="row.bannerType === 'link' && row.linkUrl">
-                <el-tag size="mini" type="info">{{ row.linkUrl }}</el-tag>
+                <StatusTag size="mini" type="info" :text="row.linkUrl" />
               </div>
-              <div v-else style="color:#bbb">-</div>
+              <div v-else style="color:var(--adm-text-25)">-</div>
             </template>
           </el-table-column>
           <el-table-column label="封面" width="80">
             <template slot-scope="{ row }">
               <img v-if="row.coverImage" :src="row.coverImage" style="width:50px;height:35px;object-fit:cover;border-radius:4px;" />
-              <span v-else style="color:#999">无</span>
+              <span v-else style="color:var(--adm-text-45)">无</span>
             </template>
           </el-table-column>
           <el-table-column label="排序" width="80">
@@ -67,7 +67,7 @@
           <el-table-column label="投放时间" width="180">
             <template slot-scope="{ row }">
               <span v-if="row.startTime || row.endTime">{{ formatDate(row.startTime) }} ~ {{ formatDate(row.endTime) }}</span>
-              <span v-else style="color:#bbb">不限</span>
+              <span v-else style="color:var(--adm-text-25)">不限</span>
             </template>
           </el-table-column>
           <el-table-column label="状态" width="80">
@@ -190,7 +190,7 @@
             <el-image :src="form.coverImage" style="width:200px;height:120px;" fit="cover" />
           </div>
           <el-button v-if="form.coverImage" size="mini" type="text" style="margin-left:10px;" @click="form.coverImage = ''">清除</el-button>
-          <div style="margin-top:4px;font-size:12px;color:#999;">建议尺寸 750×320rpx(约 2.35:1),单张不超过 5MB</div>
+          <div style="margin-top:4px;font-size:12px;color:var(--adm-text-45);">建议尺寸 750×320rpx(约 2.35:1),单张不超过 5MB</div>
         </el-form-item>
 
         <el-form-item label="排序">
@@ -636,16 +636,6 @@ export default {
 </script>
 
 <style scoped>
-.admin-page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-.admin-page-title {
-  font-size: 18px;
-  font-weight: 600;
-  color: #303133;
-}
 .filter-bar {
   display: flex;
   align-items: center;

+ 2 - 26
cfc-web/src/views/admin/NoticeManage.vue

@@ -12,7 +12,7 @@
           <el-table-column prop="id" label="ID" width="70" />
           <el-table-column label="类型" width="90">
             <template slot-scope="{ row }">
-              <el-tag size="mini" :type="typeTagType(row.type)">{{ typeLabel(row.type) }}</el-tag>
+              <StatusTag size="mini" :type="typeTagType(row.type) || 'primary'" :text="typeLabel(row.type)" />
             </template>
           </el-table-column>
           <el-table-column label="标题" min-width="200">
@@ -23,9 +23,7 @@
           </el-table-column>
           <el-table-column label="状态" width="90">
             <template slot-scope="{ row }">
-              <el-tag size="mini" :type="row.status === 'active' ? 'success' : 'info'">
-                {{ row.status === 'active' ? '已发布' : '草稿' }}
-              </el-tag>
+              <StatusTag size="mini" :type="row.status === 'active' ? 'success' : 'info'" :text="row.status === 'active' ? '已发布' : '草稿'" />
             </template>
           </el-table-column>
           <el-table-column label="创建时间" width="160">
@@ -173,25 +171,3 @@ export default {
   }
 }
 </script>
-
-<style scoped>
-.admin-page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
-</style>

+ 3 - 21
cfc-web/src/views/admin/NutritionProducts.vue

@@ -406,15 +406,6 @@ export default {
 .nutrition-products {
   padding: 16px;
 }
-.admin-page-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-.admin-page-title {
-  font-size: 16px;
-  font-weight: 600;
-}
 .header-actions {
   display: flex;
   align-items: center;
@@ -426,24 +417,15 @@ export default {
 }
 .price-val {
   font-weight: 600;
-  color: #e74c3c;
+  color: var(--adm-error-text);
 }
 .price-orig {
   margin-left: 6px;
-  color: #999;
+  color: var(--adm-text-45);
   text-decoration: line-through;
   font-size: 12px;
 }
 .no-data {
-  color: #999;
-}
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
+  color: var(--adm-text-45);
 }
 </style>

+ 9 - 33
cfc-web/src/views/admin/OrderManage.vue

@@ -1,7 +1,6 @@
 <template>
   <div class="order-manage admin-page">
-    <div class="header">
-      <h2 class="admin-page-title">订单管理</h2>
+    <PageHeader title="订单管理">
       <div class="filters filter-bar">
         <el-input v-model="keyword" placeholder="搜索商品/订单号..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" style="width:220px;" />
         <el-date-picker
@@ -28,7 +27,7 @@
         </el-select>
         <el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
       </div>
-    </div>
+    </PageHeader>
 
     <div class="adm-table-wrap">
       <el-table height="100%" :data="list" v-loading="loading" border stripe>
@@ -48,20 +47,20 @@
       </el-table-column>
 
       <el-table-column prop="quantity" label="数量" width="60" align="center" />
-      <el-table-column label="金额" width="100">
+      <el-table-column label="金额" width="100" align="right">
         <template slot-scope="{ row }">
-          {{ formatPrice(row.totalAmount) }}
+          <span class="adm-num">{{ formatPrice(row.totalAmount) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="状态" width="100">
         <template slot-scope="{ row }">
-          <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
+          <StatusTag :type="statusType(row.status)" :text="statusLabel(row.status)" />
         </template>
       </el-table-column>
       <el-table-column label="履约状态" width="120">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.fulfillStatus" :type="fulfillType(row.fulfillStatus)" size="mini">{{ fulfillLabel(row.fulfillStatus) }}</el-tag>
-          <span v-else style="color:#999;">-</span>
+          <StatusTag v-if="row.fulfillStatus" size="mini" :type="fulfillType(row.fulfillStatus)" :text="fulfillLabel(row.fulfillStatus)" />
+          <span v-else style="color:var(--adm-text-45);">-</span>
         </template>
       </el-table-column>
       <el-table-column prop="paymentMethod" label="支付方式" width="100">
@@ -117,7 +116,7 @@
           <el-descriptions-item label="总金额">{{ formatPrice(detail.totalAmount) }}</el-descriptions-item>
           <el-descriptions-item label="优惠金额">{{ detail.discountAmount ? formatPrice(detail.discountAmount) : '-' }}</el-descriptions-item>
           <el-descriptions-item label="订单状态">
-            <el-tag :type="statusType(detail.status)">{{ statusLabel(detail.status) }}</el-tag>
+            <StatusTag :type="statusType(detail.status)" :text="statusLabel(detail.status)" />
           </el-descriptions-item>
           <el-descriptions-item label="支付方式">{{ payMethodLabel(detail.paymentMethod) }}</el-descriptions-item>
           <el-descriptions-item label="支付时间">{{ detail.paidAt ? formatTime(detail.paidAt) : '-' }}</el-descriptions-item>
@@ -127,7 +126,7 @@
             {{ deliveryMethodLabel(detail.deliveryMethod) }}
           </el-descriptions-item>
           <el-descriptions-item label="履约状态" v-if="detail.fulfillStatus">
-            <el-tag :type="fulfillType(detail.fulfillStatus)" size="mini">{{ fulfillLabel(detail.fulfillStatus) }}</el-tag>
+            <StatusTag size="mini" :type="fulfillType(detail.fulfillStatus)" :text="fulfillLabel(detail.fulfillStatus)" />
           </el-descriptions-item>
           <el-descriptions-item label="收货人" v-if="getJsonField(detail.addressSnapshot, 'receiverName') !== '-'">{{ getJsonField(detail.addressSnapshot, 'receiverName') }}</el-descriptions-item>
           <el-descriptions-item label="联系电话" v-if="getJsonField(detail.addressSnapshot, 'phone') !== '-'">{{ getJsonField(detail.addressSnapshot, 'phone') }}</el-descriptions-item>
@@ -422,32 +421,9 @@ export default {
 
 <style scoped>
 .order-manage { padding: 20px; }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-}
-.header h2 { margin: 0; }
 .filters {
   display: flex;
   gap: 10px;
   align-items: center;
 }
-
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
 </style>

+ 9 - 21
cfc-web/src/views/admin/PendingRefund.vue

@@ -1,7 +1,6 @@
 <template>
   <div class="pending-refund admin-page">
-    <div class="header admin-page-header">
-      <h2 class="admin-page-title">待退款列表</h2>
+    <PageHeader title="待退款列表">
       <div class="flex items-center gap-sm">
         <el-select v-model="statusFilter" placeholder="退款状态" @change="loadList">
           <el-option label="全部状态" value="" />
@@ -16,7 +15,7 @@
           <el-option label="商品退款" value="product" />
         </el-select>
       </div>
-    </div>
+    </PageHeader>
 
     <div v-if="summary.totalPendingAmount > 0" class="summary-bar">
       <el-alert
@@ -36,9 +35,7 @@
         </el-table-column>
         <el-table-column label="类型" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="row.orderType === 'product' ? 'primary' : 'warning'" size="small">
-              {{ row.orderType === 'product' ? '商品退款' : '提现退款' }}
-            </el-tag>
+            <StatusTag size="small" :type="row.orderType === 'product' ? 'primary' : 'warning'" :text="row.orderType === 'product' ? '商品退款' : '提现退款'" />
           </template>
         </el-table-column>
         <el-table-column label="订单号" width="180">
@@ -56,19 +53,19 @@
             {{ row.userName || '用户' + row.userId }}
           </template>
         </el-table-column>
-        <el-table-column label="退款金额" width="120">
+        <el-table-column label="退款金额" width="120" align="right">
           <template slot-scope="{ row }">
-            <span class="amount">{{ formatPriceWithSymbol(row.amount) }}</span>
+            <span class="amount adm-num">{{ formatPriceWithSymbol(row.amount) }}</span>
           </template>
         </el-table-column>
-        <el-table-column label="实退金额" width="120">
+        <el-table-column label="实退金额" width="120" align="right">
           <template slot-scope="{ row }">
-            <span class="amount">{{ row.refundedAmount ? formatPriceWithSymbol(row.refundedAmount) : '-' }}</span>
+            <span class="amount adm-num">{{ row.refundedAmount ? formatPriceWithSymbol(row.refundedAmount) : '-' }}</span>
           </template>
         </el-table-column>
         <el-table-column label="状态" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
+            <StatusTag :type="statusType(row.status)" :text="statusLabel(row.status)" />
           </template>
         </el-table-column>
         <el-table-column label="尝试次数" width="80">
@@ -249,15 +246,6 @@ async loadList() {
 
 <style scoped>
 .summary-bar {
-  margin-bottom: 16px;
-}
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
+  margin-bottom: var(--spacing-base);
 }
 </style>

+ 4 - 22
cfc-web/src/views/admin/PeriodicServiceConfig.vue

@@ -1,9 +1,8 @@
 <template>
   <div class="periodic-service-config">
-    <div class="header">
-      <h2>周期性服务续费配置</h2>
+    <PageHeader title="周期性服务续费配置">
       <el-button type="primary" icon="el-icon-plus" @click="openDialog()">新增配置</el-button>
-    </div>
+    </PageHeader>
 
         <div class="adm-table-wrap">
 <el-table :data="list" v-loading="loading" border stripe style="width: 100%" height="100%">
@@ -34,9 +33,7 @@
       </el-table-column>
       <el-table-column label="自动续费" width="100">
         <template slot-scope="scope">
-          <el-tag :type="scope.row.autoRenew === 1 ? 'success' : 'info'" size="small">
-            {{ scope.row.autoRenew === 1 ? '支持' : '不支持' }}
-          </el-tag>
+          <StatusTag size="small" :type="scope.row.autoRenew === 1 ? 'success' : 'info'" :text="scope.row.autoRenew === 1 ? '支持' : '不支持'" />
         </template>
       </el-table-column>
       <el-table-column label="状态" width="80">
@@ -48,7 +45,7 @@
       <el-table-column label="操作" width="160" fixed="right">
         <template slot-scope="scope">
           <el-button type="text" size="small" @click="openDialog(scope.row)">编辑</el-button>
-          <el-button type="text" size="small" style="color: #f56c6c"
+          <el-button type="text" size="small" style="color: var(--adm-error)"
             @click="handleDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
@@ -219,19 +216,4 @@ export default {
 .periodic-service-config {
   padding: 20px;
 }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-}
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
 </style>

+ 5 - 16
cfc-web/src/views/admin/PlanManagement.vue

@@ -1,7 +1,6 @@
 <template>
   <div class="plan-management">
-    <div class="header">
-      <h2>方案管理</h2>
+    <PageHeader title="方案管理">
       <div class="filters">
         <el-select v-model="statusFilter" placeholder="状态筛选" clearable @change="loadPlans" style="width:160px">
           <el-option label="全部" value="" />
@@ -14,7 +13,7 @@
         <el-input v-model="familySearch" placeholder="搜索家庭ID" style="width:180px;margin-left:10px" @keyup.enter="loadPlans" />
         <el-button type="primary" @click="loadPlans" style="margin-left:10px">查询</el-button>
       </div>
-    </div>
+    </PageHeader>
 
         <div class="adm-table-wrap">
 <el-table :data="plans" border stripe style="width:100%" height="100%">
@@ -40,7 +39,7 @@
       </el-table-column>
       <el-table-column label="状态" width="100">
         <template slot-scope="{ row }">
-          <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
+          <StatusTag :type="statusType(row.status)" :text="statusLabel(row.status)" />
         </template>
       </el-table-column>
       <el-table-column label="进度" width="120">
@@ -76,7 +75,7 @@
         <el-form-item label="孩子ID">{{ currentPlan.childId }}</el-form-item>
         <el-form-item label="方案名称">{{ currentPlan.name }}</el-form-item>
         <el-form-item label="状态">
-          <el-tag :type="statusType(currentPlan.status)">{{ statusLabel(currentPlan.status) }}</el-tag>
+          <StatusTag :type="statusType(currentPlan.status)" :text="statusLabel(currentPlan.status)" />
         </el-form-item>
         <el-form-item label="周期">{{ currentPlan.totalDays }} 天</el-form-item>
         <el-form-item label="进度">{{ currentPlan.completedDays || 0 }} / {{ currentPlan.totalDays || '-' }} 天</el-form-item>
@@ -85,7 +84,7 @@
         <el-form-item label="审核时间">{{ currentPlan.reviewedAt || '-' }}</el-form-item>
         <el-form-item label="激活时间">{{ currentPlan.activatedAt || '-' }}</el-form-item>
         <el-form-item label="备注">
-          <pre style="white-space:pre-wrap;background:#f5f5f5;padding:12px;border-radius:6px;">{{ currentPlan.remark }}</pre>
+          <pre style="white-space:pre-wrap;background:var(--adm-bg-header);padding:12px;border-radius:6px;">{{ currentPlan.remark }}</pre>
         </el-form-item>
       </el-form>
     </el-dialog>
@@ -153,15 +152,5 @@ export default {
 </script>
 
 <style scoped>
-.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
 .filters { display: flex; align-items: center; }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
 </style>

+ 6 - 24
cfc-web/src/views/admin/PointsLog.vue

@@ -39,14 +39,12 @@
         </el-table-column>
         <el-table-column label="分类" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="row.category === 'task' ? 'success' : 'warning'" size="mini">
-              {{ row.category === 'task' ? '任务积分' : '系统积分' }}
-            </el-tag>
+            <StatusTag size="mini" :type="row.category === 'task' ? 'success' : 'warning'" :text="row.category === 'task' ? '任务积分' : '系统积分'" />
           </template>
         </el-table-column>
         <el-table-column label="变动" width="100">
           <template slot-scope="{ row }">
-            <span :style="{ color: row.amount > 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
+            <span :style="{ color: row.amount > 0 ? 'var(--adm-success)' : 'var(--adm-error-text)', fontWeight: 'bold' }">
               {{ row.amount > 0 ? '+' : '' }}{{ row.amount }}
             </span>
           </template>
@@ -58,10 +56,10 @@
         </el-table-column>
         <el-table-column prop="expireAt" label="过期时间" width="160">
           <template slot-scope="{ row }">
-            <span v-if="row.expireAt" :style="{ color: row.expired ? '#999' : '#E6A23C' }">
+            <span v-if="row.expireAt" :style="{ color: row.expired ? 'var(--adm-text-45)' : 'var(--adm-warning-text)' }">
               {{ formatTime(row.expireAt) }}
             </span>
-            <span v-else style="color:#999">永久有效</span>
+            <span v-else style="color:var(--adm-text-45)">永久有效</span>
           </template>
           <template slot="header">
             <span class="sort-header" @click.stop="onSortClick('expireAt', $event)">过期时间<span v-if="sortIndex('expireAt') !== null" class="sort-index" :class="sortClass('expireAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('expireAt') }}</span>{{ sortIcon('expireAt') }}</span>
@@ -104,12 +102,10 @@
           <el-descriptions-item label="孩子ID">{{ currentRow.childId }}</el-descriptions-item>
           <el-descriptions-item label="类型">{{ typeLabel(currentRow.type) }}</el-descriptions-item>
           <el-descriptions-item label="分类">
-            <el-tag :type="currentRow.category === 'task' ? 'success' : 'warning'" size="mini">
-              {{ currentRow.category === 'task' ? '任务积分' : '系统积分' }}
-            </el-tag>
+            <StatusTag size="mini" :type="currentRow.category === 'task' ? 'success' : 'warning'" :text="currentRow.category === 'task' ? '任务积分' : '系统积分'" />
           </el-descriptions-item>
           <el-descriptions-item label="变动">
-            <span :style="{ color: currentRow.amount > 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
+            <span :style="{ color: currentRow.amount > 0 ? 'var(--adm-success)' : 'var(--adm-error-text)', fontWeight: 'bold' }">
               {{ currentRow.amount > 0 ? '+' : '' }}{{ currentRow.amount }}
             </span>
           </el-descriptions-item>
@@ -224,18 +220,4 @@ export default {
 <style scoped>
 .points-log { padding: 20px; }
 .detail-content { padding: 10px 0; }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
 </style>

+ 1 - 9
cfc-web/src/views/admin/PromotionManagement.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="promotion-management admin-page">
+    <PageHeader title="推广管理" />
     <el-card>
       <el-tabs v-model="activeTab" @tab-click="handleTabChange">
         <el-tab-pane label="邀请里程碑" name="milestone">
@@ -276,13 +277,4 @@ export default {
 .promotion-management {
   padding: 20px;
 }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
 </style>

+ 3 - 17
cfc-web/src/views/admin/PurchaseManagement.vue

@@ -58,8 +58,8 @@
             <span class="sort-header" @click.stop="onSortClick('familyId', $event)">家庭ID<span v-if="sortIndex('familyId') !== null" class="sort-index" :class="sortClass('familyId') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('familyId') }}</span>{{ sortIcon('familyId') }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="amount" label="金额(分)" width="100">
-          <template slot-scope="{ row }">{{ row.amount / 100 }}元</template>
+        <el-table-column prop="amount" label="金额(分)" width="100" align="right">
+          <template slot-scope="{ row }"><span class="adm-num">{{ row.amount / 100 }}元</span></template>
           <template slot="header">
             <span class="sort-header" @click.stop="onSortClick('amount', $event)">金额<span v-if="sortIndex('amount') !== null" class="sort-index" :class="sortClass('amount') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('amount') }}</span>{{ sortIcon('amount') }}</span>
           </template>
@@ -125,7 +125,7 @@
         <el-descriptions-item label="家庭ID">{{ currentOrder.familyId }}</el-descriptions-item>
         <el-descriptions-item label="金额">{{ currentOrder.amount / 100 }}元</el-descriptions-item>
         <el-descriptions-item label="状态">
-          <el-tag :type="statusType(currentOrder.status)" size="small">{{ statusText(currentOrder.status) }}</el-tag>
+          <StatusTag :type="statusType(currentOrder.status)" size="small" :text="statusText(currentOrder.status)" />
         </el-descriptions-item>
         <el-descriptions-item label="支付方式">{{ currentOrder.paymentMethod || '-' }}</el-descriptions-item>
         <el-descriptions-item label="开始时间">{{ formatTime(currentOrder.startDate) }}</el-descriptions-item>
@@ -227,18 +227,4 @@ export default {
 
 <style scoped>
 .admin-page { padding: 16px; }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: var(--adm-primary);
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
 </style>

+ 3 - 16
cfc-web/src/views/admin/Recipes.vue

@@ -52,6 +52,9 @@
           </template>
         </el-table-column>
         <el-table-column prop="status" label="状态" width="80">
+          <template slot-scope="{ row }">
+            <StatusTag size="mini" :type="row.status === 'active' ? 'success' : 'info'" :text="row.status === 'active' ? '启用' : '停用'" />
+          </template>
           <template slot="header">
             <span class="sort-header" @click.stop="onSortClick('status', $event)">状态<span v-if="sortIndex('status') !== null" class="sort-index" :class="sortClass('status') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('status') }}</span>{{ sortIcon('status') }}</span>
           </template>
@@ -263,19 +266,3 @@ export default {
   }
 }
 </script>
-<style scoped>
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
-</style>

+ 5 - 13
cfc-web/src/views/admin/ReportManagement.vue

@@ -1,5 +1,6 @@
 <template>
-  <div class="report-management">
+  <div class="report-management admin-page">
+    <PageHeader title="报告管理" />
     <el-card>
       <div class="filter-bar">
         <el-select v-model="query.type" placeholder="报告类型" clearable style="width:140px">
@@ -28,7 +29,7 @@
           </el-table-column>
           <el-table-column label="报告类型" width="100">
             <template slot-scope="scope">
-              <el-tag size="small" :type="getTypeTag(scope.row.reportType)">{{ typeLabel(scope.row.reportType) }}</el-tag>
+              <StatusTag size="small" :type="getTypeTag(scope.row.reportType)" :text="typeLabel(scope.row.reportType)" />
             </template>
           </el-table-column>
           <el-table-column prop="title" label="标题" min-width="140" show-overflow-tooltip>
@@ -50,7 +51,7 @@
           </el-table-column>
           <el-table-column label="综合评分" width="100">
             <template slot-scope="scope">
-              <el-tag :type="scoreType(scope.row.overallScore)" size="small">{{ scope.row.overallScore == null ? '-' : scope.row.overallScore }}</el-tag>
+              <StatusTag size="small" :type="scoreType(scope.row.overallScore)" :text="scope.row.overallScore == null ? '-' : String(scope.row.overallScore)" />
             </template>
             <template slot="header">
               <span class="sort-header" @click.stop="onSortClick('overallScore', $event)">综合评分{{ sortIcon('overallScore') }}</span>
@@ -58,7 +59,7 @@
           </el-table-column>
           <el-table-column label="状态" width="100">
             <template slot-scope="scope">
-              <el-tag size="small">{{ scope.row.status || '已确认' }}</el-tag>
+              <StatusTag size="small" type="primary" :text="scope.row.status || '已确认'" />
             </template>
             <template slot="header">
               <span class="sort-header" @click.stop="onSortClick('status', $event)">状态{{ sortIcon('status') }}</span>
@@ -248,13 +249,4 @@ export default {
   gap: 12px;
   flex-wrap: wrap;
 }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
 </style>

+ 1 - 15
cfc-web/src/views/admin/SeasonalFoods.vue

@@ -34,9 +34,7 @@
         </el-table-column>
         <el-table-column label="推荐等级" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="row.peak >= 3 ? 'danger' : row.peak >= 2 ? 'warning' : 'info'" size="mini">
-              {{ row.peak }}
-            </el-tag>
+            <StatusTag size="mini" :type="row.peak >= 3 ? 'danger' : row.peak >= 2 ? 'warning' : 'info'" :text="String(row.peak)" />
           </template>
         </el-table-column>
         <el-table-column label="操作" width="200" fixed="right">
@@ -183,15 +181,3 @@ export default {
   }
 }
 </script>
-
-<style scoped>
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-</style>

+ 3 - 3
cfc-web/src/views/admin/SpecialPriceManage.vue

@@ -80,9 +80,9 @@
             <el-table-column label="时间窗口" width="230">
               <template slot-scope="{ row }">
                 <div class="pm-time-window">
-                  <el-tag size="mini" type="info">{{ formatTime(row.startTime) }}</el-tag>
+                  <StatusTag size="mini" type="info" :text="formatTime(row.startTime)" />
                   <span class="pm-time-window__sep">至</span>
-                  <el-tag size="mini" type="info">{{ formatTime(row.endTime) }}</el-tag>
+                  <StatusTag size="mini" type="info" :text="formatTime(row.endTime)" />
                 </div>
               </template>
             </el-table-column>
@@ -101,7 +101,7 @@
             </el-table-column>
             <el-table-column label="券开关" width="88">
               <template slot-scope="{ row }">
-                <el-tag :type="row.allowCoupon === 1 ? 'success' : 'danger'" size="mini">{{ row.allowCoupon === 1 ? '可用券' : '禁券' }}</el-tag>
+                <StatusTag size="mini" :type="row.allowCoupon === 1 ? 'success' : 'danger'" :text="row.allowCoupon === 1 ? '可用券' : '禁券'" />
               </template>
             </el-table-column>
             <el-table-column label="运行状态" width="96">

+ 8 - 35
cfc-web/src/views/admin/SubscriptionManagement.vue

@@ -1,7 +1,6 @@
 <template>
   <div class="subscription-management admin-page">
-    <div class="header">
-      <h2 class="admin-page-title">订阅管理</h2>
+    <PageHeader title="订阅管理">
       <div class="filters">
         <el-input v-model="keyword" placeholder="搜索家庭/用户..." prefix-icon="el-icon-search" style="width: 200px;" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
         <el-select v-model="statusFilter" placeholder="订阅状态" @change="loadList" style="width: 120px;">
@@ -17,7 +16,7 @@
         </el-select>
         <el-button type="primary" @click="loadList">查询</el-button>
       </div>
-    </div>
+    </PageHeader>
 
     <div class="adm-table-wrap">
       <el-table height="100%" :data="list" v-loading="loading" border stripe>
@@ -36,12 +35,12 @@
         </el-table-column>
         <el-table-column label="订阅等级" width="120">
           <template slot-scope="{ row }">
-            <el-tag :type="row.level === 'L1' ? 'success' : 'danger'">{{ levelLabel(row.level) }}</el-tag>
+            <StatusTag :type="row.level === 'L1' ? 'success' : 'danger'" :text="levelLabel(row.level)" />
           </template>
         </el-table-column>
         <el-table-column label="状态" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
+            <StatusTag :type="statusType(row.status)" :text="statusLabel(row.status)" />
           </template>
         </el-table-column>
         <el-table-column label="开始时间" width="160">
@@ -54,9 +53,9 @@
             {{ formatTime(row.expireTime) }}
           </template>
         </el-table-column>
-        <el-table-column label="支付金额" width="100">
+        <el-table-column label="支付金额" width="100" align="right">
           <template slot-scope="{ row }">
-            {{ formatPrice(row.amount) }}
+            <span class="adm-num">{{ formatPrice(row.amount) }}</span>
           </template>
         </el-table-column>
         <el-table-column label="创建时间" width="160">
@@ -102,10 +101,10 @@
         <el-descriptions-item label="订阅 ID">{{ detail.id }}</el-descriptions-item>
         <el-descriptions-item label="家庭名称">{{ detail.familyName || '-' }}</el-descriptions-item>
         <el-descriptions-item label="订阅等级">
-          <el-tag :type="detail.level === 'L1' ? 'success' : 'danger'">{{ levelLabel(detail.level) }}</el-tag>
+          <StatusTag :type="detail.level === 'L1' ? 'success' : 'danger'" :text="levelLabel(detail.level)" />
         </el-descriptions-item>
         <el-descriptions-item label="状态">
-          <el-tag :type="statusType(detail.status)">{{ statusLabel(detail.status) }}</el-tag>
+          <StatusTag :type="statusType(detail.status)" :text="statusLabel(detail.status)" />
         </el-descriptions-item>
         <el-descriptions-item label="开始时间">{{ formatTime(detail.startTime) }}</el-descriptions-item>
         <el-descriptions-item label="结束时间">{{ formatTime(detail.expireTime) }}</el-descriptions-item>
@@ -339,35 +338,9 @@ export default {
 .subscription-management {
   padding: 20px;
 }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-}
-.header h2 {
-  margin: 0;
-}
 .filters {
   display: flex;
   gap: 10px;
   align-items: center;
 }
-.sort-header {
-  cursor: pointer;
-  user-select: none;
-  font-weight: 500;
-  font-size: 12px;
-}
-.sort-header:hover {
-  color: #409eff;
-}
-.sort-tag {
-  margin-left: 8px;
-  cursor: pointer;
-  white-space: nowrap;
-}
-
-
 </style>