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

refactor(cfc-web): unify admin page styles with global CSS design tokens

- Add admin-tokens.css with global design tokens and standard CSS classes
- Import admin-tokens.css globally in main.js
- Refactor ~33 admin pages to use standard classes:
  - admin-page-header / admin-page-title / admin-page-actions for card headers
  - table-scroll-wrap(-sm/-lg) for table containers
  - pagination-wrap for pagination
  - filter-bar for search/filter bars
  - Remove inline width/height/float styles
- Update ActivityEdit, ProductEdit with proper header layout
- Fix ActivityReview, Assessment (syntax error fix)
- Remove duplicate scoped CSS for filter-bar, header patterns
Xiaogang Liao 2 месяцев назад
Родитель
Сommit
312725b35e
31 измененных файлов с 784 добавлено и 369 удалено
  1. 1 0
      cfc-web/src/main.js
  2. 435 0
      cfc-web/src/styles/admin-tokens.css
  3. 3 4
      cfc-web/src/views/GuideAudit.vue
  4. 3 3
      cfc-web/src/views/GuideFamilyTask.vue
  5. 7 8
      cfc-web/src/views/admin/Activities.vue
  6. 3 3
      cfc-web/src/views/admin/ActivityEdit.vue
  7. 4 2
      cfc-web/src/views/admin/ActivityRegistrationReview.vue
  8. 9 7
      cfc-web/src/views/admin/ActivityReview.vue
  9. 8 9
      cfc-web/src/views/admin/ArticleCategory.vue
  10. 43 56
      cfc-web/src/views/admin/ArticleManage.vue
  11. 12 8
      cfc-web/src/views/admin/Assessment.vue
  12. 9 7
      cfc-web/src/views/admin/BaziConfigs.vue
  13. 8 7
      cfc-web/src/views/admin/BloodTypeConfigs.vue
  14. 7 7
      cfc-web/src/views/admin/CouponManagement.vue
  15. 8 9
      cfc-web/src/views/admin/EducationSystems.vue
  16. 27 26
      cfc-web/src/views/admin/Foods.vue
  17. 6 4
      cfc-web/src/views/admin/MembershipCenter.vue
  18. 16 16
      cfc-web/src/views/admin/OrderManage.vue
  19. 12 12
      cfc-web/src/views/admin/PointsLog.vue
  20. 5 3
      cfc-web/src/views/admin/ProductEdit.vue
  21. 37 50
      cfc-web/src/views/admin/ProductManage.vue
  22. 23 23
      cfc-web/src/views/admin/Recipes.vue
  23. 9 7
      cfc-web/src/views/admin/RelationshipTypes.vue
  24. 17 15
      cfc-web/src/views/admin/SeasonalFoods.vue
  25. 10 6
      cfc-web/src/views/admin/ServiceContents.vue
  26. 8 9
      cfc-web/src/views/admin/ServiceTypes.vue
  27. 10 17
      cfc-web/src/views/admin/SysConfig.vue
  28. 14 18
      cfc-web/src/views/admin/VendorReview.vue
  29. 8 17
      cfc-web/src/views/admin/WithdrawAudit.vue
  30. 9 7
      cfc-web/src/views/admin/ZodiacConfigs.vue
  31. 13 9
      cfc-web/src/views/admin/data-source-config.vue

+ 1 - 0
cfc-web/src/main.js

@@ -14,6 +14,7 @@ import {
   MessageBox
 } from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
+import './styles/admin-tokens.css'
 import { formatPrice, formatPriceWithSymbol, formatRate, formatScore } from './utils/format'
 
 Vue.use(Button)

+ 435 - 0
cfc-web/src/styles/admin-tokens.css

