【保姆级教程】30分钟从零搭建企业级SaaS管理平台:madong-Admin开源框架实战指南

【保姆级教程】30分钟从零搭建企业级SaaS管理平台:madong-Admin开源框架实战指南

【免费下载链接】madong-Admin后台管理框架-SaaS版本 基于Webman的权限管理系统 【免费下载链接】madong-Admin后台管理框架-SaaS版本 项目地址: https://gitcode.com/motion-code/madong

为什么选择madong-Admin?解决SaaS开发3大痛点

你是否还在为这些问题困扰?
✅ 多租户架构设计复杂,数据隔离方案难以落地
✅ 权限系统臃肿,RBAC配置与API鉴权耗费80%开发时间
✅ 前端组件复用率低,重复造轮子导致项目延期

本文将带你实现

  • 基于Webman构建高性能后端服务(接口响应<300ms)
  • 配置企业级多租户数据隔离方案
  • 实现细粒度RBAC权限控制(菜单/按钮/数据三级权限)
  • 部署开箱即用的管理系统前端(Ant Design Vue+TypeScript)

技术架构全景图:为什么这套组合拳碾压传统方案?

mermaid

性能对比:传统LAMP vs madong-Admin

指标传统LAMP架构madong-Admin提升倍数
并发处理能力500 req/s5000 req/s10x
内存占用80MB/进程15MB/进程5.3x
接口响应时间300-800ms10-150ms6x
代码开发效率3x

环境准备:3分钟配置开发环境

系统要求清单

mermaid

一键部署命令(Linux/MacOS)

# 克隆代码仓库
git clone https://gitcode.com/motion-code/madong.git
cd madong

# 后端环境配置
cd server
composer install --no-dev
cp .env.example .env
# 编辑数据库配置
vim .env 
php webman install

# 前端环境配置
cd ../web
pnpm install
pnpm dev

⚠️ Windows用户需执行:
cd server && php windows.php install
详细环境检查脚本见 server/scripts/check_env.php

后端核心配置:从0到1搭建多租户体系

1. 数据库设计:3种租户隔离方案对比

mermaid

2. 配置文件详解(server/.env)

# 多租户模式配置 (schema/database/shared)
TENANT_MODE=schema
# 数据库连接池配置
DB_POOL_SIZE=10
# Redis分布式锁
REDIS_LOCK_PREFIX=madong:lock:
# JWT密钥 (生产环境必须修改)
JWT_SECRET=your_unique_secret_key_here
# API请求频率限制
RATE_LIMIT_ENABLE=true
RATE_LIMIT_TIMES=60
RATE_LIMIT_SECONDS=60

3. 核心中间件工作流程

mermaid

前端极速开发:10分钟配置权限与路由

1. 项目结构解析

src/
├── api/           # API接口封装
├── components/    # 业务组件
├── layout/        # 布局组件
├── router/        # 路由配置
├── store/         # 状态管理
└── views/         # 页面视图

2. 权限控制实现(src/router/guard.ts)

// 路由守卫示例代码
import { createRouterGuard } from 'ant-design-vue-pro';
import { useAuthStore } from '@/store/modules/auth';

export function setupRouterGuard(router) {
  const authStore = useAuthStore();
  
  createRouterGuard(router, {
    async beforeEach(to, from, next) {
      // 1. 检查登录状态
      if (!authStore.token) {
        return next('/login');
      }
      
      // 2. 检查路由权限
      const hasPermission = await authStore.checkRoutePermission(to.path);
      if (!hasPermission) {
        return next('/403');
      }
      
      next();
    },
    // 按钮权限指令注册
    setupPermissionDirective(app) {
      app.directive('auth', {
        mounted(el, binding) {
          if (!authStore.hasButtonPermission(binding.value)) {
            el.parentElement?.removeChild(el);
          }
        }
      });
    }
  });
}

3. 多主题切换实现(src/store/modules/site-config.ts)

import { defineStore } from 'pinia';

