Files
medical-mall/docs/admin/CRMEB_UVUE_MIGRATION_GUIDE.md
2026-02-02 20:07:37 +08:00

27 KiB
Raw Blame History

CRMEB 页面设计规范与 Uni-App-X UVue 复刻指南

📋 目录

  1. CRMEB 项目架构分析
  2. 页面布局模式
  3. 样式系统设计
  4. 组件设计规范
  5. 工程化配置
  6. UVue 复刻方案
  7. 迁移检查清单

CRMEB 项目架构分析

1. 项目结构概览

CRMEB/template/admin/
├── src/
│   ├── layout/              # 布局系统
│   │   ├── index.vue        # 主布局容器(支持多种布局模式)
│   │   ├── main/            # 主要布局模式
│   │   │   ├── defaults.vue       # 默认布局
│   │   │   ├── classic.vue        # 经典布局
│   │   │   ├── transverse.vue     # 横向布局
│   │   │   └── columns.vue        # 分栏布局
│   │   ├── navBars/         # 导航栏系统
│   │   │   ├── breadcrumb/  # 面包屑
│   │   │   └── tagsView/    # 标签页
│   │   ├── navMenu/         # 侧边栏菜单
│   │   ├── footer/          # 页脚
│   │   └── component/       # 布局相关组件
│   ├── components/          # 全局可复用组件60+
│   │   ├── cards/           # 卡片组件
│   │   ├── from/            # 表单相关
│   │   ├── searchFrom/      # 搜索表单
│   │   └── ...
│   ├── pages/               # 页面模块16个大类
│   │   ├── account/         # 账户管理
│   │   ├── agent/           # 代理管理
│   │   ├── app/             # APP管理
│   │   ├── cms/             # CMS内容
│   │   ├── finance/         # 财务
│   │   ├── order/           # 订单
│   │   ├── product/         # 商品
│   │   ├── system/          # 系统设置
│   │   ├── user/            # 用户管理
│   │   └── ...
│   ├── styles/              # 全局样式
│   ├── router/              # 路由配置
│   ├── store/               # 状态管理Vuex
│   ├── utils/               # 工具函数
│   └── ...
├── package.json             # 项目依赖Vue 2
├── vue.config.js            # Webpack 配置
├── .prettierrc.js           # 代码格式化规则
└── babel.config.js          # Babel 配置

2. 核心设计特点

2.1 多布局支持

CRMEB 支持 4 种布局模式:

  • Defaults: 侧边栏 + 顶部菜单 + 内容区
  • Classic: 经典布局(左菜单 + 内容)
  • Transverse: 顶部菜单 + 内容
  • Columns: 三栏布局(侧菜单 + 侧栏 + 内容)

2.2 标签页系统

  • 每个打开的页面都生成一个标签
  • 支持标签页关闭、固定、刷新
  • 与路由历史联动

2.3 面包屑导航

  • 动态生成,根据路由元信息
  • 支持多级导航回溯

2.4 响应式设计

  • 自动监听窗口大小
  • < 1000px 时自动切换移动端布局
  • 侧边栏自动收起

页面布局模式

CRMEB 的四种布局

模式 1: Defaults默认布局 - 最常用)

┌─────────────────────────────────────────┐
│  Logo  │  Breadcrumb  │  Tags  │  User  │ ← NavBars
├─────────┼─────────────────────────────────┤
│ Menu    │                                 │
│         │  Content Area                   │
│         │  (Page Components)              │
│         │                                 │
├─────────┴─────────────────────────────────┤
│  Footer                                   │
└─────────────────────────────────────────┘

特点:

  • 左侧固定菜单栏
  • 顶部面包屑 + 标签页
  • 主内容区占据剩余空间

模式 2: Classic经典布局

┌─────────────────────────────────────────┐
│ Logo │ Breadcrumb │ Tags │ User Settings │ ← NavBars
├──────┴─────────────────────────────────────┤
│ Menu │  Content Area                      │
│      │  (Page Components)                 │
│      │                                    │
├──────┴─────────────────────────────────────┤
│ Footer                                     │
└─────────────────────────────────────────────┘

模式 3: Transverse横向菜单