@@ -0,0 +1,435 @@
+/**
+ * Admin 后台管理页面样式规范
+ * 
+ * 设计原则:
+ * - 基于 Element UI 的默认风格进行扩展
+ * - 统一间距和尺寸标准
+ * - 减少内联样式使用,改为 class 复用
+ */
+
+/* ========================
+   CSS 自定义属性 (设计令牌)
+   ======================== */
+:root {
+  /* 主色调 */
+  --color-primary: #409EFF;
+  --color-primary-light: #66b1ff;
+  --color-primary-dark: #337ecc;
+  
+  /* 成功/警告/危险 */
+  --color-success: #67C23A;
+  --color-warning: #E6A23C;
+  --color-danger: #F56C6C;
+  --color-info: #909399;
+  
+  /* 文字色 */
+  --color-text-primary: #303133;
+  --color-text-regular: #606266;
+  --color-text-secondary: #909399;
+  --color-text-placeholder: #C0C4CC;
+  
+  /* 边框色 */
+  --color-border-base: #DCDFE6;
+  --color-border-light: #E4E7ED;
+  --color-border-lighter: #EBEEF5;
+  --color-border-extra-light: #F2F6FC;
+  
+  /* 背景色 */
+  --color-bg-page: #f0f2f5;
+  --color-bg-card: #ffffff;
+  --color-bg-overlay: rgba(0, 0, 0, 0.5);
+  
+  /* 字体 */
+  --font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
+  --font-size-base: 14px;
+  --font-size-small: 13px;
+  --font-size-mini: 12px;
+  
+  /* 间距 (8px 基准) */
+  --spacing-xs: 4px;
+  --spacing-sm: 8px;
+  --spacing-md: 12px;
+  --spacing-base: 16px;
+  --spacing-lg: 20px;
+  --spacing-xl: 24px;
+  --spacing-xxl: 32px;
+  
+  /* 圆角 */
+  --border-radius-base: 4px;
+  --border-radius-small: 2px;
+  --border-radius-large: 8px;
+  
+  /* 阴影 */
+  --box-shadow-base: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  --box-shadow-light: 0 2px 4px 0 rgba(0, 0, 0, 0.08);
+  
+  /* 宽度标准 */
+  --width-search-input: 220px;
+  --width-select-sm: 120px;
+  --width-select-base: 150px;
+  --width-select-lg: 180px;
+  --width-select-xl: 200px;
+  
+  /* 高度标准 */
+  --height-table-max: calc(100vh - 280px);
+  --height-table-with-filter: calc(100vh - 340px);
+}
+
+/* ========================
+   全局重置
+   ======================== */
+.admin-page {
+  padding: var(--spacing-base);
+  background: var(--color-bg-page);
+  min-height: calc(100vh - 60px);
+}
+
+/* ========================
+   页面头部标题栏
+   ======================== */
+.admin-page-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: var(--spacing-base);
+}
+
+.admin-page-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: var(--color-text-primary);
+}
+
+.admin-page-actions {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+/* ========================
+   筛选器 / 搜索栏
+   ======================== */
+.filter-bar {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: var(--spacing-sm);
+  margin-bottom: var(--spacing-base);
+  padding: var(--spacing-base);
+  background: var(--color-bg-card);
+  border-radius: var(--border-radius-base);
+  box-shadow: var(--box-shadow-light);
+}
+
+.filter-bar .el-select {
+  width: var(--width-select-base);
+}
+
+.filter-bar .el-input {
+  width: var(--width-search-input);
+}
+
+.filter-bar .el-input--small {
+  width: var(--width-search-input);
+}
+
+.filter-bar .el-input--mini {
+  width: 160px;
+}
+
+/* ========================
+   状态标签栏 (ArticleManage 等)
+   ======================== */
+.status-tabs {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: var(--spacing-xs);
+  margin-bottom: var(--spacing-md);
+}
+
+.status-tabs .el-button + .el-button {
+  margin-left: 0;
+}
+
+/* ========================
+   表格容器 (滚动)
+   ======================== */
+.table-scroll-wrap {
+  overflow: auto;
+  max-height: var(--height-table-max);
+  border-radius: var(--border-radius-base);
+}
+
+.table-scroll-wrap-sm {
+  overflow: auto;
+  max-height: calc(100vh - 300px);
+  border-radius: var(--border-radius-base);
+}
+
+.table-scroll-wrap-lg {
+  overflow: auto;
+  max-height: var(--height-table-with-filter);
+  border-radius: var(--border-radius-base);
+}
+
+/* ========================
+   卡片
+   ======================== */
+.admin-card {
+  background: var(--color-bg-card);
+  border-radius: var(--border-radius-base);
+  box-shadow: var(--box-shadow-light);
+  margin-bottom: var(--spacing-base);
+}
+
+.admin-card .el-card__header {
+  padding: var(--spacing-base);
+  border-bottom: 1px solid var(--color-border-lighter);
+}
+
+.admin-card .el-card__body {
+  padding: var(--spacing-base);
+}
+
+/* ========================
+   操作按钮区 (分页上方/下方)
+   ======================== */
+.table-actions {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-top: var(--spacing-base);
+}
+
+.table-actions-right {
+  text-align: right;
+  margin-top: var(--spacing-base);
+}
+
+/* ========================
+   对话框表单
+   ======================== */
+.admin-form-dialog .el-form-item {
+  margin-bottom: var(--spacing-base);
+}
+
+.admin-form-dialog .el-form-item__label {
+  color: var(--color-text-regular);
+}
+
+/* ========================
+   搜索结果统计
+   ======================== */
+.search-result-count {
+  font-size: var(--font-size-small);
+  color: var(--color-text-secondary);
+  margin-bottom: var(--spacing-sm);
+}
+
+/* ========================
+   空状态
+   ======================== */
+.empty-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: var(--spacing-xxl) 0;
+  color: var(--color-text-placeholder);
+}
+
+.empty-state i {
+  font-size: 48px;
+  margin-bottom: var(--spacing-sm);
+}
+
+/* ========================
+   分页器
+   ======================== */
+.pagination-wrap {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: var(--spacing-base);
+  padding: var(--spacing-sm) 0;
+}
+
+/* ========================
+   详情页布局
+   ======================== */
+.detail-section {
+  margin-bottom: var(--spacing-lg);
+}
+
+.detail-section-title {
+  font-size: 15px;
+  font-weight: 600;
+  color: var(--color-text-primary);
+  margin-bottom: var(--spacing-md);
+  padding-bottom: var(--spacing-sm);
+  border-bottom: 1px solid var(--color-border-lighter);
+}
+
+/* ========================
+   编辑页通用样式
+   ======================== */
+.edit-form {
+  max-width: 800px;
+}
+
+.edit-form .el-form-item__label {
+  font-weight: 500;
+}
+
+.edit-form-footer {
+  margin-top: var(--spacing-xl);
+  padding-top: var(--spacing-base);
+  border-top: 1px solid var(--color-border-lighter);
+  text-align: right;
+}
+
+/* ========================
+   富文本编辑器容器
+   ======================== */
+.rich-editor {
+  border: 1px solid var(--color-border-base);
+  border-radius: var(--border-radius-base);
+  overflow: hidden;
+}
+
+.rich-editor /deep/ .w-e-toolbar {
+  flex-wrap: wrap;
+  padding: var(--spacing-sm);
+}
+
+.rich-editor /deep/ .w-e-text-container {
+  min-height: 300px;
+}
+
+.rich-editor /deep/ .w-e-panel-container {
+  z-index: 2000;
+}
+
+/* ========================
+   Element UI 组件覆盖样式
+   ======================== */
+
+/* 表格 */
+.el-table {
+  font-size: var(--font-size-small);
+}
+
+.el-table th {
+  background-color: var(--color-bg-page) !important;
+  color: var(--color-text-regular);
+  font-weight: 600;
+}
+
+.el-table td {
+  padding: 8px 0;
+}
+
+/* 按钮 */
+.el-button--small {
+  padding: 9px 15px;
+}
+
+/* 卡片 */
+.el-card {
+  border-radius: var(--border-radius-base);
+  box-shadow: var(--box-shadow-light);
+}
+
+.el-card__header {
+  padding: var(--spacing-base);
+  font-weight: 600;
+  border-bottom: 1px solid var(--color-border-lighter);
+}
+
+.el-card__body {
+  padding: var(--spacing-base);
+}
+
+/* 输入框 */
+.el-input--small {
+  font-size: var(--font-size-small);
+}
+
+/* 表单项 */
+.el-form-item--small .el-form-item__label {
+  font-size: var(--font-size-small);
+}
+
+/* 标签 */
+.el-tag {
+  border-radius: var(--border-radius-small);
+}
+
+/* 分页 */
+.el-pagination {
+  font-weight: normal;
+}
+
+/* 对话框 */
+.el-dialog__header {
+  padding: var(--spacing-base);
+  border-bottom: 1px solid var(--color-border-lighter);
+}
+
+.el-dialog__body {
+  padding: var(--spacing-lg);
+}
+
+.el-dialog__footer {
+  padding: var(--spacing-base);
+  border-top: 1px solid var(--color-border-lighter);
+}
+
+/* ========================
+   工具类
+   ======================== */
+
+/* 文本 */
+.text-muted {
+  color: var(--color-text-placeholder);
+}
+
+.text-secondary {
+  color: var(--color-text-secondary);
+}
+
+.text-primary {
+  color: var(--color-text-primary);
+}
+
+.text-success {
+  color: var(--color-success);
+}
+
+.text-warning {
+  color: var(--color-warning);
+}
+
+.text-danger {
+  color: var(--color-danger);
+}
+
+/* 间距 */
+.mt-sm { margin-top: var(--spacing-sm); }
+.mt-base { margin-top: var(--spacing-base); }
+.mt-lg { margin-top: var(--spacing-lg); }
+.mb-sm { margin-bottom: var(--spacing-sm); }
+.mb-base { margin-bottom: var(--spacing-base); }
+.mb-lg { margin-bottom: var(--spacing-lg); }
+
+/* Flex */
+.flex { display: flex; }
+.flex-wrap { flex-wrap: wrap; }
+.items-center { align-items: center; }
+.justify-between { justify-content: space-between; }
+.gap-sm { gap: var(--spacing-sm); }
+.gap-base { gap: var(--spacing-base); }
+
+/* 浮动 */
+.pull-right { float: right; }
+.clearfix::after { content: ""; display: table; clear: both; }

