457 lines
14 KiB
Markdown
457 lines
14 KiB
Markdown
:::warning 特别提醒
|
||
官方精心制作本教程,目的在于方便用户快速掌握软件产品的使用和部署。通过此教程,刚入行的开发者也可以快速掌握并投入产品研发。本地部署时务必请耐心阅读文档操作。
|
||
:::
|
||
|
||
## 教程概述
|
||
|
||
本教程将带你从零开始,完成一个完整的后台管理系统的搭建和运行。整个过程分为以下几个步骤:
|
||
|
||
```
|
||
1. 环境准备:安装 Python、MySQL、Redis、Node.js 等基础软件。
|
||
2. 获取源码:从官方网站下载授权源码包并解压。
|
||
3. 后端启动:安装 Python 依赖、配置环境变量、初始化数据库、启动后端服务。
|
||
4. 前端启动:安装前端依赖、启动前端开发服务器。
|
||
5. 功能验证:登录系统,验证各功能模块是否正常。
|
||
6. 新增模块:以岗位管理为例,演示如何新增一个完整的业务模块。
|
||
```
|
||
|
||
## 第一步:环境准备
|
||
|
||
确保电脑上已安装以下软件:
|
||
|
||
| 软件 | 版本要求 | 用途 |
|
||
|------|----------|------|
|
||
| Python | 3.12+ | 后端运行环境 |
|
||
| MySQL | 8.0+ | 数据库 |
|
||
| Redis | 3.2+ | 缓存(验证码、JWT黑名单、限流) |
|
||
| Node.js | 22+ | 前端构建环境 |
|
||
| pnpm | 最新版 | 前端包管理器 |
|
||
| Git | 最新版 | 版本控制 |
|
||
|
||
:::tip 温馨提示
|
||
详细的安装步骤请参考 [环境准备](/zh/volume1/environment) 章节。
|
||
:::
|
||
|
||
## 第二步:获取源码
|
||
|
||
前往 [官方网站](https://www.djangoadmin.cn) 购买授权后,按以下步骤获取源码:
|
||
|
||
```
|
||
1. 登录官方网站,进入「个人中心」→「我的订单」页面。
|
||
2. 在订单列表中找到已购买的授权订单,点击「下载」按钮。
|
||
3. 下载的压缩包包含完整的前后端源码、数据库脚本及部署配置文件。
|
||
4. 将压缩包解压到本地开发目录(如 E:\Projects\ 或 ~/Projects/)。
|
||
```
|
||
|
||
```bash
|
||
# 进入项目目录(以实际解压路径为准)
|
||
cd djangoadmin
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
1. 源码包请务必从官方网站订单中心下载,确保获取的是正版授权的最新版本。
|
||
2. 授权有效期内可无限次下载最新版本,版本更新后可重新下载获取最新源码。
|
||
3. 解压后请先阅读根目录下的 `README.md` 和 `CHANGELOG.md` 了解版本更新内容。
|
||
:::
|
||
|
||
## 第三步:后端启动
|
||
|
||
### 3.1 安装 Python 依赖
|
||
|
||
```bash
|
||
# 创建虚拟环境(推荐)
|
||
python -m venv venv
|
||
|
||
# 激活虚拟环境
|
||
# Windows
|
||
venv\Scripts\activate
|
||
# Linux/macOS
|
||
source venv/bin/activate
|
||
|
||
# 安装依赖
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 3.2 配置环境变量
|
||
|
||
```bash
|
||
# 复制环境变量模板
|
||
cp .env.example .env
|
||
```
|
||
|
||
编辑 `.env` 文件,配置数据库和 Redis 连接信息:
|
||
|
||
```bash
|
||
# 数据库配置
|
||
DB_HOST=127.0.0.1
|
||
DB_PORT=3306
|
||
DB_DATABASE=djangoadmin.flask.elevue
|
||
DB_USERNAME=root
|
||
DB_PASSWORD=your_password
|
||
|
||
# Redis 配置
|
||
REDIS_HOST=127.0.0.1
|
||
REDIS_PORT=6379
|
||
REDIS_PASSWORD=your_redis_password
|
||
|
||
# JWT 密钥(至少32字节)
|
||
JWT_SALT=your_random_secret_key_at_least_32_bytes_long
|
||
```
|
||
|
||
:::danger
|
||
`JWT_SALT` 必须配置,留空时应用会拒绝启动。生成方式:
|
||
```bash
|
||
python -c "import secrets; print(secrets.token_urlsafe(48))"
|
||
```
|
||
:::
|
||
|
||
### 3.3 初始化数据库
|
||
|
||
**方式一:手动导入(推荐)**
|
||
|
||
```bash
|
||
# 1. 登录 MySQL,创建数据库
|
||
mysql -uroot -p
|
||
CREATE DATABASE `djangoadmin.flask.elevue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||
|
||
# 2. 导入数据库脚本(脚本位于 document/mysql/ 目录下)
|
||
mysql -uroot -p djangoadmin.flask.elevue < document/mysql/djangoadmin.flask.elevue.sql
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
项目支持 MySQL、PostgreSQL、SQL Server、SQLite、Oracle 等数据库,对应的 SQL 脚本分别存放在 `document/` 目录下的对应文件夹中(`mysql/`、`postgresql/`、`sqlserver/`、`sqlite/`、`oracle/`)。请根据你使用的数据库类型选择对应的脚本导入。详细的多数据库初始化步骤请参考 [数据库初始化](/zh/volume1/database) 章节。
|
||
:::
|
||
|
||
**方式二:脚本初始化(备选)**
|
||
|
||
```bash
|
||
# 自动完成建库、建表、导入种子数据
|
||
python scripts/init_db.py
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
以上命令是推荐的直接执行方式,适用于所有操作系统。文档中出现的 `make` 命令(如 `make db-init`)是 Linux / macOS 系统的便捷别名,Windows 用户直接使用对应的原始命令即可(如 `python scripts/init_db.py`)。
|
||
:::
|
||
|
||
初始化完成后,数据库中包含以下默认数据:
|
||
|
||
```
|
||
管理员账号:admin / 123456(超级管理员,ID=1,跳过权限校验)
|
||
默认角色:超级管理员角色
|
||
默认菜单:系统管理、内容管理、监控管理等菜单及权限节点
|
||
数据字典:系统内置字典数据
|
||
系统配置:系统默认配置项
|
||
```
|
||
|
||
### 3.4 启动后端服务
|
||
|
||
```bash
|
||
python app.py
|
||
```
|
||
|
||
启动成功后会看到:
|
||
|
||
```
|
||
* Running on http://127.0.0.1:8021
|
||
* Debug mode: on
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
后端默认运行在 `8021` 端口(可通过 `.env` 中 `FLASK_PORT` 修改)。
|
||
:::
|
||
|
||
## 第四步:前端启动
|
||
|
||
### 4.1 安装前端依赖
|
||
|
||
```bash
|
||
# 进入前端目录
|
||
cd ui
|
||
|
||
# 安装依赖
|
||
pnpm install
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
如果安装速度较慢,可配置国内镜像源:
|
||
```bash
|
||
pnpm config set registry https://registry.npmmirror.com
|
||
```
|
||
:::
|
||
|
||
### 4.2 启动前端开发服务器
|
||
|
||
```bash
|
||
pnpm dev
|
||
```
|
||
|
||
启动成功后会看到:
|
||
|
||
```
|
||
VITE v3.x.x ready in xxx ms
|
||
|
||
➜ Local: http://localhost:8001/
|
||
```
|
||
|
||
### 4.3 访问系统
|
||
|
||
打开浏览器访问 `http://localhost:8001`,使用默认账号登录:
|
||
|
||
```
|
||
账号:admin
|
||
密码:123456
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
前端默认运行在 `8001` 端口,后端默认 `8021` 端口。`vite.config.ts` 中配置了代理,前端请求 `/api/*` 路径时自动转发到后端。
|
||
:::
|
||
|
||
## 第五步:功能验证
|
||
|
||
登录成功后,可以验证以下核心功能:
|
||
|
||
```
|
||
1. 控制台:首页仪表盘,显示系统概况。
|
||
2. 用户管理:系统管理 → 用户管理,查看用户列表、新增、编辑、删除。
|
||
3. 角色管理:系统管理 → 角色管理,管理角色和权限分配。
|
||
4. 菜单管理:系统管理 → 菜单管理,管理菜单和权限节点。
|
||
5. 数据字典:数据管理 → 字典管理,管理系统字典数据。
|
||
6. 操作日志:系统管理 → 日志管理 → 操作日志,查看操作记录。
|
||
```
|
||
|
||
## 第六步:新增业务模块
|
||
|
||
以「岗位管理」为例,演示如何新增一个完整的 CRUD 模块。
|
||
|
||
### 6.1 后端开发
|
||
|
||
在 `src/modules/system/position/` 目录下创建以下文件:
|
||
|
||
**models.py** — 定义数据模型:
|
||
|
||
```python
|
||
from sqlalchemy import Column, String, Integer, text
|
||
from src.common.base_db import BaseDB
|
||
from src.common.base_model import BaseModel
|
||
from config.database import DB_PREFIX
|
||
|
||
|
||
class Position(BaseModel, BaseDB):
|
||
"""岗位模型类"""
|
||
__tablename__ = DB_PREFIX + "position"
|
||
__table_comment__ = "岗位表"
|
||
|
||
# 岗位名称
|
||
name = Column(String(255), nullable=False, index=True, comment="岗位名称")
|
||
# 岗位状态:1-在用 2-停用
|
||
status = Column(Integer, default=0, server_default=text('0'), index=True, comment="岗位状态:1-在用 2-停用")
|
||
# 岗位排序
|
||
sort = Column(Integer, default=0, server_default=text('0'), comment="岗位排序")
|
||
```
|
||
|
||
**schema.py** — 定义表单校验:
|
||
|
||
```python
|
||
from wtforms import StringField, IntegerField
|
||
from wtforms.validators import DataRequired, Length, NumberRange, Optional
|
||
|
||
from src.common.forms.base_form import BaseForm
|
||
from src.modules.system.position.repository import PositionRepository
|
||
|
||
|
||
class PositionForm(BaseForm):
|
||
"""岗位创建/编辑表单"""
|
||
name = StringField('岗位名称', validators=[
|
||
DataRequired(message='岗位名称不能为空'),
|
||
Length(max=150, message='岗位名称长度不得超过150个字符')
|
||
])
|
||
status = IntegerField('岗位状态', validators=[
|
||
DataRequired(message='岗位状态不能为空'),
|
||
NumberRange(min=1, max=2, message='岗位状态值在1~2之间')
|
||
])
|
||
sort = IntegerField('岗位排序', validators=[
|
||
Optional(),
|
||
NumberRange(min=0, max=99999, message='岗位排序值在0~99999之间')
|
||
])
|
||
|
||
def validate_name(self, field):
|
||
"""岗位名称唯一性校验"""
|
||
if not field.data:
|
||
return
|
||
current_id = self.id.data if self.id.data else None
|
||
if PositionRepository.exists_by({'name': field.data}, exclude_id=current_id):
|
||
raise ValidationError("岗位名称已存在")
|
||
|
||
|
||
class PositionStatusForm(BaseForm):
|
||
"""岗位状态更新表单"""
|
||
id = IntegerField('岗位ID', validators=[
|
||
DataRequired(message='岗位ID不能为空'),
|
||
NumberRange(min=1, message='岗位ID必须大于0')
|
||
])
|
||
status = IntegerField('岗位状态', validators=[
|
||
DataRequired(message='岗位状态不能为空'),
|
||
NumberRange(min=1, max=2, message='岗位状态值在1~2之间')
|
||
])
|
||
```
|
||
|
||
**repository.py** — 定义数据访问层:
|
||
|
||
```python
|
||
from src.common.base_repository import BaseRepository
|
||
from src.modules.system.position.models import Position
|
||
|
||
|
||
class PositionRepository(BaseRepository):
|
||
"""岗位数据仓储,继承 BaseRepository 获得通用 CRUD 能力"""
|
||
model = Position
|
||
|
||
@classmethod
|
||
def page(cls, params: dict):
|
||
"""岗位分页查询"""
|
||
return cls.find_page(
|
||
page=int(params.get('pageNo', 1)),
|
||
page_size=int(params.get('pageSize', 10)),
|
||
filters={'status': params.get('status')},
|
||
like_filters={'name': params.get('name')},
|
||
order_by='sort',
|
||
)
|
||
|
||
@classmethod
|
||
def list_enabled(cls, params=None):
|
||
"""查询启用的岗位列表"""
|
||
params = params or {}
|
||
return cls.find_list(
|
||
filters={'status': 1},
|
||
like_filters={'name': params.get('name')},
|
||
order_by='sort',
|
||
)
|
||
```
|
||
|
||
**service.py** — 定义业务逻辑层:
|
||
|
||
```python
|
||
from src.common.base_service import BaseService
|
||
from src.core.exceptions import BizError
|
||
from src.modules.system.position.schema import PositionForm, PositionStatusForm
|
||
from src.modules.system.position.repository import PositionRepository
|
||
from src.modules.system.user.repository import UserRepository
|
||
|
||
|
||
class PositionService(BaseService):
|
||
"""岗位服务类,继承 BaseService 获得标准 CRUD 能力"""
|
||
repository = PositionRepository
|
||
form = PositionForm
|
||
status_form = PositionStatusForm
|
||
model_name = "岗位"
|
||
|
||
@classmethod
|
||
def before_delete(cls, ids):
|
||
"""删除前校验:存在用户引用该岗位时禁止删除"""
|
||
for pid in ids:
|
||
if UserRepository.count_by({'position_id': pid}) > 0:
|
||
raise BizError(f"岗位ID {pid} 已被用户引用,无法删除")
|
||
|
||
|
||
# 模块级代理函数:保持 router 调用兼容
|
||
get_position_page = PositionService.get_page
|
||
get_position_detail = PositionService.get_detail
|
||
add_position = PositionService.add
|
||
update_position = PositionService.update
|
||
delete_positions = PositionService.remove
|
||
update_position_status = PositionService.update_status
|
||
get_position_list = PositionService.get_list
|
||
```
|
||
|
||
### 6.2 注册路由
|
||
|
||
在 `src/modules/system/position/router.py` 中创建 Blueprint 路由,然后在 `src/routes/v1.py` 中注册:
|
||
|
||
```python
|
||
# src/modules/system/position/router.py
|
||
from flask import Blueprint, request
|
||
|
||
from src.core.permission import check_permission
|
||
from src.modules.system.position import service as position
|
||
from src.common.utils.request import parse_request_body
|
||
from src.core import response as R
|
||
|
||
position_blue = Blueprint('position', __name__, url_prefix='/position')
|
||
|
||
|
||
@position_blue.route('/page', methods=["GET"])
|
||
@check_permission("sys:position:page")
|
||
def page():
|
||
"""查询岗位分页数据"""
|
||
return R.ok(data=position.get_position_page(request.args))
|
||
|
||
|
||
@position_blue.route('/add', methods=["POST"])
|
||
@check_permission("sys:position:add")
|
||
def add():
|
||
"""添加岗位"""
|
||
json_data, err = parse_request_body()
|
||
if err:
|
||
return R.failed(msg=err)
|
||
position.add_position(json_data)
|
||
return R.ok(msg="添加成功")
|
||
```
|
||
|
||
```python
|
||
# src/routes/v1.py
|
||
from src.modules.system.position.router import position_blue
|
||
|
||
BLUEPRINTS = [
|
||
position_blue,
|
||
# ... 其他模块
|
||
]
|
||
```
|
||
|
||
### 6.3 前端开发
|
||
|
||
在 `ui/src/api/system/position/` 中定义接口,在 `ui/src/views/system/position/` 中创建页面文件(index.vue、editModal.vue、columns.ts、querySchemas.ts)。
|
||
|
||
### 6.4 配置菜单权限
|
||
|
||
在系统管理 → 菜单管理中:
|
||
|
||
```
|
||
1. 新增菜单:岗位管理(路径:/system/position,组件:system/position/index)
|
||
2. 新增按钮:查看(sys:position:page)、新增(sys:position:add)、编辑(sys:position:update)、删除(sys:position:delete)
|
||
3. 在角色管理中为角色分配"岗位管理"菜单权限
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
详细的端到端教程请参考 [模块开发实战](/zh/volume2/overview) 章节。
|
||
:::
|
||
|
||
## 常见问题
|
||
|
||
在部署和使用过程中,可能会遇到以下常见问题:
|
||
|
||
```
|
||
1. 端口被占用:修改 .env 中的 FLASK_PORT 或终止占用端口的进程。
|
||
2. 数据库连接失败:检查 .env 中的数据库配置,确认 MySQL 服务已启动。
|
||
3. Redis 连接失败:检查 Redis 服务状态和密码配置。
|
||
4. JWT_SALT 未配置:使用 python -c "import secrets; print(secrets.token_urlsafe(48))" 生成。
|
||
5. pnpm install 失败:配置国内镜像 pnpm config set registry https://registry.npmmirror.com。
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
更多问题请参考 [常见问题FAQ](/zh/volume1/faq) 章节。
|
||
:::
|
||
|
||
## 总结
|
||
|
||
通过以上步骤,你已经完成了从零搭建一个完整的后台管理系统的全过程:
|
||
|
||
```
|
||
1. 环境准备:Python + MySQL + Redis + Node.js + pnpm
|
||
2. 后端启动:pip install → 配置 .env → 初始化数据库 → python app.py
|
||
3. 前端启动:pnpm install → pnpm dev
|
||
4. 功能验证:登录系统,验证各模块功能
|
||
5. 新增模块:models → schema → repository → service → router → 前端页面 → 菜单权限
|
||
```
|
||
|
||
整个搭建过程约 30 分钟即可完成。如果在操作过程中遇到问题,请查阅文档或在社区寻求帮助。
|