┌────────────────────────────────────────┐
│ Logo │ Menu 1 │ Menu 2 │ ... │ Settings│ ← Top Menu
├────────────────────────────────────────┤
│ Breadcrumb │ Tags │ Actions            │
├────────────────────────────────────────┤
│                                        │
│  Content Area                          │
│  (Page Components)                     │
│                                        │
└────────────────────────────────────────┘

模式 4: Columns三栏布局

┌──────────────────────────────────────────┐
│  NavBars (Breadcrumb + Tags)             │
├─────────┬──────────┬──────────────────────┤
│ Menu    │ SubMenu  │  Content Area        │
│         │          │  (Page Components)   │
│         │          │                      │
└─────────┴──────────┴──────────────────────┘

样式系统设计

1. 全局样式架构

styles/
├── common.scss          # 通用样式重置基础类名
├── variables.scss       # CSS 变量主题颜色
├── animate.scss         # 动画库
├── element-ui.scss      # Element UI 主题覆盖
└── index.scss           # 主入口文件

2. 颜色系统

CRMEB 使用标准设计系统颜色:

  • 主颜色: #1890ff(蓝色)
  • 成功: #52c41a(绿色)
  • 警告: #faad14(黄色)
  • 错误: #ff4d4f(红色)
  • 边框: #d9d9d9(灰色)
  • 文字: #000000 / #666666 / #999999

3. 间距系统

$space-xs: 4px;
$space-sm: 8px;
$space: 12px;
$space-md: 16px;
$space-lg: 24px;
$space-xl: 32px;

4. 圆角系统

$radius-xs: 2px;
$radius-sm: 4px;
$radius: 6px;
$radius-lg: 8px;
$radius-xl: 12px;

5. 阴影系统

$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.06);
$shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.15);

组件设计规范

1. 组件命名规范

常用组件类型:
- Cards/           # 卡片展示(数据统计卡、信息卡)
- Form/            # 表单相关(表单控件、表单验证)
- List/            # 列表显示(表格、数据列表)
- Modal/           # 模态框(确认框、详情框)
- Table/           # 表格组件(支持排序、分页、筛选)
- Upload/          # 上传组件(图片、视频、文件)
- Search/          # 搜索组件(高级搜索、快速搜索)

2. 常用组件库

CRMEB 使用 Element UI 作为基础组件库:

  • el-button - 按钮
  • el-input - 输入框
  • el-select - 选择器
  • el-table - 表格
  • el-form - 表单
  • el-dialog - 对话框
  • el-tree - 树形控件
  • el-pagination - 分页

3. 页面组件结构

<template>
  <div class="page-container">
    <!-- 页面标题 / 操作栏 -->
    <div class="page-header">
      <h1>{{ pageTitle }}</h1>
      <div class="page-actions">
        <el-button type="primary">新增</el-button>
        <el-button>导出</el-button>
      </div>
    </div>

    <!-- 搜索表单 -->
    <div class="search-container">
      <SearchForm @search="handleSearch" />
    </div>

    <!-- 列表 / 内容区 -->
    <div class="content-container">
      <el-table :data="tableData" />
    </div>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination @current-change="handlePageChange" />
    </div>
  </div>
</template>

<script>
export default {
  name: "PageName",
  components: {
    SearchForm: () => import("@/components/searchFrom/index"),
  },
  data() {
    return {
      pageTitle: "页面标题",
      tableData: [],
    };
  },
};
</script>

<style scoped lang="scss">
.page-container {
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;

  h1 {
    font-size: 20px;
    font-weight: 600;
  }
}

.search-container {
  margin-bottom: 20px;
}

.content-container {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  margin-bottom: 20px;
}

.pagination-container {
  display: flex;
  justify-content: flex-end;
}
</style>

工程化配置

1. 构建工具配置

vue.config.js (Webpack):

module.exports = {
  productionSourceMap: false,
  configureWebpack: {
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "./src"),
      },
    },
  },
  chainWebpack: (config) => {
    // 优化大文件分割
    config.optimization.splitChunks({
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "chunk-vendors",
          priority: 10,
        },
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    });
  },
};

2. 代码格式化配置

.prettierrc.js:

module.exports = {
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
  semi: true,
  singleQuote: true,
  trailingComma: "es5",
  bracketSpacing: true,
  arrowParens: "always",
};