+ 3 - 4
cfc-web/src/views/GuideAudit.vue

@@ -59,11 +59,10 @@
               </el-dropdown-menu>
             </el-dropdown>
           </template>
-        </el-table-column>
-        </el-table>
-        </div>
+      </el-table-column>
+    </el-table></div>
 
-        <el-pagination
+  <el-pagination
         v-if="total > 0"
         style="margin-top: 20px; text-align: right"
         :current-page="pagination.page"

+ 3 - 3
cfc-web/src/views/GuideFamilyTask.vue

@@ -131,10 +131,10 @@
             </el-dropdown>
           </template>
         </el-table-column>
-      </el-table>
+    </el-table></div>
 
-      <!-- 分页 -->
-      <el-pagination
+    <!-- 分页 -->
+    <el-pagination
         v-if="searchForm.childId && total > 0"
         style="margin-top: 20px; text-align: right"
         :current-page="pagination.page"

+ 7 - 8
cfc-web/src/views/admin/Activities.vue

@@ -1,15 +1,14 @@
 <template>
   <div class="activities admin-page">
     <el-card>
-      <div slot="header">
-        <span>活动管理</span>
-        <div style="float:right">
-          <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">活动管理</span>
+        <div>
+          <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
           <el-select
             v-model="filter.status"
             placeholder="状态筛选"
             size="mini"
-            style="margin-right:12px;width:130px"
             clearable
             @change="loadActivities"
           >
@@ -21,8 +20,8 @@
           <el-button type="primary" size="mini" @click="$router.push('/activity-edit')">创建活动</el-button>
         </div>
       </div>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-        <el-table :data="activities" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+      <div class="table-scroll-wrap-lg">
+        <el-table :data="activities" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column label="封面" width="80">
           <template slot-scope="{ row }">
@@ -84,7 +83,7 @@
         :page-size="filter.size"
         layout="total, sizes, prev, pager, next, jumper"
         :total="total"
-        style="margin-top:16px;text-align:right"
+        class="pagination-wrap"
       />
     </el-card>
 

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

@@ -1,9 +1,9 @@
 <template>
   <div class="activity-edit admin-page">
     <el-card>
-      <div slot="header">
-        <span>{{ readonly && activityStatus !== 'rejected' ? '活动详情' : (isEdit ? '编辑活动' : '创建活动') }}</span>
-        <div style="float: right;">
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">{{ readonly && activityStatus !== 'rejected' ? '活动详情' : (isEdit ? '编辑活动' : '创建活动') }}</span>
+        <div class="admin-page-actions">
           <el-button @click="$router.push('/activities')">返回列表</el-button>
           <template v-if="!readonly && activityStatus !== 'rejected'">
             <el-button type="primary" @click="saveActivity(false)" :loading="saving">保存草稿</el-button>

+ 4 - 2
cfc-web/src/views/admin/ActivityRegistrationReview.vue

@@ -16,7 +16,8 @@
       </div>
     </div>
 
-    <div style="overflow:auto;max-height:calc(100vh - 300px);"><el-table style="max-height:calc(100vh - 300px);" :data="filteredList" v-loading="loading" border stripe>
+    <div class="table-scroll-wrap-sm">
+      <el-table :data="filteredList" v-loading="loading" border stripe>
       <el-table-column prop="id" label="ID" width="60" />
       <el-table-column prop="userId" label="用户ID" width="70" />
       <el-table-column prop="childId" label="孩子ID" width="70" />
@@ -39,7 +40,8 @@
           <span v-else style="color: #999;">已处理</span>
         </template>
       </el-table-column>
-    </el-table></div>
+    </el-table>
+    </div>
 
     <el-dialog title="拒绝原因" :visible.sync="rejectDialogVisible" width="400px">
       <el-input v-model="rejectReason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />

+ 9 - 7
cfc-web/src/views/admin/ActivityReview.vue

@@ -1,12 +1,14 @@
 <template>
   <div class="activity-review admin-page">
     <el-card>
-      <div slot="header">
-        <span>活动审核</span>
-        <el-input v-model="keyword" placeholder="搜索活动..." prefix-icon="el-icon-search" style="width:200px;float:right" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table :data="pendingActivities" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">活动审核</span>
+        <div class="admin-page-actions">
+          <el-input v-model="keyword" placeholder="搜索活动..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+        </div>
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="pendingActivities" v-loading="loading" border stripe>
       <el-table-column prop="id" label="ID" width="80" />
       <el-table-column prop="title" label="活动标题" />
       <el-table-column prop="applicant" label="申请人" width="120" />
@@ -44,7 +46,7 @@
         :page-size="size"
         :total="total"
         layout="total, prev, pager, next"
-        style="margin-top: 20px; text-align: right;"
+        class="pagination-wrap"
       />
     </el-card>
   </div>

+ 8 - 9
cfc-web/src/views/admin/ArticleCategory.vue

@@ -1,14 +1,15 @@
 <template>
   <div class="article-category admin-page">
     <el-card>
-      <div slot="header">
-        <span>文章分类管理</span>
-        <div style="float: right">
-          <el-input v-model="keyword" placeholder="搜索分类..." prefix-icon="el-icon-search" style="width:200px;margin-right:10px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">文章分类管理</span>
+        <div class="admin-page-actions">
+          <el-input v-model="keyword" placeholder="搜索分类..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
           <el-button type="primary" size="small" @click="handleCreate">+ 新增分类</el-button>
         </div>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table :data="filteredData" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);"
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="filteredData" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column label="图标" width="80">
           <template slot-scope="{ row }">
@@ -44,9 +45,7 @@
           </template>
         </el-table-column>
       </el-table></div>
-    </el-card>
-
-    <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑分类' : '新增分类'" width="500px" :close-on-click-modal="false">
+    </el-card> :visible.sync="dialogVisible" :title="isEdit ? '编辑分类' : '新增分类'" width="500px" :close-on-click-modal="false">
       <el-form :model="form" label-width="80px">
         <el-form-item label="名称">
           <el-input v-model="form.name" placeholder="请输入分类名称" />

+ 43 - 56
cfc-web/src/views/admin/ArticleManage.vue

@@ -2,9 +2,9 @@
   <div class="admin-page">
     <div class="article-manage">
     <el-card>
-      <div slot="header">
-        <span>文章管理</span>
-        <el-button style="float: right" type="primary" size="small" @click="$router.push('/article-edit')">+ 新建文章</el-button>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">文章管理</span>
+        <el-button type="primary" size="small" @click="$router.push('/article-edit')">+ 新建文章</el-button>
       </div>
 
       <!-- 状态标签栏 -->
@@ -20,43 +20,43 @@
 
       <!-- 搜索筛选栏 -->
       <div class="filter-bar">
