diff --git a/ install b/ install
new file mode 100644
index 0000000..e69de29
diff --git a/docs/assets/2.jpg b/docs/assets/2.jpg
deleted file mode 100644
index 8673684..0000000
Binary files a/docs/assets/2.jpg and /dev/null differ
diff --git a/docs/assets/3.jpg b/docs/assets/3.jpg
deleted file mode 100644
index 9491d3e..0000000
Binary files a/docs/assets/3.jpg and /dev/null differ
diff --git a/docs/assets/4.jpg b/docs/assets/4.jpg
deleted file mode 100644
index 3c0aba0..0000000
Binary files a/docs/assets/4.jpg and /dev/null differ
diff --git a/docs/assets/5.jpg b/docs/assets/5.jpg
deleted file mode 100644
index 9e64446..0000000
Binary files a/docs/assets/5.jpg and /dev/null differ
diff --git a/docs/assets/6.jpg b/docs/assets/6.jpg
deleted file mode 100644
index 98a81ef..0000000
Binary files a/docs/assets/6.jpg and /dev/null differ
diff --git a/docs/assets/1.jpg b/docs/assets/官网地址.jpg
similarity index 100%
rename from docs/assets/1.jpg
rename to docs/assets/官网地址.jpg
diff --git a/docs/assets/源码仓库.jpg b/docs/assets/源码仓库.jpg
new file mode 100644
index 0000000..6d06c37
Binary files /dev/null and b/docs/assets/源码仓库.jpg differ
diff --git a/docs/assets/界面演示.jpeg b/docs/assets/界面演示.jpeg
new file mode 100644
index 0000000..f66f1b1
Binary files /dev/null and b/docs/assets/界面演示.jpeg differ
diff --git a/docs/detail.md b/docs/detail.md
index 5710ca2..7d60398 100644
--- a/docs/detail.md
+++ b/docs/detail.md
@@ -1,140 +1,44 @@
-### 权限管理 :id=authorize
+## 项目介绍 :id=start
-使用装饰器 @authorize时需要注意,该装饰器需要写在 @app.route 之后
+欢迎阅读 Pear Admin Flask 的开发文档!Pear Admin Flask 是一个基于 Flask 的后台管理系统,拥抱应用广泛的 Python 语言,通过使用本系统,即可快速构建你的功能业务。
-```python
-@authorize(power: str, log: bool)
-```
+项目旨在为 Python 开发者提供一个后台管理系统的模板,成为您构建信息管理系统、物联网后台等应用时灵活、简单的工具。
-第一个参数为权限 code
+同时,Pear Admin Flask 项目也是一个对于 Python 初学者友好的项目。此项目处于开发初期,欢迎各位 Python 爱好者加入到 Pear Admin Flask 项目建设中来。如果您在使用此项目的过程中,发现项目代码存在问题,请在 Gitee 上提交 PR ,一起开源共建!
-第二个参数为是否生成日志
+接下来,我们将会为您详细介绍该项目搭建方法与开发架构。
-```python
-# 例如
-@authorize("admin:power:remove", log=True)
-```
+> 如果对项目有不理解的地方欢迎加入我们的讨论群。
-在前端中,例如增加,删除按钮,对于没有编辑权限的用户不显示的话,可以使用
+
- `{% **if** authorize("admin:user:edit") %}`
+> 微信群不定期在qq群更新二维码。
- `{% endif %}`
+
-例如
+**[master分支版本](https://gitee.com/pear-admin/pear-admin-flask/tree/master/)**
-```python
- {% if authorize("admin:user:edit") %}
-
- {% endif %}
- {% if authorize("admin:user:remove") %}
-
- {% endif %}
-```
+flask 2.0.1 + flask-sqlalchemy + 权限验证 + Flask-APScheduler 定时任务 + marshmallow 序列化与数据验证
-## model序列化 :id=Schema
+master 分支为主分支,是功能最全、页面最多的分支。
-- sqlalchemy查询的model对象转dict
+
-
-```
- model_to_dicts(Schema, model)
-```
-
-Schema 是 序列化类,我把他放在了models文件里,觉得没有必要见一个文件夹叫Schema,也方便看着模型写序列化类
-
-```python
-# 例如
-class DeptSchema(ma.Schema): # 序列化类
- deptId = fields.Integer(attribute="id")
- parentId = fields.Integer(attribute="parent_id")
- deptName = fields.Str(attribute="dept_name")
- leader = fields.Str()
- phone = fields.Str()
- email = fields.Str()
- address = fields.Str()
- status = fields.Str()
- sort = fields.Str()
-```
-
->这一部分有问题的话请看marshmallow文档
-
-model写的是查询后的对象
-
-```python
-dept = Dept.query.order_by(Dept.sort).all()
-```
-
-进行序列化
-
-```python
-res = model_to_dicts(Schema=DeptSchema, model=dept)
-```
-
-## 构造查询过滤
-
-```python
-# 准确查询字段
-# 不等于查询字段
-# 大于查询字段
-# 小于查询字段
-# 模糊查询字段(%+xxx+%)
-# 左模糊 (% + xxx)
-# 右模糊查询字段(xxx+ %)
-# 包含查询字段
-#范围查询字段
-# 查询
-```
-
-## xss过滤
-
-```python
-from applications.common.utils.validate import str_escape
-details = str_escape(req.get("details"))
-```
+## 下载使用 :id=download
+#### 1. 官网地址
-## 邮件发送
+官网提供稳定版本的 Release 发行版本 [前往](http://www.pearadmin.com)
-```python
-#在.flaskenv中配置邮箱
+
-from applications/common/utils/mail import send_main
-send_mail(subject='title', recipients=['123@qq.com'], content='body')
-```
+#### 2. 源码仓库
+
+如果你需要最新代码,请前往 Gitee 仓库 [前往](https://gitee.com/pear-admin/pear-admin-flask)
+
+
+如果您完成了这一步,请参阅[下载安装](install.md)章节。
-## 返回格式
-
-```
-from applications/common/utils/http import success_api,fail_api,table_api
-
-# 这是源代码
-def success_api(msg: str = "成功"):
- """ 成功响应 默认值”成功“ """
- return jsonify(success=True, msg=msg)
-
-
-def fail_api(msg: str = "失败"):
- """ 失败响应 默认值“失败” """
- return jsonify(success=False, msg=msg)
-
-
-def table_api(msg: str = "", count=0, data=None, limit=10):
- """ 动态表格渲染响应 """
- res = {
- 'msg': msg,
- 'code': 0,
- 'data': data,
- 'count': count,
- 'limit': limit
-
- }
- return jsonify(res)
-```
\ No newline at end of file
diff --git a/docs/function.md b/docs/function.md
new file mode 100644
index 0000000..3d1db1c
--- /dev/null
+++ b/docs/function.md
@@ -0,0 +1,279 @@
+## 用户权限判断
+
+Pear Admin Flask 项目中集成很多实用的功能,为了便于二次开发,同样也提供了许多便于开发的自定义函数。
+
+Pear Admin Flask 项目支持多用户,不同用户有不同的权限,此处将介绍 Pear Admin Flask 中的权限管理函数的用法。
+
+### 函数原型
+
+函数调用位于项目代码 ```applications/common/utils/rights.py``` 中,函数原型如下:
+
+```python
+def authorize(power: str, log: bool = False):
+ """
+ 用户权限判断,用于判断目前会话用户是否拥有访问权限
+
+ :param power: 权限标识
+ :type power: str
+ :param log: 是否记录日志, defaults to False
+ :type log: bool, optional
+ """
+ ...
+```
+
+### 基本用法
+
++ 后端用法
+
+```python
+from applications.common.utils.rights import authorize
+
+@app.route("/test")
+@authorize("admin:power:remove", log=True)
+def test_index():
+ return 'You are allowed.'
+```
+
+> 使用装饰器 @authorize时需要注意,该装饰器需要写在 @app.route之后
+
++ 前端用法
+
+在前端中,例如增加,删除按钮,对于没有编辑权限的用户不显示的话,可以使用
+
+ `{% **if** authorize("admin:user:edit") %}`
+
+ `{% endif %}`
+
+例如
+
+```python
+ {% if authorize("admin:user:edit") %}
+
+ {% endif %}
+ {% if authorize("admin:user:remove") %}
+
+ {% endif %}
+```
+
+## Schema 序列化
+
+项目中时常会涉及到数据库的读写,在读入数据时可以采用SQLalchemy,将模型查询的数据对象转化为字典。
+
+> Schema 是序列化类,我们把他放在了models文件里,因为觉得没有必要新建一个文件夹叫 Schema ,也方便看着模型写序列化类。
+
+```python
+# 例如
+class DeptSchema(ma.Schema): # 序列化类
+ deptId = fields.Integer(attribute="id")
+ parentId = fields.Integer(attribute="parent_id")
+ deptName = fields.Str(attribute="dept_name")
+ leader = fields.Str()
+ phone = fields.Str()
+ email = fields.Str()
+ address = fields.Str()
+ status = fields.Str()
+ sort = fields.Str()
+```
+
+> 这一部分有问题的话请看 marshmallow 文档
+
+### 模型到字典
+
+#### 函数原型
+
+函数调用位于项目代码 ```applications/common/curd.py``` 中,函数原型如下:
+
+```
+def model_to_dicts(schema: ma.Schema, data):
+ """
+ 将模型查询的数据对象转化为字典
+
+ :param schema: schema类
+ :param model: sqlalchemy查询结果
+ :return: 返回单个查询结果
+ """
+ ...
+```
+
+#### 基本用法
+
++ model写的是查询后的对象
+
+```python
+from applications.common import curd
+from applications.models import Dept
+from applications.schemas import DeptOutSchema
+
+def test(): # 某函数内
+ dept = Dept.query.order_by(Dept.sort).all()
+ res = curd.model_to_dicts(Schema=DeptOutSchema, model=dept)
+```
+
+## 查询多字段构造器
+
+```python
+# 准确查询字段
+# 不等于查询字段
+# 大于查询字段
+# 小于查询字段
+# 模糊查询字段(%+xxx+%)
+# 左模糊 (% + xxx)
+# 右模糊查询字段(xxx+ %)
+# 包含查询字段
+# 范围查询字段
+# 查询
+```
+
+## xss过滤
+
+### 函数原型
+
+函数调用位于项目代码 ```applications/common/utils/validate.py``` 中,函数原型如下:
+
+```
+def str_escape(s: str) -> str:
+ """
+ xss过滤,内部采用flask自带的过滤函数。
+ 与原过滤函数不同的是此过滤函数将在 s 为 None 时返回 None。
+
+ :param s: 要过滤的字符串
+ :type s: str
+ :return: s 为 None 时返回 None,否则过滤字符串后返回。
+ :rtype: str
+ """
+ ...
+```
+
+### 使用方法
+
+```python
+from applications.common.utils.validate import str_escape
+real_name = xss_escape(request.args.get('realName', type=str))
+```
+
+
+## 邮件发送
+
++ 原邮件发送函数
+
+### 函数原型
+
+函数调用位于项目代码 ```applications/common/utils/mail.py``` 中,函数原型如下:
+
+```
+def send_mail(subject, recipients, content):
+ """原发送邮件函数,不会记录邮件发送记录
+
+ 失败报错,请注意使用 try 拦截。
+
+ :param subject: 主题
+ :param recipients: 接收者 多个用英文分号隔开
+ :param content: 邮件 html
+ """
+ ...
+```
+
+### 示例代码
+
+```python
+#在.flaskenv中配置邮箱
+from applications.common.utils import mail
+
+mail.send_mail("subject", "test@test.com", "
Hello
")
+```
+
++ 基于二次开发的邮件发送函数
+
+### 函数原型
+
+函数调用位于项目代码 ```applications/common/utils/mail.py``` 中,函数原型如下:
+
+```
+def add(receiver, subject, content, user_id):
+ """
+ 发送一封邮件,若发送成功立刻提交数据库。
+
+ :param receiver: 接收者 多个用英文逗号隔开
+ :param subject: 邮件主题
+ :param content: 邮件 html
+ :param user_id: 发送用户ID(谁发送的?) 可以用 from flask_login import current_user ; current_user.id 来表示当前登录用户
+ :return: 成功与否
+ """
+ ...
+```
+
+### 示例代码
+
+```python
+#在.flaskenv中配置邮箱
+from applications.common.utils import mail
+
+mail.add("test@test.com", "subject", "Hello
", current_user)
+```
+
+
+
+## 返回格式
+
+> 后端响应时我们推荐使用规定的API响应格式。
+
+### 函数原型
+
+函数调用位于项目代码 ```applications/common/utils/http.py``` 中,函数原型如下:
+
+```
+def success_api(msg: str = "成功"):
+ """ 成功响应 默认值“成功” """
+ return jsonify(success=True, msg=msg)
+
+
+def fail_api(msg: str = "失败"):
+ """ 失败响应 默认值“失败” """
+ return jsonify(success=False, msg=msg)
+
+
+def table_api(msg: str = "", count=0, data=None, limit=10):
+ """ 动态表格渲染响应 """
+ res = {
+ 'msg': msg,
+ 'code': 0,
+ 'data': data,
+ 'count': count,
+ 'limit': limit
+
+ }
+ return jsonify(res)
+```
+
+### 示例代码
+
+```python
+from applications.common.utils.http import success_api, fail_api, table_api
+
+@admin_log.get('/operateLog')
+@authorize("admin:log:main")
+def operate_log():
+ # orm查询
+ # 使用分页获取data需要.items
+ log = AdminLog.query.filter(
+ AdminLog.url != '/passport/login').order_by(
+ desc(AdminLog.create_time)).layui_paginate()
+ count = log.total
+ return table_api(data=model_to_dicts(schema=LogOutSchema, data=log.items), count=count)
+```
+
+```python
+from applications.common.utils.http import success_api, fail_api, table_api
+
+@admin_power.post('/save')
+@authorize("admin:power:add", log=True)
+def save():
+ ... # 若干操作
+ if success:
+ return success_api(msg="成功")
+ return fail_api(msg="成功")
+```
diff --git a/docs/group.md b/docs/group.md
deleted file mode 100644
index 0da9fe9..0000000
--- a/docs/group.md
+++ /dev/null
@@ -1,2 +0,0 @@
-
-微信群不定期在qq群更新二维码
\ No newline at end of file
diff --git a/docs/install.md b/docs/install.md
new file mode 100644
index 0000000..7b54e72
--- /dev/null
+++ b/docs/install.md
@@ -0,0 +1,113 @@
+### 环境要求 :id=install
+- Python >= 3.6
+- Mysql >= 5.7.0
+
+### 安装配置
+
+#### 克隆远程仓库
+
+您可以使用 git 来克隆远程仓库:
+
+```shell
+# 进入项目主目录
+cd Pear Admin Flask
+
+# 使用 git 克隆远程仓库
+git clone https://gitee.com/pear-admin/pear-admin-flask.git
+
+# 切换分支
+git checkout master # master, main or mini
+```
+
+或者直接前往 Pear Admin Flask 项目的[Gitee 主页](https://gitee.com/pear-admin/pear-admin-flask)下载项目仓库。
+
+#### 搭建开发环境
+
+我们推荐使用 Python 的虚拟环境来开发该项目,这样便于项目的迁移与二次开发。当然,您也可以选择使用原 Python 环境。
+
+如果你想创建 Python 虚拟环境,你可以使用下面的命令行:
+
+```shell
+# 在当前目录的venv文件夹创建虚拟环境
+python -m venv venv
+
+# Windows 激活虚拟环境
+.\test_env\Scripts\Activate.ps1
+
+# Linux 和 Mac 激活虚拟环境
+source ./test_env/bin/activate
+```
+
+**如果在创建虚拟环境时报错 “ModuleNotFoundError” ,这说明您的 Python 版本小于 3.3 。**
+
+#### 安装项目依赖
+
+```shell
+# 使用 pip 安装必要模块(对于 master 分支)
+pip install -r requirement\requirement.txt
+
+# 使用 pip 安装必要模块(对于 mini 分支)
+pip install -r requirement.txt
+```
+
+或者您可以尝试:
+
+```shell
+# 使用 pip 安装必要模块
+python -m pip install -r requirement.txt
+```
+
+#### 配置数据库
+
+在 `applications/config.py` 中配置好数据库。
+
+> 由于结构与目录调整,我们简化了项目结构,废弃了文件 ```.flaskenv``` ,请使用 config.py 配置程序。
+
+并使用以下命令生成数据库文件:
+
+```shell
+# 初始化数据库
+flask db init
+flask db migrate
+flask db upgrade
+flask admin init
+```
+
+#### 运行项目
+
+```shell
+python app.py
+
+# 或者可以使用
+flask run
+```
+
+#### 使用docker-compose运行项目
+
+```shell
+# 安装docker-compose
+curl -L https://github.com/docker/compose/releases/download/1.26.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
+
+docker-compose --version
+docker-compose up -d # -d后台运行
+docker-compose stop # 停止启动
+docker-compose down # 清除容器
+
+dockerdata/config.py # 配置文件
+dockerdata/mysql/initdb/ # MySQL初始化数据在
+rm -rf dockerdata/mysql/{log,data}/* # down掉容器后启动需要清除删除log,dat
+```
+
+### 二次开发
+
+恭喜!现在您已经成功搭建并运行了 Pear Admin Flask ,是时候参与开发了:
+
+请阅读:
+
++ Pear Admin Flask [目录结构](list.md) 章节
++ Pear Admin Flask [开发函数](function.md) 章节
++ Pear Admin Flask [插件开发](plugin.md) 章节
+
+其它章节等待更新。
diff --git a/docs/list.md b/docs/list.md
new file mode 100644
index 0000000..891fa73
--- /dev/null
+++ b/docs/list.md
@@ -0,0 +1,43 @@
+## 应用结构 :id=config
+```应用结构
+Pear Admin Flask
+├─applications # 应用
+│ ├─configs # 配置文件
+│ │ ├─ common.py # 普通配置
+│ │ └─ config.py # 配置文件对象
+│ ├─extensions # 注册插件
+│ ├─models # 数据模型
+│ ├─static # 静态资源文件
+│ ├─templates # 静态模板文件
+│ └─views # 视图部分
+│ ├─admin # 后台管理视图模块
+│ └─index # 前台视图模块
+├─docs # 文档说明
+├─migrations # 迁移文件记录
+├─requirement # 依赖文件
+└─.env # 项目的配置文件
+```
+
+## 资源结构 :id=static
+```资源结构
+Pear Admin Flask
+├─static # 项目设定的 Flask 资源文件夹
+│ ├─admin # pear admin flask 的后端资源文件(与 pear admin layui 同步)
+│ ├─index # pear admin flask 的前端资源文件
+│ └─upload # 用户上传保存目录
+└─templates # 项目设定的 Flask 模板文件夹
+ ├─admin # pear admin flask 的后端管理页面模板
+ │ ├─admin_log # 日志页面
+ │ ├─common # 基本模板页面(头部模板与页脚模板)
+ │ ├─console # 系统监控页面模板
+ │ ├─dept # 部门管理页面模板
+ │ ├─dict # 数据自动页面模板
+ │ ├─mail # 邮件管理页面模板
+ │ ├─photo # 图片上传页面模板
+ │ ├─power # 权限(菜单)管理页面模板
+ │ ├─role # 角色管理页面模板
+ │ ├─task # 任务设置页面模板
+ │ └─user # 用户管理页面模板
+ ├─errors # 错误页面模板
+ └─index # 主页模板
+```
\ No newline at end of file
diff --git a/docs/plugin.md b/docs/plugin.md
new file mode 100644
index 0000000..9ccb1d4
--- /dev/null
+++ b/docs/plugin.md
@@ -0,0 +1,47 @@
+### 说明
+
+插件功能旨在最大限度不修改原框架的前提下添加新功能,我们提供了三个示例插件。
+
+
+### 插件配置
+
+将插件文件夹放置在 ```applications/config.py``` 文件夹中,并且在 .flaskenv 中配置。再配置项中填入插件的文件夹名,已 json 格式写入其中。
+
+```python
+# 插件配置
+PLUGIN_ENABLE_FOLDERS = ["helloworld"]
+```
+
+### 插件目录
+
+```
+Plugin
+│ __init__.json
+└─ __init__.py
+```
+
+这是一个非常简单的插件。
+
+### 插件信息
+
+插件信息保存在 ```__init__.py``` 中,以测试插件“helloword”为例。插件的数据应该不少于下面三项:
+
+```json
+{
+ "plugin_name": "Hello World",
+ "plugin_version": "1.0.0.1",
+ "plugin_description": "一个测试的插件。"
+}
+```
+
+### 插件格式
+
+插件的入口点为 ```__init__.py``` 文件,在插件被启用后,程序启动时此 Python 文件中的 ```event_init``` 函数。代码如下:
+
+```python
+from flask import Flask
+
+def event_init(app: Flask):
+ """初始化完成时会调用这里"""
+ print("加载完毕后,我会输出一句话。")
+```
\ No newline at end of file
diff --git a/plugins/helloworld/__init__.py b/plugins/helloworld/__init__.py
index efbe8ae..d6b218e 100644
--- a/plugins/helloworld/__init__.py
+++ b/plugins/helloworld/__init__.py
@@ -10,14 +10,6 @@ from .main import helloworld_blueprint
dir_path = os.path.dirname(__file__).replace("\\", "/")
folder_name = dir_path[dir_path.rfind("/") + 1:] # 插件文件夹名称
-def event_enable():
- """当此插件被启用时会调用此处"""
- print(f"启用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
-def event_disable():
- """当此插件被禁用时会调用此处"""
- print(f"禁用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
def event_init(app: Flask):
"""初始化完成时会调用这里"""
app.register_blueprint(helloworld_blueprint)
\ No newline at end of file
diff --git a/plugins/realip/__init__.py b/plugins/realip/__init__.py
index f6971fd..50e18b4 100644
--- a/plugins/realip/__init__.py
+++ b/plugins/realip/__init__.py
@@ -10,15 +10,6 @@ from . import console
dir_path = os.path.dirname(__file__).replace("\\", "/")
folder_name = dir_path[dir_path.rfind("/") + 1:] # 插件文件夹名称
-def event_enable():
- """当此插件被启用时会调用此处"""
- print(f"启用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
-
-def event_disable():
- """当此插件被禁用时会调用此处"""
- print(f"禁用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
def event_init(app: Flask):
"""初始化完成时会调用这里"""
# 移除原有的输出日志
diff --git a/plugins/replacePage/__init__.py b/plugins/replacePage/__init__.py
index 3756f0a..6e4cd7e 100644
--- a/plugins/replacePage/__init__.py
+++ b/plugins/replacePage/__init__.py
@@ -8,15 +8,6 @@ from flask import Flask, render_template_string
dir_path = os.path.dirname(__file__).replace("\\", "/")
folder_name = dir_path[dir_path.rfind("/") + 1:] # 插件文件夹名称
-def event_enable():
- """当此插件被启用时会调用此处"""
- print(f"启用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
-
-def event_disable():
- """当此插件被禁用时会调用此处"""
- print(f"禁用插件,dir_path: {dir_path} ; folder_name: {folder_name}")
-
def event_init(app: Flask):
"""初始化完成时会调用这里"""
# 使用下面的代码 查看所有注册的视图函数。对于 Flask app.route 函数的实现,请参考 https://www.jianshu.com/p/dff3bc2f4836