3. ESLint 配置

.eslintrc.js:

module.exports = {
  root: true,
  env: {
    node: true,
    browser: true,
    es2021: true,
  },
  extends: ["plugin:vue/essential", "eslint:recommended"],
  parserOptions: {
    parser: "babel-eslint",
    ecmaVersion: 2020,
  },
  rules: {
    "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
  },
};

4. Babel 配置

babel.config.js:

module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"],
  plugins: [],
};

UVue 复刻方案

1. 布局系统复刻

1.1 AdminLayout 增强版

layouts/admin/AdminLayout.uvue - 支持多种布局:

<template>
  <view class="admin-layout" :class="layoutClass">
    <!-- 模式1: Defaults默认布局 -->
    <template v-if="layoutMode === 'defaults'">
      <AdminAside :collapsed="isCollapsed" @toggle="toggleCollapse" />
      <view class="admin-main-defaults">
        <AdminNavBar :breadcrumb="breadcrumb" />
        <AdminTagsView :tabs="tabs" />
        <view class="admin-content-defaults">
          <slot></slot>
        </view>
        <AdminFooter />
      </view>
    </template>

    <!-- 模式2: Classic经典布局 -->
    <template v-else-if="layoutMode === 'classic'">
      <view class="admin-sidebar-classic">
        <AdminAside :collapsed="isCollapsed" @toggle="toggleCollapse" />
      </view>
      <view class="admin-main-classic">
        <AdminNavBar />
        <view class="admin-content-classic">
          <slot></slot>
        </view>
      </view>
    </template>

    <!-- 模式3: Columns三栏布局 -->
    <template v-else-if="layoutMode === 'columns'">
      <AdminAside :collapsed="isCollapsed" @toggle="toggleCollapse" />
      <AdminSubSider :collapsed="isSubCollapsed" @toggle="toggleSubCollapse" />
      <view class="admin-main-columns">
        <AdminNavBar />
        <view class="admin-content-columns">
          <slot></slot>
        </view>
      </view>
    </template>
  </view>
</template>

<script setup lang="uts">
import { ref, computed, watch, onMounted, provide } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import AdminAside from './components/AdminAside.uvue'
import AdminSubSider from './components/AdminSubSider.uvue'
import AdminNavBar from './components/AdminNavBar.uvue'
import AdminTagsView from './components/AdminTagsView.uvue'
import AdminFooter from './components/AdminFooter.uvue'

// Props
interface AdminLayoutProps {
  currentPage: string
  layoutMode?: 'defaults' | 'classic' | 'columns'
}

const props = withDefaults(defineProps<AdminLayoutProps>(), {
  layoutMode: 'defaults'
})

// State
const isCollapsed = ref(false)
const isSubCollapsed = ref(false)
const tabs = ref([])
const breadcrumb = ref('')

// Computed
const layoutClass = computed(() => `layout-${props.layoutMode}`)

// Methods
const toggleCollapse = () => {
  isCollapsed.value = !isCollapsed.value
}

const toggleSubCollapse = () => {
  isSubCollapsed.value = !isSubCollapsed.value
}

// Provide to children
provide('layoutMode', props.layoutMode)
provide('isCollapsed', isCollapsed)
</script>

<style scoped lang="uts">
.admin-layout {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f5f5;
}

/* Defaults 布局样式 */
.layout-defaults {
  flex-direction: row;
}