-        <el-select v-model="filters.categoryId" placeholder="分类" clearable @change="loadList" style="width: 150px;">
+        <el-select v-model="filters.categoryId" placeholder="分类" clearable @change="loadList">
           <el-option label="全部分类" value="" />
           <el-option v-for="cat in categories" :key="cat.id" :label="cat.name" :value="cat.id" />
         </el-select>
-    <el-select v-model="filters.contentType" placeholder="内容类型" clearable @change="loadList" style="width: 130px;">
-      <el-option label="全部类型" value="" />
-      <el-option label="文章" value="article" />
-      <el-option label="知识点" value="knowledge" />
-      <el-option label="课程" value="course" />
-      <el-option label="贴士" value="tip" />
-    </el-select>
-    <el-select v-model="filters.difficultyLevel" placeholder="难度" clearable @change="loadList" style="width: 100px;">
-      <el-option label="全部难度" value="" />
-      <el-option label="1星" value="1" />
-      <el-option label="2星" value="2" />
-      <el-option label="3星" value="3" />
-      <el-option label="4星" value="4" />
-      <el-option label="5星" value="5" />
-    </el-select>
-    <el-select v-model="filters.dimensionCode" placeholder="维度" clearable @change="loadList" style="width: 100px;">
-      <el-option label="全部维度" value="" />
-      <el-option label="身" value="body" />
-      <el-option label="心" value="mind" />
-      <el-option label="智" value="wisdom" />
-      <el-option label="行" value="action" />
-      <el-option label="富" value="wealth" />
-    </el-select>
-    <el-select v-model="filters.tagId" placeholder="知识标签" clearable @change="loadList" style="width: 150px;" filterable>
-      <el-option label="全部标签" value="" />
+        <el-select v-model="filters.contentType" placeholder="内容类型" clearable @change="loadList">
+          <el-option label="全部类型" value="" />
+          <el-option label="文章" value="article" />
+          <el-option label="知识点" value="knowledge" />
+          <el-option label="课程" value="course" />
+          <el-option label="贴士" value="tip" />
+        </el-select>
+        <el-select v-model="filters.difficultyLevel" placeholder="难度" clearable @change="loadList">
+          <el-option label="全部难度" value="" />
+          <el-option label="1星" value="1" />
+          <el-option label="2星" value="2" />
+          <el-option label="3星" value="3" />
+          <el-option label="4星" value="4" />
+          <el-option label="5星" value="5" />
+        </el-select>
+        <el-select v-model="filters.dimensionCode" placeholder="维度" clearable @change="loadList">
+          <el-option label="全部维度" value="" />
+          <el-option label="身" value="body" />
+          <el-option label="心" value="mind" />
+          <el-option label="智" value="wisdom" />
+          <el-option label="行" value="action" />
+          <el-option label="富" value="wealth" />
+        </el-select>
+        <el-select v-model="filters.tagId" placeholder="知识标签" clearable @change="loadList" filterable>
+          <el-option label="全部标签" value="" />
           <el-option v-for="tag in tagOptions" :key="tag.id" :label="tag.name" :value="tag.id" />
         </el-select>
-        <el-input v-model="filters.keyword" placeholder="搜索文章标题..." clearable style="width: 220px;" @keyup.enter.native="loadList" />
+        <el-input v-model="filters.keyword" placeholder="搜索文章标题..." clearable @keyup.enter.native="loadList" />
         <el-button type="primary" icon="el-icon-search" @click="loadList">搜索</el-button>
       </div>
 
-      <div style="overflow:auto;max-height:calc(100vh - 340px);">
-        <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 340px);">
+      <div class="table-scroll-wrap-lg">
+        <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column label="标题" min-width="220">
           <template slot-scope="{ row }">
@@ -210,15 +210,16 @@
       </el-table>
       </div>
 
-      <el-pagination
-        @size-change="onPageChange"
-        @current-change="onPageChange"
-        :current-page="page"
-        :page-size="size"
-        :total="total"
-        layout="total, prev, pager, next"
-        style="margin-top: 20px; text-align: right;"
-      />
+      <div class="pagination-wrap">
+        <el-pagination
+          @size-change="onPageChange"
+          @current-change="onPageChange"
+          :current-page="page"
+          :page-size="size"
+          :total="total"
+          layout="total, prev, pager, next"
+        />
+      </div>
     </el-card>
   </div>
 