export const useSiteConfigStore = defineStore('site-config', {
  state: () => ({
    theme: 'light',
    layout: 'side',
    themeColor: '#1890ff',
    // 更多配置...
  }),
  actions: {
    setTheme(theme: 'light' | 'dark') {
      this.theme = theme;
      document.documentElement.setAttribute('data-theme', theme);
      localStorage.setItem('site-theme', theme);
    },
    setThemeColor(color: string) {
      this.themeColor = color;
      // 动态修改Ant Design主题色
      document.documentElement.style.setProperty('--primary-color', color);
    }
  }
});

实战案例:企业级用户管理模块开发

1. 数据模型设计(server/app/common/model/User.php)

namespace app\common\model;

use core\abstracts\BaseModel;
use core\traits\HasTenant;

class User extends BaseModel
{
    use HasTenant; // 多租户特性Trait
    
    protected $table = 'users';
    
    // 数据权限范围定义
    protected $dataScope = [
        'dept' => true, // 部门数据权限
        'user' => true, // 用户自身数据权限
    ];
    
    // 字段类型转换
    protected $type = [
        'status' => 'integer',
        'role_ids' => 'array',
        'last_login_time' => 'datetime',
    ];
    
    // 关联角色
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'user_roles', 'user_id', 'role_id');
    }
}

2. API接口实现(server/app/admin/controller/UserController.php)

namespace app\admin\controller;

use app\common\model\User;
use core\abstracts\BaseController;
use support\Request;
use support\Response;

class UserController extends BaseController
{
    // 列表接口(支持分页/筛选/排序)
    public function index(Request $request): Response
    {
        $page = $request->get('page', 1);
        $limit = $request->get('limit', 20);
        $keyword = $request->get('keyword', '');
        
        $query = User::query();
        
        // 关键词搜索
        if ($keyword) {
            $query->where('username', 'like', "%{$keyword}%")
                  ->orWhere('nickname', 'like', "%{$keyword}%")
                  ->orWhere('mobile', 'like', "%{$keyword}%");
        }
        
        // 数据权限过滤(自动应用)
        $data = $query->paginate($limit, $page);
        
        return $this->success($data);
    }
    
    // 保存接口(支持新增/编辑)
    public function save(Request $request): Response
    {
        $id = $request->post('id');
        $data = $request->post();
        
        // 密码加密处理
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        } else {
            unset($data['password']); // 编辑时不修改密码
        }
        
        $result = User::updateOrCreate(['id' => $id], $data);
        
        return $this->success($result);
    }
}

3. 前端页面实现(src/views/system/user/index.vue)

<template>
  <BasicPage :title="t('menu.system.user')">
    <template #toolbar>
      <a-button type="primary" @click="handleAdd" v-auth="'system:user:add'">
        <template #icon><PlusOutlined /></template>
        {{ t('btn.add') }}
      </a-button>
    </template>
    
    <BasicTable 
      ref="tableRef" 
      :columns="columns" 
      :request="getUserList" 
      :row-key="(record) => record.id"
    >
      <template #action="{ record }">
        <TableAction 
          :actions="[
            { label: t('btn.edit'), onClick: () => handleEdit(record), auth: 'system:user:edit' },
            { label: t('btn.delete'), onClick: () => handleDelete(record), auth: 'system:user:delete', confirm: true }
          ]" 
        />
      </template>
    </BasicTable>
  </BasicPage>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import { BasicPage, BasicTable, TableAction } from '@/components/common';
import { getUserList } from '@/api/system/user';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const tableRef = ref<InstanceType<typeof BasicTable>>();

// 表格列定义
const columns = [
  { title: 'ID', dataIndex: 'id', width: 80 },
  { title: t('common.username'), dataIndex: 'username', width: 150 },
  { title: t('common.nickname'), dataIndex: 'nickname', width: 150 },
  { title: t('common.mobile'), dataIndex: 'mobile', width: 150 },
  { title: t('common.status'), dataIndex: 'status', width: 100, 
    customRender: ({ text }) => (
      <span>{text === 1 ? t('common.enable') : t('common.disable')}</span>
    )
  },
  { title: t('common.createTime'), dataIndex: 'created_at', width: 180 },
  { title: t('common.action'), width: 150, slots: { customRender: 'action' } },
];