.admin-main-defaults {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.admin-content-defaults {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

/* Classic 布局样式 */
.layout-classic {
  flex-direction: row;
}

.admin-sidebar-classic {
  width: 200px;
  height: 100vh;
  overflow: hidden;
}

.admin-main-classic {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.admin-content-classic {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

/* Columns 布局样式 */
.layout-columns {
  flex-direction: row;
}

.admin-main-columns {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.admin-content-columns {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}
</style>

2. 样式系统复刻

2.1 主样式文件

uni.scss - 全局 SCSS 变量:

// 颜色系统
$primary-color: #1890ff;
$success-color: #52c41a;
$warning-color: #faad14;
$error-color: #ff4d4f;
$info-color: #1890ff;

$text-primary: #000000;
$text-secondary: #666666;
$text-disabled: #999999;

$border-color: #d9d9d9;
$background-color: #f5f5f5;

// 间距系统
$space-xs: 4px;
$space-sm: 8px;
$space: 12px;
$space-md: 16px;
$space-lg: 24px;
$space-xl: 32px;

// 圆角系统
$radius-xs: 2px;
$radius-sm: 4px;
$radius: 6px;
$radius-lg: 8px;
$radius-xl: 12px;

// 阴影系统
$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.06);
$shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.15);

// 字体大小
$font-size-xs: 12px;
$font-size-sm: 13px;
$font-size: 14px;
$font-size-md: 16px;
$font-size-lg: 18px;
$font-size-xl: 20px;

// 行高
$line-height-xs: 1.2;
$line-height-sm: 1.4;
$line-height: 1.6;
$line-height-lg: 1.8;

// 过渡动画
$transition-duration: 0.3s;
$transition-timing: cubic-bezier(0.645, 0.045, 0.355, 1);

2.2 通用样式类

styles/common.scss - 常用工具类:

// 布局相关
.flex {
  display: flex;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.flex-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.flex-col {
  display: flex;
  flex-direction: column;
}

// 间距相关
.m-xs {
  margin: $space-xs;
}
.m-sm {
  margin: $space-sm;
}
.m {
  margin: $space;
}
.m-md {
  margin: $space-md;
}
.m-lg {
  margin: $space-lg;
}
.m-xl {
  margin: $space-xl;
}

.p-xs {
  padding: $space-xs;
}
.p-sm {
  padding: $space-sm;
}
.p {
  padding: $space;
}
.p-md {
  padding: $space-md;
}
.p-lg {
  padding: $space-lg;
}
.p-xl {
  padding: $space-xl;
}

// 文字相关
.text-center {
  text-align: center;
}
.text-left {
  text-align: left;
}
.text-right {
  text-align: right;
}

.text-primary {
  color: $text-primary;
}
.text-secondary {
  color: $text-secondary;
}
.text-disabled {
  color: $text-disabled;
}

.text-xs {
  font-size: $font-size-xs;
}
.text-sm {
  font-size: $font-size-sm;
}
.text {
  font-size: $font-size;
}
.text-md {
  font-size: $font-size-md;
}
.text-lg {
  font-size: $font-size-lg;
}

// 显示/隐藏
.hidden {
  display: none;
}
.block {
  display: block;
}
.inline-block {
  display: inline-block;
}

// 溢出处理
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.line-clamp-2 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

// 边框
.border {
  border: 1px solid $border-color;
}
.border-top {
  border-top: 1px solid $border-color;
}
.border-bottom {
  border-bottom: 1px solid $border-color;
}
.border-left {
  border-left: 1px solid $border-color;
}
.border-right {
  border-right: 1px solid $border-color;
}

// 圆角
.rounded {
  border-radius: $radius;
}
.rounded-sm {
  border-radius: $radius-sm;
}
.rounded-lg {
  border-radius: $radius-lg;
}

// 阴影
.shadow-sm {
  box-shadow: $shadow-sm;
}
.shadow {
  box-shadow: $shadow;
}
.shadow-lg {
  box-shadow: $shadow-lg;
}

// 背景色
.bg-white {
  background-color: #ffffff;
}
.bg-light {
  background-color: $background-color;
}
.bg-primary {
  background-color: $primary-color;
}

// 透明度
.opacity-50 {
  opacity: 0.5;
}
.opacity-75 {
  opacity: 0.75;
}

3. 页面模板复刻

3.1 标准列表页面

pages/mall/admin/template/ListPage.uvue

<template>
  <AdminLayout :currentPage="currentPage">
    <view class="list-page">
      <!-- 页面标题和操作栏 -->
      <view class="page-header flex-between">
        <text class="page-title">{{ pageTitle }}</text>
        <view class="page-actions">
          <button @click="handleAdd" class="btn btn-primary">{{ addButtonText }}</button>
          <button @click="handleExport" class="btn btn-default">导出</button>
        </view>
      </view>

      <!-- 搜索表单 -->
      <view class="search-form-container bg-white p-md rounded shadow-sm">
        <SearchForm :fields="searchFields" @search="handleSearch" />
      </view>

      <!-- 列表内容 -->
      <view class="list-container bg-white p-md rounded shadow-sm">
        <view class="list-toolbar flex-between mb-md">
          <text class="text-secondary">共 {{ total }} 条记录</text>
          <view class="list-tools">
            <button @click="handleRefresh" class="btn btn-sm">刷新</button>
            <button @click="handleDelete" class="btn btn-sm">删除</button>
          </view>
        </view>

        <view class="list-table">
          <table-view :data="listData" :columns="columns" @row-click="handleRowClick" />
        </view>
      </view>

      <!-- 分页 -->
      <view class="pagination-container flex-center mt-lg">
        <pagination
          :current="pagination.current"
          :pageSize="pagination.pageSize"
          :total="total"
          @change="handlePageChange"
        />
      </view>
    </view>
  </AdminLayout>
</template>

<script setup lang="uts">
import { ref, reactive } from 'vue'
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
import SearchForm from '@/layouts/admin/components/SearchForm.uvue'
import TableView from '@/components/TableView.uvue'
import Pagination from '@/components/Pagination.uvue'

// 页面配置
const currentPage = 'list-page'
const pageTitle = '数据列表'
const addButtonText = '新增'

// 数据状态
const listData = ref([])
const total = ref(0)

// 分页信息
const pagination = reactive({
  current: 1,
  pageSize: 20,
})

// 搜索字段配置
const searchFields = ref([
  { key: 'name', label: '名称', type: 'text', placeholder: '请输入名称' },
  { key: 'status', label: '状态', type: 'select', options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 },
  ]},
  { key: 'date', label: '日期', type: 'daterange' },
])

// 表格列配置
const columns = ref([
  { prop: 'id', label: 'ID', width: 60 },
  { prop: 'name', label: '名称', minWidth: 120 },
  { prop: 'status', label: '状态', width: 80, formatter: (row: any) => row.status ? '启用' : '禁用' },
  { prop: 'createTime', label: '创建时间', width: 160 },
  { label: '操作', width: 120, fixed: 'right', slots: ['actions'] },
])

// 方法
const handleSearch = (filters: any) => {
  pagination.current = 1
  fetchList(filters)
}

const handlePageChange = (page: number) => {
  pagination.current = page
  fetchList()
}

const handleAdd = () => {
  uni.navigateTo({ url: '/pages/mall/admin/list/add' })
}

const handleRefresh = () => {
  fetchList()
}

const handleDelete = () => {
  // 删除逻辑
}

const handleRowClick = (row: any) => {
  uni.navigateTo({ url: `/pages/mall/admin/list/edit?id=${row.id}` })
}

const handleExport = () => {
  // 导出逻辑
}

const fetchList = async (filters?: any) => {
  // API 请求逻辑
  // listData.value = response.data
  // total.value = response.total
}
</script>

<style scoped lang="scss">
.list-page {
  padding: 20px;
}

.page-header {
  margin-bottom: 20px;
}

.page-title {
  font-size: $font-size-lg;
  font-weight: 600;
  color: $text-primary;
}

.page-actions {
  display: flex;
  gap: 10px;
}

.search-form-container {
  margin-bottom: 20px;
}

.list-container {
  margin-bottom: 20px;
}

.list-toolbar {
  border-bottom: 1px solid $border-color;
  padding-bottom: 12px;
}

.list-tools {
  display: flex;
  gap: 10px;
}

.pagination-container {
  margin: 20px 0;
}

.btn {
  padding: 8px 16px;
  border: none;
  border-radius: $radius;
  font-size: $font-size;
  cursor: pointer;
  transition: all $transition-duration $transition-timing;
}

.btn-primary {
  background-color: $primary-color;
  color: #fff;
}

.btn-primary:active {
  opacity: 0.8;
}

.btn-default {
  background-color: $background-color;
  color: $text-primary;
  border: 1px solid $border-color;
}

.btn-sm {
  padding: 6px 12px;
  font-size: $font-size-sm;
}
</style>

3.2 表单页面

pages/mall/admin/template/FormPage.uvue

<template>
  <AdminLayout :currentPage="currentPage">
    <view class="form-page">
      <!-- 页面标题 -->
      <view class="page-header">
        <text class="page-title">{{ pageTitle }}</text>
      </view>

      <!-- 表单容器 -->
      <form-view
        ref="formRef"
        :model="formData"
        :fields="formFields"
        :loading="loading"
        @submit="handleSubmit"
      />
    </view>
  </AdminLayout>
</template>

<script setup lang="uts">
import { ref, reactive } from 'vue'
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
import FormView from '@/components/FormView.uvue'

const currentPage = 'form-page'
const pageTitle = '编辑数据'
const loading = ref(false)

const formData = reactive({
  name: '',
  description: '',
  status: 1,
  category: '',
  tags: [],
  attachments: [],
})

const formFields = ref([
  {
    key: 'name',
    label: '名称',
    type: 'text',
    required: true,
    placeholder: '请输入名称',
    rules: [{ required: true, message: '名称不能为空' }],
  },
  {
    key: 'description',
    label: '描述',
    type: 'textarea',
    placeholder: '请输入描述',
    rows: 4,
  },
  {
    key: 'category',
    label: '分类',
    type: 'select',
    required: true,
    options: [
      { label: '分类1', value: 1 },
      { label: '分类2', value: 2 },
    ],
  },
  {
    key: 'status',
    label: '状态',
    type: 'radio',
    options: [
      { label: '启用', value: 1 },
      { label: '禁用', value: 0 },
    ],
  },
  {
    key: 'tags',
    label: '标签',
    type: 'checkbox',
    options: [
      { label: '热销', value: 'hot' },
      { label: '新品', value: 'new' },
      { label: '推荐', value: 'recommend' },
    ],
  },
  {
    key: 'attachments',
    label: '附件',
    type: 'upload',
    multiple: true,
    accept: 'file',
  },
])

const handleSubmit = async (data: any) => {
  loading.value = true
  try {
    // API 提交逻辑
    uni.showToast({ title: '提交成功', icon: 'success' })
    setTimeout(() => {
      uni.navigateBack()
    }, 1500)
  } catch (error) {
    uni.showToast({ title: '提交失败', icon: 'error' })
  } finally {
    loading.value = false
  }
}
</script>

<style scoped lang="scss">
.form-page {
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.page-header {
  margin-bottom: 24px;
}

.page-title {
  font-size: $font-size-lg;
  font-weight: 600;
  color: $text-primary;
}
</style>

组件库清单

必须实现的组件

1. 基础组件

  • Button按钮
  • Input输入框
  • Select选择器
  • Checkbox复选框
  • Radio单选框
  • Switch开关
  • DatePicker日期选择器

2. 容器组件

  • Card卡片
  • Modal模态框
  • Drawer抽屉
  • Tabs标签页
  • Collapse折叠面板

3. 数据展示

  • Table表格
  • List列表
  • Pagination分页
  • Tree树形控件
  • Empty空状态

4. 表单组件

  • Form表单
  • Upload上传
  • SearchForm搜索表单
  • Filter高级筛选

5. 反馈组件

  • Message消息
  • Toast提示
  • Confirm确认框
  • Loading加载中

6. 导航组件

  • Menu菜单
  • Breadcrumb面包屑
  • Tabs标签
  • Pagination分页

迁移检查清单

Phase 1: 基础设施

  • 创建样式系统文件

    • uni.scss全局变量
    • styles/common.scss通用类
    • styles/animate.scss动画
  • 更新 AdminLayout 支持多布局

    • Defaults 布局
    • Classic 布局
    • Columns 布局
  • 配置工程化工具

    • .eslintrc 配置
    • .prettierrc 配置
    • tsconfig.json 优化

Phase 2: 核心组件

  • 实现基础 UI 组件库
  • 实现 FormView 表单组件
  • 实现 TableView 表格组件
  • 实现 SearchForm 搜索组件

Phase 3: 页面模板

  • 创建列表页面模板
  • 创建表单页面模板
  • 创建详情页面模板
  • 创建仪表板页面模板

Phase 4: 样式规范化

  • 统一所有页面的样式
  • 规范间距使用
  • 规范颜色使用
  • 规范排版样式

Phase 5: 文档完善

  • 编写组件使用文档
  • 编写样式规范文档
  • 编写页面开发指南
  • 维护变更日志

推荐阅读


文档维护者: AI Assistant
最后更新: 2026-01-31
版本: 1.0