首页
/ 10分钟上手企业级微服务前端开发:Saber框架从搭建到实战全指南

10分钟上手企业级微服务前端开发:Saber框架从搭建到实战全指南

2026-02-04 04:20:18作者:宣聪麟

你还在为中后台系统开发效率低下而烦恼?还在重复编写CRUD代码浪费时间?本文将带你10分钟入门企业级微服务前端解决方案Saber,掌握基于JSON驱动的配置式开发模式,让你从繁琐的UI编码中解放出来,专注业务逻辑实现。读完本文你将获得:

  • 快速搭建Saber开发环境的完整步骤
  • 掌握JSON驱动开发模式的核心原理与实践方法
  • 学会二次封装组件的高级技巧
  • 理解权限控制、多语言等企业级特性实现方案
  • 获得一个可直接用于生产环境的中后台系统架构

一、Saber框架简介:企业级前端开发的新范式

Saber是SpringBlade微服务开发平台的前端框架之一,基于Vue.js和Element UI构建,专为企业级中后台系统设计。它通过对Avue、Element-UI等组件库的二次封装,实现了基于JSON驱动的配置式开发模式,极大提升了开发效率。

1.1 核心技术栈概览

技术框架 版本 作用
Vue.js 3.x 前端核心框架
Element Plus 最新 UI组件库
Avue 2.x 基于Element的二次封装组件库
Vue Router 4.x 路由管理
Vuex 4.x 状态管理
Axios 0.27+ HTTP客户端
Vite 3.x 构建工具

1.2 框架架构解析

Saber采用分层架构设计,各模块职责清晰,便于维护和扩展:

flowchart TD
    A[应用层] --> B[业务组件层]
    B --> C[通用组件层]
    C --> D[核心框架层]
    D --> E[基础设施层]
    
    subgraph 应用层
        A1[页面组件]
        A2[路由配置]
        A3[状态管理]
    end
    
    subgraph 业务组件层
        B1[权限组件]
        B2[表单组件]
        B3[表格组件]
    end
    
    subgraph 通用组件层
        C1[容器组件]
        C2[区块组件]
        C3[视频组件]
    end
    
    subgraph 核心框架层
        D1[JSON驱动引擎]
        D2[组件二次封装]
        D3[权限控制]
    end
    
    subgraph 基础设施层
        E1[HTTP客户端]
        E2[工具函数]
        E3[错误处理]
    end

二、环境搭建:从零开始的Saber开发之旅

2.1 准备工作

在开始前,请确保你的开发环境满足以下要求:

  • Node.js 18.x+
  • npm 8.x+ 或 yarn 1.22+
  • Git

2.2 获取源代码

# 克隆仓库
git clone https://gitcode.com/bladex/Saber.git
cd Saber

# 安装依赖
npm install
# 或
yarn install

2.3 启动开发服务器

# 开发环境
npm run dev
# 或
yarn dev

# 生产环境构建
npm run build
# 或
yarn build

启动成功后,访问 http://localhost:3000 即可看到Saber的登录界面。

2.4 项目目录结构解析

Saber/
├── public/           # 静态资源
├── src/              # 源代码
│   ├── api/          # API请求
│   ├── components/   # 组件
│   ├── config/       # 配置文件
│   ├── lang/         # 国际化
│   ├── router/       # 路由
│   ├── store/        # 状态管理
│   ├── styles/       # 样式
│   ├── utils/        # 工具函数
│   ├── views/        # 页面视图
│   ├── App.vue       # 应用入口
│   └── main.js       # 入口文件
├── vite.config.mjs   # Vite配置
└── package.json      # 项目依赖

三、核心特性实战:JSON驱动开发详解

3.1 JSON驱动开发模式

Saber最强大的特性之一就是JSON驱动开发,通过配置JSON即可生成复杂的表单和表格,大幅减少重复代码。

3.1.1 表格组件示例

<template>
  <basic-container>
    <avue-crud
      :option="tableOption"
      :data="tableData"
      @on-load="handleLoad"
      @on-save="handleSave"
      @on-delete="handleDelete"
    ></avue-crud>
  </basic-container>
</template>

