重构: 整体提交
parent
136ff839b6
commit
19eda2533c
|
@ -1,22 +1,3 @@
|
|||
# Build and Release Folders
|
||||
bin-debug/
|
||||
bin-release/
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
|
||||
# Other files and folders
|
||||
.settings/
|
||||
|
||||
# Executables
|
||||
*.swf
|
||||
*.air
|
||||
*.ipa
|
||||
*.apk
|
||||
|
||||
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
|
||||
# should NOT be excluded as they contain compiler settings and other important
|
||||
# information for Eclipse / Flash Builder.
|
||||
docker_env/mysql/data/
|
||||
docker_env/redis/data/
|
||||
*/.idea
|
||||
dvadmin-doc/docs/.vuepress/dist
|
||||
/backend/venv
|
||||
/backend/.idea
|
||||
.idea
|
||||
|
|
214
LICENSE
214
LICENSE
|
@ -1,21 +1,201 @@
|
|||
MIT License
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2021 李强
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
1. Definitions.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2022] [django-vue-admin]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
Copyright 2021 李强
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
224
README.md
224
README.md
|
@ -1,24 +1,52 @@
|
|||
# Django-Vue-Admin
|
||||
|
||||
[](https://gitee.com/liqianglog/django-vue-admin/blob/master/LICENSE) [](https://python.org/) [](https://docs.djangoproject.com/zh-hans/2.2/) [](https://nodejs.org/zh-cn/) [](https://gitee.com/liqianglog/django-vue-admin)
|
||||
[](https://gitee.com/liqianglog/django-vue-admin/blob/master/LICENSE) [](https://python.org/) [](https://docs.djangoproject.com/zh-hans/3.2/) [](https://nodejs.org/zh-cn/) [](https://gitee.com/liqianglog/django-vue-admin)
|
||||
|
||||
[预 览](https://demo.django-vue-admin.com) | [官 网文档](https://www.django-vue-admin.com) | [群聊](https://qm.qq.com/cgi-bin/qm/qr?k=fOdnHhC8DJlRHGYSnyhoB8P5rgogA6Vs&jump_from=webapi) | [社区](https://bbs.django-vue-admin.com/) | [Github](https://github.com/liqianglog/django-vue-admin)
|
||||
[预 览](https://demo.django-vue-admin.com) | [官网文档](https://www.django-vue-admin.com) | [群聊](https://qm.qq.com/cgi-bin/qm/qr?k=fOdnHhC8DJlRHGYSnyhoB8P5rgogA6Vs&jump_from=webapi) | [社区](https://bbs.django-vue-admin.com) | [插件市场](https://bbs.django-vue-admin.com/plugMarket.html) | [Github](https://github.com/liqianglog/django-vue-admin)
|
||||
|
||||
|
||||
|
||||
💡 **「关于」**
|
||||
|
||||
我们是一群热爱代码的青年,在这个炙热的时代下,我们希望静下心来通过Code带来一点我们的色彩和颜色。
|
||||
|
||||
因为热爱,所以拥抱未来
|
||||
|
||||
## 平台简介
|
||||
|
||||
Django-Vue-Admin 是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||
💡 [django-vue-admin](https://gitee.com/dvadmin/django-vue-admin) 是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||
|
||||
|
||||
|
||||
* 🧑🤝🧑前端采用[D2Admin](https://github.com/d2-projects/d2-admin) 、[Vue](https://cn.vuejs.org/)、[ElementUI](https://element.eleme.cn/)。
|
||||
* 👭后端采用 Python 语言 Django 框架以及强大的 [Django REST Framework](https://pypi.org/project/djangorestframework)。
|
||||
* 👫权限认证使用[Django REST Framework SimpleJWT](https://pypi.org/project/djangorestframework-simplejwt),支持多终端认证系统。
|
||||
* 👬支持加载动态权限菜单,多方式轻松权限控制。
|
||||
* 💏特别鸣谢:[D2Admin](https://github.com/d2-projects/d2-admin) 、[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)。
|
||||
* 💡 特别感谢[jetbrains](https://www.jetbrains.com/) 为本开源项目提供免费的 IntelliJ IDEA 授权。
|
||||
|
||||
|
||||
|
||||
## 在线体验
|
||||
|
||||
👩👧👦演示地址:[http://demo.django-vue-admin.com](http://demo.django-vue-admin.com)
|
||||
|
||||
账号:superadmin
|
||||
|
||||
密码:superadmin123456
|
||||
|
||||
👩👦👦文档地址:[https://django-vue-admin.com](https://django-vue-admin.com)
|
||||
|
||||
|
||||
* 前端采用ruoyi-ui 、Vue、Element UI。
|
||||
* 后端采用Python语言Django框架。
|
||||
* 权限认证使用Jwt,支持多终端认证系统。
|
||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
||||
* 特别鸣谢:<u>[Gin-Vue-Admin](https://www.gin-vue-admin.com/)</u>,[RuoYi](https://gitee.com/y_project/RuoYi-Vue) ,[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)。
|
||||
|
||||
## 交流
|
||||
|
||||
- 社区:[戳我](https://bbs.django-vue-admin.com)
|
||||
- 交流社区:[戳我](https://bbs.django-vue-admin.com)👩👦👦
|
||||
|
||||
- QQ群号:812482043 <a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=fOdnHhC8DJlRHGYSnyhoB8P5rgogA6Vs&jump_from=webapi"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="django-vue-admin交流01群" title="django-vue-admin交流01群"></a>
|
||||
- 插件市场:[戳我](https://bbs.django-vue-admin.com/plugMarket.html)👩👦👦
|
||||
|
||||
- django-vue-admin交流01群:812482043 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=aJVwjDvH-Es4MPJQuoO32N0SucK22TE5&jump_from=webapi)
|
||||
- django-vue-admin交流02群:687252418 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=4jJN4IjWGfxJ8YJXbb_gTsuWjR34WLdc&jump_from=webapi)
|
||||
|
||||
- 二维码
|
||||
|
||||
|
@ -26,78 +54,70 @@ Django-Vue-Admin 是一套全部开源的快速开发平台,毫无保留给个
|
|||
|
||||
## 源码地址
|
||||
|
||||
gitee地址(主推):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)
|
||||
gitee地址(主推):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)👩👦👦
|
||||
|
||||
github地址:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)👩👦👦
|
||||
|
||||
|
||||
github地址:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)
|
||||
|
||||
## 内置功能
|
||||
|
||||
##### 后期版本 [版本功能说明](https://gitee.com/liqianglog/django-vue-admin/wikis/releaseNote?sort_id=3615540)
|
||||
1. 👨⚕️菜单管理:配置系统菜单,操作权限,按钮权限标识、后端接口权限等。
|
||||
2. 🧑⚕️部门管理:配置系统组织机构(公司、部门、角色)。
|
||||
3. 👩⚕️角色管理:角色菜单权限分配、数据权限分配、设置角色按部门进行数据范围权限划分。
|
||||
4. 🧑🎓权限权限:授权角色的权限范围。
|
||||
5. 👨🎓用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||
6. 👬接口白名单:配置不需要进行权限校验的接口。
|
||||
7. 🧑🔧字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||
8. 🧑🔧地区管理:对省市县区域进行管理。
|
||||
9. 📁附件管理:对平台上所有文件、图片等进行统一管理。
|
||||
10. 🗓️操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||
11. 🔌[插件市场 ](https://bbs.django-vue-admin.com/plugMarket.html):基于Django-Vue-Admin框架开发的应用和插件。
|
||||
|
||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||
3. 岗位管理:配置系统用户所属担任职务。
|
||||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识、后端接口权限等。
|
||||
5. 角色管理:角色菜单权限分配、数据权限分配、设置角色按机构进行数据范围权限划分。
|
||||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||
7. 参数管理:对系统动态配置常用参数。
|
||||
8. 文件管理:管理所有上传的和导出的文件。
|
||||
9. 通知公告:发布通知公告给所有人,进行消息的通知。
|
||||
10. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||
11. 登录日志:系统登录日志记录查询包含登录异常。
|
||||
12. 定时日志:celery定时任务执行日志记录。
|
||||
13. 在线用户:当前系统中活跃用户状态监控、用户强退功能。
|
||||
14. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||
15. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
16. 服务监控:进行可视化的服务器监控,CPU、内存、文件使用率等信息。
|
||||
## 插件市场 🔌
|
||||
|
||||
## 在线体验
|
||||
- Celery异步任务:[dvadmin-celery](https://gitee.com/huge-dream/dvadmin-celery)
|
||||
- 升级中心后端:[dvadmin-upgrade-center](https://gitee.com/huge-dream/dvadmin-upgrade-center)
|
||||
- 升级中心前端:[dvadmin-upgrade-center-web](https://gitee.com/huge-dream/dvadmin-upgrade-center-web)
|
||||
|
||||
演示地址:[http://demo.django-vue-admin.com](http://demo.django-vue-admin.com) 账号:admin 密码:123456
|
||||
## 准备工作
|
||||
~~~
|
||||
Python >= 3.6.0 (推荐3.8+版本)
|
||||
nodejs >= 14.0 (推荐最新)
|
||||
Mysql >= 5.7.0 (可选,默认数据库sqlite3,推荐8.0版本)
|
||||
Redis(可选,最新版)
|
||||
~~~
|
||||
|
||||
文档地址:[http://django-vue-admin.com](http://django-vue-admin.com)
|
||||
|
||||
## 前端
|
||||
|
||||
### 开发
|
||||
## 前端♝
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/liqianglog/django-vue-admin.git
|
||||
|
||||
# 进入项目目录
|
||||
cd dvadmin-ui
|
||||
cd web
|
||||
|
||||
# 安装依赖
|
||||
npm install --registry=https://registry.npm.taobao.org
|
||||
|
||||
# 启动服务
|
||||
npm run dev
|
||||
|
||||
# 浏览器访问 http://localhost:8080
|
||||
# .env.development 文件中可配置启动端口等参数
|
||||
```
|
||||
|
||||
### 发布
|
||||
|
||||
```bash
|
||||
# 构建测试环境
|
||||
npm run build:stage
|
||||
|
||||
# 构建生产环境
|
||||
npm run build:prod
|
||||
# npm run build
|
||||
```
|
||||
|
||||
## 后端
|
||||
|
||||
|
||||
## 后端💈
|
||||
|
||||
~~~bash
|
||||
1. 进入项目目录 cd dvadmin-backend
|
||||
1. 进入项目目录 cd backend
|
||||
2. 在项目根目录中,复制 ./conf/env.example.py 文件为一份新的到 ./conf 文件夹下,并重命名为 env.py
|
||||
|
||||
3. 在 env.py 中配置数据库信息
|
||||
mysql数据库版本建议:8.0
|
||||
mysql数据库字符集:utf8mb4
|
||||
|
||||
4. 安装依赖环境
|
||||
pip3 install -r requirements.txt
|
||||
5. 执行迁移命令:
|
||||
|
@ -105,75 +125,67 @@ npm run build:prod
|
|||
python3 manage.py migrate
|
||||
6. 初始化数据
|
||||
python3 manage.py init
|
||||
7. 启动项目
|
||||
python3 manage.py runserver 127.0.0.1:8000
|
||||
|
||||
定时任务启动命令:
|
||||
celery -A application worker -B --loglevel=info
|
||||
注:
|
||||
Windows 运行celery 需要安装 pip install eventlet
|
||||
celery -A application worker -P eventlet --loglevel=info
|
||||
|
||||
初始账号:admin 密码:123456
|
||||
|
||||
后端接口文档地址:http://127.0.0.1:8000/docs/
|
||||
7. 初始化省市县数据:
|
||||
python3 manage.py init_area
|
||||
8. 启动项目
|
||||
python3 manage.py runserver 0.0.0.0:8000
|
||||
或使用 daphne :
|
||||
daphne -b 0.0.0.0 -8000 application.asgi:application
|
||||
~~~
|
||||
|
||||
### 访问项目
|
||||
|
||||
- 访问地址:[http://localhost:8080](http://localhost:8080) (默认为此地址,如有修改请按照配置文件)
|
||||
- 账号:`superadmin` 密码:`admin123456`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### docker-compose 运行
|
||||
|
||||
~~~shell
|
||||
# 先安装docker-compose (自行百度安装),执行此命令等待安装
|
||||
docker-compose up
|
||||
# 先安装docker-compose (自行百度安装),执行此命令等待安装,如有使用celery插件请打开docker-compose.yml中celery 部分注释
|
||||
docker-compose up -d
|
||||
# 初始化后端数据(第一次执行即可)
|
||||
docker exec -ti dvadmin-django bash
|
||||
docker exec -ti DVAdmin-django bash
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
python manage.py init -y
|
||||
exit
|
||||
|
||||
前端地址:http://127.0.0.1:8080
|
||||
后端地址:http://127.0.0.1:8000
|
||||
账号:admin 密码:123456
|
||||
# 在服务器上请把127.0.0.1 换成自己公网ip
|
||||
账号:superadmin 密码:admin123456
|
||||
|
||||
# docker-compose 停止
|
||||
docker-compose down
|
||||
# docker-compose 重启
|
||||
docker-compose restart
|
||||
# docker-compose 启动时重新进行 build
|
||||
docker-compose up -d --build
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
## 演示图
|
||||
## 演示图✅
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/155624_fc01f49e_5074988.jpeg" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/162526_68e8c4c5_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163049_0a16b3b8_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163157_628941bc_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163444_73d4a6ae_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163456_c4ddcaf6_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163732_48cca279_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/163756_99176d5d_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/164149_b223657a_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/164226_58653572_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/164259_e06fbfe9_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/164330_6406c28f_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/164359_add984a1_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/181144_9665dae5_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/181700_25edc19f_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/181715_9305b7e8_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/181732_953b05e4_5074988.png" height="200" width="400"/></td>
|
||||
<td><img src="https://images.gitee.com/uploads/images/2021/0505/182122_73bddac6_5074988.png" height="200" width="400"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -1,92 +1,37 @@
|
|||
# start django command
|
||||
# local domain
|
||||
# saas-local.anthembj.com
|
||||
# ceshi-local.anthembj.com
|
||||
# docker-compose run --entrypoint '/backend/docker_start.sh' -p 8000:8000 docker_django
|
||||
|
||||
version: "3"
|
||||
services:
|
||||
dvadmin-ui:
|
||||
container_name: dvadmin-ui
|
||||
DVAdmin-web:
|
||||
container_name: DVAdmin-web
|
||||
ports:
|
||||
- "8080:8080"
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./docker_env/vue-ui/Dockerfile
|
||||
dockerfile: ./docker_env/web/Dockerfile
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
volumes:
|
||||
- "./dvadmin-ui:/dvadmin-ui"
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
cd /dvadmin-ui
|
||||
npm install --registry=https://registry.npm.taobao.org
|
||||
rm -rf /dvadmin-ui/dist
|
||||
npm run build:prod
|
||||
npm run dev
|
||||
|
||||
|
||||
dvadmin-redis:
|
||||
image: redis:latest
|
||||
container_name: dvadmin-redis
|
||||
ports:
|
||||
- "6380:6379"
|
||||
- ./docker_env/nginx/my.conf:/etc/nginx/conf.d/my.conf
|
||||
expose:
|
||||
- "6379"
|
||||
volumes:
|
||||
- ./docker_env/redis/data:/data
|
||||
- ./docker_env/redis/redis.conf:/etc/redis/redis.conf
|
||||
command: redis-server /etc/redis/redis.conf
|
||||
- "8080"
|
||||
networks:
|
||||
- dvadmin_net
|
||||
network:
|
||||
ipv4_address: 177.7.0.11
|
||||
|
||||
|
||||
dvadmin-mysql:
|
||||
image: mysql:5.7
|
||||
container_name: dvadmin-mysql
|
||||
#使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限
|
||||
#设置为true,不然数据卷可能挂载不了,启动不起
|
||||
privileged: true
|
||||
restart: always
|
||||
ports:
|
||||
- "3307:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "q1w2e3r4T%Y^U&MYSQL"
|
||||
MYSQL_DATABASE: "django-vue-admin"
|
||||
TZ: Asia/Shanghai
|
||||
command:
|
||||
--wait_timeout=31536000
|
||||
--interactive_timeout=31536000
|
||||
--max_connections=1000
|
||||
--default-authentication-plugin=mysql_native_password
|
||||
volumes:
|
||||
#映射mysql的数据目录到宿主机,保存数据
|
||||
- "./docker_env/mysql/data:/var/lib/mysql"
|
||||
#根据宿主机下的配置文件创建容器
|
||||
- "./docker_env/mysql/conf.d:/etc/mysql/conf.d"
|
||||
- "./docker_env/mysql/logs:/logs"
|
||||
networks:
|
||||
- dvadmin_net
|
||||
|
||||
dvadmin-django:
|
||||
DVAdmin-django:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker_env/django/Dockerfile
|
||||
# image: django:2.2
|
||||
container_name: dvadmin-django
|
||||
working_dir: /dvadmin-backend
|
||||
# command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --noinput && python manage.py runserver"
|
||||
# command: bash
|
||||
depends_on:
|
||||
- dvadmin-mysql
|
||||
- dvadmin-redis
|
||||
container_name: DVAdmin-django
|
||||
working_dir: /backend
|
||||
# 打开mysql 时,打开此选项
|
||||
# depends_on:
|
||||
# - DVAdmin-mysql
|
||||
environment:
|
||||
- REDIS_HOST=dvadmin-redis
|
||||
- DATABASE_HOST=dvadmin-mysql
|
||||
PYTHONUNBUFFERED: 1
|
||||
DATABASE_HOST: DVAdmin-mysql
|
||||
TZ: Asia/Shanghai
|
||||
volumes:
|
||||
- ./dvadmin-backend:/dvadmin-backend
|
||||
- ./backend:/backend
|
||||
- ./logs/log:/var/log
|
||||
ports:
|
||||
- "8000:8000"
|
||||
|
@ -94,31 +39,62 @@ services:
|
|||
- "8000"
|
||||
restart: always
|
||||
networks:
|
||||
- dvadmin_net
|
||||
network:
|
||||
ipv4_address: 177.7.0.12
|
||||
|
||||
# DVAdmin-mysql:
|
||||
# image: mysql:5.7
|
||||
# container_name: DVAdmin-mysql
|
||||
# #使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限
|
||||
# #设置为true,不然数据卷可能挂载不了,启动不起
|
||||
## privileged: true
|
||||
# restart: always
|
||||
# ports:
|
||||
# - "3306:3306"
|
||||
# environment:
|
||||
# MYSQL_ROOT_PASSWORD: "123456"
|
||||
# MYSQL_DATABASE: "dvadmin_pro"
|
||||
# TZ: Asia/Shanghai
|
||||
# command:
|
||||
# --wait_timeout=31536000
|
||||
# --interactive_timeout=31536000
|
||||
# --max_connections=1000
|
||||
# --default-authentication-plugin=mysql_native_password
|
||||
# volumes:
|
||||
# - "./docker_env/mysql/data:/var/lib/mysql"
|
||||
# - "./docker_env/mysql/conf.d:/etc/mysql/conf.d"
|
||||
# - "./docker_env/mysql/logs:/logs"
|
||||
# networks:
|
||||
# network:
|
||||
# ipv4_address: 177.7.0.13
|
||||
|
||||
|
||||
dvadmin-celery:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker_env/celery/Dockerfile
|
||||
# image: django:2.2
|
||||
container_name: dvadmin-celery
|
||||
working_dir: /dvadmin-backend
|
||||
# command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --noinput && python manage.py runserver"
|
||||
# command: bash
|
||||
depends_on:
|
||||
- dvadmin-mysql
|
||||
- dvadmin-redis
|
||||
environment:
|
||||
- REDIS_HOST=dvadmin-redis
|
||||
- DATABASE_HOST=dvadmin-mysql
|
||||
volumes:
|
||||
- ./dvadmin-backend:/dvadmin-backend
|
||||
- ./logs/log:/var/log
|
||||
restart: always
|
||||
networks:
|
||||
- dvadmin_net
|
||||
# 如果使用celery 插件,请自行打开此注释
|
||||
# DVAdmin-celery:
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: ./docker_env/celery/Dockerfile
|
||||
# # image: django:2.2
|
||||
# container_name: DVAdmin-celery
|
||||
# working_dir: /backend
|
||||
# depends_on:
|
||||
# - DVAdmin-mysql
|
||||
# environment:
|
||||
# PYTHONUNBUFFERED: 1
|
||||
# DATABASE_HOST: DVAdmin-mysql
|
||||
# TZ: Asia/Shanghai
|
||||
# volumes:
|
||||
# - ./backend:/backend
|
||||
# - ./logs/log:/var/log
|
||||
# restart: always
|
||||
# networks:
|
||||
# network:
|
||||
# ipv4_address: 177.7.0.14
|
||||
|
||||
networks:
|
||||
dvadmin_net:
|
||||
driver: bridge
|
||||
network:
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: '177.7.0.0/16'
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# docker 镜像打包
|
||||
|
||||
### 打包web基础Build包
|
||||
|
||||
~~~sh
|
||||
# 编译打包到本地
|
||||
docker build -f ./docker_env/web/DockerfileBuild -t registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/node12-base-web:latest .
|
||||
# 上传到阿里云仓库
|
||||
docker push registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/node12-base-web:latest
|
||||
|
||||
~~~
|
||||
|
||||
### 打包Backend基础Build包
|
||||
|
||||
~~~sh
|
||||
# 编译打包到本地
|
||||
docker build -f ./docker_env/django/DockerfileBuild -t registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest .
|
||||
# 上传到阿里云仓库
|
||||
docker push registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest
|
||||
~~~
|
||||
|
||||
### 运行前端
|
||||
|
||||
~~~
|
||||
docker build -f ./docker_env/web/Dockerfile -t dvadmin-pro-web .
|
||||
~~~
|
||||
|
||||
### 运行后端
|
||||
|
||||
~~~
|
||||
docker build -f ./docker_env/django/Dockerfile -t dvadmin-pro-django .
|
||||
~~~
|
||||
|
||||
### 运行celery
|
||||
|
||||
~~~
|
||||
docker build -f ./docker_env/celery/Dockerfile -t dvadmin-pro-celery .
|
||||
~~~
|
||||
|
||||
## docker-compose 运行
|
||||
|
||||
~~~
|
||||
# 先安装docker-compose (自行百度安装),执行此命令等待安装,如有使用celery插件请打开docker-compose.yml中celery 部分注释
|
||||
docker-compose up -d
|
||||
# 初始化后端数据(第一次执行即可)
|
||||
docker exec -ti dvadmin-django bash
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
python manage.py init -y
|
||||
exit
|
||||
|
||||
前端地址:http://127.0.0.1:8080
|
||||
后端地址:http://127.0.0.1:8000
|
||||
# 在服务器上请把127.0.0.1 换成自己公网ip
|
||||
账号:superadmin 密码:admin123456
|
||||
|
||||
# docker-compose 停止
|
||||
docker-compose down
|
||||
# docker-compose 重启
|
||||
docker-compose restart
|
||||
# docker-compose 启动时重新进行 build
|
||||
docker-compose up -d --build
|
||||
|
||||
~~~
|
||||
|
|
@ -1,16 +1,7 @@
|
|||
FROM python:3.8
|
||||
# ENV PYTHONUNBUFFERED 1
|
||||
RUN sed -i s/deb.debian.org/mirrors.163.com/g /etc/apt/sources.list
|
||||
RUN cat /etc/apt/sources.list
|
||||
RUN apt-get clean
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y build-essential
|
||||
RUN apt-get install -y python3.8-dev libpq-dev libopencv-dev
|
||||
RUN apt-get install -y redis-tools
|
||||
RUN mkdir /dvadmin-backend
|
||||
WORKDIR /dvadmin-backend
|
||||
COPY ./dvadmin-backend/requirements.txt /
|
||||
COPY ./dvadmin-backend/conf/env.example.py /dvadmin-backend/conf/env.py
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirements.txt
|
||||
FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest
|
||||
WORKDIR /backend
|
||||
COPY ./backend/ .
|
||||
RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }'
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
|
||||
CMD ["celery", "-A", "application", "worker", "-B", "--loglevel=info"]
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
cd ../../backend/
|
||||
docker build -f docker_env/celery/Dockerfile -t celery:1.0 .
|
|
@ -1,16 +1,6 @@
|
|||
FROM python:3.8
|
||||
# ENV PYTHONUNBUFFERED 1
|
||||
RUN sed -i s/deb.debian.org/mirrors.163.com/g /etc/apt/sources.list
|
||||
RUN cat /etc/apt/sources.list
|
||||
RUN apt-get clean
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y build-essential
|
||||
RUN apt-get install -y python3.8-dev libpq-dev libopencv-dev
|
||||
RUN apt-get install -y redis-tools
|
||||
RUN mkdir /dvadmin-backend
|
||||
WORKDIR /dvadmin-backend
|
||||
COPY ./dvadmin-backend/requirements.txt /
|
||||
COPY ./dvadmin-backend/conf/env.example.py /dvadmin-backend/conf/env.py
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirements.txt
|
||||
CMD ["/dvadmin-backend/docker_start.sh"]
|
||||
# ENTRYPOINT [ "uwsgi --ini /backend/azcrm/uwsgi.ini" ]
|
||||
FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/python38-base-backend:latest
|
||||
WORKDIR /backend
|
||||
COPY ./backend/ .
|
||||
RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }'
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
|
||||
CMD ["daphne","-b","0.0.0.0","-p","8000","application.asgi:application"]
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
FROM python:3.8-alpine
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||
RUN apk update && apk add bash bash-doc bash-completion git freetds-dev jpeg-dev linux-headers mysql-client mariadb-dev build-base libffi-dev openssl-dev zlib-dev bzip2-dev pcre-dev ncurses-dev readline-dev tk-dev postgresql-dev
|
||||
WORKDIR /backend
|
||||
COPY ./backend/requirements.txt /
|
||||
COPY ./docker_env/requirements-all.txt /
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirements.txt
|
||||
RUN python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirements-all.txt
|
|
@ -1,3 +0,0 @@
|
|||
cd ../../dvadmin-backend/
|
||||
|
||||
docker build -f docker_env/django/Dockerfile -t django:2.2 .
|
|
@ -18,7 +18,7 @@ symbolic-links=0
|
|||
# customize your systemd unit file for mariadb according to the
|
||||
# instructions in http://fedoraproject.org/wiki/Systemdd
|
||||
#允许最大连接数
|
||||
max_connections=200
|
||||
max_connections=1000
|
||||
#服务端使用的字符集默认为8比特编码的latin1字符集
|
||||
character-set-server=utf8
|
||||
#创建新表时将使用的默认存储引擎
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
client_max_body_size 100M;
|
||||
location / {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.php index.htm;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
rewrite ^/api/(.*)$ /$1 break; #重写
|
||||
proxy_pass http://177.7.0.12:8000/; # 设置代理服务器的协议和地址
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
cur_path=`pwd`
|
||||
# docker pull redis:latest
|
||||
docker run -d \
|
||||
-p 6379:6379 \
|
||||
-v $cur_path/redis.conf:/etc/redis/redis.conf \
|
||||
--privileged=true \
|
||||
--name docker-redis \
|
||||
redis:latest \
|
||||
redis-server /etc/redis/redis.conf
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +0,0 @@
|
|||
FROM node:12
|
||||
COPY ./dvadmin-ui/package.json /
|
||||
RUN npm install --registry=https://registry.npm.taobao.org
|
||||
#RUN npm run build:prod
|
||||
#CMD ["npm","run","dev"]
|
|
@ -0,0 +1,9 @@
|
|||
FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/node12-base-web:latest
|
||||
WORKDIR /web/
|
||||
COPY web/. .
|
||||
RUN npm install --registry=https://registry.npm.taobao.org
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY ./docker_env/nginx/my.conf /etc/nginx/conf.d/my.conf
|
||||
COPY --from=0 /web/dist /usr/share/nginx/html
|
|
@ -0,0 +1,3 @@
|
|||
FROM node:14-alpine
|
||||
COPY ./web/package.json /
|
||||
RUN npm install --registry=https://registry.npm.taobao.org
|
|
@ -1,97 +0,0 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
__pycache__/
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
.idea/
|
||||
*.db
|
||||
.DS_Store
|
||||
__pycache__
|
||||
migrations/
|
||||
!migrations/__init__.py
|
||||
*.pyc
|
||||
conf/
|
||||
!conf/env.example.py
|
||||
db.sqlite3
|
|
@ -1,18 +0,0 @@
|
|||
import os
|
||||
|
||||
import django
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
django.setup()
|
||||
from channels.auth import AuthMiddlewareStack
|
||||
from channels.http import AsgiHandler
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
|
||||
websocket_urlpatterns = [
|
||||
]
|
||||
|
||||
application = ProtocolTypeRouter({
|
||||
"http": AsgiHandler(),
|
||||
# Just HTTP for now. (We can add other protocols later.)
|
||||
'websocket': AuthMiddlewareStack(URLRouter(websocket_urlpatterns, )),
|
||||
})
|
|
@ -1,14 +0,0 @@
|
|||
import os
|
||||
|
||||
import django
|
||||
from celery import Celery, platforms
|
||||
from django.conf import settings
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', "application.settings")
|
||||
django.setup()
|
||||
|
||||
app = Celery(f"dvadmin")
|
||||
|
||||
app.config_from_object('django.conf:settings')
|
||||
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||
platforms.C_FORCE_ROOT = True
|
|
@ -1,336 +0,0 @@
|
|||
"""
|
||||
Django settings for application project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 2.2.16.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.11/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.11/ref/settings/
|
||||
"""
|
||||
|
||||
# 导入全局环境变量
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
from mongoengine import connect
|
||||
|
||||
from conf.env import *
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = ')ns9h-%fl^&ro=+-vgl*b-!+a%2=tuwc#&xbpmcavj0*ufpyjh'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ALLOWED_HOSTS
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'corsheaders',
|
||||
'captcha',
|
||||
'django_celery_beat',
|
||||
'drf_yasg', # swagger 接口
|
||||
# 自定义app
|
||||
'apps.vadmin.permission',
|
||||
'apps.vadmin.op_drf',
|
||||
'apps.vadmin.system',
|
||||
'apps.vadmin.celery',
|
||||
'apps.vadmin.monitor',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
# 'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'vadmin.op_drf.middleware.ApiLoggingMiddleware', # 用于记录API访问日志
|
||||
'vadmin.op_drf.middleware.PermissionModeMiddleware', # 权限中间件
|
||||
]
|
||||
# 允许跨域源
|
||||
CORS_ORIGIN_ALLOW_ALL = CORS_ORIGIN_ALLOW_ALL
|
||||
# 允许ajax请求携带cookie
|
||||
CORS_ALLOW_CREDENTIALS = CORS_ALLOW_CREDENTIALS
|
||||
X_FRAME_OPTIONS = "ALLOW-FROM"
|
||||
ROOT_URLCONF = 'application.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'application.wsgi.application'
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||
# 配置语言
|
||||
LANGUAGE_CODE = 'zh-hans'
|
||||
TIME_ZONE = 'Asia/Shanghai'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = False
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.11/howto/static-files/
|
||||
"""
|
||||
静态目录、多媒体配置
|
||||
"""
|
||||
# 访问静态文件的url地址前缀
|
||||
STATIC_URL = '/static/'
|
||||
# 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释
|
||||
# python manage.py collectstatic
|
||||
# STATIC_ROOT=os.path.join(BASE_DIR,'static')
|
||||
# # 设置django的静态文件目录
|
||||
STATICFILES_DIRS = [
|
||||
os.path.join(BASE_DIR, "static"),
|
||||
]
|
||||
if not os.path.exists(os.path.join(BASE_DIR, 'media')):
|
||||
os.makedirs(os.path.join(BASE_DIR, 'media'))
|
||||
# 访问上传文件的url地址前缀
|
||||
MEDIA_URL = "/media/"
|
||||
# 项目中存储上传文件的根目录
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
|
||||
|
||||
"""
|
||||
日志配置
|
||||
"""
|
||||
# log 配置部分BEGIN #
|
||||
SERVER_LOGS_FILE = os.path.join(BASE_DIR, 'logs', 'server.log')
|
||||
ERROR_LOGS_FILE = os.path.join(BASE_DIR, 'logs', 'error.log')
|
||||
if not os.path.exists(os.path.join(BASE_DIR, 'logs')):
|
||||
os.makedirs(os.path.join(BASE_DIR, 'logs'))
|
||||
|
||||
# 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志:
|
||||
# 格式:[日期][模块.函数名称():行号] [级别] 信息
|
||||
STANDARD_LOG_FORMAT = '[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s'
|
||||
CONSOLE_LOG_FORMAT = '[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s'
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'standard': {
|
||||
'format': STANDARD_LOG_FORMAT
|
||||
},
|
||||
'console': {
|
||||
'format': CONSOLE_LOG_FORMAT,
|
||||
'datefmt': '%Y-%m-%d %H:%M:%S',
|
||||
},
|
||||
'file': {
|
||||
'format': CONSOLE_LOG_FORMAT,
|
||||
'datefmt': '%Y-%m-%d %H:%M:%S',
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'file': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.handlers.RotatingFileHandler',
|
||||
'filename': SERVER_LOGS_FILE,
|
||||
'maxBytes': 1024 * 1024 * 100, # 100 MB
|
||||
'backupCount': 5, # 最多备份5个
|
||||
'formatter': 'standard',
|
||||
'encoding': 'utf-8',
|
||||
},
|
||||
'error': {
|
||||
'level': 'ERROR',
|
||||
'class': 'logging.handlers.RotatingFileHandler',
|
||||
'filename': ERROR_LOGS_FILE,
|
||||
'maxBytes': 1024 * 1024 * 100, # 100 MB
|
||||
'backupCount': 3, # 最多备份3个
|
||||
'formatter': 'standard',
|
||||
'encoding': 'utf-8',
|
||||
},
|
||||
'console': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'console',
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
# default日志
|
||||
'': {
|
||||
'handlers': ['console', 'error', 'file'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
# 数据库相关日志
|
||||
'django.db.backends': {
|
||||
'handlers': [],
|
||||
'propagate': True,
|
||||
'level': 'INFO',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
# ================================================= #
|
||||
# ************** 数据库 配置 ************** #
|
||||
# ================================================= #
|
||||
|
||||
if DATABASE_TYPE == "MYSQL":
|
||||
# Mysql数据库
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.mysql",
|
||||
"HOST": os.getenv('DATABASE_HOST') or DATABASE_HOST,
|
||||
"PORT": DATABASE_PORT,
|
||||
"USER": DATABASE_USER,
|
||||
"PASSWORD": DATABASE_PASSWORD,
|
||||
"NAME": DATABASE_NAME,
|
||||
}
|
||||
}
|
||||
else:
|
||||
# sqlite3 数据库
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
# redis 缓存
|
||||
REDIS_URL = f'redis://:{REDIS_PASSWORD if REDIS_PASSWORD else ""}@{os.getenv("REDIS_HOST") or REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}'
|
||||
# 是否启用redis
|
||||
if locals().get("REDIS_ENABLE", True):
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": REDIS_URL,
|
||||
"OPTIONS": {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
}
|
||||
},
|
||||
}
|
||||
# ================================================= #
|
||||
# ******************** JWT配置 ******************** #
|
||||
# ================================================= #
|
||||
JWT_AUTH = {
|
||||
'JWT_ALLOW_REFRESH': True,
|
||||
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=60 * 60 * 24), # JWT有效时间24小时
|
||||
'JWT_AUTH_HEADER_PREFIX': 'Bearer', # JWT的Header认证头以'JWT '开始
|
||||
'JWT_AUTH_COOKIE': 'AUTH_JWT',
|
||||
'JWT_VERIFY_EXPIRATION': True,
|
||||
'JWT_PAYLOAD_HANDLER': 'apps.vadmin.utils.jwt_util.jwt_payload_handler',
|
||||
'JWT_GET_USER_SECRET_KEY': 'apps.vadmin.utils.jwt_util.jwt_get_user_secret_key',
|
||||
'JWT_RESPONSE_PAYLOAD_HANDLER': 'apps.vadmin.utils.jwt_util.jwt_response_payload_handler',
|
||||
}
|
||||
|
||||
# ================================================= #
|
||||
# ************** REST_FRAMEWORK 配置 ************** #
|
||||
# ================================================= #
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
),
|
||||
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'apps.vadmin.utils.authentication.RedisOpAuthJwtAuthentication',
|
||||
# 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
|
||||
),
|
||||
|
||||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
|
||||
'DEFAULT_PAGINATION_CLASS': 'vadmin.op_drf.pagination.Pagination',
|
||||
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
|
||||
'EXCEPTION_HANDLER': 'apps.vadmin.utils.exceptions.op_exception_handler',
|
||||
}
|
||||
# ================================================= #
|
||||
# ************** 登录方式配置 ************** #
|
||||
# ================================================= #
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'apps.vadmin.utils.backends.CustomBackend',
|
||||
'apps.vadmin.utils.backends.SessionAuthentication',
|
||||
)
|
||||
AUTH_USER_MODEL = 'permission.UserProfile'
|
||||
# username_field
|
||||
USERNAME_FIELD = 'username'
|
||||
|
||||
# ================================================= #
|
||||
# ************** 登录验证码配置 ************** #
|
||||
# ================================================= #
|
||||
CAPTCHA_STATE = CAPTCHA_STATE
|
||||
# 字母验证码
|
||||
CAPTCHA_IMAGE_SIZE = (160, 60) # 设置 captcha 图片大小
|
||||
CAPTCHA_LENGTH = 4 # 字符个数
|
||||
CAPTCHA_TIMEOUT = 1 # 超时(minutes)
|
||||
# 加减乘除验证码
|
||||
CAPTCHA_OUTPUT_FORMAT = '%(image)s %(text_field)s %(hidden_field)s '
|
||||
CAPTCHA_FONT_SIZE = 40 # 字体大小
|
||||
CAPTCHA_FOREGROUND_COLOR = '#0033FF' # 前景色
|
||||
CAPTCHA_BACKGROUND_COLOR = '#F5F7F4' # 背景色
|
||||
CAPTCHA_NOISE_FUNCTIONS = (
|
||||
# 'captcha.helpers.noise_arcs', # 线
|
||||
# 'captcha.helpers.noise_dots', # 点
|
||||
)
|
||||
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
|
||||
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
|
||||
|
||||
API_LOG_ENABLE = True
|
||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||
# API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
||||
BROKER_URL = f'redis://:{REDIS_PASSWORD if REDIS_PASSWORD else ""}@{os.getenv("REDIS_HOST") or REDIS_HOST}:' \
|
||||
f'{REDIS_PORT}/{locals().get("CELERY_DB", 2)}' # Broker使用Redis
|
||||
CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' # Backend数据库
|
||||
# ================================================= #
|
||||
# ************** 其他配置 ************** #
|
||||
# ================================================= #
|
||||
# 接口权限
|
||||
INTERFACE_PERMISSION = locals().get("INTERFACE_PERMISSION", False)
|
||||
DJANGO_CELERY_BEAT_TZ_AWARE = False
|
||||
CELERY_TIMEZONE = 'Asia/Shanghai' # celery 时区问题
|
|
@ -1,63 +0,0 @@
|
|||
"""application URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.11/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.conf.urls import url, include
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||
"""
|
||||
|
||||
from captcha.conf import settings as ca_settings
|
||||
from captcha.helpers import captcha_image_url, captcha_audio_url
|
||||
from captcha.models import CaptchaStore
|
||||
from django.conf import settings
|
||||
from django.urls import re_path, include
|
||||
from django.views.static import serve
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.vadmin.op_drf.response import SuccessResponse
|
||||
from rest_framework import permissions
|
||||
from drf_yasg.views import get_schema_view
|
||||
from drf_yasg import openapi
|
||||
schema_view = get_schema_view(
|
||||
openapi.Info(
|
||||
title="Snippets API",
|
||||
default_version='v1',
|
||||
description="Test description",
|
||||
terms_of_service="https://www.google.com/policies/terms/",
|
||||
contact=openapi.Contact(email="contact@snippets.local"),
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
public=True,
|
||||
permission_classes=[permissions.AllowAny],
|
||||
)
|
||||
|
||||
class CaptchaRefresh(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
def get(self, request):
|
||||
new_key = CaptchaStore.pick()
|
||||
to_json_response = {
|
||||
"key": new_key,
|
||||
"image_url": captcha_image_url(new_key),
|
||||
"audio_url": captcha_audio_url(new_key) if ca_settings.CAPTCHA_FLITE_PATH else None,
|
||||
}
|
||||
return SuccessResponse(to_json_response)
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
|
||||
re_path(r'^admin/', include('apps.vadmin.urls')),
|
||||
re_path(r'^$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
|
||||
re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
|
||||
]
|
|
@ -1,11 +0,0 @@
|
|||
[uwsgi]
|
||||
chdir = /dvadmin-backend
|
||||
wsgi-file = /dvadmin-backend/application/wsgi.py
|
||||
master = true
|
||||
processes = 8
|
||||
http-socket = 0.0.0.0:8000
|
||||
module = application.wsgi:application
|
||||
vacuum = true
|
||||
log-maxsize = 20000000
|
||||
log-reopen = true
|
||||
buffer-size = 65536
|
|
@ -1,16 +0,0 @@
|
|||
"""
|
||||
WSGI config for application project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
|
||||
|
||||
application = get_wsgi_application()
|
|
@ -1 +0,0 @@
|
|||
from django.contrib import admin
|
|
@ -1,7 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class DpCmdbConfig(AppConfig):
|
||||
name = 'apps.vadmin.celery'
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import django_filters
|
||||
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||
|
||||
|
||||
class IntervalScheduleFilter(django_filters.rest_framework.FilterSet):
|
||||
class Meta:
|
||||
model = IntervalSchedule
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class CrontabScheduleFilter(django_filters.rest_framework.FilterSet):
|
||||
class Meta:
|
||||
model = CrontabSchedule
|
||||
exclude = ('timezone',)
|
||||
|
||||
|
||||
class PeriodicTaskFilter(django_filters.rest_framework.FilterSet):
|
||||
class Meta:
|
||||
model = PeriodicTask
|
||||
fields = '__all__'
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.vadmin.op_drf.serializers import CustomModelSerializer
|
||||
from apps.vadmin.utils.exceptions import APIException
|
||||
|
||||
|
||||
class IntervalScheduleSerializer(CustomModelSerializer):
|
||||
class Meta:
|
||||
model = IntervalSchedule
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class CrontabScheduleSerializer(CustomModelSerializer):
|
||||
|
||||
def save(self, **kwargs):
|
||||
queryset = CrontabSchedule.objects.filter(**self.validated_data)
|
||||
if queryset.count() and (
|
||||
queryset.count() == 1 and self.initial_data.get('id', None) not in queryset.values_list('id',
|
||||
flat=True)):
|
||||
raise APIException(message='值已存在!!!')
|
||||
super().save(**kwargs)
|
||||
|
||||
class Meta:
|
||||
model = CrontabSchedule
|
||||
exclude = ('timezone',)
|
||||
|
||||
|
||||
class PeriodicTaskSerializer(CustomModelSerializer):
|
||||
interval_list = serializers.SerializerMethodField(read_only=True)
|
||||
crontab_list = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_interval_list(self, obj):
|
||||
return IntervalScheduleSerializer(obj.interval).data if obj.interval else {}
|
||||
|
||||
def get_crontab_list(self, obj):
|
||||
return CrontabScheduleSerializer(obj.crontab).data if obj.crontab else {}
|
||||
|
||||
class Meta:
|
||||
model = PeriodicTask
|
||||
fields = '__all__'
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,20 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.urlpatterns import format_suffix_patterns
|
||||
|
||||
from apps.vadmin.celery.views import IntervalScheduleModelViewSet, CrontabScheduleModelViewSet, PeriodicTaskModelViewSet, TasksAsChoices, \
|
||||
OperateCeleryTask
|
||||
|
||||
router = DefaultRouter()
|
||||
# 调度间隔
|
||||
router.register(r'intervalschedule', IntervalScheduleModelViewSet)
|
||||
router.register(r'crontabschedule', CrontabScheduleModelViewSet)
|
||||
router.register(r'periodictask', PeriodicTaskModelViewSet)
|
||||
|
||||
urlpatterns = format_suffix_patterns([
|
||||
# 获取所有 tasks 名称
|
||||
url(r'^tasks_as_choices/', TasksAsChoices.as_view()),
|
||||
url(r'^operate_celery/', OperateCeleryTask.as_view()),
|
||||
])
|
||||
|
||||
urlpatterns += router.urls
|
|
@ -1,99 +0,0 @@
|
|||
from django_celery_beat.admin import TaskSelectWidget
|
||||
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.vadmin.celery.filters import IntervalScheduleFilter, CrontabScheduleFilter, PeriodicTaskFilter
|
||||
from apps.vadmin.celery.serializers import IntervalScheduleSerializer, CrontabScheduleSerializer, PeriodicTaskSerializer
|
||||
from apps.vadmin.op_drf.views import CustomAPIView
|
||||
from apps.vadmin.op_drf.viewsets import CustomModelViewSet
|
||||
from apps.vadmin.op_drf.response import SuccessResponse
|
||||
|
||||
|
||||
class IntervalScheduleModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
IntervalSchedule 调度间隔模型
|
||||
every 次数
|
||||
period 时间(天,小时,分钟,秒.毫秒)
|
||||
"""
|
||||
queryset = IntervalSchedule.objects.all()
|
||||
serializer_class = IntervalScheduleSerializer
|
||||
create_serializer_class = IntervalScheduleSerializer
|
||||
update_serializer_class = IntervalScheduleSerializer
|
||||
filter_class = IntervalScheduleFilter
|
||||
search_fields = ('every', 'period')
|
||||
ordering = 'every' # 默认排序
|
||||
|
||||
|
||||
class CrontabScheduleModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
CrontabSchedule crontab调度模型
|
||||
minute 分钟
|
||||
hour 小时
|
||||
day_of_week 每周的周几
|
||||
day_of_month 每月的某一天
|
||||
month_of_year 每年的某一个月
|
||||
|
||||
"""
|
||||
queryset = CrontabSchedule.objects.all()
|
||||
serializer_class = CrontabScheduleSerializer
|
||||
filter_class = CrontabScheduleFilter
|
||||
search_fields = ('minute', 'hour')
|
||||
ordering = 'minute' # 默认排序
|
||||
|
||||
|
||||
class PeriodicTaskModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
PeriodicTask celery 任务数据模型
|
||||
name 名称
|
||||
task celery任务名称
|
||||
interval 频率
|
||||
crontab 任务编排
|
||||
args 形式参数
|
||||
kwargs 位置参数
|
||||
queue 队列名称
|
||||
exchange 交换
|
||||
routing_key 路由密钥
|
||||
expires 过期时间
|
||||
enabled 是否开启
|
||||
|
||||
"""
|
||||
queryset = PeriodicTask.objects.exclude(name="celery.backend_cleanup")
|
||||
serializer_class = PeriodicTaskSerializer
|
||||
filter_class = PeriodicTaskFilter
|
||||
search_fields = ('name', 'task', 'date_changed')
|
||||
ordering = 'date_changed' # 默认排序
|
||||
|
||||
|
||||
class TasksAsChoices(APIView):
|
||||
def get(self, request):
|
||||
"""
|
||||
获取所有 tasks 名称
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
lis = []
|
||||
|
||||
def get_data(datas):
|
||||
for item in datas:
|
||||
if isinstance(item, (str, int)) and item:
|
||||
lis.append(item)
|
||||
else:
|
||||
get_data(item)
|
||||
|
||||
get_data(TaskSelectWidget().tasks_as_choices())
|
||||
return SuccessResponse(list(set(lis)))
|
||||
|
||||
|
||||
class OperateCeleryTask(CustomAPIView):
|
||||
def post(self, request):
|
||||
req_data = request.data
|
||||
task = req_data.get('celery_name', '')
|
||||
data = {
|
||||
'task': ''
|
||||
}
|
||||
test = f"""
|
||||
from {'.'.join(task.split('.')[:-1])} import {task.split('.')[-1]}
|
||||
task = {task.split('.')[-1]}.delay()
|
||||
"""
|
||||
exec(test, data)
|
||||
return SuccessResponse({'task_id': data.get('task').id})
|
|
@ -1,6 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MonitorConfig(AppConfig):
|
||||
name = 'apps.vadmin.monitor'
|
||||
verbose_name = "系统监控"
|
|
@ -1,23 +0,0 @@
|
|||
import django_filters
|
||||
|
||||
from apps.vadmin.monitor.models import Server, Monitor
|
||||
|
||||
|
||||
class ServerFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
服务器信息 简单过滤器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Server
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MonitorFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
服务器监控信息 简单过滤器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Monitor
|
||||
fields = '__all__'
|
|
@ -1,3 +0,0 @@
|
|||
from apps.vadmin.monitor.models.monitor import Monitor
|
||||
from apps.vadmin.monitor.models.server import Server
|
||||
from apps.vadmin.monitor.models.sys_files import SysFiles
|
|
@ -1,19 +0,0 @@
|
|||
from django.db.models import CharField, ForeignKey, CASCADE
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class Monitor(CoreModel):
|
||||
cpu_num = CharField(max_length=8, verbose_name='CPU核数')
|
||||
cpu_sys = CharField(max_length=8, verbose_name='CPU已使用率')
|
||||
mem_num = CharField(max_length=32, verbose_name='内存总数(KB)')
|
||||
mem_sys = CharField(max_length=32, verbose_name='内存已使用大小(KB)')
|
||||
seconds = CharField(max_length=32, verbose_name='系统已运行时间')
|
||||
server = ForeignKey(to='monitor.Server', on_delete=CASCADE, verbose_name="关联服务器信息", db_constraint=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '服务器监控信息'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.server and self.server.name and self.server.ip}监控信息"
|
|
@ -1,20 +0,0 @@
|
|||
from django.db import models
|
||||
from django.db.models import CharField
|
||||
|
||||
from apps.vadmin.op_drf.fields import UpdateDateTimeField, CreateDateTimeField
|
||||
|
||||
|
||||
class Server(models.Model):
|
||||
name = CharField(max_length=256, verbose_name='服务器名称', null=True, blank=True)
|
||||
ip = CharField(max_length=32, verbose_name="ip地址")
|
||||
os = CharField(max_length=32, verbose_name="操作系统")
|
||||
remark = CharField(max_length=256, verbose_name="备注", null=True, blank=True)
|
||||
update_datetime = UpdateDateTimeField() # 修改时间
|
||||
create_datetime = CreateDateTimeField() # 创建时间
|
||||
|
||||
class Meta:
|
||||
verbose_name = '服务器信息'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name and self.ip}"
|
|
@ -1,19 +0,0 @@
|
|||
from django.db.models import CharField, ForeignKey, CASCADE
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class SysFiles(CoreModel):
|
||||
dir_name = CharField(max_length=32, verbose_name='磁盘路径')
|
||||
sys_type_name = CharField(max_length=400, verbose_name='系统文件类型')
|
||||
type_name = CharField(max_length=32, verbose_name='盘符类型')
|
||||
total = CharField(max_length=32, verbose_name='磁盘总大小(KB)')
|
||||
disk_sys = CharField(max_length=32, verbose_name='已使用大小(KB)')
|
||||
monitor = ForeignKey(to='monitor.Monitor', on_delete=CASCADE, verbose_name="关联服务器监控信息", db_constraint=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '系统磁盘'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.creator and self.creator.name}"
|
|
@ -1,40 +0,0 @@
|
|||
from apps.vadmin.monitor.models import Server, Monitor
|
||||
from apps.vadmin.op_drf.serializers import CustomModelSerializer
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 服务器信息 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class ServerSerializer(CustomModelSerializer):
|
||||
"""
|
||||
服务器信息 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Server
|
||||
fields = ("id", "ip", "name", "os", "remark")
|
||||
|
||||
|
||||
class UpdateServerSerializer(CustomModelSerializer):
|
||||
"""
|
||||
服务器信息 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Server
|
||||
fields = ("name", "remark")
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 服务器监控信息 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class MonitorSerializer(CustomModelSerializer):
|
||||
"""
|
||||
服务器监控信息 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Monitor
|
||||
fields = '__all__'
|
|
@ -1,90 +0,0 @@
|
|||
import datetime
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
import psutil
|
||||
|
||||
from apps.vadmin.monitor.models import Server, Monitor, SysFiles
|
||||
from apps.vadmin.op_drf.response import SuccessResponse
|
||||
from apps.vadmin.system.models import ConfigSettings
|
||||
from apps.vadmin.utils.decorators import BaseCeleryApp
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from platform import platform
|
||||
|
||||
|
||||
def getIP():
|
||||
"""获取ipv4地址"""
|
||||
dic = psutil.net_if_addrs()
|
||||
ipv4_list = []
|
||||
for adapter in dic:
|
||||
snicList = dic[adapter]
|
||||
for snic in snicList:
|
||||
if snic.family.name == 'AF_INET':
|
||||
ipv4 = snic.address
|
||||
if ipv4 != '127.0.0.1':
|
||||
ipv4_list.append(ipv4)
|
||||
if len(ipv4_list) >= 1:
|
||||
return ipv4_list[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@BaseCeleryApp(name='apps.vadmin.monitor.tasks.get_monitor_info', save_success_logs=False)
|
||||
def get_monitor_info():
|
||||
"""
|
||||
定时获取系统监控信息
|
||||
:return:
|
||||
"""
|
||||
# 获取服务器
|
||||
ip = getIP()
|
||||
if not ip:
|
||||
logger.error("无法获取到IP")
|
||||
return
|
||||
server_obj, create = Server.objects.get_or_create(ip=ip)
|
||||
if create:
|
||||
server_obj.name = ip
|
||||
terse = ('terse' in sys.argv or '--terse' in sys.argv)
|
||||
aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
|
||||
server_obj.os = platform(aliased, terse)
|
||||
server_obj.save()
|
||||
|
||||
# 获取CPU和内存信息
|
||||
mem = psutil.virtual_memory()
|
||||
monitor_obj = Monitor()
|
||||
monitor_obj.cpu_num = psutil.cpu_count()
|
||||
monitor_obj.cpu_sys = float(psutil.cpu_percent(0.1))
|
||||
monitor_obj.mem_num = int(mem.total / 1024)
|
||||
monitor_obj.mem_sys = int(mem.used / 1024)
|
||||
monitor_obj.seconds = time.strftime("%d天 %H 小时 %M 分 %S 秒", time.gmtime(int(time.time()) - int(psutil.boot_time())))
|
||||
monitor_obj.server = server_obj
|
||||
monitor_obj.save()
|
||||
|
||||
# 保存磁盘信息
|
||||
for ele in psutil.disk_partitions():
|
||||
disk = psutil.disk_usage('/')
|
||||
|
||||
sys_files_obj = SysFiles()
|
||||
sys_files_obj.dir_name = ele.mountpoint
|
||||
sys_files_obj.sys_type_name = ele.opts
|
||||
sys_files_obj.type_name = ele.fstype
|
||||
sys_files_obj.total = disk.total
|
||||
sys_files_obj.disk_sys = disk.used
|
||||
sys_files_obj.monitor = monitor_obj
|
||||
sys_files_obj.save()
|
||||
|
||||
return SuccessResponse(msg="")
|
||||
|
||||
|
||||
@BaseCeleryApp(name='apps.vadmin.monitor.tasks.clean_surplus_monitor_info')
|
||||
def clean_surplus_monitor_info():
|
||||
"""
|
||||
定时清理多余 系统监控信息
|
||||
:return:
|
||||
"""
|
||||
config_settings_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first()
|
||||
today = datetime.datetime.now().date()
|
||||
clean_day_before = today - datetime.timedelta(days=int(config_settings_obj.configValue or 30))
|
||||
Monitor.objects.filter(update_datetime__lt=clean_day_before).delete()
|
||||
logger.info(f"成功清空{config_settings_obj.configValue}天前数据")
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,16 +0,0 @@
|
|||
from django.urls import re_path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.vadmin.monitor.views import ServerModelViewSet, MonitorModelViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'server', ServerModelViewSet)
|
||||
router.register(r'monitor', MonitorModelViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
re_path('monitor/info/(?P<pk>.*)/', MonitorModelViewSet.as_view({'get': 'get_monitor_info'})),
|
||||
re_path('monitor/rate/(?P<pk>.*)/', MonitorModelViewSet.as_view({'get': 'get_rate_info'})),
|
||||
re_path('monitor/enabled/', MonitorModelViewSet.as_view({'get': 'enabled_monitor_info'})),
|
||||
re_path('monitor/clean/', MonitorModelViewSet.as_view({'get': 'clean_all'})),
|
||||
]
|
||||
urlpatterns += router.urls
|
|
@ -1,184 +0,0 @@
|
|||
from django_celery_beat.models import PeriodicTask, IntervalSchedule, CrontabSchedule
|
||||
from rest_framework.request import Request
|
||||
|
||||
from apps.vadmin.monitor.filters import ServerFilter, MonitorFilter
|
||||
from apps.vadmin.monitor.models import Server, Monitor, SysFiles
|
||||
from apps.vadmin.monitor.serializers import ServerSerializer, MonitorSerializer, UpdateServerSerializer
|
||||
from apps.vadmin.op_drf.response import SuccessResponse, ErrorResponse
|
||||
from apps.vadmin.op_drf.viewsets import CustomModelViewSet
|
||||
from apps.vadmin.permission.permissions import CommonPermission
|
||||
from apps.vadmin.system.models import ConfigSettings
|
||||
|
||||
|
||||
class ServerModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
服务器信息 模型的CRUD视图
|
||||
"""
|
||||
queryset = Server.objects.all()
|
||||
serializer_class = ServerSerializer
|
||||
update_serializer_class = UpdateServerSerializer
|
||||
# extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
filter_class = ServerFilter
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
ordering = '-create_datetime' # 默认排序
|
||||
|
||||
|
||||
class MonitorModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
服务器监控信息 模型的CRUD视图
|
||||
"""
|
||||
queryset = Monitor.objects.all()
|
||||
serializer_class = MonitorSerializer
|
||||
# extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
filter_class = MonitorFilter
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
ordering = '-create_datetime' # 默认排序
|
||||
|
||||
def get_rate_info(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
获取使用率 监控信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
pk = kwargs.get("pk")
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
queryset = queryset.filter(server__id=pk).order_by("create_datetime")
|
||||
# 间隔取值
|
||||
queryset_count = queryset.count()
|
||||
Interval_num = 1 if queryset_count < 200 else int(queryset_count / 100)
|
||||
queryset = queryset.values('cpu_sys', 'mem_num', 'mem_sys', 'create_datetime')[::Interval_num][:100]
|
||||
data = {
|
||||
"cpu": [],
|
||||
"memory": [],
|
||||
"datetime": [],
|
||||
}
|
||||
for ele in queryset:
|
||||
data["cpu"].append(round(float(ele.get('cpu_sys', 0)), 2))
|
||||
data["datetime"].append(ele.get('create_datetime').strftime('%Y-%m-%d %H:%M:%S'))
|
||||
data["memory"].append(round(float(ele.get('mem_num', 0)), 4) and round(float(ele.get('mem_sys', 0)) /
|
||||
float(ele.get('mem_num', 0)) * 100,
|
||||
2))
|
||||
return SuccessResponse(data=data)
|
||||
|
||||
def get_monitor_info(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
最新的服务器状态信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
pk = kwargs.get("pk")
|
||||
instance = Monitor.objects.filter(server__id=pk).order_by("-create_datetime").first()
|
||||
if not instance:
|
||||
return ErrorResponse(msg="未找到服务器信息id")
|
||||
serializer = self.get_serializer(instance)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data={
|
||||
"cpu": {
|
||||
"total": int(data.get('cpu_num'), 0),
|
||||
"used": "", # cpu核心 可不传,如指cpu当前主频,该值可以传
|
||||
"rate": float(data.get('cpu_sys', 0)) / 100,
|
||||
"unit": "核心", # 默认单位 核心
|
||||
},
|
||||
"memory": {
|
||||
"total": int(int(data.get('mem_num', 0)) / 1024),
|
||||
"used": int(int(data.get('mem_sys', 0)) / 1024),
|
||||
"rate": int(data.get('mem_num', 0)) and round(int(data.get('mem_sys', 0)) /
|
||||
int(data.get('mem_num', 0)), 4),
|
||||
"unit": "MB", # 默认单位 MB
|
||||
},
|
||||
"disk": [{
|
||||
"dir_name": ele.get('dir_name'),
|
||||
"total": int(int(ele.get('total', 0)) / 1024 / 1024 / 1024),
|
||||
"used": int(int(ele.get('disk_sys', 0)) / 1024 / 1024 / 1024),
|
||||
"rate": int(ele.get('total', 0)) and round(int(ele.get('disk_sys', 0)) / int(ele.get('total', 0)),
|
||||
4),
|
||||
"unit": "GB", # 默认单位 GB
|
||||
} for ele in SysFiles.objects.filter(monitor=instance).values('dir_name', 'total', 'disk_sys')]
|
||||
})
|
||||
|
||||
def enabled_monitor_info(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
更新和获取监控信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
enabled = request.query_params.get('enabled', None)
|
||||
save_days = request.query_params.get('save_days', None)
|
||||
interval = request.query_params.get('interval', None)
|
||||
# 定时获取系统监控信息
|
||||
periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first()
|
||||
if not periodictask_obj:
|
||||
intervalschedule_obj, _ = IntervalSchedule.objects.get_or_create(every=5, period="seconds")
|
||||
periodictask_obj = PeriodicTask()
|
||||
periodictask_obj.task = "apps.vadmin.monitor.tasks.get_monitor_info"
|
||||
periodictask_obj.name = "定时获取系统监控信息"
|
||||
periodictask_obj.interval = intervalschedule_obj
|
||||
periodictask_obj.enabled = False
|
||||
periodictask_obj.save()
|
||||
|
||||
# 定时清理多余 系统监控信息
|
||||
clean_task_obj = PeriodicTask.objects.filter(
|
||||
task='apps.vadmin.monitor.tasks.clean_surplus_monitor_info').first()
|
||||
if not clean_task_obj:
|
||||
crontab_obj, _ = CrontabSchedule.objects.get_or_create(day_of_month="*", day_of_week="*", hour="1",
|
||||
minute="0", month_of_year="*")
|
||||
clean_task_obj = PeriodicTask()
|
||||
clean_task_obj.task = "apps.vadmin.monitor.tasks.clean_surplus_monitor_info"
|
||||
clean_task_obj.name = "定时清理多余-系统监控信息"
|
||||
clean_task_obj.crontab = crontab_obj
|
||||
clean_task_obj.enabled = True
|
||||
clean_task_obj.save()
|
||||
# 配置添加
|
||||
config_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first()
|
||||
if not config_obj:
|
||||
config_obj = ConfigSettings()
|
||||
config_obj.configKey = "sys.monitor.info.save_days"
|
||||
config_obj.configName = "定时清理多余系统监控信息"
|
||||
config_obj.configValue = "30"
|
||||
config_obj.configType = "Y"
|
||||
config_obj.status = "1"
|
||||
config_obj.remark = "定时清理多余-系统监控信息,默认30天"
|
||||
config_obj.save()
|
||||
|
||||
if enabled:
|
||||
# 更新监控状态
|
||||
periodictask_obj.enabled = True if enabled == "1" else False
|
||||
periodictask_obj.save()
|
||||
|
||||
# 更新 定时清理多余 系统监控信息 状态
|
||||
clean_task_obj.enabled = True if enabled == "1" else False
|
||||
clean_task_obj.save()
|
||||
# 更新保留天数
|
||||
if save_days and config_obj:
|
||||
config_obj.configValue = save_days
|
||||
config_obj.save()
|
||||
# 更新监控获取频率
|
||||
if interval:
|
||||
periodictask_obj.interval.every = interval
|
||||
periodictask_obj.interval.save()
|
||||
return SuccessResponse(data={
|
||||
"enabled": periodictask_obj.enabled,
|
||||
"interval": periodictask_obj.interval.every,
|
||||
"save_days": config_obj.configValue if config_obj else "30",
|
||||
})
|
||||
|
||||
def clean_all(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
清空监控信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
self.get_queryset().delete()
|
||||
return SuccessResponse(msg="清空成功")
|
|
@ -1,13 +0,0 @@
|
|||
import logging
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpDrfConfig(AppConfig):
|
||||
name = 'apps.vadmin.op_drf'
|
||||
verbose_name = "OP DRF"
|
||||
|
||||
def ready(self):
|
||||
logging.info("OP DRF框架检测完成:success")
|
|
@ -1,155 +0,0 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from django.db.models import SET_NULL
|
||||
|
||||
from apps.vadmin.utils.string_util import uuid_8, uuid_16, uuid_32, uuid_36
|
||||
|
||||
|
||||
class IdField(models.CharField):
|
||||
"""
|
||||
id = IdField()
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 8)
|
||||
kwargs['primary_key'] = kwargs.get('primary_key', True)
|
||||
kwargs['unique'] = kwargs.get('unique', True)
|
||||
kwargs['db_index'] = kwargs.get('db_index', True)
|
||||
kwargs['default'] = kwargs.get('default', uuid_8)
|
||||
kwargs['null'] = kwargs.get('null', False)
|
||||
kwargs['blank'] = kwargs.get('blank', False)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', 'ID')
|
||||
kwargs['help_text'] = kwargs.get('help_text', 'ID')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UUID8Field(models.CharField):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 8)
|
||||
kwargs['default'] = kwargs.get('default', uuid_8)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', 'UUID')
|
||||
kwargs['help_text'] = kwargs.get('help_text', 'UUID')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UUID16Field(models.CharField):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 16)
|
||||
kwargs['default'] = kwargs.get('default', uuid_16)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', 'UUID')
|
||||
kwargs['help_text'] = kwargs.get('help_text', 'UUID')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UUID32Field(models.CharField):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 32)
|
||||
kwargs['default'] = kwargs.get('default', uuid_32)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', 'UUID')
|
||||
kwargs['help_text'] = kwargs.get('help_text', 'UUID')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UUID36Field(models.CharField):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 36)
|
||||
kwargs['unique'] = kwargs.get('unique', True)
|
||||
kwargs['default'] = kwargs.get('default', uuid_36)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', 'UUID')
|
||||
kwargs['help_text'] = kwargs.get('help_text', 'UUID')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class DescriptionField(models.TextField):
|
||||
"""
|
||||
description = DescriptionField()
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if kwargs.get('null', True):
|
||||
kwargs['default'] = kwargs.get('default', '')
|
||||
kwargs['blank'] = kwargs.get('blank', True)
|
||||
kwargs['null'] = kwargs.get('null', True)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', '描述')
|
||||
kwargs['help_text'] = kwargs.get('help_text', '') or kwargs.get('verbose_name', '描述')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UserForeignKeyField(models.ForeignKey):
|
||||
"""
|
||||
user = UserForeignKeyField()
|
||||
"""
|
||||
|
||||
def __init__(self, to=None, on_delete=None, related_name=None, related_query_name=None, limit_choices_to=None,
|
||||
parent_link=False, to_field=None, db_constraint=False, **kwargs):
|
||||
if to is None:
|
||||
to = get_user_model()
|
||||
if to_field is None:
|
||||
to_field = 'id'
|
||||
if on_delete is None:
|
||||
on_delete = SET_NULL
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', '关联的用户')
|
||||
kwargs['help_text'] = kwargs.get('help_text', '') or kwargs.get('verbose_name', '关联的用户')
|
||||
kwargs['editable'] = kwargs.get('default', False)
|
||||
super().__init__(to, on_delete, related_name, related_query_name, limit_choices_to, parent_link, to_field,
|
||||
db_constraint, **kwargs)
|
||||
|
||||
|
||||
class UpdateDateTimeField(models.DateTimeField):
|
||||
"""
|
||||
update_datetime = ModifyDateTimeField()
|
||||
"""
|
||||
|
||||
def __init__(self, verbose_name=None, name=None, auto_now=True, auto_now_add=False, **kwargs):
|
||||
verbose_name = verbose_name or '修改时间'
|
||||
kwargs['help_text'] = kwargs.get('help_text', '修改时间')
|
||||
kwargs['editable'] = kwargs.get('default', False)
|
||||
kwargs['blank'] = kwargs.get('blank', True)
|
||||
kwargs['null'] = kwargs.get('null', True)
|
||||
super().__init__(verbose_name, name, auto_now, auto_now_add, **kwargs)
|
||||
|
||||
|
||||
class CreateDateTimeField(models.DateTimeField):
|
||||
"""
|
||||
create_datetime = CreateDateTimeField()
|
||||
"""
|
||||
|
||||
def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=True, **kwargs):
|
||||
verbose_name = verbose_name or '创建时间'
|
||||
kwargs['help_text'] = kwargs.get('help_text', '创建时间')
|
||||
kwargs['editable'] = kwargs.get('default', False)
|
||||
kwargs['blank'] = kwargs.get('blank', True)
|
||||
kwargs['null'] = kwargs.get('null', True)
|
||||
super().__init__(verbose_name, name, auto_now, auto_now_add, **kwargs)
|
||||
|
||||
|
||||
class CreatorCharField(models.CharField):
|
||||
"""
|
||||
creator = CreatorCharField()
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 255)
|
||||
kwargs['null'] = kwargs.get('null', True)
|
||||
kwargs['blank'] = kwargs.get('blank', True)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', '创建者')
|
||||
kwargs['help_text'] = kwargs.get('help_text', '该记录的创建者')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class ModifierCharField(models.CharField):
|
||||
"""
|
||||
modifier = ModifierCharField()
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 255)
|
||||
kwargs['null'] = kwargs.get('null', True)
|
||||
kwargs['blank'] = kwargs.get('blank', True)
|
||||
kwargs['verbose_name'] = kwargs.get('verbose_name', '修改者')
|
||||
kwargs['help_text'] = kwargs.get('help_text', '该记录最后修改者')
|
||||
super().__init__(*args, **kwargs)
|
|
@ -1,151 +0,0 @@
|
|||
"""
|
||||
常用的过滤器以及DRF的过滤器
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import operator
|
||||
from functools import reduce
|
||||
|
||||
from django.utils import six
|
||||
from mongoengine.queryset import visitor
|
||||
from rest_framework.filters import BaseFilterBackend, SearchFilter, OrderingFilter
|
||||
|
||||
from apps.vadmin.utils.model_util import get_dept
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_as_kwargs(request):
|
||||
params = request.GET.dict()
|
||||
if 'as' not in params:
|
||||
return {}
|
||||
as_params = json.loads(params.get('as', '{}'))
|
||||
return as_params
|
||||
|
||||
|
||||
class MongoSearchFilter(SearchFilter):
|
||||
"""
|
||||
适配Mongo模型视图的Search过滤器
|
||||
"""
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
search_fields = getattr(view, 'search_fields', None)
|
||||
search_terms = self.get_search_terms(request)
|
||||
if not search_fields or not search_terms:
|
||||
return queryset
|
||||
orm_lookups = [
|
||||
self.construct_search(six.text_type(search_field))
|
||||
for search_field in search_fields
|
||||
]
|
||||
if not orm_lookups:
|
||||
return queryset
|
||||
conditions = []
|
||||
for search_term in search_terms:
|
||||
queries = [
|
||||
visitor.Q(**{orm_lookup: search_term})
|
||||
for orm_lookup in orm_lookups
|
||||
]
|
||||
conditions.append(reduce(operator.or_, queries))
|
||||
queryset = queryset.filter(reduce(operator.and_, conditions))
|
||||
return queryset
|
||||
|
||||
|
||||
class MongoOrderingFilter(OrderingFilter):
|
||||
"""
|
||||
适配Mongo模型视图的Search过滤器
|
||||
"""
|
||||
|
||||
def get_valid_fields(self, queryset, view, context={}):
|
||||
valid_fields = getattr(view, 'ordering_fields', self.ordering_fields)
|
||||
if valid_fields is None:
|
||||
return self.get_default_valid_fields(queryset, view, context)
|
||||
elif valid_fields == '__all__':
|
||||
# View explicitly allows filtering on any model field
|
||||
model = view.get_serializer().__class__.Meta.model
|
||||
valid_fields = [
|
||||
(field_name, getattr(field, 'verbose_name', field_name)) for field_name, field in model._fields.items()
|
||||
]
|
||||
else:
|
||||
valid_fields = [
|
||||
(item, item) if isinstance(item, six.string_types) else item
|
||||
for item in valid_fields
|
||||
]
|
||||
|
||||
return valid_fields
|
||||
|
||||
|
||||
class AdvancedSearchFilter(BaseFilterBackend):
|
||||
"""
|
||||
高级搜索过滤器
|
||||
"""
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
as_kwargs = get_as_kwargs(request)
|
||||
if as_kwargs:
|
||||
queryset = queryset.filter(**as_kwargs)
|
||||
return queryset
|
||||
|
||||
|
||||
class MongoAdvancedSearchFilter(BaseFilterBackend):
|
||||
"""
|
||||
mongo高级搜索过滤器
|
||||
"""
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
as_kwargs = get_as_kwargs(request)
|
||||
if as_kwargs:
|
||||
queryset = queryset.filter(**as_kwargs)
|
||||
return queryset
|
||||
|
||||
|
||||
class DataLevelPermissionsFilter(BaseFilterBackend):
|
||||
"""
|
||||
数据 级权限过滤器
|
||||
0. 获取用户的部门id,没有部门则返回空
|
||||
1. 判断过滤的数据是否有创建人所在部门 "creator" 字段,没有则返回全部
|
||||
2. 如果用户没有关联角色则返回本部门数据
|
||||
3. 根据角色的最大权限进行数据过滤(会有多个角色,进行去重取最大权限)
|
||||
3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据
|
||||
|
||||
4. 只为仅本人数据权限时只返回过滤本人数据,并且部门为自己本部门(考虑到用户会变部门,只能看当前用户所在的部门数据)
|
||||
5. 自定数据权限 获取部门,根据部门过滤
|
||||
"""
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
# 0. 获取用户的部门id,没有部门则返回空
|
||||
user_dept_id = getattr(request.user, 'dept_id')
|
||||
if not user_dept_id:
|
||||
return queryset.none()
|
||||
|
||||
# 1. 判断过滤的数据是否有创建人所在部门 "dept_belong_id" 字段
|
||||
if not getattr(queryset.model, 'dept_belong_id', None):
|
||||
return queryset
|
||||
|
||||
# 2. 如果用户没有关联角色则返回本部门数据
|
||||
if not hasattr(request.user, 'role'):
|
||||
return queryset.filter(dept_belong_id=user_dept_id)
|
||||
|
||||
# 3. 根据所有角色 获取所有权限范围
|
||||
role_list = request.user.role.filter(status='1').values('admin', 'dataScope')
|
||||
dataScope_list = []
|
||||
for ele in role_list:
|
||||
# 3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据
|
||||
if '1' == ele.get('dataScope') or ele.get('admin') == True:
|
||||
return queryset
|
||||
dataScope_list.append(ele.get('dataScope'))
|
||||
dataScope_list = list(set(dataScope_list))
|
||||
|
||||
# 4. 只为仅本人数据权限时只返回过滤本人数据,并且部门为自己本部门(考虑到用户会变部门,只能看当前用户所在的部门数据)
|
||||
if dataScope_list == ['5']:
|
||||
return queryset.filter(creator=request.user, dept_belong_id=user_dept_id)
|
||||
|
||||
# 5. 自定数据权限 获取部门,根据部门过滤
|
||||
dept_list = []
|
||||
for ele in dataScope_list:
|
||||
if ele == '2':
|
||||
dept_list.extend(request.user.role.filter(status='1').values_list('dept__id', flat=True))
|
||||
elif ele == '3':
|
||||
dept_list.append(user_dept_id)
|
||||
elif ele == '4':
|
||||
dept_list.extend(get_dept(user_dept_id, ))
|
||||
return queryset.filter(dept_belong_id__in=list(set(dept_list)))
|
|
@ -1,465 +0,0 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db.models.query import QuerySet
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404 as _get_object_or_404
|
||||
from rest_framework.settings import api_settings
|
||||
|
||||
from apps.vadmin.utils.jsonpath_util import get_jsonpath, filter_json, search_json
|
||||
from apps.vadmin.utils.sort_util import sortList
|
||||
from . import mixins
|
||||
from .pagination import JsonPagination
|
||||
from .response import SuccessResponse
|
||||
from .views import CustomAPIView
|
||||
|
||||
|
||||
def get_object_or_404(queryset, *filter_args, **filter_kwargs):
|
||||
"""
|
||||
Same as Django's standard shortcut, but make sure to also raise 404
|
||||
if the filter_kwargs don't match the required types.
|
||||
"""
|
||||
try:
|
||||
return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
|
||||
except (TypeError, ValueError, ValidationError):
|
||||
raise Http404
|
||||
|
||||
|
||||
class GenericAPIView(CustomAPIView):
|
||||
"""
|
||||
Base class for all other generic views.
|
||||
"""
|
||||
# You'll need to either set these attributes,
|
||||
# or override `get_queryset()`/`get_serializer_class()`.
|
||||
# If you are overriding a view method, it is important that you call
|
||||
# `get_queryset()` instead of accessing the `queryset` property directly,
|
||||
# as `queryset` will get evaluated only once, and those results are cached
|
||||
# for all subsequent requests.
|
||||
queryset = None
|
||||
serializer_class = None
|
||||
|
||||
# If you want to use object lookups other than pk, set 'lookup_field'.
|
||||
# For more complex lookup requirements override `get_object()`.
|
||||
lookup_field = 'pk'
|
||||
lookup_url_kwarg = None
|
||||
|
||||
# The filter backend classes to use for queryset filtering
|
||||
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
|
||||
|
||||
# The style to use for queryset pagination.
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
Get the list of items for this view.
|
||||
This must be an iterable, and may be a queryset.
|
||||
Defaults to using `self.queryset`.
|
||||
|
||||
This method should always be used rather than accessing `self.queryset`
|
||||
directly, as `self.queryset` gets evaluated only once, and those results
|
||||
are cached for all subsequent requests.
|
||||
|
||||
You may want to override this if you need to provide different
|
||||
querysets depending on the incoming request.
|
||||
|
||||
(Eg. return a list of items that is specific to the user)
|
||||
"""
|
||||
assert self.queryset is not None, (
|
||||
"'%s' should either include a `queryset` attribute, "
|
||||
"or override the `get_queryset()` method."
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
queryset = self.queryset
|
||||
if isinstance(queryset, QuerySet):
|
||||
# Ensure queryset is re-evaluated on each request.
|
||||
queryset = queryset.all()
|
||||
return queryset
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
Returns the object the view is displaying.
|
||||
|
||||
You may want to override this if you need to provide non-standard
|
||||
queryset lookups. Eg if objects are referenced using multiple
|
||||
keyword arguments in the url conf.
|
||||
"""
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, obj)
|
||||
|
||||
return obj
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""
|
||||
Return the serializer instance that should be used for validating and
|
||||
deserializing input, and for serializing output.
|
||||
"""
|
||||
serializer_class = self.get_serializer_class()
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
return serializer_class(*args, **kwargs)
|
||||
|
||||
def get_serializer_class(self):
|
||||
"""
|
||||
Return the class to use for the serializer.
|
||||
Defaults to using `self.serializer_class`.
|
||||
|
||||
You may want to override this if you need to provide different
|
||||
serializations depending on the incoming request.
|
||||
|
||||
(Eg. admins get full serialization, others get basic serialization)
|
||||
"""
|
||||
assert self.serializer_class is not None, (
|
||||
"'%s' should either include a `serializer_class` attribute, "
|
||||
"or override the `get_serializer_class()` method."
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
return self.serializer_class
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""
|
||||
Extra context provided to the serializer class.
|
||||
"""
|
||||
return {
|
||||
'request': self.request,
|
||||
'format': self.format_kwarg,
|
||||
'view': self
|
||||
}
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
"""
|
||||
Given a queryset, filter it with whichever filter backend is in use.
|
||||
|
||||
You are unlikely to want to override this method, although you may need
|
||||
to call it either from a list view, or from a custom `get_object`
|
||||
method if you want to apply the configured filtering backend to the
|
||||
default queryset.
|
||||
"""
|
||||
for backend in list(self.filter_backends):
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
return queryset
|
||||
|
||||
@property
|
||||
def paginator(self):
|
||||
"""
|
||||
The paginator instance associated with the view, or `None`.
|
||||
"""
|
||||
if not hasattr(self, '_paginator'):
|
||||
if self.pagination_class is None:
|
||||
self._paginator = None
|
||||
else:
|
||||
self._paginator = self.pagination_class()
|
||||
return self._paginator
|
||||
|
||||
def paginate_queryset(self, queryset):
|
||||
"""
|
||||
Return a single page of results, or `None` if pagination is disabled.
|
||||
"""
|
||||
if self.paginator is None:
|
||||
return None
|
||||
return self.paginator.paginate_queryset(queryset, self.request, view=self)
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
"""
|
||||
Return a paginated style `Response` object for the given output data.
|
||||
"""
|
||||
assert self.paginator is not None
|
||||
return self.paginator.get_paginated_response(data)
|
||||
|
||||
|
||||
# Concrete view classes that provide method handlers
|
||||
# by composing the mixin classes with the base view.
|
||||
|
||||
class CreateAPIView(mixins.CreateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for creating a model instance.
|
||||
"""
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.create(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ListAPIView(mixins.ListModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for listing a queryset.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.list(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveAPIView(mixins.RetrieveModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving a model instance.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
class DestroyAPIView(mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for deleting a model instance.
|
||||
"""
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class UpdateAPIView(mixins.UpdateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for updating a model instance.
|
||||
"""
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ListCreateAPIView(mixins.ListModelMixin,
|
||||
mixins.CreateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for listing a queryset or creating a model instance.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.list(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.create(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving, updating a model instance.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving or deleting a model instance.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving, updating or deleting a model instance.
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class JsonListView(GenericAPIView):
|
||||
"""
|
||||
JsonList的查询、过滤、搜索、排序通用视图
|
||||
"""
|
||||
# 模糊搜索
|
||||
search_param = api_settings.SEARCH_PARAM
|
||||
search_fields = []
|
||||
|
||||
ordering_param = api_settings.ORDERING_PARAM
|
||||
# 可排序属性,默认所有属性可排序
|
||||
ordering_fields = '__all__'
|
||||
|
||||
pagination_class = JsonPagination
|
||||
queryset: list = []
|
||||
pagination_total = 0
|
||||
|
||||
# 返回的属性
|
||||
response_fields = '__all__'
|
||||
# response_fields = ['app_code', 'ip', 'hostname', 'host_type', 'host_env']
|
||||
# 默认排序, 只支持view中设置ordering, 暂不支持排序参数由请求动态传入
|
||||
ordering = None # 正序
|
||||
# ordering = '-ip' # 倒序
|
||||
|
||||
_has_ordering = False
|
||||
_exclude_params = []
|
||||
# 属性
|
||||
_json_fields = None
|
||||
|
||||
@property
|
||||
def paginator(self):
|
||||
if not hasattr(self, '_paginator'):
|
||||
if self.pagination_class is None:
|
||||
self._paginator = None
|
||||
else:
|
||||
self._paginator = self.pagination_class(len(self.get_queryset()))
|
||||
self._paginator.request = self.request
|
||||
return self._paginator
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
"""
|
||||
使用jsonpath实现, 重写对查询集的条件过滤逻辑
|
||||
:param queryset:
|
||||
:return:
|
||||
"""
|
||||
if not self._exclude_params:
|
||||
self.__class__._exclude_params = []
|
||||
self.__class__._exclude_params.append(self.paginator.page_size_query_param)
|
||||
self.__class__._exclude_params.append(self.paginator.page_query_param)
|
||||
self.__class__._exclude_params.extend(self.paginator.other_page_size_query_param)
|
||||
self.__class__._exclude_params.extend(self.paginator.other_page_query_param)
|
||||
self.__class__._exclude_params.append(self.ordering_param)
|
||||
self.__class__._exclude_params.append(self.search_param)
|
||||
expr = get_jsonpath(self.request.query_params, self._exclude_params, self.json_fields)
|
||||
if not expr:
|
||||
return queryset
|
||||
_queryset = filter_json(self.get_queryset(), expr)
|
||||
if not _queryset:
|
||||
_queryset = []
|
||||
return _queryset
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
获取查询集/初始化查询集
|
||||
:return:
|
||||
"""
|
||||
return self.queryset
|
||||
|
||||
@property
|
||||
def json_fields(self):
|
||||
if self._json_fields is None:
|
||||
queryset = self.get_queryset()
|
||||
if len(queryset):
|
||||
ele: dict = queryset[0]
|
||||
self.__class__._json_fields = {key: value.__class__.__name__ for (key, value) in ele.items()}
|
||||
else:
|
||||
self.__class__._json_fields = []
|
||||
return self._json_fields
|
||||
|
||||
def queryset_ordering(self):
|
||||
"""
|
||||
查询集排序
|
||||
:return:
|
||||
"""
|
||||
if self._has_ordering:
|
||||
return
|
||||
_ordering = self.ordering
|
||||
if _ordering and self.ordering.startswith('-'):
|
||||
_ordering = self.ordering[1:]
|
||||
if _ordering and _ordering in self.json_fields:
|
||||
if (isinstance(self.ordering_fields,
|
||||
str) and self.ordering_fields.lower() == '__all__') or _ordering in self.ordering_fields:
|
||||
sortList(self.get_queryset(), self.ordering)
|
||||
self.__class__._has_ordering = True
|
||||
|
||||
def queryset_search(self, queryset):
|
||||
search_value = self.request.query_params.get(self.search_param, None)
|
||||
if self.search_fields and search_value:
|
||||
queryset = search_json(queryset, search_value, self.search_fields)
|
||||
return queryset
|
||||
|
||||
def paginate_queryset(self, queryset):
|
||||
"""
|
||||
重写内存分页逻辑
|
||||
:param queryset:
|
||||
:return:
|
||||
"""
|
||||
paginator: JsonPagination = self.paginator
|
||||
if paginator is None:
|
||||
return queryset
|
||||
request = self.request
|
||||
page_size = paginator.get_page_size(request)
|
||||
page_num = paginator.get_page_num(request)
|
||||
start_index = (page_num - 1) * page_size
|
||||
end_index = start_index + page_size
|
||||
page_expr = f"$[{start_index}:{end_index}]"
|
||||
queryset = filter_json(queryset, page_expr)
|
||||
return queryset
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
"""
|
||||
重写分页的返回格式
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
if self.paginator is None:
|
||||
return SuccessResponse(data)
|
||||
return self.paginator.get_paginated_response(data, self.pagination_total)
|
||||
|
||||
def filter_response_fields(self, data):
|
||||
"""
|
||||
过滤掉不显示的字段
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
if isinstance(self.response_fields, str) and self.response_fields.lower() == '__all__':
|
||||
return data
|
||||
data = [{key: value for key, value in ele.items() if key in self.response_fields} for ele in data]
|
||||
return data
|
||||
|
||||
def filter_json(self):
|
||||
"""
|
||||
过滤
|
||||
(1)查询集排序, 根据ordering对查询集进行正序/倒序
|
||||
(2)查询集过滤,根据请求参数传入的属性值
|
||||
(3)分页, 如果存在分页器, 根据输入的分页参数分页
|
||||
(4)属性字段过滤, 过滤掉不需要返回的属性值
|
||||
:return:
|
||||
"""
|
||||
self.queryset_ordering()
|
||||
queryset = self.get_queryset()
|
||||
queryset = self.filter_queryset(queryset)
|
||||
queryset = self.queryset_search(queryset)
|
||||
self.paginator.data_count = len(queryset)
|
||||
|
||||
queryset = self.paginate_queryset(queryset)
|
||||
data = self.filter_response_fields(queryset)
|
||||
return data
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
data = self.filter_json()
|
||||
return self.get_paginated_response(data)
|
|
@ -1,8 +0,0 @@
|
|||
import logging
|
||||
|
||||
|
||||
class RedisHandler(logging.StreamHandler):
|
||||
|
||||
def emit(self, record):
|
||||
msg = self.format(record)
|
||||
print(msg)
|
|
@ -1,213 +0,0 @@
|
|||
import logging
|
||||
|
||||
from django.db.models import Model
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.views import APIView
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ViewLogger(object):
|
||||
"""
|
||||
基于View视图的日志
|
||||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__()
|
||||
self.view = view
|
||||
self.request = request
|
||||
self.model = None
|
||||
self.log_prefix: str = ''
|
||||
if self.view and hasattr(self.view.get_queryset(), 'model'):
|
||||
self.model: Model = self.view.get_queryset().model
|
||||
elif self.view and hasattr(self.view.get_serializer(), 'Meta') and hasattr(self.view.get_serializer().Meta,
|
||||
'model'):
|
||||
self.model: Model = self.view.get_serializer().Meta.model
|
||||
if self.model:
|
||||
request.session['model_name'] = str(getattr(self.model, '_meta').verbose_name)
|
||||
|
||||
def handle(self, request: Request, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def logger(self, msg):
|
||||
"""
|
||||
|
||||
:param msg:
|
||||
:return: logger
|
||||
"""
|
||||
self.request.session['request_msg'] = msg
|
||||
return logger
|
||||
|
||||
|
||||
class APIViewLogger(ViewLogger):
|
||||
"""
|
||||
(1)仅在op_drf.views.CustomAPIView的子类中生效
|
||||
(2)使用: 请勿直接配置view_logger_classes = (APIViewLogger, ), 这样无效,
|
||||
如有需求, 需要继承APIViewLogger重写其相应的方法
|
||||
(3)重写handle()方法,所有请求均触发此方法
|
||||
重写handle_get()方法,仅GET请求均触发此方法
|
||||
重写handle_post()方法,仅POST请求均触发此方法
|
||||
重写handle_put()方法,仅PUT请求均触发此方法
|
||||
重写handle_delete()方法,仅DELETE请求均触发此方法
|
||||
重写handle_xxx()方法,仅xxx请求均触发此方法
|
||||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request, *args, **kwargs)
|
||||
self.view: APIView = view
|
||||
self.request: Request = request
|
||||
self.user = request.user
|
||||
|
||||
|
||||
class ModelViewLogger(APIViewLogger):
|
||||
"""
|
||||
基础模型操作日志
|
||||
(1)仅在op_drf.viewsets.GenericViewSet的子类中生效
|
||||
(1)在CustomModelViewSet子类中配置: view_logger_classes = [ModelViewLogger, ]
|
||||
(2)不要在op_drf中继续写具体的日志逻辑代码,
|
||||
如有需求, 应该继承ModelViewLogger并且重写相应的方法, 例如CustomerModelViewLogger(涉及到其他模块时不要将代码放入op_drf)
|
||||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request, *args, **kwargs)
|
||||
|
||||
|
||||
class RelationshipViewLogger(APIViewLogger):
|
||||
"""
|
||||
关联关系模型操作日志
|
||||
(1)在ModelRelationshipView子类中配置: view_logger_classes = [RelationshipViewLogger, ]
|
||||
(2)不要在op_drf中继续写具体的日志逻辑代码,
|
||||
如有需求, 应该继承RelationshipViewLogger并且重写相应的方法, 例如CustomerRelationshipViewLogger(涉及到其他模块时不要将代码放入op_drf)
|
||||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, instanceId=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request)
|
||||
self.instanceId: str = instanceId
|
||||
|
||||
def handle(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
每一次请求都会触发此方法
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class CustomerRelationshipViewLogger(RelationshipViewLogger):
|
||||
"""
|
||||
(1)在ModelRelationshipView子类中配置: view_logger_classes = [CustomerRelationshipViewLogger, ]
|
||||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, instanceId=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request, instanceId, *args, **kwargs)
|
||||
self.log_prefix: str = 'RelationshipView日志系统:'
|
||||
|
||||
def handle_get(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
仅GET请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
|
||||
def handle_post(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
仅POST请求才会触发此方法
|
||||
"""
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]新增, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
def handle_put(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
仅PUT请求才会触发此方法
|
||||
"""
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]重置, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
def handle_delete(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
仅DELETE请求才会触发此方法
|
||||
"""
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]移除, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
|
||||
class CustomerModelViewLogger(ModelViewLogger):
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request, *args, **kwargs)
|
||||
self.log_prefix: str = 'CustomModelViewSet日志系统:'
|
||||
|
||||
def handle(self, request: Request, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def handle_retrieve(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅retrieve(GET)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]检索{model_name}:[{instance}]')
|
||||
|
||||
def handle_list(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
仅list(GET)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]查询{model_name}')
|
||||
|
||||
def handle_create(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅create(POST)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]创建{model_name}:[{instance}]')
|
||||
|
||||
def handle_update(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅update(PUT)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]更新{model_name}:[{instance}]')
|
||||
|
||||
def handle_partial_update(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅partial_update(PATCH)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]部分更新{model_name}:[{instance}]')
|
||||
|
||||
def handle_destroy(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅destroy(DELETE)请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]删除{model_name}:[{instance}]')
|
||||
|
||||
def handle_other(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅 其他 请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]其他请求{model_name}:[{instance}]')
|
|
@ -1,78 +0,0 @@
|
|||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from application.settings import BASE_DIR
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
创建App命令:
|
||||
python manage.py createapp app名
|
||||
python manage.py createapp app01 app02 ...
|
||||
python manage.py createapp 一级文件名/app01 ... # 支持多级目录建app
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('app_name', nargs='*', type=str, )
|
||||
|
||||
def handle(self, *args, **options):
|
||||
app_name = options.get('app_name')
|
||||
for name in app_name:
|
||||
names = name.split('/')
|
||||
dnames = ".".join(names)
|
||||
app_path = os.path.join(BASE_DIR, "apps", *names)
|
||||
# 判断app是否存在
|
||||
if os.path.exists(app_path):
|
||||
print(f"创建失败,App {name} 已存在!")
|
||||
break
|
||||
source_path = os.path.join(BASE_DIR, "apps", "vadmin", "template")
|
||||
target_path = app_path
|
||||
if not os.path.exists(target_path):
|
||||
# 如果目标路径不存在原文件夹的话就创建
|
||||
os.makedirs(target_path)
|
||||
if os.path.exists(source_path):
|
||||
# 如果目标路径存在原文件夹的话就先删除
|
||||
shutil.rmtree(target_path)
|
||||
shutil.copytree(source_path, target_path)
|
||||
# 修改app中的apps 内容
|
||||
content = f"""from django.apps import AppConfig
|
||||
|
||||
|
||||
class {name[-1].capitalize()}Config(AppConfig):
|
||||
name = 'apps.{dnames}'
|
||||
verbose_name = "{names[-1]}App"
|
||||
"""
|
||||
with open(os.path.join(app_path, "apps.py"), 'w', encoding='UTF-8') as f:
|
||||
f.write(content)
|
||||
f.close()
|
||||
# 注册app到 settings.py 中
|
||||
injection(os.path.join(BASE_DIR, "application", "settings.py"), f" 'apps.{dnames}',\n", "INSTALLED_APPS",
|
||||
"]")
|
||||
|
||||
# 注册app到 urls.py 中
|
||||
injection(os.path.join(BASE_DIR, "application", "urls.py"),
|
||||
f" re_path(r'^{name}/', include('apps.{dnames}.urls')),\n", "urlpatterns = [",
|
||||
"]")
|
||||
|
||||
print(f"创建 {name} App成功")
|
||||
|
||||
|
||||
def injection(file_path, insert_content, startswith, endswith):
|
||||
with open(file_path, "r+", encoding="utf-8") as f:
|
||||
data = f.readlines()
|
||||
with open(file_path, 'w', encoding='UTF-8') as f1:
|
||||
is_INSTALLED_APPS = False
|
||||
is_insert = False
|
||||
for content in data:
|
||||
# 判断文件是否 INSTALLED_APPS 开头
|
||||
if not is_insert and content.startswith(startswith):
|
||||
is_INSTALLED_APPS = True
|
||||
if not is_insert and content.startswith(endswith) and is_INSTALLED_APPS:
|
||||
# 给前一行插入数据
|
||||
content = insert_content + content
|
||||
is_insert = True
|
||||
f1.writelines(content)
|
|
@ -1,169 +0,0 @@
|
|||
"""
|
||||
django中间件
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
from apps.vadmin.op_drf.response import ErrorJsonResponse
|
||||
from apps.vadmin.permission.models import Menu
|
||||
from apps.vadmin.system.models import OperationLog
|
||||
from apps.vadmin.utils.request_util import get_request_ip, get_request_data, get_request_path, get_browser, get_os, \
|
||||
get_login_location, get_request_canonical_path, get_request_user, get_verbose_name
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
"""
|
||||
用于记录API访问日志中间件
|
||||
"""
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
super().__init__(get_response)
|
||||
self.enable = getattr(settings, 'API_LOG_ENABLE', None) or False
|
||||
self.methods = getattr(settings, 'API_LOG_METHODS', None) or set()
|
||||
|
||||
@classmethod
|
||||
def __handle_request(cls, request):
|
||||
request.request_ip = get_request_ip(request)
|
||||
request.request_data = get_request_data(request)
|
||||
request.request_path = get_request_path(request)
|
||||
|
||||
@classmethod
|
||||
def __handle_response(cls, request, response):
|
||||
# request_data,request_ip由PermissionInterfaceMiddleware中间件中添加的属性
|
||||
body = getattr(request, 'request_data', {})
|
||||
# 请求含有password则用*替换掉(暂时先用于所有接口的password请求参数)
|
||||
if isinstance(body, dict) and body.get('password', ''):
|
||||
body['password'] = '*' * len(body['password'])
|
||||
if not hasattr(response, 'data') or not isinstance(response.data, dict):
|
||||
response.data = {}
|
||||
if not response.data and response.content:
|
||||
try:
|
||||
content = json.loads(response.content.decode())
|
||||
response.data = content if isinstance(content, dict) else {}
|
||||
except:
|
||||
pass
|
||||
user = get_request_user(request)
|
||||
info = {
|
||||
'request_ip': getattr(request, 'request_ip', 'unknown'),
|
||||
'creator': user if not isinstance(user, AnonymousUser) else None,
|
||||
'dept_belong_id': getattr(request.user, 'dept_id', None),
|
||||
'request_method': request.method,
|
||||
'request_path': request.request_path,
|
||||
'request_body': body,
|
||||
'response_code': response.data.get('code'),
|
||||
'request_location': get_login_location(request),
|
||||
'request_os': get_os(request),
|
||||
'request_browser': get_browser(request),
|
||||
'request_msg': request.session.get('request_msg'),
|
||||
'status': True if response.data.get('code') in [200, 204] else False,
|
||||
'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
|
||||
'request_modular': request.session.get('model_name'),
|
||||
}
|
||||
log = OperationLog(**info)
|
||||
log.save()
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
if hasattr(view_func, 'cls') and hasattr(view_func.cls, 'queryset'):
|
||||
request.session['model_name'] = get_verbose_name(view_func.cls.queryset)
|
||||
return
|
||||
|
||||
def process_request(self, request):
|
||||
self.__handle_request(request)
|
||||
|
||||
def process_response(self, request, response):
|
||||
"""
|
||||
主要请求处理完之后记录
|
||||
:param request:
|
||||
:param response:
|
||||
:return:
|
||||
"""
|
||||
if self.enable:
|
||||
if self.methods == 'ALL' or request.method in self.methods:
|
||||
self.__handle_response(request, response)
|
||||
return response
|
||||
|
||||
|
||||
class PermissionModeMiddleware(MiddlewareMixin):
|
||||
"""
|
||||
权限模式拦截判断
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
return
|
||||
|
||||
def has_interface_permission(self, request, method, view_path, user=None):
|
||||
"""
|
||||
接口权限验证,优先级:
|
||||
(1)接口是否接入权限管理, 是:继续; 否:通过
|
||||
(2)认证的user是否superuser, 是:通过; 否:继续
|
||||
(3)user的角色有该接口权限, 是:通过, 否:不通过
|
||||
|
||||
auth_code含义: auth_code >=0, 表示接口认证通过; auth_code < 0, 表示无接口访问权限, 具体含义如下
|
||||
-1:
|
||||
-10: 该请求已认证的用户没有这个接口的访问权限
|
||||
0:
|
||||
1: 白名单
|
||||
10: 该接口没有录入权限系统, 放行 请求中认证的用户为超级管理员, 直接放行
|
||||
20: 请求中认证的用户是superuser放行
|
||||
30: 请求中认证的用户对应的角色中,某个角色包含了该接口的访问权限, 放行
|
||||
1. 先获取所有录入系统的接口
|
||||
2 判断此用户是否为 superuser
|
||||
3. 获取此用户所请求的接口
|
||||
4. 获取此用户关联角色所有有权限的接口
|
||||
|
||||
:param interface: 接口模型
|
||||
:param path: 接口路径
|
||||
:param method: 请求方法
|
||||
:param project: 接口所属项目
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
interface_dict = Menu.get_interface_dict()
|
||||
# (1) 接口是否接入权限管理, 是:继续; 否:通过
|
||||
if not view_path in interface_dict.get(method, []):
|
||||
return 10
|
||||
# (2)认证的user是否superuser, 是:通过; 否:继续
|
||||
if user.is_superuser or (hasattr(user, 'role') and user.role.filter(status='1', admin=True).count()):
|
||||
return 20
|
||||
# (3)user的角色有该接口权限, 是:通过, 否:不通过
|
||||
if view_path in user.get_user_interface_dict.get(method, []):
|
||||
return 30
|
||||
return -10
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
# 判断环境变量中,是否为演示模式(正常可忽略此判断)
|
||||
white_list = ['/admin/logout/', '/admin/login/', '/admin/api-auth/login/']
|
||||
if os.getenv('DEMO_ENV') and not request.method in ['GET', 'OPTIONS'] and request.path not in white_list:
|
||||
return ErrorJsonResponse(data={}, msg=f'演示模式,不允许操作!')
|
||||
|
||||
if not settings.INTERFACE_PERMISSION:
|
||||
return
|
||||
user = get_request_user(request)
|
||||
|
||||
if user and not isinstance(user, AnonymousUser):
|
||||
method = request.method.upper()
|
||||
if method == 'GET': # GET 不设置接口权限
|
||||
return
|
||||
view_path = get_request_canonical_path(request, *view_args, **view_kwargs)
|
||||
auth_code = self.has_interface_permission(request, method, view_path, user)
|
||||
logger.info(f"[{user.username}] {method}:{view_path}, 权限认证:{auth_code}")
|
||||
if auth_code >= 0:
|
||||
return
|
||||
return ErrorJsonResponse(data={}, msg=f'无接口访问权限!')
|
||||
|
||||
def process_response(self, request, response):
|
||||
"""
|
||||
主要请求处理完之后记录
|
||||
:param request:
|
||||
:param response:
|
||||
:return:
|
||||
"""
|
||||
return response
|
|
@ -1,366 +0,0 @@
|
|||
from django.db import transaction
|
||||
from rest_framework import mixins
|
||||
from rest_framework import serializers
|
||||
from rest_framework import status
|
||||
from rest_framework.relations import ManyRelatedField, RelatedField, PrimaryKeyRelatedField
|
||||
from rest_framework.request import Request
|
||||
|
||||
from apps.vadmin.utils.export_excel import excel_to_data, export_excel_save_model
|
||||
from apps.vadmin.utils.request_util import get_verbose_name
|
||||
from .response import SuccessResponse
|
||||
|
||||
|
||||
class CreateModelMixin(mixins.CreateModelMixin):
|
||||
"""
|
||||
继承、增强DRF的CreateModelMixin, 标准化其返回值
|
||||
"""
|
||||
create_serializer_class = None
|
||||
|
||||
def create(self, request: Request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_create(serializer)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=serializer.instance, *args, **kwargs)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return SuccessResponse(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
super().perform_create(serializer)
|
||||
|
||||
|
||||
class ListModelMixin(mixins.ListModelMixin):
|
||||
"""
|
||||
继承、增强DRF的CreateModelMixin, 标准化其返回值
|
||||
"""
|
||||
list_serializer_class = None
|
||||
|
||||
def list(self, request: Request, *args, **kwargs):
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
if getattr(self, 'values_queryset', None):
|
||||
return self.get_paginated_response(page)
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
if getattr(self, 'values_queryset', None):
|
||||
return SuccessResponse(page)
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
|
||||
class RetrieveModelMixin(mixins.RetrieveModelMixin):
|
||||
"""
|
||||
继承、增强DRF的CreateModelMixin, 标准化其返回值
|
||||
"""
|
||||
retrieve_serializer_class = None
|
||||
|
||||
def retrieve(self, request: Request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
|
||||
class UpdateModelMixin(mixins.UpdateModelMixin):
|
||||
"""
|
||||
继承、增强DRF的CreateModelMixin, 标准化其返回值
|
||||
"""
|
||||
update_serializer_class = None
|
||||
|
||||
def update(self, request: Request, *args, **kwargs):
|
||||
partial = kwargs.pop('partial', False)
|
||||
instance = self.get_object()
|
||||
serializer = self.get_serializer(instance, data=request.data, partial=partial)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_update(serializer)
|
||||
if getattr(instance, '_prefetched_objects_cache', None):
|
||||
instance._prefetched_objects_cache = {}
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def partial_update(self, request, *args, **kwargs):
|
||||
kwargs['partial'] = True
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class DestroyModelMixin(mixins.DestroyModelMixin):
|
||||
"""
|
||||
继承、增强DRF的CreateModelMixin, 标准化其返回值
|
||||
"""
|
||||
destroy_serializer_class = None
|
||||
|
||||
def get_object_list(self):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
filter_kwargs = {f"{self.lookup_field}__in": self.kwargs[lookup_url_kwarg].split(',')}
|
||||
obj = queryset.filter(**filter_kwargs)
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
|
||||
def destroy(self, request: Request, *args, **kwargs):
|
||||
instance = self.get_object_list()
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
self.perform_destroy(instance)
|
||||
return SuccessResponse(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
instance.delete()
|
||||
|
||||
|
||||
class TableSerializerMixin:
|
||||
table_option = None
|
||||
extra_columns = []
|
||||
|
||||
FIELD_TYPE_MAP = {
|
||||
'AutoField': {
|
||||
'type': 'input',
|
||||
'addDisabled': True,
|
||||
},
|
||||
|
||||
'CharField': {
|
||||
'type': 'input',
|
||||
"maxlength": 255
|
||||
},
|
||||
|
||||
'PasswordField': {
|
||||
'type': 'input',
|
||||
'maxlength': 255
|
||||
},
|
||||
|
||||
'URLField': {
|
||||
'type': 'input',
|
||||
},
|
||||
|
||||
'UUIDField': {
|
||||
'type': 'input',
|
||||
'minlength': 32,
|
||||
'maxlength': 32,
|
||||
},
|
||||
|
||||
'UUID8Field': {
|
||||
'type': 'input',
|
||||
'minlength': 8,
|
||||
'maxlength': 8,
|
||||
},
|
||||
|
||||
'UUID16Field': {
|
||||
'type': 'input',
|
||||
'minlength': 16,
|
||||
'maxlength': 16,
|
||||
},
|
||||
|
||||
'UUID32Field': {
|
||||
'type': 'input',
|
||||
'minlength': 32,
|
||||
'maxlength': 32,
|
||||
},
|
||||
|
||||
'UUID36Field': {
|
||||
'type': 'input',
|
||||
'minlength': 36,
|
||||
'maxlength': 36
|
||||
},
|
||||
|
||||
'DateTimeField': {
|
||||
'type': 'datetime',
|
||||
'format': "yyyy-MM-dd hh:mm:ss",
|
||||
'valueFormat': "yyyy-MM-dd hh:mm:ss",
|
||||
},
|
||||
'DateField': {
|
||||
'type': 'date',
|
||||
'format': "yyyy-MM-dd",
|
||||
'valueFormat': "yyyy-MM-dd",
|
||||
},
|
||||
|
||||
'TimeField': {
|
||||
'type': 'time',
|
||||
'format': "hh:mm:ss",
|
||||
'valueFormat': "hh:mm:ss",
|
||||
},
|
||||
|
||||
'BooleanField': {
|
||||
'type': 'radio',
|
||||
'dicData': [
|
||||
{'value': False, 'label': '否'},
|
||||
{'value': True, 'label': '是'},
|
||||
]
|
||||
},
|
||||
|
||||
'ManyRelatedField': {
|
||||
# 'type': 'select',
|
||||
'type': 'array',
|
||||
# "multiple": True,
|
||||
'required': False,
|
||||
},
|
||||
}
|
||||
|
||||
FIELD_TYPE_DEFAULT = {
|
||||
'type': 'input',
|
||||
}
|
||||
|
||||
def getTable(self, serializer: serializers.ModelSerializer = None):
|
||||
if not serializer:
|
||||
serializer = self.get_serializer()
|
||||
serializer_class = serializer.__class__
|
||||
model = serializer_class.Meta.model
|
||||
title = model.__name__
|
||||
if hasattr(model, 'Meta'):
|
||||
if hasattr(model.Meta, 'verbose_name'):
|
||||
title = model.Meta.verbose_name or ''
|
||||
column = self.getColumn(serializer)
|
||||
table = {
|
||||
'title': title,
|
||||
'page': True,
|
||||
'align': 'center',
|
||||
'menuAlign': 'center',
|
||||
'columnBtn': True,
|
||||
'menu': True,
|
||||
'menuType': 'icon',
|
||||
'addBtn': True,
|
||||
'delBtn': True,
|
||||
'editBtn': True,
|
||||
'column': column
|
||||
}
|
||||
return table
|
||||
|
||||
def getColumn(self, serializer: serializers.ModelSerializer = None):
|
||||
if not serializer:
|
||||
serializer = self.get_serializer()
|
||||
serializer_class = serializer.__class__
|
||||
fields = serializer.get_fields()
|
||||
show_fields = getattr(serializer_class.Meta, 'show_fields', set())
|
||||
hide_fields = getattr(serializer_class.Meta, 'hide_fields', set())
|
||||
search_fields = getattr(serializer_class.Meta, 'search_fields', set())
|
||||
sortable_fields = getattr(serializer_class.Meta, 'sortable_fields', set())
|
||||
column = []
|
||||
for prop in fields:
|
||||
field = fields[prop]
|
||||
field_type = field.__class__.__name__
|
||||
info = {
|
||||
'prop': prop,
|
||||
'label': field.label or prop,
|
||||
'hide': hide_fields == '__all__' or prop in hide_fields,
|
||||
'search': search_fields == '__all__' or prop in search_fields,
|
||||
'sortable': sortable_fields == '__all__' or prop in sortable_fields,
|
||||
'width': 'auto',
|
||||
'align': 'left',
|
||||
'overHidden': False,
|
||||
}
|
||||
type_info = self.FIELD_TYPE_MAP.get(field_type, self.FIELD_TYPE_DEFAULT)
|
||||
info.update(type_info)
|
||||
|
||||
allow_null = getattr(field, 'allow_null', False)
|
||||
allow_blank = getattr(field, 'allow_blank', False)
|
||||
allow_empty = getattr(field, 'allow_empty', False)
|
||||
|
||||
read_only = getattr(field, 'read_only', False)
|
||||
write_only = getattr(field, 'write_only', False)
|
||||
|
||||
if not any([allow_null, allow_blank, allow_empty]):
|
||||
rules = [{
|
||||
'required': True,
|
||||
'message': f"""请输入{info['label']}""",
|
||||
'trigger': "blur"
|
||||
}]
|
||||
info['rules'] = rules
|
||||
if read_only:
|
||||
info['editDisabled'] = True,
|
||||
info['clearable'] = False
|
||||
|
||||
if not isinstance(field, (ManyRelatedField, RelatedField, PrimaryKeyRelatedField)):
|
||||
# 防止序列化该字段的关系模型所有数据
|
||||
choices = getattr(field, 'choices', None)
|
||||
if choices:
|
||||
dicData = list(map(lambda choice: {'value': choice[0], 'label': choice[1]}, choices.items()))
|
||||
info['dicData'] = dicData
|
||||
info['type'] = 'select'
|
||||
column.append(info)
|
||||
return column
|
||||
|
||||
|
||||
class ImportSerializerMixin:
|
||||
"""
|
||||
自定义导出模板、导入功能
|
||||
"""
|
||||
# 导入字段
|
||||
import_field_data = {}
|
||||
# 导入序列化器
|
||||
import_serializer_class = None
|
||||
|
||||
@transaction.atomic # Django 事物
|
||||
def importTemplate(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
用户导人模板
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
assert self.import_field_data, (
|
||||
"'%s' 请配置对应的导出模板字段。"
|
||||
% self.__class__.__name__
|
||||
)
|
||||
# 导出模板
|
||||
if request.method == 'GET':
|
||||
# 示例数据
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
return SuccessResponse(
|
||||
export_excel_save_model(request, self.import_field_data.values(), [],
|
||||
f'导入{get_verbose_name(queryset)}模板.xls'))
|
||||
updateSupport = request.data.get('updateSupport')
|
||||
# 从excel中组织对应的数据结构,然后使用序列化器保存
|
||||
data = excel_to_data(request.data.get('file_url'), self.import_field_data)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
unique_list = [ele.attname for ele in queryset.model._meta.get_fields() if
|
||||
hasattr(ele, 'unique') and ele.unique == True]
|
||||
for ele in data:
|
||||
# 获取 unique 字段
|
||||
filter_dic = {i: ele.get(i) for i in list(set(self.import_field_data.keys()) & set(unique_list))}
|
||||
instance = filter_dic and queryset.filter(**filter_dic).first()
|
||||
if instance and not updateSupport:
|
||||
continue
|
||||
if not filter_dic:
|
||||
instance = None
|
||||
serializer = self.import_serializer_class(instance, data=ele)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return SuccessResponse(msg=f"导入成功!")
|
||||
|
||||
|
||||
class ExportSerializerMixin:
|
||||
"""
|
||||
自定义导出功能
|
||||
"""
|
||||
# 导出字段
|
||||
export_field_data = []
|
||||
# 导出序列化器
|
||||
export_serializer_class = None
|
||||
|
||||
def export(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
导出功能
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
assert self.export_field_data, (
|
||||
"'%s' 请配置对应的导出模板字段。"
|
||||
% self.__class__.__name__
|
||||
)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
data = self.export_serializer_class(queryset, many=True).data
|
||||
return SuccessResponse(export_excel_save_model(request, self.export_field_data, data,
|
||||
f'导出{get_verbose_name(queryset)}.xls'))
|
|
@ -1,38 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models import SET_NULL
|
||||
|
||||
from .fields import CreateDateTimeField, DescriptionField, ModifierCharField, UpdateDateTimeField
|
||||
|
||||
|
||||
class BaseModel(models.Model):
|
||||
"""
|
||||
标准抽象模型模型,可直接继承使用
|
||||
"""
|
||||
description = DescriptionField() # 描述
|
||||
update_datetime = UpdateDateTimeField() # 修改时间
|
||||
create_datetime = CreateDateTimeField() # 创建时间
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = '基本模型'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
class CoreModel(models.Model):
|
||||
"""
|
||||
核心标准抽象模型模型,可直接继承使用
|
||||
增加审计字段, 覆盖字段时, 字段名称请勿修改, 必须统一审计字段名称
|
||||
"""
|
||||
description = DescriptionField() # 描述
|
||||
creator = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_query_name='creator_query', null=True,
|
||||
verbose_name='创建者', on_delete=SET_NULL, db_constraint=False) # 创建者
|
||||
modifier = ModifierCharField() # 修改者
|
||||
dept_belong_id = models.CharField(max_length=64, verbose_name="数据归属部门", null=True, blank=True)
|
||||
update_datetime = UpdateDateTimeField() # 修改时间
|
||||
create_datetime = CreateDateTimeField() # 创建时间
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = '核心模型'
|
||||
verbose_name_plural = verbose_name
|
|
@ -1,123 +0,0 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from rest_framework.pagination import PageNumberPagination, _positive_int
|
||||
from rest_framework.utils.urls import replace_query_param
|
||||
|
||||
from .response import SuccessResponse
|
||||
|
||||
|
||||
class Pagination(PageNumberPagination):
|
||||
"""
|
||||
标准分页器
|
||||
"""
|
||||
page_size_query_param = 'pageSize'
|
||||
other_page_size_query_param = []
|
||||
# other_page_size_query_param = ['pageSize', ]
|
||||
|
||||
page_query_param = "pageNum"
|
||||
other_page_query_param = []
|
||||
# other_page_query_param = ['currentPage', 'pageNum']
|
||||
max_page_size = 1000
|
||||
page_size = 10
|
||||
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
page_num = request.query_params.get(self.page_query_param)
|
||||
# 判断,如果 pageNum 为all 则取消分页返回所有
|
||||
if page_num == 'all':
|
||||
return None
|
||||
return super().paginate_queryset(queryset, request, view)
|
||||
|
||||
def get_next_link(self):
|
||||
return super().get_next_link()
|
||||
|
||||
def get_previous_link(self):
|
||||
return super().get_previous_link()
|
||||
|
||||
def get_page_size(self, request):
|
||||
"""
|
||||
获取页大小
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if self.other_page_size_query_param:
|
||||
for param_name in self.other_page_size_query_param:
|
||||
if param_name in request.query_params:
|
||||
return _positive_int(
|
||||
request.query_params[param_name],
|
||||
strict=True,
|
||||
cutoff=self.max_page_size
|
||||
)
|
||||
return super().get_page_size(request)
|
||||
|
||||
def get_page_num(self, request):
|
||||
"""
|
||||
获取页码
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if self.other_page_query_param:
|
||||
for param_name in self.other_page_query_param:
|
||||
if param_name in request.query_params:
|
||||
return _positive_int(request.query_params[param_name], strict=True)
|
||||
page_num = request.query_params.get(self.page_query_param, 1)
|
||||
return _positive_int(page_num, strict=True)
|
||||
|
||||
def get_paginated_response(self, data, search_fields=''):
|
||||
return SuccessResponse(OrderedDict([
|
||||
('count', self.page.paginator.count),
|
||||
('next', self.get_next_link()),
|
||||
('previous', self.get_previous_link()),
|
||||
('results', data)
|
||||
]))
|
||||
|
||||
|
||||
class JsonPagination(Pagination):
|
||||
"""
|
||||
Json数据内存分页器
|
||||
"""
|
||||
|
||||
def __init__(self, count=0) -> None:
|
||||
super().__init__()
|
||||
self._page_size = 0
|
||||
self._page_num = 0
|
||||
self._count = count
|
||||
self.data_count = 0
|
||||
|
||||
def get_page_size(self, request):
|
||||
_page_size = super().get_page_size(request)
|
||||
self._page_size = _page_size
|
||||
return _page_size
|
||||
|
||||
def get_page_num(self, request):
|
||||
_page_num = super().get_page_num(request)
|
||||
self._page_num = _page_num
|
||||
return _page_num
|
||||
|
||||
def get_next_link(self):
|
||||
if self._page_size * self._page_num >= self.data_count:
|
||||
return None
|
||||
url = self.request.build_absolute_uri()
|
||||
url = replace_query_param(url, self.page_query_param, self._page_num + 1)
|
||||
url = replace_query_param(url, self.page_size_query_param, self._page_size)
|
||||
return url
|
||||
|
||||
def get_previous_link(self, count=0):
|
||||
if self._page_num <= 1:
|
||||
return None
|
||||
url = self.request.build_absolute_uri()
|
||||
url = replace_query_param(url, self.page_query_param, self._page_num - 1)
|
||||
url = replace_query_param(url, self.page_size_query_param, self._page_size)
|
||||
return url
|
||||
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
self.get_page_size(request)
|
||||
self.get_page_num(request)
|
||||
return super().paginate_queryset(queryset, request, view)
|
||||
|
||||
def get_paginated_response(self, data, search_fields=''):
|
||||
return SuccessResponse(OrderedDict([
|
||||
('count', self.data_count),
|
||||
('next', self.get_next_link()),
|
||||
('previous', self.get_previous_link()),
|
||||
('results', data)
|
||||
]))
|
|
@ -1,91 +0,0 @@
|
|||
"""
|
||||
常用的Response以及Django的Response、DRF的Response
|
||||
"""
|
||||
from django.http.response import DjangoJSONEncoder, JsonResponse
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
||||
class OpDRFJSONEncoder(DjangoJSONEncoder):
|
||||
"""
|
||||
重写DjangoJSONEncoder
|
||||
(1)默认返回支持中文格式的json字符串
|
||||
"""
|
||||
|
||||
def __init__(self, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False,
|
||||
indent=None, separators=None, default=None):
|
||||
super().__init__(skipkeys=skipkeys, ensure_ascii=False, check_circular=check_circular,
|
||||
allow_nan=allow_nan, sort_keys=sort_keys, indent=indent, separators=separators,
|
||||
default=default)
|
||||
|
||||
|
||||
class SuccessResponse(Response):
|
||||
"""
|
||||
标准响应成功的返回, SuccessResponse(data)或者SuccessResponse(data=data)
|
||||
(1)默认错误码返回200, 不支持指定其他返回码
|
||||
"""
|
||||
|
||||
def __init__(self, data=None, msg='success', status=None, template_name=None, headers=None, exception=False,
|
||||
content_type=None):
|
||||
self.std_data = {
|
||||
"code": 200,
|
||||
"data": data,
|
||||
"msg": msg,
|
||||
"status": 'success'
|
||||
}
|
||||
super().__init__(self.std_data, status, template_name, headers, exception, content_type)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.std_data)
|
||||
|
||||
|
||||
class ErrorResponse(Response):
|
||||
"""
|
||||
标准响应错误的返回,ErrorResponse(msg='xxx')
|
||||
(1)默认错误码返回201, 也可以指定其他返回码:ErrorResponse(code=xxx)
|
||||
"""
|
||||
|
||||
def __init__(self, data=None, msg='error', code=201, status=None, template_name=None, headers=None,
|
||||
exception=False, content_type=None):
|
||||
self.std_data = {
|
||||
"code": code,
|
||||
"data": data,
|
||||
"msg": msg,
|
||||
"status": 'error'
|
||||
}
|
||||
super().__init__(self.std_data, status, template_name, headers, exception, content_type)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.std_data)
|
||||
|
||||
|
||||
class SuccessJsonResponse(JsonResponse):
|
||||
"""
|
||||
标准JsonResponse, SuccessJsonResponse(data)SuccessJsonResponse(data=data)
|
||||
(1)仅SuccessResponse无法使用时才能推荐使用SuccessJsonResponse
|
||||
"""
|
||||
|
||||
def __init__(self, data, msg='success', encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs):
|
||||
std_data = {
|
||||
"code": 200,
|
||||
"data": data,
|
||||
"msg": msg,
|
||||
"status": 'success'
|
||||
}
|
||||
super().__init__(std_data, encoder, safe, json_dumps_params, **kwargs)
|
||||
|
||||
|
||||
class ErrorJsonResponse(JsonResponse):
|
||||
"""
|
||||
标准JsonResponse, 仅ErrorResponse无法使用时才能使用ErrorJsonResponse
|
||||
(1)默认错误码返回2001, 也可以指定其他返回码:ErrorJsonResponse(code=xxx)
|
||||
"""
|
||||
|
||||
def __init__(self, data, msg='error', code=201, encoder=OpDRFJSONEncoder, safe=True, json_dumps_params=None,
|
||||
**kwargs):
|
||||
std_data = {
|
||||
"code": code,
|
||||
"data": data,
|
||||
"msg": msg,
|
||||
"status": 'error'
|
||||
}
|
||||
super().__init__(std_data, encoder, safe, json_dumps_params, **kwargs)
|
|
@ -1,72 +0,0 @@
|
|||
"""
|
||||
标准返回
|
||||
"""
|
||||
|
||||
|
||||
def funcSuccess(data=None, msg='success', **kwargs):
|
||||
"""
|
||||
普通函数成功返回格式
|
||||
:param data:
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
return {
|
||||
"result": True,
|
||||
"msg": msg,
|
||||
"data": data,
|
||||
}
|
||||
|
||||
|
||||
def funcError(data=None, msg='error', **kwargs):
|
||||
"""
|
||||
普通函数失败返回格式
|
||||
:param data:
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
return {
|
||||
"result": False,
|
||||
"msg": msg,
|
||||
"data": data,
|
||||
}
|
||||
|
||||
|
||||
def funcResult(result=True, data=None, msg='success', **kwargs):
|
||||
"""
|
||||
普通函数返回格式
|
||||
:param result:
|
||||
:param data:
|
||||
:param msg:
|
||||
:return:
|
||||
"""
|
||||
if result:
|
||||
return funcSuccess(data=data, msg=msg)
|
||||
return funcError(data=data, msg=msg)
|
||||
|
||||
|
||||
def paginate(data=None, count=0, next=None, previous=None, msg='success', code=2000):
|
||||
"""
|
||||
标准分页返回, 分页错误时:应该直接使用pagination()即可,无需传入任何参数
|
||||
:param data: 默认为[]
|
||||
:param count: 默认为len(data); 总计值, 不是data的元素个数,相当于count(*);仅当不传入count时, count==len(data)
|
||||
:param next: 默认为None, 下一页
|
||||
:param previous: 默认为None, 上一页
|
||||
:param msg: 默认为success
|
||||
:param code: 默认为2000, 建议不传入参数,使用默认即可
|
||||
:return:
|
||||
"""
|
||||
if not data:
|
||||
data = []
|
||||
if not count:
|
||||
count = len(data)
|
||||
return {
|
||||
"code": code,
|
||||
"data": {
|
||||
"count": count,
|
||||
"next": next,
|
||||
"previous": previous,
|
||||
"results": data
|
||||
},
|
||||
"msg": msg,
|
||||
"status": "success"
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
from django.utils.functional import cached_property
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework.fields import empty
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.utils.serializer_helpers import BindingDict
|
||||
|
||||
|
||||
class CustomModelSerializer(ModelSerializer):
|
||||
"""
|
||||
增强DRF的ModelSerializer,可自动更新模型的审计字段记录
|
||||
(1)仅当op_drf.generics.GenericAPIView的子类里使用时有效
|
||||
(2)非op_drf.generics.GenericAPIView里使用时, 与ModelSerializer作用一样,没人任何增强
|
||||
(3)self.request能获取到rest_framework.request.Request对象
|
||||
"""
|
||||
# 修改人的审计字段名称, 默认modifier, 继承使用时可自定义覆盖
|
||||
modifier_field_name = 'modifier'
|
||||
# 创建人的审计字段名称, 默认creator, 继承使用时可自定义覆盖
|
||||
creator_field_name = 'creator'
|
||||
# 数据所属部门字段
|
||||
dept_belong_id_field_name = 'dept_belong_id'
|
||||
# 添加默认时间返回格式
|
||||
create_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
||||
update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
||||
|
||||
def __init__(self, instance=None, data=empty, request=None, **kwargs):
|
||||
super().__init__(instance, data, **kwargs)
|
||||
self.request: Request = request
|
||||
|
||||
def save(self, **kwargs):
|
||||
return super().save(**kwargs)
|
||||
|
||||
def create(self, validated_data):
|
||||
if self.context.get('request'):
|
||||
self.request = self.context.get('request')
|
||||
if self.request:
|
||||
username = self.get_request_username()
|
||||
if self.modifier_field_name in self.fields.fields:
|
||||
validated_data[self.modifier_field_name] = username
|
||||
if self.creator_field_name in self.fields.fields:
|
||||
validated_data[self.creator_field_name] = self.request.user
|
||||
if self.dept_belong_id_field_name in self.fields.fields:
|
||||
validated_data[self.dept_belong_id_field_name] = getattr(self.request.user, 'dept_id', None)
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
if self.request:
|
||||
if hasattr(self.instance, self.modifier_field_name):
|
||||
self.instance.modifier = self.get_request_username()
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
def get_request_username(self):
|
||||
if getattr(self.request, 'user', None):
|
||||
return getattr(self.request.user, 'username', None)
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def fields(self):
|
||||
fields = BindingDict(self)
|
||||
for key, value in self.get_fields().items():
|
||||
fields[key] = value
|
||||
|
||||
if not hasattr(self, '_context'):
|
||||
return fields
|
||||
is_root = self.root == self
|
||||
parent_is_list_root = self.parent == self.root and getattr(self.parent, 'many', False)
|
||||
if not (is_root or parent_is_list_root):
|
||||
return fields
|
||||
|
||||
try:
|
||||
request = self.request or self.context['request']
|
||||
except KeyError:
|
||||
return fields
|
||||
params = getattr(
|
||||
request, 'query_params', getattr(request, 'GET', None)
|
||||
)
|
||||
if params is None:
|
||||
pass
|
||||
try:
|
||||
filter_fields = params.get('_fields', None).split(',')
|
||||
except AttributeError:
|
||||
filter_fields = None
|
||||
|
||||
try:
|
||||
omit_fields = params.get('_omit', None).split(',')
|
||||
except AttributeError:
|
||||
omit_fields = []
|
||||
|
||||
existing = set(fields.keys())
|
||||
if filter_fields is None:
|
||||
allowed = existing
|
||||
else:
|
||||
allowed = set(filter(None, filter_fields))
|
||||
|
||||
omitted = set(filter(None, omit_fields))
|
||||
for field in existing:
|
||||
if field not in allowed:
|
||||
fields.pop(field, None)
|
||||
if field in omitted:
|
||||
fields.pop(field, None)
|
||||
|
||||
return fields
|
||||
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
"""
|
||||
重写校验器返回字段
|
||||
"""
|
||||
from rest_framework.validators import UniqueValidator, qs_exists
|
||||
|
||||
from apps.vadmin.utils.exceptions import APIException
|
||||
|
||||
|
||||
class CustomUniqueValidator(UniqueValidator):
|
||||
"""
|
||||
继承,重写必填字段的验证器结果,防止字段暴露
|
||||
"""
|
||||
|
||||
def __call__(self, value, serializer_field):
|
||||
# Determine the underlying model field name. This may not be the
|
||||
# same as the serializer field name if `source=<>` is set.
|
||||
field_name = serializer_field.source_attrs[-1]
|
||||
# Determine the existing instance, if this is an update operation.
|
||||
instance = getattr(serializer_field.parent, 'instance', None)
|
||||
|
||||
queryset = self.queryset
|
||||
queryset = self.filter_queryset(value, queryset, field_name)
|
||||
queryset = self.exclude_current_instance(queryset, instance)
|
||||
if qs_exists(queryset):
|
||||
raise APIException(message=self.message)
|
||||
|
||||
def __repr__(self):
|
||||
return super().__repr__()
|
|
@ -1,98 +0,0 @@
|
|||
import logging
|
||||
import traceback
|
||||
from types import FunctionType, MethodType
|
||||
|
||||
from rest_framework.exceptions import APIException as DRFAPIException
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.vadmin.utils import exceptions
|
||||
from .response import ErrorResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def op_exception_handler(ex, context):
|
||||
"""
|
||||
统一异常拦截处理
|
||||
目的:(1)取消所有的500异常响应,统一响应为标准错误返回
|
||||
(2)准确显示错误信息
|
||||
:param ex:
|
||||
:param context:
|
||||
:return:
|
||||
"""
|
||||
msg = ''
|
||||
if isinstance(ex, DRFAPIException):
|
||||
# set_rollback()
|
||||
msg = ex.detail
|
||||
elif isinstance(ex, exceptions.APIException):
|
||||
msg = ex.message
|
||||
elif isinstance(ex, Exception):
|
||||
logger.error(traceback.format_exc())
|
||||
msg = str(ex)
|
||||
return ErrorResponse(msg=msg)
|
||||
|
||||
|
||||
class CustomAPIView(APIView):
|
||||
"""
|
||||
继承、增强DRF的APIView
|
||||
"""
|
||||
extra_permission_classes = ()
|
||||
# 仅当GET方法时会触发该权限的校验
|
||||
GET_permission_classes = ()
|
||||
|
||||
# 仅当POST方法时会触发该权限的校验
|
||||
POST_permission_classes = ()
|
||||
|
||||
# 仅当DELETE方法时会触发该权限的校验
|
||||
DELETE_permission_classes = ()
|
||||
|
||||
# 仅当PUT方法时会触发该权限的校验
|
||||
PUT_permission_classes = ()
|
||||
|
||||
view_logger_classes = ()
|
||||
|
||||
def initial(self, request: Request, *args, **kwargs):
|
||||
super().initial(request, *args, **kwargs)
|
||||
self.check_extra_permissions(request)
|
||||
self.check_method_extra_permissions(request)
|
||||
|
||||
def get_view_loggers(self, request: Request, *args, **kwargs):
|
||||
logger_classes = self.view_logger_classes or []
|
||||
if not logger_classes:
|
||||
return []
|
||||
view_loggers = [logger_class(view=self, request=request, *args, **kwargs) for logger_class in logger_classes]
|
||||
return view_loggers
|
||||
|
||||
def handle_logging(self, request: Request, *args, **kwargs):
|
||||
view_loggers = self.get_view_loggers(request, *args, **kwargs)
|
||||
method = request.method.lower()
|
||||
for view_logger in view_loggers:
|
||||
view_logger.handle(request, *args, **kwargs)
|
||||
logger_fun = getattr(view_logger, f'handle_{method}', f'handle_other')
|
||||
if logger_fun and isinstance(logger_fun, (FunctionType, MethodType)):
|
||||
logger_fun(request, *args, **kwargs)
|
||||
|
||||
def get_extra_permissions(self):
|
||||
return [permission() for permission in self.extra_permission_classes]
|
||||
|
||||
def check_extra_permissions(self, request: Request):
|
||||
for permission in self.get_extra_permissions():
|
||||
if not permission.has_permission(request, self):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
def get_method_extra_permissions(self):
|
||||
_name = self.request.method.upper()
|
||||
method_extra_permission_classes = getattr(self, f"{_name}_permission_classes", None)
|
||||
if not method_extra_permission_classes:
|
||||
return []
|
||||
return [permission() for permission in method_extra_permission_classes]
|
||||
|
||||
def check_method_extra_permissions(self, request):
|
||||
for permission in self.get_method_extra_permissions():
|
||||
if not permission.has_permission(request, self):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
|
@ -1,364 +0,0 @@
|
|||
from types import FunctionType, MethodType
|
||||
|
||||
# from rest_framework_mongoengine.generics import GenericAPIView as MongoGenericAPIView
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.http.response import Http404
|
||||
from django.shortcuts import get_object_or_404 as _get_object_or_404
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from mongoengine.queryset.base import BaseQuerySet
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.viewsets import ViewSetMixin
|
||||
|
||||
from apps.vadmin.utils.exceptions import APIException
|
||||
from . import mixins
|
||||
from .filters import MongoSearchFilter, MongoOrderingFilter, AdvancedSearchFilter, MongoAdvancedSearchFilter
|
||||
from .generics import GenericAPIView
|
||||
from .logging.view_logger import CustomerModelViewLogger
|
||||
from .serializers import CustomModelSerializer
|
||||
|
||||
|
||||
def get_object_or_404(queryset, *filter_args, **filter_kwargs):
|
||||
try:
|
||||
return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
|
||||
except (TypeError, ValueError, ValidationError, Http404):
|
||||
raise APIException(message='该对象不存在或者无访问权限')
|
||||
|
||||
|
||||
class GenericViewSet(ViewSetMixin, GenericAPIView):
|
||||
extra_filter_backends = []
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
filter_backends = [DjangoFilterBackend, OrderingFilter, SearchFilter, AdvancedSearchFilter]
|
||||
view_logger_classes = (CustomerModelViewLogger,)
|
||||
|
||||
def handle_logging(self, request: Request, *args, **kwargs):
|
||||
view_loggers = self.get_view_loggers(request, *args, **kwargs)
|
||||
for view_logger in view_loggers:
|
||||
handle_action = getattr(view_logger, f'handle_{self.action}', None)
|
||||
if handle_action and isinstance(handle_action, (FunctionType, MethodType)):
|
||||
handle_action(request, *args, **kwargs)
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
serializer_class = self.get_serializer_class()
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
serializer = serializer_class(*args, **kwargs)
|
||||
if isinstance(serializer, CustomModelSerializer):
|
||||
serializer.request = self.request
|
||||
return serializer
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])):
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
queryset = self.action_extra_filter_queryset(queryset)
|
||||
return queryset
|
||||
|
||||
def action_extra_filter_queryset(self, queryset):
|
||||
action__extra_filter_backends = getattr(self, f"{self.action}_extra_filter_backends", None)
|
||||
if not action__extra_filter_backends:
|
||||
return queryset
|
||||
for backend in action__extra_filter_backends:
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
return queryset
|
||||
|
||||
def get_serializer_class(self):
|
||||
action_serializer_name = f"{self.action}_serializer_class"
|
||||
action_serializer_class = getattr(self, action_serializer_name, None)
|
||||
if action_serializer_class:
|
||||
return action_serializer_class
|
||||
return super().get_serializer_class()
|
||||
|
||||
def reverse_action(self, url_name, *args, **kwargs):
|
||||
return super().reverse_action(url_name, *args, **kwargs)
|
||||
|
||||
def get_action_extra_permissions(self):
|
||||
"""
|
||||
获取已配置的action权限校验,并且实例化其对象
|
||||
:return:
|
||||
"""
|
||||
action_extra_permission_classes = getattr(self, f"{self.action}_extra_permission_classes", None)
|
||||
if not action_extra_permission_classes:
|
||||
return []
|
||||
return [permission() for permission in action_extra_permission_classes]
|
||||
|
||||
def check_action_extra_permissions(self, request):
|
||||
"""
|
||||
逐个校验action权限校验
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
for permission in self.get_action_extra_permissions():
|
||||
if not permission.has_permission(request, self):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
def check_action_extra_object_permissions(self, request, obj):
|
||||
"""
|
||||
action方法的专属对象权限校验
|
||||
:param request:
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
for permission in self.get_action_extra_permissions():
|
||||
if not permission.has_object_permission(request, self, obj):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
"""
|
||||
重写initial方法
|
||||
(1)新增action的权限校验
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
super().initial(request, *args, **kwargs)
|
||||
self.check_action_extra_permissions(request)
|
||||
|
||||
def get_object(self):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
|
||||
def check_object_permissions(self, request, obj):
|
||||
"""
|
||||
重新check_object_permissions
|
||||
(1)新增action方法的专属对象权限检查入口
|
||||
(2)先校验共同的object_permissions, 再校验action的object_permissions
|
||||
:param request:
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
super().check_object_permissions(request, obj)
|
||||
self.check_action_extra_object_permissions(request, obj)
|
||||
|
||||
|
||||
class MongoGenericAPIView(GenericAPIView):
|
||||
""" Adaptation of DRF GenericAPIView """
|
||||
lookup_field = 'id'
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super(MongoGenericAPIView, self).get_queryset()
|
||||
if isinstance(queryset, BaseQuerySet):
|
||||
queryset = queryset.all()
|
||||
return queryset
|
||||
|
||||
def get_object(self):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
|
||||
|
||||
class MongoGenericViewSet(ViewSetMixin, MongoGenericAPIView):
|
||||
extra_filter_backends = []
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
filter_backends = [DjangoFilterBackend, OrderingFilter, SearchFilter, AdvancedSearchFilter]
|
||||
view_logger_classes = (CustomerModelViewLogger,)
|
||||
|
||||
def handle_logging(self, request: Request, *args, **kwargs):
|
||||
view_loggers = self.get_view_loggers(request, *args, **kwargs)
|
||||
for view_logger in view_loggers:
|
||||
handle_action = getattr(view_logger, f'handle_{self.action}', None)
|
||||
if handle_action and isinstance(handle_action, (FunctionType, MethodType)):
|
||||
handle_action(request, *args, **kwargs)
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
serializer_class = self.get_serializer_class()
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
serializer = serializer_class(*args, **kwargs)
|
||||
if isinstance(serializer, CustomModelSerializer):
|
||||
serializer.request = self.request
|
||||
return serializer
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])):
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
queryset = self.action_extra_filter_queryset(queryset)
|
||||
return queryset
|
||||
|
||||
def action_extra_filter_queryset(self, queryset):
|
||||
action__extra_filter_backends = getattr(self, f"{self.action}_extra_filter_backends", None)
|
||||
if not action__extra_filter_backends:
|
||||
return queryset
|
||||
for backend in action__extra_filter_backends:
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
return queryset
|
||||
|
||||
def get_serializer_class(self):
|
||||
action_serializer_name = f"{self.action}_serializer_class"
|
||||
action_serializer_class = getattr(self, action_serializer_name, None)
|
||||
if action_serializer_class:
|
||||
return action_serializer_class
|
||||
return super().get_serializer_class()
|
||||
|
||||
def reverse_action(self, url_name, *args, **kwargs):
|
||||
return super().reverse_action(url_name, *args, **kwargs)
|
||||
|
||||
def get_action_extra_permissions(self):
|
||||
"""
|
||||
获取已配置的action权限校验,并且实例化其对象
|
||||
:return:
|
||||
"""
|
||||
action_extra_permission_classes = getattr(self, f"{self.action}_extra_permission_classes", None)
|
||||
if not action_extra_permission_classes:
|
||||
return []
|
||||
return [permission() for permission in action_extra_permission_classes]
|
||||
|
||||
def check_action_extra_permissions(self, request):
|
||||
"""
|
||||
逐个校验action权限校验
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
for permission in self.get_action_extra_permissions():
|
||||
if not permission.has_permission(request, self):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
def check_action_extra_object_permissions(self, request, obj):
|
||||
"""
|
||||
action方法的专属对象权限校验
|
||||
:param request:
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
for permission in self.get_action_extra_permissions():
|
||||
if not permission.has_object_permission(request, self, obj):
|
||||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
"""
|
||||
重写initial方法
|
||||
(1)新增action的权限校验
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
super().initial(request, *args, **kwargs)
|
||||
self.check_action_extra_permissions(request)
|
||||
|
||||
def get_object(self):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
|
||||
def check_object_permissions(self, request, obj):
|
||||
"""
|
||||
重新check_object_permissions
|
||||
(1)新增action方法的专属对象权限检查入口
|
||||
(2)先校验共同的object_permissions, 再校验action的object_permissions
|
||||
:param request:
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
super().check_object_permissions(request, obj)
|
||||
self.check_action_extra_object_permissions(request, obj)
|
||||
|
||||
|
||||
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet):
|
||||
pass
|
||||
|
||||
|
||||
class ModelViewSet(mixins.CreateModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet):
|
||||
pass
|
||||
|
||||
|
||||
class MongoModelViewSet(mixins.CreateModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
MongoGenericViewSet):
|
||||
pass
|
||||
|
||||
|
||||
class CustomModelViewSet(ModelViewSet, mixins.TableSerializerMixin,
|
||||
mixins.ImportSerializerMixin,
|
||||
mixins.ExportSerializerMixin):
|
||||
"""
|
||||
自定义的ModelViewSet:
|
||||
(1)默认分页器就为统一分页器op_drf.pagination.Pagination
|
||||
(1)默认使用统一标准返回格式
|
||||
(1)默认支持高级搜索
|
||||
(1)默认支持生成前端动态table的option
|
||||
(1)ORM性能优化, 尽可能使用values_queryset形式
|
||||
"""
|
||||
values_queryset = None
|
||||
ordering_fields = '__all__'
|
||||
|
||||
def get_queryset(self):
|
||||
if getattr(self, 'values_queryset', None):
|
||||
return self.values_queryset
|
||||
return super().get_queryset()
|
||||
|
||||
|
||||
class CustomMongoModelViewSet(MongoModelViewSet, mixins.TableSerializerMixin):
|
||||
filter_backends = (MongoOrderingFilter, MongoSearchFilter, MongoAdvancedSearchFilter)
|
||||
# filter_fields = '__all__' # 暂不支持__all__
|
||||
filter_fields = ()
|
||||
search_fields = ()
|
||||
ordering_fields = '__all__'
|
||||
view_logger_classes = (CustomerModelViewLogger,)
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset
|
||||
filtering_kwargs = {}
|
||||
for param in self.request.query_params:
|
||||
param = param.strip()
|
||||
if param in ['pageSize', 'pageNum', 'search', 'ordering', 'as']: continue
|
||||
if self.filter_fields == '__all__' or param in self.filter_fields:
|
||||
# if param in self.filter_fields:
|
||||
filtering_kwargs[param] = self.request.query_params[param]
|
||||
queryset = queryset.filter(**filtering_kwargs)
|
||||
ordering_params = self.request.query_params.get(api_settings.ORDERING_PARAM, None)
|
||||
if ordering_params:
|
||||
ordering_fields = [field.strip() for field in ordering_params.split(',')]
|
||||
ordering_fields = filter(lambda field: self.ordering_fields == '__all__' or field in self.ordering_fields,
|
||||
ordering_fields)
|
||||
queryset = queryset.order_by(*ordering_fields)
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
return super().filter_queryset(queryset)
|
|
@ -1,6 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PermissionConfig(AppConfig):
|
||||
name = 'apps.vadmin.permission'
|
||||
verbose_name = "权限管理"
|
|
@ -1,67 +0,0 @@
|
|||
import django_filters
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from apps.vadmin.permission.models import Menu, Dept, Post, Role
|
||||
from apps.vadmin.utils.model_util import get_dept
|
||||
|
||||
UserProfile = get_user_model()
|
||||
|
||||
|
||||
class MenuFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
菜单管理 简单序过滤器
|
||||
"""
|
||||
name = django_filters.CharFilter(lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class DeptFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
部门管理 简单序过滤器
|
||||
"""
|
||||
deptName = django_filters.CharFilter(lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class PostFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
岗位管理 简单序过滤器
|
||||
"""
|
||||
postName = django_filters.CharFilter(lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class RoleFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
角色管理 简单序过滤器
|
||||
"""
|
||||
roleName = django_filters.CharFilter(lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class UserProfileFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
用户管理 简单序过滤器
|
||||
"""
|
||||
username = django_filters.CharFilter(lookup_expr='icontains')
|
||||
mobile = django_filters.CharFilter(lookup_expr='icontains')
|
||||
deptId = django_filters.CharFilter(method='filter_deptId')
|
||||
|
||||
def filter_deptId(self, queryset, name, value):
|
||||
return queryset.filter(dept__id__in=get_dept(dept_id=value))
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
exclude = ('secret', 'password',)
|
|
@ -1,103 +0,0 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import connection
|
||||
|
||||
from apps.vadmin.scripts import getSql
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
项目初始化命令: python manage.py init
|
||||
"""
|
||||
|
||||
def customSql(self, sql_list, model_name, table_name, is_yes):
|
||||
"""
|
||||
批量执行sql
|
||||
:param sql_list:
|
||||
:param table_name: 表名
|
||||
:return:
|
||||
"""
|
||||
with connection.cursor() as cursor:
|
||||
num = 0
|
||||
for ele in table_name.split(','):
|
||||
cursor.execute("select count(*) from {}".format(ele))
|
||||
result = cursor.fetchone()
|
||||
num += result[0]
|
||||
if num > 0:
|
||||
while True:
|
||||
if is_yes is None:
|
||||
inp = input(f'[{model_name}]模型已初始化完成,继续将清空[{table_name}]表中所有数据,是否继续初始化?【 Y/N 】')
|
||||
else:
|
||||
inp = 'Y' if is_yes == True else 'N'
|
||||
if inp.upper() == 'N':
|
||||
return False
|
||||
elif inp.upper() == 'Y':
|
||||
logger.info(f'正在清空[{table_name}]中数据...')
|
||||
cursor.execute("SET foreign_key_checks = 0")
|
||||
for ele in table_name.split(','):
|
||||
cursor.execute("truncate table {};".format(ele))
|
||||
cursor.execute("SET foreign_key_checks = 1")
|
||||
connection.commit()
|
||||
logger.info(f'清空[{table_name}]中数据{result[0]}条')
|
||||
break
|
||||
|
||||
for sql in sql_list:
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
connection.commit()
|
||||
return True
|
||||
|
||||
def init(self, sql_filename, model_name, table_name, is_yes):
|
||||
"""
|
||||
初始化
|
||||
:param sql_filename: sql存放位置
|
||||
:param model_name: 模块名
|
||||
:param table_name: 表名
|
||||
:return:
|
||||
"""
|
||||
logger.info(f'正在初始化[{model_name}]中...')
|
||||
if self.customSql(getSql(sql_filename), model_name, table_name, is_yes):
|
||||
logger.info(f'[{model_name}]初始化完成!')
|
||||
else:
|
||||
logger.info(f'已取消[{table_name}]初始化')
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('init_name', nargs='*', type=str, )
|
||||
parser.add_argument('-y', nargs='*')
|
||||
parser.add_argument('-Y', nargs='*')
|
||||
parser.add_argument('-n', nargs='*')
|
||||
parser.add_argument('-N', nargs='*')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
user_name = "_".join(settings.AUTH_USER_MODEL.lower().split("."))
|
||||
init_dict = {
|
||||
'system_dictdata': [os.path.join('system', 'system_dictdata.sql'), '字典管理', 'system_dictdata'],
|
||||
'system_dictdetails': [os.path.join('system', 'system_dictdetails.sql'), '字典详情', 'system_dictdetails'],
|
||||
'system_configsettings': [os.path.join('system', 'system_configsettings.sql'), '参数设置',
|
||||
'system_configsettings'],
|
||||
'permission_post': [os.path.join('permission', 'permission_post.sql'), '岗位管理', 'permission_post'],
|
||||
'permission_dept': [os.path.join('permission', 'permission_dept.sql'), '部门管理', 'permission_dept'],
|
||||
'permission_menu': [os.path.join('permission', 'permission_menu.sql'), '菜单管理', 'permission_menu'],
|
||||
'permission_role': [os.path.join('permission', 'permission_role.sql'), '角色管理',
|
||||
','.join(['permission_role', 'permission_role_dept', 'permission_role_menu'])],
|
||||
'permission_userprofile': [os.path.join('permission', 'permission_userprofile.sql'), '用户管理', ','.join(
|
||||
[f'{user_name}_groups', f'{user_name}', f'{user_name}_role', f'{user_name}_post'])]
|
||||
}
|
||||
init_name = options.get('init_name')
|
||||
is_yes = None
|
||||
if isinstance(options.get('y'), list) or isinstance(options.get('Y'), list):
|
||||
is_yes = True
|
||||
if isinstance(options.get('n'), list) or isinstance(options.get('N'), list):
|
||||
is_yes = False
|
||||
if init_name:
|
||||
[self.init(*init_dict[ele], is_yes=is_yes) for ele in init_name if ele in init_dict]
|
||||
else:
|
||||
for ele in init_dict.values():
|
||||
self.init(*ele, is_yes=is_yes)
|
|
@ -1,5 +0,0 @@
|
|||
from apps.vadmin.permission.models.dept import Dept
|
||||
from apps.vadmin.permission.models.menu import Menu
|
||||
from apps.vadmin.permission.models.post import Post
|
||||
from apps.vadmin.permission.models.role import Role
|
||||
from apps.vadmin.permission.models.users import UserProfile
|
|
@ -1,22 +0,0 @@
|
|||
from django.db.models import CASCADE
|
||||
from django.db.models import CharField, IntegerField, ForeignKey
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class Dept(CoreModel):
|
||||
deptName = CharField(max_length=64, verbose_name="部门名称")
|
||||
orderNum = IntegerField(verbose_name="显示排序")
|
||||
owner = CharField(max_length=32, verbose_name="负责人", null=True, blank=True)
|
||||
phone = CharField(max_length=32, verbose_name="联系电话", null=True, blank=True)
|
||||
email = CharField(max_length=32, verbose_name="邮箱", null=True, blank=True)
|
||||
status = CharField(max_length=8, verbose_name="部门状态", null=True, blank=True)
|
||||
parentId = ForeignKey(to='permission.Dept', on_delete=CASCADE, default=False, verbose_name="上级部门",
|
||||
db_constraint=False, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '部门管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.deptName}"
|
|
@ -1,75 +0,0 @@
|
|||
from django.core.cache import cache
|
||||
from django.db.models import IntegerField, ForeignKey, CharField, CASCADE, Q
|
||||
|
||||
from application import settings
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class Menu(CoreModel):
|
||||
# MENU_TYPE_CHOICES = (
|
||||
# ("0", "目录"),
|
||||
# ("1", "菜单"),
|
||||
# ("2", "按钮"),
|
||||
# )
|
||||
# METHOD_CHOICE = (
|
||||
# ('GET', 'GET'),
|
||||
# ('POST', 'POST'),
|
||||
# ('PUT', 'PUT'),
|
||||
# ('PATCH', 'PATCH'),
|
||||
# ('DELETE', 'DELETE'),
|
||||
# ('HEAD', 'HEAD'),
|
||||
# ('OPTIONS', 'OPTIONS'),
|
||||
# ('TRACE', 'TRACE'),
|
||||
# )
|
||||
parentId = ForeignKey(to='Menu', on_delete=CASCADE, verbose_name="上级菜单", null=True, blank=True, db_constraint=False)
|
||||
menuType = CharField(max_length=8, verbose_name="菜单类型")
|
||||
icon = CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True)
|
||||
name = CharField(max_length=64, verbose_name="菜单名称")
|
||||
orderNum = IntegerField(verbose_name="显示排序")
|
||||
isFrame = CharField(max_length=8, verbose_name="是否外链")
|
||||
web_path = CharField(max_length=128, verbose_name="前端路由地址", null=True, blank=True)
|
||||
component_path = CharField(max_length=128, verbose_name="前端组件路径", null=True, blank=True)
|
||||
interface_path = CharField(max_length=256, verbose_name="后端接口路径", null=True, blank=True)
|
||||
interface_method = CharField(max_length=16, default='GET', verbose_name="接口请求方式")
|
||||
perms = CharField(max_length=256, verbose_name="权限标识", null=True, blank=True)
|
||||
status = CharField(max_length=8, verbose_name="菜单状态")
|
||||
visible = CharField(max_length=8, verbose_name="显示状态")
|
||||
isCache = CharField(max_length=8, verbose_name="是否缓存")
|
||||
|
||||
@classmethod
|
||||
def get_interface_dict(cls):
|
||||
"""
|
||||
获取所有接口列表
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
interface_dict = cache.get('permission_interface_dict', {}) if getattr(settings, "REDIS_ENABLE",
|
||||
False) else {}
|
||||
except:
|
||||
interface_dict = {}
|
||||
if not interface_dict:
|
||||
for ele in Menu.objects.filter(~Q(interface_path=''), ~Q(interface_path=None), status='1', ).values(
|
||||
'interface_path', 'interface_method'):
|
||||
if ele.get('interface_method') in interface_dict:
|
||||
interface_dict[ele.get('interface_method', '')].append(ele.get('interface_path'))
|
||||
else:
|
||||
interface_dict[ele.get('interface_method', '')] = [ele.get('interface_path')]
|
||||
if getattr(settings, "REDIS_ENABLE", False):
|
||||
cache.set('permission_interface_dict', interface_dict, 84600)
|
||||
return interface_dict
|
||||
|
||||
@classmethod
|
||||
def delete_cache(cls):
|
||||
"""
|
||||
清空缓存中的接口列表
|
||||
:return:
|
||||
"""
|
||||
if getattr(settings, "REDIS_ENABLE", False):
|
||||
cache.delete('permission_interface_dict')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '菜单管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
|
@ -1,18 +0,0 @@
|
|||
from django.db.models import IntegerField, BooleanField, CharField, TextField
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class Post(CoreModel):
|
||||
postName = CharField(null=False, max_length=64, verbose_name="岗位名称")
|
||||
postCode = CharField(max_length=32, verbose_name="岗位编码")
|
||||
postSort = IntegerField(verbose_name="岗位顺序")
|
||||
status = CharField(max_length=8, verbose_name="岗位状态")
|
||||
remark = TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '岗位管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.postName}"
|
|
@ -1,29 +0,0 @@
|
|||
from django.db.models import IntegerField, BooleanField, CharField, TextField, ManyToManyField
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class Role(CoreModel):
|
||||
DATASCOPE_CHOICES = (
|
||||
('1', "全部数据权限"),
|
||||
('2', "自定数据权限"),
|
||||
('3', "本部门数据权限"),
|
||||
('4', "本部门及以下数据权限"),
|
||||
('5', "仅本人数据权限"),
|
||||
)
|
||||
roleName = CharField(max_length=64, verbose_name="角色名称")
|
||||
roleKey = CharField(max_length=64, verbose_name="权限字符")
|
||||
roleSort = IntegerField(verbose_name="角色顺序")
|
||||
status = CharField(max_length=8, verbose_name="角色状态")
|
||||
admin = BooleanField(default=False, verbose_name="是否为admin")
|
||||
dataScope = CharField(max_length=8, default='1', choices=DATASCOPE_CHOICES, verbose_name="权限范围", )
|
||||
remark = TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
|
||||
dept = ManyToManyField(to='permission.Dept', verbose_name='数据权限-关联部门', db_constraint=False)
|
||||
menu = ManyToManyField(to='permission.Menu', verbose_name='关联菜单权限', db_constraint=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '角色管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.roleName}"
|
|
@ -1,66 +0,0 @@
|
|||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import UserManager, AbstractUser
|
||||
from django.core.cache import cache
|
||||
from django.db.models import IntegerField, ForeignKey, CharField, TextField, ManyToManyField, CASCADE
|
||||
|
||||
from apps.vadmin.op_drf.models import CoreModel
|
||||
|
||||
|
||||
class UserProfile(AbstractUser, CoreModel):
|
||||
USER_TYPE_CHOICES = (
|
||||
(0, "后台用户"),
|
||||
(1, "前台用户"),
|
||||
)
|
||||
objects = UserManager()
|
||||
username = CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号')
|
||||
secret = CharField(max_length=255, default=uuid4, verbose_name='加密秘钥')
|
||||
email = CharField(max_length=255, verbose_name="邮箱", null=True, blank=True)
|
||||
mobile = CharField(max_length=255, verbose_name="电话", null=True, blank=True)
|
||||
avatar = TextField(verbose_name="头像", null=True, blank=True)
|
||||
name = CharField(max_length=40, verbose_name="姓名")
|
||||
gender = CharField(max_length=8, verbose_name="性别", null=True, blank=True)
|
||||
remark = TextField(verbose_name="备注", null=True)
|
||||
user_type = IntegerField(default=0, verbose_name="用户类型")
|
||||
post = ManyToManyField(to='permission.Post', verbose_name='关联岗位', db_constraint=False)
|
||||
role = ManyToManyField(to='permission.Role', verbose_name='关联角色', db_constraint=False)
|
||||
dept = ForeignKey(to='permission.Dept', verbose_name='归属部门', on_delete=CASCADE, db_constraint=False, null=True,
|
||||
blank=True)
|
||||
|
||||
@property
|
||||
def get_user_interface_dict(self):
|
||||
interface_dict = cache.get(f'permission_interface_dict_{self.username}', {}) if \
|
||||
getattr(settings, "REDIS_ENABLE", False) else {}
|
||||
if not interface_dict:
|
||||
for ele in self.role.filter(status='1', menu__status='1').values('menu__interface_path',
|
||||
'menu__interface_method').distinct():
|
||||
interface_path = ele.get('menu__interface_path')
|
||||
if interface_path is None or interface_path == '':
|
||||
continue
|
||||
if ele.get('menu__interface_method') in interface_dict:
|
||||
interface_dict[ele.get('menu__interface_method', '')].append(interface_path)
|
||||
else:
|
||||
interface_dict[ele.get('menu__interface_method', '')] = [interface_path]
|
||||
if getattr(settings, "REDIS_ENABLE", False):
|
||||
cache.set(f'permission_interface_dict_{self.username}', interface_dict, 84600)
|
||||
return interface_dict
|
||||
|
||||
@property
|
||||
def delete_cache(self):
|
||||
"""
|
||||
清空缓存中的接口列表
|
||||
:return:
|
||||
"""
|
||||
if not getattr(settings, "REDIS_ENABLE", False): return ""
|
||||
return cache.delete(f'permission_interface_dict_{self.username}')
|
||||
|
||||
class Meta:
|
||||
abstract = settings.AUTH_USER_MODEL != 'permission.UserProfile'
|
||||
verbose_name = '用户管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
if self.name:
|
||||
return f"{self.username}({self.name})"
|
||||
return f"{self.username}"
|
|
@ -1,119 +0,0 @@
|
|||
"""
|
||||
常用的Permission以及DRF的Permission
|
||||
@author: ruoxing
|
||||
"""
|
||||
import logging
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from rest_framework.permissions import (BasePermission,
|
||||
)
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.vadmin.permission.models import Dept
|
||||
from apps.vadmin.utils.model_util import get_dept
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class CustomPermission(BasePermission):
|
||||
def __init__(self, message=None) -> None:
|
||||
super().__init__()
|
||||
self.message = getattr(self.__class__, 'message', '无权限')
|
||||
self.user: User = None
|
||||
|
||||
def init_permission(self, request: Request, view: APIView):
|
||||
self.user = request.user
|
||||
|
||||
def has_permission(self, request: Request, view: APIView):
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, obj):
|
||||
return True
|
||||
|
||||
|
||||
class CommonPermission(CustomPermission):
|
||||
"""
|
||||
通用权限类,判断用户是否有这条数据的查询权限,如没有则直接没有操作权限
|
||||
0. 获取用户的部门id,没有部门则返回 False
|
||||
1. 判断过滤的数据是否有创建人所在部门 "dept_belong_id" 字段,没有则返回 True
|
||||
2. 如果用户没有关联角色则校验该数据是否属于本部门
|
||||
3. 根据所有角色 获取所有权限范围
|
||||
3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则有权限操作
|
||||
4. 只为仅本人数据权限时只有操作本人数据权限,并且部门为自己本部门(考虑到用户会变部门,只能看当前用户所在的部门数据)
|
||||
5. 自定数据权限 获取部门,根据部门判断,是否有权限操作
|
||||
"""
|
||||
message = '没有有操作权限'
|
||||
|
||||
def check_queryset(self, request, instance):
|
||||
# 0. 获取用户的部门id,没有部门则返回 False
|
||||
user_dept_id = getattr(request.user, 'dept_id')
|
||||
if not user_dept_id:
|
||||
self.message = "该用户无部门,无权限操作!"
|
||||
return False
|
||||
|
||||
# 1. 判断过滤的数据是否有创建人所在部门 "dept_belong_id" 字段,没有则返回 True
|
||||
if not getattr(instance, 'dept_belong_id', None):
|
||||
return True
|
||||
|
||||
# 2. 如果用户没有关联角色则校验该数据是否属于本部门
|
||||
if not hasattr(request.user, 'role'):
|
||||
self.message = "该用户无角色,无权限操作!"
|
||||
return False
|
||||
|
||||
# 3. 根据所有角色 获取所有权限范围
|
||||
role_list = request.user.role.filter(status='1').values('admin', 'dataScope')
|
||||
dataScope_list = []
|
||||
for ele in role_list:
|
||||
# 3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则有权限操作
|
||||
if '1' == ele.get('dataScope') or ele.get('admin') == True:
|
||||
return True
|
||||
dataScope_list.append(ele.get('dataScope'))
|
||||
dataScope_list = list(set(dataScope_list))
|
||||
|
||||
# 4. 只为仅本人数据权限时只有操作本人数据权限,并且部门为自己本部门(考虑到用户会变部门,只能看当前用户所在的部门数据)
|
||||
if dataScope_list == ['5']:
|
||||
return int(instance.dept_belong_id) == user_dept_id and request.user == instance.creator
|
||||
|
||||
# 5. 自定数据权限 获取部门,根据部门判断,是否有权限操作
|
||||
dept_list = []
|
||||
for ele in dataScope_list:
|
||||
if ele == '2':
|
||||
dept_list.extend(request.user.role.filter(status='1').values_list('dept__id', flat=True))
|
||||
elif ele == '3':
|
||||
dept_list.append(user_dept_id)
|
||||
elif ele == '4':
|
||||
dept_list.extend(get_dept(user_dept_id, ))
|
||||
return int(instance.dept_belong_id) in list(set(dept_list))
|
||||
|
||||
def has_permission(self, request: Request, view: APIView):
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, instance):
|
||||
self.message = f"没有此数据操作权限!"
|
||||
res = self.check_queryset(request, instance)
|
||||
return res
|
||||
|
||||
|
||||
class DeptDestroyPermission(CustomPermission):
|
||||
"""
|
||||
部门删除权限校验:判断部门下是否有用户存在,存在不可删除
|
||||
"""
|
||||
message = '没有有操作权限'
|
||||
|
||||
def has_permission(self, request: Request, view: APIView):
|
||||
return True
|
||||
|
||||
def check_queryset(self, request, instance):
|
||||
if list(filter(None, instance.values_list('userprofile', flat=True))):
|
||||
self.message = "该部门下有关联用户,无法删除!"
|
||||
return False
|
||||
if Dept.objects.filter(parentId__in=instance).count() > 0:
|
||||
self.message = "该部门下有下级部门,请先删除下级部门!"
|
||||
return False
|
||||
return True
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, instance):
|
||||
res = self.check_queryset(request, instance)
|
||||
return res
|
|
@ -1,321 +0,0 @@
|
|||
import hashlib
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.vadmin.op_drf.serializers import CustomModelSerializer
|
||||
from apps.vadmin.op_drf.validator import CustomUniqueValidator
|
||||
from apps.vadmin.permission.models import Menu, Dept, Post, Role
|
||||
from apps.vadmin.system.models import MessagePush
|
||||
|
||||
UserProfile = get_user_model()
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 菜单管理 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class MenuSerializer(CustomModelSerializer):
|
||||
"""
|
||||
简单菜单序列化器
|
||||
"""
|
||||
parentId = serializers.IntegerField(source="parentId.id", default=0)
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class MenuCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
# name = attrs['name']
|
||||
# role: Role = Role.objects.filter(name=name).first()
|
||||
# if role and attrs.get('instanceId', '') != role.instanceId:
|
||||
# raise APIException(message=f'角色名称[{name}]不能重复')
|
||||
# if getattr(self.instance, 'is_public', False) or attrs.get('is_public', False):
|
||||
# up = UserPermission(self.request.user)
|
||||
# if not up.is_manager():
|
||||
# raise APIException(message=f'仅Manger能创建/更新角色为公共角色')
|
||||
return super().validate(attrs)
|
||||
|
||||
def save(self, **kwargs):
|
||||
Menu.delete_cache()
|
||||
return super().save(**kwargs)
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MenuTreeSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
菜单树形架构序列化器:递归序列化所有深度的子菜单
|
||||
"""
|
||||
label = serializers.CharField(source='name', default='')
|
||||
parentId = serializers.IntegerField(source="parentId.id", default=0)
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ('id', 'label', 'orderNum', 'parentId')
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 部门管理 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class DeptSerializer(CustomModelSerializer):
|
||||
"""
|
||||
部门管理 简单序列化器
|
||||
"""
|
||||
parentId = serializers.IntegerField(source="parentId.id", default=0)
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class DeptCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
部门管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
return super().validate(attrs)
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class DeptTreeSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
部门树形架构序列化器:递归序列化所有深度的子部门
|
||||
"""
|
||||
label = serializers.CharField(source='deptName', default='')
|
||||
parentId = serializers.IntegerField(source="parentId.id", default=0)
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = ('id', 'label', 'parentId', 'status')
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 岗位管理 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class PostSerializer(CustomModelSerializer):
|
||||
"""
|
||||
岗位管理 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class ExportPostSerializer(CustomModelSerializer):
|
||||
"""
|
||||
导出 岗位管理 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = ('id', 'postName', 'postCode', 'postSort', 'status', 'creator', 'modifier', 'remark')
|
||||
|
||||
|
||||
class PostSimpleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
岗位管理 极简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = ('id', 'postName', 'postCode', 'status')
|
||||
|
||||
|
||||
class PostCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
岗位管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
return super().validate(attrs)
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 角色管理 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class RoleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色管理 简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
exclude = ('description', 'creator', 'modifier')
|
||||
|
||||
|
||||
class ExportRoleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
导出 角色管理 简单序列化器
|
||||
"""
|
||||
dataScope = serializers.SerializerMethodField()
|
||||
|
||||
def get_dataScope(self, obj):
|
||||
dataScope = obj.get_dataScope_display()
|
||||
return dataScope
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ('id', 'roleName', 'roleKey', 'roleSort', 'dataScope', 'status', 'creator', 'modifier', 'remark')
|
||||
|
||||
|
||||
class RoleSimpleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色管理 极简单序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ('id', 'roleName', 'roleKey', 'status')
|
||||
|
||||
|
||||
class RoleCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色管理 创建/更新时的列化器
|
||||
"""
|
||||
menu = MenuSerializer(many=True, read_only=True)
|
||||
dept = DeptSerializer(many=True, read_only=True)
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
return super().validate(attrs)
|
||||
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
data.dept.set(self.initial_data.get('dept'))
|
||||
data.menu.set(self.initial_data.get('menu'))
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 用户管理 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
|
||||
class UserProfileSerializer(CustomModelSerializer):
|
||||
"""
|
||||
简单用户序列化器
|
||||
"""
|
||||
admin = serializers.SerializerMethodField(read_only=True)
|
||||
deptId = serializers.IntegerField(source='dept.id', read_only=True)
|
||||
# 未读通知数量
|
||||
unread_msg_count = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_admin(self, obj: UserProfile):
|
||||
role_list = obj.role.filter(status='1').values_list('admin', flat=True)
|
||||
if True in list(set(role_list)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_unread_msg_count(self, obj: UserProfile):
|
||||
return MessagePush.objects.filter(status='2').exclude(messagepushuser_message_push__is_read=True,
|
||||
messagepushuser_message_push__user=obj).count()
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
depth = 1
|
||||
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined', 'creator')
|
||||
|
||||
|
||||
class ExportUserProfileSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户导出 序列化器
|
||||
"""
|
||||
last_login = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
|
||||
dept__deptName = serializers.CharField(source='dept.deptName', default='')
|
||||
dept__owner = serializers.CharField(source='dept.owner', default='')
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
fields = ('id', 'username', 'name', 'email', 'mobile', 'gender', 'is_active', 'last_login', 'dept__deptName',
|
||||
'dept__owner')
|
||||
|
||||
|
||||
class UserProfileCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户管理 创建/更新时的列化器
|
||||
"""
|
||||
admin = serializers.SerializerMethodField(read_only=True)
|
||||
post = PostSerializer(many=True, read_only=True)
|
||||
role = RoleSerializer(many=True, read_only=True)
|
||||
username = serializers.CharField(required=True, max_length=150,
|
||||
validators=[
|
||||
CustomUniqueValidator(queryset=UserProfile.objects.all(), message="用戶已存在")],
|
||||
error_messages={
|
||||
"blank": "请输入用户名称",
|
||||
"required": "用户名称不能为空",
|
||||
"max_length": "用户名称过长",
|
||||
})
|
||||
|
||||
def get_admin(self, obj: UserProfile):
|
||||
role_list = obj.role.filter(status='1').values_list('admin', flat=True)
|
||||
if True in list(set(role_list)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
return super().validate(attrs)
|
||||
|
||||
def save(self, **kwargs):
|
||||
self.validated_data['dept_id'] = self.initial_data.get('deptId', None)
|
||||
data = super().save(**kwargs)
|
||||
data.post.set(self.initial_data.get('postIds'))
|
||||
data.role.set(self.initial_data.get('roleIds'))
|
||||
return data
|
||||
|
||||
def create(self, validated_data):
|
||||
data = super().create(validated_data)
|
||||
data.set_password(self.initial_data.get('password', None))
|
||||
data.save()
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')
|
||||
read_only_fields = ('dept',)
|
||||
|
||||
|
||||
class UserProfileImportSerializer(CustomModelSerializer):
|
||||
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
password = hashlib.new('md5', self.initial_data.get('password', '').encode(encoding='UTF-8')).hexdigest()
|
||||
data.set_password(password)
|
||||
data.save()
|
||||
return data
|
||||
|
||||
def run_validation(self, data={}):
|
||||
# 把excel 数据进行格式转换
|
||||
if type(data) is dict:
|
||||
data['role'] = str(data['role']).split(',')
|
||||
data['post'] = str(data['post']).split(',')
|
||||
data['gender'] = {'男': '0', '女': '1', '未知': '2'}.get(data['gender'])
|
||||
data['is_active'] = {'启用': True, '禁用': False}.get(data['is_active'])
|
||||
return super().run_validation(data)
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')
|
|
@ -1,20 +0,0 @@
|
|||
import datetime
|
||||
import logging
|
||||
|
||||
from captcha.models import CaptchaStore
|
||||
|
||||
from apps.vadmin.utils.decorators import BaseCeleryApp
|
||||
from apps.vadmin.op_drf.response import SuccessResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@BaseCeleryApp(name='apps.vadmin.permission.tasks.clear_invalid_captcha')
|
||||
def clear_invalid_captcha():
|
||||
"""
|
||||
清除数据库中废弃失效的验证码
|
||||
:return:
|
||||
"""
|
||||
queryset = CaptchaStore.objects.filter(expiration__lt=datetime.datetime.now())
|
||||
msg = f"成功删除 {queryset.count()} 条失效验证码!"
|
||||
logger.info(msg)
|
||||
queryset.delete()
|
||||
return SuccessResponse(msg=msg)
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,46 +0,0 @@
|
|||
from django.urls import re_path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.vadmin.permission.views import MenuModelViewSet, DeptModelViewSet, PostModelViewSet, RoleModelViewSet, \
|
||||
UserProfileModelViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'menus', MenuModelViewSet)
|
||||
router.register(r'dept', DeptModelViewSet)
|
||||
router.register(r'dept/exclude', DeptModelViewSet)
|
||||
router.register(r'post', PostModelViewSet)
|
||||
router.register(r'role', RoleModelViewSet)
|
||||
router.register(r'user', UserProfileModelViewSet)
|
||||
urlpatterns = [
|
||||
|
||||
re_path('dept/exclude/(?P<pk>.*)/', DeptModelViewSet.as_view({'get': 'exclude_list'})),
|
||||
re_path('dept/treeselect/', DeptModelViewSet.as_view({'get': 'tree_select_list'})),
|
||||
re_path('menus/treeselect/', MenuModelViewSet.as_view({'get': 'tree_select_list'})),
|
||||
# 根据角色ID查询菜单下拉树结构
|
||||
re_path('menus/roleMenuTreeselect/(?P<pk>.*)/', MenuModelViewSet.as_view({'get': 'role_menu_tree_select'})),
|
||||
# 根据角色ID查询部门树结构
|
||||
re_path('dept/roleDeptTreeselect/(?P<pk>.*)/', DeptModelViewSet.as_view({'get': 'role_dept_tree_select'})),
|
||||
# 更新状态
|
||||
re_path('user/changeStatus/', UserProfileModelViewSet.as_view({'put': 'change_status'})),
|
||||
# 获取用户详情
|
||||
re_path('user/details/', UserProfileModelViewSet.as_view({'get': 'get_user_details'})),
|
||||
# 后台重置密码
|
||||
re_path('user/resetPwd/', UserProfileModelViewSet.as_view({'put': 'reset_pwd'})),
|
||||
# 用户自己重置密码
|
||||
re_path('user/profile/updatePwd/', UserProfileModelViewSet.as_view({'put': 'update_pwd'})),
|
||||
# 更新用户头像
|
||||
re_path('user/profile/avatar/', UserProfileModelViewSet.as_view({'put': 'put_avatar'})),
|
||||
# 获取、更新用户个人信息
|
||||
re_path('user/profile/', UserProfileModelViewSet.as_view({'get': 'profile', 'put': 'put_profile'})),
|
||||
# 导出用户
|
||||
re_path('user/export/', UserProfileModelViewSet.as_view({'get': 'export', })),
|
||||
# 导出角色
|
||||
re_path('role/export/', RoleModelViewSet.as_view({'get': 'export', })),
|
||||
# 导出岗位
|
||||
re_path('post/export/', PostModelViewSet.as_view({'get': 'export', })),
|
||||
# 用户导入模板下载及导入
|
||||
re_path('user/importTemplate/',
|
||||
UserProfileModelViewSet.as_view({'get': 'importTemplate', 'post': 'importTemplate'})),
|
||||
|
||||
]
|
||||
urlpatterns += router.urls
|
|
@ -1,375 +0,0 @@
|
|||
from django.contrib.auth import authenticate, get_user_model
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from apps.vadmin.op_drf.response import SuccessResponse, ErrorResponse
|
||||
from apps.vadmin.permission.permissions import CommonPermission, DeptDestroyPermission
|
||||
from apps.vadmin.op_drf.filters import DataLevelPermissionsFilter
|
||||
from apps.vadmin.op_drf.viewsets import CustomModelViewSet
|
||||
from apps.vadmin.permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter
|
||||
from apps.vadmin.permission.models import Role, Menu, Dept, Post
|
||||
from apps.vadmin.permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \
|
||||
MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \
|
||||
RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \
|
||||
PostSimpleSerializer, RoleSimpleSerializer, ExportUserProfileSerializer, ExportRoleSerializer, ExportPostSerializer, \
|
||||
UserProfileImportSerializer
|
||||
from apps.vadmin.system.models import DictDetails
|
||||
|
||||
UserProfile = get_user_model()
|
||||
|
||||
|
||||
class GetUserProfileView(APIView):
|
||||
"""
|
||||
获取用户详细信息
|
||||
"""
|
||||
|
||||
def get(self, request, format=None):
|
||||
user_dict = UserProfileSerializer(request.user).data
|
||||
permissions_list = ['*:*:*'] if user_dict.get('admin') else Menu.objects.filter(
|
||||
role__userprofile=request.user).values_list('perms', flat=True)
|
||||
delete_cache = request.user.delete_cache
|
||||
return SuccessResponse({
|
||||
'permissions': [ele for ele in permissions_list if ele],
|
||||
'roles': Role.objects.filter(userprofile=request.user).values_list('roleKey', flat=True),
|
||||
'user': user_dict
|
||||
})
|
||||
|
||||
|
||||
class GetRouters(APIView):
|
||||
"""
|
||||
获取路由详细信息
|
||||
"""
|
||||
|
||||
def depth_menu(self, menus):
|
||||
"""
|
||||
获取菜单(通过前端递归值)
|
||||
:param menus:
|
||||
:return:
|
||||
"""
|
||||
|
||||
return dict
|
||||
|
||||
def get(self, request, format=None):
|
||||
kwargs = {}
|
||||
if not request.user.is_superuser:
|
||||
kwargs['role__userprofile'] = request.user
|
||||
menus = Menu.objects.filter(**kwargs) \
|
||||
.exclude(menuType='2').values('id', 'name', 'web_path', 'visible', 'status', 'isFrame', 'component_path',
|
||||
'icon', 'parentId', 'orderNum', 'isCache').distinct()
|
||||
data = []
|
||||
sys_show_hide = DictDetails.get_default_dictValue('sys_show_hide')
|
||||
for ele in menus:
|
||||
data.append({
|
||||
'id': ele.get('id'),
|
||||
'name': ele.get('web_path', '').split('/')[-1] and ele.get('web_path', '').split('/')[-1].capitalize(),
|
||||
'path': ele.get('web_path'),
|
||||
'orderNum': ele.get('orderNum'),
|
||||
'hidden': True if ele.get('visible') != '1' else False,
|
||||
'redirect': ele.get('web_path') if ele.get('isFrame') == '1' else 'noRedirect',
|
||||
'component': ele.get('component_path') or 'Layout',
|
||||
'meta': {'title': ele.get('name'), 'icon': ele.get('icon'),
|
||||
'noCache': True if ele.get('isCache') == sys_show_hide else False},
|
||||
'parentId': ele.get('parentId')
|
||||
})
|
||||
return SuccessResponse(data)
|
||||
|
||||
|
||||
class MenuModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单模型 的CRUD视图
|
||||
"""
|
||||
queryset = Menu.objects.all()
|
||||
serializer_class = MenuSerializer
|
||||
create_serializer_class = MenuCreateUpdateSerializer
|
||||
update_serializer_class = MenuCreateUpdateSerializer
|
||||
filter_class = MenuFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('name',)
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
|
||||
def tree_select_list(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
递归获取部门树
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
serializer = MenuTreeSerializer(queryset, many=True)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def role_menu_tree_select(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
根据角色ID查询菜单下拉树结构
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
menu_queryset = Menu.objects.filter(role__id=kwargs.get('pk')).values_list('id', flat=True)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
serializer = MenuTreeSerializer(queryset, many=True)
|
||||
return SuccessResponse({
|
||||
'menus': serializer.data,
|
||||
'checkedKeys': menu_queryset
|
||||
})
|
||||
|
||||
|
||||
class DeptModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
部门管理 的CRUD视图
|
||||
"""
|
||||
queryset = Dept.objects.all()
|
||||
serializer_class = DeptSerializer
|
||||
create_serializer_class = DeptCreateUpdateSerializer
|
||||
update_serializer_class = DeptCreateUpdateSerializer
|
||||
filter_class = DeptFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission, DeptDestroyPermission)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('deptName',)
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
|
||||
def exclude_list(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
过滤剔除同级部门
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
dept_queryset = Dept.objects.filter(id=kwargs.get('pk')).first()
|
||||
parentId = dept_queryset.parentId if dept_queryset else ''
|
||||
queryset = self.queryset.exclude(parentId=parentId).order_by('orderNum')
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def tree_select_list(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
递归获取部门树
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
serializer = DeptTreeSerializer(queryset, many=True)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def role_dept_tree_select(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
根据角色ID查询部门树结构
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
dept_queryset = Dept.objects.filter(role__id=kwargs.get('pk')).values_list('id', flat=True)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
serializer = DeptTreeSerializer(queryset, many=True)
|
||||
return SuccessResponse({
|
||||
'depts': serializer.data,
|
||||
'checkedKeys': dept_queryset
|
||||
})
|
||||
|
||||
|
||||
class PostModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
岗位管理 的CRUD视图
|
||||
"""
|
||||
queryset = Post.objects.all()
|
||||
serializer_class = PostSerializer
|
||||
create_serializer_class = PostCreateUpdateSerializer
|
||||
update_serializer_class = PostCreateUpdateSerializer
|
||||
filter_class = PostFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('postName',)
|
||||
ordering = ['postSort', 'create_datetime'] # 默认排序
|
||||
export_field_data = ['岗位序号', '岗位编码', '岗位名称', '岗位排序', '状态', '创建者', '修改者', '备注']
|
||||
export_serializer_class = ExportPostSerializer
|
||||
|
||||
|
||||
class RoleModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
角色管理 的CRUD视图
|
||||
"""
|
||||
queryset = Role.objects.all()
|
||||
serializer_class = RoleSerializer
|
||||
create_serializer_class = RoleCreateUpdateSerializer
|
||||
update_serializer_class = RoleCreateUpdateSerializer
|
||||
filter_class = RoleFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('roleName',)
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
export_field_data = ['角色序号', '角色名称', '角色权限', '角色排序', '数据范围', '角色状态', '创建者', '修改者', '备注']
|
||||
export_serializer_class = ExportRoleSerializer
|
||||
|
||||
|
||||
class UserProfileModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
用户管理 的CRUD视图
|
||||
"""
|
||||
queryset = UserProfile.objects.all()
|
||||
serializer_class = UserProfileSerializer
|
||||
create_serializer_class = UserProfileCreateUpdateSerializer
|
||||
update_serializer_class = UserProfileCreateUpdateSerializer
|
||||
filter_class = UserProfileFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
# 导出
|
||||
export_serializer_class = ExportUserProfileSerializer
|
||||
export_field_data = ['用户序号', '登录名称', '用户名称', '用户邮箱', '手机号码', '用户性别', '帐号状态', '最后登录时间', '部门名称', '部门负责人']
|
||||
# 导入
|
||||
import_serializer_class = UserProfileImportSerializer
|
||||
import_field_data = {'username': '登录账号', 'name': '用户名称', 'email': '用户邮箱', 'mobile': '手机号码',
|
||||
'gender': '用户性别(男/女/未知)',
|
||||
'is_active': '帐号状态(启用/禁用)', 'password': '登录密码', 'dept': '部门ID', 'role': '角色ID',
|
||||
'post': '岗位ID'}
|
||||
update_extra_permission_classes = (CommonPermission,)
|
||||
destroy_extra_permission_classes = (CommonPermission,)
|
||||
create_extra_permission_classes = (CommonPermission,)
|
||||
search_fields = ('username',)
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
|
||||
def change_status(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
修改用户状态
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.data.get('userId'))
|
||||
instance.is_active = request.data.get('status')
|
||||
instance.save()
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def get_user_details(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
获取用户详情
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
userId = request.query_params.get('userId')
|
||||
data = {
|
||||
'posts': PostSimpleSerializer(Post.objects.filter(status='1').order_by('postSort'), many=True).data,
|
||||
'roles': RoleSimpleSerializer(Role.objects.filter(status='1').order_by('roleSort'), many=True).data
|
||||
}
|
||||
if userId:
|
||||
instance = self.queryset.get(id=userId)
|
||||
serializer = self.get_serializer(instance)
|
||||
data['data'] = serializer.data
|
||||
data['postIds'] = [ele.get('id') for ele in serializer.data.get('post')]
|
||||
data['roleIds'] = [ele.get('id') for ele in serializer.data.get('role')]
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(data)
|
||||
|
||||
def reset_pwd(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
重置密码
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.data.get('userId'))
|
||||
serializer = self.get_serializer(instance)
|
||||
instance.set_password(request.data.get('password'))
|
||||
instance.save()
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def profile(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
获取用户个人信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.user.id)
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def put_profile(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
更新用户个人信息
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.user.id)
|
||||
instance.name = request.data.get('name', None)
|
||||
instance.mobile = request.data.get('mobile', None)
|
||||
instance.email = request.data.get('email', None)
|
||||
instance.gender = request.data.get('gender', None)
|
||||
instance.save()
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def put_avatar(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
更新用户头像
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.user.id)
|
||||
instance.avatar = request.data.get('avatar_url', None)
|
||||
instance.save()
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
||||
|
||||
def update_pwd(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
个人修改密码
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
instance = self.queryset.get(id=request.user.id)
|
||||
instance.password = request.data.get('newPassword', None)
|
||||
if not authenticate(username=request.user.username, password=request.data.get('oldPassword', None)):
|
||||
return ErrorResponse(msg='旧密码不正确!')
|
||||
instance.set_password(request.data.get('newPassword'))
|
||||
instance.save()
|
||||
serializer = self.get_serializer(instance)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, instance=instance, *args, **kwargs)
|
||||
return SuccessResponse(serializer.data)
|
|
@ -1,20 +0,0 @@
|
|||
import os
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def getSql(filename):
|
||||
"""
|
||||
获取文件内所有sql
|
||||
:param filename: 例如:os.path.join('permission','permission_dept.sql')
|
||||
:return:
|
||||
"""
|
||||
abspath = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
|
||||
pwd = os.path.join(abspath, 'scripts', filename)
|
||||
with open(pwd, 'rb') as fp:
|
||||
content = fp.read().decode('utf8')
|
||||
if filename == "permission/permission_userprofile.sql":
|
||||
user_name = "_".join(settings.AUTH_USER_MODEL.lower().split("."))
|
||||
content = content.replace("permission_userprofile", user_name). \
|
||||
replace("userprofile", settings.AUTH_USER_MODEL.lower().split(".")[-1])
|
||||
return [ele for ele in content.split('\n') if not ele.startswith('--') and ele.strip(' ')]
|
|
@ -1,42 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 部门管理 初始化sql
|
||||
-- Table structure for permission_dept
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_dept`;
|
||||
-- CREATE TABLE `permission_dept` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `description` longtext,
|
||||
-- `creator` varchar(255) DEFAULT NULL,
|
||||
-- `modifier` varchar(255) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `deptName` varchar(64) NOT NULL,
|
||||
-- `orderNum` int(11) NOT NULL,
|
||||
-- `owner` varchar(32) DEFAULT NULL,
|
||||
-- `phone` varchar(32) DEFAULT NULL,
|
||||
-- `email` varchar(32) DEFAULT NULL,
|
||||
-- `status` varchar(8) DEFAULT NULL,
|
||||
-- `parentId_id` int(11) DEFAULT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- KEY `permission_dept_parentId_id_43a4fd49` (`parentId_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_dept
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (1, '', 'admin', '2021-02-27 07:26:20.518695', '2021-02-27 15:18:39.000000', 'XX创新科技', 1, NULL, '15888888888', 'cxkj@qq.com', '1', 1,NULL, 1);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (2, '', 'admin', '2021-02-27 07:25:09.041807', '2021-02-27 07:25:09.041853', '北京总公司', 1, NULL, NULL, NULL, '1', 1, 1, 2);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (3, '', 'admin', '2021-02-27 07:26:14.418894', '2021-02-27 07:25:25.195849', '上海分公司', 2, NULL, NULL, NULL, '1', 1, 1, 3);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (4, '', 'admin', '2021-02-27 07:26:01.993095', '2021-02-27 07:25:38.904644', '杭州分公司', 4, NULL, NULL, NULL, '1', 1, 1, 4);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (5, '', 'admin', '2021-02-27 07:28:15.854856', '2021-02-27 07:25:54.379081', '深圳分公司', 3, NULL, NULL, NULL, '0', 1, 1, 5);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (6, '', 'admin', '2021-02-27 07:26:37.589741', '2021-02-27 07:26:37.589780', '研发部门', 1, NULL, NULL, NULL, '1', 1, 2, 6);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (7, '', 'admin', '2021-02-27 07:26:47.781467', '2021-02-27 07:26:47.781511', '市场部门', 2, NULL, NULL, NULL, '1', 1, 2, 7);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (8, '', 'admin', '2021-02-27 07:26:57.059878', '2021-02-27 07:26:57.059923', '测试部门', 3, NULL, NULL, NULL, '1', 1, 2, 8);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (9, '', 'admin', '2021-02-27 07:27:06.088134', '2021-02-27 07:27:06.088178', '财务部门', 4, NULL, NULL, NULL, '1', 1, 2, 9);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (10, '', 'admin', '2021-02-27 07:27:15.287731', '2021-02-27 07:27:15.287772', '运维部门', 5, NULL, NULL, NULL, '1', 1, 2, 10);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (11, '', 'admin', '2021-02-27 07:27:24.834369', '2021-02-27 07:27:24.834413', '市场部门', 1, NULL, NULL, NULL, '1', 1, 3, 11);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (12, '', 'admin', '2021-02-27 07:27:34.161898', '2021-02-27 07:27:34.161944', '财务部门', 2, NULL, NULL, NULL, '1', 1, 3, 12);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (13, '', 'admin', '2021-02-27 07:28:20.474025', '2021-02-27 07:27:47.938676', '市场部门', 1, NULL, NULL, NULL, '0', 1, 5, 13);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (14, '', 'admin', '2021-02-27 07:28:23.394188', '2021-02-27 07:27:53.794331', '财务部门', 2, NULL, NULL, NULL, '0', 1, 5, 14);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (15, '', 'admin', '2021-02-27 07:28:03.368497', '2021-02-27 07:28:03.368540', '市场部门', 1, NULL, NULL, NULL, '1', 1, 4, 15);
|
||||
INSERT INTO `permission_dept` (id, description, modifier, update_datetime, create_datetime, deptName, orderNum, owner, phone, email, status, creator_id, parentId_id, dept_belong_id) VALUES (16, '', 'admin', '2021-02-27 07:28:10.532392', '2021-02-27 07:28:10.532436', '财务部门', 2, NULL, NULL, NULL, '1', 1, 4, 16);
|
|
@ -1,129 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 菜单管理初始化sql
|
||||
-- Table structure for permission_menu
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_menu`;
|
||||
-- CREATE TABLE `permission_menu` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `description` longtext,
|
||||
-- `creator` varchar(255) DEFAULT NULL,
|
||||
-- `modifier` varchar(255) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `menuType` varchar(8) NOT NULL,
|
||||
-- `icon` varchar(64) DEFAULT NULL,
|
||||
-- `name` varchar(64) NOT NULL,
|
||||
-- `orderNum` int(11) NOT NULL,
|
||||
-- `isFrame` varchar(8) NOT NULL,
|
||||
-- `web_path` varchar(128) DEFAULT NULL,
|
||||
-- `component_path` varchar(128) DEFAULT NULL,
|
||||
-- `interface_path` varchar(256) DEFAULT NULL,
|
||||
-- `interface_method` varchar(16) NOT NULL,
|
||||
-- `perms` varchar(256) DEFAULT NULL,
|
||||
-- `status` varchar(8) NOT NULL,
|
||||
-- `visible` varchar(8) NOT NULL,
|
||||
-- `isCache` varchar(8) NOT NULL,
|
||||
-- `parentId_id` int(11) DEFAULT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- KEY `permission_menu_parentId_id_df49c7ef_fk_permission_menu_id` (`parentId_id`),
|
||||
-- CONSTRAINT `permission_menu_parentId_id_df49c7ef_fk_permission_menu_id` FOREIGN KEY (`parentId_id`) REFERENCES `permission_menu` (`id`)
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_menu
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (1, '', 'admin', '2021-02-27 07:50:00.410101', '2021-02-27 07:41:28.660364', '0', 'system', '系统管理', 1, '1', '/system', '', '', 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (2, '', 'admin', '2021-02-27 07:51:14.500722', '2021-02-27 07:51:14.500768', '0', 'peoples', '权限管理', 2, '1', '/permission', '', '', 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (3, '', 'admin', '2021-03-16 14:50:55.740451', '2021-02-27 07:54:38.630670', '1', 'dict', '字典管理', 1, '1', 'dict', 'vadmin/system/dict/index', '', 'GET', '', '1', '1', '1', 1, 1, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (4, '', 'admin', '2021-03-26 00:48:34.067871', '2021-02-27 08:06:51.019173', '1', 'edit', '参数管理', 2, '1', 'config', 'vadmin/system/config/index', '', 'GET', '', '1', '1', '1', 1, 1, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (5, '', 'admin', '2021-03-26 00:49:19.728695', '2021-02-27 08:25:37.339270', '1', 'post', '岗位管理', 1, '1', 'post', 'vadmin/permission/post/index', '', 'GET', '', '1', '1', '1', 1, 2, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (6, '', 'admin', '2021-03-26 00:49:25.882167', '2021-02-27 08:26:48.454553', '1', 'tree', '部门管理', 2, '1', 'dept', 'vadmin/permission/dept/index', '', 'GET', '', '1', '1', '1', 1, 2, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (7, '', 'admin', '2021-03-26 00:49:31.601381', '2021-02-27 08:28:20.411164', '1', 'tree-table', '菜单管理', 3, '1', 'menu', 'vadmin/permission/menu/index', '', 'GET', '', '1', '1', '0', 1, 2, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (8, '', 'admin', '2021-03-26 00:49:37.244296', '2021-02-27 08:29:30.153361', '1', 'peoples', '角色管理', 4, '1', 'role', 'vadmin/permission/role/index', '', 'GET', '', '1', '1', '1', 1, 2, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (9, '', 'admin', '2021-03-26 00:49:42.699298', '2021-02-27 08:30:14.030888', '1', 'user', '用户管理', 5, '1', 'user', 'vadmin/permission/user/index', '', 'GET', '', '1', '1', '1', 1, 2, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (10, '', 'admin', '2021-03-26 00:51:15.986262', '2021-02-27 08:36:04.824117', '0', 'guide', 'dvAdmin官网', 9, '0', 'https://django-vue-admin.com', '', NULL, 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (11, '', 'admin', '2021-03-26 00:48:40.309707', '2021-02-27 16:17:36.685174', '1', 'job', '文件管理', 3, '1', 'savefile', 'vadmin/system/savefile/index', '', 'GET', '', '1', '1', '1', 1, 1, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (13, '', 'admin', '2021-03-03 14:41:08.227821', '2021-03-03 14:18:52.530449', '2', NULL, '用户新增', 1, '1', NULL, NULL, '/admin/permission/user/', 'POST', 'permission:user:post', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (14, '', 'admin', '2021-03-03 14:43:34.207938', '2021-03-03 14:43:34.208093', '2', NULL, '用户修改', 2, '1', NULL, NULL, '/admin/permission/user/{id}/', 'PUT', 'permission:user:{id}:put', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (15, '', 'admin', '2021-03-03 14:44:58.006289', '2021-03-03 14:44:58.006338', '2', NULL, '用户删除', 3, '1', '', NULL, '/admin/permission/user/{id}/', 'DELETE', 'permission:user:{id}:delete', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (16, '', 'admin', '2021-03-03 14:45:50.575443', '2021-03-03 14:45:50.575507', '2', NULL, '用户导出', 4, '1', NULL, NULL, '/admin/permission/user/export/', 'GET', 'permission:user:export:get', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (17, '', 'admin', '2021-03-03 14:51:14.157310', '2021-03-03 14:51:14.157447', '2', NULL, '用户导入', 5, '1', NULL, NULL, '/admin/permission/user/import/', 'POST', 'permission:user:import:post', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (18, '', 'admin', '2021-03-03 14:51:51.220886', '2021-03-03 14:51:51.220933', '2', NULL, '重置密码', 6, '1', NULL, NULL, '/admin/permission/user/resetPwd/', 'PUT', 'permission:user:resetpwd:put', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (19, '', 'admin', '2021-03-03 14:53:47.877063', '2021-03-03 14:53:47.877116', '2', NULL, '角色新增', 1, '1', NULL, NULL, '/admin/permission/role/', 'POST', 'permission:role:post', '1', '1', '1', 1, 8, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (20, '', 'admin', '2021-03-03 14:54:28.794968', '2021-03-03 14:54:28.795015', '2', NULL, '角色修改', 2, '1', NULL, NULL, '/admin/permission/role/{id}/', 'PUT', 'permission:role:{id}:put', '1', '1', '1', 1, 8, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (21, '', 'admin', '2021-03-03 14:58:00.798718', '2021-03-03 14:58:00.798813', '2', NULL, '删除角色', 3, '1', NULL, NULL, '/admin/permission/role/{id}/', 'DELETE', 'permission:role:{id}:delete', '1', '1', '1', 1, 8, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (22, '', 'admin', '2021-03-03 14:58:28.940577', '2021-03-03 14:58:28.940625', '2', NULL, '角色导出', 4, '1', NULL, NULL, '/admin/permission/role/export/', 'GET', 'permission:role:export:get', '1', '1', '1', 1, 8, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (23, '', 'admin', '2021-03-03 15:00:41.081771', '2021-03-03 15:00:41.081832', '2', NULL, '菜单新增', 1, '1', NULL, NULL, '/admin/permission/menus/', 'POST', 'permission:menus:post', '1', '1', '1', 1, 7, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (24, '', 'admin', '2021-03-03 15:01:03.178824', '2021-03-03 15:01:03.178874', '2', NULL, '菜单修改', 2, '1', NULL, NULL, '/admin/permission/menus/{id}/', 'PUT', 'permission:menus:{id}:put', '1', '1', '1', 1, 7, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (25, '', 'admin', '2021-03-03 15:02:56.123525', '2021-03-03 15:02:56.123571', '2', NULL, '菜单删除', 3, '1', NULL, NULL, '/admin/permission/menus/{id}/', 'DELETE', 'permission:menus:{id}:delete', '1', '1', '1', 1, 7, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (26, '', 'admin', '2021-03-03 15:04:35.191774', '2021-03-03 15:04:35.191856', '2', NULL, '部门新增', 1, '1', NULL, NULL, '/admin/permission/dept/', 'POST', 'permission:dept:post', '1', '1', '1', 1, 6, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (27, '', 'admin', '2021-03-03 15:04:56.963168', '2021-03-03 15:04:56.963214', '2', NULL, '部门修改', 2, '1', NULL, NULL, '/admin/permission/dept/{id}/', 'PUT', 'permission:dept:{id}:put', '1', '1', '1', 1, 6, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (28, '', 'admin', '2021-03-03 15:05:39.602577', '2021-03-03 15:05:39.602622', '2', NULL, '部门删除', 3, '1', NULL, NULL, '/admin/permission/dept/{id}/', 'DELETE', 'permission:dept:{id}:delete', '1', '1', '1', 1, 6, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (29, '', 'admin', '2021-03-03 15:06:50.095341', '2021-03-03 15:06:50.095388', '2', NULL, '岗位新增', 1, '1', NULL, NULL, '/admin/permission/post/', 'POST', 'permission:post:post', '1', '1', '1', 1, 5, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (30, '', 'admin', '2021-03-03 15:07:36.013313', '2021-03-03 15:07:36.013358', '2', NULL, '岗位修改', 2, '1', NULL, NULL, '/admin/permission/post/{id}/', 'PUT', 'permission:post:{id}:put', '1', '1', '1', 1, 5, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (31, '', 'admin', '2021-03-03 15:08:10.371530', '2021-03-03 15:08:10.371575', '2', NULL, '岗位删除', 3, '1', NULL, NULL, '/admin/permission/post/{id}/', 'DELETE', 'permission:post:{id}:delete', '1', '1', '1', 1, 5, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (32, '', 'admin', '2021-03-03 15:09:02.213084', '2021-03-03 15:09:02.213131', '2', NULL, '岗位导出', 4, '1', NULL, NULL, '/admin/permission/post/export/', 'GET', 'permission:post:export:get', '1', '1', '1', 1, 5, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (33, '', 'admin', '2021-03-03 15:11:37.616329', '2021-03-03 15:11:37.616415', '2', NULL, '字典新增', 1, '1', NULL, NULL, '/admin/system/dict/type/', 'POST', 'system:dict:type:post', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (34, '', 'admin', '2021-03-03 15:12:47.237658', '2021-03-03 15:12:47.237713', '2', NULL, '字典修改', 2, '1', NULL, NULL, '/admin/system/dict/type/{id}/', 'PUT', 'system:dict:type:{id}:put', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (35, '', 'admin', '2021-03-03 15:13:40.185174', '2021-03-03 15:13:40.185230', '2', NULL, '字典删除', 3, '1', NULL, NULL, '/admin/system/dict/type/{id}/', 'DELETE', 'system:dict:type:{id}:delete', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (36, '', 'admin', '2021-03-03 15:15:12.950584', '2021-03-03 15:15:12.950684', '2', NULL, '字典导出', 4, '1', NULL, NULL, '/admin/system/dict/type/export/', 'GET', 'system:dict:type:export:get', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (37, '', 'admin', '2021-03-03 15:16:54.709780', '2021-03-03 15:16:20.868146', '2', NULL, '清理缓存', 5, '1', NULL, NULL, '/admin/system/dict/type/clearCache/', 'DELETE', 'system:dict:type:clearcache:delete', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (38, '', 'admin', '2021-03-03 15:17:54.232085', '2021-03-03 15:17:54.232166', '2', NULL, '参数新增', 1, '1', NULL, NULL, '/admin/system/config/', 'POST', 'system:config:post', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (39, '', 'admin', '2021-03-03 15:18:37.088187', '2021-03-03 15:18:37.088237', '2', NULL, '参数修改', 2, '1', NULL, NULL, '/admin/system/config/{id}/', 'PUT', 'system:config:{id}:put', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (40, '', 'admin', '2021-03-03 15:19:05.532556', '2021-03-03 15:19:05.532616', '2', NULL, '参数删除', 3, '1', NULL, NULL, '/admin/system/config/{id}/', 'DELETE', 'system:config:{id}:delete', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (41, '', 'admin', '2021-03-03 15:19:49.576174', '2021-03-03 15:19:49.576221', '2', NULL, '参数导出', 4, '1', NULL, NULL, '/admin/system/config/export/', 'GET', 'system:config:export:get', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (42, '', 'admin', '2021-03-03 15:21:20.098250', '2021-03-03 15:21:20.098345', '2', NULL, '清理缓存', 5, '1', NULL, NULL, '/admin/system/config/clearCache/', 'DELETE', 'system:config:clearcache:delete', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (43, '', 'admin', '2021-03-03 15:22:48.492613', '2021-03-03 15:22:48.492666', '2', NULL, '文件上传', 1, '1', NULL, NULL, '/admin/system/savefile/', 'POST', 'system:savefile:post', '1', '1', '1', 1, 11, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (44, '', 'admin', '2021-03-03 15:23:58.219105', '2021-03-03 15:23:58.219155', '2', NULL, '文件删除', 2, '1', NULL, NULL, '/admin/system/savefile/{id}/', 'DELETE', 'system:savefile:{id}:delete', '1', '1', '1', 1, 11, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (45, '', 'admin', '2021-03-03 15:25:15.224971', '2021-03-03 15:25:15.225018', '2', NULL, '清理废弃文件', 3, '1', NULL, NULL, '/admin/system/clearsavefile/', 'POST', 'system:clearsavefile:post', '1', '1', '1', 1, 11, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (46, '', 'admin', '2021-03-03 15:28:30.061632', '2021-03-03 15:27:19.945663', '2', NULL, '文件下载', 4, '1', NULL, NULL, NULL, 'GET', 'system:clearsavefile:download:post', '1', '1', '1', 1, 11, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (47, '', 'admin', '2021-03-26 00:48:49.655959', '2021-03-07 14:32:06.754815', '1', 'message', '通知公告', 4, '1', 'message', 'vadmin/system/message/index', '', 'GET', '', '1', '1', '1', 1, 1, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (48, '', 'admin', '2021-03-07 14:35:06.718432', '2021-03-07 14:35:06.718463', '2', NULL, '发布公告', 1, '1', NULL, NULL, '/admin/system/message/', 'POST', 'system:message:post', '1', '1', '1', 1, 47, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (49, '', 'admin', '2021-03-08 13:04:32.158707', '2021-03-07 14:36:47.675837', '2', NULL, '修改公告', 2, '1', NULL, NULL, '/admin/system/message/{id}/', 'PUT', 'system:message:{id}:put', '1', '1', '1', 1, 47, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (50, '', 'admin', '2021-03-08 13:04:58.206693', '2021-03-07 14:37:52.130567', '2', NULL, '删除公告', 3, '1', NULL, NULL, '/admin/permission/menu/{id}/', 'DELETE', 'permission:menu:{id}:delete', '1', '1', '1', 1, 47, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (51, '', 'admin', '2021-03-07 14:42:37.410336', '2021-03-07 14:42:37.410366', '2', NULL, '公告导出', 4, '1', NULL, NULL, '/admin/system/message/export/', 'GET', 'system:message:export:get', '1', '1', '1', 1, 47, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (52, '', 'admin', '2021-03-09 17:19:13.828166', '2021-03-09 17:18:14.976783', '2', NULL, '字典查询', 0, '1', NULL, NULL, '/admin/system/dict/type/', 'GET', 'system:dict:type:get', '1', '1', '1', 1, 3, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (53, '', 'admin', '2021-03-09 17:19:46.963317', '2021-03-09 17:19:33.953559', '2', NULL, '参数查询', 0, '1', NULL, NULL, '/admin/system/config/', 'GET', 'system:config:get', '1', '1', '1', 1, 4, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (54, '', 'admin', '2021-03-09 17:20:14.749627', '2021-03-09 17:20:02.783389', '2', NULL, '文件查询', 0, '1', NULL, NULL, '/admin/system/savefile/', 'GET', 'system:savefile:get', '1', '1', '1', 1, 11, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (55, '', 'admin', '2021-03-09 17:20:44.604824', '2021-03-09 17:20:36.025364', '2', NULL, '公告查询', 0, '1', NULL, NULL, '/admin/system/message/', 'GET', 'system:message:get', '1', '1', '1', 1, 47, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (56, '', 'admin', '2021-03-09 17:21:06.429585', '2021-03-09 17:21:06.429629', '2', NULL, '岗位查询', 0, '1', NULL, NULL, '/admin/permission/post/', 'GET', 'permission:post:get', '1', '1', '1', 1, 5, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (57, '', 'admin', '2021-03-09 17:21:29.013165', '2021-03-09 17:21:29.013210', '2', NULL, '部门查询', 0, '1', NULL, NULL, '/admin/permission/dept/', 'GET', 'permission:dept:get', '1', '1', '1', 1, 6, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (58, '', 'admin', '2021-03-09 17:21:56.243957', '2021-03-09 17:21:47.358360', '2', NULL, '菜单查询', 0, '1', NULL, NULL, '/admin/permission/menus/', 'GET', 'permission:menus:get', '1', '1', '1', 1, 7, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (59, '', 'admin', '2021-03-09 17:22:20.140143', '2021-03-09 17:22:20.140189', '2', NULL, '角色查询', 0, '1', '', NULL, '/admin/permission/role/', 'GET', 'permission:role:get', '1', '1', '1', 1, 8, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (60, '', 'admin', '2021-03-09 17:22:38.595706', '2021-03-09 17:22:38.595751', '2', NULL, '用户查询', 0, '1', NULL, NULL, '/admin/permission/user/', 'GET', 'permission:user:get', '1', '1', '1', 1, 9, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (61, '', 'admin', '2021-03-21 11:34:17.635680', '2021-03-16 13:34:04.148728', '0', 'log', '日志管理', 5, '1', 'log', 'ParentView', NULL, 'GET', NULL, '1', '1', '1', 1, 1, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (62, '', 'admin', '2021-03-16 15:09:30.396752', '2021-03-16 13:36:00.114652', '1', 'logininfor', '登录日志', 1, '1', 'logininfor', 'vadmin/monitor/logininfor/index', '', 'GET', '', '1', '1', '1', 1, 61, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (63, '', 'admin', '2021-03-16 15:09:38.015636', '2021-03-16 14:28:10.395273', '1', 'log', '操作日志', 2, '1', 'operlog', 'vadmin/monitor/operlog/index', '', 'GET', '', '1', '1', '1', 1, 61, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (64, '', 'admin', '2021-03-16 14:31:27.618230', '2021-03-16 14:31:01.026470', '2', NULL, '登录日志查询', 1, '1', NULL, NULL, '/admin/system/logininfor/', 'GET', 'admin:system:logininfor:get', '1', '1', '1', 1, 62, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (65, '', 'admin', '2021-03-16 14:31:44.112525', '2021-03-16 14:31:44.112572', '2', NULL, '操作日志查询', 1, '1', NULL, NULL, '/admin/system/operlog/', 'GET', 'admin:system:operlog:get', '1', '1', '1', 1, 63, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (66, '', 'admin', '2021-03-26 00:47:50.628148', '2021-03-16 14:33:05.483003', '0', 'monitor', '系统监控', 3, '1', '/monitor', NULL, NULL, 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
||||
-- INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (67, '', 'admin', '2021-03-16 14:49:59.260322', '2021-03-16 14:34:59.165065', '1', 'online', '在线用户', 1, '1', 'online', 'vadmin/monitor/online/index', '', 'GET', '', '1', '1', '1', 1, 66, '1');
|
||||
-- INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (68, '', 'admin', '2021-03-16 14:36:00.989981', '2021-03-16 14:35:50.894454', '2', NULL, '在线用户查询', 1, '1', NULL, NULL, '/admin/monitor/online/', 'GET', 'admin:monitor:online:get', '1', '1', '1', 1, 67, '1');
|
||||
-- INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (69, '', 'admin', '2021-03-16 14:37:10.577186', '2021-03-16 14:37:10.577231', '2', NULL, '用户强退', 2, '1', NULL, NULL, '/admin/monitor/online/{id}/', 'PUT', 'admin:monitor:online:{id}:put', '1', '1', '1', 1, 67, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (70, '', 'admin', '2021-03-26 00:49:56.410579', '2021-03-16 14:45:51.507961', '1', 'job', '定时任务', 2, '1', 'celery', 'vadmin/monitor/celery/index', '', 'GET', NULL, '1', '1', '1', 1, 66, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (71, '', 'admin', '2021-03-16 15:04:11.799260', '2021-03-16 14:59:53.619219', '2', NULL, '任务查询', 1, '1', NULL, NULL, '/admin/monitor/celery/', 'GET', 'admin:monitor:celery:get', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (72, '', 'admin', '2021-03-16 15:04:06.645135', '2021-03-16 15:00:21.809600', '2', NULL, '任务新增', 2, '1', NULL, NULL, '/admin/monitor/celery/', 'POST', 'admin:monitor:celery:post', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (73, '', 'admin', '2021-03-16 15:04:00.041701', '2021-03-16 15:00:45.994228', '2', NULL, '任务修改', 3, '1', NULL, NULL, '/admin/monitor/celery/{id}/', 'PUT', 'admin:monitor:celery:{id}:put', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (74, '', 'admin', '2021-03-16 15:03:54.891216', '2021-03-16 15:01:19.624182', '2', NULL, '任务删除', 4, '1', NULL, NULL, '/admin/monitor/celery/{id}/', 'DELETE', 'admin:monitor:celery:{id}:delete', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (75, '', 'admin', '2021-03-16 15:07:03.505007', '2021-03-16 15:03:35.796596', '2', NULL, '任务单次执行', 6, '1', NULL, NULL, '/admin/monitor/celery/run/', 'PUT', 'admin:monitor:celery:run:put', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (76, '', 'admin', '2021-03-16 15:08:09.768588', '2021-03-16 15:07:45.064547', '2', NULL, '任务导出', 5, '1', NULL, NULL, '/admin/monitor/celery/export/', 'GET', 'admin:monitor:celery:export:get', '1', '1', '1', 1, 70, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (77, '', 'admin', '2021-03-16 15:09:09.928480', '2021-03-16 15:08:46.299829', '2', NULL, '登录日志导出', 2, '1', NULL, NULL, '/admin/system/logininfor/export/', 'GET', 'admin:system:logininfor:export:get', '1', '1', '1', 1, 62, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (78, '', 'admin', '2021-03-16 15:09:59.500271', '2021-03-16 15:09:59.500333', '2', NULL, '操作日志导出', 2, '1', NULL, NULL, '/admin/system/operlog/export/', 'GET', 'admin:system:operlog:export:get', '1', '1', '1', 1, 63, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (79, '', 'admin', '2021-03-26 00:27:17.614309', '2021-03-16 15:11:05.675729', '1', 'job', '定时日志', 3, '1', 'celerylog', 'vadmin/monitor/celery/celerylog/index', NULL, 'GET', NULL, '1', '1', '1', 1, 61, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (80, '', 'admin', '2021-03-16 15:16:29.349992', '2021-03-16 15:12:19.707979', '2', NULL, '定时日志查询', 1, '1', NULL, NULL, '/admin/monitor/celerylog/', 'GET', 'admin:monitor:celerylog:get', '1', '1', '1', 1, 79, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (81, '', 'admin', '2021-03-16 15:16:34.419420', '2021-03-16 15:12:51.090410', '2', NULL, '定时日志导出', 2, '1', NULL, NULL, '/admin/monitor/celerylog/export/', 'GET', 'admin:monitor:celerylog:export:get', '1', '1', '1', 1, 79, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (82, '', 'admin', '2021-03-26 00:47:37.970118', '2021-03-16 15:15:21.397186', '0', 'tool', '系统工具', 4, '1', '/tool', NULL, NULL, 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (83, '', 'admin', '2021-03-26 00:50:12.345672', '2021-03-16 15:16:10.318426', '1', 'build', '表单构建', 1, '1', 'build', 'vadmin/tool/build/index', NULL, 'GET', NULL, '1', '1', '1', 1, 82, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (84, '', 'admin', '2021-03-16 15:19:24.228395', '2021-03-16 15:17:23.507732', '1', 'swagger', '系统接口', 2, '1', 'swagger', 'vadmin/tool/swagger/index', '/admin/docs/', 'GET', 'admin:docs:get', '1', '1', '1', 1, 82, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (85, '', 'admin', '2021-03-21 11:37:06.119591', '2021-03-21 11:37:06.119623', '2', NULL, '操作日志批量删除', 3, '1', NULL, NULL, '/admin/system/operation_log/{id}/', 'DELETE', 'admin:system:operation_log:{id}:delete', '1', '1', '1', 1, 63, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (86, '', 'admin', '2021-03-21 11:39:07.579469', '2021-03-21 11:39:07.579517', '2', NULL, '操作日志清空', 4, '1', NULL, NULL, '/admin/system/operation_log/clean/', 'DELETE', 'admin:system:operation_log:clean:delete', '1', '1', '1', 1, 63, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (87, '', 'admin', '2021-03-21 23:32:44.308857', '2021-03-21 23:32:44.308882', '2', NULL, '登录日志批量删除', 3, '1', NULL, NULL, '/admin/system/logininfor/{id}/', 'DELETE', 'admin:system:logininfor:{id}:delete', '1', '1', '1', 1, 62, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (88, '', 'admin', '2021-03-21 23:33:30.888568', '2021-03-21 23:33:30.888593', '2', NULL, '登录日志清空', 4, '1', NULL, NULL, '/admin/system/logininfor/clean/', 'DELETE', 'admin:system:logininfor:clean:delete', '1', '1', '1', 1, 62, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (90, '', 'admin', '2021-03-26 00:44:00.756139', '2021-03-26 00:43:14.390228', '2', NULL, '定时日志批量删除', 3, '1', NULL, NULL, '/admin/system/celery_log/{id}/', 'DELETE', 'admin:system:celery_log:{id}:delete', '1', '1', '1', 1, 79, '8');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (91, '', 'admin', '2021-03-26 00:44:36.135658', '2021-03-26 00:44:36.135679', '2', NULL, '定时日志清空', 4, '1', NULL, NULL, '/admin/system/celery_log/clean/', 'DELETE', 'admin:system:celery_log:clean:delete', '1', '1', '1', 1, 79, '8');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (92, '', 'admin', '2021-04-27 23:49:59.036636', '2021-04-27 23:44:54.512207', '1', 'server', '服务监控', 3, '1', '/monitor/server', 'vadmin/monitor/server/index', NULL, 'GET', NULL, '1', '1', '1', 1, 66, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (93, '', 'admin', '2021-04-27 23:57:46.633022', '2021-04-27 23:49:28.569029', '2', NULL, '服务监控查询', 1, '1', NULL, NULL, '/admin/monitor/server/', 'GET', 'admin:monitor:server:get', '1', '1', '1', 1, 92, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (94, '', 'admin', '2021-04-27 23:58:44.705142', '2021-04-27 23:58:13.384483', '2', NULL, '修改服务器信息', 2, '1', NULL, NULL, '/admin/monitor/server/{id}/', 'PUT', 'admin:monitor:server:{id}:put', '1', '1', '1', 1, 92, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (95, '', 'admin', '2021-04-27 23:59:29.530633', '2021-04-27 23:59:07.744938', '2', NULL, '修改监控信息', 3, '1', NULL, NULL, '/admin/monitor/monitor/enabled/', 'GET', 'admin:monitor:monitor:enabled:get', '1', '1', '1', 1, 92, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (96, '', 'admin', '2021-04-28 00:01:15.071889', '2021-04-27 23:59:48.612905', '2', NULL, '清空监控记录', 4, '1', NULL, NULL, '/admin/monitor/monitor/clean/', 'GET', 'admin:monitor:monitor:clean:get', '1', '1', '1', 1, 92, '1');
|
||||
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (97, '', 'admin', '2021-05-02 19:12:06.813143', '2021-05-02 18:58:06.260280', '0', 'dashboard', '首页', 0, '1', '/index', 'Layout/index', NULL, 'GET', NULL, '1', '1', '1', 1, NULL, '1');
|
|
@ -1,27 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 岗位管理初始化sql
|
||||
-- Table structure for permission_post
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_post`;
|
||||
-- CREATE TABLE `permission_post` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `description` longtext,
|
||||
-- `creator` varchar(255) DEFAULT NULL,
|
||||
-- `modifier` varchar(255) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `postName` varchar(64) NOT NULL,
|
||||
-- `postCode` varchar(32) NOT NULL,
|
||||
-- `postSort` int(11) NOT NULL,
|
||||
-- `status` varchar(8) NOT NULL,
|
||||
-- `remark` longtext,
|
||||
-- PRIMARY KEY (`id`)
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_post
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_post` (id, description, modifier, update_datetime, create_datetime, postName, postCode, postSort, status, remark, creator_id, dept_belong_id) VALUES (1, '', 'admin', '2021-02-27 07:16:10.725970', '2021-02-27 07:16:10.726016', '董事长', 'ceo', 1, '1', NULL, 1, 1);
|
||||
INSERT INTO `permission_post` (id, description, modifier, update_datetime, create_datetime, postName, postCode, postSort, status, remark, creator_id, dept_belong_id) VALUES (2, '', 'admin', '2021-02-27 07:16:28.139648', '2021-02-27 07:16:28.139689', '项目经理', 'ce', 2, '1', NULL, 1, 1);
|
||||
INSERT INTO `permission_post` (id, description, modifier, update_datetime, create_datetime, postName, postCode, postSort, status, remark, creator_id, dept_belong_id) VALUES (3, '', 'admin', '2021-02-27 07:16:39.843069', '2021-02-27 07:16:39.843114', '人力资源', 'hr', 3, '1', NULL, 1, 1);
|
||||
INSERT INTO `permission_post` (id, description, modifier, update_datetime, create_datetime, postName, postCode, postSort, status, remark, creator_id, dept_belong_id) VALUES (4, '', 'admin', '2021-02-27 07:16:51.082769', '2021-02-27 07:16:51.082813', '普通员工', 'user', 4, '1', NULL, 1, 1);
|
|
@ -1,192 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 角色管理 初始化
|
||||
-- Table structure for permission_role
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_role`;
|
||||
-- CREATE TABLE `permission_role` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `description` longtext,
|
||||
-- `creator` varchar(255) DEFAULT NULL,
|
||||
-- `modifier` varchar(255) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `roleName` varchar(64) NOT NULL,
|
||||
-- `roleKey` varchar(64) NOT NULL,
|
||||
-- `roleSort` int(11) NOT NULL,
|
||||
-- `status` varchar(8) NOT NULL,
|
||||
-- `admin` tinyint(1) NOT NULL,
|
||||
-- `dataScope` varchar(8) NOT NULL,
|
||||
-- `remark` longtext,
|
||||
-- PRIMARY KEY (`id`)
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_role
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_role` (id, description, modifier, update_datetime, create_datetime, roleName, roleKey, roleSort, status, admin, dataScope, remark, creator_id, dept_belong_id) VALUES (1, '', 'admin', '2021-02-27 08:48:23.225361', '2021-02-27 08:48:08.064911', '超级管理员', 'admin', 1, '1', 1, '2', NULL, 1, 1);
|
||||
INSERT INTO `permission_role` (id, description, modifier, update_datetime, create_datetime, roleName, roleKey, roleSort, status, admin, dataScope, remark, creator_id, dept_belong_id) VALUES (2, '', 'admin', '2021-02-27 08:49:05.149632', '2021-02-27 08:48:47.317214', '普通角色', 'common', 2, '1', 0, '2', NULL, 1, 1);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for permission_role_dept
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_role_dept`;
|
||||
-- CREATE TABLE `permission_role_dept` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `role_id` int(11) NOT NULL,
|
||||
-- `dept_id` int(11) NOT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `permission_role_dept_role_id_dept_id_1d89afeb_uniq` (`role_id`,`dept_id`),
|
||||
-- KEY `permission_role_dept_role_id_99a9f232` (`role_id`) USING BTREE,
|
||||
-- KEY `permission_role_dept_dept_id_cbe9076a` (`dept_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_role_dept
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (1, 1, 1);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (2, 1, 2);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (3, 1, 3);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (4, 1, 4);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (5, 1, 5);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (6, 1, 6);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (7, 1, 7);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (8, 1, 8);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (9, 1, 9);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (10, 1, 10);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (11, 1, 11);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (12, 1, 12);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (13, 1, 13);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (14, 1, 14);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (15, 1, 15);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (16, 1, 16);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (17, 2, 1);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (18, 2, 2);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (19, 2, 3);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (20, 2, 4);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (21, 2, 5);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (22, 2, 6);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (23, 2, 7);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (24, 2, 8);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (25, 2, 9);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (26, 2, 10);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (27, 2, 11);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (28, 2, 12);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (29, 2, 13);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (30, 2, 14);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (31, 2, 15);
|
||||
INSERT INTO `permission_role_dept` (id, role_id, dept_id) VALUES (32, 2, 16);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for permission_role_menu
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_role_menu`;
|
||||
-- CREATE TABLE `permission_role_menu` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `role_id` int(11) NOT NULL,
|
||||
-- `menu_id` int(11) NOT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `permission_role_menu_role_id_menu_id_bb9e5441_uniq` (`role_id`,`menu_id`),
|
||||
-- KEY `permission_role_menu_role_id_33541d2b` (`role_id`) USING BTREE,
|
||||
-- KEY `permission_role_menu_menu_id_0c24555f` (`menu_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_role_menu
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (1, 1, 1);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (2, 1, 2);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (3, 1, 3);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (4, 1, 4);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (5, 1, 5);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (6, 1, 6);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (7, 1, 7);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (8, 1, 8);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (9, 1, 9);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (10, 1, 10);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (11, 2, 1);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (12, 2, 2);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (13, 2, 3);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (14, 2, 4);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (15, 2, 5);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (16, 2, 6);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (17, 2, 7);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (18, 2, 8);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (19, 2, 9);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (20, 2, 10);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (21, 1, 11);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (22, 1, 13);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (23, 1, 14);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (24, 1, 15);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (25, 1, 16);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (26, 1, 17);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (27, 1, 18);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (28, 1, 19);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (29, 1, 20);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (30, 1, 21);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (31, 1, 22);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (32, 1, 23);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (33, 1, 24);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (34, 1, 25);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (35, 1, 26);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (36, 1, 27);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (37, 1, 28);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (38, 1, 29);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (39, 1, 30);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (40, 1, 31);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (41, 1, 32);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (42, 1, 33);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (43, 1, 34);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (44, 1, 35);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (45, 1, 36);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (46, 1, 37);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (47, 1, 38);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (48, 1, 39);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (49, 1, 40);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (50, 1, 41);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (51, 1, 42);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (52, 1, 43);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (53, 1, 44);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (54, 1, 45);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (55, 1, 46);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (56, 1, 47);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (57, 1, 48);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (58, 1, 49);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (59, 1, 50);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (60, 1, 51);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (61, 1, 52);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (62, 1, 53);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (63, 1, 54);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (64, 1, 55);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (65, 1, 56);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (66, 1, 57);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (67, 1, 58);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (68, 1, 59);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (69, 1, 60);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (74, 1, 61);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (75, 1, 62);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (76, 1, 63);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (70, 1, 64);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (71, 1, 65);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (79, 1, 66);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (80, 1, 70);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (81, 1, 71);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (82, 1, 72);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (83, 1, 73);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (84, 1, 74);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (85, 1, 75);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (86, 1, 76);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (72, 1, 77);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (73, 1, 78);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (92, 1, 79);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (93, 1, 80);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (94, 1, 81);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (88, 1, 82);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (89, 1, 83);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (77, 1, 85);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (78, 1, 86);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (95, 1, 87);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (96, 1, 88);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (97, 1, 90);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (98, 1, 91);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (99, 2, 97);
|
||||
INSERT INTO `permission_role_menu` (id, role_id, menu_id) VALUES (100, 1, 97);
|
|
@ -1,76 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 用户管理 初始化sql
|
||||
-- Table structure for permission_userprofile
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_userprofile`;
|
||||
-- CREATE TABLE `permission_userprofile` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `password` varchar(128) NOT NULL,
|
||||
-- `last_login` datetime(6) DEFAULT NULL,
|
||||
-- `is_superuser` tinyint(1) NOT NULL,
|
||||
-- `first_name` varchar(30) NOT NULL,
|
||||
-- `last_name` varchar(150) NOT NULL,
|
||||
-- `is_staff` tinyint(1) NOT NULL,
|
||||
-- `is_active` tinyint(1) NOT NULL,
|
||||
-- `date_joined` datetime(6) NOT NULL,
|
||||
-- `username` varchar(150) NOT NULL,
|
||||
-- `secret` varchar(255) NOT NULL,
|
||||
-- `email` varchar(255) DEFAULT NULL,
|
||||
-- `mobile` varchar(255) DEFAULT NULL,
|
||||
-- `avatar` longtext,
|
||||
-- `name` varchar(40) NOT NULL,
|
||||
-- `gender` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
|
||||
-- `remark` longtext,
|
||||
-- `user_type` int(11) NOT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `dept_id` int(11) DEFAULT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `username` (`username`),
|
||||
-- KEY `permission_userprofile_dept_id_bd5c7976` (`dept_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_userprofile
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_userprofile` (id, password, last_login, is_superuser, first_name, last_name, is_staff, is_active, date_joined, username, secret, email, mobile, avatar, name, gender, remark, user_type, create_datetime, update_datetime, dept_id, dept_belong_id, creator_id) VALUES (1, 'pbkdf2_sha256$150000$X0RG2idBumnn$TaMaXFquGzyDtytL3ofZG/sSN+1VR521A9xLkUPxYI4=', '2021-02-27 06:20:28.214775', 1, '', '', 1, 1, '2021-02-27 06:20:09.188689', 'admin', '3704adf3-380f-4c27-a8da-60420e8cb4ab', 'admin@qq.com', NULL, NULL, '管理员', '2', '1', 2, '2021-02-27 06:20:09.263192', '2021-02-27 09:14:30.009998', 1, 1, 1);
|
||||
INSERT INTO `permission_userprofile` (id, password, last_login, is_superuser, first_name, last_name, is_staff, is_active, date_joined, username, secret, email, mobile, avatar, name, gender, remark, user_type, create_datetime, update_datetime, dept_id, dept_belong_id, creator_id) VALUES (2, 'pbkdf2_sha256$150000$vWY1VIn7rEJz$qq2iiADgcGumy9kNU1FSBhktcimaudYICviCcOKzfKY=', NULL, 0, '', '', 0, 1, '2021-03-03 15:38:27.009893', 'dvadmin', 'b4c5d79a-f01c-4244-92f8-b5288eca1d50', NULL, NULL, NULL, '普通用户', '2', NULL, 0, '2021-03-03 15:38:27.010771', '2021-03-03 15:38:27.086069', 1, 1, 1);
|
||||
-- ----------------------------
|
||||
-- Table structure for permission_userprofile_post
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_userprofile_post`;
|
||||
-- CREATE TABLE `permission_userprofile_post` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `userprofile_id` int(11) NOT NULL,
|
||||
-- `post_id` int(11) NOT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `permission_userprofile_post_userprofile_id_post_id_b9fb91e9_uniq` (`userprofile_id`,`post_id`),
|
||||
-- KEY `permission_userprofile_post_userprofile_id_229fe756` (`userprofile_id`) USING BTREE,
|
||||
-- KEY `permission_userprofile_post_post_id_dda441c3` (`post_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_userprofile_post
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_userprofile_post` (id, userprofile_id, post_id) VALUES (1, 1, 1);
|
||||
INSERT INTO `permission_userprofile_post` (id, userprofile_id, post_id) VALUES (2, 2, 4);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for permission_userprofile_role
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `permission_userprofile_role`;
|
||||
-- CREATE TABLE `permission_userprofile_role` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `userprofile_id` int(11) NOT NULL,
|
||||
-- `role_id` int(11) NOT NULL,
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `permission_userprofile_role_userprofile_id_role_id_70affc5e_uniq` (`userprofile_id`,`role_id`),
|
||||
-- KEY `permission_userprofile_role_userprofile_id_66835002` (`userprofile_id`) USING BTREE,
|
||||
-- KEY `permission_userprofile_role_role_id_e91fd02e` (`role_id`) USING BTREE
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permission_userprofile_role
|
||||
-- ----------------------------
|
||||
INSERT INTO `permission_userprofile_role` (id, userprofile_id, role_id) VALUES (1, 1, 1);
|
||||
INSERT INTO `permission_userprofile_role` (id, userprofile_id, role_id) VALUES (2, 2, 2);
|
|
@ -1,27 +0,0 @@
|
|||
-- ----------------------------
|
||||
-- 参数设置 初始化sql
|
||||
-- Table structure for system_configsettings
|
||||
-- ----------------------------
|
||||
-- DROP TABLE IF EXISTS `system_configsettings`;
|
||||
-- CREATE TABLE `system_configsettings` (
|
||||
-- `id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
-- `description` longtext,
|
||||
-- `creator` varchar(255) DEFAULT NULL,
|
||||
-- `modifier` varchar(255) DEFAULT NULL,
|
||||
-- `update_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `create_datetime` datetime(6) DEFAULT NULL,
|
||||
-- `configName` varchar(64) NOT NULL,
|
||||
-- `configKey` varchar(256) NOT NULL,
|
||||
-- `configValue` varchar(256) NOT NULL,
|
||||
-- `configType` varchar(8) NOT NULL,
|
||||
-- `status` varchar(8) NOT NULL,
|
||||
-- `remark` varchar(256) DEFAULT NULL,
|
||||
-- PRIMARY KEY (`id`)
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_configsettings
|
||||
-- ----------------------------
|
||||
INSERT INTO `system_configsettings` (id, description, modifier, update_datetime, create_datetime, configName, configKey, configValue, configType, status, remark, creator_id, dept_belong_id) VALUES (1, '', 'admin', '2021-02-27 07:14:48.935587', '2021-02-27 07:14:48.935634', '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', '1', '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 1, 1);
|
||||
INSERT INTO `system_configsettings` (id, description, modifier, update_datetime, create_datetime, configName, configKey, configValue, configType, status, remark, creator_id, dept_belong_id) VALUES (2, '', 'admin', '2021-02-27 07:15:14.039924', '2021-02-27 07:15:14.039967', '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', '1', '初始化密码 123456', 1, 1);
|
||||
INSERT INTO `system_configsettings` (id, description, modifier, update_datetime, create_datetime, configName, configKey, configValue, configType, status, remark, creator_id, dept_belong_id) VALUES (3, '', 'admin', '2021-02-27 07:15:36.091655', '2021-02-27 07:15:36.091694', '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', '1', '深色主题theme-dark,浅色主题theme-light', 1, 1);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue