Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c7517be4a | ||
|
|
9b8d632995 | ||
|
|
9bfdac0953 | ||
|
|
2e6067fd31 | ||
|
|
a3c61d3291 | ||
|
|
ef8044ea22 | ||
|
|
56dcc7eff8 | ||
|
|
4eeb2cfec9 | ||
|
|
28d503eb8b | ||
|
|
0bec251f08 | ||
|
|
027481ce56 | ||
|
|
dd6cbf2694 | ||
|
|
7d179aae2e | ||
|
|
b5fbd9867b | ||
|
|
2acc3cce67 | ||
|
|
0cd0c414ee | ||
|
|
e51c86c83f | ||
|
|
71a25f4774 | ||
|
|
56563657e8 | ||
|
|
6bfb10e4a4 | ||
|
|
70cb8eb35b | ||
|
|
cdea48c7d4 | ||
|
|
fba22bbcbf | ||
|
|
14f96abdb3 | ||
|
|
28ff95bf0d | ||
|
|
6cee5a6104 | ||
|
|
3add95e910 | ||
|
|
1db1064c11 | ||
|
|
f75928119e | ||
|
|
9051e8138c | ||
|
|
8396f49105 | ||
|
|
c664c70bbc | ||
|
|
7a503cd94a | ||
|
|
7a9aeec8db | ||
|
|
2c57bc36ea | ||
|
|
c0fc70425b | ||
|
|
f95944a781 | ||
|
|
589e0c8ce7 | ||
|
|
6e0ff64893 | ||
|
|
044e432eb7 | ||
|
|
5887079ade | ||
|
|
724e0817a5 | ||
|
|
9caa7a22e5 | ||
|
|
c2042d5f80 | ||
|
|
51f17c9539 | ||
|
|
27ed99ee27 | ||
|
|
7eb41e9754 | ||
|
|
c7f266a482 | ||
|
|
f2d444b877 | ||
|
|
9e59035300 | ||
|
|
b0ed2100a2 | ||
|
|
6f0c86fba6 | ||
|
|
c71562a12f | ||
|
|
a7fa415545 | ||
|
|
24d2523385 | ||
|
|
d30a3d79de | ||
|
|
860d5778cc | ||
|
|
23dbe9ee9c | ||
|
|
9114964ef2 | ||
|
|
56615528b9 | ||
|
|
1b5c54daf9 | ||
|
|
c0a3f5243b | ||
|
|
d22eb22f74 | ||
|
|
7eeb4c2489 | ||
|
|
d691c444ae | ||
|
|
83c23ea276 | ||
|
|
cff67d152f | ||
|
|
ad67c289d3 | ||
|
|
4a4d8f763d | ||
|
|
dfc734c13a | ||
|
|
654f441d05 | ||
|
|
48eebc1c95 | ||
|
|
3c1764e58d | ||
|
|
233241c962 | ||
|
|
30f9774ab1 | ||
|
|
a255c746d4 | ||
|
|
eac2a1c941 | ||
|
|
110a5faaff | ||
|
|
f3cfdcf580 | ||
|
|
34a1066cd0 | ||
|
|
67d05c39f3 | ||
|
|
fa49130c4f | ||
|
|
5b76973d9c | ||
|
|
0d57a2a8f2 | ||
|
|
78b7dae880 | ||
|
|
04a89144ba | ||
|
|
3b3eecc1d1 | ||
|
|
ca92d949dd | ||
|
|
663c7925e3 | ||
|
|
76b2ad6f58 | ||
|
|
fd8dcfee40 | ||
|
|
0a60c1960d | ||
|
|
28021df2ab | ||
|
|
6d42b6d56c | ||
|
|
3b467f42fe | ||
|
|
e37749c669 | ||
|
|
2cbbf25060 | ||
|
|
986ae4e4bc | ||
|
|
103aaf4911 | ||
|
|
7038ce64a6 | ||
|
|
9b8525ca1e | ||
|
|
254ce53387 | ||
|
|
0ff0c456b0 | ||
|
|
57a54090bb | ||
|
|
e3d3424ee1 | ||
|
|
99b2f611ec | ||
|
|
a675d78b82 | ||
|
|
62bd10cc60 | ||
|
|
9e8a5357be | ||
|
|
5faf88283f | ||
|
|
14a32e6d3c | ||
|
|
5e08f3e49b | ||
|
|
d9a5bcb0de | ||
|
|
48633729fb | ||
|
|
f274e060f4 | ||
|
|
9784f7816a | ||
|
|
f93a36c094 | ||
|
|
375d3a10b2 | ||
|
|
a1fbf5a0ae | ||
|
|
10035cc158 | ||
|
|
3b1150ad1f | ||
|
|
73222e854c | ||
|
|
3db99422b7 | ||
|
|
d876c8309f | ||
|
|
e0738aa5b2 | ||
|
|
f051693690 | ||
|
|
c6ffbbc062 | ||
|
|
2836fc1139 | ||
|
|
e111f4a763 | ||
|
|
3d5e4b9e9b | ||
|
|
8f4054e576 | ||
|
|
3ea4edd117 | ||
|
|
2f0df0a700 | ||
|
|
a709095dc2 | ||
|
|
4a8ac0ac83 | ||
|
|
b9301046da | ||
|
|
3e98b4e656 | ||
|
|
dd97ccf8c4 | ||
|
|
43d2ffa132 | ||
|
|
f4420c211e | ||
|
|
6757c5d595 | ||
|
|
2455351347 | ||
|
|
0672a13c0a | ||
|
|
cc6a96fc94 | ||
|
|
d97b600f88 | ||
|
|
94b05256b3 | ||
|
|
c15d5aff66 | ||
|
|
229cb88179 | ||
|
|
03df5e8014 | ||
|
|
a521fcb7dc | ||
|
|
51f1201bca | ||
|
|
4c8917fe05 | ||
|
|
115d0c0c5a | ||
|
|
328458eda9 | ||
|
|
3dcdf8e1a3 | ||
|
|
d2a2b35317 | ||
|
|
3cf62d4305 |
@@ -1,69 +0,0 @@
|
|||||||
[tool.commitizen]
|
|
||||||
name = "cz_customize"
|
|
||||||
tag_format = "$version"
|
|
||||||
version_scheme = "pep440"
|
|
||||||
version_provider = "poetry"
|
|
||||||
update_changelog_on_bump = true
|
|
||||||
major_version_zero = true
|
|
||||||
|
|
||||||
[tool.commitizen.customize]
|
|
||||||
message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}:{% if subject %} {{subject}}{% endif %} {% if footer %} {{footer}}{% endif %}"
|
|
||||||
example = "feature: this feature enable customize through config file"
|
|
||||||
schema = "<type>: <body>"
|
|
||||||
schema_pattern = "(feature|fix|docs|style|refactor|perf|test|revert|build).*?:(\\s.*)"
|
|
||||||
bump_pattern = "^(break|new|fix|hotfix)"
|
|
||||||
bump_map = { "break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH" }
|
|
||||||
change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"]
|
|
||||||
info_path = "cz_customize_info.txt"
|
|
||||||
info = """
|
|
||||||
This is customized info
|
|
||||||
"""
|
|
||||||
commit_parser = "^(?P<change_type>feature|fix|docs|style|refactor|perf|test|revert|build).*?:\\s(?P<message>.*)?"
|
|
||||||
changelog_pattern = "^(feature|fix|docs|style|refactor|perf|test|revert|build)?(!)?"
|
|
||||||
change_type_map = { "feature" = "Feat", "bug fix" = "Fix" }
|
|
||||||
|
|
||||||
|
|
||||||
# 自定义提交指令
|
|
||||||
[[tool.commitizen.customize.questions]]
|
|
||||||
type = "list"
|
|
||||||
name = "change_type"
|
|
||||||
choices = [
|
|
||||||
{ value = "feature", name = "feature: 新功能" },
|
|
||||||
{ value = "fix", name = "fix: 修复 bug" },
|
|
||||||
{ value = "docs", name = "docs: 文档的修改" },
|
|
||||||
{ value = "style", name = "style: 格式化变动,不影响代码逻辑" },
|
|
||||||
{ value = "refactor", name = "refactor: 重构,即不是新增功能,也不是修改 bug 的代码变动" },
|
|
||||||
{ value = "perf", name = "perf: 性能优化" },
|
|
||||||
{ value = "test", name = "test: 增加测试" },
|
|
||||||
{ value = "revert", name = "revert: 回退" },
|
|
||||||
{ value = "build", name = "build: 打包" },
|
|
||||||
]
|
|
||||||
# choices = ["feature", "fix"] # short version
|
|
||||||
message = "请选择提交类型:"
|
|
||||||
|
|
||||||
|
|
||||||
# 修改内容的范围
|
|
||||||
[[tool.commitizen.customize.questions]]
|
|
||||||
type = "input"
|
|
||||||
name = "scope"
|
|
||||||
message = "请输入修改内容的范围(可选):"
|
|
||||||
|
|
||||||
|
|
||||||
# 自己的提交内容
|
|
||||||
[[tool.commitizen.customize.questions]]
|
|
||||||
type = "input"
|
|
||||||
name = "subject"
|
|
||||||
message = "请输入简要描述(必填):"
|
|
||||||
|
|
||||||
|
|
||||||
# 自己的提交内容
|
|
||||||
[[tool.commitizen.customize.questions]]
|
|
||||||
type = "input"
|
|
||||||
name = "body"
|
|
||||||
message = "请输入详细描述(可选):"
|
|
||||||
|
|
||||||
|
|
||||||
[[tool.commitizen.customize.questions]]
|
|
||||||
type = "input"
|
|
||||||
name = "footer"
|
|
||||||
message = "请输入需要关闭的 issue(可选):"
|
|
||||||
@@ -1,4 +1,14 @@
|
|||||||
FLASK_DEBUG=True # 开启调试模式
|
# flask配置
|
||||||
FLASK_RUN_PORT=5000 # 设置运行的端口
|
FLASK_APP="entrance:create_app()"
|
||||||
FLASK_RUN_HOST=0.0.0.0 # 设置监听的 ip
|
FLASK_ENV=development
|
||||||
FLASK_APP="pear_admin:create_app()" # 运行程序
|
FLASK_DEBUG=1
|
||||||
|
FLASK_RUN_HOST = 127.0.0.1
|
||||||
|
FLASK_RUN_PORT = 5000
|
||||||
|
|
||||||
|
# MySql配置信息
|
||||||
|
MYSQL_HOST=127.0.0.1
|
||||||
|
# MYSQL_HOST=dbserver
|
||||||
|
MYSQL_PORT=3306
|
||||||
|
MYSQL_DATABASE=next
|
||||||
|
MYSQL_USERNAME=root
|
||||||
|
MYSQL_PASSWORD=root
|
||||||
@@ -1,5 +1,118 @@
|
|||||||
.idea/
|
# Byte-compiled / optimized / DLL files
|
||||||
.venv/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# 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/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
instance/
|
instance/
|
||||||
migrations/
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
#ide
|
||||||
|
.idea/
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
repos:
|
|
||||||
- repo: https://github.com/python/black
|
|
||||||
rev: 23.9.1
|
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
language_version: python3.10
|
|
||||||
- repo: https://github.com/pycqa/isort
|
|
||||||
rev: 5.12.0
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
args: [ "--profile", "black", "--filter-files" ]
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
|
||||||
rev: "v3.0.3"
|
|
||||||
hooks:
|
|
||||||
- id: prettier
|
|
||||||
exclude: >
|
|
||||||
(?x)^(
|
|
||||||
.*.yaml|
|
|
||||||
package-lock.json|
|
|
||||||
yarn.lock|
|
|
||||||
^.+\.min\.(js|css)$
|
|
||||||
)$
|
|
||||||
stages: [ commit ]
|
|
||||||
- repo: https://github.com/commitizen-tools/commitizen
|
|
||||||
rev: 3.5.3
|
|
||||||
hooks:
|
|
||||||
- id: commitizen
|
|
||||||
stages: [ commit-msg ]
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 mkg
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -1,55 +1,56 @@
|
|||||||
## 本地启动
|
<div align="center">
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<h1 align="center">
|
||||||
|
Pear Admin Flask
|
||||||
|
</h1>
|
||||||
|
<h4 align="center">
|
||||||
|
开 箱 即 用 的 Flask 快 速 开 发 平 台
|
||||||
|
</h4>
|
||||||
|
|
||||||
环境要求:python 3.10 以上,安装了 poetry
|
[预 览](http://flask.pearadmin.com) | [官 网](http://www.pearadmin.com/) | [群聊](https://jq.qq.com/?_wv=1027&k=5OdSmve) | [社区](http://forum.pearadmin.com/)
|
||||||
|
|
||||||
初始化环境
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/pear%20admin%20flask-1.0.0-green" alt="Pear Admin Layui Version">
|
||||||
|
</a>
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/Python-3.6+-green.svg" alt="Python Version">
|
||||||
|
</a>
|
||||||
|
<a href="#">
|
||||||
|
<img src="https://img.shields.io/badge/Mysql-5.3.2+-green.svg" alt="Mysql Version">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img width="92%" style="border-radius:10px;margin-top:20px;margin-bottom:20px;box-shadow: 2px 0 6px gray;" src="https://images.gitee.com/uploads/images/2020/1019/104805_042b888c_4835367.png" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#### 项目简介
|
||||||
|
>Pear Admin Flask 新版本开发中
|
||||||
|
|
||||||
|
#### 安装
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
poetry install
|
pip install -r require/common.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
初始化数据库
|
#### 目录结构
|
||||||
|
|
||||||
```shell
|
pear-admin-flask
|
||||||
flask init
|
|
||||||
```
|
|
||||||
|
|
||||||
启动
|
common -> 公共
|
||||||
|
|
||||||
```shell
|
entrance -> 核心
|
||||||
flask run
|
|
||||||
```
|
|
||||||
|
|
||||||
## 贡献指南
|
logs -> 日志
|
||||||
|
|
||||||
如果想参与项目的贡献,提交代码之前需要启用 pre-commit、commitizen 对代码进行校验,运行以下指令即可。
|
modules -> 蓝图,视图,模型,服务
|
||||||
|
|
||||||
初始化 pre-commit
|
require -> 安装需要的文件
|
||||||
|
|
||||||
```shell
|
.flaskenv -> 配置文件
|
||||||
pre-commit install
|
|
||||||
```
|
|
||||||
|
|
||||||
检查代码是否符合规范
|
app.py -> 启动模块(使用flask run命令的话可以删除)
|
||||||
|
|
||||||
```shell
|
|
||||||
git add .
|
|
||||||
```
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pre-commit run --all-files
|
|
||||||
```
|
|
||||||
|
|
||||||
初始化 commitizen
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pre-commit install -t commit-msg
|
|
||||||
```
|
|
||||||
|
|
||||||
使用
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cz commit
|
|
||||||
```
|
|
||||||
|
|
||||||
代替 `git commit` 进行提交
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from entrance import create_app
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run()
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from flask import current_app
|
||||||
|
from cachelib.file import FileSystemCache
|
||||||
|
from cachelib.memcached import MemcachedCache
|
||||||
|
from cachelib.redis import RedisCache
|
||||||
|
from cachelib.simple import SimpleCache
|
||||||
|
from cachelib.uwsgi import UWSGICache
|
||||||
|
|
||||||
|
cacher: dict = {
|
||||||
|
'filesystem': FileSystemCache,
|
||||||
|
'memcached': MemcachedCache,
|
||||||
|
'redis': RedisCache,
|
||||||
|
'simple': SimpleCache,
|
||||||
|
'uwsgi': UWSGICache
|
||||||
|
}
|
||||||
|
cache = RedisCache()
|
||||||
|
|
||||||
|
|
||||||
|
def get_cache():
|
||||||
|
return cache.get(current_app.config.get("CACHE_TYPE") or "filesystem")()
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
from entrance.config import celery as config
|
||||||
|
from entrance.config.celery import broker_url
|
||||||
|
|
||||||
|
celery = Celery(__name__, broker=broker_url)
|
||||||
|
|
||||||
|
|
||||||
|
def register_celery(app):
|
||||||
|
celery.config_from_object(config)
|
||||||
|
|
||||||
|
class ContextTask(celery.Task):
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
with app.app_context():
|
||||||
|
return self.run(*args, **kwargs)
|
||||||
|
|
||||||
|
celery.Task = ContextTask
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
from flask_limiter import Limiter
|
||||||
|
from flask_limiter.util import get_remote_address
|
||||||
|
|
||||||
|
limiter = Limiter(
|
||||||
|
key_func=get_remote_address,
|
||||||
|
default_limits=["200 per day", "50 per hour"]
|
||||||
|
)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
from logging.config import dictConfig
|
||||||
|
|
||||||
|
|
||||||
|
def config_logger():
|
||||||
|
dictConfig(
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": False,
|
||||||
|
"formatters": {
|
||||||
|
"simple": {"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"}
|
||||||
|
},
|
||||||
|
"handlers": {
|
||||||
|
"console": {
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG",
|
||||||
|
"formatter": "simple",
|
||||||
|
"stream": "ext://sys.stdout",
|
||||||
|
},
|
||||||
|
"info_file_handler": {
|
||||||
|
"class": "logging.handlers.RotatingFileHandler",
|
||||||
|
"level": "INFO",
|
||||||
|
"formatter": "simple",
|
||||||
|
"filename": "logs/info.log",
|
||||||
|
"maxBytes": 10485760,
|
||||||
|
"backupCount": 50,
|
||||||
|
"encoding": "utf8",
|
||||||
|
},
|
||||||
|
"error_file_handler": {
|
||||||
|
"class": "logging.handlers.RotatingFileHandler",
|
||||||
|
"level": "ERROR",
|
||||||
|
"formatter": "simple",
|
||||||
|
"filename": "logs/errors.log",
|
||||||
|
"maxBytes": 10485760,
|
||||||
|
"backupCount": 20,
|
||||||
|
"encoding": "utf8",
|
||||||
|
},
|
||||||
|
"debug_file_handler": {
|
||||||
|
"class": "logging.handlers.RotatingFileHandler",
|
||||||
|
"level": "DEBUG",
|
||||||
|
"formatter": "simple",
|
||||||
|
"filename": "logs/debug.log",
|
||||||
|
"maxBytes": 10485760,
|
||||||
|
"backupCount": 50,
|
||||||
|
"encoding": "utf8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"loggers": {
|
||||||
|
"my_module": {"level": "ERROR", "handlers": ["console"], "propagate": "no"}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"level": "DEBUG",
|
||||||
|
"handlers": ["error_file_handler", "debug_file_handler"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from flask_mail import Mail
|
||||||
|
|
||||||
|
mail = Mail()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
from flask_migrate import Migrate
|
||||||
|
|
||||||
|
from common.extend.orm import db
|
||||||
|
from entrance.models import model_lists
|
||||||
|
|
||||||
|
migrate = Migrate(db=db, directory='entrance/migrations')
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import datetime
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from flask import request
|
||||||
|
from flask_sqlalchemy import SQLAlchemy, BaseQuery
|
||||||
|
|
||||||
|
|
||||||
|
class Query(BaseQuery):
|
||||||
|
|
||||||
|
def all_json(self) -> list:
|
||||||
|
return [dict(i) for i in self.all()]
|
||||||
|
|
||||||
|
def soft_delete(self):
|
||||||
|
return self.update({"delete_at": datetime.datetime.now()})
|
||||||
|
|
||||||
|
def logic_all(self):
|
||||||
|
return self.filter_by(delete_at=None).all()
|
||||||
|
|
||||||
|
def layui_paginate(self):
|
||||||
|
return self.paginate(page=request.args.get('page', type=int),
|
||||||
|
per_page=request.args.get('limit', type=int),
|
||||||
|
error_out=False)
|
||||||
|
|
||||||
|
def layui_paginate_json(self) -> Tuple[list, int]:
|
||||||
|
p = self.paginate(page=request.args.get('page', type=int),
|
||||||
|
per_page=request.args.get('limit', type=int),
|
||||||
|
error_out=False)
|
||||||
|
|
||||||
|
return [dict(i) for i in p.items], p.total
|
||||||
|
|
||||||
|
|
||||||
|
db = SQLAlchemy(query_class=Query)
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from entrance.extensions import db
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
from sqlalchemy import ForeignKey
|
||||||
|
from sqlalchemy.orm import backref
|
||||||
|
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModel(db.Model):
|
||||||
|
__abstract__ = True
|
||||||
|
|
||||||
|
# insert and update
|
||||||
|
def save(self):
|
||||||
|
db.session.add(self)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# delete
|
||||||
|
def delete(self):
|
||||||
|
db.session.delete(self)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
class CommonModel(BaseModel):
|
||||||
|
__abstract__ = True
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
|
||||||
|
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = db.Column(db.DateTime, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
|
||||||
|
|
||||||
|
class CurdModel(BaseModel):
|
||||||
|
__abstract__ = True
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
|
||||||
|
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = db.Column(db.DateTime, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
delete_at = db.Column(db.DateTime, comment='删除时间')
|
||||||
|
|
||||||
|
|
||||||
|
Column = db.Column
|
||||||
|
Table = db.Table
|
||||||
|
relationship = relationship
|
||||||
|
ForeignKey = ForeignKey
|
||||||
|
backref = backref
|
||||||
|
|
||||||
|
TypeDecorator = db.TypeDecorator
|
||||||
|
INT = db.INT
|
||||||
|
CHAR = db.CHAR
|
||||||
|
VARCHAR = db.VARCHAR
|
||||||
|
NCHAR = db.NCHAR
|
||||||
|
NVARCHAR = db.NVARCHAR
|
||||||
|
TEXT = db.TEXT
|
||||||
|
Text = db.Text
|
||||||
|
FLOAT = db.FLOAT
|
||||||
|
NUMERIC = db.NUMERIC
|
||||||
|
REAL = db.REAL
|
||||||
|
DECIMAL = db.DECIMAL
|
||||||
|
TIMESTAMP = db.TIMESTAMP
|
||||||
|
DATETIME = db.DATETIME
|
||||||
|
CLOB = db.CLOB
|
||||||
|
BLOB = db.BLOB
|
||||||
|
BINARY = db.BINARY
|
||||||
|
VARBINARY = db.VARBINARY
|
||||||
|
BOOLEAN = db.BOOLEAN
|
||||||
|
BIGINT = db.BIGINT
|
||||||
|
SMALLINT = db.SMALLINT
|
||||||
|
INTEGER = db.INTEGER
|
||||||
|
DATE = db.DATE
|
||||||
|
TIME = db.TIME
|
||||||
|
TupleType = db.TupleType
|
||||||
|
String = db.String
|
||||||
|
Integer = db.Integer
|
||||||
|
SmallInteger = db.SmallInteger
|
||||||
|
BigInteger = db.BigInteger
|
||||||
|
Numeric = db.Numeric
|
||||||
|
Float = db.Float
|
||||||
|
DateTime = db.DateTime
|
||||||
|
Date = db.Date
|
||||||
|
Time = db.Time
|
||||||
|
LargeBinary = db.LargeBinary
|
||||||
|
Boolean = db.Boolean
|
||||||
|
Unicode = db.Unicode
|
||||||
|
UnicodeText = db.UnicodeText
|
||||||
|
PickleType = db.PickleType
|
||||||
|
Interval = db.Interval
|
||||||
|
Enum = db.Enum
|
||||||
|
ARRAY = db.ARRAY
|
||||||
|
JSON = db.JSON
|
||||||
|
|
||||||
|
SQLAlchemyAutoSchema = SQLAlchemyAutoSchema
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import random, math
|
||||||
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||||
|
|
||||||
|
|
||||||
|
class vieCode:
|
||||||
|
__fontSize = 20 # 字体大小
|
||||||
|
__width = 120 # 画布宽度
|
||||||
|
__heigth = 45 # 画布高度
|
||||||
|
__length = 4 # 验证码长度
|
||||||
|
__draw = None # 画布
|
||||||
|
__img = None # 图片资源
|
||||||
|
__code = None # 验证码字符
|
||||||
|
__str = None # 自定义验证码字符集
|
||||||
|
__inCurve = True # 是否画干扰线
|
||||||
|
__inNoise = True # 是否画干扰点
|
||||||
|
__type = 2 # 验证码类型 1、纯字母 2、数字字母混合
|
||||||
|
__fontPatn = 'applications/common/utils/fonts/2.ttf' # 字体
|
||||||
|
|
||||||
|
def GetCodeImage(self, size=80, length=4):
|
||||||
|
'''获取验证码图片
|
||||||
|
@param int size 验证码大小
|
||||||
|
@param int length 验证码长度
|
||||||
|
'''
|
||||||
|
# 准备基础数据
|
||||||
|
self.__length = length
|
||||||
|
self.__fontSize = size
|
||||||
|
self.__width = self.__fontSize * self.__length
|
||||||
|
self.__heigth = int(self.__fontSize * 1.5)
|
||||||
|
|
||||||
|
# 生成验证码图片
|
||||||
|
self.__createCode()
|
||||||
|
self.__createImage()
|
||||||
|
self.__createNoise()
|
||||||
|
self.__printString()
|
||||||
|
self.__cerateFilter()
|
||||||
|
|
||||||
|
return self.__img, self.__code
|
||||||
|
|
||||||
|
def __cerateFilter(self):
|
||||||
|
'''模糊处理'''
|
||||||
|
self.__img = self.__img.filter(ImageFilter.BLUR)
|
||||||
|
filter = ImageFilter.ModeFilter(8)
|
||||||
|
self.__img = self.__img.filter(filter)
|
||||||
|
|
||||||
|
def __createCode(self):
|
||||||
|
'''创建验证码字符'''
|
||||||
|
# 是否自定义字符集合
|
||||||
|
if not self.__str:
|
||||||
|
# 源文本
|
||||||
|
number = "3456789"
|
||||||
|
srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
|
||||||
|
srcUpper = srcLetter.upper()
|
||||||
|
if self.__type == 1:
|
||||||
|
self.__str = number
|
||||||
|
else:
|
||||||
|
self.__str = srcLetter + srcUpper + number
|
||||||
|
|
||||||
|
# 构造验证码
|
||||||
|
self.__code = random.sample(self.__str, self.__length)
|
||||||
|
|
||||||
|
def __createImage(self):
|
||||||
|
'''创建画布'''
|
||||||
|
bgColor = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
|
||||||
|
self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
|
||||||
|
self.__draw = ImageDraw.Draw(self.__img)
|
||||||
|
|
||||||
|
def __createNoise(self):
|
||||||
|
'''画干扰点'''
|
||||||
|
if not self.__inNoise:
|
||||||
|
return
|
||||||
|
font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
|
||||||
|
for i in range(5):
|
||||||
|
# 杂点颜色
|
||||||
|
noiseColor = (random.randint(150, 200), random.randint(150, 200), random.randint(150, 200))
|
||||||
|
putStr = random.sample(self.__str, 2)
|
||||||
|
for j in range(2):
|
||||||
|
# 绘杂点
|
||||||
|
size = (random.randint(-10, self.__width), random.randint(-10, self.__heigth))
|
||||||
|
self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __createCurve(self):
|
||||||
|
'''画干扰线'''
|
||||||
|
if not self.__inCurve:
|
||||||
|
return
|
||||||
|
x = y = 0
|
||||||
|
|
||||||
|
# 计算曲线系数
|
||||||
|
a = random.uniform(1, self.__heigth / 2)
|
||||||
|
b = random.uniform(-self.__width / 4, self.__heigth / 4)
|
||||||
|
f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
|
||||||
|
t = random.uniform(self.__heigth, self.__width * 2)
|
||||||
|
xend = random.randint(self.__width / 2, self.__width * 2)
|
||||||
|
w = (2 * math.pi) / t
|
||||||
|
|
||||||
|
# 画曲线
|
||||||
|
color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
|
||||||
|
for x in range(xend):
|
||||||
|
if w != 0:
|
||||||
|
for k in range(int(self.__heigth / 10)):
|
||||||
|
y = a * math.sin(w * x + f) + b + self.__heigth / 2
|
||||||
|
i = int(self.__fontSize / 5)
|
||||||
|
while i > 0:
|
||||||
|
px = x + i
|
||||||
|
py = y + i + k
|
||||||
|
self.__draw.point((px, py), color)
|
||||||
|
i -= i
|
||||||
|
|
||||||
|
def __printString(self):
|
||||||
|
'''打印验证码字符串'''
|
||||||
|
font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
|
||||||
|
x = 0
|
||||||
|
# 打印字符到画板
|
||||||
|
for i in range(self.__length):
|
||||||
|
# 设置字体随机颜色
|
||||||
|
color = (random.randint(30, 150), random.randint(30, 150), random.randint(30, 150))
|
||||||
|
# 计算座标
|
||||||
|
x = random.uniform(self.__fontSize * i * 0.95, self.__fontSize * i * 1.1)
|
||||||
|
y = self.__fontSize * random.uniform(0.3, 0.5)
|
||||||
|
# 打印字符
|
||||||
|
self.__draw.text((x, y), self.__code[i], font=font, fill=color)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from flask_mail import Message
|
||||||
|
|
||||||
|
# send_mail(subject='title', recipients=['123@qq.com'], content='body')
|
||||||
|
from common.extend.mail import mail
|
||||||
|
|
||||||
|
|
||||||
|
def send_mail(subject, recipients, content):
|
||||||
|
try:
|
||||||
|
message = Message(subject=subject, recipients=recipients, body=content)
|
||||||
|
mail.send(message)
|
||||||
|
except Exception as e:
|
||||||
|
print('邮箱发送出错了')
|
||||||
|
raise
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from file_system_uploader import FilesystemUploader
|
||||||
|
from qiniu_uploader import QiniuUploader
|
||||||
|
from upyun_uploader import UpyunUploader
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
uploader: dict = {
|
||||||
|
"filesystem": FilesystemUploader,
|
||||||
|
"qiniu": QiniuUploader,
|
||||||
|
'upyun': UpyunUploader
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_uploader():
|
||||||
|
return uploader.get(current_app.config.get("UPLOAD_PROVIDER") or "filesystem")()
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class BaseUploader(object):
|
||||||
|
def __init__(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def store(self, fileobj, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def upload(self, file_obj, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def download(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
from pathlib import PurePath
|
||||||
|
from shutil import copyfileobj, rmtree
|
||||||
|
|
||||||
|
from PIL.features import codecs
|
||||||
|
from flask import current_app, send_file
|
||||||
|
from werkzeug.utils import safe_join, secure_filename
|
||||||
|
|
||||||
|
from common.utils.uploads.base_uploader import BaseUploader
|
||||||
|
|
||||||
|
|
||||||
|
def hexencode(s):
|
||||||
|
if isinstance(s, (str,)):
|
||||||
|
s = s.encode("utf-8")
|
||||||
|
encoded = codecs.encode(s, "hex")
|
||||||
|
try:
|
||||||
|
encoded = encoded.decode("utf-8")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
pass
|
||||||
|
return encoded
|
||||||
|
|
||||||
|
|
||||||
|
class FilesystemUploader(BaseUploader):
|
||||||
|
def __init__(self, base_path=None):
|
||||||
|
super(BaseUploader, self).__init__()
|
||||||
|
self.base_path = base_path or current_app.config.get("UPLOAD_FOLDER")
|
||||||
|
|
||||||
|
def store(self, fileobj, filename):
|
||||||
|
location = os.path.join(self.base_path, filename)
|
||||||
|
directory = os.path.dirname(location)
|
||||||
|
|
||||||
|
if not os.path.exists(directory):
|
||||||
|
os.makedirs(directory)
|
||||||
|
|
||||||
|
with open(location, "wb") as dst:
|
||||||
|
copyfileobj(fileobj, dst, 16384)
|
||||||
|
|
||||||
|
return filename
|
||||||
|
|
||||||
|
def upload(self, file_obj, filename):
|
||||||
|
if len(filename) == 0:
|
||||||
|
raise Exception("Empty filenames cannot be used")
|
||||||
|
|
||||||
|
filename = secure_filename(filename)
|
||||||
|
md5hash = hexencode(os.urandom(16))
|
||||||
|
file_path = posixpath.join(md5hash, filename)
|
||||||
|
|
||||||
|
return self.store(file_obj, file_path)
|
||||||
|
|
||||||
|
def download(self, filename):
|
||||||
|
return send_file(safe_join(self.base_path, filename), as_attachment=True)
|
||||||
|
|
||||||
|
def delete(self, filename):
|
||||||
|
if os.path.exists(os.path.join(self.base_path, filename)):
|
||||||
|
file_path = PurePath(filename).parts[0]
|
||||||
|
rmtree(os.path.join(self.base_path, file_path))
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
from qiniu import Auth, put_data
|
||||||
|
from base_uploader import BaseUploader
|
||||||
|
|
||||||
|
access_key = '自己账号的access key'
|
||||||
|
|
||||||
|
secret_key = '自己账号的secret key'
|
||||||
|
|
||||||
|
bucket_name = '空间名'
|
||||||
|
|
||||||
|
|
||||||
|
class QiniuUploader(BaseUploader):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def store(self, fileobj, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def upload(self, file_obj, filename):
|
||||||
|
|
||||||
|
token = Auth(access_key=access_key, secret_key=secret_key).upload_token(bucket=bucket_name)
|
||||||
|
ret, res = put_data(token, None, data=file_obj)
|
||||||
|
ret.get('key')
|
||||||
|
print(ret)
|
||||||
|
print(res)
|
||||||
|
|
||||||
|
if res.status_code != 200:
|
||||||
|
raise Exception("upload failed")
|
||||||
|
return ret, res
|
||||||
|
|
||||||
|
def download(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
raise NotImplementedError
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
from base_uploader import BaseUploader
|
||||||
|
import upyun
|
||||||
|
|
||||||
|
|
||||||
|
class UpyunUploader(BaseUploader):
|
||||||
|
def __init__(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def store(self, fileobj, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def upload(self, file_obj, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def download(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete(self, filename):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
raise NotImplementedError
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from flask import Blueprint as FlaskBlueprint
|
||||||
|
from flask.views import MethodViewType, MethodView
|
||||||
|
|
||||||
|
|
||||||
|
class Blueprint(FlaskBlueprint):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self._endpoints = []
|
||||||
|
|
||||||
|
def add_url_rule(
|
||||||
|
self,
|
||||||
|
rule,
|
||||||
|
endpoint=None,
|
||||||
|
view_func=None,
|
||||||
|
provide_automatic_options=None,
|
||||||
|
*,
|
||||||
|
parameters=None,
|
||||||
|
tags=None,
|
||||||
|
**options,
|
||||||
|
):
|
||||||
|
|
||||||
|
if view_func is None:
|
||||||
|
raise TypeError("view_func must be provided")
|
||||||
|
|
||||||
|
if endpoint is None:
|
||||||
|
endpoint = view_func.__name__
|
||||||
|
|
||||||
|
# Ensure endpoint name is unique
|
||||||
|
# - to avoid a name clash when registering a MethodView
|
||||||
|
# - to use it as a key internally in endpoint -> doc mapping
|
||||||
|
if endpoint in self._endpoints:
|
||||||
|
endpoint = f"{endpoint}_{len(self._endpoints)}"
|
||||||
|
self._endpoints.append(endpoint)
|
||||||
|
|
||||||
|
if isinstance(view_func, MethodViewType):
|
||||||
|
func = view_func.as_view(endpoint)
|
||||||
|
else:
|
||||||
|
func = view_func
|
||||||
|
|
||||||
|
# Add URL rule in Flask and store endpoint documentation
|
||||||
|
super().add_url_rule(rule, endpoint, func, **options)
|
||||||
|
|
||||||
|
def route(self, rule, *, parameters=None, tags=None, **options):
|
||||||
|
"""Decorator to register view function in application and documentation
|
||||||
|
|
||||||
|
Calls :meth:`add_url_rule <Blueprint.add_url_rule>`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
endpoint = options.pop("endpoint", None)
|
||||||
|
self.add_url_rule(
|
||||||
|
rule, endpoint, func, parameters=parameters, tags=tags, **options
|
||||||
|
)
|
||||||
|
return func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
def register_child_bp(self, bp_lists):
|
||||||
|
for bp in bp_lists:
|
||||||
|
self.register_blueprint(bp)
|
||||||
|
|
||||||
|
|
||||||
|
class View(MethodView):
|
||||||
|
pass
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import os
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
|
|
||||||
class BaseConfig:
|
|
||||||
SECRET_KEY = os.getenv("SECRET_KEY", "pear-admin-flask")
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = ""
|
|
||||||
|
|
||||||
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
JWT_TOKEN_LOCATION = ["headers"]
|
|
||||||
JWT_ACCESS_TOKEN_EXPIRES = timedelta(days=7)
|
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentConfig(BaseConfig):
|
|
||||||
"""开发配置"""
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = "sqlite:///pear_admin.db"
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
||||||
|
|
||||||
|
|
||||||
class TestingConfig(BaseConfig):
|
|
||||||
"""测试配置"""
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:" # 内存数据库
|
|
||||||
|
|
||||||
|
|
||||||
class ProductionConfig(BaseConfig):
|
|
||||||
"""生成环境配置"""
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = "mysql://root:root@127.0.0.1:3306/pear_admin"
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
||||||
|
|
||||||
|
|
||||||
config = {"dev": DevelopmentConfig, "test": TestingConfig, "prod": ProductionConfig}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
from flask import Flask
|
||||||
|
import os
|
||||||
|
from common.extend.logger import config_logger
|
||||||
|
from entrance.bps import sys, register_parent_bp
|
||||||
|
from entrance.extensions import init_extensions
|
||||||
|
|
||||||
|
|
||||||
|
def create_app():
|
||||||
|
config_logger()
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_pyfile('config/config.py')
|
||||||
|
register_parent_bp(app)
|
||||||
|
init_extensions(app)
|
||||||
|
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
|
||||||
|
___ _ _ _ ___ _ _
|
||||||
|
| _ \___ __ _ _ _ /_\ __| |_ __ (_)_ _ | __| |__ _ __| |__
|
||||||
|
| _/ -_) _` | '_| / _ \/ _` | ' \| | ' \ | _|| / _` (_-< / /
|
||||||
|
|_| \___\__,_|_| /_/ \_\__,_|_|_|_|_|_||_| |_| |_\__,_/__/_\_\\
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from flask import Flask
|
||||||
|
from typing import List
|
||||||
|
from common.view import Blueprint
|
||||||
|
from modules.sys.view.user import user
|
||||||
|
|
||||||
|
sys = Blueprint('sys', __name__, url_prefix='/sys')
|
||||||
|
sys_lists: List[Blueprint] = [
|
||||||
|
user
|
||||||
|
]
|
||||||
|
sys.register_child_bp(sys_lists)
|
||||||
|
|
||||||
|
parent_lists: List[Blueprint] = [
|
||||||
|
sys
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def register_parent_bp(app: Flask):
|
||||||
|
for bp in parent_lists:
|
||||||
|
app.register_blueprint(bp)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
broker_url = 'redis://127.0.0.1:6379/1'
|
||||||
|
result_backend = 'rpc://'
|
||||||
|
|
||||||
|
task_serializer = 'json'
|
||||||
|
result_serializer = 'json'
|
||||||
|
accept_content = ['json']
|
||||||
|
timezone = 'Asia/Shanghai'
|
||||||
|
enable_utc = True
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
# mysql 配置
|
||||||
|
MYSQL_USERNAME: str = os.getenv('MYSQL_USERNAME') or "root"
|
||||||
|
MYSQL_PASSWORD: str = os.getenv('MYSQL_PASSWORD') or "123456"
|
||||||
|
MYSQL_HOST: str = os.getenv('MYSQL_HOST') or "127.0.0.1"
|
||||||
|
MYSQL_PORT: int = int(os.getenv('MYSQL_PORT') or 3306)
|
||||||
|
MYSQL_DATABASE: str = os.getenv('MYSQL_DATABASE') or "PearAdminFlask"
|
||||||
|
|
||||||
|
# mysql 数据库的配置信息
|
||||||
|
SQLALCHEMY_DATABASE_URI: str = f"mysql+pymysql://{MYSQL_USERNAME}:{MYSQL_PASSWORD}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}"
|
||||||
|
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||||
|
SQLALCHEMY_ECHO = False
|
||||||
|
SQLALCHEMY_POOL_RECYCLE = 8
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
from common.extend.celeryer import register_celery
|
||||||
|
from common.extend.limit import limiter
|
||||||
|
from common.extend.orm import db
|
||||||
|
from common.extend.migrate import migrate
|
||||||
|
|
||||||
|
|
||||||
|
def init_extensions(app: Flask):
|
||||||
|
db.init_app(app)
|
||||||
|
migrate.init_app(app)
|
||||||
|
register_celery(app)
|
||||||
|
limiter.init_app(app)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Single-database configuration for Flask.
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# A generic, single database configuration.
|
||||||
|
|
||||||
|
[alembic]
|
||||||
|
# template used to generate migration files
|
||||||
|
# file_template = %%(rev)s_%%(slug)s
|
||||||
|
|
||||||
|
# set to 'true' to run the environment during
|
||||||
|
# the 'revision' command, regardless of autogenerate
|
||||||
|
# revision_environment = false
|
||||||
|
|
||||||
|
|
||||||
|
# Logging configuration
|
||||||
|
[loggers]
|
||||||
|
keys = root,sqlalchemy,alembic,flask_migrate
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys = console
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys = generic
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
level = WARN
|
||||||
|
handlers = console
|
||||||
|
qualname =
|
||||||
|
|
||||||
|
[logger_sqlalchemy]
|
||||||
|
level = WARN
|
||||||
|
handlers =
|
||||||
|
qualname = sqlalchemy.engine
|
||||||
|
|
||||||
|
[logger_alembic]
|
||||||
|
level = INFO
|
||||||
|
handlers =
|
||||||
|
qualname = alembic
|
||||||
|
|
||||||
|
[logger_flask_migrate]
|
||||||
|
level = INFO
|
||||||
|
handlers =
|
||||||
|
qualname = flask_migrate
|
||||||
|
|
||||||
|
[handler_console]
|
||||||
|
class = StreamHandler
|
||||||
|
args = (sys.stderr,)
|
||||||
|
level = NOTSET
|
||||||
|
formatter = generic
|
||||||
|
|
||||||
|
[formatter_generic]
|
||||||
|
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||||
|
datefmt = %H:%M:%S
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from logging.config import fileConfig
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from alembic import context
|
||||||
|
|
||||||
|
# this is the Alembic Config object, which provides
|
||||||
|
# access to the values within the .ini file in use.
|
||||||
|
config = context.config
|
||||||
|
|
||||||
|
# Interpret the config file for Python logging.
|
||||||
|
# This line sets up loggers basically.
|
||||||
|
fileConfig(config.config_file_name)
|
||||||
|
logger = logging.getLogger('alembic.env')
|
||||||
|
|
||||||
|
# add your model's MetaData object here
|
||||||
|
# for 'autogenerate' support
|
||||||
|
# from myapp import mymodel
|
||||||
|
# target_metadata = mymodel.Base.metadata
|
||||||
|
config.set_main_option(
|
||||||
|
'sqlalchemy.url',
|
||||||
|
str(current_app.extensions['migrate'].db.get_engine().url).replace(
|
||||||
|
'%', '%%'))
|
||||||
|
target_metadata = current_app.extensions['migrate'].db.metadata
|
||||||
|
|
||||||
|
# other values from the config, defined by the needs of env.py,
|
||||||
|
# can be acquired:
|
||||||
|
# my_important_option = config.get_main_option("my_important_option")
|
||||||
|
# ... etc.
|
||||||
|
|
||||||
|
|
||||||
|
def run_migrations_offline():
|
||||||
|
"""Run migrations in 'offline' mode.
|
||||||
|
|
||||||
|
This configures the context with just a URL
|
||||||
|
and not an Engine, though an Engine is acceptable
|
||||||
|
here as well. By skipping the Engine creation
|
||||||
|
we don't even need a DBAPI to be available.
|
||||||
|
|
||||||
|
Calls to context.execute() here emit the given string to the
|
||||||
|
script output.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url = config.get_main_option("sqlalchemy.url")
|
||||||
|
context.configure(
|
||||||
|
url=url, target_metadata=target_metadata, literal_binds=True
|
||||||
|
)
|
||||||
|
|
||||||
|
with context.begin_transaction():
|
||||||
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
|
def run_migrations_online():
|
||||||
|
"""Run migrations in 'online' mode.
|
||||||
|
|
||||||
|
In this scenario we need to create an Engine
|
||||||
|
and associate a connection with the context.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# this callback is used to prevent an auto-migration from being generated
|
||||||
|
# when there are no changes to the schema
|
||||||
|
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||||
|
def process_revision_directives(context, revision, directives):
|
||||||
|
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||||
|
script = directives[0]
|
||||||
|
if script.upgrade_ops.is_empty():
|
||||||
|
directives[:] = []
|
||||||
|
logger.info('No changes in schema detected.')
|
||||||
|
|
||||||
|
connectable = current_app.extensions['migrate'].db.get_engine()
|
||||||
|
|
||||||
|
with connectable.connect() as connection:
|
||||||
|
context.configure(
|
||||||
|
connection=connection,
|
||||||
|
target_metadata=target_metadata,
|
||||||
|
process_revision_directives=process_revision_directives,
|
||||||
|
**current_app.extensions['migrate'].configure_args
|
||||||
|
)
|
||||||
|
|
||||||
|
with context.begin_transaction():
|
||||||
|
context.run_migrations()
|
||||||
|
|
||||||
|
|
||||||
|
if context.is_offline_mode():
|
||||||
|
run_migrations_offline()
|
||||||
|
else:
|
||||||
|
run_migrations_online()
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
"""${message}
|
||||||
|
|
||||||
|
Revision ID: ${up_revision}
|
||||||
|
Revises: ${down_revision | comma,n}
|
||||||
|
Create Date: ${create_date}
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
${imports if imports else ""}
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = ${repr(up_revision)}
|
||||||
|
down_revision = ${repr(down_revision)}
|
||||||
|
branch_labels = ${repr(branch_labels)}
|
||||||
|
depends_on = ${repr(depends_on)}
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
${upgrades if upgrades else "pass"}
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
${downgrades if downgrades else "pass"}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 74133ba99af7
|
||||||
|
Revises:
|
||||||
|
Create Date: 2022-01-22 18:50:29.097473
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '74133ba99af7'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('admin_user',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='用户ID'),
|
||||||
|
sa.Column('username', sa.String(length=20), nullable=True, comment='用户名'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('admin_user')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 8293d5eb9040
|
||||||
|
Revises: d51040631f21
|
||||||
|
Create Date: 2022-01-23 15:56:22.001914
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '8293d5eb9040'
|
||||||
|
down_revision = 'd51040631f21'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('sys_admin_log',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('method', sa.String(length=10), nullable=True),
|
||||||
|
sa.Column('uid', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('url', sa.String(length=255), nullable=True),
|
||||||
|
sa.Column('desc', sa.Text(), nullable=True),
|
||||||
|
sa.Column('ip', sa.String(length=255), nullable=True),
|
||||||
|
sa.Column('success', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('user_agent', sa.Text(), nullable=True),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_dept',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False, comment='部门ID'),
|
||||||
|
sa.Column('parent_id', sa.Integer(), nullable=True, comment='父级编号'),
|
||||||
|
sa.Column('dept_name', sa.String(length=50), nullable=True, comment='部门名称'),
|
||||||
|
sa.Column('sort', sa.Integer(), nullable=True, comment='排序'),
|
||||||
|
sa.Column('leader', sa.String(length=50), nullable=True, comment='负责人'),
|
||||||
|
sa.Column('phone', sa.String(length=20), nullable=True, comment='联系方式'),
|
||||||
|
sa.Column('email', sa.String(length=50), nullable=True, comment='邮箱'),
|
||||||
|
sa.Column('status', sa.Integer(), nullable=True, comment='状态(1开启,0关闭)'),
|
||||||
|
sa.Column('remark', sa.Text(), nullable=True, comment='备注'),
|
||||||
|
sa.Column('address', sa.String(length=255), nullable=True, comment='详细地址'),
|
||||||
|
sa.Column('create_at', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_at', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_dict_data',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('data_label', sa.String(length=255), nullable=True, comment='字典类型名称'),
|
||||||
|
sa.Column('data_value', sa.String(length=255), nullable=True, comment='字典类型标识'),
|
||||||
|
sa.Column('type_code', sa.String(length=255), nullable=True, comment='字典类型描述'),
|
||||||
|
sa.Column('is_default', sa.Integer(), nullable=True, comment='是否默认'),
|
||||||
|
sa.Column('enable', sa.Integer(), nullable=True, comment='是否开启'),
|
||||||
|
sa.Column('remark', sa.String(length=255), nullable=True, comment='备注'),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_time', sa.DateTime(), nullable=True, comment='更新时间'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_dict_type',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('type_name', sa.String(length=255), nullable=True, comment='字典类型名称'),
|
||||||
|
sa.Column('type_code', sa.String(length=255), nullable=True, comment='字典类型标识'),
|
||||||
|
sa.Column('description', sa.String(length=255), nullable=True, comment='字典类型描述'),
|
||||||
|
sa.Column('enable', sa.Integer(), nullable=True, comment='是否开启'),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_time', sa.DateTime(), nullable=True, comment='更新时间'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_photo',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('href', sa.String(length=255), nullable=True),
|
||||||
|
sa.Column('mime', sa.CHAR(length=50), nullable=False),
|
||||||
|
sa.Column('size', sa.CHAR(length=30), nullable=False),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_power',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False, comment='权限编号'),
|
||||||
|
sa.Column('name', sa.String(length=255), nullable=True, comment='权限名称'),
|
||||||
|
sa.Column('type', sa.String(length=1), nullable=True, comment='权限类型'),
|
||||||
|
sa.Column('code', sa.String(length=30), nullable=True, comment='权限标识'),
|
||||||
|
sa.Column('url', sa.String(length=255), nullable=True, comment='权限路径'),
|
||||||
|
sa.Column('open_type', sa.String(length=10), nullable=True, comment='打开方式'),
|
||||||
|
sa.Column('parent_id', sa.Integer(), nullable=True, comment='父类编号'),
|
||||||
|
sa.Column('icon', sa.String(length=128), nullable=True, comment='图标'),
|
||||||
|
sa.Column('sort', sa.Integer(), nullable=True, comment='排序'),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_time', sa.DateTime(), nullable=True, comment='更新时间'),
|
||||||
|
sa.Column('enable', sa.Integer(), nullable=True, comment='是否开启'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_role',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False, comment='角色ID'),
|
||||||
|
sa.Column('name', sa.String(length=255), nullable=True, comment='角色名称'),
|
||||||
|
sa.Column('code', sa.String(length=255), nullable=True, comment='角色标识'),
|
||||||
|
sa.Column('enable', sa.Integer(), nullable=True, comment='是否启用'),
|
||||||
|
sa.Column('remark', sa.String(length=255), nullable=True, comment='备注'),
|
||||||
|
sa.Column('details', sa.String(length=255), nullable=True, comment='详情'),
|
||||||
|
sa.Column('sort', sa.Integer(), nullable=True, comment='排序'),
|
||||||
|
sa.Column('create_time', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_time', sa.DateTime(), nullable=True, comment='更新时间'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_user',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='用户ID'),
|
||||||
|
sa.Column('username', sa.String(length=20), nullable=True, comment='用户名'),
|
||||||
|
sa.Column('realname', sa.String(length=20), nullable=True, comment='真实名字'),
|
||||||
|
sa.Column('avatar', sa.String(length=255), nullable=True, comment='头像'),
|
||||||
|
sa.Column('remark', sa.String(length=255), nullable=True, comment='备注'),
|
||||||
|
sa.Column('password_hash', sa.String(length=128), nullable=True, comment='哈希密码'),
|
||||||
|
sa.Column('enable', sa.Integer(), nullable=True, comment='启用'),
|
||||||
|
sa.Column('dept_id', sa.Integer(), nullable=True, comment='部门id'),
|
||||||
|
sa.Column('create_at', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.Column('update_at', sa.DateTime(), nullable=True, comment='创建时间'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_role_power',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='标识'),
|
||||||
|
sa.Column('power_id', sa.Integer(), nullable=True, comment='用户编号'),
|
||||||
|
sa.Column('role_id', sa.Integer(), nullable=True, comment='角色编号'),
|
||||||
|
sa.ForeignKeyConstraint(['power_id'], ['sys_power.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['role_id'], ['sys_role.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('sys_user_role',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='标识'),
|
||||||
|
sa.Column('user_id', sa.Integer(), nullable=True, comment='用户编号'),
|
||||||
|
sa.Column('role_id', sa.Integer(), nullable=True, comment='角色编号'),
|
||||||
|
sa.ForeignKeyConstraint(['role_id'], ['sys_role.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['sys_user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.drop_table('admin_test')
|
||||||
|
op.drop_table('admin_user')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('admin_user',
|
||||||
|
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False, comment='用户ID'),
|
||||||
|
sa.Column('username', mysql.VARCHAR(collation='utf8mb4_general_ci', length=20), nullable=True, comment='用户名'),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_collate='utf8mb4_general_ci',
|
||||||
|
mysql_default_charset='utf8mb4',
|
||||||
|
mysql_engine='MyISAM'
|
||||||
|
)
|
||||||
|
op.create_table('admin_test',
|
||||||
|
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False, comment='ID'),
|
||||||
|
sa.Column('name', mysql.VARCHAR(collation='utf8mb4_general_ci', length=20), nullable=True, comment='名'),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_collate='utf8mb4_general_ci',
|
||||||
|
mysql_default_charset='utf8mb4',
|
||||||
|
mysql_engine='MyISAM'
|
||||||
|
)
|
||||||
|
op.drop_table('sys_user_role')
|
||||||
|
op.drop_table('sys_role_power')
|
||||||
|
op.drop_table('sys_user')
|
||||||
|
op.drop_table('sys_role')
|
||||||
|
op.drop_table('sys_power')
|
||||||
|
op.drop_table('sys_photo')
|
||||||
|
op.drop_table('sys_dict_type')
|
||||||
|
op.drop_table('sys_dict_data')
|
||||||
|
op.drop_table('sys_dept')
|
||||||
|
op.drop_table('sys_admin_log')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: d51040631f21
|
||||||
|
Revises: 74133ba99af7
|
||||||
|
Create Date: 2022-01-22 23:30:04.372043
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd51040631f21'
|
||||||
|
down_revision = '74133ba99af7'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('admin_test',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='ID'),
|
||||||
|
sa.Column('name', sa.String(length=20), nullable=True, comment='名'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('admin_test')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
from modules.sys.models.user_role import user_role
|
||||||
|
from modules.sys.models.role_power import role_power
|
||||||
|
from modules.sys.models.dict import DictType, DictData
|
||||||
|
from modules.sys.models.admin_log import AdminLog
|
||||||
|
from modules.sys.models.photo import Photo
|
||||||
|
from modules.sys.models.power import Power
|
||||||
|
from modules.sys.models.role import Role
|
||||||
|
from modules.sys.models.dept import Dept
|
||||||
|
|
||||||
|
from modules.sys.models.user import User
|
||||||
|
|
||||||
|
|
||||||
|
model_lists: list = [
|
||||||
|
role_power,
|
||||||
|
user_role,
|
||||||
|
Dept,
|
||||||
|
DictType, DictData,
|
||||||
|
AdminLog,
|
||||||
|
Photo,
|
||||||
|
Power,
|
||||||
|
Role,
|
||||||
|
User,
|
||||||
|
|
||||||
|
]
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Column, Integer, String, Text, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class AdminLog(BaseModel):
|
||||||
|
__tablename__ = 'sys_admin_log'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
method = Column(String(10))
|
||||||
|
uid = Column(Integer)
|
||||||
|
url = Column(String(255))
|
||||||
|
desc = Column(Text)
|
||||||
|
ip = Column(String(255))
|
||||||
|
success = Column(Integer)
|
||||||
|
user_agent = Column(Text)
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
class AdminLogSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = AdminLog
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Column, Integer, String, Text, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Dept(BaseModel):
|
||||||
|
__tablename__ = 'sys_dept'
|
||||||
|
id = Column(Integer, primary_key=True, comment="部门ID")
|
||||||
|
parent_id = Column(Integer, comment="父级编号")
|
||||||
|
dept_name = Column(String(50), comment="部门名称")
|
||||||
|
sort = Column(Integer, comment="排序")
|
||||||
|
leader = Column(String(50), comment="负责人")
|
||||||
|
phone = Column(String(20), comment="联系方式")
|
||||||
|
email = Column(String(50), comment="邮箱")
|
||||||
|
status = Column(Integer, comment='状态(1开启,0关闭)')
|
||||||
|
remark = Column(Text, comment="备注")
|
||||||
|
address = Column(String(255), comment="详细地址")
|
||||||
|
create_at = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间')
|
||||||
|
|
||||||
|
|
||||||
|
class DeptSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Dept
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Column, Integer, String, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class DictType(BaseModel):
|
||||||
|
__tablename__ = 'sys_dict_type'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
type_name = Column(String(255), comment='字典类型名称')
|
||||||
|
type_code = Column(String(255), comment='字典类型标识')
|
||||||
|
description = Column(String(255), comment='字典类型描述')
|
||||||
|
enable = Column(Integer, comment='是否开启')
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
|
||||||
|
|
||||||
|
class DictTypeSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = DictType
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
|
|
||||||
|
|
||||||
|
class DictData(BaseModel):
|
||||||
|
__tablename__ = 'sys_dict_data'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
data_label = Column(String(255), comment='字典类型名称')
|
||||||
|
data_value = Column(String(255), comment='字典类型标识')
|
||||||
|
type_code = Column(String(255), comment='字典类型描述')
|
||||||
|
is_default = Column(Integer, comment='是否默认')
|
||||||
|
enable = Column(Integer, comment='是否开启')
|
||||||
|
remark = Column(String(255), comment='备注')
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
|
||||||
|
|
||||||
|
class DictDataSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = DictData
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Integer, Column, String, CHAR, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class File(BaseModel):
|
||||||
|
__tablename__ = 'sys_file'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
name = Column(String(255), nullable=False)
|
||||||
|
href = Column(String(255))
|
||||||
|
mime = Column(CHAR(50), nullable=False)
|
||||||
|
size = Column(CHAR(30), nullable=False)
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
class AdminLogSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = False
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Integer, Column, String, CHAR, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Photo(BaseModel):
|
||||||
|
__tablename__ = 'sys_photo'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
name = Column(String(255), nullable=False)
|
||||||
|
href = Column(String(255))
|
||||||
|
mime = Column(CHAR(50), nullable=False)
|
||||||
|
size = Column(CHAR(30), nullable=False)
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
class AdminLogSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Photo
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from common.model import BaseModel, Column, Integer, String, DateTime, SQLAlchemyAutoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class Power(BaseModel):
|
||||||
|
__tablename__ = 'sys_power'
|
||||||
|
id = Column(Integer, primary_key=True, comment='权限编号')
|
||||||
|
name = Column(String(255), comment='权限名称')
|
||||||
|
type = Column(String(1), comment='权限类型')
|
||||||
|
code = Column(String(30), comment='权限标识')
|
||||||
|
url = Column(String(255), comment='权限路径')
|
||||||
|
open_type = Column(String(10), comment='打开方式')
|
||||||
|
parent_id = Column(Integer, comment='父类编号')
|
||||||
|
icon = Column(String(128), comment='图标')
|
||||||
|
sort = Column(Integer, comment='排序')
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
enable = Column(Integer, comment='是否开启')
|
||||||
|
|
||||||
|
|
||||||
|
class PowerSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Power
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import datetime
|
||||||
|
from common.model import BaseModel, Column, String, Integer, DateTime, relationship, SQLAlchemyAutoSchema, backref
|
||||||
|
|
||||||
|
|
||||||
|
class Role(BaseModel):
|
||||||
|
__tablename__ = 'sys_role'
|
||||||
|
id = Column(Integer, primary_key=True, comment='角色ID')
|
||||||
|
name = Column(String(255), comment='角色名称')
|
||||||
|
code = Column(String(255), comment='角色标识')
|
||||||
|
enable = Column(Integer, comment='是否启用')
|
||||||
|
remark = Column(String(255), comment='备注')
|
||||||
|
details = Column(String(255), comment='详情')
|
||||||
|
sort = Column(Integer, comment='排序')
|
||||||
|
create_time = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
||||||
|
power = relationship('Power', secondary="sys_role_power", backref=backref('role'))
|
||||||
|
|
||||||
|
|
||||||
|
class RoleSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Role
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from common.model import Column, Table, Integer, ForeignKey
|
||||||
|
|
||||||
|
role_power = Table(
|
||||||
|
"sys_role_power",
|
||||||
|
Column("id", Integer, primary_key=True, autoincrement=True, comment='标识'),
|
||||||
|
Column("power_id", Integer, ForeignKey("sys_power.id"), comment='用户编号'),
|
||||||
|
Column("role_id", Integer, ForeignKey("sys_role.id"), comment='角色编号'),
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import datetime
|
||||||
|
from flask_login import UserMixin
|
||||||
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
|
|
||||||
|
from common.model import BaseModel, Column, Integer, String, DateTime, relationship, SQLAlchemyAutoSchema, backref
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseModel, UserMixin):
|
||||||
|
__tablename__ = 'sys_user'
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True, comment='用户ID')
|
||||||
|
username = Column(String(20), comment='用户名')
|
||||||
|
realname = Column(String(20), comment='真实名字')
|
||||||
|
avatar = Column(String(255), comment='头像', default="/static/admin/admin/images/avatar.jpg")
|
||||||
|
remark = Column(String(255), comment='备注')
|
||||||
|
password_hash = Column(String(128), comment='哈希密码')
|
||||||
|
enable = Column(Integer, default=0, comment='启用')
|
||||||
|
dept_id = Column(Integer, comment='部门id')
|
||||||
|
create_at = Column(DateTime, default=datetime.datetime.now, comment='创建时间')
|
||||||
|
update_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间')
|
||||||
|
role = relationship('Role', secondary="sys_user_role", backref=backref('user'), lazy='dynamic')
|
||||||
|
|
||||||
|
def set_password(self, password):
|
||||||
|
self.password_hash = generate_password_hash(password)
|
||||||
|
|
||||||
|
def validate_password(self, password):
|
||||||
|
return check_password_hash(self.password_hash, password)
|
||||||
|
|
||||||
|
|
||||||
|
# 如果要全换全部字段,就不要声明fields或exclude字段即可
|
||||||
|
class UserRoleSchema(SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
include_fk = True
|
||||||
|
load_instance = True
|
||||||
|
exclude = ['password_hash']
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from common.model import Table, Column, Integer, ForeignKey
|
||||||
|
|
||||||
|
user_role = Table(
|
||||||
|
"sys_user_role",
|
||||||
|
Column("id", Integer, primary_key=True, autoincrement=True, comment='标识'),
|
||||||
|
Column("user_id", Integer, ForeignKey("sys_user.id"), comment='用户编号'),
|
||||||
|
Column("role_id", Integer, ForeignKey("sys_role.id"), comment='角色编号'),
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from common.view import Blueprint, View
|
||||||
|
|
||||||
|
|
||||||
|
user = Blueprint('sys', __name__, url_prefix='/user')
|
||||||
|
|
||||||
|
|
||||||
|
@user.route('/')
|
||||||
|
class UserView(View):
|
||||||
|
def get(self):
|
||||||
|
pass
|
||||||
|
# data, total = db.session.query(User.id, User.username).layui_paginate_json()
|
||||||
|
# print(data)
|
||||||
|
# return jsonify(data)
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
from flask import Flask, render_template
|
|
||||||
|
|
||||||
from configs import config
|
|
||||||
from pear_admin.apis import register_apis
|
|
||||||
from pear_admin.extensions import register_extensions
|
|
||||||
from pear_admin.orms import UserORM
|
|
||||||
from pear_admin.views import register_views
|
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_name="dev"):
|
|
||||||
app = Flask("pear-admin-flask")
|
|
||||||
|
|
||||||
app.config.from_object(config[config_name])
|
|
||||||
|
|
||||||
register_extensions(app)
|
|
||||||
register_apis(app)
|
|
||||||
|
|
||||||
register_views(app)
|
|
||||||
|
|
||||||
# @app.errorhandler(403)
|
|
||||||
# def handle_404(e):
|
|
||||||
# return render_template("error/403.html")
|
|
||||||
#
|
|
||||||
# @app.errorhandler(404)
|
|
||||||
# def handle_403(e):
|
|
||||||
# return render_template("error/404.html")
|
|
||||||
#
|
|
||||||
# @app.errorhandler(500)
|
|
||||||
# def handle_500(e):
|
|
||||||
# return render_template("error/500.html")
|
|
||||||
|
|
||||||
return app
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
from flask import Blueprint, Flask
|
|
||||||
|
|
||||||
from .department import department_api
|
|
||||||
from .passport import passport_api
|
|
||||||
from .rights import rights_api
|
|
||||||
from .role import role_api
|
|
||||||
from .user import user_api
|
|
||||||
|
|
||||||
|
|
||||||
def register_apis(app: Flask):
|
|
||||||
apis = Blueprint("api", __name__, url_prefix="/api/v1")
|
|
||||||
|
|
||||||
apis.register_blueprint(passport_api)
|
|
||||||
apis.register_blueprint(rights_api)
|
|
||||||
apis.register_blueprint(role_api)
|
|
||||||
apis.register_blueprint(department_api)
|
|
||||||
apis.register_blueprint(user_api)
|
|
||||||
|
|
||||||
app.register_blueprint(apis)
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
from flask import Blueprint, request
|
|
||||||
from flask_sqlalchemy.pagination import Pagination
|
|
||||||
|
|
||||||
from pear_admin.common.utils.responses import JsonResponse
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import DepartmentORM
|
|
||||||
|
|
||||||
department_api = Blueprint("department", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@department_api.get("/department")
|
|
||||||
def department_list():
|
|
||||||
page = request.args.get("page", default=1, type=int)
|
|
||||||
per_page = request.args.get("limit", default=10, type=int)
|
|
||||||
|
|
||||||
_type = request.args.get("type")
|
|
||||||
ret = []
|
|
||||||
if _type == "tree":
|
|
||||||
dept_obj: DepartmentORM = DepartmentORM.query.get(1)
|
|
||||||
for child in dept_obj.children:
|
|
||||||
child_data = child.json()
|
|
||||||
child_data["children"] = []
|
|
||||||
if child.children:
|
|
||||||
child_data["isParent"] = True
|
|
||||||
for son in child.children:
|
|
||||||
son_data = son.json()
|
|
||||||
# son_data["isParent"] = True
|
|
||||||
child_data["children"].append(son_data)
|
|
||||||
ret.append(child_data)
|
|
||||||
return JsonResponse().set_body(ret).set_msg("请求权限数据成功").ok()
|
|
||||||
q = db.select(DepartmentORM)
|
|
||||||
|
|
||||||
pages: Pagination = db.paginate(q, page=page, per_page=per_page)
|
|
||||||
return JsonResponse().set_table(pages).set_msg("获取部门数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@department_api.post("/department")
|
|
||||||
def create_department():
|
|
||||||
data = request.get_json()
|
|
||||||
if data["id"]:
|
|
||||||
del data["id"]
|
|
||||||
department = DepartmentORM(**data)
|
|
||||||
department.save()
|
|
||||||
return JsonResponse().set_msg("新增部门成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@department_api.put("/department/<int:rid>")
|
|
||||||
def change_department(rid):
|
|
||||||
data = request.get_json()
|
|
||||||
del data["id"]
|
|
||||||
|
|
||||||
department_obj = DepartmentORM.query.get(rid)
|
|
||||||
for column in DepartmentORM.__table__.columns:
|
|
||||||
if column.name in data:
|
|
||||||
setattr(department_obj, column.name, data[column.name])
|
|
||||||
department_obj.save()
|
|
||||||
return JsonResponse().set_msg("修改部门成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@department_api.delete("/department/<int:rid>")
|
|
||||||
def del_department(rid):
|
|
||||||
department_obj = DepartmentORM.query.get(rid)
|
|
||||||
department_obj.delete()
|
|
||||||
return JsonResponse().set_msg("删除删除成功").ok()
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
from collections import OrderedDict
|
|
||||||
from copy import deepcopy
|
|
||||||
|
|
||||||
from flask import Blueprint, make_response, request
|
|
||||||
from flask_jwt_extended import (
|
|
||||||
create_access_token,
|
|
||||||
create_refresh_token,
|
|
||||||
get_current_user,
|
|
||||||
jwt_required,
|
|
||||||
)
|
|
||||||
|
|
||||||
from pear_admin.common.utils.responses import JsonResponse
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import RightsORM, RoleORM, UserORM
|
|
||||||
|
|
||||||
passport_api = Blueprint("passport", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@passport_api.post("/login")
|
|
||||||
def login_in():
|
|
||||||
data = request.get_json()
|
|
||||||
|
|
||||||
user: UserORM = db.session.execute(
|
|
||||||
db.select(UserORM).where(UserORM.username == data["username"])
|
|
||||||
).scalar()
|
|
||||||
|
|
||||||
if not user:
|
|
||||||
return JsonResponse().set_msg("用户不存在").failure(), 401
|
|
||||||
if not user.check_password(data["password"]):
|
|
||||||
return JsonResponse().set_msg("用户密码错误").failure(), 401
|
|
||||||
|
|
||||||
access_token = create_access_token(user)
|
|
||||||
refresh_token = create_refresh_token(user)
|
|
||||||
|
|
||||||
response = make_response(
|
|
||||||
{
|
|
||||||
"code": 0,
|
|
||||||
"msg": "登录成功",
|
|
||||||
"access_token": access_token,
|
|
||||||
"refresh_token": refresh_token,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
@passport_api.route("/logout", methods=["GET", "POST"])
|
|
||||||
@jwt_required()
|
|
||||||
def logout():
|
|
||||||
return JsonResponse().set_msg("退出登录成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@passport_api.get("/menu")
|
|
||||||
@jwt_required()
|
|
||||||
def menus_api():
|
|
||||||
rights_orm_list = set()
|
|
||||||
current_user: UserORM = get_current_user()
|
|
||||||
for role in current_user.role_list:
|
|
||||||
for rights_orm in role.rights_list:
|
|
||||||
if rights_orm.type != "auth":
|
|
||||||
rights_orm_list.add(rights_orm)
|
|
||||||
|
|
||||||
rights_list = [rights_orm.menu_json() for rights_orm in rights_orm_list]
|
|
||||||
rights_list.sort(key=lambda x: (x["pid"], x["id"]), reverse=True)
|
|
||||||
|
|
||||||
menu_dict_list = OrderedDict()
|
|
||||||
for menu_dict in rights_list:
|
|
||||||
if menu_dict["id"] in menu_dict_list.keys(): # 如果当前节点已经存在与字典中
|
|
||||||
# 当前节点添加子节点
|
|
||||||
menu_dict["children"] = deepcopy(menu_dict_list[menu_dict["id"]])
|
|
||||||
menu_dict["children"].sort(key=lambda item: item["sort"])
|
|
||||||
# 删除子节点
|
|
||||||
del menu_dict_list[menu_dict["id"]]
|
|
||||||
|
|
||||||
if menu_dict["pid"] not in menu_dict_list:
|
|
||||||
menu_dict_list[menu_dict["pid"]] = [menu_dict]
|
|
||||||
else:
|
|
||||||
menu_dict_list[menu_dict["pid"]].append(menu_dict)
|
|
||||||
|
|
||||||
return sorted(menu_dict_list.get(0), key=lambda item: item["sort"])
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
from copy import deepcopy
|
|
||||||
|
|
||||||
from flask import Blueprint, request
|
|
||||||
from flask_jwt_extended import jwt_required
|
|
||||||
|
|
||||||
from pear_admin.common.utils.responses import JsonResponse
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import RightsORM
|
|
||||||
|
|
||||||
rights_api = Blueprint("rights", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@rights_api.get("/rights")
|
|
||||||
@jwt_required()
|
|
||||||
def rights_list():
|
|
||||||
t = request.args.get("type", default="")
|
|
||||||
if t == "tree": # tree 组件数据,用于权限赋值
|
|
||||||
# 1. 获取所有的权限
|
|
||||||
rights_all = db.session.execute(db.select(RightsORM)).scalars()
|
|
||||||
rights_list = [
|
|
||||||
{"id": r.id, "pid": r.pid, "title": r.name, "sort": r.sort}
|
|
||||||
for r in rights_all
|
|
||||||
]
|
|
||||||
# 2. 获取已有权限 id 集合
|
|
||||||
# 3. 列表转属性组件
|
|
||||||
rights_list.sort(key=lambda item: (item["pid"], item["id"]), reverse=True)
|
|
||||||
tree_dict = {}
|
|
||||||
for rights_dict in rights_list: # 遍历子节点
|
|
||||||
# 2. 如果当前阶段已经存在于树状表格字典,则是父节点
|
|
||||||
if rights_dict["id"] in tree_dict.keys():
|
|
||||||
# 将之前的节点添加到父节点之下
|
|
||||||
rights_dict["children"] = deepcopy(tree_dict[rights_dict["id"]])
|
|
||||||
rights_dict["children"].sort(key=lambda item: item["sort"])
|
|
||||||
del tree_dict[rights_dict["id"]]
|
|
||||||
|
|
||||||
# 1. 如果父节点未出现在树状字典里面,就新增子节点列表,否则就追加
|
|
||||||
if rights_dict["pid"] not in tree_dict.keys():
|
|
||||||
tree_dict[rights_dict["pid"]] = [rights_dict]
|
|
||||||
else:
|
|
||||||
tree_dict[rights_dict["pid"]].append(rights_dict)
|
|
||||||
|
|
||||||
return JsonResponse().set_body(tree_dict.get(0)).ok()
|
|
||||||
|
|
||||||
if t == "treetable": # tree table 数据
|
|
||||||
page = request.args.get("page", type=int, default=1)
|
|
||||||
per_page = request.args.get("per_page", type=int, default=10)
|
|
||||||
|
|
||||||
q = db.select(RightsORM).where(RightsORM.type == "menu")
|
|
||||||
pages = db.paginate(q, page=page, per_page=per_page, error_out=False)
|
|
||||||
|
|
||||||
ret = []
|
|
||||||
|
|
||||||
# 构建树状表格的数据
|
|
||||||
for page in pages.items:
|
|
||||||
data = page.json()
|
|
||||||
data["children"] = []
|
|
||||||
for child in page.children:
|
|
||||||
child_data = child.json()
|
|
||||||
if child.children:
|
|
||||||
child_data["children"] = [
|
|
||||||
sub_child.json() for sub_child in child.children
|
|
||||||
]
|
|
||||||
child_data["isParent"] = True
|
|
||||||
|
|
||||||
data["children"].append(child_data)
|
|
||||||
data["isParent"] = True
|
|
||||||
ret.append(data)
|
|
||||||
return JsonResponse().set_msg("请求权限数据成功").set_body(ret).ok()
|
|
||||||
return JsonResponse().set_msg("请求权限数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@rights_api.post("/rights")
|
|
||||||
@jwt_required()
|
|
||||||
def create_rights():
|
|
||||||
data = request.get_json()
|
|
||||||
if not data["pid"]:
|
|
||||||
data["pid"] = 0
|
|
||||||
if not data["sort"]:
|
|
||||||
data["sort"] = int(data["sort"])
|
|
||||||
rights_obj = RightsORM(**data)
|
|
||||||
rights_obj.save()
|
|
||||||
return JsonResponse().set_msg("新增权限数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@rights_api.put("/rights/<int:rid>")
|
|
||||||
@jwt_required()
|
|
||||||
def change_rights(rid):
|
|
||||||
data = request.get_json()
|
|
||||||
del data["id"]
|
|
||||||
|
|
||||||
rights_obj = RightsORM.query.get(rid)
|
|
||||||
for key, value in data.items():
|
|
||||||
setattr(rights_obj, key, value)
|
|
||||||
rights_obj.save()
|
|
||||||
return JsonResponse().set_msg("修改权限数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@rights_api.delete("/rights/<int:rid>")
|
|
||||||
@jwt_required()
|
|
||||||
def delete_rights(rid):
|
|
||||||
rights_obj = RightsORM.query.get(rid)
|
|
||||||
rights_obj.delete()
|
|
||||||
return JsonResponse().set_msg("删除权限数据成功").ok()
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
from flask import Blueprint, request
|
|
||||||
from flask_sqlalchemy.pagination import Pagination
|
|
||||||
|
|
||||||
from pear_admin.common.utils.responses import JsonResponse
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import RightsORM, RoleORM
|
|
||||||
|
|
||||||
role_api = Blueprint("role", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.get("/role")
|
|
||||||
def role_list():
|
|
||||||
page = request.args.get("page", default=1, type=int)
|
|
||||||
per_page = request.args.get("limit", default=10, type=int)
|
|
||||||
q = db.select(RoleORM)
|
|
||||||
|
|
||||||
pages: Pagination = db.paginate(q, page=page, per_page=per_page)
|
|
||||||
return JsonResponse().set_table(pages).set_msg("获取角色数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.post("/role")
|
|
||||||
def create_role():
|
|
||||||
data = request.get_json()
|
|
||||||
if data["id"]:
|
|
||||||
del data["id"]
|
|
||||||
role = RoleORM(**data)
|
|
||||||
role.save()
|
|
||||||
return JsonResponse().set_msg("新增角色成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.put("/role/<int:rid>")
|
|
||||||
def change_role(rid):
|
|
||||||
data = request.get_json()
|
|
||||||
del data["id"]
|
|
||||||
|
|
||||||
role_obj = RoleORM.query.get(rid)
|
|
||||||
for key, value in data.items():
|
|
||||||
setattr(role_obj, key, value)
|
|
||||||
role_obj.save()
|
|
||||||
return JsonResponse().set_msg("修改角色权限成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.delete("/role/<int:rid>")
|
|
||||||
def del_role(rid):
|
|
||||||
role_obj = RoleORM.query.get(rid)
|
|
||||||
role_obj.delete()
|
|
||||||
return JsonResponse().set_msg("删除角色成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.get("/role/role_rights/<int:rid>")
|
|
||||||
def role_rights(rid):
|
|
||||||
role: RoleORM = db.session.execute(
|
|
||||||
db.select(RoleORM).where(RoleORM.id == rid)
|
|
||||||
).scalar()
|
|
||||||
own_rights_list = [r.id for r in role.rights_list]
|
|
||||||
|
|
||||||
return JsonResponse().set_body(own_rights_list).set_msg("删除角色成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@role_api.put("/role/role_rights/<int:rid>")
|
|
||||||
def change_role_rights(rid):
|
|
||||||
rights_ids = request.json.get("rights_ids", "")
|
|
||||||
|
|
||||||
rights_list = rights_ids.split(",")
|
|
||||||
role: RoleORM = db.session.execute(
|
|
||||||
db.select(RoleORM).where(RoleORM.id == rid)
|
|
||||||
).scalar()
|
|
||||||
rights_obj_list = db.session.execute(
|
|
||||||
db.select(RightsORM).where(RightsORM.id.in_(rights_list))
|
|
||||||
).all()
|
|
||||||
role.rights_list = [r[0] for r in rights_obj_list]
|
|
||||||
role.save()
|
|
||||||
return JsonResponse().set_msg("授权成功").ok()
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from flask import Blueprint, request
|
|
||||||
from flask_jwt_extended import current_user, jwt_required
|
|
||||||
from flask_sqlalchemy.pagination import Pagination
|
|
||||||
|
|
||||||
from pear_admin.common.utils.responses import JsonResponse
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import RoleORM, UserORM
|
|
||||||
|
|
||||||
user_api = Blueprint("user", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.get("/user")
|
|
||||||
def user_list():
|
|
||||||
page = request.args.get("page", default=1, type=int)
|
|
||||||
per_page = request.args.get("limit", default=10, type=int)
|
|
||||||
q = db.select(UserORM)
|
|
||||||
|
|
||||||
pages: Pagination = db.paginate(q, page=page, per_page=per_page)
|
|
||||||
|
|
||||||
return JsonResponse().set_table(pages).set_msg("获取用户数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.post("/user")
|
|
||||||
def create_user():
|
|
||||||
data = request.get_json()
|
|
||||||
if data["id"]:
|
|
||||||
del data["id"]
|
|
||||||
role = UserORM(**data)
|
|
||||||
create_at = data["create_at"]
|
|
||||||
if create_at:
|
|
||||||
role.create_at = datetime.strptime(create_at, "%Y-%m-%d %H:%M:%S")
|
|
||||||
role.password = "123456"
|
|
||||||
role.save()
|
|
||||||
return JsonResponse().set_msg("新增用户成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.put("/user/<int:uid>")
|
|
||||||
def change_user(uid):
|
|
||||||
data = request.get_json()
|
|
||||||
del data["id"]
|
|
||||||
|
|
||||||
user_obj = UserORM.query.get(uid)
|
|
||||||
for key, value in data.items():
|
|
||||||
if key == "create_at":
|
|
||||||
value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
|
||||||
setattr(user_obj, key, value)
|
|
||||||
user_obj.save()
|
|
||||||
return JsonResponse().set_msg("修改用户信息成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.delete("/user/<int:rid>")
|
|
||||||
def del_user(rid):
|
|
||||||
user_obj = UserORM.query.get(rid)
|
|
||||||
user_obj.delete()
|
|
||||||
return JsonResponse().set_msg("删除用户成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.get("/user/user_role/<int:uid>")
|
|
||||||
def get_user_role(uid):
|
|
||||||
user: UserORM = db.session.execute(
|
|
||||||
db.select(UserORM).where(UserORM.id == uid)
|
|
||||||
).scalar()
|
|
||||||
|
|
||||||
wn_role_list = [r.id for r in user.role_list]
|
|
||||||
return JsonResponse().set_body(wn_role_list).set_msg("返回角色权限数据成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.put("/user/user_role/<int:rid>")
|
|
||||||
def change_user_role(rid):
|
|
||||||
role_ids = request.json.get("rights_ids", "")
|
|
||||||
role_list = role_ids.split(",")
|
|
||||||
|
|
||||||
user: UserORM = db.session.execute(
|
|
||||||
db.select(UserORM).where(UserORM.id == rid)
|
|
||||||
).scalar()
|
|
||||||
role_obj_list = db.session.execute(
|
|
||||||
db.select(RoleORM).where(RoleORM.id.in_(role_list))
|
|
||||||
).all()
|
|
||||||
user.role_list = [r[0] for r in role_obj_list]
|
|
||||||
user.save()
|
|
||||||
return JsonResponse().set_msg("授权成功").ok()
|
|
||||||
|
|
||||||
|
|
||||||
@user_api.get("/user/profile")
|
|
||||||
@jwt_required()
|
|
||||||
def user_profile():
|
|
||||||
return JsonResponse().set_body(current_user.json()).set_msg("获取个人数据成功").ok()
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class ResponseCodeEnum(Enum):
|
|
||||||
"""状态码枚举类"""
|
|
||||||
|
|
||||||
ok = (0, "成功")
|
|
||||||
|
|
||||||
error = (400000, "请求错误")
|
|
||||||
failure = (400000, "请求失败")
|
|
||||||
image_code_err = (400001, "图形验证码错误")
|
|
||||||
throttling_err = (400002, "访问过于频繁")
|
|
||||||
necessary_param_err = (400003, "缺少必传参数")
|
|
||||||
USER_ERR = (400004, "用户名错误")
|
|
||||||
PWD_ERR = (400005, "密码错误")
|
|
||||||
CPWD_ERR = (400006, "密码不一致")
|
|
||||||
MOBILE_ERR = (400007, "手机号错误")
|
|
||||||
SMS_CODE_ERR = (400008, "短信验证码有误")
|
|
||||||
ALLOW_ERR = (400009, "未勾选协议")
|
|
||||||
SESSION_ERR = (401000, "用户未登录")
|
|
||||||
|
|
||||||
forbid = (403000, "权限禁止")
|
|
||||||
jwt_expired = (403001, "Token 已过期,请重新登录")
|
|
||||||
unauthorized = (403003, "Token 已失效,请重新登录")
|
|
||||||
not_found = (404000, "数据未找到")
|
|
||||||
|
|
||||||
SERVER_ERR = (500000, "服务器异常")
|
|
||||||
DB_ERR = (500000, "数据错误")
|
|
||||||
EMAIL_ERR = (500001, "邮箱错误")
|
|
||||||
TEL_ERR = (500002, "固定电话错误")
|
|
||||||
NODATA_ERR = (500003, "无数据")
|
|
||||||
NEW_PWD_ERR = (500004, "新密码错误")
|
|
||||||
OPENID_ERR = (500005, "无效的 openid")
|
|
||||||
PARAM_ERR = (500006, "参数错误")
|
|
||||||
STOCK_ERR = (500007, "库存不足")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def code(self):
|
|
||||||
"""获取状态码"""
|
|
||||||
return self.value[0]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def msg(self):
|
|
||||||
"""获取状态码信息"""
|
|
||||||
return self.value[1]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def status_code(self):
|
|
||||||
return self.value[0] // 1000
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
from pear_admin.common.utils.response_code import ResponseCodeEnum
|
|
||||||
|
|
||||||
|
|
||||||
class JsonResponse:
|
|
||||||
"""
|
|
||||||
JsonResponse 响应体,统一返回前端的格式
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._data = None
|
|
||||||
self._code = None
|
|
||||||
self._msg = None
|
|
||||||
self._status_code = None
|
|
||||||
self._error_code = 0
|
|
||||||
self._table_data = {}
|
|
||||||
|
|
||||||
def set_body(self, body):
|
|
||||||
self._data = body
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_msg(self, msg):
|
|
||||||
self._msg = msg
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_status_code(self, status_code):
|
|
||||||
# 设置响应状态码
|
|
||||||
self._status_code = status_code
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_error_code(self, error_code):
|
|
||||||
# 单独设置响应错误码
|
|
||||||
self._error_code = error_code
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_response_code_enum(self, code):
|
|
||||||
# 设置响应状态码
|
|
||||||
self._set_code(code)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_table(self, pages):
|
|
||||||
self.set_body([item.json() for item in pages.items])
|
|
||||||
self._table_data.update(
|
|
||||||
{
|
|
||||||
"count": pages.total,
|
|
||||||
"page": pages.page,
|
|
||||||
"per_page": pages.per_page,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def set_table_info(self, pages):
|
|
||||||
self._table_data.update(
|
|
||||||
{
|
|
||||||
"count": pages.total,
|
|
||||||
"page": pages.page,
|
|
||||||
"per_page": pages.per_page,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def ok(self):
|
|
||||||
self._set_code(ResponseCodeEnum.ok)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def not_found(self):
|
|
||||||
self._set_code(ResponseCodeEnum.not_found)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def forbid(self):
|
|
||||||
self._set_code(ResponseCodeEnum.forbid)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def error(self):
|
|
||||||
self._set_code(ResponseCodeEnum.error)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def failure(self):
|
|
||||||
self._set_code(ResponseCodeEnum.failure)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def jwt_expired(self):
|
|
||||||
self._set_code(ResponseCodeEnum.jwt_expired)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
def _set_code(self, code):
|
|
||||||
# 在内部设置状态码
|
|
||||||
if not self._msg:
|
|
||||||
self._msg = code.msg
|
|
||||||
if not self._status_code:
|
|
||||||
self._status_code = code.status_code
|
|
||||||
self._error_code = code.code
|
|
||||||
return self
|
|
||||||
|
|
||||||
def _res_result(self):
|
|
||||||
data = {"code": self._error_code, "msg": self._msg, "data": self._data}
|
|
||||||
data.update(self._table_data)
|
|
||||||
return data
|
|
||||||
|
|
||||||
def set_code(self, code):
|
|
||||||
self._set_code(code)
|
|
||||||
return self._res_result()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print(JsonResponse().set_msg("请求过于频繁").ok())
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
|
|
||||||
from .init_db import db, migrate
|
|
||||||
from .init_jwt import jwt
|
|
||||||
from .init_script import register_script
|
|
||||||
|
|
||||||
|
|
||||||
def register_extensions(app: Flask):
|
|
||||||
db.init_app(app)
|
|
||||||
migrate.init_app(app, db)
|
|
||||||
jwt.init_app(app)
|
|
||||||
|
|
||||||
register_script(app)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from flask_migrate import Migrate
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
|
|
||||||
db = SQLAlchemy()
|
|
||||||
migrate = Migrate()
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
from flask import redirect
|
|
||||||
from flask_jwt_extended import JWTManager
|
|
||||||
|
|
||||||
from pear_admin.orms.user import UserORM
|
|
||||||
|
|
||||||
jwt = JWTManager()
|
|
||||||
|
|
||||||
|
|
||||||
@jwt.user_identity_loader
|
|
||||||
def user_identity_lookup(user):
|
|
||||||
return user.id
|
|
||||||
|
|
||||||
|
|
||||||
@jwt.user_lookup_loader
|
|
||||||
def user_lookup_callback(_jwt_header, jwt_data):
|
|
||||||
identity = jwt_data["sub"]
|
|
||||||
return UserORM.query.filter(UserORM.id == identity).one_or_none()
|
|
||||||
|
|
||||||
|
|
||||||
@jwt.expired_token_loader
|
|
||||||
def expired_token_callback():
|
|
||||||
return {"msg": "token 已过期,请重新登录", "code": -1}, 403
|
|
||||||
|
|
||||||
|
|
||||||
@jwt.unauthorized_loader
|
|
||||||
def missing_token_callback(error):
|
|
||||||
return {"msg": "操作未授权,请重新登录", "code": -1}, 403
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import csv
|
|
||||||
import os
|
|
||||||
|
|
||||||
from flask import Flask, current_app
|
|
||||||
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
from pear_admin.orms import DepartmentORM, RightsORM, RoleORM, UserORM
|
|
||||||
|
|
||||||
|
|
||||||
def dict_to_orm(d, o):
|
|
||||||
for k, v in d.items():
|
|
||||||
if k == "password":
|
|
||||||
o.password = v
|
|
||||||
else:
|
|
||||||
setattr(o, k, v or None)
|
|
||||||
|
|
||||||
|
|
||||||
def csv_to_databases(path, orm):
|
|
||||||
with open(path, encoding="utf-8") as file:
|
|
||||||
for d in csv.DictReader(file):
|
|
||||||
o = orm()
|
|
||||||
dict_to_orm(d, o)
|
|
||||||
db.session.add(o)
|
|
||||||
db.session.flush()
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def register_script(app: Flask):
|
|
||||||
@app.cli.command()
|
|
||||||
def init():
|
|
||||||
db.drop_all()
|
|
||||||
db.create_all()
|
|
||||||
|
|
||||||
root = current_app.config.get("ROOT_PATH")
|
|
||||||
|
|
||||||
rights_data_path = os.path.join(root, "static", "data", "ums_rights.csv")
|
|
||||||
csv_to_databases(rights_data_path, RightsORM)
|
|
||||||
|
|
||||||
role_data_path = os.path.join(root, "static", "data", "ums_role.csv")
|
|
||||||
csv_to_databases(role_data_path, RoleORM)
|
|
||||||
|
|
||||||
with open(role_data_path, encoding="utf-8") as file:
|
|
||||||
for d in csv.DictReader(file):
|
|
||||||
role: RoleORM = RoleORM.query.get(d["id"])
|
|
||||||
id_list = [int(_id) for _id in d["rights_ids"].split(":")]
|
|
||||||
role.rights_list = RightsORM.query.filter(
|
|
||||||
RightsORM.id.in_(id_list)
|
|
||||||
).all()
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
department_data_path = os.path.join(
|
|
||||||
root, "static", "data", "ums_department.csv"
|
|
||||||
)
|
|
||||||
csv_to_databases(department_data_path, DepartmentORM)
|
|
||||||
|
|
||||||
user_data_path = os.path.join(root, "static", "data", "ums_user.csv")
|
|
||||||
csv_to_databases(user_data_path, UserORM)
|
|
||||||
|
|
||||||
with open(user_data_path, encoding="utf-8") as file:
|
|
||||||
for d in csv.DictReader(file):
|
|
||||||
user: UserORM = UserORM.query.get(d["id"])
|
|
||||||
id_list = [int(_id) for _id in d["role_ids"].split(":")]
|
|
||||||
user.role_list = RoleORM.query.filter(RoleORM.id.in_(id_list)).all()
|
|
||||||
db.session.commit()
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
from .department import DepartmentORM
|
|
||||||
from .rights import RightsORM
|
|
||||||
from .role import RoleORM
|
|
||||||
from .user import UserORM
|
|
||||||
|
|
||||||
user_role = db.Table(
|
|
||||||
"ums_user_role", # 用户 - 角色中间表名称
|
|
||||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment="标识"),
|
|
||||||
db.Column("user_id", db.Integer, db.ForeignKey("ums_user.id"), comment="用户编号"),
|
|
||||||
db.Column("role_id", db.Integer, db.ForeignKey("ums_role.id"), comment="角色编号"),
|
|
||||||
)
|
|
||||||
|
|
||||||
role_rights = db.Table(
|
|
||||||
"ums_role_rights", # 用户 - 权限中间表名称
|
|
||||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment="标识"),
|
|
||||||
db.Column("rights_id", db.Integer, db.ForeignKey("ums_rights.id"), comment="用户编号"),
|
|
||||||
db.Column("role_id", db.Integer, db.ForeignKey("ums_role.id"), comment="角色编号"),
|
|
||||||
)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
|
|
||||||
class BaseORM(db.Model):
|
|
||||||
__abstract__ = True
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
db.session.add(self)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
db.session.delete(self)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
def json(self):
|
|
||||||
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
from ._base import BaseORM
|
|
||||||
|
|
||||||
|
|
||||||
class DepartmentORM(BaseORM):
|
|
||||||
__tablename__ = "ums_department"
|
|
||||||
id = db.Column(db.Integer, primary_key=True, comment="部门 ID")
|
|
||||||
name = db.Column(db.String(50), comment="部门名称")
|
|
||||||
leader = db.Column(db.String(50), comment="负责人")
|
|
||||||
enable = db.Column(db.Boolean, comment="状态 (1 开启,0 关闭)", default=True)
|
|
||||||
|
|
||||||
users = db.relationship("UserORM", backref="department")
|
|
||||||
|
|
||||||
pid = db.Column(db.Integer, db.ForeignKey("ums_department.id"), default=1)
|
|
||||||
parent = db.relationship(
|
|
||||||
"DepartmentORM", back_populates="children", remote_side=[id]
|
|
||||||
) # 自关联
|
|
||||||
children = db.relationship("DepartmentORM", back_populates="parent")
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
from sqlalchemy.orm import backref
|
|
||||||
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
from ._base import BaseORM
|
|
||||||
|
|
||||||
|
|
||||||
class RightsORM(BaseORM):
|
|
||||||
__tablename__ = "ums_rights"
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(20), nullable=False, comment="权限名称")
|
|
||||||
code = db.Column(db.String(30), comment="权限标识")
|
|
||||||
type = db.Column(db.String(30), comment="权限类型")
|
|
||||||
url = db.Column(db.String(30), comment="路径地址")
|
|
||||||
|
|
||||||
icon_sign = db.Column(db.String(128), comment="图标")
|
|
||||||
status = db.Column(db.Boolean, default=True, comment="是否开启")
|
|
||||||
sort = db.Column(db.Integer, default=0)
|
|
||||||
open_type = db.Column(db.String(128), comment="打开方式")
|
|
||||||
pid = db.Column(
|
|
||||||
db.Integer,
|
|
||||||
db.ForeignKey("ums_rights.id"),
|
|
||||||
default=0,
|
|
||||||
comment="父类编号",
|
|
||||||
)
|
|
||||||
|
|
||||||
parent = db.relationship(
|
|
||||||
"RightsORM", back_populates="children", remote_side=[id]
|
|
||||||
) # 自关联
|
|
||||||
children = db.relationship("RightsORM", back_populates="parent")
|
|
||||||
|
|
||||||
def menu_json(self):
|
|
||||||
type_map_dict = {"menu": 0, "path": 1}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"id": self.id,
|
|
||||||
"pid": self.pid,
|
|
||||||
"title": self.name,
|
|
||||||
"type": type_map_dict[self.type],
|
|
||||||
"href": self.url,
|
|
||||||
"icon": self.icon_sign,
|
|
||||||
"sort": self.sort,
|
|
||||||
"openType": self.open_type,
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
from ._base import BaseORM
|
|
||||||
|
|
||||||
|
|
||||||
class RoleORM(BaseORM):
|
|
||||||
__tablename__ = "ums_role"
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(20), nullable=False, comment="角色名称")
|
|
||||||
code = db.Column(db.String(20), nullable=False, comment="角色标识符")
|
|
||||||
desc = db.Column(db.Text)
|
|
||||||
|
|
||||||
rights_ids = db.Column(
|
|
||||||
db.String(512),
|
|
||||||
comment="权限 ids,1,2,5。冗余字段,用户缓存用户权限",
|
|
||||||
)
|
|
||||||
|
|
||||||
rights_list = db.relationship(
|
|
||||||
"RightsORM", secondary="ums_role_rights", backref=db.backref("role")
|
|
||||||
)
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from werkzeug.security import check_password_hash, generate_password_hash
|
|
||||||
|
|
||||||
from pear_admin.extensions import db
|
|
||||||
|
|
||||||
from ._base import BaseORM
|
|
||||||
|
|
||||||
|
|
||||||
class UserORM(BaseORM):
|
|
||||||
__tablename__ = "ums_user"
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True, comment="自增 id")
|
|
||||||
nickname = db.Column(db.String(128), nullable=False, comment="昵称")
|
|
||||||
username = db.Column(db.String(128), nullable=False, comment="登录名")
|
|
||||||
password_hash = db.Column(db.String(102), nullable=False, comment="登录密码")
|
|
||||||
mobile = db.Column(db.String(32), nullable=False, comment="手机")
|
|
||||||
email = db.Column(db.String(64), nullable=False, comment="邮箱")
|
|
||||||
avatar = db.Column(db.Text, comment="头像地址")
|
|
||||||
create_at = db.Column(
|
|
||||||
db.DateTime,
|
|
||||||
nullable=False,
|
|
||||||
comment="创建时间",
|
|
||||||
default=datetime.now,
|
|
||||||
)
|
|
||||||
department_id = db.Column(
|
|
||||||
db.Integer, db.ForeignKey("ums_department.id"), default=1, comment="部门 id"
|
|
||||||
)
|
|
||||||
|
|
||||||
role_list = db.relationship(
|
|
||||||
"RoleORM",
|
|
||||||
secondary="ums_user_role",
|
|
||||||
backref=db.backref("user"),
|
|
||||||
lazy="dynamic",
|
|
||||||
)
|
|
||||||
|
|
||||||
def json(self):
|
|
||||||
create_at = (self.create_at.strftime("%Y-%m-%d %H:%M:%S"),)
|
|
||||||
data = super().json()
|
|
||||||
data["create_at"] = create_at
|
|
||||||
return data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def password(self):
|
|
||||||
return self.password_hash
|
|
||||||
|
|
||||||
@password.setter
|
|
||||||
def password(self, password):
|
|
||||||
self.password_hash = generate_password_hash(password)
|
|
||||||
|
|
||||||
def check_password(self, password):
|
|
||||||
return check_password_hash(self.password_hash, password=password)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
|
|
||||||
from .index import index_bp
|
|
||||||
from .system import system_bp
|
|
||||||
|
|
||||||
|
|
||||||
def register_views(app: Flask):
|
|
||||||
app.register_blueprint(index_bp)
|
|
||||||
app.register_blueprint(system_bp)
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, send_file, send_from_directory
|
|
||||||
|
|
||||||
index_bp = Blueprint("index", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/")
|
|
||||||
def index():
|
|
||||||
return render_template("view/index.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/view/login.html")
|
|
||||||
def login():
|
|
||||||
return render_template("view/login.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/view/register.html")
|
|
||||||
def register():
|
|
||||||
return render_template("view/register.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/view/console/index.html")
|
|
||||||
def console1():
|
|
||||||
return render_template("view/console/index.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/view/analysis/index.html")
|
|
||||||
def analysis():
|
|
||||||
return render_template("view/analysis/index.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/view/system/person.html")
|
|
||||||
def person():
|
|
||||||
return render_template("view/system/person.html")
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route("/favicon.ico")
|
|
||||||
def fav_icon():
|
|
||||||
return send_from_directory(directory="static", path="favicon.ico")
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
from flask import Blueprint, render_template
|
|
||||||
|
|
||||||
system_bp = Blueprint("system", __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@system_bp.get("/system/<path1>/<path2>")
|
|
||||||
def system_view(path1, path2):
|
|
||||||
return render_template(f"system/{path1}/{path2}")
|
|
||||||
|
|
||||||
|
|
||||||
@system_bp.get("/views/role.html")
|
|
||||||
def role_view():
|
|
||||||
return render_template("system/role/index.html")
|
|
||||||
|
|
||||||
|
|
||||||
@system_bp.get("/views/department.html")
|
|
||||||
def department_view():
|
|
||||||
return render_template("system/department/index.html")
|
|
||||||
|
|
||||||
|
|
||||||
@system_bp.get("/views/user.html")
|
|
||||||
def user_view():
|
|
||||||
return render_template("system/user/index.html")
|
|
||||||
@@ -1,935 +0,0 @@
|
|||||||
# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand.
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "alembic"
|
|
||||||
version = "1.12.1"
|
|
||||||
description = "A database migration tool for SQLAlchemy."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "alembic-1.12.1-py3-none-any.whl", hash = "sha256:47d52e3dfb03666ed945becb723d6482e52190917fdb47071440cfdba05d92cb"},
|
|
||||||
{file = "alembic-1.12.1.tar.gz", hash = "sha256:bca5877e9678b454706347bc10b97cb7d67f300320fa5c3a94423e8266e2823f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Mako = "*"
|
|
||||||
SQLAlchemy = ">=1.3.0"
|
|
||||||
typing-extensions = ">=4"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
tz = ["python-dateutil"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "argcomplete"
|
|
||||||
version = "3.1.2"
|
|
||||||
description = "Bash tab completion for argparse"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"},
|
|
||||||
{file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
test = ["coverage", "mypy", "pexpect", "ruff", "wheel"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blinker"
|
|
||||||
version = "1.6.3"
|
|
||||||
description = "Fast, simple object-to-object and broadcast signaling"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "blinker-1.6.3-py3-none-any.whl", hash = "sha256:296320d6c28b006eb5e32d4712202dbcdcbf5dc482da298c2f44881c43884aaa"},
|
|
||||||
{file = "blinker-1.6.3.tar.gz", hash = "sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfgv"
|
|
||||||
version = "3.4.0"
|
|
||||||
description = "Validate configuration and produce human readable error messages."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
|
||||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "charset-normalizer"
|
|
||||||
version = "3.3.1"
|
|
||||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7.0"
|
|
||||||
files = [
|
|
||||||
{file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"},
|
|
||||||
{file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"},
|
|
||||||
{file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "click"
|
|
||||||
version = "8.1.7"
|
|
||||||
description = "Composable command line interface toolkit"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
|
||||||
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colorama"
|
|
||||||
version = "0.4.6"
|
|
||||||
description = "Cross-platform colored terminal text."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
|
||||||
files = [
|
|
||||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "commitizen"
|
|
||||||
version = "3.12.0"
|
|
||||||
description = "Python commitizen client tool"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "commitizen-3.12.0-py3-none-any.whl", hash = "sha256:082f4733409bc4f01f987467295f8393ceb16b42cc648cf2f5a7a754c6d594db"},
|
|
||||||
{file = "commitizen-3.12.0.tar.gz", hash = "sha256:7c313f1f85f45c9acf1a70f1637deab5c388150ae8660a0037ac260e77bb1492"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
argcomplete = ">=1.12.1,<3.2"
|
|
||||||
charset-normalizer = ">=2.1.0,<4"
|
|
||||||
colorama = ">=0.4.1,<0.5.0"
|
|
||||||
decli = ">=0.6.0,<0.7.0"
|
|
||||||
importlib_metadata = ">=4.13,<7"
|
|
||||||
jinja2 = ">=2.10.3"
|
|
||||||
packaging = ">=19"
|
|
||||||
pyyaml = ">=3.08"
|
|
||||||
questionary = ">=2.0,<3.0"
|
|
||||||
termcolor = ">=1.1,<3"
|
|
||||||
tomlkit = ">=0.5.3,<1.0.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "decli"
|
|
||||||
version = "0.6.1"
|
|
||||||
description = "Minimal, easy-to-use, declarative cli tool"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "decli-0.6.1-py3-none-any.whl", hash = "sha256:7815ac58617764e1a200d7cadac6315fcaacc24d727d182f9878dd6378ccf869"},
|
|
||||||
{file = "decli-0.6.1.tar.gz", hash = "sha256:ed88ccb947701e8e5509b7945fda56e150e2ac74a69f25d47ac85ef30ab0c0f0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "distlib"
|
|
||||||
version = "0.3.7"
|
|
||||||
description = "Distribution utilities"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
|
|
||||||
{file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "filelock"
|
|
||||||
version = "3.13.1"
|
|
||||||
description = "A platform independent file lock."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
|
|
||||||
{file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
|
|
||||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
|
|
||||||
typing = ["typing-extensions (>=4.8)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flask"
|
|
||||||
version = "3.0.0"
|
|
||||||
description = "A simple framework for building complex web applications."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"},
|
|
||||||
{file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
blinker = ">=1.6.2"
|
|
||||||
click = ">=8.1.3"
|
|
||||||
itsdangerous = ">=2.1.2"
|
|
||||||
Jinja2 = ">=3.1.2"
|
|
||||||
Werkzeug = ">=3.0.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
async = ["asgiref (>=3.2)"]
|
|
||||||
dotenv = ["python-dotenv"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flask-jwt-extended"
|
|
||||||
version = "4.5.3"
|
|
||||||
description = "Extended JWT integration with Flask"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7,<4"
|
|
||||||
files = [
|
|
||||||
{file = "Flask-JWT-Extended-4.5.3.tar.gz", hash = "sha256:061ef3d25ed5743babe4964ab38f36d870e6d2fd8a126bab5d77ddef8a01932b"},
|
|
||||||
{file = "Flask_JWT_Extended-4.5.3-py2.py3-none-any.whl", hash = "sha256:eaec42af107dcb919785a4b3766c09ffba9f286b92a8d58603933f28fd4db6a3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
Flask = ">=2.0,<4.0"
|
|
||||||
PyJWT = ">=2.0,<3.0"
|
|
||||||
Werkzeug = ">=0.14"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
asymmetric-crypto = ["cryptography (>=3.3.1)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flask-migrate"
|
|
||||||
version = "4.0.5"
|
|
||||||
description = "SQLAlchemy database migrations for Flask applications using Alembic."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "Flask-Migrate-4.0.5.tar.gz", hash = "sha256:d3f437a8b5f3849d1bb1b60e1b818efc564c66e3fefe90b62e5db08db295e1b1"},
|
|
||||||
{file = "Flask_Migrate-4.0.5-py3-none-any.whl", hash = "sha256:613a2df703998e78716cace68cd83972960834424457f5b67f56e74fff950aef"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
alembic = ">=1.9.0"
|
|
||||||
Flask = ">=0.9"
|
|
||||||
Flask-SQLAlchemy = ">=1.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flask-sqlalchemy"
|
|
||||||
version = "3.1.1"
|
|
||||||
description = "Add SQLAlchemy support to your Flask application."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "flask_sqlalchemy-3.1.1-py3-none-any.whl", hash = "sha256:4ba4be7f419dc72f4efd8802d69974803c37259dd42f3913b0dcf75c9447e0a0"},
|
|
||||||
{file = "flask_sqlalchemy-3.1.1.tar.gz", hash = "sha256:e4b68bb881802dda1a7d878b2fc84c06d1ee57fb40b874d3dc97dabfa36b8312"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
flask = ">=2.2.5"
|
|
||||||
sqlalchemy = ">=2.0.16"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "greenlet"
|
|
||||||
version = "3.0.1"
|
|
||||||
description = "Lightweight in-process concurrent programming"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"},
|
|
||||||
{file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"},
|
|
||||||
{file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"},
|
|
||||||
{file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"},
|
|
||||||
{file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"},
|
|
||||||
{file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"},
|
|
||||||
{file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"},
|
|
||||||
{file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["Sphinx"]
|
|
||||||
test = ["objgraph", "psutil"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "identify"
|
|
||||||
version = "2.5.31"
|
|
||||||
description = "File identification library for Python"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"},
|
|
||||||
{file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
license = ["ukkonen"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "importlib-metadata"
|
|
||||||
version = "6.8.0"
|
|
||||||
description = "Read metadata from Python packages"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
|
|
||||||
{file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
zipp = ">=0.5"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
perf = ["ipython"]
|
|
||||||
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itsdangerous"
|
|
||||||
version = "2.1.2"
|
|
||||||
description = "Safely pass data to untrusted environments and back."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
|
|
||||||
{file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jinja2"
|
|
||||||
version = "3.1.2"
|
|
||||||
description = "A very fast and expressive template engine."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
|
|
||||||
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
MarkupSafe = ">=2.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
i18n = ["Babel (>=2.7)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mako"
|
|
||||||
version = "1.2.4"
|
|
||||||
description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "Mako-1.2.4-py3-none-any.whl", hash = "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818"},
|
|
||||||
{file = "Mako-1.2.4.tar.gz", hash = "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
MarkupSafe = ">=0.9.2"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
babel = ["Babel"]
|
|
||||||
lingua = ["lingua"]
|
|
||||||
testing = ["pytest"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "markupsafe"
|
|
||||||
version = "2.1.3"
|
|
||||||
description = "Safely add untrusted strings to HTML/XML markup."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
|
|
||||||
{file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nodeenv"
|
|
||||||
version = "1.8.0"
|
|
||||||
description = "Node.js virtual environment builder"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
|
||||||
files = [
|
|
||||||
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
|
||||||
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
setuptools = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "packaging"
|
|
||||||
version = "23.2"
|
|
||||||
description = "Core utilities for Python packages"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
|
|
||||||
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "platformdirs"
|
|
||||||
version = "3.11.0"
|
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
|
|
||||||
{file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pre-commit"
|
|
||||||
version = "3.5.0"
|
|
||||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"},
|
|
||||||
{file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cfgv = ">=2.0.0"
|
|
||||||
identify = ">=1.0.0"
|
|
||||||
nodeenv = ">=0.11.1"
|
|
||||||
pyyaml = ">=5.1"
|
|
||||||
virtualenv = ">=20.10.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prompt-toolkit"
|
|
||||||
version = "3.0.36"
|
|
||||||
description = "Library for building powerful interactive command lines in Python"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6.2"
|
|
||||||
files = [
|
|
||||||
{file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"},
|
|
||||||
{file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
wcwidth = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyjwt"
|
|
||||||
version = "2.8.0"
|
|
||||||
description = "JSON Web Token implementation in Python"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"},
|
|
||||||
{file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
crypto = ["cryptography (>=3.4.0)"]
|
|
||||||
dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
|
|
||||||
docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
|
|
||||||
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "python-dotenv"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
|
|
||||||
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
cli = ["click (>=5.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyyaml"
|
|
||||||
version = "6.0.1"
|
|
||||||
description = "YAML parser and emitter for Python"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
|
||||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
|
||||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "questionary"
|
|
||||||
version = "2.0.1"
|
|
||||||
description = "Python library to build pretty command line user prompts ⭐️"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "questionary-2.0.1-py3-none-any.whl", hash = "sha256:8ab9a01d0b91b68444dff7f6652c1e754105533f083cbe27597c8110ecc230a2"},
|
|
||||||
{file = "questionary-2.0.1.tar.gz", hash = "sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
prompt_toolkit = ">=2.0,<=3.0.36"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "setuptools"
|
|
||||||
version = "68.2.2"
|
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"},
|
|
||||||
{file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sqlalchemy"
|
|
||||||
version = "2.0.22"
|
|
||||||
description = "Database Abstraction Library"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f146c61ae128ab43ea3a0955de1af7e1633942c2b2b4985ac51cc292daf33222"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:875de9414393e778b655a3d97d60465eb3fae7c919e88b70cc10b40b9f56042d"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13790cb42f917c45c9c850b39b9941539ca8ee7917dacf099cc0b569f3d40da7"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04ab55cf49daf1aeb8c622c54d23fa4bec91cb051a43cc24351ba97e1dd09f5"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a42c9fa3abcda0dcfad053e49c4f752eef71ecd8c155221e18b99d4224621176"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14cd3bcbb853379fef2cd01e7c64a5d6f1d005406d877ed9509afb7a05ff40a5"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win32.whl", hash = "sha256:d143c5a9dada696bcfdb96ba2de4a47d5a89168e71d05a076e88a01386872f97"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win_amd64.whl", hash = "sha256:ccd87c25e4c8559e1b918d46b4fa90b37f459c9b4566f1dfbce0eb8122571547"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f6ff392b27a743c1ad346d215655503cec64405d3b694228b3454878bf21590"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f776c2c30f0e5f4db45c3ee11a5f2a8d9de68e81eb73ec4237de1e32e04ae81c"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8f1792d20d2f4e875ce7a113f43c3561ad12b34ff796b84002a256f37ce9437"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80eeb5189d7d4b1af519fc3f148fe7521b9dfce8f4d6a0820e8f5769b005051"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69fd9e41cf9368afa034e1c81f3570afb96f30fcd2eb1ef29cb4d9371c6eece2"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54bcceaf4eebef07dadfde424f5c26b491e4a64e61761dea9459103ecd6ccc95"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win32.whl", hash = "sha256:7ee7ccf47aa503033b6afd57efbac6b9e05180f492aeed9fcf70752556f95624"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win_amd64.whl", hash = "sha256:b560f075c151900587ade06706b0c51d04b3277c111151997ea0813455378ae0"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2c9bac865ee06d27a1533471405ad240a6f5d83195eca481f9fc4a71d8b87df8"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:625b72d77ac8ac23da3b1622e2da88c4aedaee14df47c8432bf8f6495e655de2"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39a6e21110204a8c08d40ff56a73ba542ec60bab701c36ce721e7990df49fb9"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a766cb0b468223cafdf63e2d37f14a4757476157927b09300c8c5832d88560"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0e1ce8ebd2e040357dde01a3fb7d30d9b5736b3e54a94002641dfd0aa12ae6ce"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:505f503763a767556fa4deae5194b2be056b64ecca72ac65224381a0acab7ebe"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win32.whl", hash = "sha256:154a32f3c7b00de3d090bc60ec8006a78149e221f1182e3edcf0376016be9396"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win_amd64.whl", hash = "sha256:129415f89744b05741c6f0b04a84525f37fbabe5dc3774f7edf100e7458c48cd"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3940677d341f2b685a999bffe7078697b5848a40b5f6952794ffcf3af150c301"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55914d45a631b81a8a2cb1a54f03eea265cf1783241ac55396ec6d735be14883"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096d6b018d242a2bcc9e451618166f860bb0304f590d205173d317b69986c95"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:19c6986cf2fb4bc8e0e846f97f4135a8e753b57d2aaaa87c50f9acbe606bd1db"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ac28bd6888fe3c81fbe97584eb0b96804bd7032d6100b9701255d9441373ec1"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win32.whl", hash = "sha256:cb9a758ad973e795267da334a92dd82bb7555cb36a0960dcabcf724d26299db8"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win_amd64.whl", hash = "sha256:40b1206a0d923e73aa54f0a6bd61419a96b914f1cd19900b6c8226899d9742ad"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3aa1472bf44f61dd27987cd051f1c893b7d3b17238bff8c23fceaef4f1133868"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:56a7e2bb639df9263bf6418231bc2a92a773f57886d371ddb7a869a24919face"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccca778c0737a773a1ad86b68bda52a71ad5950b25e120b6eb1330f0df54c3d0"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6c3e9350f9fb16de5b5e5fbf17b578811a52d71bb784cc5ff71acb7de2a7f9"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:564e9f9e4e6466273dbfab0e0a2e5fe819eec480c57b53a2cdee8e4fdae3ad5f"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af66001d7b76a3fab0d5e4c1ec9339ac45748bc4a399cbc2baa48c1980d3c1f4"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win32.whl", hash = "sha256:9e55dff5ec115316dd7a083cdc1a52de63693695aecf72bc53a8e1468ce429e5"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win_amd64.whl", hash = "sha256:4e869a8ff7ee7a833b74868a0887e8462445ec462432d8cbeff5e85f475186da"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9886a72c8e6371280cb247c5d32c9c8fa141dc560124348762db8a8b236f8692"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a571bc8ac092a3175a1d994794a8e7a1f2f651e7c744de24a19b4f740fe95034"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db5ba8b7da759b727faebc4289a9e6a51edadc7fc32207a30f7c6203a181592"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0b3f2686c3f162123adba3cb8b626ed7e9b8433ab528e36ed270b4f70d1cdb"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c1fea8c0abcb070ffe15311853abfda4e55bf7dc1d4889497b3403629f3bf00"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4bb062784f37b2d75fd9b074c8ec360ad5df71f933f927e9e95c50eb8e05323c"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win32.whl", hash = "sha256:58a3aba1bfb32ae7af68da3f277ed91d9f57620cf7ce651db96636790a78b736"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win_amd64.whl", hash = "sha256:92e512a6af769e4725fa5b25981ba790335d42c5977e94ded07db7d641490a85"},
|
|
||||||
{file = "SQLAlchemy-2.0.22-py3-none-any.whl", hash = "sha256:3076740335e4aaadd7deb3fe6dcb96b3015f1613bd190a4e1634e1b99b02ec86"},
|
|
||||||
{file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
|
|
||||||
typing-extensions = ">=4.2.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
|
|
||||||
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"]
|
|
||||||
asyncio = ["greenlet (!=0.4.17)"]
|
|
||||||
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
|
|
||||||
mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"]
|
|
||||||
mssql = ["pyodbc"]
|
|
||||||
mssql-pymssql = ["pymssql"]
|
|
||||||
mssql-pyodbc = ["pyodbc"]
|
|
||||||
mypy = ["mypy (>=0.910)"]
|
|
||||||
mysql = ["mysqlclient (>=1.4.0)"]
|
|
||||||
mysql-connector = ["mysql-connector-python"]
|
|
||||||
oracle = ["cx-oracle (>=7)"]
|
|
||||||
oracle-oracledb = ["oracledb (>=1.0.1)"]
|
|
||||||
postgresql = ["psycopg2 (>=2.7)"]
|
|
||||||
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
|
|
||||||
postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
|
|
||||||
postgresql-psycopg = ["psycopg (>=3.0.7)"]
|
|
||||||
postgresql-psycopg2binary = ["psycopg2-binary"]
|
|
||||||
postgresql-psycopg2cffi = ["psycopg2cffi"]
|
|
||||||
postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
|
|
||||||
pymysql = ["pymysql"]
|
|
||||||
sqlcipher = ["sqlcipher3-binary"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termcolor"
|
|
||||||
version = "2.3.0"
|
|
||||||
description = "ANSI color formatting for output in terminal"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"},
|
|
||||||
{file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
tests = ["pytest", "pytest-cov"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tomlkit"
|
|
||||||
version = "0.12.1"
|
|
||||||
description = "Style preserving TOML library"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"},
|
|
||||||
{file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typing-extensions"
|
|
||||||
version = "4.8.0"
|
|
||||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
|
|
||||||
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "virtualenv"
|
|
||||||
version = "20.24.6"
|
|
||||||
description = "Virtual Python Environment builder"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"},
|
|
||||||
{file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
distlib = ">=0.3.7,<1"
|
|
||||||
filelock = ">=3.12.2,<4"
|
|
||||||
platformdirs = ">=3.9.1,<4"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
|
||||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wcwidth"
|
|
||||||
version = "0.2.9"
|
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "wcwidth-0.2.9-py2.py3-none-any.whl", hash = "sha256:9a929bd8380f6cd9571a968a9c8f4353ca58d7cd812a4822bba831f8d685b223"},
|
|
||||||
{file = "wcwidth-0.2.9.tar.gz", hash = "sha256:a675d1a4a2d24ef67096a04b85b02deeecd8e226f57b5e3a72dbb9ed99d27da8"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "werkzeug"
|
|
||||||
version = "3.0.1"
|
|
||||||
description = "The comprehensive WSGI web application library."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "werkzeug-3.0.1-py3-none-any.whl", hash = "sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10"},
|
|
||||||
{file = "werkzeug-3.0.1.tar.gz", hash = "sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
MarkupSafe = ">=2.1.1"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
watchdog = ["watchdog (>=2.3)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zipp"
|
|
||||||
version = "3.17.0"
|
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
|
|
||||||
{file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
lock-version = "2.0"
|
|
||||||
python-versions = "^3.10"
|
|
||||||
content-hash = "e99a77db2a32e04474571eea6c88dad45078d1a0b2d146af67e1f360ecd4760f"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
[tool.poetry]
|
|
||||||
name = "pear-admin-flask"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "flask + pear admin layui"
|
|
||||||
authors = ["zhengxinonly <pyxxponly@gmail.com>"]
|
|
||||||
license = "MIT"
|
|
||||||
readme = "README.md"
|
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
|
||||||
python = "^3.10"
|
|
||||||
flask = "^3.0.0"
|
|
||||||
flask-sqlalchemy = "^3.1.1"
|
|
||||||
flask-jwt-extended = "^4.5.2"
|
|
||||||
flask-migrate = "^4.0.5"
|
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
|
||||||
python-dotenv = "^1.0.0"
|
|
||||||
pre-commit = "^3.4.0"
|
|
||||||
commitizen = "^3.10.0"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["poetry-core"]
|
|
||||||
build-backend = "poetry.core.masonry.api"
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-r min.txt
|
||||||
|
-r extra.txt
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Flask-Mail==0.9.1
|
||||||
|
celery==5.2.3
|
||||||
|
qiniu==7.5.0
|
||||||
|
upyun==2.5.5
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
Flask==2.0.2
|
||||||
|
flask-restx==0.5.1
|
||||||
|
pymysql==1.0.2
|
||||||
|
Flask-Migrate==3.1.0
|
||||||
|
flask-marshmallow==0.14.0
|
||||||
|
marshmallow-sqlalchemy==0.27.0
|
||||||
|
Flask-Login==0.5.0
|
||||||
|
Pillow==9.0.0
|
||||||
|
flask-limiter-2.1
|
||||||
|
cachelib-0.6.0
|
||||||
@@ -1,643 +0,0 @@
|
|||||||
html,
|
|
||||||
body,
|
|
||||||
.layui-layout {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-body,
|
|
||||||
.pear-admin .layui-logo,
|
|
||||||
.pear-admin .layui-side,
|
|
||||||
.pear-admin .layui-header,
|
|
||||||
.pear-admin .layui-header .layui-layout-left {
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-side {
|
|
||||||
top: 60px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-side .layui-logo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header .layui-logo {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-side .layui-side-scroll {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-side .layui-side-scroll {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header.dark-theme .layui-layout-control .layui-this * {
|
|
||||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header .layui-logo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-logo .title {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-layout-right .layui-nav-child {
|
|
||||||
border: 1px solid whitesmoke;
|
|
||||||
border-radius: 4px;
|
|
||||||
width: auto;
|
|
||||||
left: auto;
|
|
||||||
right: -23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header {
|
|
||||||
left: 230px;
|
|
||||||
width: calc(100% - 230px);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-layout-control {
|
|
||||||
left: 140px;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-layout-control .layui-nav {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-logo {
|
|
||||||
height: 60px;
|
|
||||||
line-height: 60px;
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: relative;
|
|
||||||
background-color: #28333e;
|
|
||||||
width: 230px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-logo img {
|
|
||||||
width: 34px;
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-logo .title {
|
|
||||||
font-size: 21px;
|
|
||||||
font-weight: 550;
|
|
||||||
color: var(--global-primary-color);
|
|
||||||
position: relative;
|
|
||||||
top: 5px;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-logo .logo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-side {
|
|
||||||
top: 0px;
|
|
||||||
width: 230px;
|
|
||||||
box-shadow: 2px 0 6px rgba(0, 21, 41, 0.2);
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-side-scroll::-webkit-scrollbar {
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-side-scroll {
|
|
||||||
height: calc(100% - 60px) !important;
|
|
||||||
background-color: #28333e;
|
|
||||||
width: 247px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header .layui-nav .layui-nav-item > a {
|
|
||||||
color: black;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-body {
|
|
||||||
bottom: 0px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
overflow-y: auto;
|
|
||||||
left: 230px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-body > div {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-layout-left {
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-footer {
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
left: 230px;
|
|
||||||
background: #fff;
|
|
||||||
border-top: 1px solid #f2f2f2;
|
|
||||||
box-shadow: none;
|
|
||||||
-webkit-transition: left 0.3s;
|
|
||||||
transition: left 0.3s;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #3c3c3cb3;
|
|
||||||
font-weight: 300;
|
|
||||||
font-size: 13.6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-footer.close {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通栏布局 */
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header {
|
|
||||||
left: 0px;
|
|
||||||
z-index: 99999;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header.light-theme {
|
|
||||||
border-bottom: 1px solid whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header.auto-theme,
|
|
||||||
.pear-admin.banner-layout .layui-header.dark-theme {
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header .layui-layout-left {
|
|
||||||
left: 230px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header .layui-logo .title {
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin.banner-layout .layui-header .layui-layout-control {
|
|
||||||
display: inline-block;
|
|
||||||
left: 370px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 头部主题 */
|
|
||||||
.pear-admin .auto-theme {
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .auto-theme .layui-logo {
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .auto-theme .layui-logo .title {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .auto-theme .layui-nav * {
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .auto-theme .layui-nav.pear-nav-control .layui-this * {
|
|
||||||
color: black !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .auto-theme .layui-nav .layui-nav-child a {
|
|
||||||
color: #5f5f5f !important;
|
|
||||||
color: rgba(0, 0, 0, 0.8) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 收缩布局 */
|
|
||||||
.pear-mini .layui-side .layui-logo .title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side .layui-logo .logo {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side {
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-header {
|
|
||||||
left: 60px;
|
|
||||||
width: calc(100% - 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-body {
|
|
||||||
left: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side .layui-logo {
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-footer {
|
|
||||||
left: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-nav-tree .layui-nav-item span {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side-scroll {
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header .layui-nav .layui-nav-bar {
|
|
||||||
top: 0px !important;
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
height: 2px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header .layui-nav .layui-this:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header .layui-nav-more {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-collapsed-pe {
|
|
||||||
right: 30px;
|
|
||||||
bottom: 30px;
|
|
||||||
z-index: 400000;
|
|
||||||
position: absolute;
|
|
||||||
background-color: var(--global-primary-color) !important;
|
|
||||||
box-shadow: 2px 0 6px rgba(0, 21, 41, 0.2);
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 50px;
|
|
||||||
display: none;
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-collapsed-pe a {
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
|
||||||
.layui-hide-sm {
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 769px) {
|
|
||||||
.layui-hide-sm {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增兼容 */
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
.collapse {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-collapsed-pe {
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-layout-control {
|
|
||||||
left: 45px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-layout-left {
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side-scroll {
|
|
||||||
height: calc(100% - 62px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-side {
|
|
||||||
width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-header {
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-body {
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-footer {
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .layui-logo {
|
|
||||||
width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-body {
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .layui-header {
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin .pear-cover {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1000;
|
|
||||||
opacity: 0;
|
|
||||||
margin-top: -60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-mini .pear-cover {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes am-horizontal-roll_show {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: translateX(2000px);
|
|
||||||
transform: translateX(2000px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: translateX(0);
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes am-horizontal-roll_show {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: translateX(800px);
|
|
||||||
-ms-transform: translateX(800px);
|
|
||||||
transform: translateX(800px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transform: translateX(0);
|
|
||||||
-ms-transform: translateX(0);
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.layer-anim-right {
|
|
||||||
-webkit-animation: am-horizontal-roll_show 0.5s ease-out;
|
|
||||||
animation: am-horizontal-roll_show 0.5s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 侧边主题 (亮) */
|
|
||||||
.light-theme.layui-side {
|
|
||||||
box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-theme.layui-side .layui-logo {
|
|
||||||
background-color: white !important;
|
|
||||||
color: black !important;
|
|
||||||
border-bottom: 1px whitesmoke solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-theme.layui-side .layui-side-scroll {
|
|
||||||
background-color: white !important;
|
|
||||||
color: black !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-theme.layui-header {
|
|
||||||
border-bottom: none;
|
|
||||||
background-color: #28333e;
|
|
||||||
color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-theme.layui-header li > a {
|
|
||||||
color: whitesmoke !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-theme.layui-header .layui-logo {
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 顶部主题 (白) */
|
|
||||||
.light-theme.layui-header .layui-logo {
|
|
||||||
background-color: white;
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 主题面板 */
|
|
||||||
.pearone-color .set-text {
|
|
||||||
height: 42px;
|
|
||||||
line-height: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-title {
|
|
||||||
padding: 15px 0 0px 20px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-content {
|
|
||||||
padding: 15px 10px 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-content ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-content ul li {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
width: 70px;
|
|
||||||
height: 50px;
|
|
||||||
margin: 0 20px 20px 0;
|
|
||||||
padding: 2px 2px 2px 2px;
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-content li.layui-this:after,
|
|
||||||
.pearone-color .color-content li:hover:after {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 4px;
|
|
||||||
top: -6px;
|
|
||||||
left: -6px;
|
|
||||||
border: var(--global-primary-color) 2px solid;
|
|
||||||
opacity: 1;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pearone-color .color-content li:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
z-index: 20;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
width: 1px;
|
|
||||||
height: 0;
|
|
||||||
border: 2px solid #f2f2f2;
|
|
||||||
transition: all 0.3s;
|
|
||||||
-webkit-transition: all 0.3s;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-color {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-color .select-color-title {
|
|
||||||
padding: 15px 0 0px 20px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-color .select-color-content {
|
|
||||||
padding: 20px 0 0px 0px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-color .select-color-content .select-color-item {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
color: white;
|
|
||||||
margin-left: 24px;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: gray;
|
|
||||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
|
|
||||||
text-align: center;
|
|
||||||
line-height: 24px;
|
|
||||||
font-size: 14px;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message .layui-tab-title li:not(:last-child) {
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 首屏加载 */
|
|
||||||
.loader-wrapper {
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
z-index: 9999999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
margin: 30px auto 40px;
|
|
||||||
margin-top: 20%;
|
|
||||||
position: relative;
|
|
||||||
z-index: 999999;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader:before {
|
|
||||||
content: "";
|
|
||||||
width: 50px;
|
|
||||||
height: 7px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #000;
|
|
||||||
opacity: 0.1;
|
|
||||||
position: absolute;
|
|
||||||
top: 59px;
|
|
||||||
left: 0;
|
|
||||||
animation: shadow 0.5s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader:after {
|
|
||||||
content: "";
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
animation: loading 0.5s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes loading {
|
|
||||||
17% {
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
transform: translateY(9px) rotate(22.5deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: translateY(18px) scale(1, 0.9) rotate(45deg);
|
|
||||||
border-bottom-right-radius: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
transform: translateY(9px) rotate(67.5deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: translateY(0) rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loading {
|
|
||||||
17% {
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
|
||||||
transform: translateY(9px) rotate(22.5deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: translateY(18px) scale(1, 0.9) rotate(45deg);
|
|
||||||
border-bottom-right-radius: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
75% {
|
|
||||||
transform: translateY(9px) rotate(67.5deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: translateY(0) rotate(90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes shadow {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
transform: scale(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: scale(1.2, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shadow {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
transform: scale(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: scale(1.2, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,356 +0,0 @@
|
|||||||
/** loader */
|
|
||||||
.pear-admin-dark .loader-wrapper,
|
|
||||||
.pear-admin-dark .loader-wrapper .loader {
|
|
||||||
background-color: #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** layout */
|
|
||||||
.pear-admin-dark .layui-layout {
|
|
||||||
background-color: #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** header */
|
|
||||||
.pear-admin-dark .layui-header,
|
|
||||||
.pear-admin-dark .layui-header .layui-logo {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
.pear-admin-dark .layui-header.auto-theme,
|
|
||||||
.pear-admin-dark .layui-header.auto-theme .layui-logo {
|
|
||||||
background-color: var(--global-primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header.auto-theme .layui-logo .title {
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header {
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.4) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header .layui-nav * {
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header .layui-nav .layui-nav-child {
|
|
||||||
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.6) !important;
|
|
||||||
background-color: #141414;
|
|
||||||
border-color: #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header .layui-nav .layui-nav-child dd > a:hover {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-header .pear-nav-control .layui-this a {
|
|
||||||
background-color: #0c0c0c !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .auto-theme .layui-logo .title {
|
|
||||||
color: var(--global-primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** side */
|
|
||||||
.pear-admin-dark .layui-side {
|
|
||||||
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.6) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-logo {
|
|
||||||
border-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-side .layui-logo,
|
|
||||||
.pear-admin-dark .layui-side .layui-side-scroll,
|
|
||||||
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav-tree
|
|
||||||
.layui-nav-child {
|
|
||||||
background-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a,
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav
|
|
||||||
.layui-nav-item
|
|
||||||
a
|
|
||||||
> .layui-nav-more {
|
|
||||||
color: rgba(255, 255, 255, 0.7) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav
|
|
||||||
.layui-nav-child
|
|
||||||
dd.layui-this
|
|
||||||
a,
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav
|
|
||||||
.layui-nav-itemed
|
|
||||||
> a,
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav
|
|
||||||
.layui-nav-itemed
|
|
||||||
> a
|
|
||||||
> .layui-nav-more,
|
|
||||||
.pear-admin-dark
|
|
||||||
.layui-side
|
|
||||||
.layui-side-scroll
|
|
||||||
.layui-nav
|
|
||||||
.layui-nav-item
|
|
||||||
> a:hover {
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** body */
|
|
||||||
.pear-admin-dark .layui-body,
|
|
||||||
.pear-admin-dark .layui-body .pear-tab-page-loading,
|
|
||||||
.pear-admin-dark .layui-body .pear-page-loading {
|
|
||||||
background-color: #0a0a0a !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-tab-title,
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-tab-title li,
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-tab-control li {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
border-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-tab-title li > span:first-child {
|
|
||||||
background-color: #434343;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim {
|
|
||||||
border-color: #141414;
|
|
||||||
background-color: #141414 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a:hover {
|
|
||||||
background-color: #0a0a0a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-body .layui-tab .layui-tab-close:hover {
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #0a0a0a !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .pear-tab-page-menu ul li {
|
|
||||||
color: #ffffff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-footer {
|
|
||||||
background-color: #141414;
|
|
||||||
border-top: 1px solid #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** theme */
|
|
||||||
.pear-admin-dark .set-text,
|
|
||||||
.pear-admin-dark .select-color-title,
|
|
||||||
.pear-admin-dark .color-title {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** search */
|
|
||||||
.pear-admin-dark .menu-search-no-data {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .menu-search-tips * {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .menu-search-tips kbd {
|
|
||||||
border-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** message center */
|
|
||||||
.pear-admin-dark .pear-message-center .layui-tab-title,
|
|
||||||
.pear-admin-dark .pear-message-center .message-item {
|
|
||||||
border-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** button */
|
|
||||||
.pear-admin-dark .layui-btn {
|
|
||||||
color: #ffffff;
|
|
||||||
border-color: #4c4d4f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** layer */
|
|
||||||
.pear-admin-dark .layui-layer {
|
|
||||||
background-color: #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-layer-msg {
|
|
||||||
border-color: #141414;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-layer-msg .layui-layer-content {
|
|
||||||
color: #e5eaf3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-layer .layui-layer-setwin > span,
|
|
||||||
.pear-admin-dark .layui-layer .layui-layer-title {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** card */
|
|
||||||
.pear-admin-dark .layui-card {
|
|
||||||
background-color: #1d1e1f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-card .layui-card-header {
|
|
||||||
border-bottom-color: #414243;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-card .layui-card-body {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** input */
|
|
||||||
.pear-admin-dark .layui-input {
|
|
||||||
background-color: transparent;
|
|
||||||
color: #ffffff;
|
|
||||||
border-color: rgba(0, 0, 0, 0.3) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** switch */
|
|
||||||
.pear-admin-dark .layui-form-switch {
|
|
||||||
border-color: #484849;
|
|
||||||
background-color: rgba(255, 255, 255, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** table */
|
|
||||||
.pear-admin-dark .layui-table {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-table tr:hover {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-table td,
|
|
||||||
.pear-admin-dark .layui-table th,
|
|
||||||
.pear-admin-dark .layui-table-view,
|
|
||||||
.pear-admin-dark .layui-table-page,
|
|
||||||
.pear-admin-dark .layui-table-tool,
|
|
||||||
.pear-admin-dark .layui-table-header {
|
|
||||||
border-color: rgba(0, 0, 0, 0.4) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-laypage select,
|
|
||||||
.pear-admin-dark .layui-laypage button {
|
|
||||||
border-color: rgba(0, 0, 0, 0.4) !important;
|
|
||||||
color: #ffffff !important;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-table-tool-self > div {
|
|
||||||
border-color: rgba(0, 0, 0, 0.4) !important;
|
|
||||||
color: #ffffff !important;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** panel */
|
|
||||||
.pear-admin-dark .layui-panel {
|
|
||||||
background-color: #1d1e1f !important;
|
|
||||||
border-color: #1d1e1f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** menu */
|
|
||||||
.pear-admin-dark .layui-menu {
|
|
||||||
background-color: #1d1e1f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-menu .layui-menu-body-title,
|
|
||||||
.pear-admin-dark .layui-menu .layui-menu-body-title:hover {
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #1d1e1f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** timeline */
|
|
||||||
.pear-admin-dark .layui-timeline-axis {
|
|
||||||
background-color: rgb(29, 30, 31) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .layui-timeline-item:before {
|
|
||||||
background-color: #414243 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** toast */
|
|
||||||
.pear-admin-dark .iziToast {
|
|
||||||
background-color: #1f1f1f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** console */
|
|
||||||
|
|
||||||
.pear-admin-dark .deputy,
|
|
||||||
.pear-admin-dark .shortcut-menu {
|
|
||||||
background-color: #141414 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .deputy:hover,
|
|
||||||
.pear-admin-dark .shortcut-menu:hover {
|
|
||||||
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.6) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .message-board li {
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** analysis */
|
|
||||||
.pear-admin-dark .top-panel-number {
|
|
||||||
color: #ffffff !important;
|
|
||||||
border-color: #414243;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .dynamic-status dd {
|
|
||||||
border-color: #414243;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** success failure */
|
|
||||||
.pear-admin-dark .pear-result .content {
|
|
||||||
background-color: rgba(153, 153, 153, 0.12);
|
|
||||||
color: #e5eaf3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .pear-result .title {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark .pear-result .description {
|
|
||||||
color: #8d9095;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 403 404 500*/
|
|
||||||
.pear-admin-dark .pear-exception .title p {
|
|
||||||
color: #e5eaf3 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** scroll */
|
|
||||||
.pear-admin-dark *::-webkit-scrollbar-thumb {
|
|
||||||
background: #141414;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-admin-dark *::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: #0a0a0a;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
.top-panel {
|
|
||||||
border-radius: 4px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-panel > .layui-card-body {
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-panel-number {
|
|
||||||
line-height: 60px;
|
|
||||||
font-size: 29px;
|
|
||||||
border-right: 1px solid #eceff9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-panel-tips {
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-top: 16px;
|
|
||||||
line-height: 30px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-panel-tips i {
|
|
||||||
font-size: 33px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-panel-tips svg {
|
|
||||||
margin-top: -12px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status {
|
|
||||||
padding: 0 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status dd {
|
|
||||||
padding: 15px 0;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status dd div.dynamic-status-img {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status dd div.dynamic-status-img a {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status dd div span {
|
|
||||||
color: #bbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-status dd div a {
|
|
||||||
color: #01aaed;
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
.shortcut-menu {
|
|
||||||
width: 100%;
|
|
||||||
height: 66px;
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcut-menu i {
|
|
||||||
font-size: 30px;
|
|
||||||
height: 66px;
|
|
||||||
line-height: 66px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcut-menu:hover {
|
|
||||||
box-shadow: 2px 0 8px 0 lightgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcut-menu-label {
|
|
||||||
width: 100%;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deputy {
|
|
||||||
width: 100%;
|
|
||||||
height: 90px;
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deputy:hover {
|
|
||||||
box-shadow: 2px 0 8px 0 lightgray !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deputy .deputy-label {
|
|
||||||
color: gray;
|
|
||||||
margin-top: 14px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deputy .deputy-count {
|
|
||||||
margin-top: 12px;
|
|
||||||
color: var(--global-primary-color);
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board {
|
|
||||||
padding: 0 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li {
|
|
||||||
position: relative;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li p {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-top: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li > span {
|
|
||||||
color: #999;
|
|
||||||
height: 24px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board .message-board-reply {
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
bottom: 12px;
|
|
||||||
height: 24px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
.pear-exception {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
text-align: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 70px 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-exception .title {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-exception .title p {
|
|
||||||
color: rgb(0, 0, 0);
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-exception .description {
|
|
||||||
margin-top: 10px;
|
|
||||||
color: #8d9095;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pear-exception .extra {
|
|
||||||
margin: 30px;
|
|
||||||
}
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
html,
|
|
||||||
body,
|
|
||||||
.layui-row {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-page {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-bg {
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: rgb(250, 250, 250);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-bg-img {
|
|
||||||
width: 90%;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form {
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-center {
|
|
||||||
background: #fff;
|
|
||||||
box-sizing: border-box;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-center-box {
|
|
||||||
width: 360px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-log-title {
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-log {
|
|
||||||
width: 50px;
|
|
||||||
border-radius: 12px;
|
|
||||||
margin-right: 20px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-log-title span {
|
|
||||||
font-size: 32px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--global-primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-desc {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #808695;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-method {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
padding: 20px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-method-item {
|
|
||||||
flex: 1;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 5px 50px;
|
|
||||||
text-align: right;
|
|
||||||
color: #1f2225;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-method-item:nth-child(2) {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-method-item > span {
|
|
||||||
display: inline-block;
|
|
||||||
width: 40px;
|
|
||||||
text-align: center;
|
|
||||||
height: 30px;
|
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-method-item > span:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
color: #16baaa;
|
|
||||||
border-bottom: 2px solid #16baaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-log-verification {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verification-text {
|
|
||||||
flex: 2;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.verification-img {
|
|
||||||
flex: 1;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid #eeeeee;
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 40px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remember-passsword {
|
|
||||||
margin: 20px 0;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.remember-cehcked {
|
|
||||||
flex: 1;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.greenText {
|
|
||||||
color: #16baaa;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn > .layui-btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.other-login {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 20px 0 0;
|
|
||||||
text-align: left;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.other-login-methods {
|
|
||||||
display: inline-block;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-input {
|
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
.text-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info-head {
|
|
||||||
width: 110px;
|
|
||||||
height: 110px;
|
|
||||||
line-height: 110px;
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-line-dash {
|
|
||||||
border-bottom: 1px dashed #ccc;
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blog-title {
|
|
||||||
padding-left: 13.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blog-content {
|
|
||||||
padding-left: 13px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: dimgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-tab-title {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fl-item {
|
|
||||||
height: 30px;
|
|
||||||
font-size: 13.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot {
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border-radius: 50px;
|
|
||||||
background-color: gray;
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board {
|
|
||||||
padding: 0 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li {
|
|
||||||
position: relative;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li p {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-top: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board li > span {
|
|
||||||
color: #999;
|
|
||||||
height: 24px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-board .message-board-reply {
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
bottom: 12px;
|
|
||||||
height: 24px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
.pear-result {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.pear-result .success svg {
|
|
||||||
color: #32c682;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
.pear-result .error svg {
|
|
||||||
color: #f56c6c;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
.pear-result .title {
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
.pear-result .description {
|
|
||||||
margin-top: 25px;
|
|
||||||
width: 60%;
|
|
||||||
margin-left: 20%;
|
|
||||||
color: rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
.pear-result .content {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 80%;
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
padding: 20px 32px;
|
|
||||||
margin-left: 10%;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.pear-result .extra {
|
|
||||||
padding-top: 10px;
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
.layui-dropdown {
|
|
||||||
border-radius: var(--global-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-input {
|
|
||||||
border-radius: var(--global-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-form-onswitch {
|
|
||||||
background-color: var(--global-primary-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn {
|
|
||||||
background-color: var(--global-primary-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn.layui-btn-normal {
|
|
||||||
background-color: #1e9fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn.layui-btn-danger {
|
|
||||||
background-color: #ff5722 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn.layui-btn-warm {
|
|
||||||
background-color: #ffb800 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-btn.layui-btn-primary {
|
|
||||||
background-color: transparent !important;
|
|
||||||
color: #5f5f5f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-card {
|
|
||||||
border-radius: var(--global-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-timeline-axis {
|
|
||||||
color: var(--global-primary-color);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
:root {
|
|
||||||
--global-primary-color: #16baaa;
|
|
||||||
|
|
||||||
--global-border-radius: 4px;
|
|
||||||
}
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"title": "工作空间",
|
|
||||||
"icon": "layui-icon layui-icon-console",
|
|
||||||
"type": 0,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "10",
|
|
||||||
"title": "分析页",
|
|
||||||
"icon": "layui-icon layui-icon-console",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/analysis/index.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "11",
|
|
||||||
"title": "工作台",
|
|
||||||
"icon": "layui-icon layui-icon-console",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/console/index.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"title": "列表页面",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": 91,
|
|
||||||
"title": "查询表格",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/listing/table.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"title": "扩展组件",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": 23,
|
|
||||||
"title": "高级栅格",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/component/grid.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 24,
|
|
||||||
"title": "消息提示",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/component/toast.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 25,
|
|
||||||
"title": "路由过渡",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/component/nprogress.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "result",
|
|
||||||
"title": "结果页面",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"href": "",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "success",
|
|
||||||
"title": "成功页面",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "failure",
|
|
||||||
"title": "失败页面",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/error.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "exception",
|
|
||||||
"title": "异常页面",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"href": "",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "403",
|
|
||||||
"title": "403",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/exception/403.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "404",
|
|
||||||
"title": "404",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/exception/404.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "500",
|
|
||||||
"title": "500",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/exception/500.html"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "open",
|
|
||||||
"title": "菜单模式",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "a",
|
|
||||||
"title": "普通路由",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "b",
|
|
||||||
"title": "嵌套网页",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_iframe",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "c",
|
|
||||||
"title": "新建标签",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "d",
|
|
||||||
"title": "弹窗网页",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_layer",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep",
|
|
||||||
"title": "深度测试",
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"type": 0,
|
|
||||||
"href": "",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-1",
|
|
||||||
"title": "二级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-1-1",
|
|
||||||
"title": "三级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-1-1-1",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-1-1-2",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-1-2",
|
|
||||||
"title": "三级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-1-2-1",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-1-2-2",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-2",
|
|
||||||
"title": "二级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-2-1",
|
|
||||||
"title": "三级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-2-1-1",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-2-1-2",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-2-2",
|
|
||||||
"title": "三级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 0,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": "deep1-2-2-1",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-smile",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_component",
|
|
||||||
"href": "view/result/success.html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "deep1-2-2-2",
|
|
||||||
"title": "四级菜单",
|
|
||||||
"icon": "layui-icon layui-icon-face-cry",
|
|
||||||
"type": 1,
|
|
||||||
"openType": "_blank",
|
|
||||||
"href": "http://www.layui-vue.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
{
|
|
||||||
"code": 200,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"title": "通知",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
|
|
||||||
"title": "你收到了 14 份新周报",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png",
|
|
||||||
"title": "曲妮妮 已通过第三轮面试",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png",
|
|
||||||
"title": "可以区分多种通知类型",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png",
|
|
||||||
"title": "左侧图标用于区分不同的类型",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
|
|
||||||
"title": "内容不要超过两行字",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"title": "消息",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
|
|
||||||
"title": "你收到了 14 份新周报",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png",
|
|
||||||
"title": "曲妮妮 已通过第三轮面试",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png",
|
|
||||||
"title": "可以区分多种通知类型",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png",
|
|
||||||
"title": "左侧图标用于区分不同的类型",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
|
|
||||||
"title": "内容不要超过两行字",
|
|
||||||
"context": "这是消息内容。",
|
|
||||||
"form": "就眠仪式",
|
|
||||||
"time": "刚刚"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"title": "代办",
|
|
||||||
"children": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
{
|
|
||||||
"code": 0,
|
|
||||||
"msg": "",
|
|
||||||
"count": 1000,
|
|
||||||
"totalRow": {
|
|
||||||
"era": {
|
|
||||||
"tang": "2",
|
|
||||||
"song": "2",
|
|
||||||
"xian": "20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"id": "10001",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test1@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10002",
|
|
||||||
"username": "杜甫",
|
|
||||||
"email": "test2@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "108",
|
|
||||||
"joinTime": "2016-10-14",
|
|
||||||
"LAY_CHECKED": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10003",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test3@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10004",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test4@email.com",
|
|
||||||
"sex": "女",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10005",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test5@email.com",
|
|
||||||
"sex": "女",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10006",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test6@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10007",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test7@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10008",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test8@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10009",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test9@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10010",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test10@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10011",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test11@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10012",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test12@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10013",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test13@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10014",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test14@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10015",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test15@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10016",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test16@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10017",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test17@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10018",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test18@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10019",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test19@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10020",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test20@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10021",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test21@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10022",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test22@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10023",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test23@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10024",
|
|
||||||
"username": "就眠儀式",
|
|
||||||
"email": "test24@email.com",
|
|
||||||
"sex": "男",
|
|
||||||
"city": "浙江杭州",
|
|
||||||
"sign": "花开堪折直须折,莫待无花空折枝.",
|
|
||||||
"experience": "100",
|
|
||||||
"ip": "192.168.0.8",
|
|
||||||
"checkin": "106",
|
|
||||||
"joinTime": "2016-10-14"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 74 KiB |
@@ -1,68 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1361px" height="609px" viewBox="0 0 1361 609" version="1.1">
|
|
||||||
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>Group 21</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs/>
|
|
||||||
<g id="Ant-Design-Pro-3.0" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<g id="账户密码登录-校验" transform="translate(-79.000000, -82.000000)">
|
|
||||||
<g id="Group-21" transform="translate(77.000000, 73.000000)">
|
|
||||||
<g id="Group-18" opacity="0.8" transform="translate(74.901416, 569.699158) rotate(-7.000000) translate(-74.901416, -569.699158) translate(4.901416, 525.199158)">
|
|
||||||
<ellipse id="Oval-11" fill="#CFDAE6" opacity="0.25" cx="63.5748792" cy="32.468367" rx="21.7830479" ry="21.766008"/>
|
|
||||||
<ellipse id="Oval-3" fill="#CFDAE6" opacity="0.599999964" cx="5.98746479" cy="13.8668601" rx="5.2173913" ry="5.21330997"/>
|
|
||||||
<path d="M38.1354514,88.3520215 C43.8984227,88.3520215 48.570234,83.6838647 48.570234,77.9254015 C48.570234,72.1669383 43.8984227,67.4987816 38.1354514,67.4987816 C32.3724801,67.4987816 27.7006688,72.1669383 27.7006688,77.9254015 C27.7006688,83.6838647 32.3724801,88.3520215 38.1354514,88.3520215 Z" id="Oval-3-Copy" fill="#CFDAE6" opacity="0.45"/>
|
|
||||||
<path d="M64.2775582,33.1704963 L119.185836,16.5654915" id="Path-12" stroke="#CFDAE6" stroke-width="1.73913043" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M42.1431708,26.5002681 L7.71190162,14.5640702" id="Path-16" stroke="#E0B4B7" stroke-width="0.702678964" opacity="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"/>
|
|
||||||
<path d="M63.9262187,33.521561 L43.6721326,69.3250951" id="Path-15" stroke="#BACAD9" stroke-width="0.702678964" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"/>
|
|
||||||
<g id="Group-17" transform="translate(126.850922, 13.543654) rotate(30.000000) translate(-126.850922, -13.543654) translate(117.285705, 4.381889)" fill="#CFDAE6">
|
|
||||||
<ellipse id="Oval-4" opacity="0.45" cx="9.13482653" cy="9.12768076" rx="9.13482653" ry="9.12768076"/>
|
|
||||||
<path d="M18.2696531,18.2553615 C18.2696531,13.2142826 14.1798519,9.12768076 9.13482653,9.12768076 C4.08980114,9.12768076 0,13.2142826 0,18.2553615 L18.2696531,18.2553615 Z" id="Oval-4" transform="translate(9.134827, 13.691521) scale(-1, -1) translate(-9.134827, -13.691521) "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="Group-14" transform="translate(216.294700, 123.725600) rotate(-5.000000) translate(-216.294700, -123.725600) translate(106.294700, 35.225600)">
|
|
||||||
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.25" cx="29.1176471" cy="29.1402439" rx="29.1176471" ry="29.1402439"/>
|
|
||||||
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.3" cx="29.1176471" cy="29.1402439" rx="21.5686275" ry="21.5853659"/>
|
|
||||||
<ellipse id="Oval-2-Copy" stroke="#CFDAE6" opacity="0.4" cx="179.019608" cy="138.146341" rx="23.7254902" ry="23.7439024"/>
|
|
||||||
<ellipse id="Oval-2" fill="#BACAD9" opacity="0.5" cx="29.1176471" cy="29.1402439" rx="10.7843137" ry="10.7926829"/>
|
|
||||||
<path d="M29.1176471,39.9329268 L29.1176471,18.347561 C23.1616351,18.347561 18.3333333,23.1796097 18.3333333,29.1402439 C18.3333333,35.1008781 23.1616351,39.9329268 29.1176471,39.9329268 Z" id="Oval-2" fill="#BACAD9"/>
|
|
||||||
<g id="Group-9" opacity="0.45" transform="translate(172.000000, 131.000000)" fill="#E6A1A6">
|
|
||||||
<ellipse id="Oval-2-Copy-2" cx="7.01960784" cy="7.14634146" rx="6.47058824" ry="6.47560976"/>
|
|
||||||
<path d="M0.549019608,13.6219512 C4.12262681,13.6219512 7.01960784,10.722722 7.01960784,7.14634146 C7.01960784,3.56996095 4.12262681,0.670731707 0.549019608,0.670731707 L0.549019608,13.6219512 Z" id="Oval-2-Copy-2" transform="translate(3.784314, 7.146341) scale(-1, 1) translate(-3.784314, -7.146341) "/>
|
|
||||||
</g>
|
|
||||||
<ellipse id="Oval-10" fill="#CFDAE6" cx="218.382353" cy="138.685976" rx="1.61764706" ry="1.61890244"/>
|
|
||||||
<ellipse id="Oval-10-Copy-2" fill="#E0B4B7" opacity="0.35" cx="179.558824" cy="175.381098" rx="1.61764706" ry="1.61890244"/>
|
|
||||||
<ellipse id="Oval-10-Copy" fill="#E0B4B7" opacity="0.35" cx="180.098039" cy="102.530488" rx="2.15686275" ry="2.15853659"/>
|
|
||||||
<path d="M28.9985381,29.9671598 L171.151018,132.876024" id="Path-11" stroke="#CFDAE6" opacity="0.8"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group-10" opacity="0.799999952" transform="translate(1054.100635, 36.659317) rotate(-11.000000) translate(-1054.100635, -36.659317) translate(1026.600635, 4.659317)">
|
|
||||||
<ellipse id="Oval-7" stroke="#CFDAE6" stroke-width="0.941176471" cx="43.8135593" cy="32" rx="11.1864407" ry="11.2941176"/>
|
|
||||||
<g id="Group-12" transform="translate(34.596774, 23.111111)" fill="#BACAD9">
|
|
||||||
<ellipse id="Oval-7" opacity="0.45" cx="9.18534718" cy="8.88888889" rx="8.47457627" ry="8.55614973"/>
|
|
||||||
<path d="M9.18534718,17.4450386 C13.8657264,17.4450386 17.6599235,13.6143199 17.6599235,8.88888889 C17.6599235,4.16345787 13.8657264,0.332739156 9.18534718,0.332739156 L9.18534718,17.4450386 Z" id="Oval-7"/>
|
|
||||||
</g>
|
|
||||||
<path d="M34.6597385,24.809694 L5.71666084,4.76878945" id="Path-2" stroke="#CFDAE6" stroke-width="0.941176471"/>
|
|
||||||
<ellipse id="Oval" stroke="#CFDAE6" stroke-width="0.941176471" cx="3.26271186" cy="3.29411765" rx="3.26271186" ry="3.29411765"/>
|
|
||||||
<ellipse id="Oval-Copy" fill="#F7E1AD" cx="2.79661017" cy="61.1764706" rx="2.79661017" ry="2.82352941"/>
|
|
||||||
<path d="M34.6312443,39.2922712 L5.06366663,59.785082" id="Path-10" stroke="#CFDAE6" stroke-width="0.941176471"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group-19" opacity="0.33" transform="translate(1282.537219, 446.502867) rotate(-10.000000) translate(-1282.537219, -446.502867) translate(1142.537219, 327.502867)">
|
|
||||||
<g id="Group-17" transform="translate(141.333539, 104.502742) rotate(275.000000) translate(-141.333539, -104.502742) translate(129.333539, 92.502742)" fill="#BACAD9">
|
|
||||||
<circle id="Oval-4" opacity="0.45" cx="11.6666667" cy="11.6666667" r="11.6666667"/>
|
|
||||||
<path d="M23.3333333,23.3333333 C23.3333333,16.8900113 18.1099887,11.6666667 11.6666667,11.6666667 C5.22334459,11.6666667 0,16.8900113 0,23.3333333 L23.3333333,23.3333333 Z" id="Oval-4" transform="translate(11.666667, 17.500000) scale(-1, -1) translate(-11.666667, -17.500000) "/>
|
|
||||||
</g>
|
|
||||||
<circle id="Oval-5-Copy-6" fill="#CFDAE6" cx="201.833333" cy="87.5" r="5.83333333"/>
|
|
||||||
<path d="M143.5,88.8126685 L155.070501,17.6038544" id="Path-17" stroke="#BACAD9" stroke-width="1.16666667"/>
|
|
||||||
<path d="M17.5,37.3333333 L127.466252,97.6449735" id="Path-18" stroke="#BACAD9" stroke-width="1.16666667"/>
|
|
||||||
<polyline id="Path-19" stroke="#CFDAE6" stroke-width="1.16666667" points="143.902597 120.302281 174.935455 231.571342 38.5 147.510847 126.366941 110.833333"/>
|
|
||||||
<path d="M159.833333,99.7453842 L195.416667,89.25" id="Path-20" stroke="#E0B4B7" stroke-width="1.16666667" opacity="0.6"/>
|
|
||||||
<path d="M205.333333,82.1372105 L238.719406,36.1666667" id="Path-24" stroke="#BACAD9" stroke-width="1.16666667"/>
|
|
||||||
<path d="M266.723424,132.231988 L207.083333,90.4166667" id="Path-25" stroke="#CFDAE6" stroke-width="1.16666667"/>
|
|
||||||
<circle id="Oval-5" fill="#C1D1E0" cx="156.916667" cy="8.75" r="8.75"/>
|
|
||||||
<circle id="Oval-5-Copy-3" fill="#C1D1E0" cx="39.0833333" cy="148.75" r="5.25"/>
|
|
||||||
<circle id="Oval-5-Copy-2" fill-opacity="0.6" fill="#D1DEED" cx="8.75" cy="33.25" r="8.75"/>
|
|
||||||
<circle id="Oval-5-Copy-4" fill-opacity="0.6" fill="#D1DEED" cx="243.833333" cy="30.3333333" r="5.83333333"/>
|
|
||||||
<circle id="Oval-5-Copy-5" fill="#E0B4B7" cx="175.583333" cy="232.75" r="5.25"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.9 MiB |
|
Before Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 322 KiB |