<script setup>
const tableOption = {
  border: true,
  index: true,
  indexLabel: '序号',
  stripe: true,
  menuAlign: 'center',
  align: 'center',
  searchShow: true,
  addBtn: true,
  editBtn: true,
  delBtn: true,
  column: [
    {
      label: '用户名',
      prop: 'username',
      search: true,
      rules: [
        { required: true, message: '请输入用户名', trigger: 'blur' }
      ]
    },
    {
      label: '邮箱',
      prop: 'email',
      type: 'email',
      rules: [
        { required: true, message: '请输入邮箱', trigger: 'blur' },
        { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
      ]
    },
    {
      label: '状态',
      prop: 'status',
      type: 'select',
      dicData: [
        { label: '启用', value: 1 },
        { label: '禁用', value: 0 }
      ],
      search: true
    },
    {
      label: '创建时间',
      prop: 'createTime',
      type: 'datetime',
      format: 'YYYY-MM-DD HH:mm:ss',
      editDisplay: false,
      addDisplay: false
    }
  ]
}

const tableData = ref([])

// 加载数据
const handleLoad = () => {
  // 实际项目中这里会调用API获取数据
  tableData.value = [
    {
      id: 1,
      username: 'admin',
      email: 'admin@example.com',
      status: 1,
      createTime: '2023-01-01 12:00:00'
    }
  ]
}

// 保存数据
const handleSave = (row) => {
  // 保存逻辑
}

// 删除数据
const handleDelete = (row) => {
  // 删除逻辑
}
</script>

3.1.2 JSON配置核心属性

属性 类型 描述
border Boolean 是否显示边框
index Boolean 是否显示序号
stripe Boolean 是否显示斑马纹
menuAlign String 操作栏对齐方式
align String 内容对齐方式
searchShow Boolean 是否显示搜索栏
addBtn Boolean 是否显示添加按钮
editBtn Boolean 是否显示编辑按钮
delBtn Boolean 是否显示删除按钮
column Array 列配置

3.2 二次封装组件实战

Saber提供了基础组件如basic-containerbasic-block,便于快速构建页面布局:

<template>
  <basic-container>
    <basic-block title="用户管理" icon="User">
      <!-- 表格组件 -->
      <avue-crud :option="tableOption"></avue-crud>
    </basic-block>
  </basic-container>
</template>

<script setup>
import basicContainer from '@/components/basic-container/main.vue'
import basicBlock from '@/components/basic-block/main.vue'
</script>

三、核心功能实现:企业级应用的关键技术点

3.1 权限控制

Saber的权限控制基于Vue Router的导航守卫实现,在src/permission.js中配置:

import router from './router'
import store from './store'
import { getToken } from '@/utils/auth'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

const whiteList = ['/login', '/auth-redirect']

router.beforeEach(async(to, from, next) => {
  NProgress.start()
  
  // 判断是否有token
  if (getToken()) {
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else {
      // 判断是否已加载用户信息
      if (store.getters.roles.length === 0) {
        try {
          // 获取用户信息
          await store.dispatch('GetInfo')
          // 动态生成路由
          const accessRoutes = await store.dispatch('GenerateRoutes', store.getters.roles)
          router.addRoutes(accessRoutes)
          next({ ...to, replace: true })
        } catch (error) {
          // 清除token并重定向到登录页
          await store.dispatch('FedLogOut')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      } else {
        next()
      }
    }
  } else {
    // 没有token
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

3.2 多语言支持

Saber使用vue-i18n实现多语言支持,在src/lang/index.js中配置:

import { createI18n } from 'vue-i18n'
import { getLanguage } from '@/utils/cookies'
import elementEnLocale from 'element-plus/lib/locale/lang/en'
import elementZhLocale from 'element-plus/lib/locale/lang/zh-cn'
import elementJaLocale from 'element-plus/lib/locale/lang/ja'
import enLocale from './en'
import zhLocale from './zh'
import jaLocale from './ja'

const messages = {
  en: {
    ...enLocale,
    ...elementEnLocale
  },
  zh: {
    ...zhLocale,
    ...elementZhLocale
  },
  ja: {
    ...jaLocale,
    ...elementJaLocale
  }
}

export const getLocale = () => {
  const cookieLanguage = getLanguage()
  if (cookieLanguage) {
    return cookieLanguage
  }
  
  // 默认语言
  const language = navigator.language.toLowerCase()
  const locales = Object.keys(messages)
  for (const locale of locales) {
    if (language.indexOf(locale) > -1) {
      return locale
    }
  }
  return 'zh'
}

const i18n = createI18n({
  locale: getLocale(),
  fallbackLocale: 'zh',
  messages
})

export default i18n

3.3 HTTP请求封装

Saber对Axios进行了二次封装,实现了请求/响应拦截、错误处理等功能:

import axios from 'axios'
import store from '@/store/'
import router from '@/router/'
import { getToken } from 'utils/auth'
import { ElMessage } from 'element-plus'
import website from '@/config/website'
import NProgress from 'nprogress'

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    NProgress.start()
    if (getToken()) {
      config.headers[website.Authorization] = 'Bearer ' + getToken()
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    NProgress.done()
    const res = response.data
    
    if (res.code !== 200) {
      ElMessage({
        message: res.msg || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      
      // 401: 未授权
      if (res.code === 401) {
        store.dispatch('FedLogOut').then(() => {
          router.push('/login')
        })
      }
      return Promise.reject(new Error(res.msg || 'Error'))
    } else {
      return res
    }
  },
  error => {
    NProgress.done()
    ElMessage({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

四、项目实战:构建企业级用户管理系统

4.1 数据模型设计

用户管理模块的数据模型如下:

classDiagram
    class User {
        +id: Number
        +username: String
        +password: String
        +name: String
        +email: String
        +phone: String
        +status: Number
        +createTime: Date
        +updateTime: Date
        +roles: Array
    }
    
    class Role {
        +id: Number
        +name: String
        +code: String
        +description: String
    }
    
    User "1" -- "*" Role : has many

4.2 页面实现

用户管理页面采用JSON驱动的方式实现,核心代码如下:

<template>
  <basic-container>
    <avue-crud
      :option="option"
      :api="api"
      :page.sync="page"
      @on-load="onLoad"
      @on-save="onSave"
      @on-update="onUpdate"
      @on-delete="onDelete"
    ></avue-crud>
  </basic-container>
</template>

<script>
export default {
  data() {
    return {
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      option: {
        index: true,
        indexLabel: '序号',
        border: true,
        stripe: true,
        menuAlign: 'center',
        align: 'center',
        searchShow: true,
        searchMenuSpan: 6,
        addBtn: true,
        editBtn: true,
        delBtn: true,
        viewBtn: true,
        column: [
          {
            label: '用户名',
            prop: 'username',
            search: true,
            rules: [
              { required: true, message: '请输入用户名', trigger: 'blur' },
              { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
            ]
          },
          {
            label: '姓名',
            prop: 'name',
            search: true,
            rules: [
              { required: true, message: '请输入姓名', trigger: 'blur' }
            ]
          },
          {
            label: '邮箱',
            prop: 'email',
            type: 'email',
            rules: [
              { required: true, message: '请输入邮箱', trigger: 'blur' },
              { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
            ]
          },
          {
            label: '手机',
            prop: 'phone',
            rules: [
              { required: true, message: '请输入手机号', trigger: 'blur' },
              { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
            ]
          },
          {
            label: '状态',
            prop: 'status',
            type: 'select',
            dicData: [
              { label: '启用', value: 1 },
              { label: '禁用', value: 0 }
            ],
            search: true
          },
          {
            label: '创建时间',
            prop: 'createTime',
            type: 'datetime',
            format: 'YYYY-MM-DD HH:mm:ss',
            editDisplay: false,
            addDisplay: false
          }
        ]
      },
      api: {
        list: '/api/user/list',
        add: '/api/user/add',
        update: '/api/user/update',
        del: '/api/user/delete'
      }
    }
  },
  methods: {
    onLoad(data) {
      this.page.total = data.total
    },
    onSave(form, done) {
      this.$http.post(this.api.add, form).then(res => {
        if (res.code === 200) {
          this.$message.success('添加成功')
          done()
        }
      })
    },
    onUpdate(form, done) {
      this.$http.post(this.api.update, form).then(res => {
        if (res.code === 200) {
          this.$message.success('修改成功')
          done()
        }
      })
    },
    onDelete(ids) {
      this.$confirm('确定要删除选中的记录吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$http.post(this.api.del, { ids: ids.join(',') }).then(res => {
          if (res.code === 200) {
            this.$message.success('删除成功')
            this.$refs.crud.refresh()
          }
        })
      })
    }
  }
}
</script>

4.3 权限控制实现

用户管理页面的权限控制基于角色实现,不同角色拥有不同的操作权限:

// src/store/modules/user.js
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'

const getDefaultState = () => {
  return {
    token: getToken(),
    name: '',
    avatar: '',
    roles: []
  }
}

const state = getDefaultState()

const mutations = {
  RESET_STATE: (state) => {
    Object.assign(state, getDefaultState())
  },
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  }
}

const actions = {
  // user login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          return reject('Verification failed, please Login again.')
        }

        const { name, avatar, roles } = data

        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_ROLES', roles)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

  // user logout
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      removeToken() // must remove  token  first
      commit('RESET_STATE')
      resolve()
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

五、进阶技巧:提升开发效率的最佳实践

5.1 工具函数封装

Saber提供了丰富的工具函数,位于src/utils/目录下,如auth.jsutil.js等:

// src/utils/util.js
/**
 * 获取屏幕宽度类型
 */
export const getScreen = () => {
  const width = window.innerWidth
  if (width < 768) {
    return 'xs'
  } else if (width < 992) {
    return 'sm'
  } else if (width < 1200) {
    return 'md'
  } else if (width < 1920) {
    return 'lg'
  } else {
    return 'xl'
  }
}

/**
 * 防抖函数
 */
export const debounce = (func, wait, immediate) => {
  let timeout, args, context, timestamp, result

  const later = function() {
    const last = +new Date() - timestamp

    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

5.2 全局状态管理

Saber使用Vuex进行状态管理,将状态分为多个模块:

// src/store/index.js
import { createStore } from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
import tags from './modules/tags'
import logs from './modules/logs'

export default createStore({
  modules: {
    app,
    settings,
    user,
    tags,
    logs
  },
  getters
})

5.3 自定义主题

Saber支持自定义主题,通过修改src/styles/variables.scss文件:

// 主题色
$primary-color: #1890ff;
$success-color: #52c41a;
$warning-color: #faad14;
$error-color: #f5222d;
$info-color: #1890ff;

// 中性色
$text-color: rgba(0, 0, 0, 0.85);
$text-color-secondary: rgba(0, 0, 0, 0.45);
$text-color-placeholder: rgba(0, 0, 0, 0.25);
$background-color: #f5f5f5;
$background-color-light: #ffffff;
$border-color: #e8e8e8;
$border-color-light: #f0f0f0;

六、部署与优化:从开发到生产的完整流程

6.1 构建优化

Saber使用Vite作为构建工具,可通过以下配置优化构建性能:

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'components': path.resolve(__dirname, 'src/components'),
      'styles': path.resolve(__dirname, 'src/styles')
    }
  },
  build: {
    target: 'es2015',
    outDir: 'dist',
    assetsDir: 'assets',
    sourcemap: false,
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    },
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]',
        manualChunks: {
          'element-plus': ['element-plus'],
          'avue': ['@smallwei/avue'],
          'vue': ['vue', 'vue-router', 'vuex']
        }
      }
    }
  }
})

6.2 Docker部署

Saber提供了Docker部署配置,位于src/docker/Dockerfile

FROM nginx:alpine

WORKDIR /usr/share/nginx/html

COPY dist/ .

COPY src/docker/nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

构建Docker镜像:

# 构建前端资源
npm run build

# 构建Docker镜像
docker build -t saber:latest -f src/docker/Dockerfile .

# 运行Docker容器
docker run -d -p 80:80 --name saber saber:latest

七、总结与展望

通过本文的介绍,我们了解了Saber框架的核心特性和使用方法,从环境搭建到实际开发,再到部署优化,全方位展示了如何使用Saber快速构建企业级中后台系统。Saber的JSON驱动开发模式极大提升了开发效率,丰富的企业级特性如权限控制、多语言支持等,使其成为构建中后台系统的理想选择。

随着前端技术的不断发展,Saber也在持续演进,未来将支持更多新特性,如:

  1. 基于Vue 3的Composition API重构
  2. 支持TypeScript
  3. 微前端架构支持
  4. 低代码平台集成

无论你是前端初学者还是资深开发者,Saber都能帮助你快速构建高质量的企业级应用。现在就开始你的Saber之旅吧!

七、收藏与关注

如果本文对你有所帮助,请点赞、收藏、关注三连,获取更多前端开发优质内容!下期我们将带来Saber高级特性实战,敬请期待!

登录后查看全文
热门项目推荐
相关项目推荐