// 新增用户
const handleAdd = () => {
  // 打开新增表单模态框逻辑
};

// 编辑用户
const handleEdit = (record) => {
  // 打开编辑表单模态框逻辑
};

// 删除用户
const handleDelete = async (record) => {
  // 执行删除API调用逻辑
};
</script>

部署与性能优化:从开发到生产环境

1. 生产环境构建命令

# 后端优化
cd server
composer install --no-dev -o
php webman optimize:autoload
php webman cache:clear

# 前端构建
cd ../web
pnpm build
# 构建产物在 web/dist 目录

2. 性能优化清单

优化项实施方法性能提升
数据库索引优化为租户ID/用户ID添加复合索引300%
Redis缓存热点数据用户权限/字典数据缓存500%
接口数据压缩启用gzip压缩60%
静态资源CDN配置七牛云/阿里云OSS80%
前端路由懒加载按模块拆分路由组件40%

3. 容器化部署(docker-compose.yml)

version: '3'
services:
  webman:
    build: ./server
    ports:
      - "8787:8787"
    volumes:
      - ./server:/app
      - ./server/runtime:/app/runtime
    environment:
      - APP_ENV=production
      - DB_HOST=mysql
    depends_on:
      - mysql
      - redis
  
  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=madong
    volumes:
      - mysql_data:/var/lib/mysql
  
  redis:
    image: redis:4.0
    volumes:
      - redis_data:/data

volumes:
  mysql_data:
  redis_data:

进阶开发指南:核心功能扩展

1. 自定义权限策略(Casbin模型)

# server/config/core/casbin/model.conf
[request_definition]
r = sub, obj, act, ten

[policy_definition]
p = sub, obj, act, ten, eft

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))

[matchers]
m = g(r.sub, p.sub, r.ten) && keyMatch2(r.obj, p.obj) && r.act == p.act && r.ten == p.ten

2. 任务调度示例(定时清理日志)

// server/app/admin/command/CleanLog.php
namespace app\admin\command;

use support\Command;
use app\common\model\OperateLog;
use Workerman\Crontab\Crontab;

class CleanLog extends Command
{
    protected $name = 'clean:log';
    
    public function configure()
    {
        $this->setDescription('Clean up operation logs');
    }
    
    public function handle()
    {
        // 每天凌晨3点执行
        new Crontab('0 3 * * *', function(){
            $expireDay = config('app.log_expire_day', 30);
            $time = date('Y-m-d H:i:s', strtotime("-{$expireDay} days"));
            OperateLog::where('created_at', '<', $time)->delete();
        });
    }
}

总结与资源获取

本文关键成果

  • ✅ 掌握基于Webman的高性能后端开发
  • ✅ 实现企业级多租户架构设计
  • ✅ 构建细粒度RBAC权限系统
  • ✅ 部署生产级SaaS管理平台

官方资源

  • 完整文档:https://madong.tech/kbase/doc?name=md
  • 演示系统:https://admin.madong.tech(账号:admin,密码:123456)
  • 源码仓库:https://gitcode.com/motion-code/madong

下期预告:微服务改造指南——从单体应用到分布式架构的平滑过渡

生产环境安全提示

  1. 必须修改默认JWT密钥(.env文件)
  2. 开启HTTPS加密传输
  3. 定期备份数据库(推荐使用xtrabackup)
  4. 限制服务器SSH登录IP

【免费下载链接】madong-Admin后台管理框架-SaaS版本 基于Webman的权限管理系统 【免费下载链接】madong-Admin后台管理框架-SaaS版本 项目地址: https://gitcode.com/motion-code/madong

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值