@@ -498,20 +499,6 @@ export default {
 
 <style scoped>
 .article-manage {
-  padding: 20px;
-}
-.filter-bar {
-  margin-bottom: 18px;
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  flex-wrap: wrap;
-}
-.status-tabs {
-  margin-bottom: 18px;
-  display: flex;
-  align-items: center;
-  gap: 6px;
-  flex-wrap: wrap;
+  padding: 0;
 }
 </style>

+ 12 - 8
cfc-web/src/views/admin/Assessment.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="assessment-admin admin-page">
     <el-card class="config-card">
-      <div slot="header">
-        <span class="card-title">💰 积分配置</span>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">💰 积分配置</span>
       </div>
       <el-form :model="pointsConfig" label-width="120px">
         <el-form-item label="完成获得积分">
@@ -20,12 +20,15 @@
     </el-card>
 
     <el-card class="materials-card">
-      <div slot="header">
-        <span class="card-title">📚 测评资料</span>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">📚 测评资料</span>
         <el-input v-model="keyword" placeholder="搜索测评资料..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button type="primary" size="small" style="float: right; margin-left: 10px" @click="showCreateDialog">添加资料</el-button>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table :data="filteredData" border stripe style="max-height:calc(100vh - 300px);"
+        <div class="admin-page-actions">
+          <el-button type="primary" size="small" @click="showCreateDialog">添加资料</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="filteredData" border stripe>
         <el-table-column prop="id" label="ID" width="60" />
         <el-table-column prop="title" label="标题" />
         <el-table-column prop="content" label="内容" show-overflow-tooltip />
@@ -52,7 +55,8 @@
             </el-dropdown>
           </template>
         </el-table-column>
-      </el-table></div>
+      </el-table>
+      </div>
     </el-card>
 
     <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">

+ 9 - 7
cfc-web/src/views/admin/BaziConfigs.vue

@@ -1,12 +1,15 @@
 <template>
   <div class="bazi-configs admin-page">
     <el-card>
-      <div slot="header">
-        <span>八字配置管理</span>
-        <el-input v-model="keyword" placeholder="搜索八字..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right" type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table :data="filteredData" stripe style="max-height:calc(100vh - 300px);"
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">八字配置管理</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索八字..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap">
+      <el-table :data="filteredData" stripe
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="stemOrBranch" label="天干/地支" width="100"></el-table-column>
         <el-table-column prop="type" label="类型" width="80">
@@ -183,5 +186,4 @@ export default {
 </script>
 
 <style scoped>
-.bazi-configs { padding: 20px; }
 </style>

+ 8 - 7
cfc-web/src/views/admin/BloodTypeConfigs.vue

@@ -1,12 +1,14 @@
 <template>
   <div class="blood-type-configs admin-page">
     <el-card>
-      <div slot="header">
-        <span>血型配置管理</span>
-        <el-input v-model="keyword" placeholder="搜索血型..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right" type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);"><el-table style="max-height:calc(100vh - 300px);" :data="filteredData" stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">血型配置管理</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索血型..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap"><el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="bloodType" label="血型" width="80"></el-table-column>
         <el-table-column prop="description" label="性格描述" min-width="200"></el-table-column>
@@ -160,5 +162,4 @@ export default {
 </script>
 
 <style scoped>
-.blood-type-configs { padding: 20px; }
 </style>

+ 7 - 7
cfc-web/src/views/admin/CouponManagement.vue

@@ -1,17 +1,17 @@
 <template>
   <div class="coupon-management admin-page">
     <el-card>
-      <div slot="header">
-        <span>优惠券管理</span>
-        <div style="float: right">
-          <el-input v-model="keyword" placeholder="搜索优惠券..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">优惠券管理</span>
+        <div class="admin-page-actions">
+          <el-input v-model="keyword" placeholder="搜索优惠券..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
           <el-button type="primary" size="small" @click="handleCreate">新建优惠券</el-button>
           <el-button type="success" size="small" @click="handleBatchIssue">批量发放</el-button>
         </div>
       </div>
 
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-        <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+      <div class="table-scroll-wrap-sm">
+        <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column prop="name" label="名称" min-width="140" show-overflow-tooltip />
         <el-table-column label="类型" width="90">
@@ -63,7 +63,7 @@
         :page-size="size"
         :total="total"
         layout="total, prev, pager, next"
-        style="margin-top: 20px; text-align: right"
+        class="pagination-wrap"
       />
     </el-card>
 

+ 8 - 9
cfc-web/src/views/admin/EducationSystems.vue

@@ -1,12 +1,14 @@
 <template>
   <div class="education-systems admin-page">
     <el-card>
-      <div slot="header">
-        <span>教育体系管理</span>
-        <el-input v-model="keyword" placeholder="搜索体系..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right" type="primary" size="small" @click="handleCreate">+ 添加体系</el-button>
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);"><el-table style="max-height:calc(100vh - 300px);" :data="filteredData" stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">教育体系管理</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索体系..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加体系</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap"><el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="name" label="编码" width="120"></el-table-column>
         <el-table-column prop="label" label="显示名称"></el-table-column>
@@ -152,7 +154,4 @@ export default {
 </script>
 
 <style scoped>
-.education-systems {
-  padding: 20px;
-}
 </style>

+ 27 - 26
cfc-web/src/views/admin/Foods.vue

@@ -1,33 +1,34 @@
 <template>
   <div class="foods admin-page">
     <el-card>
-      <div slot="header">
-        <span>食材管理</span>
-        <el-button type="primary" size="mini" style="float:right" @click="openCreate">新建食材</el-button>
-        <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="categoryFilter"
-          placeholder="分类筛选"
-          size="mini"
-          style="float:right;margin-right:12px"
-          clearable
-          @change="loadList"
-        >
-          <el-option label="全部分类" value="" />
-          <el-option label="蔬菜" value="蔬菜" />
-          <el-option label="水果" value="水果" />
-          <el-option label="肉类" value="肉类" />
-          <el-option label="水产" value="水产" />
-          <el-option label="蛋奶" value="蛋奶" />
-          <el-option label="豆类" value="豆类" />
-          <el-option label="谷物" value="谷物" />
-          <el-option label="坚果" value="坚果" />
-          <el-option label="调味品" value="调味品" />
-          <el-option label="其他" value="其他" />
-        </el-select>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">食材管理</span>
+        <div>
+          <el-button type="primary" size="mini" @click="openCreate">新建食材</el-button>
+          <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-select
+            v-model="categoryFilter"
+            placeholder="分类筛选"
+            size="mini"
+            clearable
+            @change="loadList"
+          >
+            <el-option label="全部分类" value="" />
+            <el-option label="蔬菜" value="蔬菜" />
+            <el-option label="水果" value="水果" />
+            <el-option label="肉类" value="肉类" />
+            <el-option label="水产" value="水产" />
+            <el-option label="蛋奶" value="蛋奶" />
+            <el-option label="豆类" value="豆类" />
+            <el-option label="谷物" value="谷物" />
+            <el-option label="坚果" value="坚果" />
+            <el-option label="调味品" value="调味品" />
+            <el-option label="其他" value="其他" />
+          </el-select>
+        </div>
       </div>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-        <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+      <div class="table-scroll-wrap-lg">
+        <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column prop="name" label="名称" />
         <el-table-column prop="category" label="分类" width="100" />

+ 6 - 4
cfc-web/src/views/admin/MembershipCenter.vue

@@ -82,8 +82,9 @@
     <el-card>
       <div slot="header">
         <span>会员升级记录</span>
-      </div>
-      <el-table :data="upgradeRecords" v-loading="recordsLoading" border stripe>
+    </div>
+    <div style="overflow:auto;max-height:calc(100vh - 300px);">
+    <el-table :data="upgradeRecords" v-loading="recordsLoading" border stripe style="max-height:calc(100vh - 300px);">
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column prop="userId" label="用户ID" width="80" />
         <el-table-column label="从" width="100">
@@ -108,8 +109,9 @@
         <el-table-column prop="createdAt" label="创建时间" width="160">
           <template slot-scope="{ row }">{{ formatTime(row.createdAt) }}</template>
         </el-table-column>
-      </el-table>
-      <el-pagination
+    </el-table>
+    </div>
+    <el-pagination
         v-if="recordsTotal > 0"
         @size-change="handleRecordSizeChange"
         @current-change="handleRecordPageChange"

+ 16 - 16
cfc-web/src/views/admin/OrderManage.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="order-manage admin-page">
     <div class="header">
-      <h2>订单管理</h2>
-      <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: 180px;">
+      <h2 class="admin-page-title">订单管理</h2>
+      <div class="filters filter-bar">
+        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+        <el-select v-model="statusFilter" placeholder="订单状态" @change="loadList" clearable>
           <el-option label="全部状态" value="" />
           <el-option label="待支付" value="pending" />
           <el-option label="已支付(待发货)" value="paid" />
@@ -18,8 +18,8 @@
       </div>
     </div>
 
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+    <div class="table-scroll-wrap-lg">
+      <el-table :data="list" v-loading="loading" border stripe>
       <el-table-column prop="orderNo" label="订单号" width="180" />
       <el-table-column label="商品" min-width="160">
         <template slot-scope="{ row }">
@@ -68,16 +68,16 @@
     </el-table>
     </div>
 
-    <el-pagination
-      @size-change="onSizeChange"
-      @current-change="onPageChange"
-      :current-page="page"
-      :page-size="size"
-      :total="total"
-      layout="total, sizes, prev, pager, next"
-      :page-sizes="[10, 20, 50]"
-      style="margin-top: 20px; text-align: right;"
-    />
+<el-pagination
+        @size-change="onSizeChange"
+        @current-change="onPageChange"
+        :current-page="page"
+        :page-size="size"
+        :total="total"
+        layout="total, sizes, prev, pager, next"
+        :page-sizes="[10, 20, 50]"
+        class="pagination-wrap"
+      />
 
     <!-- Detail Dialog -->
     <el-dialog title="订单详情" :visible.sync="detailDialogVisible" width="700px" top="5vh">

+ 12 - 12
cfc-web/src/views/admin/PointsLog.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="points-log admin-page">
-    <el-card>
-      <div slot="header">
-        <span>积分记录</span>
-        <div style="float:right">
-          <el-select v-model="filter.type" placeholder="类型筛选" size="mini" style="margin-right:12px;width:130px" clearable @change="loadData">
+<el-card>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">积分记录</span>
+        <div class="admin-page-actions">
+          <el-select v-model="filter.type" placeholder="类型筛选" size="mini" clearable @change="loadData">
             <el-option label="全部" value="" />
             <el-option label="任务奖励" value="task" />
             <el-option label="系统调整" value="adjust" />
@@ -12,16 +12,16 @@
             <el-option label="退款返还" value="refund" />
             <el-option label="超时扣分" value="timeout" />
           </el-select>
-          <el-select v-model="filter.category" placeholder="分类筛选" size="mini" style="margin-right:12px;width:130px" clearable @change="loadData">
+          <el-select v-model="filter.category" placeholder="分类筛选" size="mini" clearable @change="loadData">
             <el-option label="全部" value="" />
             <el-option label="任务积分" value="task" />
             <el-option label="系统积分" value="system" />
           </el-select>
-          <el-input v-model="filter.childKeyword" placeholder="搜索孩子ID..." prefix-icon="el-icon-search" size="mini" style="width:180px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-    </div>
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+          <el-input v-model="filter.childKeyword" placeholder="搜索孩子 ID..." prefix-icon="el-icon-search" size="mini" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+        </div>
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="createdAt" label="时间" width="160">
           <template slot-scope="{ row }">{{ formatTime(row.createdAt) }}</template>
         </el-table-column>
@@ -77,7 +77,7 @@
         :page-size="filter.size"
         layout="total, sizes, prev, pager, next, jumper"
         :total="total"
-        style="margin-top:16px;text-align:right"
+        class="pagination-wrap"
       />
     </el-card>
 

+ 5 - 3
cfc-web/src/views/admin/ProductEdit.vue

@@ -1,9 +1,11 @@
 <template>
   <div class="product-edit admin-page">
     <el-card v-loading="pageLoading">
-      <div slot="header">
-        <span>{{ isEdit ? '编辑商品' : '新增商品' }}</span>
-        <el-button style="float: right;" size="mini" @click="$router.back()">返回</el-button>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">{{ isEdit ? '编辑商品' : '新增商品' }}</span>
+        <div class="admin-page-actions">
+          <el-button size="mini" @click="$router.back()">返回</el-button>
+        </div>
       </div>
 
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">

+ 37 - 50
cfc-web/src/views/admin/ProductManage.vue

@@ -1,38 +1,39 @@
 <template>
   <div class="product-manage admin-page">
-    <div class="header">
-      <h2>商品管理</h2>
-      <div class="filters">
-        <el-input
-          v-model="filters.keyword"
-          placeholder="搜索商品名称"
-          prefix-icon="el-icon-search"
-          clearable
-          style="width: 180px;"
-          @clear="loadList"
-          @keyup.enter.native="loadList"
-        />
-        <el-select v-model="filters.status" placeholder="商品状态" @change="loadList" style="width: 130px;" clearable>
-          <el-option label="全部状态" value="" />
-          <el-option label="待审核" value="pending" />
-          <el-option label="待上架" value="approved" />
-          <el-option label="已上架" value="on_shelf" />
-          <el-option label="已下架" value="off_shelf" />
-          <el-option label="已拒绝" value="rejected" />
-        </el-select>
-        <el-select v-model="filters.productType" placeholder="商品类型" @change="loadList" style="width: 140px;" clearable>
-          <el-option label="全部类型" value="" />
-          <el-option label="实物商品" value="physical" />
-          <el-option label="虚拟商品" value="virtual" />
-          <el-option label="优惠券" value="coupon" />
-        </el-select>
-        <el-button type="primary" size="mini" @click="loadList">查询</el-button>
-        <el-button type="success" size="mini" icon="el-icon-plus" @click="$router.push('/product-edit')">新增商品</el-button>
+    <el-card>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">商品管理</span>
+        <div class="admin-page-actions">
+          <el-input
+            v-model="filters.keyword"
+            placeholder="搜索商品名称"
+            prefix-icon="el-icon-search"
+            clearable
+            class="header-search"
+            @clear="loadList"
+            @keyup.enter.native="loadList"
+          />
+          <el-select v-model="filters.status" placeholder="商品状态" @change="loadList" clearable>
+            <el-option label="全部状态" value="" />
+            <el-option label="待审核" value="pending" />
+            <el-option label="待上架" value="approved" />
+            <el-option label="已上架" value="on_shelf" />
+            <el-option label="已下架" value="off_shelf" />
+            <el-option label="已拒绝" value="rejected" />
+          </el-select>
+          <el-select v-model="filters.productType" placeholder="商品类型" @change="loadList" clearable>
+            <el-option label="全部类型" value="" />
+            <el-option label="实物商品" value="physical" />
+            <el-option label="虚拟商品" value="virtual" />
+            <el-option label="优惠券" value="coupon" />
+          </el-select>
+          <el-button type="primary" size="mini" @click="loadList">查询</el-button>
+          <el-button type="success" size="mini" icon="el-icon-plus" @click="$router.push('/product-edit')">新增商品</el-button>
+        </div>
       </div>
-    </div>
 
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+      <div class="table-scroll-wrap-sm">
+        <el-table :data="list" v-loading="loading" border stripe>
       <el-table-column prop="id" label="ID" width="70" />
       <el-table-column label="商品图片" width="80">
         <template slot-scope="{ row }">
@@ -106,7 +107,7 @@
       :page-size="pagination.size"
       :total="pagination.total"
       layout="total, sizes, prev, pager, next, jumper"
-      style="margin-top: 16px; text-align: right;"
+      class="pagination-wrap"
     />
 
     <el-dialog title="拒绝原因" :visible.sync="rejectDialogVisible" width="420px">
@@ -135,6 +136,7 @@
       </el-descriptions>
       <div v-else style="text-align:center;color:#999;">加载中...</div>
     </el-dialog>
+  </el-card>
   </div>
 </template>
 
@@ -289,24 +291,6 @@ export default {
 .product-manage {
   padding: 20px;
 }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-  flex-wrap: wrap;
-  gap: 12px;
-}
-.header h2 {
-  margin: 0;
-  font-size: 18px;
-}
-.filters {
-  display: flex;
-  gap: 8px;
-  flex-wrap: wrap;
-  align-items: center;
-}
 .product-thumb {
   width: 50px;
   height: 50px;
@@ -318,4 +302,7 @@ export default {
   color: #f56c6c;
   font-weight: bold;
 }
+.header-search {
+  width: 180px;
+}
 </style>

+ 23 - 23
cfc-web/src/views/admin/Recipes.vue

@@ -1,26 +1,28 @@
 <template>
   <div class="recipes admin-page">
     <el-card>
-      <div slot="header">
-        <span>食谱管理</span>
-        <el-button type="primary" size="mini" style="float:right" @click="openCreate">新建食谱</el-button>
-        <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="mealTypeFilter"
-          placeholder="餐次筛选"
-          size="mini"
-          style="float:right;margin-right:12px"
-          clearable
-          @change="loadList"
-        >
-          <el-option label="全部餐次" value="" />
-          <el-option label="早餐" value="早餐" />
-          <el-option label="午餐" value="午餐" />
-          <el-option label="晚餐" value="晚餐" />
-          <el-option label="加餐" value="加餐" />
-        </el-select>
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);"><el-table style="max-height:calc(100vh - 300px);" :data="list" v-loading="loading" border stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">食谱管理</span>
+        <div class="admin-page-actions">
+          <el-select
+            v-model="mealTypeFilter"
+            placeholder="餐次筛选"
+            size="mini"
+            clearable
+            @change="loadList"
+          >
+            <el-option label="全部餐次" value="" />
+            <el-option label="早餐" value="早餐" />
+            <el-option label="午餐" value="午餐" />
+            <el-option label="晚餐" value="晚餐" />
+            <el-option label="加餐" value="加餐" />
+          </el-select>
+          <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="mini" @click="openCreate">新建食谱</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column prop="name" label="名称" />
         <el-table-column prop="mealType" label="类型" width="80" />
@@ -40,9 +42,7 @@
           </template>
         </el-table-column>
     </el-table></div>
-  </el-card>
-
-    <el-dialog :title="editId ? '编辑食谱' : '新建食谱'" :visible.sync="dialogVisible" width="700px">
+  </el-card> :title="editId ? '编辑食谱' : '新建食谱'" :visible.sync="dialogVisible" width="700px">
       <el-form label-width="120px">
         <el-form-item label="名称">
           <el-input v-model="form.name" />

+ 9 - 7
cfc-web/src/views/admin/RelationshipTypes.vue

@@ -1,12 +1,15 @@
 <template>
   <div class="relationship-types admin-page">
     <el-card>
-      <div slot="header">
-        <span>关系类型配置</span>
-        <el-input v-model="keyword" placeholder="搜索关系类型..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right; margin-left: 10px" type="primary" size="small" @click="handleCreate">+ 添加关系类型</el-button>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table style="max-height:calc(100vh - 300px);" :data="filteredData" stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">关系类型配置</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索关系类型..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加关系类型</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap">
+      <el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="typeKey" label="编码" width="120"></el-table-column>
         <el-table-column prop="typeName" label="显示名称" width="120"></el-table-column>
@@ -162,5 +165,4 @@ export default {
 </script>
 
 <style scoped>
-.relationship-types { padding: 20px; }
 </style>

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

@@ -1,21 +1,23 @@
 <template>
   <div class="seasonal-foods admin-page">
     <el-card>
-      <div slot="header">
-        <span>应季食材配置</span>
-        <el-button type="primary" size="mini" style="float:right" @click="openCreate">新增应季映射</el-button>
-        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" style="width:200px;float:right;margin-right:12px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-select
-          v-model="monthFilter"
-          placeholder="选择月份"
-          size="mini"
-          style="float:right;margin-right:12px"
-          @change="loadList"
-        >
-          <el-option v-for="m in 12" :key="m" :label="m + '月'" :value="m" />
-        </el-select>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table style="max-height:calc(100vh - 300px);" :data="list" v-loading="loading" border stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">应季食材配置</span>
+        <div class="flex items-center gap-sm">
+          <el-select
+            v-model="monthFilter"
+            placeholder="选择月份"
+            size="mini"
+            @change="loadList"
+          >
+            <el-option v-for="m in 12" :key="m" :label="m + '月'" :value="m" />
+          </el-select>
+          <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="mini" @click="openCreate">新增应季映射</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap">
+      <el-table :data="list" v-loading="loading" border stripe>
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column prop="foodId" label="食材ID" width="80" />
         <el-table-column label="月份" width="80">

+ 10 - 6
cfc-web/src/views/admin/ServiceContents.vue

@@ -1,10 +1,12 @@
 <template>
   <div class="service-contents admin-page">
     <el-card>
-      <div slot="header">
-        <span>服务内容管理</span>
-        <el-input v-model="keyword" placeholder="搜索内容..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right" type="primary" size="small" @click="handleCreate">+ 添加内容</el-button>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">服务内容管理</span>
+        <div class="admin-page-actions">
+          <el-input v-model="keyword" placeholder="搜索内容..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加内容</el-button>
+        </div>
       </div>
       <el-form :inline="true">
         <el-form-item label="服务类型">
@@ -22,7 +24,8 @@
           <el-button @click="handleQuery">查询</el-button>
         </el-form-item>
     </el-form>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);"><el-table style="max-height:calc(100vh - 300px);" :data="filteredData" stripe>
+    <div class="table-scroll-wrap-sm">
+    <el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="title" label="标题"></el-table-column>
         <el-table-column prop="typeId" label="类型" width="120">
@@ -56,7 +59,8 @@
             </el-dropdown>
           </template>
         </el-table-column>
-    </el-table></div>
+    </el-table>
+    </div>
   </el-card>
 
     <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑服务内容' : '添加服务内容'" width="800px">

+ 8 - 9
cfc-web/src/views/admin/ServiceTypes.vue

@@ -1,13 +1,15 @@
 <template>
   <div class="service-types admin-page">
     <el-card>
-      <div slot="header">
-        <span>服务类型管理</span>
-        <el-input v-model="keyword" placeholder="搜索服务类型..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right; margin-left: 10px" type="primary" size="small" @click="handleCreate">+ 添加类型</el-button>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">服务类型管理</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索服务类型..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加类型</el-button>
+        </div>
       </div>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-        <el-table :data="filteredData" stripe style="max-height:calc(100vh - 300px);">
+      <div class="table-scroll-wrap">
+        <el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="name" label="类型名称"></el-table-column>
         <el-table-column prop="icon" label="图标" width="100">
@@ -158,7 +160,4 @@ export default {
 </script>
 
 <style scoped>
-.service-types {
-  padding: 20px;
-}
 </style>

+ 10 - 17
cfc-web/src/views/admin/SysConfig.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="sys-config admin-page">
-    <div class="header">
-      <h2>系统配置</h2>
-      <div>
-        <el-input v-model="keyword" placeholder="搜索配置..." prefix-icon="el-icon-search" style="width:200px;margin-right:10px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+<div class="header admin-page-header">
+      <h2 class="admin-page-title">系统配置</h2>
+      <div class="flex items-center gap-sm">
+        <el-input v-model="keyword" placeholder="搜索配置..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
         <el-button type="primary" size="small" @click="addConfig" icon="el-icon-plus">新增配置</el-button>
       </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table style="max-height:calc(100vh - 300px);" :data="list" v-loading="loading" border stripe>
+    </div>
+    <div class="table-scroll-wrap" style="overflow:auto;max-height:calc(100vh - 300px);">
+    <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
       <el-table-column prop="configKey" label="配置键" min-width="200" show-overflow-tooltip />
       <el-table-column prop="configValue" label="配置值" min-width="250" show-overflow-tooltip />
       <el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
@@ -29,7 +30,8 @@
           </el-dropdown>
         </template>
       </el-table-column>
-    </el-table></div>
+    </el-table>
+    </div>
 
     <el-pagination
       @size-change="onPageChange"
@@ -38,7 +40,7 @@
       :page-size="size"
       :total="total"
       layout="total, prev, pager, next"
-      style="margin-top: 20px; text-align: right;"
+      class="pagination-wrap"
     />
 
     <!-- 编辑弹窗 -->
@@ -181,13 +183,4 @@ export default {
 .sys-config {
   padding: 20px;
 }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-}
-.header h2 {
-  margin: 0;
-}
 </style>

+ 14 - 18
cfc-web/src/views/admin/VendorReview.vue

@@ -1,18 +1,20 @@
 <template>
   <div class="vendor-review admin-page">
-    <div class="header">
-      <h2>服务商入驻审核</h2>
-      <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: 150px;">
-        <el-option label="全部状态" value="" />
-        <el-option label="待审核" value="pending" />
-        <el-option label="已通过" value="approved" />
-        <el-option label="已拒绝" value="rejected" />
-      </el-select>
+    <div class="header admin-page-header">
+      <h2 class="admin-page-title">服务商入驻审核</h2>
+      <div class="flex items-center gap-sm">
+        <el-select v-model="statusFilter" placeholder="审核状态" @change="loadList">
+          <el-option label="全部状态" value="" />
+          <el-option label="待审核" value="pending" />
+          <el-option label="已通过" value="approved" />
+          <el-option label="已拒绝" value="rejected" />
+        </el-select>
+        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+      </div>
     </div>
 
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+    <div class="table-scroll-wrap">
+    <el-table :data="list" v-loading="loading" border stripe>
       <el-table-column prop="id" label="用户ID" width="80" />
       <el-table-column prop="nickname" label="昵称" width="120" />
       <el-table-column prop="realName" label="真实姓名" width="120" />
@@ -54,7 +56,7 @@
       :page-size="size"
       :total="total"
       layout="total, prev, pager, next"
-      style="margin-top: 20px; text-align: right;"
+      class="pagination-wrap"
     />
 
     <!-- 拒绝弹窗 -->
@@ -156,12 +158,6 @@ export default {
 </script>
 
 <style scoped>
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-}
 .no-op {
   color: #ccc;
 }

+ 8 - 17
cfc-web/src/views/admin/WithdrawAudit.vue

@@ -1,20 +1,20 @@
 <template>
   <div class="withdraw-audit admin-page">
-    <div class="header">
-      <h2>提现审核</h2>
-      <div style="display:flex;align-items:center;gap:12px">
-        <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: 150px;">
+    <div class="header admin-page-header">
+      <h2 class="admin-page-title">提现审核</h2>
+      <div class="flex items-center gap-sm">
+        <el-select v-model="statusFilter" placeholder="审核状态" @change="loadList">
           <el-option label="全部状态" value="" />
           <el-option label="待审核" value="pending" />
           <el-option label="已通过" value="approved" />
           <el-option label="已拒绝" value="rejected" />
         </el-select>
+        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
       </div>
     </div>
 
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table :data="list" v-loading="loading" border stripe style="max-height:calc(100vh - 300px);">
+    <div class="table-scroll-wrap">
+    <el-table :data="list" v-loading="loading" border stripe>
       <el-table-column prop="id" label="ID" width="70" />
       <el-table-column label="用户" width="120">
         <template slot-scope="{ row }">
@@ -79,7 +79,7 @@
       :page-size="size"
       :total="total"
       layout="total, prev, pager, next"
-      style="margin-top: 20px; text-align: right;"
+      class="pagination-wrap"
     />
 
     <!-- 拒绝原因弹窗 -->
@@ -214,15 +214,6 @@ export default {
 .withdraw-audit {
   padding: 20px;
 }
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20px;
-}
-.header h2 {
-  margin: 0;
-}
 .amount {
   font-weight: bold;
   color: #f56c6c;

+ 9 - 7
cfc-web/src/views/admin/ZodiacConfigs.vue

@@ -1,12 +1,15 @@
 <template>
   <div class="zodiac-configs admin-page">
     <el-card>
-      <div slot="header">
-        <span>星座配置管理</span>
-        <el-input v-model="keyword" placeholder="搜索星座..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right" type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-      <el-table style="max-height:calc(100vh - 300px);" :data="filteredData" stripe>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">星座配置管理</span>
+        <div class="flex items-center gap-sm">
+          <el-input v-model="keyword" placeholder="搜索星座..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加配置</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap">
+      <el-table :data="filteredData" stripe>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="zodiacCode" label="代码" width="120"></el-table-column>
         <el-table-column prop="zodiacName" label="名称"></el-table-column>
@@ -183,5 +186,4 @@ export default {
 </script>
 
 <style scoped>
-.zodiac-configs { padding: 20px; }
 </style>

+ 13 - 9
cfc-web/src/views/admin/data-source-config.vue

@@ -1,13 +1,15 @@
 <template>
   <div class="data-source-config admin-page">
     <el-card>
-      <div slot="header">
-        <span>健康数据源配置</span>
+      <div slot="header" class="admin-page-header">
+        <span class="admin-page-title">健康数据源配置</span>
         <el-input v-model="keyword" placeholder="搜索数据源..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-        <el-button style="float: right; margin-left: 10px" type="primary" size="small" @click="handleCreate">+ 添加数据源</el-button>
-    </div>
-    <div style="overflow:auto;max-height:calc(100vh - 300px);">
-    <el-table :data="records" stripe v-loading="loading" style="max-height:calc(100vh - 300px);">
+        <div class="admin-page-actions">
+          <el-button type="primary" size="small" @click="handleCreate">+ 添加数据源</el-button>
+        </div>
+      </div>
+      <div class="table-scroll-wrap-sm">
+      <el-table :data="records" stripe v-loading="loading">
         <el-table-column prop="id" label="ID" width="60"></el-table-column>
         <el-table-column prop="memberId" label="成员ID" width="80"></el-table-column>
         <el-table-column prop="sourceType" label="类型" width="100">
@@ -41,10 +43,12 @@
             </el-dropdown>
           </template>
         </el-table-column>
-    </el-table>
-    </div>
-    <el-pagination
+      </el-table>
+      </div>
+      <el-pagination
         v-if="total > 0"
+        class="pagination-wrap"
+        :total="total"
         style="margin-top:16px;text-align:right"
         :total="total"
         :page.sync="page"