Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55ea1e7252 | ||
|
|
b80b869dd8 | ||
|
|
7fea9743c9 | ||
|
|
c09812f85d | ||
|
|
794a8a57ad | ||
|
|
cab60da886 | ||
|
|
7501ae1dc2 | ||
|
|
9fc2eb0ae3 | ||
|
|
12d4dfe410 | ||
|
|
d54eb4dc3e | ||
|
|
246ce3b3b7 | ||
|
|
36250fad43 | ||
|
|
0d25b479e5 | ||
|
|
7e6aecc99b | ||
|
|
82de7b0273 | ||
|
|
8760f21b03 | ||
|
|
1e34ef339a | ||
|
|
5333a68416 | ||
|
|
decde3a69a | ||
|
|
9dcc05deda | ||
|
|
c0d963628b | ||
|
|
6978002393 | ||
|
|
3453b01938 | ||
|
|
820ab9f5c6 | ||
|
|
9490ccb7c0 | ||
|
|
056c4b7023 | ||
|
|
d4d8d8b294 | ||
|
|
8bc5d6e0c2 | ||
|
|
3fa8ae0a8a | ||
|
|
316ebc2441 | ||
|
|
550f99e468 | ||
|
|
b9c449ad57 | ||
|
|
db5b4e89ed | ||
|
|
733286b090 | ||
|
|
7505e4552b | ||
|
|
e918727984 | ||
|
|
00053da117 | ||
|
|
27f5d78c35 | ||
|
|
97e0160aaf | ||
|
|
04794e583f | ||
|
|
0640255519 | ||
|
|
460984f209 | ||
|
|
635dcc1dac | ||
|
|
b26237e24b | ||
|
|
a35d443fb6 | ||
|
|
ab4bb1ca40 | ||
|
|
2b7304e615 | ||
|
|
64748e513d | ||
|
|
5b07fed518 | ||
|
|
eb85e30b79 | ||
|
|
b8e0173a9c | ||
|
|
0ca75c81d4 | ||
|
|
aa86bbe372 | ||
|
|
86f07817b1 | ||
|
|
3f74011c98 | ||
|
|
ce8adda79d | ||
|
|
5470837707 | ||
|
|
c26f15ae69 | ||
|
|
4d6d998ae2 | ||
|
|
d628432621 | ||
|
|
2bcaa8e071 | ||
|
|
ebf76055a4 | ||
|
|
b2b08769b0 | ||
|
|
aae15fd07a | ||
|
|
945f746d97 | ||
|
|
dce7908041 | ||
|
|
0ba2b3aa56 | ||
|
|
17792ccacf | ||
|
|
e3dd5458ad | ||
|
|
e9bd8a17a0 | ||
|
|
b8870d4c33 | ||
|
|
8fba71c464 | ||
|
|
0cb74c5eb7 | ||
|
|
6da6768f81 | ||
|
|
05dff28523 | ||
|
|
d7c7237cd4 |
@@ -0,0 +1,3 @@
|
|||||||
|
FLASK_ENV=development
|
||||||
|
FLASK_RUN_HOST=0.0.0.0
|
||||||
|
FLASK_APP='applications:create_app'
|
||||||
|
|||||||
@@ -116,3 +116,9 @@ dmypy.json
|
|||||||
|
|
||||||
#ide
|
#ide
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# 数据库文件
|
||||||
|
*.db
|
||||||
|
#上传到本地的图片文件
|
||||||
|
*upload/
|
||||||
|
migrations/
|
||||||
@@ -29,111 +29,112 @@
|
|||||||
<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" />
|
<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>
|
</div>
|
||||||
|
|
||||||
#### 项目简介
|
## 项目简介
|
||||||
>Pear Admin Flask 基于 Flask 的后台管理系统,拥抱应用广泛的python语言,通过使用本系统,即可快速构建你的功能业务
|
Pear Admin Flask 基于 Flask 生态的后台管理系统,该项目旨在为 python 开发者提供一个快速开发前后端半分离的后台管理系统的模板
|
||||||
>
|
|
||||||
>项目旨在为python开发者提供一个后台管理系统的模板,成为您构建信息管理系统,物联网后台....等等应用时灵活,简单的工具
|
|
||||||
>
|
|
||||||
>各位Python爱好者多多指教
|
|
||||||
|
|
||||||
Pear Admin Flask 分为 Common / Simple 两个版本:
|
在使用本项目之前最好掌握以下知识点
|
||||||
|
|
||||||
[** Common 通用版本 **](https://gitee.com/pear-admin/pear-admin-flask/tree/master/)
|
+ [html、css、JavaScript](https://developer.mozilla.org/zh-CN/docs/Learn/HTML)
|
||||||
|
+ [jQuery](https://www.w3school.com.cn/jquery/index.asp)
|
||||||
[** Simple 简洁版本 **](https://gitee.com/pear-admin/pear-admin-flask/tree/simple/)
|
+ [layui](https://www.layui.com/)
|
||||||
|
+ [flask](https://dormousehole.readthedocs.io/en/latest/)
|
||||||
#### 内置功能
|
+ [flask-login](https://flask-login.readthedocs.io/en/latest/)
|
||||||
|
+ [flask-sqlalchemy](http://www.pythondoc.com/flask-sqlalchemy/quickstart.html)
|
||||||
- [x] 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
+ [flask-restful](https://flask-restful.readthedocs.io/en/latest/)
|
||||||
- [x] 权限管理:配置系统菜单,操作权限,按钮权限标识等。
|
|
||||||
- [x] 角色管理:角色菜单权限分配。
|
|
||||||
- [x] 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
|
||||||
- [x] 登录日志:系统登录日志记录查询包含登录异常。
|
|
||||||
- [x] 服务监控:监视当前系统CPU、内存、磁盘、python版本,运行时长等相关信息。
|
|
||||||
- [x] 文件上传: 图片上传示例
|
|
||||||
- [ ] 代码生成: 构想中....
|
|
||||||
|
|
||||||
#### 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
Pear Admin Flask
|
|
||||||
├─applications # 应用
|
|
||||||
│ ├─configs # 配置文件
|
|
||||||
│ │ ├─ common.py # 普通配置
|
|
||||||
│ │ └─ config.py # 配置文件对象
|
|
||||||
│ ├─extensions # 注册插件
|
|
||||||
│ ├─models # 数据模型
|
|
||||||
│ ├─static # 静态资源文件
|
|
||||||
│ ├─templates # 静态模板文件
|
|
||||||
│ └─views # 视图部分
|
|
||||||
│ ├─admin # 后台管理视图模块
|
|
||||||
│ └─index # 前台视图模块
|
|
||||||
├─docs # 文档说明(占坑)
|
|
||||||
├─migrations # 迁移文件记录
|
|
||||||
├─requirement # 依赖文件
|
|
||||||
├─test # 测试文件夹(占坑)
|
|
||||||
└─.env # 项目的配置文件
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
## 预览
|
||||||
|
Pear Admin Flask 有以下几个版本:
|
||||||
|
|
||||||
#### 项目安装
|
[master分支版本 ](https://gitee.com/pear-admin/pear-admin-flask/tree/master/)
|
||||||
|
|
||||||
```bash
|
>flask 2.x + flask-sqlalchemy + 权限验证 + Flask-APScheduler 定时任务 + marshmallow 序列化与数据验证
|
||||||
# 下 载
|
|
||||||
git clone https://gitee.com/pear-admin/pear-admin-flask
|
|
||||||
|
|
||||||
# 安 装
|
[Mini 分支版本 ](https://gitee.com/pear-admin/pear-admin-flask/tree/mini/)
|
||||||
pip install -r requirement\requirement-dev.txt
|
|
||||||
|
|
||||||
# 配 置
|
>flask 2.x + flask-sqlalchemy + Flask-restful + 基于角色的权限管理
|
||||||
.env
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 修改配置
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 主 机
|
|
||||||
HOST = '127.0.0.1'
|
|
||||||
|
|
||||||
# 端 口
|
|
||||||
PORT = '3306'
|
|
||||||
|
|
||||||
# 数 据 库
|
|
||||||
DATABASE = 'PearAdminFlask'
|
|
||||||
|
|
||||||
# 账 户
|
|
||||||
USERNAME = 'root'
|
|
||||||
|
|
||||||
# 密 码
|
|
||||||
PASSWORD = 'root'
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Venv 安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python -m venv venv
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 运行项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 初 始 化 数 据 库
|
|
||||||
python test\init_databases.py
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
执行 flask run 命令启动项目
|
|
||||||
|
|
||||||
|
|
||||||
#### 预览项目
|
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---------------------|---------------------|
|
|---------------------|---------------------|
|
||||||
|  |  |
|
|  |  |
|
||||||
| |  |
|
| |  |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
|
## 内置功能
|
||||||
|
|
||||||
|
- [x] 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
|
- [x] 权限管理:配置系统菜单,操作权限,按钮权限标识等。
|
||||||
|
- [x] 角色管理:角色菜单权限分配。
|
||||||
|
- [x] 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||||
|
- [x] 登录日志:系统登录日志记录查询包含登录异常。
|
||||||
|
- [x] 文件上传: 图片上传示例
|
||||||
|
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
正在编写
|
||||||
|
|
||||||
|
|
||||||
|
## 安装使用
|
||||||
|
|
||||||
|
+ 下载源码
|
||||||
|
```bash
|
||||||
|
git clone https://gitee.com/pear-admin/pear-admin-flask
|
||||||
|
|
||||||
|
# 进入 pear-admin-flask 代码根目录
|
||||||
|
cd pear-admin-flask
|
||||||
|
|
||||||
|
# 切换分支
|
||||||
|
git checkout mini
|
||||||
|
```
|
||||||
|
|
||||||
|
+ 安装依赖
|
||||||
|
```bash
|
||||||
|
# 创建虚拟环境
|
||||||
|
python -m venv venv
|
||||||
|
|
||||||
|
# 然后使虚拟环境生效(windows)
|
||||||
|
venv\Scripts\activate
|
||||||
|
# source venv/bin/activate # (Linux激活虚拟环境)
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
pip install -r requirement.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
+ 数据迁移
|
||||||
|
|
||||||
|
默认的使用 `sqlite3` 作为测试环境的数据库进行演示,不需要按照mysql即可查看演示。如果需要二次开发,建议改成 `mysql` 。
|
||||||
|
|
||||||
|
如果需要在开发环境使用 mysql 作为数据库,请查看 `applications/configs/config.py` 文件里面的相关配置文件, 注释掉 sqlite 的配置即可
|
||||||
|
|
||||||
|
如果需要修改数据的配置信息,请在 `.flaskenv` 里面调整即可
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask db init
|
||||||
|
flask db migrate -m '数据初始化'
|
||||||
|
flask db upgrade
|
||||||
|
|
||||||
|
flask init-db
|
||||||
|
```
|
||||||
|
|
||||||
|
+ 项目启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git 贡献提交规范
|
||||||
|
|
||||||
|
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||||
|
- `feat` 增加新功能
|
||||||
|
- `fix` 修复问题/BUG
|
||||||
|
- `style` 代码风格相关无影响运行结果的
|
||||||
|
- `perf` 优化/性能提升
|
||||||
|
- `refactor` 重构
|
||||||
|
- `revert` 撤销修改
|
||||||
|
- `test` 测试相关
|
||||||
|
- `docs` 文档/注释
|
||||||
|
- `chore` 依赖更新/脚手架配置修改等
|
||||||
|
- `workflow` 工作流改进
|
||||||
|
- `ci` 持续集成
|
||||||
|
- `types` 类型定义文件更改
|
||||||
|
- `wip` 开发中
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
from applications import create_app
|
|
||||||
|
|
||||||
app = create_app()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run()
|
|
||||||
+28
-14
@@ -1,35 +1,49 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask, Blueprint
|
||||||
from flask_uploads import configure_uploads
|
|
||||||
|
|
||||||
from applications.common.utils.upload import photos
|
import config
|
||||||
from applications.configs import common
|
|
||||||
from applications.extensions import init_plugs
|
|
||||||
from applications.view import init_view
|
from applications.view import init_view
|
||||||
from applications.configs import config
|
from common import register_api
|
||||||
|
from common.flask_uploads import configure_uploads
|
||||||
|
from common.utils.upload import photos
|
||||||
|
from extensions import init_plugs
|
||||||
|
|
||||||
|
api_bp: Blueprint = Blueprint('api', __name__, url_prefix='/api/v1')
|
||||||
|
|
||||||
|
from .rights import register_rights_api
|
||||||
|
from .system import register_sys_api
|
||||||
|
from .users import register_users_api
|
||||||
|
|
||||||
|
register_rights_api(api_bp)
|
||||||
|
register_users_api(api_bp)
|
||||||
|
register_sys_api(api_bp)
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_name=None):
|
def init_api(app: Flask) -> None:
|
||||||
app = Flask(__name__)
|
app.register_blueprint(api_bp)
|
||||||
|
|
||||||
if not config_name:
|
|
||||||
# 尝试从本地环境中读取
|
def create_app() -> Flask:
|
||||||
config_name = os.getenv('FLASK_CONFIG', 'development')
|
app = Flask('pear-admin-flask')
|
||||||
|
|
||||||
# 引入数据库配置
|
# 引入数据库配置
|
||||||
app.config.from_object(common)
|
app.config.from_object(config)
|
||||||
app.config.from_object(config[config_name])
|
|
||||||
# 注册各种插件
|
# 注册各种插件
|
||||||
init_plugs(app)
|
init_plugs(app)
|
||||||
|
|
||||||
# 注册路由
|
# 注册路由
|
||||||
init_view(app)
|
init_view(app)
|
||||||
|
|
||||||
|
# 注册接口(restful api)
|
||||||
|
init_api(app)
|
||||||
|
|
||||||
# 文件上传
|
# 文件上传
|
||||||
configure_uploads(app, photos)
|
configure_uploads(app, photos)
|
||||||
|
|
||||||
logo()
|
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
|
||||||
|
logo()
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import Dept, DeptSchema
|
|
||||||
from applications.models import User
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_dept_dict():
|
|
||||||
dept = Dept.query.order_by(Dept.sort).all()
|
|
||||||
res = model_to_dicts(Schema=DeptSchema, model=dept)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def save_dept(req):
|
|
||||||
address = xss_escape(req.get("address"))
|
|
||||||
deptName = xss_escape(req.get("deptName"))
|
|
||||||
email = xss_escape(req.get("email"))
|
|
||||||
leader = xss_escape(req.get("leader"))
|
|
||||||
parentId = xss_escape(req.get("parentId"))
|
|
||||||
phone = xss_escape(req.get("phone"))
|
|
||||||
sort = xss_escape(req.get("sort"))
|
|
||||||
status = xss_escape(req.get("status"))
|
|
||||||
dept = Dept(
|
|
||||||
parent_id=parentId,
|
|
||||||
dept_name=deptName,
|
|
||||||
sort=sort,
|
|
||||||
leader=leader,
|
|
||||||
phone=phone,
|
|
||||||
email=email,
|
|
||||||
status=status,
|
|
||||||
address=address
|
|
||||||
)
|
|
||||||
r = db.session.add(dept)
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def get_dept_by_id(id):
|
|
||||||
d = Dept.query.filter_by(id=id).first()
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
# 启动权限
|
|
||||||
def enable_status(id):
|
|
||||||
enable = 1
|
|
||||||
d = Dept.query.filter_by(id=id).update({"status": enable})
|
|
||||||
if d:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 停用权限
|
|
||||||
def disable_status(id):
|
|
||||||
enable = 0
|
|
||||||
d = Dept.query.filter_by(id=id).update({"status": enable})
|
|
||||||
if d:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def update_dept(json):
|
|
||||||
id = json.get("deptId"),
|
|
||||||
data = {
|
|
||||||
"dept_name": xss_escape(json.get("deptName")),
|
|
||||||
"sort": xss_escape(json.get("sort")),
|
|
||||||
"leader": xss_escape(json.get("leader")),
|
|
||||||
"phone": xss_escape(json.get("phone")),
|
|
||||||
"email": xss_escape(json.get("email")),
|
|
||||||
"status": xss_escape(json.get("status")),
|
|
||||||
"address": xss_escape(json.get("address"))
|
|
||||||
}
|
|
||||||
d = Dept.query.filter_by(id=id).update(data)
|
|
||||||
if not d:
|
|
||||||
return False
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def remove_dept(id):
|
|
||||||
d = Dept.query.filter_by(id=id).delete()
|
|
||||||
if not d:
|
|
||||||
return False
|
|
||||||
User.query.filter_by(dept_id=id).update({"dept_id": None})
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import DictType, DictData, DictTypeSchema, DictDataSchema
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_dict(typecode: str):
|
|
||||||
dict_list = []
|
|
||||||
if DictType.query.filter_by(type_code=typecode, enable=1).first():
|
|
||||||
dicts = DictData.query.filter_by(type_code=typecode, enable=1).all()
|
|
||||||
for d in dicts:
|
|
||||||
dict_dict = {"key": d.data_label, "value": d.data_value}
|
|
||||||
dict_list.append(dict_dict)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
return dict_list
|
|
||||||
|
|
||||||
|
|
||||||
def get_dict_type(page, limit, type_name):
|
|
||||||
dict_all = DictType.query
|
|
||||||
if type_name:
|
|
||||||
dict_all = dict_all.filter(DictType.type_name.like('%' + type_name + '%'))
|
|
||||||
dict_all = dict_all.paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
count = DictType.query.count()
|
|
||||||
data = model_to_dicts(Schema=DictTypeSchema, model=dict_all.items)
|
|
||||||
return data, count
|
|
||||||
|
|
||||||
|
|
||||||
def get_dict_data(page, limit, type_code):
|
|
||||||
dict_all = DictData.query.filter_by(type_code=type_code).paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
count = DictType.query.count()
|
|
||||||
dict_dict = model_to_dicts(Schema=DictDataSchema, model=dict_all.items)
|
|
||||||
return dict_dict, count
|
|
||||||
|
|
||||||
|
|
||||||
# 增加 dict type
|
|
||||||
def save_dict_type(req_json):
|
|
||||||
description = xss_escape(req_json.get("description"))
|
|
||||||
enable = xss_escape(req_json.get("enable"))
|
|
||||||
type_code = xss_escape(req_json.get("typeCode"))
|
|
||||||
type_name = xss_escape(req_json.get("typeName"))
|
|
||||||
d = DictType(type_name=type_name, type_code=type_code, enable=enable, description=description)
|
|
||||||
db.session.add(d)
|
|
||||||
db.session.commit()
|
|
||||||
return d.id
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典类型
|
|
||||||
def update_dict_type(req_json):
|
|
||||||
id = xss_escape(req_json.get("id"))
|
|
||||||
description = xss_escape(req_json.get("description"))
|
|
||||||
enable = xss_escape(req_json.get("enable"))
|
|
||||||
type_code = xss_escape(req_json.get("typeCode"))
|
|
||||||
type_name = xss_escape(req_json.get("typeName"))
|
|
||||||
DictType.query.filter_by(id=id).update({
|
|
||||||
"description": description,
|
|
||||||
"enable": enable,
|
|
||||||
"type_code": type_code,
|
|
||||||
"type_name": type_name
|
|
||||||
})
|
|
||||||
db.session.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def enable_dict_type_status(id):
|
|
||||||
enable = 1
|
|
||||||
res = DictType.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if res:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def disable_dict_type_status(id):
|
|
||||||
enable = 0
|
|
||||||
res = DictType.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if res:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 删除字典类型
|
|
||||||
def delete_type_by_id(id):
|
|
||||||
type_code = DictType.query.filter_by(id=id).first().type_code
|
|
||||||
DictData.query.filter_by(type_code=type_code).delete()
|
|
||||||
res = DictType.query.filter_by(id=id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
# 增加dictdata
|
|
||||||
def save_dict_data(req_json):
|
|
||||||
data_label = xss_escape(req_json.get("dataLabel"))
|
|
||||||
data_value = xss_escape(req_json.get("dataValue"))
|
|
||||||
enable = xss_escape(req_json.get("enable"))
|
|
||||||
remark = xss_escape(req_json.get("remark"))
|
|
||||||
type_code = xss_escape(req_json.get("typeCode"))
|
|
||||||
d = DictData(data_label=data_label, data_value=data_value, enable=enable, remark=remark, type_code=type_code)
|
|
||||||
db.session.add(d)
|
|
||||||
db.session.commit()
|
|
||||||
return d.id
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典数据
|
|
||||||
def update_dict_data(req_json):
|
|
||||||
id = req_json.get("dataId")
|
|
||||||
DictData.query.filter_by(id=id).update({
|
|
||||||
"data_label": xss_escape(req_json.get("dataLabel")),
|
|
||||||
"data_value": xss_escape(req_json.get("dataValue")),
|
|
||||||
"enable": xss_escape(req_json.get("enable")),
|
|
||||||
"remark": xss_escape(req_json.get("remark")),
|
|
||||||
"type_code": xss_escape(req_json.get("typeCode"))
|
|
||||||
})
|
|
||||||
db.session.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def enable_dict_data_status(id):
|
|
||||||
enable = 1
|
|
||||||
res = DictData.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if res:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def disable_dict_data_status(id):
|
|
||||||
enable = 0
|
|
||||||
res = DictData.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if res:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 删除dictdata
|
|
||||||
def delete_data_by_id(id):
|
|
||||||
res = DictData.query.filter_by(id=id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return res
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import os
|
|
||||||
from flask import current_app
|
|
||||||
from sqlalchemy import desc
|
|
||||||
|
|
||||||
from applications.common.utils.upload import photos
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import Photo, PhotoSchema
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_photo(page, limit):
|
|
||||||
photo = Photo.query.order_by(desc(Photo.create_time)).paginate(page=page, per_page=limit, error_out=False)
|
|
||||||
count = Photo.query.count()
|
|
||||||
data = model_to_dicts(Schema=PhotoSchema, model=photo.items)
|
|
||||||
return data, count
|
|
||||||
|
|
||||||
|
|
||||||
def upload_one(photo, mime):
|
|
||||||
filename = photos.save(photo)
|
|
||||||
file_url = photos.url(filename)
|
|
||||||
|
|
||||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
|
||||||
size = os.path.getsize(upload_url + '/' + filename)
|
|
||||||
photo = Photo(name=filename, href=file_url, mime=mime, size=size)
|
|
||||||
db.session.add(photo)
|
|
||||||
db.session.commit()
|
|
||||||
return file_url
|
|
||||||
|
|
||||||
|
|
||||||
def delete_photo_by_id(_id):
|
|
||||||
photo_name = Photo.query.filter_by(id=_id).first().name
|
|
||||||
photo = Photo.query.filter_by(id=_id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
|
||||||
os.remove(upload_url + '/' + photo_name)
|
|
||||||
return photo
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
from io import BytesIO
|
|
||||||
from flask import session, make_response, current_app
|
|
||||||
from flask_login import current_user
|
|
||||||
|
|
||||||
from applications.common.utils.gen_captcha import gen_captcha
|
|
||||||
from applications.models.admin_power import PowerSchema
|
|
||||||
|
|
||||||
|
|
||||||
# 授权路由存入session
|
|
||||||
def add_auth_session():
|
|
||||||
role = current_user.role
|
|
||||||
user_power = []
|
|
||||||
for i in role:
|
|
||||||
if i.enable == 0:
|
|
||||||
continue
|
|
||||||
for p in i.power:
|
|
||||||
if p.enable == 0:
|
|
||||||
continue
|
|
||||||
user_power.append(p.code)
|
|
||||||
session['permissions'] = user_power
|
|
||||||
|
|
||||||
|
|
||||||
# 生成菜单树
|
|
||||||
def make_menu_tree():
|
|
||||||
# power0 = Power.query.filter(
|
|
||||||
# Power.type == 0,
|
|
||||||
# ).all()
|
|
||||||
# power1 = Power.query.filter(
|
|
||||||
# Power.type == 1
|
|
||||||
# ).all()
|
|
||||||
# 获取当前用户的角色
|
|
||||||
role = current_user.role
|
|
||||||
power0 = []
|
|
||||||
power1 = []
|
|
||||||
for i in role:
|
|
||||||
# 如果角色没有被启用就直接跳过
|
|
||||||
if i.enable == 0:
|
|
||||||
continue
|
|
||||||
# 变量角色用户的权限
|
|
||||||
for p in i.power:
|
|
||||||
# 如果权限关闭了就直接跳过
|
|
||||||
if p.enable == 0:
|
|
||||||
continue
|
|
||||||
# 一级菜单
|
|
||||||
if int(p.type) == 0:
|
|
||||||
power0.append(p)
|
|
||||||
# 二级菜单
|
|
||||||
else:
|
|
||||||
power1.append(p)
|
|
||||||
|
|
||||||
power_schema = PowerSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
|
|
||||||
power0_dict = power_schema.dump(power0) # 生成可序列化对象
|
|
||||||
power1_dict = power_schema.dump(power1) # 生成可序列化对象
|
|
||||||
power0_dict = sorted(power0_dict, key=lambda i: i['sort'])
|
|
||||||
power1_dict = sorted(power1_dict, key=lambda i: i['sort'])
|
|
||||||
# print(power0)
|
|
||||||
# print(power1)
|
|
||||||
|
|
||||||
menu = []
|
|
||||||
|
|
||||||
for p0 in power0_dict:
|
|
||||||
for p1 in power1_dict:
|
|
||||||
if p0.get('id') == p1.get('parent_id'):
|
|
||||||
if p0.get("children") is None:
|
|
||||||
p0['children'] = []
|
|
||||||
p0['children'].append(p1)
|
|
||||||
menu.append(p0)
|
|
||||||
return menu
|
|
||||||
|
|
||||||
|
|
||||||
# 生成验证码
|
|
||||||
def get_captcha():
|
|
||||||
code, image = gen_captcha()
|
|
||||||
out = BytesIO()
|
|
||||||
session["code"] = code
|
|
||||||
image.save(out, 'png')
|
|
||||||
out.seek(0)
|
|
||||||
resp = make_response(out.read())
|
|
||||||
resp.content_type = 'image/png'
|
|
||||||
return resp, code
|
|
||||||
|
|
||||||
|
|
||||||
def get_render_config():
|
|
||||||
# 网站配置
|
|
||||||
config = dict(logo={
|
|
||||||
# 网站名称
|
|
||||||
"title": current_app.config.get("SYSTEM_NAME"),
|
|
||||||
# 网站图标
|
|
||||||
"image": "/static/admin/admin/images/logo.png"
|
|
||||||
# 菜单配置
|
|
||||||
}, menu={
|
|
||||||
# 菜单数据来源
|
|
||||||
"data": "/rights/menu",
|
|
||||||
"collaspe": True,
|
|
||||||
# 是否同时只打开一个菜单目录
|
|
||||||
"accordion": True,
|
|
||||||
"method": "GET",
|
|
||||||
# 是否开启多系统菜单模式
|
|
||||||
"control": False,
|
|
||||||
# 默认选中的菜单项
|
|
||||||
"select": "0",
|
|
||||||
# 是否开启异步菜单,false 时 data 属性设置为菜单数据,false 时为 json 文件或后端接口
|
|
||||||
"async": True
|
|
||||||
}, tab={
|
|
||||||
# 是否开启多选项卡
|
|
||||||
"muiltTab": True,
|
|
||||||
# 切换选项卡时,是否刷新页面状态
|
|
||||||
"keepState": True,
|
|
||||||
# 是否开启 Tab 记忆
|
|
||||||
"session": True,
|
|
||||||
# 最大可打开的选项卡数量
|
|
||||||
"tabMax": 30,
|
|
||||||
"index": {
|
|
||||||
# 标识 ID , 建议与菜单项中的 ID 一致
|
|
||||||
"id": "10",
|
|
||||||
# 页面地址
|
|
||||||
"href": "/admin/welcome",
|
|
||||||
# 标题
|
|
||||||
"title": "首页"
|
|
||||||
}
|
|
||||||
}, theme={
|
|
||||||
# 默认主题色,对应 colors 配置中的 ID 标识
|
|
||||||
"defaultColor": "2",
|
|
||||||
# 默认的菜单主题 dark-theme 黑 / light-theme 白
|
|
||||||
"defaultMenu": "dark-theme",
|
|
||||||
# 是否允许用户切换主题,false 时关闭自定义主题面板
|
|
||||||
"allowCustom": True
|
|
||||||
}, colors=[{
|
|
||||||
"id": "1",
|
|
||||||
"color": "#2d8cf0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "2",
|
|
||||||
"color": "#5FB878"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "3",
|
|
||||||
"color": "#1E9FFF"
|
|
||||||
}, {
|
|
||||||
"id": "4",
|
|
||||||
"color": "#FFB800"
|
|
||||||
}, {
|
|
||||||
"id": "5",
|
|
||||||
"color": "darkgray"
|
|
||||||
}
|
|
||||||
], links=current_app.config.get("SYSTEM_PANEL_LINKS"), other={
|
|
||||||
# 主页动画时长
|
|
||||||
"keepLoad": 1200,
|
|
||||||
# 布局顶部主题
|
|
||||||
"autoHead": False
|
|
||||||
}, header=False)
|
|
||||||
return config
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models.admin_power import Power, PowerSchema2
|
|
||||||
from applications.models import Role
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_power_dict():
|
|
||||||
power = Power.query.all()
|
|
||||||
res = model_to_dicts(Schema=PowerSchema2, model=power)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
# 选择父节点
|
|
||||||
def select_parent():
|
|
||||||
power = Power.query.all()
|
|
||||||
res = model_to_dicts(Schema=PowerSchema2, model=power)
|
|
||||||
res.append({"powerId": 0, "powerName": "顶级权限", "parentId": -1})
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
# 增加权限
|
|
||||||
def save_power(req):
|
|
||||||
icon = xss_escape(req.get("icon"))
|
|
||||||
openType = xss_escape(req.get("openType"))
|
|
||||||
parentId = xss_escape(req.get("parentId"))
|
|
||||||
powerCode = xss_escape(req.get("powerCode"))
|
|
||||||
powerName = xss_escape(req.get("powerName"))
|
|
||||||
powerType = xss_escape(req.get("powerType"))
|
|
||||||
powerUrl = xss_escape(req.get("powerUrl"))
|
|
||||||
sort = xss_escape(req.get("sort"))
|
|
||||||
power = Power(
|
|
||||||
icon=icon,
|
|
||||||
open_type=openType,
|
|
||||||
parent_id=parentId,
|
|
||||||
code=powerCode,
|
|
||||||
name=powerName,
|
|
||||||
type=powerType,
|
|
||||||
url=powerUrl,
|
|
||||||
sort=sort,
|
|
||||||
enable=1
|
|
||||||
)
|
|
||||||
r = db.session.add(power)
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 根据id查询权限
|
|
||||||
def get_power_by_id(id):
|
|
||||||
p = Power.query.filter_by(id=id).first()
|
|
||||||
return p
|
|
||||||
|
|
||||||
|
|
||||||
# 更新权限
|
|
||||||
def update_power(req_json):
|
|
||||||
id = req_json.get("powerId")
|
|
||||||
data = {
|
|
||||||
"icon": xss_escape(req_json.get("icon")),
|
|
||||||
"open_type": xss_escape(req_json.get("openType")),
|
|
||||||
"parent_id": xss_escape(req_json.get("parentId")),
|
|
||||||
"code": xss_escape(req_json.get("powerCode")),
|
|
||||||
"name": xss_escape(req_json.get("powerName")),
|
|
||||||
"type": xss_escape(req_json.get("powerType")),
|
|
||||||
"url": xss_escape(req_json.get("powerUrl")),
|
|
||||||
"sort": xss_escape(req_json.get("sort"))
|
|
||||||
}
|
|
||||||
# print(data)
|
|
||||||
power = Power.query.filter_by(id=id).update(data)
|
|
||||||
db.session.commit()
|
|
||||||
# print(power)
|
|
||||||
return power
|
|
||||||
|
|
||||||
|
|
||||||
# 启动权限
|
|
||||||
def enable_status(id):
|
|
||||||
enable = 1
|
|
||||||
user = Power.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if user:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 停用权限
|
|
||||||
def disable_status(id):
|
|
||||||
enable = 0
|
|
||||||
user = Power.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if user:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 删除权限(目前没有判断父节点自动删除子节点)
|
|
||||||
def remove_power(id):
|
|
||||||
power = Power.query.filter_by(id=id).first()
|
|
||||||
role_id_list = []
|
|
||||||
roles = power.role
|
|
||||||
for role in roles:
|
|
||||||
role_id_list.append(role.id)
|
|
||||||
roles = Role.query.filter(Role.id.in_(role_id_list)).all()
|
|
||||||
for p in roles:
|
|
||||||
power.role.remove(p)
|
|
||||||
r = Power.query.filter_by(id=id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除权限
|
|
||||||
def batch_remove(ids):
|
|
||||||
for id in ids:
|
|
||||||
remove_power(id)
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
from sqlalchemy import and_
|
|
||||||
|
|
||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import Role, RoleSchema
|
|
||||||
from applications.models.admin_power import Power, PowerSchema2
|
|
||||||
from applications.models import User
|
|
||||||
|
|
||||||
# 获取角色对象
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_role_data(page, limit, filters):
|
|
||||||
role = Role.query.filter(and_(*[getattr(Role, k).like(v) for k, v in filters.items()])).paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
count = Role.query.count()
|
|
||||||
return role, count
|
|
||||||
|
|
||||||
|
|
||||||
# 获取角色dict
|
|
||||||
def get_role_data_dict(page, limit, filters):
|
|
||||||
role, count = get_role_data(page, limit, filters)
|
|
||||||
data = model_to_dicts(Schema=RoleSchema, model=role.items)
|
|
||||||
return data, count
|
|
||||||
|
|
||||||
|
|
||||||
# 增加角色
|
|
||||||
def add_role(req):
|
|
||||||
details = xss_escape(req.get("details"))
|
|
||||||
enable = xss_escape(req.get("enable"))
|
|
||||||
roleCode = xss_escape(req.get("roleCode"))
|
|
||||||
roleName = xss_escape(req.get("roleName"))
|
|
||||||
sort = xss_escape(req.get("sort"))
|
|
||||||
role = Role(
|
|
||||||
details=details,
|
|
||||||
enable=enable,
|
|
||||||
code=roleCode,
|
|
||||||
name=roleName,
|
|
||||||
sort=sort
|
|
||||||
)
|
|
||||||
db.session.add(role)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
# 通过id获取角色
|
|
||||||
def get_role_by_id(id):
|
|
||||||
r = Role.query.filter_by(id=id).first()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 更新角色
|
|
||||||
def update_role(req_json):
|
|
||||||
id = req_json.get("roleId")
|
|
||||||
data = {
|
|
||||||
"code": xss_escape(req_json.get("roleCode")),
|
|
||||||
"name": xss_escape(req_json.get("roleName")),
|
|
||||||
"sort": xss_escape(req_json.get("sort")),
|
|
||||||
"enable": xss_escape(req_json.get("enable")),
|
|
||||||
"details": xss_escape(req_json.get("details"))
|
|
||||||
}
|
|
||||||
role = Role.query.filter_by(id=id).update(data)
|
|
||||||
db.session.commit()
|
|
||||||
return role
|
|
||||||
|
|
||||||
|
|
||||||
# 获取角色的权限
|
|
||||||
def get_role_power(id):
|
|
||||||
role = Role.query.filter_by(id=id).first()
|
|
||||||
check_powers = role.power
|
|
||||||
check_powers_list = []
|
|
||||||
for cp in check_powers:
|
|
||||||
check_powers_list.append(cp.id)
|
|
||||||
powers = Power.query.all()
|
|
||||||
power_schema = PowerSchema2(many=True) # 用已继承ma.ModelSchema类的自定制类生成序列化类
|
|
||||||
output = power_schema.dump(powers) # 生成可序列化对象
|
|
||||||
for i in output:
|
|
||||||
if int(i.get("powerId")) in check_powers_list:
|
|
||||||
i["checkArr"] = "1"
|
|
||||||
else:
|
|
||||||
i["checkArr"] = "0"
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
# 更新角色权限
|
|
||||||
def update_role_power(id, power_list):
|
|
||||||
role = Role.query.filter_by(id=id).first()
|
|
||||||
power_id_list = []
|
|
||||||
for p in role.power:
|
|
||||||
power_id_list.append(p.id)
|
|
||||||
# print(p.id)
|
|
||||||
# print(power_id_list)
|
|
||||||
powers = Power.query.filter(Power.id.in_(power_id_list)).all()
|
|
||||||
for p in powers:
|
|
||||||
role.power.remove(p)
|
|
||||||
powers = Power.query.filter(Power.id.in_(power_list)).all()
|
|
||||||
for p in powers:
|
|
||||||
role.power.append(p)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
# 启动角色
|
|
||||||
def enable_status(id):
|
|
||||||
enable = 1
|
|
||||||
role = Role.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if role:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 停用角色
|
|
||||||
def disable_status(id):
|
|
||||||
enable = 0
|
|
||||||
role = Role.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if role:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 删除角色
|
|
||||||
def remove_role(id):
|
|
||||||
role = Role.query.filter_by(id=id).first()
|
|
||||||
# 删除该角色的权限
|
|
||||||
power_id_list = []
|
|
||||||
for p in role.power:
|
|
||||||
power_id_list.append(p.id)
|
|
||||||
|
|
||||||
powers = Power.query.filter(Power.id.in_(power_id_list)).all()
|
|
||||||
for p in powers:
|
|
||||||
role.power.remove(p)
|
|
||||||
user_id_list = []
|
|
||||||
for u in role.user:
|
|
||||||
user_id_list.append(u.id)
|
|
||||||
users = User.query.filter(User.id.in_(user_id_list)).all()
|
|
||||||
for u in users:
|
|
||||||
role.user.remove(u)
|
|
||||||
r = Role.query.filter_by(id=id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除
|
|
||||||
def batch_remove(ids):
|
|
||||||
# role = Role.query.filter(Role.id.in_(ids)).delete(synchronize_session=False)
|
|
||||||
# db.session.commit()
|
|
||||||
for id in ids:
|
|
||||||
remove_role(id)
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
from flask import jsonify
|
|
||||||
from flask_login import current_user
|
|
||||||
from sqlalchemy import and_, desc
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import User, UserSchema
|
|
||||||
from applications.models import Role
|
|
||||||
from applications.models import AdminLog
|
|
||||||
|
|
||||||
# 获取用户的 sqlalchemy 对象分页器
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_data(page, limit, filters, deptId):
|
|
||||||
if deptId:
|
|
||||||
user = User.query.filter_by(dept_id=deptId).filter(
|
|
||||||
and_(*[getattr(User, k).like(v) for k, v in filters.items()])).paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
else:
|
|
||||||
user = User.query.filter(and_(*[getattr(User, k).like(v) for k, v in filters.items()])).paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
count = User.query.count()
|
|
||||||
return user, count
|
|
||||||
|
|
||||||
|
|
||||||
# 获取用户的dict数据分页器
|
|
||||||
def get_user_data_dict(page, limit, filters, deptId):
|
|
||||||
user, count = get_user_data(page, limit, filters, deptId)
|
|
||||||
data = model_to_dicts(Schema=UserSchema, model=user.items)
|
|
||||||
return data, count
|
|
||||||
|
|
||||||
|
|
||||||
# 通过名称获取用户
|
|
||||||
def get_user_by_name(username):
|
|
||||||
return User.query.filter_by(username=username).first()
|
|
||||||
|
|
||||||
|
|
||||||
# 获取当前用户日志
|
|
||||||
def get_current_user_logs():
|
|
||||||
log = AdminLog.query.filter_by(url='/admin/login').filter_by(uid=current_user.id).order_by(
|
|
||||||
desc(AdminLog.create_time)).limit(10)
|
|
||||||
return log
|
|
||||||
|
|
||||||
|
|
||||||
# 判断用户是否存在
|
|
||||||
def is_user_exists(username):
|
|
||||||
res = User.query.filter_by(username=username).count()
|
|
||||||
return bool(res)
|
|
||||||
|
|
||||||
|
|
||||||
# 增加用户
|
|
||||||
def add_user(username, realName, password):
|
|
||||||
user = User(username=username, realname=realName)
|
|
||||||
user.set_password(password)
|
|
||||||
db.session.add(user)
|
|
||||||
db.session.commit()
|
|
||||||
return user.id
|
|
||||||
|
|
||||||
|
|
||||||
# 增加用户角色
|
|
||||||
def add_user_role(id, roles_list):
|
|
||||||
user = User.query.filter_by(id=id).first()
|
|
||||||
roles = Role.query.filter(Role.id.in_(roles_list)).all()
|
|
||||||
for r in roles:
|
|
||||||
user.role.append(r)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
# 更新用户头像
|
|
||||||
def update_avatar(url):
|
|
||||||
r = User.query.filter_by(id=current_user.id).update({"avatar": url})
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 更新用户信息
|
|
||||||
def update_user(id, username, realname, deptId):
|
|
||||||
user = User.query.filter_by(id=id).update({'username': username, 'realname': realname, 'dept_id': deptId})
|
|
||||||
db.session.commit()
|
|
||||||
return user
|
|
||||||
|
|
||||||
|
|
||||||
# 更新当前用户信息
|
|
||||||
def update_current_user_info(req_json):
|
|
||||||
r = User.query.filter_by(id=current_user.id).update(
|
|
||||||
{"realname": req_json.get("realName"), "remark": req_json.get("details")})
|
|
||||||
db.session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# 修改当前用户密码
|
|
||||||
def edit_password(res_json):
|
|
||||||
if res_json.get("newPassword") == '':
|
|
||||||
return jsonify(success=False, msg="新密码不得为空")
|
|
||||||
if res_json.get("newPassword") != res_json.get("confirmPassword"):
|
|
||||||
return jsonify(success=False, msg="俩次密码不一样")
|
|
||||||
user = current_user
|
|
||||||
is_right = user.validate_password(res_json.get("oldPassword"))
|
|
||||||
if not is_right:
|
|
||||||
return jsonify(success=False, msg="旧密码错误")
|
|
||||||
user.set_password(res_json.get("newPassword"))
|
|
||||||
db.session.add(user)
|
|
||||||
db.session.commit()
|
|
||||||
return jsonify(success=True, msg="更改成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 删除用户
|
|
||||||
def delete_by_id(id):
|
|
||||||
user = User.query.filter_by(id=id).first()
|
|
||||||
roles_id = []
|
|
||||||
for role in user.role:
|
|
||||||
roles_id.append(role.id)
|
|
||||||
roles = Role.query.filter(Role.id.in_(roles_id)).all()
|
|
||||||
for r in roles:
|
|
||||||
user.role.remove(r)
|
|
||||||
res = User.query.filter_by(id=id).delete()
|
|
||||||
db.session.commit()
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
# 启用用户
|
|
||||||
def enable_status(id):
|
|
||||||
enable = 1
|
|
||||||
user = User.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if user:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 停用用户
|
|
||||||
def disable_status(id):
|
|
||||||
enable = 0
|
|
||||||
user = User.query.filter_by(id=id).update({"enable": enable})
|
|
||||||
if user:
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除
|
|
||||||
def batch_remove(ids):
|
|
||||||
for id in ids:
|
|
||||||
delete_by_id(id)
|
|
||||||
|
|
||||||
|
|
||||||
def update_user_role(id, roles_list):
|
|
||||||
user = User.query.filter_by(id=id).first()
|
|
||||||
roles_id = []
|
|
||||||
for role in user.role:
|
|
||||||
roles_id.append(role.id)
|
|
||||||
roles = Role.query.filter(Role.id.in_(roles_id)).all()
|
|
||||||
for r in roles:
|
|
||||||
user.role.remove(r)
|
|
||||||
roles = Role.query.filter(Role.id.in_(roles_list)).all()
|
|
||||||
for r in roles:
|
|
||||||
user.role.append(r)
|
|
||||||
db.session.commit()
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
from flask_login import current_user
|
|
||||||
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import AdminLog
|
|
||||||
|
|
||||||
|
|
||||||
def login_log(request, uid, is_access):
|
|
||||||
info = {
|
|
||||||
'method': request.method,
|
|
||||||
'url': request.path,
|
|
||||||
'ip': request.remote_addr,
|
|
||||||
'user_agent': request.headers.get('User-Agent'),
|
|
||||||
'desc': request.form.get('username'),
|
|
||||||
'uid': uid,
|
|
||||||
'success': int(is_access)
|
|
||||||
|
|
||||||
}
|
|
||||||
log = AdminLog(
|
|
||||||
url=info.get('url'),
|
|
||||||
ip=info.get('ip'),
|
|
||||||
user_agent=info.get('user_agent'),
|
|
||||||
desc=info.get('desc'),
|
|
||||||
uid=info.get('uid'),
|
|
||||||
method=info.get('method'),
|
|
||||||
success=info.get('success')
|
|
||||||
)
|
|
||||||
db.session.add(log)
|
|
||||||
db.session.flush()
|
|
||||||
db.session.commit()
|
|
||||||
return log.id
|
|
||||||
|
|
||||||
|
|
||||||
def admin_log(request, is_access):
|
|
||||||
info = {
|
|
||||||
'method': request.method,
|
|
||||||
'url': request.path,
|
|
||||||
'ip': request.remote_addr,
|
|
||||||
'user_agent': request.headers.get('User-Agent'),
|
|
||||||
'desc': str(dict(request.values)),
|
|
||||||
'uid': current_user.id,
|
|
||||||
'success': int(is_access)
|
|
||||||
|
|
||||||
}
|
|
||||||
log = AdminLog(
|
|
||||||
url=info.get('url'),
|
|
||||||
ip=info.get('ip'),
|
|
||||||
user_agent=info.get('user_agent'),
|
|
||||||
desc=info.get('desc'),
|
|
||||||
uid=info.get('uid'),
|
|
||||||
method=info.get('method'),
|
|
||||||
success=info.get('success')
|
|
||||||
)
|
|
||||||
db.session.add(log)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
return log.id
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
def model_to_dicts(Schema, model):
|
|
||||||
# 如果是分页器返回,需要传入model.items
|
|
||||||
common_schema = Schema(many=True) # 用已继承ma.ModelSchema类的自定制类生成序列化类
|
|
||||||
output = common_schema.dump(model) # 生成可序列化对象
|
|
||||||
return output
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#
|
|
||||||
MYSQL_HOST = '127.0.0.1'
|
|
||||||
MYSQL_PORT = '3306'
|
|
||||||
MYSQL_DATABASE = 'PearAdminFlask'
|
|
||||||
MYSQL_USERNAME = 'root'
|
|
||||||
MYSQL_PASSWORD = 'root'
|
|
||||||
|
|
||||||
MYSQL_DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(username=USERNAME,
|
|
||||||
password=PASSWORD,
|
|
||||||
host=HOST,
|
|
||||||
port=PORT,
|
|
||||||
db=DATABASE)
|
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = MYSQL_DB_URI
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
|
||||||
SQLALCHEMY_ECHO = False
|
|
||||||
SQLALCHEMY_POOL_RECYCLE = 8
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from captcha.image import ImageCaptcha
|
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
from random import choices
|
|
||||||
|
|
||||||
|
|
||||||
def gen_captcha(content='0123456789'):
|
|
||||||
""" 生成验证码 """
|
|
||||||
image = ImageCaptcha()
|
|
||||||
# 获取字符串
|
|
||||||
captcha_text = "".join(choices(content, k=4))
|
|
||||||
# 生成图像
|
|
||||||
captcha_image = Image.open(image.generate(captcha_text))
|
|
||||||
return captcha_text, captcha_image
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
from flask import jsonify
|
|
||||||
|
|
||||||
|
|
||||||
def success_api(msg: str = "成功"):
|
|
||||||
""" 成功响应 默认值”成功“ """
|
|
||||||
return jsonify(success=True, msg=msg)
|
|
||||||
|
|
||||||
|
|
||||||
def fail_api(msg: str = "失败"):
|
|
||||||
""" 失败响应 默认值“失败” """
|
|
||||||
return jsonify(success=False, msg=msg)
|
|
||||||
|
|
||||||
|
|
||||||
def table_api(msg: str = "", count=0, data=None, limit=10):
|
|
||||||
""" 动态表格渲染响应 """
|
|
||||||
res = {
|
|
||||||
'msg': msg,
|
|
||||||
'code': 0,
|
|
||||||
'data': data,
|
|
||||||
'count': count,
|
|
||||||
'limit': limit
|
|
||||||
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
from functools import wraps
|
|
||||||
from flask import abort, request, jsonify, session
|
|
||||||
from flask_login import login_required
|
|
||||||
from applications.common.admin_log import admin_log
|
|
||||||
|
|
||||||
|
|
||||||
def authorize(power: str, log: bool = False):
|
|
||||||
def decorator(func):
|
|
||||||
@login_required
|
|
||||||
@wraps(func)
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
if not power in session.get('permissions'):
|
|
||||||
if log:
|
|
||||||
admin_log(request=request, is_access=False)
|
|
||||||
if request.method == 'GET':
|
|
||||||
abort(403)
|
|
||||||
else:
|
|
||||||
return jsonify(success=False, msg="权限不足!")
|
|
||||||
if log:
|
|
||||||
admin_log(request=request, is_access=True)
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
return decorator
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
from flask_uploads import UploadSet, IMAGES
|
|
||||||
|
|
||||||
|
|
||||||
photos = UploadSet('photos', IMAGES)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# xss过滤
|
|
||||||
from flask import abort, make_response, jsonify
|
|
||||||
|
|
||||||
|
|
||||||
def xss_escape(s: str):
|
|
||||||
if s is None:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return s.replace("&", "&").replace(">", ">").replace("<", "<").replace("'", "'").replace('"',
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def check_data(schema, data):
|
|
||||||
errors = schema.validate(data)
|
|
||||||
for k, v in errors.items():
|
|
||||||
for i in v:
|
|
||||||
# print("{}{}".format(k, i))
|
|
||||||
msg = "{}{}".format(k, i)
|
|
||||||
if errors:
|
|
||||||
abort(make_response(jsonify(result=False, msg=msg), 200))
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
from .config import config
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
SYSTEM_NAME = "Pear Admin"
|
|
||||||
# 主题面板的链接列表配置
|
|
||||||
SYSTEM_PANEL_LINKS = [
|
|
||||||
{
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"title": "官方网站",
|
|
||||||
"href": "http://www.pearadmin.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"title": "开发文档",
|
|
||||||
"href": "http://www.pearadmin.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon": "layui-icon layui-icon-auz",
|
|
||||||
"title": "开源地址",
|
|
||||||
"href": "https://gitee.com/Jmysy/Pear-Admin-Layui"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
UPLOADED_PHOTOS_DEST = 'static/upload'
|
|
||||||
UPLOADED_FILES_ALLOW = ['gif', 'jpg']
|
|
||||||
# JSON配置
|
|
||||||
JSON_AS_ASCII = False
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class BaseConfig:
|
|
||||||
SECRET_KEY = os.getenv('SECRET_KEY', 'dev key')
|
|
||||||
|
|
||||||
# redis配置
|
|
||||||
REDIS_HOST = os.getenv('REDIS_HOST') or "127.0.0.1"
|
|
||||||
REDIS_PORT = int(os.getenv('REDIS_PORT') or 6379)
|
|
||||||
|
|
||||||
# mysql 配置
|
|
||||||
MYSQL_USERNAME = os.getenv('MYSQL_USERNAME') or "root"
|
|
||||||
MYSQL_PASSWORD = os.getenv('MYSQL_PASSWORD') or "123456"
|
|
||||||
MYSQL_HOST = os.getenv('MYSQL_HOST') or "127.0.0.1"
|
|
||||||
MYSQL_PORT = int(os.getenv('MYSQL_PORT') or 3306)
|
|
||||||
MYSQL_DATABASE = os.getenv('MYSQL_DATABASE') or "PearAdminFlask"
|
|
||||||
|
|
||||||
UPLOADED_PHOTOS_DEST = '/static'
|
|
||||||
|
|
||||||
# mysql 数据库的配置信息
|
|
||||||
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{MYSQL_PASSWORD}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}"
|
|
||||||
# 默认日志等级
|
|
||||||
LOG_LEVEL = logging.WARN
|
|
||||||
|
|
||||||
|
|
||||||
class TestingConfig(BaseConfig):
|
|
||||||
""" 测试配置 """
|
|
||||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:' # 内存数据库
|
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentConfig(BaseConfig):
|
|
||||||
""" 开发配置 """
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
|
||||||
SQLALCHEMY_ECHO = False
|
|
||||||
|
|
||||||
|
|
||||||
class ProductionConfig(BaseConfig):
|
|
||||||
"""生成环境配置"""
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
||||||
SQLALCHEMY_ECHO = False
|
|
||||||
SQLALCHEMY_POOL_RECYCLE = 8
|
|
||||||
|
|
||||||
LOG_LEVEL = logging.ERROR
|
|
||||||
|
|
||||||
|
|
||||||
config = {
|
|
||||||
'development': DevelopmentConfig,
|
|
||||||
'testing': TestingConfig,
|
|
||||||
'production': ProductionConfig
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
from flask_debugtoolbar import DebugToolbarExtension
|
|
||||||
|
|
||||||
|
|
||||||
def init_debug_tool(app: Flask):
|
|
||||||
toolbar = DebugToolbarExtension()
|
|
||||||
toolbar.init_app(app)
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
from flask_marshmallow import Marshmallow
|
|
||||||
from marshmallow import fields
|
|
||||||
from marshmallow.validate import (
|
|
||||||
URL, Email, Range, Length, Equal, Regexp,
|
|
||||||
Predicate, NoneOf, OneOf, ContainsOnly
|
|
||||||
)
|
|
||||||
|
|
||||||
URL.default_message = '无效的链接'
|
|
||||||
Email.default_message = '无效的邮箱地址'
|
|
||||||
Range.message_min = '不能小于{min}'
|
|
||||||
Range.message_max = '不能小于{max}'
|
|
||||||
Range.message_all = '不能超过{min}和{max}这个范围'
|
|
||||||
Length.message_min = '长度不得小于{min}位'
|
|
||||||
Length.message_max = '长度不得大于{max}位'
|
|
||||||
Length.message_all = '长度不能超过{min}和{max}这个范围'
|
|
||||||
Length.message_equal = '长度必须等于{equal}位'
|
|
||||||
Equal.default_message = '必须等于{other}'
|
|
||||||
Regexp.default_message = '非法输入'
|
|
||||||
Predicate.default_message = '非法输入'
|
|
||||||
NoneOf.default_message = '非法输入'
|
|
||||||
OneOf.default_message = '无效的选择'
|
|
||||||
ContainsOnly.default_message = '一个或多个无效的选择'
|
|
||||||
|
|
||||||
fields.Field.default_error_messages = {
|
|
||||||
"required": "缺少必要数据",
|
|
||||||
"null": "数据不能为空",
|
|
||||||
"validator_failed": "非法数据",
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.Str.default_error_messages = {
|
|
||||||
'invalid': "不是合法文本"
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.Int.default_error_messages = {
|
|
||||||
"invalid": "不是合法整数"
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.Number.default_error_messages = {
|
|
||||||
"invalid": "不是合法数字"
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.Boolean.default_error_messages = {
|
|
||||||
"invalid": "不是合法布尔值"
|
|
||||||
}
|
|
||||||
|
|
||||||
db = SQLAlchemy()
|
|
||||||
ma = Marshmallow()
|
|
||||||
|
|
||||||
|
|
||||||
def init_databases(app: Flask):
|
|
||||||
db.init_app(app)
|
|
||||||
ma.init_app(app)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from .admin_dept import Dept, DeptSchema
|
|
||||||
from .admin_dict import DictType, DictData, DictTypeSchema, DictDataSchema
|
|
||||||
from .admin_log import AdminLog, LogSchema
|
|
||||||
from .admin_photo import Photo, PhotoSchema
|
|
||||||
from .admin_power import Power, PowerSchema, PowerSchema2
|
|
||||||
from .admin_role import Role, RoleSchema
|
|
||||||
from .admin_role_power import role_power
|
|
||||||
from .admin_user import User, UserSchema
|
|
||||||
from .admin_user_role import user_role
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import datetime
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields, validate
|
|
||||||
|
|
||||||
|
|
||||||
class Dept(db.Model):
|
|
||||||
__tablename__ = 'admin_dept'
|
|
||||||
id = db.Column(db.Integer, primary_key=True, comment="部门ID")
|
|
||||||
parent_id = db.Column(db.Integer, comment="父级编号")
|
|
||||||
dept_name = db.Column(db.String(50), comment="部门名称")
|
|
||||||
sort = db.Column(db.Integer, comment="排序")
|
|
||||||
leader = db.Column(db.String(50), comment="负责人")
|
|
||||||
phone = db.Column(db.String(20), comment="联系方式")
|
|
||||||
email = db.Column(db.String(50), comment="邮箱")
|
|
||||||
status = db.Column(db.Integer, comment='状态(1开启,0关闭)')
|
|
||||||
remark = db.Column(db.Text, comment="备注")
|
|
||||||
address = db.Column(db.String(255), comment="详细地址")
|
|
||||||
create_at = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_at = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间')
|
|
||||||
|
|
||||||
|
|
||||||
class DeptSchema(ma.Schema): # 序列化类
|
|
||||||
deptId = fields.Integer(attribute="id")
|
|
||||||
parentId = fields.Integer(attribute="parent_id")
|
|
||||||
deptName = fields.Str(attribute="dept_name")
|
|
||||||
leader = fields.Str()
|
|
||||||
phone = fields.Str()
|
|
||||||
email = fields.Str(validate=validate.Email())
|
|
||||||
address = fields.Str()
|
|
||||||
status = fields.Str(validate=validate.OneOf(["0", "1"]))
|
|
||||||
sort = fields.Integer()
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import datetime
|
|
||||||
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
|
|
||||||
|
|
||||||
class DictType(db.Model):
|
|
||||||
__tablename__ = 'admin_dict_type'
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
type_name = db.Column(db.String(255), comment='字典类型名称')
|
|
||||||
type_code = db.Column(db.String(255), comment='字典类型标识')
|
|
||||||
description = db.Column(db.String(255), comment='字典类型描述')
|
|
||||||
enable = db.Column(db.Integer, comment='是否开启')
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
|
||||||
|
|
||||||
|
|
||||||
class DictData(db.Model):
|
|
||||||
__tablename__ = 'admin_dict_data'
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
data_label = db.Column(db.String(255), comment='字典类型名称')
|
|
||||||
data_value = db.Column(db.String(255), comment='字典类型标识')
|
|
||||||
type_code = db.Column(db.String(255), comment='字典类型描述')
|
|
||||||
is_default = db.Column(db.Integer, comment='是否默认')
|
|
||||||
enable = db.Column(db.Integer, comment='是否开启')
|
|
||||||
remark = db.Column(db.String(255), comment='备注')
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
|
||||||
|
|
||||||
|
|
||||||
class DictTypeSchema(ma.Schema): # 序列化类
|
|
||||||
id = fields.Str(attribute="id")
|
|
||||||
typeName = fields.Str(attribute="type_name")
|
|
||||||
typeCode = fields.Str(attribute="type_code")
|
|
||||||
description = fields.Str(attribute="description")
|
|
||||||
createTime = fields.Str(attribute="create_time")
|
|
||||||
updateName = fields.Str(attribute="update_time")
|
|
||||||
remark = fields.Str()
|
|
||||||
enable = fields.Str()
|
|
||||||
|
|
||||||
|
|
||||||
class DictDataSchema(ma.Schema): # 序列化类
|
|
||||||
dataId = fields.Str(attribute="id")
|
|
||||||
dataLabel = fields.Str(attribute="data_label")
|
|
||||||
dataValue = fields.Str(attribute="data_value")
|
|
||||||
remark = fields.Str()
|
|
||||||
enable = fields.Str()
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import datetime
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
|
|
||||||
|
|
||||||
class AdminLog(db.Model):
|
|
||||||
__tablename__ = 'admin_admin_log'
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
method = db.Column(db.String(10))
|
|
||||||
uid = db.Column(db.Integer)
|
|
||||||
url = db.Column(db.String(255))
|
|
||||||
desc = db.Column(db.Text)
|
|
||||||
ip = db.Column(db.String(255))
|
|
||||||
success = db.Column(db.Integer)
|
|
||||||
user_agent = db.Column(db.Text)
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now)
|
|
||||||
|
|
||||||
|
|
||||||
class LogSchema(ma.Schema): # 序列化类
|
|
||||||
id = fields.Integer()
|
|
||||||
method = fields.Str()
|
|
||||||
uid = fields.Str()
|
|
||||||
url = fields.Str()
|
|
||||||
desc = fields.Str()
|
|
||||||
ip = fields.Str()
|
|
||||||
user_agent = fields.Str()
|
|
||||||
success = fields.Bool()
|
|
||||||
create_time = fields.DateTime()
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import datetime
|
|
||||||
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
|
|
||||||
|
|
||||||
class Photo(db.Model):
|
|
||||||
__tablename__ = 'admin_photo'
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
name = db.Column(db.String(255), nullable=False)
|
|
||||||
href = db.Column(db.String(255))
|
|
||||||
mime = db.Column(db.CHAR(50), nullable=False)
|
|
||||||
size = db.Column(db.CHAR(30), nullable=False)
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now)
|
|
||||||
|
|
||||||
|
|
||||||
class PhotoSchema(ma.Schema):
|
|
||||||
id = fields.Integer()
|
|
||||||
name = fields.Str()
|
|
||||||
href = fields.Str()
|
|
||||||
mime = fields.Str()
|
|
||||||
size = fields.Str()
|
|
||||||
ext = fields.Str()
|
|
||||||
create_time = fields.DateTime()
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import datetime
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
|
|
||||||
|
|
||||||
class Power(db.Model):
|
|
||||||
__tablename__ = 'admin_power'
|
|
||||||
id = db.Column(db.Integer, primary_key=True, comment='权限编号')
|
|
||||||
name = db.Column(db.String(255), comment='权限名称')
|
|
||||||
type = db.Column(db.String(1), comment='权限类型')
|
|
||||||
code = db.Column(db.String(30), comment='权限标识')
|
|
||||||
url = db.Column(db.String(255), comment='权限路径')
|
|
||||||
open_type = db.Column(db.String(10), comment='打开方式')
|
|
||||||
parent_id = db.Column(db.Integer, comment='父类编号')
|
|
||||||
icon = db.Column(db.String(128), comment='图标')
|
|
||||||
sort = db.Column(db.Integer, comment='排序')
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
|
||||||
enable = db.Column(db.Integer, comment='是否开启')
|
|
||||||
|
|
||||||
|
|
||||||
# 权限models序列化类
|
|
||||||
class PowerSchema(ma.Schema):
|
|
||||||
id = fields.Integer()
|
|
||||||
title = fields.Str(attribute="name")
|
|
||||||
type = fields.Str()
|
|
||||||
code = fields.Str()
|
|
||||||
href = fields.Str(attribute="url")
|
|
||||||
openType = fields.Str(attribute="open_type")
|
|
||||||
parent_id = fields.Integer()
|
|
||||||
icon = fields.Str()
|
|
||||||
sort = fields.Integer()
|
|
||||||
create_time = fields.DateTime()
|
|
||||||
update_time = fields.DateTime()
|
|
||||||
enable = fields.Integer()
|
|
||||||
|
|
||||||
|
|
||||||
class PowerSchema2(ma.Schema): # 序列化类
|
|
||||||
powerId = fields.Str(attribute="id")
|
|
||||||
powerName = fields.Str(attribute="name")
|
|
||||||
powerType = fields.Str(attribute="type")
|
|
||||||
powerUrl = fields.Str(attribute="url")
|
|
||||||
openType = fields.Str(attribute="open_type")
|
|
||||||
parentId = fields.Str(attribute="parent_id")
|
|
||||||
icon = fields.Str()
|
|
||||||
sort = fields.Integer()
|
|
||||||
create_time = fields.DateTime()
|
|
||||||
update_time = fields.DateTime()
|
|
||||||
enable = fields.Integer()
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import datetime
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
|
|
||||||
|
|
||||||
class Role(db.Model):
|
|
||||||
__tablename__ = 'admin_role'
|
|
||||||
id = db.Column(db.Integer, primary_key=True, comment='角色ID')
|
|
||||||
name = db.Column(db.String(255), comment='角色名称')
|
|
||||||
code = db.Column(db.String(255), comment='角色标识')
|
|
||||||
enable = db.Column(db.Integer, comment='是否启用')
|
|
||||||
remark = db.Column(db.String(255), comment='备注')
|
|
||||||
details = db.Column(db.String(255), comment='详情')
|
|
||||||
sort = db.Column(db.Integer, comment='排序')
|
|
||||||
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
|
|
||||||
power = db.relationship('Power', secondary="admin_role_power", backref=db.backref('role'))
|
|
||||||
|
|
||||||
|
|
||||||
class RoleSchema(ma.Schema):
|
|
||||||
id = fields.Integer()
|
|
||||||
roleName = fields.Str(attribute="name")
|
|
||||||
roleCode = fields.Str(attribute="code")
|
|
||||||
enable = fields.Str()
|
|
||||||
remark = fields.Str()
|
|
||||||
details = fields.Str()
|
|
||||||
sort = fields.Integer()
|
|
||||||
create_at = fields.DateTime()
|
|
||||||
update_at = fields.DateTime()
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from applications.extensions import db
|
|
||||||
|
|
||||||
# 创建中间表
|
|
||||||
role_power = db.Table(
|
|
||||||
"admin_role_power", # 中间表名称
|
|
||||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
|
||||||
db.Column("power_id", db.Integer, db.ForeignKey("admin_power.id"), comment='用户编号'), # 属性 外键
|
|
||||||
db.Column("role_id", db.Integer, db.ForeignKey("admin_role.id"), comment='角色编号'), # 属性 外键
|
|
||||||
)
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import datetime
|
|
||||||
from flask_login import UserMixin
|
|
||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
|
||||||
from applications.extensions import db, ma
|
|
||||||
from marshmallow import fields
|
|
||||||
from applications.models import Dept
|
|
||||||
|
|
||||||
|
|
||||||
class User(db.Model, UserMixin):
|
|
||||||
__tablename__ = 'admin_user'
|
|
||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
|
|
||||||
username = db.Column(db.String(20), comment='用户名')
|
|
||||||
realname = db.Column(db.String(20), comment='真实名字')
|
|
||||||
avatar = db.Column(db.String(255), comment='头像', default="/static/admin/admin/images/avatar.jpg")
|
|
||||||
remark = db.Column(db.String(255), comment='备注')
|
|
||||||
password_hash = db.Column(db.String(128), comment='哈希密码')
|
|
||||||
enable = db.Column(db.Integer, default=0, comment='启用')
|
|
||||||
dept_id = db.Column(db.Integer, comment='部门id')
|
|
||||||
create_at = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
|
|
||||||
update_at = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='创建时间')
|
|
||||||
role = db.relationship('Role', secondary="admin_user_role", backref=db.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)
|
|
||||||
|
|
||||||
|
|
||||||
# 用户models的序列化类
|
|
||||||
class UserSchema(ma.Schema):
|
|
||||||
id = fields.Integer()
|
|
||||||
username = fields.Str()
|
|
||||||
realname = fields.Str()
|
|
||||||
enable = fields.Integer()
|
|
||||||
create_at = fields.DateTime()
|
|
||||||
update_at = fields.DateTime()
|
|
||||||
dept = fields.Method("get_dept")
|
|
||||||
|
|
||||||
def get_dept(self, obj):
|
|
||||||
if obj.dept_id != None:
|
|
||||||
return Dept.query.filter_by(id=obj.dept_id).first().dept_name
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from applications.extensions import db
|
|
||||||
|
|
||||||
# 创建中间表
|
|
||||||
user_role = db.Table(
|
|
||||||
"admin_user_role", # 中间表名称
|
|
||||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
|
||||||
db.Column("user_id", db.Integer, db.ForeignKey("admin_user.id"), comment='用户编号'), # 属性 外键
|
|
||||||
db.Column("role_id", db.Integer, db.ForeignKey("admin_role.id"), comment='角色编号'), # 属性 外键
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
from common import register_api
|
||||||
|
from .department import DepartmentsApi, DeptEnableAPI
|
||||||
|
from .rights import (
|
||||||
|
RightsApi, PowerApi, right_power_enable_resource,
|
||||||
|
admin_configs_resource, admin_menu_resource
|
||||||
|
)
|
||||||
|
from .roles import RoleRoleApi, RolePowerApi, role_deletes, role_enable_resource
|
||||||
|
|
||||||
|
|
||||||
|
def register_rights_api(api_bp):
|
||||||
|
register_api(DepartmentsApi, 'rights_dept_api', '/dept/department/', pk='_id', app=api_bp)
|
||||||
|
api_bp.add_url_rule('/dept/department/<int:_id>/status',
|
||||||
|
view_func=DeptEnableAPI.as_view('dept_status_api'),
|
||||||
|
methods=['PUT', ])
|
||||||
|
api_bp.add_url_rule('/rights/rights',
|
||||||
|
view_func=RightsApi.as_view('dept_rights_api'),
|
||||||
|
methods=['GET', 'DELETE'])
|
||||||
|
|
||||||
|
register_api(PowerApi, 'rights_power_api', '/rights/power/', pk='_id', app=api_bp)
|
||||||
|
api_bp.add_url_rule('/rights/configs',
|
||||||
|
endpoint='rights_config_api',
|
||||||
|
view_func=admin_configs_resource,
|
||||||
|
methods=['GET'])
|
||||||
|
api_bp.add_url_rule('/rights/menu',
|
||||||
|
endpoint='rights_menu_api',
|
||||||
|
view_func=admin_menu_resource,
|
||||||
|
methods=['GET'])
|
||||||
|
api_bp.add_url_rule('/rights/power/<int:_id>/<action>',
|
||||||
|
endpoint='rights_power_action_api',
|
||||||
|
view_func=right_power_enable_resource,
|
||||||
|
methods=['PUT'])
|
||||||
|
api_bp.add_url_rule('/roles/role',
|
||||||
|
endpoint='rights_roles_role_api',
|
||||||
|
view_func=role_deletes,
|
||||||
|
methods=['DELETE'])
|
||||||
|
|
||||||
|
register_api(RoleRoleApi, 'rights_role_api', '/roles/role/', pk='_id', app=api_bp)
|
||||||
|
register_api(RolePowerApi, 'rights_role_power_api', '/roles/role_power/', pk='_id', app=api_bp)
|
||||||
|
api_bp.add_url_rule('/roles/role/<int:_id>/status',
|
||||||
|
endpoint='rights_roles_enable_api',
|
||||||
|
view_func=role_enable_resource,
|
||||||
|
methods=['PUT'])
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
import typing as t
|
||||||
|
|
||||||
|
from flask import jsonify
|
||||||
|
from flask.views import MethodView
|
||||||
|
from flask_pydantic import validate
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from common.utils.http import success_api, fail_api
|
||||||
|
from extensions import db
|
||||||
|
from models import DepartmentModel, UserModel
|
||||||
|
|
||||||
|
|
||||||
|
class DeptModel(BaseModel):
|
||||||
|
address: t.Optional[str]
|
||||||
|
dept_name: t.Optional[str] = Field(alias='deptName')
|
||||||
|
email: t.Optional[str]
|
||||||
|
leader: t.Optional[str]
|
||||||
|
parent_id: t.Optional[str] = Field(alias='parentId')
|
||||||
|
phone: t.Optional[str]
|
||||||
|
sort: t.Optional[int]
|
||||||
|
status: t.Optional[int]
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentsApi(MethodView):
|
||||||
|
|
||||||
|
def get(self, _id):
|
||||||
|
if _id:
|
||||||
|
dept = DepartmentModel.query.filter_by(id=_id).first()
|
||||||
|
dept_data = {
|
||||||
|
'id': dept.id,
|
||||||
|
'dept_name': dept.dept_name,
|
||||||
|
'leader': dept.leader,
|
||||||
|
'email': dept.email,
|
||||||
|
'phone': dept.phone,
|
||||||
|
'status': dept.status,
|
||||||
|
'sort': dept.sort,
|
||||||
|
'address': dept.address,
|
||||||
|
}
|
||||||
|
return dict(success=True, message='ok', dept=dept_data)
|
||||||
|
|
||||||
|
dept_data = DepartmentModel.query.order_by(DepartmentModel.sort).all()
|
||||||
|
# TODO dtree 需要返回状态信息
|
||||||
|
res = {
|
||||||
|
"status": {"code": 200, "message": "默认"},
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
'deptId': item.id,
|
||||||
|
'parentId': item.parent_id,
|
||||||
|
'deptName': item.dept_name,
|
||||||
|
'sort': item.sort,
|
||||||
|
'leader': item.leader,
|
||||||
|
'phone': item.phone,
|
||||||
|
'email': item.email,
|
||||||
|
'status': item.status,
|
||||||
|
'comment': item.comment,
|
||||||
|
'address': item.address,
|
||||||
|
'create_at': item.create_at.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
} for item in dept_data
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return jsonify(res)
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def post(self, body: DeptModel):
|
||||||
|
dept = DepartmentModel(
|
||||||
|
parent_id=body.parent_id,
|
||||||
|
dept_name=body.dept_name,
|
||||||
|
sort=body.sort,
|
||||||
|
leader=body.leader,
|
||||||
|
phone=body.phone,
|
||||||
|
email=body.email,
|
||||||
|
status=body.status,
|
||||||
|
address=body.address
|
||||||
|
)
|
||||||
|
db.session.add(dept)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success_api(message="成功")
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def put(self, _id, body: DeptModel):
|
||||||
|
data = {
|
||||||
|
"dept_name": body.dept_name,
|
||||||
|
"sort": body.sort,
|
||||||
|
"leader": body.leader,
|
||||||
|
"phone": body.phone,
|
||||||
|
"email": body.email,
|
||||||
|
"status": body.status,
|
||||||
|
"address": body.address
|
||||||
|
}
|
||||||
|
body = DepartmentModel.query.filter_by(id=_id).update(data)
|
||||||
|
if not body:
|
||||||
|
return fail_api(message="更新失败")
|
||||||
|
db.session.commit()
|
||||||
|
return success_api(message="更新成功")
|
||||||
|
|
||||||
|
def delete(self, _id):
|
||||||
|
ret = DepartmentModel.query.filter_by(id=_id).delete()
|
||||||
|
UserModel.query.filter_by(dept_id=_id).update({"dept_id": None})
|
||||||
|
db.session.commit()
|
||||||
|
if ret:
|
||||||
|
return success_api(message="删除成功")
|
||||||
|
return fail_api(message="删除失败")
|
||||||
|
|
||||||
|
|
||||||
|
class DeptEnableAPI(MethodView):
|
||||||
|
def put(self, _id):
|
||||||
|
d = DepartmentModel.query.get(_id)
|
||||||
|
if d:
|
||||||
|
d.status = not d.status
|
||||||
|
db.session.commit()
|
||||||
|
message = '修改成功'
|
||||||
|
return success_api(message=message)
|
||||||
|
return fail_api(message="出错啦")
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
import copy
|
||||||
|
from collections import OrderedDict
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from flask import request, jsonify, current_app
|
||||||
|
from flask.views import MethodView
|
||||||
|
from flask_login import current_user
|
||||||
|
from flask_pydantic import validate
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from common.utils.http import success_api, fail_api
|
||||||
|
from extensions import db
|
||||||
|
from models import RightModel, RoleModel
|
||||||
|
|
||||||
|
|
||||||
|
def get_render_config():
|
||||||
|
# 网站配置
|
||||||
|
config = {
|
||||||
|
'logo': {
|
||||||
|
# 网站名称
|
||||||
|
"title": current_app.config.get("SYSTEM_NAME"),
|
||||||
|
# 网站图标
|
||||||
|
"image": "/static/admin/admin/images/logo.png"
|
||||||
|
# 菜单配置
|
||||||
|
},
|
||||||
|
'menu': {
|
||||||
|
# 菜单数据来源
|
||||||
|
"data": "/api/v1/rights/menu",
|
||||||
|
"collaspe": True,
|
||||||
|
# 是否同时只打开一个菜单目录
|
||||||
|
"accordion": True,
|
||||||
|
"method": "GET",
|
||||||
|
# 是否开启多系统菜单模式
|
||||||
|
"control": False,
|
||||||
|
# 默认选中的菜单项
|
||||||
|
"select": "0",
|
||||||
|
# 是否开启异步菜单,false 时 data 属性设置为菜单数据,false 时为 json 文件或后端接口
|
||||||
|
"async": True
|
||||||
|
},
|
||||||
|
'tab': {
|
||||||
|
# 是否开启多选项卡
|
||||||
|
"muiltTab": True,
|
||||||
|
# 切换选项卡时,是否刷新页面状态
|
||||||
|
"keepState": True,
|
||||||
|
# 是否开启 Tab 记忆
|
||||||
|
"session": True,
|
||||||
|
# 最大可打开的选项卡数量
|
||||||
|
"tabMax": 30,
|
||||||
|
"index": {
|
||||||
|
# 标识 ID , 建议与菜单项中的 ID 一致
|
||||||
|
"id": "10",
|
||||||
|
# 页面地址
|
||||||
|
"href": "/admin/welcome",
|
||||||
|
# 标题
|
||||||
|
"title": "首页"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'theme': {
|
||||||
|
# 默认主题色,对应 colors 配置中的 ID 标识
|
||||||
|
"defaultColor": "2",
|
||||||
|
# 默认的菜单主题 dark-theme 黑 / light-theme 白
|
||||||
|
"defaultMenu": "dark-theme",
|
||||||
|
# 是否允许用户切换主题,false 时关闭自定义主题面板
|
||||||
|
"allowCustom": True
|
||||||
|
},
|
||||||
|
'colors': [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"color": "#2d8cf0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"color": "#5FB878"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"color": "#1E9FFF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"color": "#FFB800"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5",
|
||||||
|
"color": "darkgray"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'links': current_app.config.get("SYSTEM_PANEL_LINKS"),
|
||||||
|
'other': {
|
||||||
|
# 主页动画时长
|
||||||
|
"keepLoad": 1200,
|
||||||
|
# 布局顶部主题
|
||||||
|
"autoHead": False
|
||||||
|
},
|
||||||
|
'header': False
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
# 生成菜单树
|
||||||
|
def make_menu_tree():
|
||||||
|
role = current_user.role
|
||||||
|
powers = []
|
||||||
|
for i in role:
|
||||||
|
# 如果角色没有被启用就直接跳过
|
||||||
|
if i.enable == 0:
|
||||||
|
continue
|
||||||
|
# 变量角色用户的权限
|
||||||
|
for p in i.power:
|
||||||
|
# 如果权限关闭了就直接跳过
|
||||||
|
if p.enable == 0:
|
||||||
|
continue
|
||||||
|
# 一二级菜单
|
||||||
|
if p.type == 0 or p.type == 1:
|
||||||
|
powers.append(p)
|
||||||
|
|
||||||
|
power_dict = [
|
||||||
|
{
|
||||||
|
'id': item.id,
|
||||||
|
'title': item.name,
|
||||||
|
'type': item.type,
|
||||||
|
'code': item.code,
|
||||||
|
'href': item.url,
|
||||||
|
'openType': item.open_type,
|
||||||
|
'parent_id': item.parent_id,
|
||||||
|
'icon': item.icon,
|
||||||
|
'sort': item.sort,
|
||||||
|
'enable': item.enable,
|
||||||
|
} for item in powers
|
||||||
|
]
|
||||||
|
power_dict.sort(key=lambda x: x['id'], reverse=True)
|
||||||
|
|
||||||
|
menu_dict = OrderedDict()
|
||||||
|
for _dict in power_dict:
|
||||||
|
if _dict['id'] in menu_dict:
|
||||||
|
# 当前节点添加子节点
|
||||||
|
_dict['children'] = copy.deepcopy(menu_dict[_dict['id']])
|
||||||
|
_dict['children'].sort(key=lambda item: item['sort'])
|
||||||
|
# 删除子节点
|
||||||
|
del menu_dict[_dict['id']]
|
||||||
|
|
||||||
|
if _dict['parent_id'] not in menu_dict:
|
||||||
|
menu_dict[_dict['parent_id']] = [_dict]
|
||||||
|
else:
|
||||||
|
menu_dict[_dict['parent_id']].append(_dict)
|
||||||
|
|
||||||
|
return sorted(menu_dict.get(0), key=lambda item: item['sort'])
|
||||||
|
|
||||||
|
|
||||||
|
class PowerModel(BaseModel):
|
||||||
|
icon: str
|
||||||
|
open_type: Optional[str] = Field(alias='openType')
|
||||||
|
parent_id: Optional[str] = Field(alias='parentId')
|
||||||
|
power_code: Optional[str] = Field(alias='powerCode')
|
||||||
|
power_name: Optional[str] = Field(alias='powerName')
|
||||||
|
power_type: Optional[str] = Field(alias='powerType')
|
||||||
|
power_url: Optional[str] = Field(alias='powerUrl')
|
||||||
|
sort: Optional[int] = Field(alias='sort')
|
||||||
|
|
||||||
|
|
||||||
|
class RightsApi(MethodView):
|
||||||
|
def get(self):
|
||||||
|
"""获取选择父节点"""
|
||||||
|
|
||||||
|
power = RightModel.query.all()
|
||||||
|
# power_data = marshal(power, RightModel.fields())
|
||||||
|
power_data = [
|
||||||
|
{
|
||||||
|
'powerId': item.id,
|
||||||
|
'powerName': item.name,
|
||||||
|
'powerType': item.type,
|
||||||
|
'powerUrl': item.url,
|
||||||
|
'openType': item.open_type,
|
||||||
|
'parentId': item.parent_id,
|
||||||
|
'icon': item.icon,
|
||||||
|
'sort': item.sort,
|
||||||
|
'enable': item.enable,
|
||||||
|
} for item in power
|
||||||
|
]
|
||||||
|
power_data.append({"powerId": 0, "powerName": "顶级权限", "parentId": -1})
|
||||||
|
res = {
|
||||||
|
"status": {"code": 200, "message": "默认"},
|
||||||
|
"data": power_data
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
ids = request.form.getlist('ids[]')
|
||||||
|
for id in ids:
|
||||||
|
role = RoleModel.query.filter_by(id=id).first()
|
||||||
|
# 删除该角色的权限和用户
|
||||||
|
role.power = []
|
||||||
|
role.user = []
|
||||||
|
|
||||||
|
r = RoleModel.query.filter_by(id=id).delete()
|
||||||
|
db.session.commit()
|
||||||
|
return success_api(message="批量删除成功")
|
||||||
|
|
||||||
|
|
||||||
|
class PowerApi(MethodView):
|
||||||
|
@validate()
|
||||||
|
def post(self, body: PowerModel):
|
||||||
|
power = RightModel(
|
||||||
|
icon=body.icon,
|
||||||
|
open_type=body.open_type,
|
||||||
|
parent_id=body.parent_id,
|
||||||
|
code=body.power_code,
|
||||||
|
name=body.power_name,
|
||||||
|
type=body.power_type,
|
||||||
|
url=body.power_url,
|
||||||
|
sort=body.sort,
|
||||||
|
enable=1
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
db.session.add(power)
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return fail_api(message='数据提交失败')
|
||||||
|
|
||||||
|
return success_api(message="成功")
|
||||||
|
|
||||||
|
def delete(self, _id):
|
||||||
|
# 删除权限(目前没有判断父节点自动删除子节点)
|
||||||
|
power = RightModel.query.filter_by(id=_id).first()
|
||||||
|
role_id_list = []
|
||||||
|
roles = power.role
|
||||||
|
for role in roles:
|
||||||
|
role_id_list.append(role.id)
|
||||||
|
roles = RoleModel.query.filter(RoleModel.id.in_(role_id_list)).all()
|
||||||
|
for p in roles:
|
||||||
|
power.role.remove(p)
|
||||||
|
r = RightModel.query.filter_by(id=_id).delete()
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
if r:
|
||||||
|
return success_api(message="删除成功")
|
||||||
|
else:
|
||||||
|
return fail_api(message="删除失败")
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def put(self, _id, body: PowerModel):
|
||||||
|
data = {
|
||||||
|
"icon": body.icon,
|
||||||
|
"open_type": body.open_type,
|
||||||
|
"parent_id": body.parent_id,
|
||||||
|
"code": body.power_code,
|
||||||
|
"name": body.power_name,
|
||||||
|
"type": body.power_type,
|
||||||
|
"url": body.power_url,
|
||||||
|
"sort": body.sort
|
||||||
|
}
|
||||||
|
power = RightModel.query.filter_by(id=_id).update(data)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
if not power:
|
||||||
|
return fail_api(message="更新权限失败")
|
||||||
|
return success_api(message="更新权限成功")
|
||||||
|
|
||||||
|
|
||||||
|
def right_power_enable_resource(_id, action):
|
||||||
|
power = RightModel.query.get(_id)
|
||||||
|
if power:
|
||||||
|
power.enable = not power.enable
|
||||||
|
db.session.commit()
|
||||||
|
message = "修改成功"
|
||||||
|
return success_api(message=message)
|
||||||
|
else:
|
||||||
|
return fail_api(message="出错啦")
|
||||||
|
|
||||||
|
|
||||||
|
def admin_configs_resource():
|
||||||
|
return get_render_config()
|
||||||
|
|
||||||
|
|
||||||
|
def admin_menu_resource():
|
||||||
|
menu_tree = make_menu_tree()
|
||||||
|
return jsonify(menu_tree)
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
from flask import request
|
||||||
|
from flask.views import MethodView
|
||||||
|
|
||||||
|
from common.utils.http import table_api, success_api, fail_api
|
||||||
|
from extensions import db
|
||||||
|
from models import RightModel, RoleModel
|
||||||
|
|
||||||
|
|
||||||
|
def role_deletes():
|
||||||
|
ids = request.form.getlist('ids[]')
|
||||||
|
for id in ids:
|
||||||
|
role = RoleModel.query.filter_by(id=id).first()
|
||||||
|
# 删除该角色的权限和用户
|
||||||
|
role.power = []
|
||||||
|
role.user = []
|
||||||
|
|
||||||
|
r = RoleModel.query.filter_by(id=id).delete()
|
||||||
|
db.session.commit()
|
||||||
|
return success_api(message="批量删除成功")
|
||||||
|
|
||||||
|
|
||||||
|
class RoleRoleApi(MethodView):
|
||||||
|
|
||||||
|
def get(self, _id):
|
||||||
|
if not _id:
|
||||||
|
page = request.args.get('page', default=1, type=int)
|
||||||
|
limit = request.args.get('limit', default=10, type=int)
|
||||||
|
role_name = request.args.get('roleName', default="", type=str)
|
||||||
|
role_code = request.args.get('roleCode', default="", type=str)
|
||||||
|
|
||||||
|
filters = []
|
||||||
|
if role_name:
|
||||||
|
filters.append(RoleModel.name.like('%' + role_name + '%'))
|
||||||
|
if role_code:
|
||||||
|
filters.append(RoleModel.code.like('%' + role_code + '%'))
|
||||||
|
|
||||||
|
paginate = RoleModel.query.filter(*filters).paginate(page=page, per_page=limit, error_out=False)
|
||||||
|
|
||||||
|
return table_api(
|
||||||
|
result={
|
||||||
|
'items': [{'id': item.id,
|
||||||
|
'roleName': item.name,
|
||||||
|
'roleCode': item.code,
|
||||||
|
'enable': item.enable,
|
||||||
|
'comment': item.comment,
|
||||||
|
'details': item.details,
|
||||||
|
'sort': item.sort,
|
||||||
|
} for item in paginate.items],
|
||||||
|
'total': paginate.total}
|
||||||
|
, code=0)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
# TODO 添加校验
|
||||||
|
details = request.json.get('details', '')
|
||||||
|
enable = request.json.get('enable', 0)
|
||||||
|
role_code = request.json.get('roleCode', '')
|
||||||
|
role_name = request.json.get('roleName', '')
|
||||||
|
sort = request.json.get('sort', 0)
|
||||||
|
|
||||||
|
role = RoleModel(
|
||||||
|
details=details,
|
||||||
|
enable=int(enable),
|
||||||
|
code=role_code,
|
||||||
|
name=role_name,
|
||||||
|
sort=int(sort)
|
||||||
|
)
|
||||||
|
db.session.add(role)
|
||||||
|
db.session.commit()
|
||||||
|
return success_api(message="成功")
|
||||||
|
|
||||||
|
# 更新角色
|
||||||
|
def put(self, _id):
|
||||||
|
# TODO 添加校验
|
||||||
|
role_code = request.json.get('roleCode', 0)
|
||||||
|
role_name = request.json.get('roleName', '')
|
||||||
|
sort = request.json.get('sort', 0) # int
|
||||||
|
enable = request.json.get('enable', 0) # int
|
||||||
|
details = request.json.get('details', '')
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"code": role_code,
|
||||||
|
"name": role_name,
|
||||||
|
"sort": sort,
|
||||||
|
"enable": enable,
|
||||||
|
"details": details
|
||||||
|
}
|
||||||
|
|
||||||
|
role = RoleModel.query.filter_by(id=_id).update(data)
|
||||||
|
db.session.commit()
|
||||||
|
if not role:
|
||||||
|
return fail_api(message="更新角色失败")
|
||||||
|
return success_api(message="更新角色成功")
|
||||||
|
|
||||||
|
|
||||||
|
def role_enable_resource(_id):
|
||||||
|
"""启用用户"""
|
||||||
|
ret = RoleModel.query.get(_id)
|
||||||
|
ret.enable = not ret.enable
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
message = "修改成功"
|
||||||
|
if not ret:
|
||||||
|
return fail_api(message="出错啦")
|
||||||
|
return success_api(message=message)
|
||||||
|
|
||||||
|
|
||||||
|
class RolePowerApi(MethodView):
|
||||||
|
|
||||||
|
def get(self, _id):
|
||||||
|
# 获取角色权限
|
||||||
|
role = RoleModel.query.filter_by(id=_id).first()
|
||||||
|
# 获取权限列表的 id
|
||||||
|
check_powers_list = [rp.id for rp in role.power]
|
||||||
|
powers = RightModel.query.all() # 获取所有的权限
|
||||||
|
powers = [
|
||||||
|
{
|
||||||
|
'powerId': item.id,
|
||||||
|
'powerName': item.name,
|
||||||
|
'powerType': item.type,
|
||||||
|
'powerUrl': item.url,
|
||||||
|
'openType': item.open_type,
|
||||||
|
'parentId': item.parent_id,
|
||||||
|
'icon': item.icon,
|
||||||
|
'sort': item.sort,
|
||||||
|
'enable': item.enable,
|
||||||
|
} for item in powers]
|
||||||
|
for i in powers:
|
||||||
|
if int(i.get("powerId")) in check_powers_list:
|
||||||
|
i["checkArr"] = "1"
|
||||||
|
else:
|
||||||
|
i["checkArr"] = "0"
|
||||||
|
return {
|
||||||
|
"data": powers,
|
||||||
|
"status": {"code": 200, "message": "默认"}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保存角色权限
|
||||||
|
def put(self, _id):
|
||||||
|
power_ids = request.json.get('powerIds', '')
|
||||||
|
|
||||||
|
power_list = power_ids.split(',')
|
||||||
|
|
||||||
|
""" 更新角色权限 """
|
||||||
|
role = RoleModel.query.filter_by(id=_id).first()
|
||||||
|
powers = RightModel.query.filter(RightModel.id.in_(power_list)).all()
|
||||||
|
role.power = powers
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return success_api(message="授权成功")
|
||||||
|
|
||||||
|
# 角色删除
|
||||||
|
def delete(self, _id):
|
||||||
|
role = RoleModel.query.filter_by(id=_id).first()
|
||||||
|
# 删除该角色的权限和用户
|
||||||
|
role.power = []
|
||||||
|
role.user = []
|
||||||
|
|
||||||
|
r = RoleModel.query.filter_by(id=_id).delete()
|
||||||
|
db.session.commit()
|
||||||
|
if not r:
|
||||||
|
return fail_api(message="角色删除失败")
|
||||||
|
return success_api(message="角色删除成功")
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,356 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
|
||||||
<!--
|
|
||||||
2013-9-30: Created.
|
|
||||||
-->
|
|
||||||
<svg>
|
|
||||||
<metadata>
|
|
||||||
Created by iconfont
|
|
||||||
</metadata>
|
|
||||||
<defs>
|
|
||||||
|
|
||||||
<font id="pear-icon" horiz-adv-x="1024" >
|
|
||||||
<font-face
|
|
||||||
font-family="pear-icon"
|
|
||||||
font-weight="500"
|
|
||||||
font-stretch="normal"
|
|
||||||
units-per-em="1024"
|
|
||||||
ascent="896"
|
|
||||||
descent="-128"
|
|
||||||
/>
|
|
||||||
<missing-glyph />
|
|
||||||
|
|
||||||
<glyph glyph-name="jiazai" unicode="" d="M512-96c-64.78 0-127.65 12.7-186.85 37.74-57.16 24.18-108.49 58.78-152.56 102.85-44.07 44.07-78.68 95.4-102.85 152.56C44.7 256.35 32 319.22 32 384s12.7 127.65 37.74 186.85c24.18 57.16 58.78 108.49 102.85 152.56s95.4 78.68 152.56 102.85C384.35 851.3 447.22 864 512 864c19.89 0 36.01-16.12 36.01-36.01s-16.12-36.01-36.01-36.01c-55.09 0-108.52-10.78-158.79-32.05-48.58-20.55-92.21-49.97-129.69-87.45s-66.9-81.11-87.45-129.69c-21.26-50.27-32.05-103.7-32.05-158.79s10.78-108.52 32.05-158.79c20.55-48.58 49.97-92.21 87.45-129.69s81.11-66.9 129.69-87.45c50.27-21.26 103.7-32.05 158.79-32.05s108.52 10.78 158.79 32.05c48.58 20.55 92.21 49.97 129.69 87.45s66.9 81.11 87.45 129.69c21.26 50.27 32.05 103.7 32.05 158.79 0 44.18-7.01 87.61-20.83 129.09-6.29 18.87 3.91 39.26 22.78 45.55 18.87 6.29 39.26-3.91 45.55-22.78C983.75 487.02 992 435.93 992 384c0-64.78-12.7-127.65-37.74-186.85-24.18-57.16-58.78-108.49-102.85-152.56-44.07-44.07-95.4-78.68-152.56-102.85C639.65-83.3 576.78-96 512-96z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="3column" unicode="" d="M874.666667 778.666667H149.333333C108.8 778.666667 74.666667 744.533333 74.666667 704v-640c0-40.533333 34.133333-74.666667 74.666666-74.666667h725.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V704c0 40.533333-34.133333 74.666667-74.666666 74.666667z m-245.333334-64v-661.333334h-234.666666v661.333334h234.666666zM138.666667 64V704c0 6.4 4.266667 10.666667 10.666666 10.666667h181.333334v-661.333334H149.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667z m746.666666 0c0-6.4-4.266667-10.666667-10.666666-10.666667h-181.333334v661.333334H874.666667c6.4 0 10.666667-4.266667 10.666666-10.666667v-640z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="column-4" unicode="" d="M874.666667 778.666667H149.333333C108.8 778.666667 74.666667 744.533333 74.666667 704v-640c0-40.533333 34.133333-74.666667 74.666666-74.666667h725.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V704c0 40.533333-34.133333 74.666667-74.666666 74.666667z m-330.666667-64h128v-661.333334h-128v661.333334z m-64-661.333334h-128v661.333334h128v-661.333334z m-341.333333 10.666667V704c0 6.4 4.266667 10.666667 10.666666 10.666667h138.666667v-661.333334H149.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667z m746.666666 0c0-6.4-4.266667-10.666667-10.666666-10.666667h-138.666667v661.333334H874.666667c6.4 0 10.666667-4.266667 10.666666-10.666667v-640z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="add" unicode="" d="M853.333333 416H544V725.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-309.333333H170.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h309.333333V42.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V352H853.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="adjust" unicode="" d="M522.666667 437.333333c-17.066667 0-32-14.933333-32-32v-362.666666c0-17.066667 14.933333-32 32-32S554.666667 25.6 554.666667 42.666667V405.333333c0 17.066667-14.933333 32-32 32zM341.333333 341.333333H106.666667c-17.066667 0-32-14.933333-32-32S89.6 277.333333 106.666667 277.333333h74.666666v-234.666666c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V277.333333H341.333333c17.066667 0 32 14.933333 32 32S358.4 341.333333 341.333333 341.333333zM693.333333 522.666667c0 17.066667-14.933333 32-32 32h-106.666666V725.333333c0 17.066667-14.933333 32-32 32S490.666667 742.4 490.666667 725.333333v-170.666666h-106.666667c-17.066667 0-32-14.933333-32-32S366.933333 490.666667 384 490.666667h277.333333c17.066667 0 32 14.933333 32 32zM917.333333 277.333333H682.666667c-17.066667 0-32-14.933333-32-32S665.6 213.333333 682.666667 213.333333h96v-170.666666c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v170.666666H917.333333c17.066667 0 32 14.933333 32 32S934.4 277.333333 917.333333 277.333333zM213.333333 437.333333c17.066667 0 32 14.933333 32 32V725.333333c0 17.066667-14.933333 32-32 32S181.333333 742.4 181.333333 725.333333v-256c0-17.066667 14.933333-32 32-32zM810.666667 373.333333c17.066667 0 32 14.933333 32 32V725.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-320c0-17.066667 14.933333-32 32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="ashbin" unicode="" d="M874.666667 654.933333h-202.666667V725.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667h-170.666666c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-70.4H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h53.333334V42.666667c0-40.533333 34.133333-74.666667 74.666666-74.666667h469.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V590.933333H874.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM416 725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h170.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-70.4h-192V725.333333z m341.333333-682.666666c0-6.4-4.266667-10.666667-10.666666-10.666667H277.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667V586.666667h490.666666V42.666667zM426.666667 160c17.066667 0 32 14.933333 32 32V405.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-213.333333c0-17.066667 14.933333-32 32-32zM597.333333 160c17.066667 0 32 14.933333 32 32V405.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-213.333333c0-17.066667 14.933333-32 32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="browse" unicode="" d="M512 59.733333C230.4 59.733333 74.666667 362.666667 68.266667 375.466667c-4.266667 8.533333-4.266667 19.2 0 29.866666 6.4 12.8 164.266667 315.733333 443.733333 315.733334 281.6 0 437.333333-305.066667 443.733333-317.866667 4.266667-8.533333 4.266667-19.2 0-29.866667-6.4-10.666667-162.133333-313.6-443.733333-313.6zM132.266667 390.4c34.133333-57.6 170.666667-266.666667 379.733333-266.666667s345.6 209.066667 379.733333 266.666667c-34.133333 57.6-170.666667 266.666667-379.733333 266.666667S166.4 448 132.266667 390.4zM512 245.333333c-76.8 0-138.666667 61.866667-138.666667 138.666667s61.866667 138.666667 138.666667 138.666667 138.666667-61.866667 138.666667-138.666667-61.866667-138.666667-138.666667-138.666667z m0 213.333334c-40.533333 0-74.666667-34.133333-74.666667-74.666667s34.133333-74.666667 74.666667-74.666667 74.666667 34.133333 74.666667 74.666667-34.133333 74.666667-74.666667 74.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="bottom" unicode="" d="M896 32H128c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h768c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM488.533333 168.533333c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466667 8.533333l213.333333 213.333334c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-157.866667-157.866667V725.333333c0 17.066667-14.933333 32-32 32s-34.133333-14.933333-34.133333-32v-456.533333L322.133333 426.666667c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l211.2-213.333334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="back" unicode="" d="M853.333333 650.666667H245.333333l93.866667 93.866666c12.8 12.8 12.8 34.133333 0 46.933334-12.8 12.8-34.133333 12.8-46.933333 0l-145.066667-145.066667c-12.8-12.8-12.8-34.133333 0-46.933333l145.066667-145.066667c6.4-6.4 14.933333-10.666667 23.466666-10.666667s17.066667 4.266667 23.466667 10.666667c12.8 12.8 12.8 34.133333 0 46.933333L256 584.533333h597.333333c6.4 0 10.666667-4.266667 10.666667-10.666666v-426.666667c0-6.4-4.266667-10.666667-10.666667-10.666667H170.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V576c0 40.533333-34.133333 74.666667-74.666667 74.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="bad" unicode="" d="M904.533333 373.333333L853.333333 710.4c-8.533333 51.2-55.466667 89.6-106.666666 89.6H204.8c-59.733333 0-108.8-46.933333-108.8-106.666667v-258.133333c0-57.6 49.066667-106.666667 108.8-106.666667h91.733333l125.866667-281.6c2.133333-2.133333 2.133333-4.266667 4.266667-6.4 14.933333-23.466667 38.4-36.266667 64-36.266666 12.8 0 25.6 4.266667 38.4 10.666666 57.6 34.133333 87.466667 72.533333 87.466666 117.333334v117.333333h183.466667c32 0 59.733333 12.8 81.066667 36.266667 19.2 25.6 29.866667 55.466667 23.466666 87.466666z m-616.533333 21.333334H204.8c-25.6 0-44.8 19.2-44.8 42.666666v256c0 23.466667 19.2 42.666667 44.8 42.666667h83.2v-341.333333zM832 328.533333c-8.533333-8.533333-21.333333-14.933333-34.133333-14.933333h-213.333334c-17.066667 0-32-14.933333-32-32v-149.333333c0-25.6-29.866667-49.066667-55.466666-64-4.266667-2.133333-10.666667-2.133333-14.933334 4.266666L352 362.666667V736H746.666667c21.333333 0 40.533333-14.933333 42.666666-36.266667L842.666667 362.666667c2.133333-10.666667-2.133333-23.466667-10.666667-34.133334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-double-left" unicode="" d="M842.666667 32c-8.533333 0-14.933333 2.133333-21.333334 8.533333l-341.333333 309.333334c-6.4 6.4-10.666667 14.933333-10.666667 23.466666 0 8.533333 4.266667 17.066667 10.666667 23.466667l341.333333 309.333333c12.8 12.8 34.133333 10.666667 44.8-2.133333 12.8-12.8 10.666667-34.133333-2.133333-44.8L548.266667 373.333333l315.733333-285.866666c12.8-10.666667 14.933333-32 2.133333-44.8-6.4-6.4-14.933333-10.666667-23.466666-10.666667zM512 32c-8.533333 0-14.933333 2.133333-21.333333 8.533333L149.333333 349.866667c-6.4 6.4-10.666667 14.933333-10.666666 23.466666 0 8.533333 4.266667 17.066667 10.666666 23.466667L490.666667 706.133333c12.8 12.8 34.133333 10.666667 44.8-2.133333 12.8-12.8 10.666667-34.133333-2.133334-44.8L217.6 373.333333 533.333333 87.466667c12.8-12.8 14.933333-32 2.133334-44.8-6.4-6.4-14.933333-10.666667-23.466667-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-double-right" unicode="" d="M544 373.333333c0 8.533333-4.266667 17.066667-10.666667 23.466667L192 706.133333c-12.8 12.8-34.133333 10.666667-44.8-2.133333-12.8-12.8-10.666667-34.133333 2.133333-44.8l315.733334-285.866667L149.333333 87.466667c-12.8-12.8-14.933333-32-2.133333-44.8 6.4-6.4 14.933333-10.666667 23.466667-10.666667 8.533333 0 14.933333 2.133333 21.333333 8.533333l341.333333 309.333334c6.4 6.4 10.666667 14.933333 10.666667 23.466666zM864 396.8l-341.333333 309.333333c-12.8 12.8-34.133333 10.666667-44.8-2.133333-12.8-12.8-10.666667-34.133333 2.133333-44.8l315.733333-285.866667-315.733333-285.866666c-12.8-12.8-14.933333-32-2.133333-44.8 6.4-6.4 14.933333-10.666667 23.466666-10.666667 8.533333 0 14.933333 2.133333 21.333334 8.533333l341.333333 309.333334c6.4 6.4 10.666667 14.933333 10.666667 23.466666 0 8.533333-4.266667 17.066667-10.666667 23.466667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="camera" unicode="" d="M846.933333 657.066667h-140.8L646.4 746.666667c-6.4 10.666667-17.066667 17.066667-29.866667 17.066666h-209.066666c-12.8 0-23.466667-6.4-29.866667-17.066666l-59.733333-89.6H177.066667c-57.6 0-106.666667-46.933333-106.666667-106.666667v-426.666667c0-57.6 46.933333-106.666667 106.666667-106.666666h672c57.6 0 106.666667 46.933333 106.666666 106.666666v426.666667c-2.133333 59.733333-49.066667 106.666667-108.8 106.666667z m34.133334-533.333334c0-19.2-14.933333-34.133333-34.133334-34.133333H177.066667c-19.2 0-34.133333 14.933333-34.133334 34.133333v426.666667c0 19.2 14.933333 34.133333 34.133334 34.133333h160c12.8 0 23.466667 6.4 29.866666 17.066667L426.666667 689.066667h170.666666l59.733334-89.6c6.4-10.666667 17.066667-17.066667 29.866666-17.066667h160c19.2 0 34.133333-14.933333 34.133334-34.133333v-424.533334zM512 531.2c-96 0-174.933333-78.933333-174.933333-174.933333 0-96 78.933333-174.933333 174.933333-174.933334 96 0 174.933333 78.933333 174.933333 174.933334 0 96-78.933333 174.933333-174.933333 174.933333z m0-279.466667c-57.6 0-104.533333 46.933333-104.533333 104.533334s46.933333 104.533333 104.533333 104.533333 104.533333-46.933333 104.533333-104.533333-46.933333-104.533333-104.533333-104.533334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="chart-bar" unicode="" d="M149.333333 96h128c29.866667 0 53.333333 23.466667 53.333334 53.333333V362.666667c0 29.866667-23.466667 53.333333-53.333334 53.333333H149.333333c-29.866667 0-53.333333-23.466667-53.333333-53.333333v-213.333334c0-29.866667 23.466667-53.333333 53.333333-53.333333z m10.666667 256h106.666667v-192h-106.666667v192zM448 96h128c29.866667 0 53.333333 23.466667 53.333333 53.333333V746.666667c0 29.866667-23.466667 53.333333-53.333333 53.333333h-128c-29.866667 0-53.333333-23.466667-53.333333-53.333333v-597.333334c0-29.866667 23.466667-53.333333 53.333333-53.333333z m10.666667 640h106.666666v-576h-106.666666v576zM874.666667 586.666667h-128c-29.866667 0-53.333333-23.466667-53.333334-53.333334v-384c0-29.866667 23.466667-53.333333 53.333334-53.333333h128c29.866667 0 53.333333 23.466667 53.333333 53.333333V533.333333c0 29.866667-23.466667 53.333333-53.333333 53.333334z m-10.666667-426.666667h-106.666667v362.666667h106.666667v-362.666667zM896 42.666667H128c-17.066667 0-32-14.933333-32-32S110.933333-21.333333 128-21.333333h768c17.066667 0 32 14.933333 32 32S913.066667 42.666667 896 42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="attachment" unicode="" d="M874.666667 428.8c-10.666667 10.666667-29.866667 12.8-42.666667 0l-343.466667-341.333333c-74.666667-74.666667-198.4-74.666667-275.2 0-36.266667 36.266667-57.6 85.333333-57.6 136.533333s19.2 100.266667 57.6 136.533333L556.8 704c46.933333 46.933333 121.6 46.933333 168.533333 0 23.466667-23.466667 34.133333-53.333333 34.133334-83.2 0-32-12.8-61.866667-34.133334-83.2L384 192c-17.066667-17.066667-44.8-17.066667-64 0-8.533333 8.533333-12.8 19.2-12.8 32s4.266667 23.466667 12.8 32l317.866667 315.733333c10.666667 10.666667 12.8 29.866667 0 42.666667-10.666667 12.8-29.866667 12.8-42.666667 0L277.333333 298.666667c-19.2-19.2-29.866667-46.933333-29.866666-74.666667S258.133333 170.666667 277.333333 149.333333c40.533333-40.533333 106.666667-40.533333 147.2 0L768 492.8c34.133333 34.133333 53.333333 78.933333 53.333333 125.866667s-19.2 93.866667-53.333333 125.866666a178.986667 178.986667 0 0 1-253.866667 0l-341.333333-341.333333c-46.933333-46.933333-74.666667-110.933333-74.666667-179.2s25.6-132.266667 74.666667-179.2c49.066667-49.066667 115.2-74.666667 179.2-74.666667s130.133333 25.6 179.2 74.666667l343.466667 341.333333c10.666667 12.8 10.666667 32 0 42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="code" unicode="" d="M322.133333 599.466667c-12.8 12.8-32 12.8-44.8 0l-192-192c-12.8-12.8-12.8-32 0-44.8l192-192c6.4-6.4 14.933333-8.533333 23.466667-8.533334s17.066667 2.133333 23.466667 8.533334c12.8 12.8 12.8 32 0 44.8L151.466667 384l168.533333 168.533333c12.8 12.8 12.8 34.133333 2.133333 46.933334zM940.8 407.466667l-192 192c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l168.533333-168.533334-168.533333-168.533333c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333l192 192c8.533333 8.533333 8.533333 29.866667-2.133333 42.666667zM622.933333 819.2c-17.066667 4.266667-34.133333-6.4-38.4-23.466667L366.933333-6.4c-4.266667-17.066667 6.4-34.133333 23.466667-38.4 2.133333 0 6.4-2.133333 8.533333-2.133333 14.933333 0 27.733333 8.533333 29.866667 23.466666L644.266667 780.8c4.266667 17.066667-4.266667 34.133333-21.333334 38.4z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="close" unicode="" d="M556.8 384L832 659.2c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0L512 428.8l-275.2 277.333333c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l275.2-277.333333-277.333333-275.2c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333L512 339.2 787.2 64c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333c12.8 12.8 12.8 32 0 44.8L556.8 384z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="check-item" unicode="" d="M853.333333 800H170.666667C130.133333 800 96 765.866667 96 725.333333v-682.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V725.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667z m10.666667-757.333333c0-6.4-4.266667-10.666667-10.666667-10.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h682.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-682.666666zM704 514.133333l-243.2-234.666666-117.333333 125.866666c-12.8 12.8-32 12.8-44.8 2.133334-12.8-12.8-12.8-32-2.133334-44.8l140.8-149.333334c6.4-6.4 14.933333-10.666667 23.466667-10.666666 8.533333 0 17.066667 4.266667 21.333333 8.533333l264.533334 256c12.8 12.8 12.8 32 0 44.8-10.666667 12.8-29.866667 14.933333-42.666667 2.133333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="calendar" unicode="" d="M853.333333 746.666667h-138.666666V789.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-42.666666h-277.333334V789.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-42.666666H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-618.666667C96 12.8 130.133333-21.333333 170.666667-21.333333h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666666v618.666667C928 712.533333 893.866667 746.666667 853.333333 746.666667zM170.666667 682.666667h138.666666v-64c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v64h277.333334v-64c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v64H853.333333c6.4 0 10.666667-4.266667 10.666667-10.666667v-194.133333c-4.266667 2.133333-6.4 2.133333-10.666667 2.133333H170.666667c-4.266667 0-6.4 0-10.666667-2.133333v194.133333c0 6.4 4.266667 10.666667 10.666667 10.666667z m682.666666-640H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V418.133333c4.266667-2.133333 6.4-2.133333 10.666667-2.133333h682.666666c4.266667 0 6.4 0 10.666667 2.133333v-364.8c0-6.4-4.266667-10.666667-10.666667-10.666666zM384 288h-85.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h85.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM725.333333 288h-192c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h192c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="comment" unicode="" d="M853.333333 757.333333H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666666v-512c0-40.533333 34.133333-74.666667 74.666667-74.666667h151.466666V-21.333333c0-12.8 8.533333-25.6 19.2-29.866667 4.266667-2.133333 8.533333-2.133333 12.8-2.133333 8.533333 0 17.066667 4.266667 23.466667 10.666666l136.533333 138.666667H853.333333c40.533333 0 74.666667 34.133333 74.666667 74.666667V682.666667c0 40.533333-34.133333 74.666667-74.666667 74.666666z m10.666667-586.666666c0-6.4-4.266667-10.666667-10.666667-10.666667H501.333333c-8.533333 0-17.066667-4.266667-23.466666-10.666667l-89.6-93.866666V128c0 17.066667-14.933333 32-32 32H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V682.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h682.666666c6.4 0 10.666667-4.266667 10.666667-10.666666v-512zM512 405.333333H298.666667c-17.066667 0-32-14.933333-32-32S281.6 341.333333 298.666667 341.333333h213.333333c17.066667 0 32 14.933333 32 32S529.066667 405.333333 512 405.333333zM672 554.666667H298.666667c-17.066667 0-32-14.933333-32-32S281.6 490.666667 298.666667 490.666667h373.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="column-vertical" unicode="" d="M874.666667 778.666667H149.333333C108.8 778.666667 74.666667 744.533333 74.666667 704v-640c0-40.533333 34.133333-74.666667 74.666666-74.666667h725.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V704c0 40.533333-34.133333 74.666667-74.666666 74.666667z m-725.333334-64h725.333334c6.4 0 10.666667-4.266667 10.666666-10.666667v-288h-746.666666V704c0 6.4 4.266667 10.666667 10.666666 10.666667z m725.333334-661.333334H149.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667V352h746.666666V64c0-6.4-4.266667-10.666667-10.666666-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="column-horizontal" unicode="" d="M874.666667 778.666667H149.333333C108.8 778.666667 74.666667 744.533333 74.666667 704v-640c0-40.533333 34.133333-74.666667 74.666666-74.666667h725.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V704c0 40.533333-34.133333 74.666667-74.666666 74.666667zM138.666667 64V704c0 6.4 4.266667 10.666667 10.666666 10.666667h330.666667v-661.333334H149.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667z m746.666666 0c0-6.4-4.266667-10.666667-10.666666-10.666667H544v661.333334H874.666667c6.4 0 10.666667-4.266667 10.666666-10.666667v-640z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="complete" unicode="" d="M874.666667 394.666667c-17.066667 0-32-14.933333-32-32v-298.666667c0-6.4-4.266667-10.666667-10.666667-10.666667H192c-6.4 0-10.666667 4.266667-10.666667 10.666667V704c0 6.4 4.266667 10.666667 10.666667 10.666667h469.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H192C151.466667 778.666667 117.333333 744.533333 117.333333 704v-640c0-40.533333 34.133333-74.666667 74.666667-74.666667h640c40.533333 0 74.666667 34.133333 74.666667 74.666667V362.666667c0 17.066667-14.933333 32-32 32zM940.8 727.466667c-12.8 12.8-32 12.8-44.8 0l-390.4-384-106.666667 106.666666c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l130.133334-128c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333l411.733333 405.333334c8.533333 10.666667 10.666667 32-2.133333 44.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="chart-pie" unicode="" d="M887.466667 253.866667c-17.066667 6.4-34.133333 0-42.666667-17.066667-64-151.466667-221.866667-243.2-386.133333-221.866667-164.266667 21.333333-294.4 149.333333-315.733334 313.6C119.466667 490.666667 209.066667 650.666667 358.4 716.8c17.066667 6.4 23.466667 25.6 17.066667 42.666667-6.4 17.066667-25.6 23.466667-42.666667 17.066666C155.733333 697.6 51.2 509.866667 78.933333 317.866667c27.733333-192 179.2-343.466667 371.2-369.066667 19.2-2.133333 36.266667-4.266667 55.466667-4.266667 170.666667 0 330.666667 102.4 398.933333 264.533334 6.4 17.066667-2.133333 36.266667-17.066666 44.8zM814.933333 686.933333C727.466667 774.4 612.266667 821.333333 490.666667 821.333333c-17.066667 0-32-14.933333-32-32v-426.666666c0-17.066667 14.933333-32 32-32h426.666666c17.066667 0 32 14.933333 32 32 0 121.6-46.933333 236.8-134.4 324.266666zM522.666667 394.666667V755.2c93.866667-6.4 179.2-46.933333 247.466666-115.2 66.133333-66.133333 106.666667-153.6 115.2-247.466667h-362.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="cry" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333z m0-810.666666c-204.8 0-373.333333 168.533333-373.333333 373.333333S307.2 757.333333 512 757.333333 885.333333 588.8 885.333333 384 716.8 10.666667 512 10.666667zM512 298.666667c-81.066667 0-151.466667-36.266667-211.2-106.666667-10.666667-12.8-8.533333-34.133333 4.266667-44.8 12.8-10.666667 34.133333-8.533333 44.8 4.266667 46.933333 57.6 100.266667 85.333333 162.133333 85.333333s115.2-27.733333 162.133333-85.333333c6.4-8.533333 14.933333-10.666667 25.6-10.666667 6.4 0 14.933333 2.133333 21.333334 6.4 12.8 10.666667 14.933333 32 4.266666 44.8-61.866667 70.4-132.266667 106.666667-213.333333 106.666667zM362.666667 384c23.466667 0 42.666667 19.2 42.666666 42.666667v64c0 23.466667-19.2 42.666667-42.666666 42.666666s-42.666667-19.2-42.666667-42.666666v-64c0-23.466667 19.2-42.666667 42.666667-42.666667zM661.333333 384c23.466667 0 42.666667 19.2 42.666667 42.666667v64c0 23.466667-19.2 42.666667-42.666667 42.666666s-42.666667-19.2-42.666666-42.666666v-64c0-23.466667 19.2-42.666667 42.666666-42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="customer-service" unicode="" d="M864 456.533333V469.333333c0 194.133333-157.866667 352-352 352S160 663.466667 160 469.333333v-12.8c-36.266667-4.266667-64-36.266667-64-72.533333v-170.666667c0-40.533333 34.133333-74.666667 74.666667-74.666666h85.333333c40.533333 0 74.666667 34.133333 74.666667 74.666666v170.666667c0 40.533333-34.133333 74.666667-74.666667 74.666667h-32V469.333333c0 157.866667 130.133333 288 288 288S800 627.2 800 469.333333v-10.666666H768c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-170.666667c0-40.533333 34.133333-74.666667 74.666667-74.666666h21.333333c-17.066667-49.066667-59.733333-98.133333-179.2-106.666667-12.8 19.2-32 32-55.466666 32-36.266667 0-64-27.733333-64-64s27.733333-64 64-64c23.466667 0 44.8 12.8 55.466666 34.133333 166.4 10.666667 226.133333 91.733333 245.333334 170.666667 40.533333 2.133333 72.533333 34.133333 72.533333 74.666667v170.666666c0 36.266667-27.733333 66.133333-64 70.4z m-597.333333-72.533333v-170.666667c0-6.4-4.266667-10.666667-10.666667-10.666666H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666v170.666667c0 6.4 4.266667 10.666667 10.666667 10.666667h85.333333c6.4 0 10.666667-4.266667 10.666667-10.666667z m597.333333-170.666667c0-6.4-4.266667-10.666667-10.666667-10.666666h-85.333333c-6.4 0-10.666667 4.266667-10.666667 10.666666v170.666667c0 6.4 4.266667 10.666667 10.666667 10.666667h85.333333c6.4 0 10.666667-4.266667 10.666667-10.666667v-170.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="direction-down" unicode="" d="M898.133333 384c-12.8 12.8-32 12.8-44.8 2.133333L544 96V746.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-650.666667L170.666667 386.133333c-12.8 12.8-34.133333 10.666667-44.8-2.133333-12.8-12.8-10.666667-34.133333 2.133333-44.8l362.666667-341.333333c2.133333-2.133333 6.4-4.266667 8.533333-6.4 4.266667-2.133333 6.4-2.133333 10.666667-2.133334s8.533333 0 10.666666 2.133334c4.266667 2.133333 6.4 4.266667 8.533334 6.4l362.666666 341.333333c17.066667 12.8 19.2 32 6.4 44.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="copy" unicode="" d="M853.333333 672h-53.333333V725.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667H170.666667C130.133333 800 96 765.866667 96 725.333333v-554.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h53.333333V42.666667c0-40.533333 34.133333-74.666667 74.666667-74.666667h554.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V597.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667zM160 170.666667V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h554.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-554.666666c0-6.4-4.266667-10.666667-10.666667-10.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667z m704-128c0-6.4-4.266667-10.666667-10.666667-10.666667H298.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667v53.333333H725.333333c40.533333 0 74.666667 34.133333 74.666667 74.666667V608H853.333333c6.4 0 10.666667-4.266667 10.666667-10.666667v-554.666666zM576 480h-96V576c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-96H320c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h96V320c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v96H576c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="cut" unicode="" d="M917.333333 693.333333h-96V789.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-96H277.333333c-40.533333 0-74.666667-34.133333-74.666666-74.666666v-480H106.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h96V-21.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v96H746.666667c40.533333 0 74.666667 34.133333 74.666666 74.666666V629.333333H917.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM757.333333 149.333333c0-6.4-4.266667-10.666667-10.666666-10.666666H266.666667V618.666667c0 6.4 4.266667 10.666667 10.666666 10.666666h480V149.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="data-view" unicode="" d="M874.666667 32H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V746.666667c0 17.066667-14.933333 32-32 32S96 763.733333 96 746.666667v-704c0-40.533333 34.133333-74.666667 74.666667-74.666667h704c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM437.333333 426.666667v-320c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V426.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32zM298.666667 74.666667c17.066667 0 32 14.933333 32 32V362.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-256c0-17.066667 14.933333-32 32-32zM640 330.666667c-17.066667 0-32-14.933333-32-32v-192c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v192c0 17.066667-14.933333 32-32 32zM810.666667 544c-17.066667 0-32-14.933333-32-32v-405.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V512c0 17.066667-14.933333 32-32 32zM322.133333 488.533333l147.2 147.2 147.2-147.2c6.4-6.4 14.933333-8.533333 23.466667-8.533333h2.133333c8.533333 0 17.066667 6.4 23.466667 12.8l170.666667 234.666667c10.666667 14.933333 6.4 34.133333-6.4 44.8-14.933333 10.666667-34.133333 6.4-44.8-6.4l-149.333334-204.8L490.666667 706.133333c-12.8 12.8-32 12.8-44.8 0l-170.666667-170.666666c-12.8-12.8-12.8-32 0-44.8 12.8-12.8 34.133333-12.8 46.933333-2.133334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="direction-right" unicode="" d="M904.533333 373.333333c2.133333 4.266667 2.133333 6.4 2.133334 10.666667s0 8.533333-2.133334 10.666667c-2.133333 4.266667-4.266667 6.4-6.4 8.533333l-341.333333 362.666667c-12.8 12.8-32 12.8-44.8 2.133333-12.8-12.8-12.8-32-2.133333-44.8l290.133333-309.333333H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h650.666667L509.866667 42.666667c-12.8-12.8-10.666667-34.133333 2.133333-44.8 6.4-6.4 14.933333-8.533333 21.333333-8.533334 8.533333 0 17.066667 4.266667 23.466667 10.666667l341.333333 362.666667c2.133333 2.133333 4.266667 6.4 6.4 10.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="direction-up" unicode="" d="M896 428.8l-362.666667 341.333333c-2.133333 2.133333-6.4 4.266667-8.533333 6.4-4.266667 2.133333-6.4 2.133333-10.666667 2.133334s-8.533333 0-10.666666-2.133334c-4.266667-2.133333-6.4-4.266667-8.533334-6.4l-362.666666-341.333333c-12.8-12.8-12.8-32-2.133334-44.8 12.8-12.8 32-12.8 44.8-2.133333l309.333334 290.133333V21.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V672L853.333333 381.866667c6.4-6.4 14.933333-8.533333 21.333334-8.533334 8.533333 0 17.066667 4.266667 23.466666 10.666667 12.8 12.8 10.666667 32-2.133333 44.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="discount" unicode="" d="M874.666667 800H593.066667c-19.2 0-38.4-8.533333-53.333334-21.333333l-405.333333-405.333334c-29.866667-29.866667-29.866667-76.8 0-104.533333l260.266667-260.266667c14.933333-14.933333 32-21.333333 53.333333-21.333333s38.4 8.533333 53.333333 21.333333l405.333334 405.333334c14.933333 14.933333 21.333333 32 21.333333 53.333333V746.666667c0 29.866667-23.466667 53.333333-53.333333 53.333333z m-10.666667-334.933333c0-2.133333-2.133333-6.4-2.133333-8.533334l-405.333334-405.333333c-2.133333-2.133333-6.4-2.133333-8.533333-2.133333s-4.266667 0-8.533333 2.133333L181.333333 311.466667c-4.266667 4.266667-4.266667 10.666667 0 14.933333l405.333334 405.333333c2.133333 2.133333 4.266667 2.133333 8.533333 2.133334h270.933333v-268.8zM704 480c53.333333 0 96 42.666667 96 96s-42.666667 96-96 96-96-42.666667-96-96 42.666667-96 96-96z m0 128c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32-32 14.933333-32 32 14.933333 32 32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="direction-left" unicode="" d="M874.666667 416H224L514.133333 725.333333c12.8 12.8 10.666667 34.133333-2.133333 44.8s-32 10.666667-44.8-2.133333l-341.333333-362.666667c-2.133333-2.133333-4.266667-6.4-6.4-8.533333-2.133333-4.266667-2.133333-6.4-2.133334-10.666667s0-8.533333 2.133334-10.666666c2.133333-4.266667 4.266667-6.4 6.4-8.533334l341.333333-362.666666c6.4-6.4 14.933333-10.666667 23.466667-10.666667 8.533333 0 14.933333 2.133333 21.333333 8.533333 12.8 12.8 12.8 32 2.133333 44.8L224 352H874.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="download" unicode="" d="M896 224c-17.066667 0-32-14.933333-32-32v-128c0-6.4-4.266667-10.666667-10.666667-10.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667v128c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-128c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667v128c0 17.066667-14.933333 32-32 32zM488.533333 168.533333c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466667 8.533333l213.333333 213.333334c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-157.866667-157.866667V725.333333c0 17.066667-14.933333 32-32 32s-34.133333-14.933333-34.133333-32v-456.533333L322.133333 426.666667c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l211.2-213.333334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="electronics" unicode="" d="M840.533333 778.666667H183.466667c-59.733333 0-108.8-49.066667-108.8-108.8v-379.733334c0-59.733333 49.066667-108.8 108.8-108.8h232.533333v-115.2H341.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h341.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-74.666667v115.2h232.533333c59.733333 0 108.8 49.066667 108.8 108.8V669.866667c0 59.733333-49.066667 108.8-108.8 108.8zM544 66.133333h-64v115.2h64v-115.2z m341.333333 224c0-25.6-19.2-44.8-44.8-44.8H183.466667c-25.6 0-44.8 19.2-44.8 44.8V669.866667c0 25.6 19.2 44.8 44.8 44.8h657.066666c25.6 0 44.8-19.2 44.8-44.8v-379.733334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="drag" unicode="" d="M362.666667 704m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM661.333333 704m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM362.666667 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM661.333333 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM362.666667 64m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM661.333333 64m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="elipsis" unicode="" d="M192 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM512 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM832 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="export" unicode="" d="M582.4 32H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h309.333333V576c0-40.533333 34.133333-74.666667 74.666667-74.666667h160v-38.4c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V597.333333c0 8.533333-4.266667 17.066667-8.533334 23.466667l-170.666666 170.666667c-6.4 6.4-14.933333 8.533333-23.466667 8.533333H170.666667C130.133333 800 96 765.866667 96 725.333333v-682.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h411.733333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z m132.266667 550.4v-17.066667H554.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V736h19.2l151.466667-153.6zM866.133333 226.133333l-106.666666 106.666667c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l51.2-51.2H512c-17.066667 0-32-14.933333-32-32S494.933333 170.666667 512 170.666667h253.866667l-51.2-51.2c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466666-8.533334s17.066667 2.133333 23.466667 8.533334l106.666667 106.666666c8.533333 10.666667 8.533333 32-2.133334 44.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="explain" unicode="" d="M789.333333 821.333333H234.666667C194.133333 821.333333 160 787.2 160 746.666667v-725.333334c0-40.533333 34.133333-74.666667 74.666667-74.666666h554.666666c40.533333 0 74.666667 34.133333 74.666667 74.666666V746.666667c0 40.533333-34.133333 74.666667-74.666667 74.666666z m-138.666666-64v-296.533333L576 531.2c-6.4 6.4-14.933333 8.533333-21.333333 8.533333-8.533333 0-17.066667-2.133333-21.333334-8.533333l-74.666666-72.533333v298.666666h192z m149.333333-736c0-6.4-4.266667-10.666667-10.666667-10.666666H234.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V746.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h160v-322.133333c0-14.933333 6.4-27.733333 14.933333-36.266667 21.333333-21.333333 53.333333-21.333333 74.666667 0l70.4 68.266667 70.4-68.266667c10.666667-10.666667 23.466667-14.933333 36.266666-14.933333 29.866667 0 53.333333 23.466667 53.333334 53.333333v320H789.333333c6.4 0 10.666667-4.266667 10.666667-10.666666v-725.333334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="edit" unicode="" d="M853.333333 394.666667c-17.066667 0-32-14.933333-32-32v-320c0-6.4-4.266667-10.666667-10.666666-10.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V682.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h320c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666666v-640c0-40.533333 34.133333-74.666667 74.666667-74.666667h640c40.533333 0 74.666667 34.133333 74.666666 74.666667V362.666667c0 17.066667-14.933333 32-32 32zM405.333333 411.733333l-32-125.866666c-2.133333-10.666667 0-23.466667 8.533334-29.866667 6.4-6.4 14.933333-8.533333 23.466666-8.533333h8.533334l125.866666 32c6.4 2.133333 10.666667 4.266667 14.933334 8.533333l300.8 300.8c38.4 38.4 38.4 102.4 0 140.8-38.4 38.4-102.4 38.4-140.8 0L413.866667 426.666667c-4.266667-4.266667-6.4-8.533333-8.533334-14.933334z m59.733334-23.466666L761.6 682.666667c12.8 12.8 36.266667 12.8 49.066667 0 12.8-12.8 12.8-36.266667 0-49.066667L516.266667 337.066667l-66.133334-17.066667 14.933334 68.266667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="eye-close" unicode="" d="M955.733333 403.2c-6.4 12.8-162.133333 317.866667-443.733333 317.866667-23.466667 0-46.933333-2.133333-70.4-6.4-17.066667-4.266667-29.866667-19.2-25.6-36.266667 4.266667-17.066667 19.2-29.866667 36.266667-25.6 19.2 4.266667 38.4 4.266667 57.6 4.266667 209.066667 0 345.6-209.066667 379.733333-266.666667-10.666667-19.2-32-53.333333-64-91.733333-10.666667-12.8-8.533333-34.133333 4.266667-44.8 6.4-4.266667 12.8-6.4 21.333333-6.4s19.2 4.266667 25.6 10.666666c51.2 61.866667 78.933333 115.2 78.933333 117.333334 6.4 8.533333 6.4 19.2 0 27.733333zM215.466667 770.133333c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l91.733333-91.733333C138.666667 541.866667 72.533333 411.733333 68.266667 405.333333c-4.266667-8.533333-4.266667-19.2 0-29.866666 6.4-12.8 162.133333-315.733333 443.733333-315.733334 83.2 0 164.266667 27.733333 241.066667 81.066667l96-96c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333c12.8 12.8 12.8 32 0 44.8L215.466667 770.133333z m243.2-334.933333l104.533333-104.533333c-12.8-12.8-32-21.333333-51.2-21.333334-40.533333 0-74.666667 34.133333-74.666667 74.666667 0 19.2 8.533333 38.4 21.333334 51.2zM512 123.733333c-209.066667 0-345.6 209.066667-379.733333 266.666667 21.333333 36.266667 81.066667 130.133333 174.933333 196.266667l104.533333-104.533334c-25.6-25.6-38.4-59.733333-38.4-96 0-76.8 61.866667-138.666667 138.666667-138.666666 36.266667 0 70.4 14.933333 96 38.4l98.133333-98.133334c-61.866667-42.666667-128-64-194.133333-64z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="email" unicode="" d="M874.666667 714.666667H149.333333c-40.533333 0-74.666667-34.133333-74.666666-74.666667v-512c0-40.533333 34.133333-74.666667 74.666666-74.666667h725.333334c40.533333 0 74.666667 34.133333 74.666666 74.666667V640c0 40.533333-34.133333 74.666667-74.666666 74.666667z m-725.333334-64h725.333334c6.4 0 10.666667-4.266667 10.666666-10.666667v-25.6L512 379.733333l-373.333333 234.666667V640c0 6.4 4.266667 10.666667 10.666666 10.666667z m725.333334-533.333334H149.333333c-6.4 0-10.666667 4.266667-10.666666 10.666667V539.733333l356.266666-224c4.266667-4.266667 10.666667-4.266667 17.066667-4.266666s12.8 2.133333 17.066667 4.266666l356.266666 224V128c0-6.4-4.266667-10.666667-10.666666-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="favorite" unicode="" d="M934.4 539.733333c-8.533333 10.666667-21.333333 19.2-34.133333 21.333334l-234.666667 34.133333-104.533333 213.333333c-6.4 8.533333-14.933333 17.066667-25.6 23.466667-12.8 6.4-27.733333 6.4-40.533334 2.133333-12.8-4.266667-23.466667-14.933333-29.866666-27.733333l-104.533334-213.333333-234.666666-34.133334c-10.666667-2.133333-21.333333-6.4-29.866667-14.933333-21.333333-21.333333-19.2-55.466667 0-74.666667l170.666667-166.4-40.533334-234.666666c-2.133333-10.666667 0-23.466667 6.4-34.133334 12.8-25.6 46.933333-36.266667 72.533334-21.333333l211.2 110.933333 211.2-110.933333c8.533333-4.266667 17.066667-6.4 25.6-6.4h8.533333c14.933333 2.133333 25.6 10.666667 34.133333 21.333333 8.533333 10.666667 10.666667 25.6 8.533334 40.533334l-40.533334 234.666666 170.666667 166.4c8.533333 8.533333 14.933333 19.2 14.933333 29.866667-2.133333 14.933333-6.4 27.733333-14.933333 40.533333z m-224-194.133333c-12.8-12.8-19.2-29.866667-14.933333-46.933333l38.4-217.6L512 196.266667l-221.866667-115.2L328.533333 298.666667c2.133333 17.066667-2.133333 34.133333-14.933333 46.933333l-157.866667 153.6 219.733334 32c17.066667 2.133333 32 12.8 40.533333 29.866667L512 759.466667l98.133333-198.4c8.533333-14.933333 23.466667-27.733333 40.533334-29.866667l219.733333-32-160-153.6z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="file-common" unicode="" d="M832 821.333333H192c-17.066667 0-32-14.933333-32-32v-765.866666c0-12.8 4.266667-23.466667 12.8-34.133334 8.533333-10.666667 21.333333-17.066667 36.266667-19.2h6.4c12.8 0 23.466667 4.266667 34.133333 12.8l264.533333 213.333334 264.533334-213.333334c8.533333-8.533333 21.333333-12.8 34.133333-12.8 29.866667 0 53.333333 23.466667 53.333333 53.333334V789.333333c-2.133333 17.066667-17.066667 32-34.133333 32z m-32-776.533333L531.2 262.4c-10.666667 8.533333-27.733333 8.533333-40.533333 0L224 44.8V757.333333h576v-712.533333zM341.333333 554.666667h320c17.066667 0 32 14.933333 32 32S678.4 618.666667 661.333333 618.666667H341.333333c-17.066667 0-32-14.933333-32-32S324.266667 554.666667 341.333333 554.666667zM341.333333 384h213.333334c17.066667 0 32 14.933333 32 32S571.733333 448 554.666667 448H341.333333c-17.066667 0-32-14.933333-32-32S324.266667 384 341.333333 384z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="file-delete" unicode="" d="M842.666667 610.133333l-187.733334 187.733334c-14.933333 14.933333-32 21.333333-53.333333 21.333333H234.666667C194.133333 821.333333 160 787.2 160 746.666667v-725.333334c0-40.533333 34.133333-74.666667 74.666667-74.666666h554.666666c40.533333 0 74.666667 34.133333 74.666667 74.666666V558.933333c0 19.2-8.533333 38.4-21.333333 51.2z m-44.8-44.8c-2.133333-2.133333-4.266667 0-8.533334 0h-170.666666c-6.4 0-10.666667 4.266667-10.666667 10.666667V746.666667c0 2.133333 0 6.4-2.133333 8.533333 0 0 2.133333 0 2.133333-2.133333l189.866667-187.733334z m-8.533334-554.666666H234.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V746.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h311.466666c-2.133333-4.266667-2.133333-6.4-2.133333-10.666666v-170.666667c0-40.533333 34.133333-74.666667 74.666667-74.666667h170.666666c4.266667 0 6.4 0 10.666667 2.133334V21.333333c0-6.4-4.266667-10.666667-10.666667-10.666666zM640 309.333333H384c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h256c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="file-add" unicode="" d="M842.666667 610.133333l-187.733334 187.733334c-14.933333 14.933333-32 21.333333-53.333333 21.333333H234.666667C194.133333 821.333333 160 787.2 160 746.666667v-725.333334c0-40.533333 34.133333-74.666667 74.666667-74.666666h554.666666c40.533333 0 74.666667 34.133333 74.666667 74.666666V558.933333c0 19.2-8.533333 38.4-21.333333 51.2z m-44.8-44.8H618.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V755.2l189.866667-189.866667z m-8.533334-554.666666H234.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V746.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h309.333333V576c0-40.533333 34.133333-74.666667 74.666667-74.666667h181.333333V21.333333c0-6.4-4.266667-10.666667-10.666667-10.666666zM618.666667 309.333333h-74.666667V384c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-74.666667H405.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h74.666667V170.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v74.666666H618.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="fabulous" unicode="" d="M859.733333 642.133333c-44.8 44.8-102.4 70.4-166.4 70.4-61.866667 0-121.6-25.6-166.4-70.4l-14.933333-17.066666-17.066667 17.066666c-44.8 44.8-102.4 70.4-166.4 70.4-61.866667 0-121.6-25.6-166.4-70.4-91.733333-91.733333-91.733333-243.2 0-337.066666l324.266667-330.666667c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 4.266667 23.466666 8.533333l324.266667 330.666667c44.8 44.8 68.266667 104.533333 68.266667 168.533333s-21.333333 123.733333-66.133334 168.533333z m-44.8-290.133333L512 42.666667 209.066667 352c-66.133333 68.266667-66.133333 179.2 0 247.466667 32 32 74.666667 51.2 119.466666 51.2 44.8 0 87.466667-17.066667 119.466667-51.2l38.4-40.533334c12.8-12.8 34.133333-12.8 44.8 0l38.4 40.533334c32 32 74.666667 51.2 119.466667 51.2 44.8 0 87.466667-17.066667 119.466666-51.2 32-32 49.066667-76.8 49.066667-123.733334s-12.8-91.733333-42.666667-123.733333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="file" unicode="" d="M842.666667 610.133333l-187.733334 187.733334c-14.933333 14.933333-32 21.333333-53.333333 21.333333H234.666667C194.133333 821.333333 160 787.2 160 746.666667v-725.333334c0-40.533333 34.133333-74.666667 74.666667-74.666666h554.666666c40.533333 0 74.666667 34.133333 74.666667 74.666666V558.933333c0 19.2-8.533333 38.4-21.333333 51.2z m-44.8-44.8c-2.133333-2.133333-4.266667 0-8.533334 0h-170.666666c-6.4 0-10.666667 4.266667-10.666667 10.666667V746.666667c0 2.133333 0 6.4-2.133333 8.533333 0 0 2.133333 0 2.133333-2.133333l189.866667-187.733334z m-8.533334-554.666666H234.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V746.666667c0 6.4 4.266667 10.666667 10.666667 10.666666h311.466666c-2.133333-4.266667-2.133333-6.4-2.133333-10.666666v-170.666667c0-40.533333 34.133333-74.666667 74.666667-74.666667h170.666666c4.266667 0 6.4 0 10.666667 2.133334V21.333333c0-6.4-4.266667-10.666667-10.666667-10.666666zM640 202.666667H341.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h298.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM640 373.333333H341.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h298.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM341.333333 480h85.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-85.333334c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="folder-close" unicode="" d="M853.333333 629.333333H514.133333c-4.266667 0-6.4 2.133333-8.533333 4.266667l-38.4 66.133333c-12.8 21.333333-38.4 36.266667-64 36.266667H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-554.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V554.666667c0 40.533333-34.133333 74.666667-74.666667 74.666666z m-682.666666 42.666667h232.533333c4.266667 0 6.4-2.133333 8.533333-4.266667l38.4-66.133333c12.8-21.333333 38.4-36.266667 64-36.266667H853.333333c6.4 0 10.666667-4.266667 10.666667-10.666666v-74.666667h-704V661.333333c0 6.4 4.266667 10.666667 10.666667 10.666667z m682.666666-576H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V416h704V106.666667c0-6.4-4.266667-10.666667-10.666667-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="good" unicode="" d="M881.066667 501.333333c-21.333333 23.466667-51.2 36.266667-81.066667 36.266667H618.666667v117.333333c0 44.8-29.866667 85.333333-87.466667 117.333334-17.066667 10.666667-38.4 12.8-57.6 8.533333-19.2-4.266667-36.266667-17.066667-46.933333-34.133333-2.133333-2.133333-2.133333-4.266667-4.266667-6.4l-125.866667-281.6H204.8c-59.733333 0-108.8-46.933333-108.8-106.666667v-258.133333c0-57.6 49.066667-106.666667 108.8-106.666667h544c53.333333 0 98.133333 38.4 106.666667 89.6l51.2 337.066667c4.266667 34.133333-6.4 64-25.6 87.466666z m-593.066667-448H204.8c-25.6 0-44.8 19.2-44.8 42.666667v256c0 23.466667 19.2 42.666667 44.8 42.666667h83.2v-341.333334z m554.666667 373.333334L789.333333 89.6c-4.266667-21.333333-21.333333-36.266667-42.666666-36.266667H352V424.533333l130.133333 290.133334c2.133333 4.266667 4.266667 4.266667 6.4 4.266666 2.133333 0 4.266667 0 8.533334-2.133333 25.6-14.933333 55.466667-38.4 55.466666-64v-149.333333c0-17.066667 14.933333-32 32-32h213.333334c12.8 0 25.6-4.266667 34.133333-14.933334 8.533333-6.4 12.8-19.2 10.666667-29.866666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="hide" unicode="" d="M917.333333 322.133333l-87.466666 87.466667c34.133333 32 66.133333 68.266667 91.733333 108.8 8.533333 14.933333 4.266667 34.133333-10.666667 44.8-14.933333 8.533333-34.133333 4.266667-44.8-10.666667-76.8-125.866667-209.066667-200.533333-356.266666-200.533333-145.066667 0-279.466667 74.666667-354.133334 198.4-8.533333 14.933333-29.866667 19.2-44.8 10.666667-14.933333-8.533333-19.2-29.866667-10.666666-44.8 25.6-40.533333 55.466667-76.8 91.733333-108.8l-85.333333-85.333334c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333l91.733333 91.733334c38.4-25.6 81.066667-46.933333 125.866667-59.733334l-34.133333-130.133333c-4.266667-17.066667 6.4-34.133333 23.466666-38.4 2.133333 0 6.4-2.133333 8.533334-2.133333 14.933333 0 27.733333 8.533333 29.866666 23.466666l36.266667 132.266667c25.6-4.266667 51.2-6.4 78.933333-6.4 27.733333 0 55.466667 2.133333 83.2 6.4l36.266667-132.266667c4.266667-14.933333 17.066667-23.466667 29.866667-23.466666 2.133333 0 6.4 0 8.533333 2.133333 17.066667 4.266667 27.733333 21.333333 23.466667 38.4L661.333333 311.466667c44.8 12.8 85.333333 34.133333 123.733334 59.733333l91.733333-91.733333c6.4-6.4 14.933333-8.533333 23.466667-8.533334s17.066667 2.133333 23.466666 8.533334c6.4 10.666667 6.4 29.866667-6.4 42.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="file-open" unicode="" d="M921.6 445.866667c-6.4 8.533333-14.933333 12.8-25.6 12.8h-10.666667V554.666667c0 40.533333-34.133333 74.666667-74.666666 74.666666H514.133333c-4.266667 0-6.4 2.133333-8.533333 4.266667l-38.4 66.133333c-12.8 21.333333-38.4 36.266667-64 36.266667H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-597.333333c0-6.4 2.133333-12.8 6.4-19.2 6.4-8.533333 14.933333-12.8 25.6-12.8h640c12.8 0 25.6 8.533333 29.866667 21.333333l128 362.666667c4.266667 10.666667 2.133333 21.333333-4.266667 29.866667zM170.666667 672h232.533333c4.266667 0 6.4-2.133333 8.533333-4.266667l38.4-66.133333c12.8-21.333333 38.4-36.266667 64-36.266667H810.666667c6.4 0 10.666667-4.266667 10.666666-10.666666v-96H256c-12.8 0-25.6-8.533333-29.866667-21.333334l-66.133333-185.6V661.333333c0 6.4 4.266667 10.666667 10.666667 10.666667z m573.866666-576H172.8l104.533333 298.666667h571.733334l-104.533334-298.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="forward" unicode="" d="M853.333333 138.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666666V576c0 6.4 4.266667 10.666667 10.666667 10.666667h599.466666l-83.2-83.2c-12.8-12.8-12.8-34.133333 0-46.933334 6.4-6.4 14.933333-10.666667 23.466667-10.666666s17.066667 4.266667 23.466667 10.666666l145.066666 145.066667c12.8 12.8 12.8 34.133333 0 46.933333l-145.066666 145.066667c-12.8 12.8-34.133333 12.8-46.933334 0-12.8-12.8-12.8-34.133333 0-46.933333l93.866667-93.866667H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-426.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c17.066667 0 32 14.933333 32 32s-14.933333 29.866667-32 29.866667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="import" unicode="" d="M667.733333 32H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h309.333333V576c0-40.533333 34.133333-74.666667 74.666667-74.666667h160v-38.4c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V597.333333c0 8.533333-4.266667 17.066667-8.533334 23.466667l-170.666666 170.666667c-6.4 6.4-14.933333 8.533333-23.466667 8.533333H170.666667C130.133333 800 96 765.866667 96 725.333333v-682.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h497.066666c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z m46.933334 550.4v-17.066667H554.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V736h19.2l151.466667-153.6zM853.333333 298.666667H599.466667l51.2 51.2c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-106.666667-106.666667c-12.8-12.8-12.8-32 0-44.8l106.666667-106.666667c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333c12.8 12.8 12.8 32 0 44.8L599.466667 234.666667H853.333333c17.066667 0 32 14.933333 32 32S870.4 298.666667 853.333333 298.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="link" unicode="" d="M861.866667 731.733333c-87.466667 87.466667-230.4 89.6-320 2.133334l-68.266667-68.266667c-12.8-12.8-12.8-32 0-44.8s32-12.8 44.8 0l68.266667 68.266667c64 61.866667 166.4 61.866667 230.4-2.133334 64-64 64-168.533333 2.133333-232.533333l-117.333333-119.466667c-34.133333-34.133333-81.066667-51.2-128-49.066666-46.933333 4.266667-91.733333 27.733333-119.466667 66.133333-10.666667 14.933333-29.866667 17.066667-44.8 6.4-14.933333-10.666667-17.066667-29.866667-6.4-44.8 40.533333-53.333333 100.266667-87.466667 166.4-91.733333h17.066667c59.733333 0 119.466667 23.466667 162.133333 68.266666l117.333333 119.466667c83.2 89.6 83.2 234.666667-4.266666 322.133333zM505.6 145.066667l-66.133333-68.266667c-64-61.866667-166.4-61.866667-230.4 2.133333-64 64-64 168.533333-2.133334 232.533334l117.333334 119.466666c34.133333 34.133333 81.066667 51.2 128 49.066667 46.933333-4.266667 91.733333-27.733333 119.466666-66.133333 10.666667-14.933333 29.866667-17.066667 44.8-6.4 14.933333 10.666667 17.066667 29.866667 6.4 44.8-40.533333 53.333333-100.266667 87.466667-166.4 91.733333-66.133333 4.266667-130.133333-19.2-177.066666-66.133333l-117.333334-119.466667c-85.333333-89.6-85.333333-234.666667 2.133334-322.133333 44.8-44.8 102.4-66.133333 162.133333-66.133334 57.6 0 115.2 21.333333 160 64l66.133333 68.266667c12.8 12.8 12.8 32 0 44.8-14.933333 10.666667-34.133333 10.666667-46.933333-2.133333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="layout" unicode="" d="M853.333333 800H170.666667C130.133333 800 96 765.866667 96 725.333333v-682.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V725.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667z m-682.666666-64h682.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-213.333333h-704V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667zM160 42.666667V448H341.333333v-416H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667z m693.333333-10.666667H405.333333V448h458.666667v-405.333333c0-6.4-4.266667-10.666667-10.666667-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="fullscreen-shrink" unicode="" d="M313.6 537.6H177.066667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h213.333333c4.266667 0 8.533333 0 10.666667 2.133333 8.533333 4.266667 14.933333 8.533333 17.066666 17.066667 2.133333 4.266667 2.133333 8.533333 2.133334 10.666667v213.333333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-136.533333L172.8 770.133333c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l185.6-187.733333zM695.466667 245.333333H832c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H618.666667c-4.266667 0-8.533333 0-10.666667-2.133333-8.533333-4.266667-14.933333-8.533333-17.066667-17.066667-2.133333-4.266667-2.133333-8.533333-2.133333-10.666666v-213.333334c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v136.533334l200.533333-200.533334c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466667 8.533333c12.8 12.8 12.8 32 0 44.8l-204.8 198.4zM435.2 290.133333c-4.266667 8.533333-8.533333 14.933333-17.066667 17.066667-4.266667 2.133333-8.533333 2.133333-10.666666 2.133333H192c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h136.533333L128 44.8c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333l200.533334 200.533333V64c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V277.333333c-2.133333 4.266667-2.133333 8.533333-4.266667 12.8zM603.733333 492.8c4.266667-8.533333 8.533333-14.933333 17.066667-17.066667 4.266667-2.133333 8.533333-2.133333 10.666667-2.133333h213.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-136.533333L896 725.333333c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-187.733333-187.733333V718.933333c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-213.333333c2.133333-4.266667 2.133333-8.533333 4.266666-12.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="layers" unicode="" d="M110.933333 544l384-192c4.266667-2.133333 10.666667-4.266667 17.066667-4.266667s10.666667 2.133333 17.066667 4.266667l384 192c12.8 6.4 19.2 19.2 19.2 32s-8.533333 25.6-19.2 32l-384 192c-10.666667 4.266667-21.333333 4.266667-32 0l-384-192c-12.8-6.4-19.2-19.2-19.2-32s6.4-25.6 17.066666-32zM512 727.466667L814.933333 576 512 424.533333 209.066667 576 512 727.466667zM878.933333 224L512 40.533333 145.066667 224c-17.066667 8.533333-38.4 2.133333-49.066667-17.066667-8.533333-17.066667-2.133333-38.4 17.066667-49.066666l384-192c4.266667-2.133333 10.666667-4.266667 17.066666-4.266667s10.666667 2.133333 17.066667 4.266667l384 192c17.066667 8.533333 25.6 29.866667 17.066667 49.066666-12.8 19.2-34.133333 25.6-53.333334 17.066667zM878.933333 416L512 232.533333 145.066667 416c-17.066667 8.533333-38.4 2.133333-49.066667-17.066667-8.533333-17.066667-2.133333-38.4 17.066667-49.066666l384-192c4.266667-2.133333 10.666667-4.266667 17.066666-4.266667s10.666667 2.133333 17.066667 4.266667l384 192c17.066667 8.533333 25.6 29.866667 17.066667 49.066666-12.8 19.2-34.133333 25.6-53.333334 17.066667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="lock" unicode="" d="M785.066667 480h-61.866667v121.6c0 108.8-91.733333 198.4-202.666667 198.4s-202.666667-89.6-202.666666-198.4v-121.6h-78.933334c-55.466667 0-100.266667-44.8-100.266666-100.266667v-311.466666c0-55.466667 44.8-100.266667 100.266666-100.266667h546.133334c55.466667 0 100.266667 44.8 100.266666 100.266667V379.733333c0 55.466667-44.8 100.266667-100.266666 100.266667z m-403.2 121.6c0 74.666667 61.866667 134.4 138.666666 134.4s138.666667-59.733333 138.666667-134.4v-121.6h-277.333333v121.6z m439.466666-533.333333c0-19.2-17.066667-36.266667-36.266666-36.266667H238.933333c-19.2 0-36.266667 17.066667-36.266666 36.266667V379.733333c0 19.2 17.066667 36.266667 36.266666 36.266667h546.133334c19.2 0 36.266667-17.066667 36.266666-36.266667v-311.466666zM512 352c-17.066667 0-32-14.933333-32-32v-106.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v106.666667c0 17.066667-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="fullscreen-expand" unicode="" d="M149.333333 501.333333c17.066667 0 32 14.933333 32 32v136.533334l187.733334-187.733334c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333c12.8 12.8 12.8 32 0 44.8l-187.733333 187.733334H362.666667c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H149.333333c-4.266667 0-8.533333 0-10.666666-2.133334-8.533333-4.266667-14.933333-10.666667-19.2-17.066666-2.133333-4.266667-2.133333-8.533333-2.133334-12.8v-213.333334c0-17.066667 14.933333-32 32-32zM874.666667 266.666667c-17.066667 0-32-14.933333-32-32v-136.533334L642.133333 298.666667c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l200.533334-200.533334H661.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h213.333334c4.266667 0 8.533333 0 10.666666 2.133334 8.533333 4.266667 14.933333 8.533333 17.066667 17.066666 2.133333 4.266667 2.133333 8.533333 2.133333 10.666667V234.666667c2.133333 17.066667-12.8 32-29.866666 32zM381.866667 300.8l-200.533334-200.533333V234.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-213.333334c0-4.266667 0-8.533333 2.133334-10.666666 4.266667-8.533333 8.533333-14.933333 17.066666-17.066667 4.266667-2.133333 8.533333-2.133333 10.666667-2.133333h213.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-136.533333l200.533333 200.533333c12.8 12.8 12.8 32 0 44.8s-29.866667 10.666667-42.666666 0zM904.533333 757.333333c0 2.133333 0 2.133333 0 0-4.266667 8.533333-10.666667 14.933333-17.066666 17.066667-4.266667 2.133333-8.533333 2.133333-10.666667 2.133333H661.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h136.533334l-187.733334-187.733333c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466667 8.533333l187.733333 187.733333V533.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V746.666667c-2.133333 4.266667-2.133333 8.533333-4.266667 10.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="map" unicode="" d="M512 821.333333C317.866667 821.333333 160 661.333333 160 467.2c0-264.533333 320-484.266667 334.933333-492.8 6.4-4.266667 10.666667-6.4 17.066667-6.4s12.8 2.133333 17.066667 6.4c12.8 8.533333 334.933333 228.266667 334.933333 492.8C864 661.333333 706.133333 821.333333 512 821.333333z m0-782.933333c-66.133333 49.066667-288 228.266667-288 426.666667 0 160 130.133333 290.133333 288 290.133333s288-130.133333 288-290.133333c0-196.266667-221.866667-377.6-288-426.666667zM512 586.666667c-76.8 0-138.666667-61.866667-138.666667-138.666667s61.866667-138.666667 138.666667-138.666667 138.666667 61.866667 138.666667 138.666667-61.866667 138.666667-138.666667 138.666667z m0-213.333334c-40.533333 0-74.666667 34.133333-74.666667 74.666667s34.133333 74.666667 74.666667 74.666667 74.666667-34.133333 74.666667-74.666667-34.133333-74.666667-74.666667-74.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="meh" unicode="" d="M512-53.333333C270.933333-53.333333 74.666667 142.933333 74.666667 384S270.933333 821.333333 512 821.333333 949.333333 625.066667 949.333333 384 753.066667-53.333333 512-53.333333z m0 810.666666C307.2 757.333333 138.666667 588.8 138.666667 384S307.2 10.666667 512 10.666667 885.333333 179.2 885.333333 384 716.8 757.333333 512 757.333333zM362.666667 384c-23.466667 0-42.666667 19.2-42.666667 42.666667v64c0 23.466667 19.2 42.666667 42.666667 42.666666s42.666667-19.2 42.666666-42.666666v-64c0-23.466667-19.2-42.666667-42.666666-42.666667zM661.333333 384c-23.466667 0-42.666667 19.2-42.666666 42.666667v64c0 23.466667 19.2 42.666667 42.666666 42.666666s42.666667-19.2 42.666667-42.666666v-64c0-23.466667-19.2-42.666667-42.666667-42.666667zM699.733333 181.333333H324.266667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h373.333333c17.066667 0 32-14.933333 32-32s-12.8-32-29.866667-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="menu" unicode="" d="M170.666667 682.666667m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM170.666667 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM170.666667 85.333333m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM896 117.333333H362.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h533.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM362.666667 650.666667h533.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H362.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32zM896 416H362.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h533.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="loading" unicode="" d="M512 821.333333c-17.066667 0-32-14.933333-32-32v-149.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V789.333333c0 17.066667-14.933333 32-32 32zM693.333333 533.333333c8.533333 0 17.066667 2.133333 23.466667 8.533334l104.533333 104.533333c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-104.533333-104.533333c-12.8-12.8-12.8-32 0-44.8 4.266667-6.4 12.8-8.533333 21.333333-8.533334zM917.333333 416h-149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h149.333333c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM714.666667 226.133333c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l104.533333-104.533333c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333c12.8 12.8 12.8 32 0 44.8l-106.666666 104.533333zM512 160c-17.066667 0-32-14.933333-32-32v-149.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v149.333333c0 17.066667-14.933333 32-32 32zM309.333333 226.133333l-104.533333-104.533333c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333l104.533334 104.533333c12.8 12.8 12.8 32 0 44.8s-36.266667 12.8-46.933334 0zM288 384c0 17.066667-14.933333 32-32 32H106.666667c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h149.333333c17.066667 0 32 14.933333 32 32zM247.466667 693.333333c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l104.533333-104.533333c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333c12.8 12.8 12.8 32 0 44.8l-106.666666 104.533333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="help" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333z m0-810.666666c-204.8 0-373.333333 168.533333-373.333333 373.333333S307.2 757.333333 512 757.333333 885.333333 588.8 885.333333 384 716.8 10.666667 512 10.666667zM512 149.333333m-42.666667 0a42.666667 42.666667 0 1 1 85.333334 0 42.666667 42.666667 0 1 1-85.333334 0ZM512 650.666667c-76.8 0-138.666667-61.866667-138.666667-138.666667 0-17.066667 14.933333-32 32-32s32 14.933333 32 32c0 40.533333 34.133333 74.666667 74.666667 74.666667s74.666667-34.133333 74.666667-74.666667c0-27.733333-53.333333-76.8-91.733334-100.266667-8.533333-6.4-14.933333-17.066667-14.933333-27.733333v-106.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v89.6c34.133333 25.6 106.666667 83.2 106.666667 145.066667 0 76.8-61.866667 138.666667-138.666667 138.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="modular" unicode="" d="M405.333333 437.333333H149.333333c-29.866667 0-53.333333 23.466667-53.333333 53.333334V746.666667c0 29.866667 23.466667 53.333333 53.333333 53.333333h256c29.866667 0 53.333333-23.466667 53.333334-53.333333v-256c0-29.866667-23.466667-53.333333-53.333334-53.333334z m-245.333333 64h234.666667v234.666667h-234.666667v-234.666667zM874.666667 437.333333H618.666667c-29.866667 0-53.333333 23.466667-53.333334 53.333334V746.666667c0 29.866667 23.466667 53.333333 53.333334 53.333333h256c29.866667 0 53.333333-23.466667 53.333333-53.333333v-256c0-29.866667-23.466667-53.333333-53.333333-53.333334z m-245.333334 64h234.666667v234.666667h-234.666667v-234.666667zM874.666667-32H618.666667c-29.866667 0-53.333333 23.466667-53.333334 53.333333V277.333333c0 29.866667 23.466667 53.333333 53.333334 53.333334h256c29.866667 0 53.333333-23.466667 53.333333-53.333334v-256c0-29.866667-23.466667-53.333333-53.333333-53.333333z m-245.333334 64h234.666667v234.666667h-234.666667v-234.666667zM405.333333-32H149.333333c-29.866667 0-53.333333 23.466667-53.333333 53.333333V277.333333c0 29.866667 23.466667 53.333333 53.333333 53.333334h256c29.866667 0 53.333333-23.466667 53.333334-53.333334v-256c0-29.866667-23.466667-53.333333-53.333334-53.333333z m-245.333333 64h234.666667v234.666667h-234.666667v-234.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="notification" unicode="" d="M800 270.933333V448c0 117.333333-70.4 217.6-170.666667 262.4-4.266667 61.866667-55.466667 110.933333-117.333333 110.933333s-113.066667-49.066667-117.333333-110.933333c-100.266667-44.8-170.666667-145.066667-170.666667-262.4v-177.066667c-57.6-46.933333-85.333333-110.933333-85.333333-185.6 0-17.066667 14.933333-32 32-32h206.933333c14.933333-61.866667 70.4-106.666667 134.4-106.666666s119.466667 44.8 134.4 106.666666H853.333333c17.066667 0 32 14.933333 32 32 0 76.8-27.733333 138.666667-85.333333 185.6zM512 757.333333c19.2 0 36.266667-10.666667 44.8-25.6-14.933333 2.133333-29.866667 4.266667-44.8 4.266667-14.933333 0-29.866667-2.133333-44.8-4.266667 8.533333 14.933333 25.6 25.6 44.8 25.6z m0-746.666666c-29.866667 0-55.466667 17.066667-66.133333 42.666666h134.4c-12.8-25.6-38.4-42.666667-68.266667-42.666666z m-307.2 106.666666c6.4 46.933333 29.866667 83.2 70.4 113.066667 8.533333 6.4 12.8 14.933333 12.8 25.6v192c0 123.733333 100.266667 224 224 224S736 571.733333 736 448v-192c0-10.666667 4.266667-19.2 12.8-25.6 40.533333-29.866667 64-66.133333 70.4-113.066667H204.8z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="mic" unicode="" d="M516.266667 238.933333c78.933333 0 142.933333 64 142.933333 142.933334V678.4a142.933333 142.933333 0 0 1-285.866667 0v-296.533333c0-78.933333 64-142.933333 142.933334-142.933334z m-78.933334 439.466667c0 42.666667 36.266667 78.933333 78.933334 78.933333s78.933333-36.266667 78.933333-78.933333v-296.533333c0-42.666667-36.266667-78.933333-78.933333-78.933334s-78.933333 36.266667-78.933334 78.933334V678.4zM774.4 486.4c-17.066667 0-32-14.933333-32-32v-74.666667c0-125.866667-102.4-228.266667-228.266667-228.266666S288 256 288 381.866667v74.666666c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-74.666666c0-149.333333 113.066667-273.066667 260.266667-290.133334v-85.333333h-117.333334c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h296.533334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-117.333334v85.333333c145.066667 14.933333 260.266667 140.8 260.266667 290.133334v74.666666c0 17.066667-12.8 29.866667-32 29.866667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="operation" unicode="" d="M823.466667 384H578.133333v187.733333c0 66.133333-53.333333 119.466667-117.333333 119.466667s-117.333333-53.333333-117.333333-119.466667v-296.533333l-21.333334 21.333333c-46.933333 46.933333-121.6 46.933333-168.533333 2.133334s-44.8-121.6 2.133333-168.533334l174.933334-174.933333c6.4-6.4 14.933333-8.533333 23.466666-8.533333 8.533333 0 17.066667 2.133333 23.466667 8.533333 12.8 12.8 12.8 32 0 44.8l-174.933333 174.933333c-21.333333 21.333333-23.466667 57.6-2.133334 76.8 21.333333 21.333333 55.466667 19.2 76.8-2.133333l74.666667-74.666667c12.8-12.8 32-12.8 44.8 0 6.4 6.4 8.533333 14.933333 8.533333 23.466667V569.6c0 29.866667 23.466667 55.466667 53.333334 55.466667s53.333333-25.6 53.333333-55.466667v-219.733333c0-17.066667 14.933333-32 32-32h277.333333c6.4 0 10.666667-6.4 10.666667-12.8V-21.333333c0-17.066667 14.933333-32 32-32S896-38.4 896-21.333333V309.333333c2.133333 40.533333-32 74.666667-72.533333 74.666667zM266.666667 565.333333c17.066667 0 32 14.933333 32 32 0 87.466667 72.533333 160 160 160S618.666667 684.8 618.666667 597.333333c0-17.066667 14.933333-32 32-32S682.666667 580.266667 682.666667 597.333333c0 123.733333-100.266667 224-224 224S234.666667 721.066667 234.666667 597.333333c0-17.066667 14.933333-32 32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="print" unicode="" d="M819.2 531.2h-44.8V768c0 17.066667-14.933333 32-32 32H281.6c-17.066667 0-32-14.933333-32-32v-236.8H204.8c-59.733333 0-108.8-49.066667-108.8-108.8v-192c0-59.733333 49.066667-108.8 108.8-108.8h44.8V0c0-17.066667 14.933333-32 32-32h460.8c17.066667 0 32 14.933333 32 32v121.6h44.8c59.733333 0 108.8 49.066667 108.8 108.8v192c0 59.733333-49.066667 108.8-108.8 108.8zM313.6 736h396.8v-204.8H313.6V736z m396.8-704H313.6V275.2h396.8v-243.2z m153.6 198.4c0-25.6-19.2-44.8-44.8-44.8h-44.8v121.6c0 17.066667-14.933333 32-32 32H281.6c-17.066667 0-32-14.933333-32-32v-121.6H204.8c-25.6 0-44.8 19.2-44.8 44.8v192c0 25.6 19.2 44.8 44.8 44.8h614.4c25.6 0 44.8-19.2 44.8-44.8v-192z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="mobile-phone" unicode="" d="M746.666667-53.333333H277.333333c-40.533333 0-74.666667 34.133333-74.666666 74.666666V746.666667c0 40.533333 34.133333 74.666667 74.666666 74.666666h469.333334c40.533333 0 74.666667-34.133333 74.666666-74.666666v-725.333334c0-40.533333-34.133333-74.666667-74.666666-74.666666z m-469.333334 810.666666c-6.4 0-10.666667-4.266667-10.666666-10.666666v-725.333334c0-6.4 4.266667-10.666667 10.666666-10.666666h469.333334c6.4 0 10.666667 4.266667 10.666666 10.666666V746.666667c0 6.4-4.266667 10.666667-10.666666 10.666666H277.333333zM512 128m-42.666667 0a42.666667 42.666667 0 1 1 85.333334 0 42.666667 42.666667 0 1 1-85.333334 0ZM597.333333 650.666667h-170.666666c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h170.666666c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="navigation" unicode="" d="M834.133333 682.666667c-6.4 12.8-17.066667 23.466667-29.866666 27.733333-12.8 4.266667-27.733333 4.266667-40.533334-2.133333L106.666667 394.666667c-14.933333-6.4-25.6-21.333333-29.866667-36.266667-6.4-27.733333 12.8-57.6 40.533333-64l249.6-53.333333 53.333334-249.6c4.266667-17.066667 14.933333-29.866667 29.866666-36.266667 6.4-4.266667 14.933333-4.266667 23.466667-4.266667 19.2 0 38.4 10.666667 49.066667 29.866667l313.6 657.066667c6.4 12.8 6.4 29.866667-2.133334 44.8zM477.866667 34.133333L426.666667 273.066667c-2.133333 12.8-12.8 21.333333-23.466667 23.466666L162.133333 349.866667l601.6 288-285.866666-603.733334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="move" unicode="" d="M921.6 403.2l-121.6 121.6c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l66.133333-66.133333h-277.333333v277.333333l66.133333-66.133333c6.4-6.4 14.933333-8.533333 23.466667-8.533334s17.066667 2.133333 23.466667 8.533334c12.8 12.8 12.8 32 0 44.8l-121.6 121.6c-12.8 12.8-32 12.8-44.8 0l-121.6-121.6c-12.8-12.8-12.8-32 0-44.8 12.8-12.8 32-12.8 44.8 0l66.133333 66.133333v-277.333333h-277.333333l66.133333 66.133333c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-121.6-121.6c-12.8-12.8-12.8-32 0-44.8l121.6-121.6c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333c12.8 12.8 12.8 32 0 44.8l-66.133333 66.133333h277.333333v-277.333333l-66.133333 66.133333c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l121.6-121.6c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333l121.6 121.6c12.8 12.8 12.8 32 0 44.8s-32 12.8-44.8 0l-66.133333-66.133333v277.333333h277.333333l-66.133333-66.133333c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333l121.6 121.6c6.4 6.4 8.533333 14.933333 8.533334 23.466667s-10.666667 14.933333-17.066667 21.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="refresh" unicode="" d="M934.4 689.066667c-17.066667 4.266667-34.133333-6.4-38.4-23.466667l-23.466667-87.466667C797.866667 712.533333 654.933333 800 497.066667 800 264.533333 800 74.666667 614.4 74.666667 384s189.866667-416 422.4-416c179.2 0 339.2 110.933333 398.933333 275.2 6.4 17.066667-2.133333 34.133333-19.2 40.533333-17.066667 6.4-34.133333-2.133333-40.533333-19.2-51.2-138.666667-187.733333-232.533333-339.2-232.533333C298.666667 32 138.666667 189.866667 138.666667 384S300.8 736 497.066667 736c145.066667 0 277.333333-87.466667 330.666666-217.6l-128 36.266667c-17.066667 4.266667-34.133333-6.4-38.4-23.466667-4.266667-17.066667 6.4-34.133333 23.466667-38.4l185.6-49.066667c2.133333 0 6.4-2.133333 8.533333-2.133333 6.4 0 10.666667 2.133333 17.066667 4.266667 6.4 4.266667 12.8 10.666667 14.933333 19.2l49.066667 185.6c0 17.066667-8.533333 34.133333-25.6 38.4z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="run-up" unicode="" d="M409.6 601.338776l71.053061 71.053061v-248.685715c0-16.718367 14.628571-31.346939 31.346939-31.346938s31.346939 14.628571 31.346939 31.346938v250.775511l71.053061-71.053062c6.269388-6.269388 14.628571-8.359184 22.987755-8.359183s16.718367 2.089796 22.987755 8.359183c12.538776 12.538776 12.538776 31.346939 0 43.885715l-125.387755 125.387755c-12.538776 12.538776-31.346939 12.538776-43.885714 0l-125.387755-125.387755c-12.538776-12.538776-12.538776-31.346939 0-43.885715 10.44898-12.538776 31.346939-12.538776 43.885714-2.089795zM936.228571 444.604082l-242.416326 81.50204c-16.718367 6.269388-33.436735-4.179592-39.706123-18.808163-6.269388-16.718367 4.179592-33.436735 18.808164-39.706122l156.734694-52.244898L512 302.497959 194.35102 415.346939l156.734694 52.244898c16.718367 6.269388 25.077551 22.987755 18.808164 39.706122-6.269388 16.718367-22.987755 25.077551-39.706123 18.808163L87.771429 444.604082c-12.538776-4.179592-20.897959-16.718367-20.89796-29.257143 0-12.538776 8.359184-25.077551 20.89796-29.257143l413.779591-146.285714c4.179592-2.089796 6.269388-2.089796 10.44898-2.089796s6.269388 0 10.44898 2.089796l413.779591 146.285714c12.538776 4.179592 20.897959 16.718367 20.89796 29.257143 0 14.628571-8.359184 25.077551-20.89796 29.257143zM512 181.289796c-16.718367 0-31.346939-14.628571-31.346939-31.346939v-156.734694c0-16.718367 14.628571-31.346939 31.346939-31.346939s31.346939 14.628571 31.346939 31.346939v156.734694c0 16.718367-14.628571 31.346939-31.346939 31.346939z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="picture" unicode="" d="M819.2 800H204.8c-59.733333 0-108.8-49.066667-108.8-108.8v-616.533333c0-59.733333 49.066667-108.8 108.8-108.8h616.533333c59.733333 0 108.8 49.066667 108.8 108.8V691.2c-2.133333 59.733333-51.2 108.8-110.933333 108.8zM160 76.8V691.2c0 23.466667 19.2 44.8 44.8 44.8h616.533333c23.466667 0 44.8-19.2 44.8-44.8v-388.266667l-125.866666 125.866667c-27.733333 27.733333-76.8 27.733333-104.533334 0l-390.4-384c-4.266667-4.266667-6.4-8.533333-6.4-12.8H204.8c-25.6 0-44.8 19.2-44.8 44.8z m659.2-44.8H324.266667l354.133333 354.133333c2.133333 2.133333 6.4 2.133333 8.533333 2.133334s4.266667 0 8.533334-2.133334l160-160c4.266667-4.266667 8.533333-6.4 12.8-6.4v-142.933333c-4.266667-25.6-23.466667-44.8-49.066667-44.8zM375.466667 413.866667c59.733333 0 106.666667 46.933333 106.666666 106.666666s-46.933333 106.666667-106.666666 106.666667-106.666667-46.933333-106.666667-106.666667 49.066667-106.666667 106.666667-106.666666z m0 149.333333c23.466667 0 42.666667-19.2 42.666666-42.666667s-19.2-42.666667-42.666666-42.666666-42.666667 19.2-42.666667 42.666666 19.2 42.666667 42.666667 42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="run-in" unicode="" d="M612.352 130.048l-69.632-69.632V179.2c0 16.384-14.336 30.72-30.72 30.72s-30.72-14.336-30.72-30.72v-120.832l-69.632 69.632c-12.288 12.288-30.72 12.288-43.008 0s-12.288-30.72 0-43.008l122.88-122.88c6.144-6.144 14.336-8.192 22.528-8.192s16.384 2.048 22.528 8.192l122.88 122.88c12.288 12.288 12.288 30.72 0 43.008s-34.816 12.288-47.104 2.048zM927.744 474.112l-237.568 79.872c-16.384 6.144-32.768-4.096-38.912-18.432-6.144-16.384 4.096-32.768 18.432-38.912l153.6-51.2L512 334.848 200.704 445.44l153.6 51.2c16.384 6.144 24.576 22.528 18.432 38.912-6.144 16.384-22.528 24.576-38.912 18.432L96.256 474.112c-12.288-4.096-20.48-16.384-20.48-28.672 0-12.288 8.192-24.576 20.48-28.672l405.504-143.36c4.096-2.048 6.144-2.048 10.24-2.048s6.144 0 10.24 2.048l405.504 143.36c12.288 4.096 20.48 16.384 20.48 28.672 0 14.336-8.192 24.576-20.48 28.672zM512 394.24c16.384 0 30.72 14.336 30.72 30.72V742.4c0 16.384-14.336 30.72-30.72 30.72s-30.72-14.336-30.72-30.72V424.96c0-16.384 14.336-30.72 30.72-30.72z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="pin" unicode="" d="M911.15102 572.081633L689.632653 793.6c-18.808163 18.808163-50.155102 20.897959-71.053061 2.089796l-267.493878-229.877551-96.130612-14.628572c-6.269388 0-12.538776-4.179592-16.718367-8.359183l-58.514286-58.514286c-20.897959-20.897959-20.897959-54.334694 0-73.142857l152.555102-152.555102L125.387755 51.722449c-12.538776-12.538776-12.538776-31.346939 0-43.885714 6.269388-6.269388 14.628571-10.44898 20.897959-10.44898s16.718367 2.089796 22.987755 8.359184l204.8 204.8 152.555102-152.555102c10.44898-10.44898 22.987755-14.628571 37.616327-14.628572s27.167347 6.269388 37.616326 14.628572l58.514286 58.514285c4.179592 4.179592 8.359184 10.44898 8.359184 16.718368l14.628571 96.130612 227.787755 267.493878c18.808163 25.077551 18.808163 56.42449 0 75.232653zM631.118367 266.971429c-4.179592-4.179592-6.269388-10.44898-6.269387-14.628572l-14.628572-94.040816-45.97551-45.97551-334.367347 334.367347 43.885714 43.885714 94.040817 14.628571c6.269388 0 10.44898 4.179592 14.628571 6.269388l269.583674 229.877551 206.889795-206.889796-227.787755-267.493877z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="save" unicode="" d="M906.666667 597.333333L725.333333 778.666667c-14.933333 14.933333-32 21.333333-53.333333 21.333333H170.666667C130.133333 800 96 765.866667 96 725.333333v-682.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667V546.133333c0 19.2-8.533333 38.4-21.333333 51.2zM652.8 32H371.2V247.466667h281.6v-215.466667z m211.2 10.666667c0-6.4-4.266667-10.666667-10.666667-10.666667h-140.8V277.333333c0 17.066667-12.8 29.866667-29.866666 29.866667H341.333333c-17.066667 0-29.866667-12.8-29.866666-29.866667v-245.333333H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h140.8V576c0-17.066667 12.8-29.866667 29.866666-29.866667h277.333334c17.066667 0 29.866667 12.8 29.866666 29.866667s-12.8 29.866667-29.866666 29.866667H371.2V736h302.933333c2.133333 0 6.4-2.133333 8.533334-2.133333l179.2-179.2c2.133333-2.133333 2.133333-4.266667 2.133333-8.533334V42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="search" unicode="" d="M945.066667-2.133333l-189.866667 189.866666c55.466667 64 87.466667 149.333333 87.466667 241.066667 0 204.8-168.533333 373.333333-373.333334 373.333333S96 631.466667 96 426.666667 264.533333 53.333333 469.333333 53.333333c91.733333 0 174.933333 34.133333 241.066667 87.466667l189.866667-189.866667c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333c8.533333 12.8 8.533333 34.133333-2.133333 46.933334zM469.333333 117.333333C298.666667 117.333333 160 256 160 426.666667S298.666667 736 469.333333 736 778.666667 597.333333 778.666667 426.666667 640 117.333333 469.333333 117.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="share" unicode="" d="M874.666667 352c-17.066667 0-32-14.933333-32-32v-256c0-6.4-4.266667-10.666667-10.666667-10.666667H192c-6.4 0-10.666667 4.266667-10.666667 10.666667V704c0 6.4 4.266667 10.666667 10.666667 10.666667h256c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H192C151.466667 778.666667 117.333333 744.533333 117.333333 704v-640c0-40.533333 34.133333-74.666667 74.666667-74.666667h640c40.533333 0 74.666667 34.133333 74.666667 74.666667V320c0 17.066667-14.933333 32-32 32zM874.666667 778.666667H640c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h157.866667L509.866667 428.8c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333l285.866667 285.866667V512c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V746.666667c0 17.066667-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="scanning" unicode="" d="M341.333333 32H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667v170.666666c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-170.666666c0-40.533333 34.133333-74.666667 74.666667-74.666667h170.666666c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM896 245.333333c-17.066667 0-32-14.933333-32-32v-170.666666c0-6.4-4.266667-10.666667-10.666667-10.666667h-170.666666c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h170.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667v170.666666c0 17.066667-14.933333 32-32 32zM128 522.666667c17.066667 0 32 14.933333 32 32V725.333333c0 6.4 4.266667 10.666667 10.666667 10.666667h170.666666c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H170.666667C130.133333 800 96 765.866667 96 725.333333v-170.666666c0-17.066667 14.933333-32 32-32zM853.333333 800h-170.666666c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h170.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-170.666666c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V725.333333c0 40.533333-34.133333 74.666667-74.666667 74.666667zM896 426.666667H128c-17.066667 0-32-14.933333-32-32S110.933333 362.666667 128 362.666667h768c17.066667 0 32 14.933333 32 32S913.066667 426.666667 896 426.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="security" unicode="" d="M814.933333 716.8L529.066667 817.066667c-10.666667 4.266667-23.466667 4.266667-34.133334 0L209.066667 716.8c-29.866667-10.666667-49.066667-38.4-49.066667-70.4V298.666667c0-194.133333 157.866667-352 352-352S864 104.533333 864 298.666667V646.4c0 32-19.2 61.866667-49.066667 70.4zM800 298.666667c0-157.866667-130.133333-288-288-288S224 140.8 224 298.666667V646.4c0 4.266667 2.133333 8.533333 6.4 10.666667L512 755.2l281.6-98.133333c4.266667-2.133333 6.4-6.4 6.4-10.666667V298.666667zM659.2 492.8l-192-194.133333-85.333333 68.266666c-12.8 10.666667-34.133333 8.533333-44.8-4.266666-10.666667-12.8-8.533333-34.133333 4.266666-44.8l106.666667-85.333334c6.4-4.266667 12.8-6.4 19.2-6.4 8.533333 0 17.066667 2.133333 23.466667 8.533334l213.333333 213.333333c12.8 12.8 12.8 32 0 44.8-10.666667 10.666667-32 10.666667-44.8 0z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="select" unicode="" d="M409.6 138.666667c-8.533333 0-17.066667 2.133333-23.466667 8.533333l-238.933333 234.666667c-12.8 12.8-12.8 32 0 44.8 12.8 12.8 32 12.8 44.8 0l215.466667-213.333334 422.4 428.8c12.8 12.8 32 12.8 44.8 0 12.8-12.8 12.8-32 0-44.8L430.933333 149.333333c-4.266667-8.533333-12.8-10.666667-21.333333-10.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="stop" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333zM885.333333 384c0-85.333333-29.866667-164.266667-78.933333-228.266667l-533.333333 514.133334c64 55.466667 149.333333 87.466667 238.933333 87.466666 204.8 0 373.333333-168.533333 373.333333-373.333333z m-746.666666 0c0 91.733333 34.133333 174.933333 87.466666 241.066667l535.466667-516.266667c-66.133333-59.733333-153.6-98.133333-251.733333-98.133333-202.666667 0-371.2 168.533333-371.2 373.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="smile" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333z m0-810.666666c-204.8 0-373.333333 168.533333-373.333333 373.333333S307.2 757.333333 512 757.333333 885.333333 588.8 885.333333 384 716.8 10.666667 512 10.666667zM674.133333 288c-46.933333-57.6-100.266667-85.333333-162.133333-85.333333s-115.2 27.733333-162.133333 85.333333c-10.666667 12.8-32 14.933333-44.8 4.266667-12.8-10.666667-14.933333-32-4.266667-44.8 59.733333-70.4 130.133333-106.666667 211.2-106.666667s151.466667 36.266667 211.2 106.666667c10.666667 12.8 8.533333 34.133333-4.266667 44.8-12.8 10.666667-34.133333 8.533333-44.8-4.266667zM362.666667 384c23.466667 0 42.666667 19.2 42.666666 42.666667v64c0 23.466667-19.2 42.666667-42.666666 42.666666s-42.666667-19.2-42.666667-42.666666v-64c0-23.466667 19.2-42.666667 42.666667-42.666667zM661.333333 384c23.466667 0 42.666667 19.2 42.666667 42.666667v64c0 23.466667-19.2 42.666667-42.666667 42.666666s-42.666667-19.2-42.666666-42.666666v-64c0-23.466667 19.2-42.666667 42.666666-42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="switch" unicode="" d="M128 373.333333c17.066667 0 32 14.933333 32 32v170.666667c0 6.4 4.266667 10.666667 10.666667 10.666667h652.8l-83.2-83.2c-12.8-12.8-12.8-34.133333 0-46.933334 6.4-6.4 14.933333-10.666667 23.466666-10.666666s17.066667 4.266667 23.466667 10.666666l145.066667 145.066667c12.8 12.8 12.8 34.133333 0 46.933333l-145.066667 145.066667c-12.8 12.8-34.133333 12.8-46.933333 0-12.8-12.8-12.8-34.133333 0-46.933333l93.866666-93.866667H170.666667c-40.533333 0-74.666667-34.133333-74.666667-74.666667v-170.666666c0-19.2 14.933333-34.133333 32-34.133334zM906.666667 394.666667c-17.066667 0-32-14.933333-32-32v-170.666667c0-6.4-4.266667-10.666667-10.666667-10.666667H211.2l83.2 83.2c12.8 12.8 12.8 34.133333 0 46.933334-12.8 12.8-34.133333 12.8-46.933333 0l-145.066667-145.066667c-12.8-12.8-12.8-34.133333 0-46.933333l145.066667-145.066667c6.4-6.4 14.933333-10.666667 23.466666-10.666667s17.066667 4.266667 23.466667 10.666667c12.8 12.8 12.8 34.133333 0 46.933333l-93.866667 93.866667h663.466667c40.533333 0 74.666667 34.133333 74.666667 74.666667v170.666666c0 19.2-12.8 34.133333-32 34.133334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="setting" unicode="" d="M904.533333 473.6l-85.333333 14.933333-17.066667 38.4 49.066667 70.4c14.933333 21.333333 12.8 49.066667-6.4 68.266667l-53.333333 53.333333c-19.2 19.2-46.933333 21.333333-68.266667 6.4l-70.4-49.066666-38.4 17.066666-14.933333 85.333334c-2.133333 23.466667-23.466667 42.666667-49.066667 42.666666h-74.666667c-25.6 0-46.933333-19.2-53.333333-44.8l-14.933333-85.333333-38.4-17.066667L296.533333 725.333333c-21.333333 14.933333-49.066667 12.8-68.266666-6.4l-53.333334-53.333333c-19.2-19.2-21.333333-46.933333-6.4-68.266667l49.066667-70.4-17.066667-38.4-85.333333-14.933333c-21.333333-4.266667-40.533333-25.6-40.533333-51.2v-74.666667c0-25.6 19.2-46.933333 44.8-53.333333l85.333333-14.933333 17.066667-38.4L170.666667 168.533333c-14.933333-21.333333-12.8-49.066667 6.4-68.266666l53.333333-53.333334c19.2-19.2 46.933333-21.333333 68.266667-6.4l70.4 49.066667 38.4-17.066667 14.933333-85.333333c4.266667-25.6 25.6-44.8 53.333333-44.8h74.666667c25.6 0 46.933333 19.2 53.333333 44.8l14.933334 85.333333 38.4 17.066667 70.4-49.066667c21.333333-14.933333 49.066667-12.8 68.266666 6.4l53.333334 53.333334c19.2 19.2 21.333333 46.933333 6.4 68.266666l-49.066667 70.4 17.066667 38.4 85.333333 14.933334c25.6 4.266667 44.8 25.6 44.8 53.333333v74.666667c-4.266667 27.733333-23.466667 49.066667-49.066667 53.333333z m-19.2-117.333333l-93.866666-17.066667c-10.666667-2.133333-19.2-8.533333-23.466667-19.2l-29.866667-70.4c-4.266667-10.666667-2.133333-21.333333 4.266667-29.866667l53.333333-76.8-40.533333-40.533333-76.8 53.333333c-8.533333 6.4-21.333333 8.533333-29.866667 4.266667L576 128c-10.666667-4.266667-17.066667-12.8-19.2-23.466667l-17.066667-93.866666h-57.6l-17.066666 93.866666c-2.133333 10.666667-8.533333 19.2-19.2 23.466667l-70.4 29.866667c-10.666667 4.266667-21.333333 2.133333-29.866667-4.266667l-76.8-53.333333-40.533333 40.533333 53.333333 76.8c6.4 8.533333 8.533333 21.333333 4.266667 29.866667L256 320c-4.266667 10.666667-12.8 17.066667-23.466667 19.2l-93.866666 17.066667v57.6l93.866666 17.066666c10.666667 2.133333 19.2 8.533333 23.466667 19.2l29.866667 70.4c4.266667 10.666667 2.133333 21.333333-4.266667 29.866667l-53.333333 76.8 40.533333 40.533333 76.8-53.333333c8.533333-6.4 21.333333-8.533333 29.866667-4.266667L448 640c10.666667 4.266667 17.066667 12.8 19.2 23.466667l17.066667 93.866666h57.6l17.066666-93.866666c2.133333-10.666667 8.533333-19.2 19.2-23.466667l70.4-29.866667c10.666667-4.266667 21.333333-2.133333 29.866667 4.266667l76.8 53.333333 40.533333-40.533333-53.333333-76.8c-6.4-8.533333-8.533333-21.333333-4.266667-29.866667L768 448c4.266667-10.666667 12.8-17.066667 23.466667-19.2l93.866666-17.066667v-55.466666zM512 501.333333c-64 0-117.333333-53.333333-117.333333-117.333333s53.333333-117.333333 117.333333-117.333333 117.333333 53.333333 117.333333 117.333333-53.333333 117.333333-117.333333 117.333333z m0-170.666666c-29.866667 0-53.333333 23.466667-53.333333 53.333333s23.466667 53.333333 53.333333 53.333333 53.333333-23.466667 53.333333-53.333333-23.466667-53.333333-53.333333-53.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="survey" unicode="" d="M810.666667 757.333333h-85.333334V768c0 29.866667-23.466667 53.333333-53.333333 53.333333h-320C322.133333 821.333333 298.666667 797.866667 298.666667 768v-10.666667h-85.333334c-40.533333 0-74.666667-34.133333-74.666666-74.666666v-661.333334c0-40.533333 34.133333-74.666667 74.666666-74.666666h597.333334c40.533333 0 74.666667 34.133333 74.666666 74.666666V682.666667c0 40.533333-34.133333 74.666667-74.666666 74.666666z m-149.333334 0v-64H362.666667v64h298.666666zM821.333333 21.333333c0-6.4-4.266667-10.666667-10.666666-10.666666H213.333333c-6.4 0-10.666667 4.266667-10.666666 10.666666V682.666667c0 6.4 4.266667 10.666667 10.666666 10.666666h85.333334v-10.666666c0-29.866667 23.466667-53.333333 53.333333-53.333334h320c29.866667 0 53.333333 23.466667 53.333333 53.333334v10.666666h85.333334c6.4 0 10.666667-4.266667 10.666666-10.666666v-661.333334zM659.2 450.133333l-211.2-213.333333-83.2 83.2c-12.8 12.8-32 12.8-44.8 0s-12.8-32 0-44.8l106.666667-106.666667c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333l234.666667 234.666667c12.8 12.8 12.8 32 0 44.8-14.933333 12.8-36.266667 12.8-49.066667 2.133333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="task" unicode="" d="M846.933333 780.8c-8.533333 6.4-21.333333 6.4-29.866666 2.133333 0 0-74.666667-34.133333-174.933334-34.133333-49.066667 0-96 17.066667-145.066666 34.133333-53.333333 19.2-106.666667 38.4-166.4 38.4-119.466667 0-162.133333-40.533333-168.533334-44.8-4.266667-6.4-8.533333-14.933333-8.533333-23.466666V-21.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V300.8c14.933333 8.533333 51.2 21.333333 113.066667 21.333333 49.066667 0 96-17.066667 145.066666-34.133333 53.333333-19.2 106.666667-38.4 166.4-38.4 115.2 0 198.4 38.4 200.533334 38.4 10.666667 4.266667 19.2 17.066667 19.2 29.866667V753.066667c0 10.666667-6.4 21.333333-14.933334 27.733333z m-49.066666-441.6c-27.733333-10.666667-85.333333-25.6-155.733334-25.6-49.066667 0-96 17.066667-145.066666 34.133333-53.333333 19.2-106.666667 38.4-166.4 38.4-49.066667 0-87.466667-6.4-113.066667-17.066666V736c14.933333 8.533333 51.2 21.333333 113.066667 21.333333 49.066667 0 96-17.066667 145.066666-34.133333 53.333333-19.2 106.666667-38.4 166.4-38.4 64 0 119.466667 12.8 155.733334 23.466667v-369.066667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="skip" unicode="" d="M921.6 539.733333c-14.933333 8.533333-34.133333 4.266667-42.666667-12.8L829.866667 448c-51.2 157.866667-200.533333 266.666667-369.066667 266.666667-172.8 0-324.266667-115.2-373.333333-277.333334-4.266667-17.066667 4.266667-34.133333 21.333333-40.533333 17.066667-4.266667 34.133333 4.266667 40.533333 21.333333 40.533333 136.533333 166.4 232.533333 311.466667 232.533334 140.8 0 264.533333-89.6 307.2-219.733334l-81.066667 46.933334c-14.933333 8.533333-34.133333 4.266667-42.666666-10.666667-8.533333-14.933333-4.266667-34.133333 10.666666-42.666667l147.2-85.333333c4.266667-2.133333 10.666667-4.266667 17.066667-4.266667 2.133333 0 6.4 0 8.533333 2.133334 8.533333 2.133333 14.933333 8.533333 19.2 14.933333l85.333334 147.2c8.533333 12.8 4.266667 32-10.666667 40.533333zM896 138.666667H128c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h768c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="text" unicode="" d="M853.333333 757.333333H170.666667c-17.066667 0-32-14.933333-32-32v-128c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V693.333333h277.333333v-618.666666H384c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h256c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32h-96v618.666666h277.333333V597.333333c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V725.333333c0 17.066667-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="time" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333z m0-810.666666c-204.8 0-373.333333 168.533333-373.333333 373.333333S307.2 757.333333 512 757.333333 885.333333 588.8 885.333333 384 716.8 10.666667 512 10.666667zM695.466667 328.533333l-151.466667 70.4V618.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-238.933334c0-12.8 6.4-23.466667 19.2-29.866666l170.666667-81.066667c4.266667-2.133333 8.533333-2.133333 12.8-2.133333 12.8 0 23.466667 6.4 29.866666 19.2 6.4 14.933333 0 34.133333-17.066666 42.666666z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="toggle-left" unicode="" d="M874.666667 96H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h725.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM149.333333 672h725.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32zM341.333333 416c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h512c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H341.333333zM275.2 211.2c6.4-6.4 14.933333-8.533333 23.466667-8.533333s17.066667 2.133333 23.466666 8.533333c12.8 12.8 12.8 32 0 44.8l-128 128 125.866667 125.866667c12.8 12.8 12.8 32 0 44.8-12.8 12.8-32 12.8-44.8 0l-149.333333-149.333334c-12.8-12.8-12.8-32 0-44.8l149.333333-149.333333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="toggle-right" unicode="" d="M874.666667 96H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h725.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM149.333333 672h725.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32zM149.333333 352h512c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32H149.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32zM748.8 556.8c-12.8 12.8-32 12.8-44.8 0-12.8-12.8-12.8-32 0-44.8l125.866667-125.866667-125.866667-125.866666c-12.8-12.8-12.8-32 0-44.8 6.4-6.4 14.933333-8.533333 23.466667-8.533334s17.066667 2.133333 23.466666 8.533334l149.333334 149.333333c12.8 12.8 12.8 32 0 44.8l-151.466667 147.2z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="top" unicode="" d="M896 800H128c-17.066667 0-32-14.933333-32-32S110.933333 736 128 736h768c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32zM535.466667 599.466667c-12.8 12.8-32 12.8-44.8 0l-213.333334-213.333334c-12.8-12.8-12.8-32 0-44.8s32-12.8 44.8 0l157.866667 157.866667V42.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V499.2l157.866667-157.866667c6.4-6.4 14.933333-8.533333 23.466666-8.533333s17.066667 2.133333 23.466667 8.533333c12.8 12.8 12.8 32 0 44.8l-213.333333 213.333334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="unlock" unicode="" d="M785.066667 480H381.866667v121.6c0 74.666667 61.866667 134.4 138.666666 134.4 59.733333 0 113.066667-36.266667 132.266667-91.733333 6.4-17.066667 23.466667-25.6 40.533333-19.2 17.066667 6.4 25.6 23.466667 19.2 40.533333-27.733333 81.066667-104.533333 134.4-192 134.4-110.933333 0-202.666667-89.6-202.666666-198.4v-121.6h-78.933334c-55.466667 0-100.266667-44.8-100.266666-100.266667v-311.466666c0-55.466667 44.8-100.266667 100.266666-100.266667h546.133334c55.466667 0 100.266667 44.8 100.266666 100.266667V379.733333c0 55.466667-44.8 100.266667-100.266666 100.266667z m36.266666-411.733333c0-19.2-17.066667-36.266667-36.266666-36.266667H238.933333c-19.2 0-36.266667 17.066667-36.266666 36.266667V379.733333c0 19.2 17.066667 36.266667 36.266666 36.266667h546.133334c19.2 0 36.266667-17.066667 36.266666-36.266667v-311.466666zM512 352c-17.066667 0-32-14.933333-32-32v-106.666667c0-17.066667 14.933333-32 32-32s32 14.933333 32 32v106.666667c0 17.066667-14.933333 32-32 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="user" unicode="" d="M512 821.333333C270.933333 821.333333 74.666667 625.066667 74.666667 384S270.933333-53.333333 512-53.333333 949.333333 142.933333 949.333333 384 753.066667 821.333333 512 821.333333zM288 85.333333c0 123.733333 100.266667 224 224 224S736 209.066667 736 85.333333c-61.866667-46.933333-140.8-74.666667-224-74.666666s-162.133333 27.733333-224 74.666666z m128 384c0 53.333333 42.666667 96 96 96s96-42.666667 96-96-42.666667-96-96-96-96 42.666667-96 96z m377.6-328.533333c-19.2 96-85.333333 174.933333-174.933333 211.2 32 29.866667 51.2 70.4 51.2 117.333333 0 87.466667-72.533333 160-160 160s-160-72.533333-160-160c0-46.933333 19.2-87.466667 51.2-117.333333-89.6-36.266667-155.733333-115.2-174.933334-211.2-55.466667 66.133333-91.733333 149.333333-91.733333 243.2 0 204.8 168.533333 373.333333 373.333333 373.333333S885.333333 588.8 885.333333 384c0-93.866667-34.133333-177.066667-91.733333-243.2z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="upload" unicode="" d="M896 266.666667c-17.066667 0-32-14.933333-32-32v-170.666667c0-6.4-4.266667-10.666667-10.666667-10.666667H170.666667c-6.4 0-10.666667 4.266667-10.666667 10.666667v170.666667c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-170.666667c0-40.533333 34.133333-74.666667 74.666667-74.666667h682.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667v170.666667c0 17.066667-14.933333 32-32 32zM322.133333 488.533333l157.866667 157.866667V192c0-17.066667 14.933333-32 32-32s32 14.933333 32 32V648.533333l157.866667-157.866666c6.4-6.4 14.933333-8.533333 23.466666-8.533334s17.066667 2.133333 23.466667 8.533334c12.8 12.8 12.8 32 0 44.8l-213.333333 213.333333c-12.8 12.8-32 12.8-44.8 0l-213.333334-213.333333c-12.8-12.8-12.8-32 0-44.8 10.666667-12.8 32-12.8 44.8-2.133334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="work" unicode="" d="M885.333333 640H725.333333V697.6C723.2 738.133333 689.066667 768 648.533333 768h-298.666666c-40.533333-2.133333-72.533333-34.133333-72.533334-74.666667V640H138.666667C98.133333 640 64 605.866667 64 565.333333v-490.666666C64 34.133333 98.133333 0 138.666667 0h746.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667v490.666666c0 40.533333-34.133333 74.666667-74.666667 74.666667zM341.333333 693.333333c2.133333 6.4 6.4 10.666667 12.8 10.666667h296.533334c6.4 0 10.666667-6.4 10.666666-10.666667V640H341.333333V693.333333zM138.666667 576h746.666666c6.4 0 10.666667-4.266667 10.666667-10.666667v-128H128v128c0 6.4 4.266667 10.666667 10.666667 10.666667z m277.333333-202.666667h192V320c0-6.4-4.266667-10.666667-10.666667-10.666667h-170.666666c-6.4 0-10.666667 4.266667-10.666667 10.666667v53.333333z m469.333333-309.333333h-746.666666c-6.4 0-10.666667 4.266667-10.666667 10.666667v298.666666h224V320c0-40.533333 34.133333-74.666667 74.666667-74.666667h170.666666c40.533333 0 74.666667 34.133333 74.666667 74.666667v53.333333H896v-298.666666c0-6.4-4.266667-10.666667-10.666667-10.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="warning" unicode="" d="M934.4 125.866667L605.866667 714.666667C586.666667 748.8 550.4 768 512 768c-38.4 0-74.666667-21.333333-93.866667-53.333333L89.6 125.866667c-19.2-34.133333-19.2-76.8 0-110.933334S145.066667-42.666667 183.466667-42.666667h657.066666c38.4 0 74.666667 21.333333 93.866667 57.6 19.2 34.133333 19.2 76.8 0 110.933334z m-55.466667-81.066667c-8.533333-14.933333-23.466667-23.466667-38.4-23.466667H183.466667c-14.933333 0-29.866667 8.533333-38.4 23.466667-8.533333 14.933333-8.533333 34.133333 0 49.066667L473.6 682.666667c8.533333 12.8 23.466667 21.333333 38.4 21.333333s29.866667-8.533333 38.4-21.333333l328.533333-588.8c8.533333-14.933333 8.533333-32 0-49.066667zM512 149.333333m-42.666667 0a42.666667 42.666667 0 1 1 85.333334 0 42.666667 42.666667 0 1 1-85.333334 0ZM512 266.666667c17.066667 0 32 14.933333 32 32v192c0 17.066667-14.933333 32-32 32s-32-14.933333-32-32v-192c0-17.066667 14.933333-32 32-32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="add-bold" unicode="" d="M874.666667 426.666667H554.666667V746.666667c0 23.466667-19.2 42.666667-42.666667 42.666666s-42.666667-19.2-42.666667-42.666666v-320H149.333333c-23.466667 0-42.666667-19.2-42.666666-42.666667s19.2-42.666667 42.666666-42.666667h320v-320c0-23.466667 19.2-42.666667 42.666667-42.666666s42.666667 19.2 42.666667 42.666666V341.333333h320c23.466667 0 42.666667 19.2 42.666666 42.666667s-19.2 42.666667-42.666666 42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-left-bold" unicode="" d="M384 384L731.733333 693.333333c17.066667 14.933333 19.2 42.666667 4.266667 59.733334-14.933333 17.066667-42.666667 19.2-59.733333 4.266666l-384-341.333333c-10.666667-8.533333-14.933333-19.2-14.933334-32s4.266667-23.466667 14.933334-32l384-341.333333c8.533333-6.4 19.2-10.666667 27.733333-10.666667 12.8 0 23.466667 4.266667 32 14.933333 14.933333 17.066667 14.933333 44.8-4.266667 59.733334L384 384z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-up-bold" unicode="" d="M904.533333 221.866667l-362.666666 362.666666c-17.066667 17.066667-42.666667 17.066667-59.733334 0l-362.666666-362.666666c-17.066667-17.066667-17.066667-42.666667 0-59.733334 17.066667-17.066667 42.666667-17.066667 59.733333 0L512 494.933333l332.8-332.8c8.533333-8.533333 19.2-12.8 29.866667-12.8s21.333333 4.266667 29.866666 12.8c17.066667 17.066667 17.066667 42.666667 0 59.733334z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="close-bold" unicode="" d="M571.733333 384l268.8 268.8c17.066667 17.066667 17.066667 42.666667 0 59.733333-17.066667 17.066667-42.666667 17.066667-59.733333 0L512 443.733333 243.2 712.533333c-17.066667 17.066667-42.666667 17.066667-59.733333 0-17.066667-17.066667-17.066667-42.666667 0-59.733333L452.266667 384 183.466667 115.2c-17.066667-17.066667-17.066667-42.666667 0-59.733333 8.533333-8.533333 19.2-12.8 29.866666-12.8s21.333333 4.266667 29.866667 12.8L512 324.266667l268.8-268.8c8.533333-8.533333 19.2-12.8 29.866667-12.8s21.333333 4.266667 29.866666 12.8c17.066667 17.066667 17.066667 42.666667 0 59.733333L571.733333 384z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-down-bold" unicode="" d="M904.533333 584.5333330000001c-17.066667 17.066667-42.666667 17.066667-59.733333 0L512 251.73333300000002 179.2 584.5333330000001c-17.066667 17.066667-42.666667 17.066667-59.733333 0-17.066667-17.066667-17.066667-42.666667 0-59.733333l362.666666-362.666667c8.533333-8.533333 19.2-12.8 29.866667-12.8s21.333333 4.266667 29.866667 12.8l362.666666 362.666667c17.066667 17.066667 17.066667 42.666667 0 59.733333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="minus-bold" unicode="" d="M853.333333 341.333333H170.666667c-23.466667 0-42.666667 19.2-42.666667 42.666667s19.2 42.666667 42.666667 42.666667h682.666666c23.466667 0 42.666667-19.2 42.666667-42.666667s-19.2-42.666667-42.666667-42.666667z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="arrow-right-bold" unicode="" d="M731.733333 416l-384 341.333333c-17.066667 14.933333-44.8 14.933333-59.733333-4.266666-14.933333-17.066667-14.933333-44.8 4.266667-59.733334L640 384 292.266667 74.666667c-17.066667-14.933333-19.2-42.666667-4.266667-59.733334 8.533333-8.533333 19.2-14.933333 32-14.933333 10.666667 0 19.2 4.266667 27.733333 10.666667l384 341.333333c8.533333 8.533333 14.933333 19.2 14.933334 32s-4.266667 23.466667-14.933334 32z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="select-bold" unicode="" d="M883.2 648.533333c-17.066667 17.066667-44.8 17.066667-59.733333 0L409.6 230.4l-209.066667 204.8c-17.066667 17.066667-44.8 17.066667-59.733333 0-17.066667-17.066667-17.066667-44.8 0-59.733333l238.933333-234.666667c8.533333-8.533333 19.2-12.8 29.866667-12.8 10.666667 0 21.333333 4.266667 29.866667 12.8l443.733333 448c17.066667 17.066667 17.066667 42.666667 0 59.733333z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</font>
|
|
||||||
</defs></svg>
|
|
||||||
|
Before Width: | Height: | Size: 106 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
-9
File diff suppressed because one or more lines are too long
-9
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
from common import register_api
|
||||||
|
from .file import FilePhotoAPI
|
||||||
|
from .passport import LoginAPI
|
||||||
|
|
||||||
|
|
||||||
|
def register_sys_api(api_bp):
|
||||||
|
register_api(LoginAPI, 'login_api', '/passport/login', pk='_id', app=api_bp)
|
||||||
|
register_api(FilePhotoAPI, 'photo_api', '/file/photo/', pk='photo_id', app=api_bp)
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
from flask import request, jsonify
|
||||||
|
from flask.views import MethodView
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
from common.utils.http import fail_api, success_api, table_api
|
||||||
|
from common.utils.upload import upload_one, delete_photo_by_id
|
||||||
|
from models import PhotoModel
|
||||||
|
|
||||||
|
|
||||||
|
class FilePhotoAPI(MethodView):
|
||||||
|
|
||||||
|
def get(self, photo_id):
|
||||||
|
if photo_id is None:
|
||||||
|
page = request.args.get('page', type=int, default=1)
|
||||||
|
limit = request.args.get('limit', type=int, default=10)
|
||||||
|
photo_paginate = PhotoModel.query.order_by(
|
||||||
|
desc(PhotoModel.create_at)).paginate(
|
||||||
|
page=page, per_page=limit, error_out=False)
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
'id': item.id,
|
||||||
|
'name': item.name,
|
||||||
|
'href': item.href,
|
||||||
|
'mime': item.mime,
|
||||||
|
'size': item.size,
|
||||||
|
'ext': item.ext if hasattr(item, 'ext') else "",
|
||||||
|
'create_at': str(item.create_at),
|
||||||
|
} for item in photo_paginate.items
|
||||||
|
]
|
||||||
|
return table_api(
|
||||||
|
result={
|
||||||
|
'items': data,
|
||||||
|
'total': photo_paginate.total,
|
||||||
|
},
|
||||||
|
code=0)
|
||||||
|
else:
|
||||||
|
# 显示一张图片
|
||||||
|
item = PhotoModel.query.get(photo_id)
|
||||||
|
return table_api(
|
||||||
|
result={
|
||||||
|
'items': {
|
||||||
|
'id': item.id,
|
||||||
|
'name': item.name,
|
||||||
|
'href': item.href,
|
||||||
|
'mime': item.mime,
|
||||||
|
'size': item.size,
|
||||||
|
'ext': item.ext if hasattr(item, 'ext') else "",
|
||||||
|
'create_at': str(item.create_at),
|
||||||
|
},
|
||||||
|
'total': 1,
|
||||||
|
},
|
||||||
|
code=0
|
||||||
|
)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
if 'file' in request.files:
|
||||||
|
photo = request.files['file']
|
||||||
|
mime = request.files['file'].content_type
|
||||||
|
file_url = upload_one(photo=photo, mime=mime)
|
||||||
|
|
||||||
|
res = {
|
||||||
|
"message": "上传成功",
|
||||||
|
"code": 0,
|
||||||
|
"success": True,
|
||||||
|
"data": {"src": file_url},
|
||||||
|
}
|
||||||
|
return jsonify(res)
|
||||||
|
return fail_api()
|
||||||
|
|
||||||
|
def delete(self, photo_id):
|
||||||
|
res = delete_photo_by_id(photo_id)
|
||||||
|
if res:
|
||||||
|
return success_api(message="删除成功")
|
||||||
|
else:
|
||||||
|
return fail_api(message="删除失败")
|
||||||
|
|
||||||
|
def put(self, photo_id):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
from flask import render_template, make_response
|
||||||
|
from flask import session, redirect, url_for
|
||||||
|
from flask.views import MethodView
|
||||||
|
from flask_login import current_user, login_user
|
||||||
|
from flask_pydantic import validate
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from common.gen_captcha import add_auth_session
|
||||||
|
from common.utils.http import fail_api, success_api
|
||||||
|
from common.utils.rights import record_logging
|
||||||
|
from models import UserModel
|
||||||
|
|
||||||
|
|
||||||
|
class LoginModel(BaseModel):
|
||||||
|
username: str
|
||||||
|
password: str
|
||||||
|
captcha: str
|
||||||
|
|
||||||
|
|
||||||
|
class LoginAPI(MethodView):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('admin.index'))
|
||||||
|
return make_response(render_template('index/login.html'))
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def post(self, body: LoginModel):
|
||||||
|
s_code = session.get("code", None)
|
||||||
|
session["code"] = None
|
||||||
|
|
||||||
|
if body.captcha != s_code:
|
||||||
|
return fail_api(message="验证码错误")
|
||||||
|
user = UserModel.query.filter_by(username=body.username).first()
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
return fail_api(message="不存在的用户")
|
||||||
|
|
||||||
|
if user.enable == 0:
|
||||||
|
return fail_api(message="用户被暂停使用")
|
||||||
|
|
||||||
|
if user.validate_password(body.password):
|
||||||
|
# 登录
|
||||||
|
login_user(user)
|
||||||
|
# 记录登录日志
|
||||||
|
record_logging()
|
||||||
|
|
||||||
|
# 存入权限
|
||||||
|
add_auth_session()
|
||||||
|
return success_api(message="登录成功")
|
||||||
|
record_logging()
|
||||||
|
return fail_api(message="用户名或密码错误")
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>日志</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='/admin/admin/css/other/console2.css') }}"/>
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<div class="layui-tab layui-tab-card">
|
|
||||||
<ul class="layui-tab-title">
|
|
||||||
<li class="layui-this">登录日志</li>
|
|
||||||
<li>操作日志</li>
|
|
||||||
</ul>
|
|
||||||
<div class="layui-tab-content">
|
|
||||||
<div class="layui-tab-item layui-show">
|
|
||||||
<table style="margin-top: 10px;" id="log-login-table" lay-filter="log-login-table"></table>
|
|
||||||
</div>
|
|
||||||
<div class="layui-tab-item">
|
|
||||||
<table style="margin-top: 10px;" id="log-operate-table" lay-filter="log-operate-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/html" id="log-createTime">
|
|
||||||
{{ ' {{layui.util.toDateString(d.create_time, "yyyy-MM-dd HH:mm:ss")}' |safe }}}
|
|
||||||
</script>
|
|
||||||
<script type="text/html" id="log-status">
|
|
||||||
{{ '{{#if (d.success == true) { }}
|
|
||||||
<span style="color: green">成功</span>
|
|
||||||
{{# }else if(d.success == false){ }}
|
|
||||||
<span style="color: red">失败</span>
|
|
||||||
{{# } }}'|safe }}
|
|
||||||
</script>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery', 'element', 'util'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
|
|
||||||
let MODULE_PATH = '/admin/log/'
|
|
||||||
|
|
||||||
let cols = [
|
|
||||||
[
|
|
||||||
{ title: 'ID', field: 'id', align: 'center' },
|
|
||||||
{ title: '请求方式', field: 'method', align: 'center' },
|
|
||||||
{ title: '接口', field: 'url', align: 'center' },
|
|
||||||
{ title: '浏览器', field: 'user_agent', align: 'center' },
|
|
||||||
{ title: '操作地址', field: 'ip', align: 'center' },
|
|
||||||
{ title: '访问时间', field: 'create_time', templet: '#log-createTime', align: 'center' },
|
|
||||||
{ title: '操作人ID', field: 'uid', align: 'center' },
|
|
||||||
{ title: '描述', field: 'desc', align: 'center' },
|
|
||||||
{ title: '访问状态', templet: '#log-status', align: 'center' }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
table.render({
|
|
||||||
elem: '#log-operate-table',
|
|
||||||
url: MODULE_PATH + 'operateLog',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
toolbar: false
|
|
||||||
})
|
|
||||||
|
|
||||||
table.render({
|
|
||||||
elem: '#log-login-table',
|
|
||||||
url: MODULE_PATH + 'loginLog',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
toolbar: false
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(dict-type-query)', function (data) {
|
|
||||||
table.reload('dict-type-table', { where: data.field })
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(log-operate-table)', function (obj) {
|
|
||||||
if (obj.event === 'details') {
|
|
||||||
window.info(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(log-login-table)', function (obj) {
|
|
||||||
if (obj.event === 'details') {
|
|
||||||
window.info(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
window.info = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '详细信息',
|
|
||||||
shade: 0,
|
|
||||||
area: ['400px', '400px'],
|
|
||||||
content: MODULE_PATH + 'info',
|
|
||||||
success: function (layero) {
|
|
||||||
let iframeWin = window[layero.find('iframe')[0]['name']]
|
|
||||||
iframeWin.show(obj.data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<script src="{{ url_for('static', filename='/admin/component/layui/layui.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='/admin/component/pear/pear.js') }}"></script>
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>部门管理</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">上级部门</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<ul id="selectParent" name="parentId" class="dtree" data-id="0"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="deptName" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">负责人</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="leader" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">邮箱</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="email" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">联系方式</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="phone" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" name="status" value="1" title="开启">
|
|
||||||
<input type="radio" name="status" value="0" title="关闭" checked>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">排序</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="sort" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">详细地址</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="address" class="layui-textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="dept-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery', 'dtree'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let dtree = layui.dtree
|
|
||||||
|
|
||||||
dtree.renderSelect({
|
|
||||||
elem: '#selectParent',
|
|
||||||
url: '/dept/tree',
|
|
||||||
method: 'get',
|
|
||||||
selectInputName: { nodeId: 'parentId', context: 'parentName' },
|
|
||||||
skin: 'layui',
|
|
||||||
dataFormat: 'list',
|
|
||||||
response: { treeId: 'deptId', parentId: 'parentId', title: 'deptName' },
|
|
||||||
selectInitVal: '1'
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(dept-save)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/dept/save',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'post',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))
|
|
||||||
parent.render()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>部门修改</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item layui-hide">
|
|
||||||
<label class="layui-form-label">编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dept.id }}" name="deptId" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dept.dept_name }}" name="deptName" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">负责人</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dept.leader }}" name="leader" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">邮箱</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dept.email }}" name="email" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">联系方式</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dept.phone }}" name="phone" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
|
|
||||||
<input type="radio" name="status" {% if dept.status == 1 %}checked{% endif %} value="1"
|
|
||||||
title="开启">
|
|
||||||
|
|
||||||
<input type="radio" name="status" {% if dept.status == 0 %}checked{% endif %} value="0"
|
|
||||||
title="关闭"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">排序</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="sort" value="{{ dept.sort }}" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入详细地址" name="address"
|
|
||||||
class="layui-textarea">{{ dept.address }}</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="dept-update">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(dept-update)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/dept/update',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.render()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>部门新增</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">部门名称</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="deptName" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="dept-query">
|
|
||||||
<i class="layui-icon layui-icon-search"></i>
|
|
||||||
查询
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-md">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="dept-table" lay-filter="dept-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/html" id="dept-toolbar">
|
|
||||||
{% if authorize("admin:dept:edit") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:dept:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dept-bar">
|
|
||||||
{% if authorize("admin:dept:edit") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i
|
|
||||||
class="layui-icon layui-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:dept:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i
|
|
||||||
class="layui-icon layui-icon-delete"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dept-status">
|
|
||||||
<input type="checkbox" name="status" value="{{ "{{ d.deptId }}" }}" lay-skin="switch" lay-text="启用|禁用"
|
|
||||||
lay-filter="dept-enable"
|
|
||||||
{{ "{{# if(d.status==1){ }} checked {{# } }}" }}>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery', 'treetable', 'popup'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let treetable = layui.treetable
|
|
||||||
let popup = layui.popup
|
|
||||||
|
|
||||||
let MODULE_PATH = '/dept/'
|
|
||||||
|
|
||||||
window.render = function () {
|
|
||||||
treetable.render({
|
|
||||||
treeColIndex: 1,
|
|
||||||
treeSpid: 0,
|
|
||||||
treeIdName: 'deptId',
|
|
||||||
treePidName: 'parentId',
|
|
||||||
skin: 'line',
|
|
||||||
method: 'post',
|
|
||||||
treeDefaultClose: false,
|
|
||||||
toolbar: '#dept-toolbar',
|
|
||||||
elem: '#dept-table',
|
|
||||||
url: '/dept/data',
|
|
||||||
page: false,
|
|
||||||
cols: [
|
|
||||||
[
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{ field: 'deptName', minWidth: 200, title: '部门名称' },
|
|
||||||
{ field: 'leader', title: '负责人' },
|
|
||||||
{ field: 'phone', title: '联系方式' },
|
|
||||||
{ field: 'email', title: '邮箱' },
|
|
||||||
{ field: 'address', title: '详细地址' },
|
|
||||||
{ field: 'status', title: '状态', templet: '#dept-status' },
|
|
||||||
{ field: 'sort', title: '排序', width: 100 },
|
|
||||||
{ title: '操作', templet: '#dept-bar', width: 120, align: 'center' }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
form.on('submit(dept-query)', function (data) {
|
|
||||||
var keyword = data.field.deptName
|
|
||||||
var $tds = $('#dept-table').next('.treeTable').find('.layui-table-body tbody tr td')
|
|
||||||
if (!keyword) {
|
|
||||||
$tds.css('background-color', 'transparent')
|
|
||||||
layer.msg('请输入关键字', { icon: 5 })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var searchCount = 0
|
|
||||||
$tds.each(function () {
|
|
||||||
$(this).css('background-color', 'transparent')
|
|
||||||
if ($(this).text().indexOf(keyword) >= 0) {
|
|
||||||
$(this).css('background-color', 'rgba(250,230,160,0.5)')
|
|
||||||
if (searchCount === 0) {
|
|
||||||
$('body,html').stop(true)
|
|
||||||
$('body,html').animate({ scrollTop: $(this).offset().top - 150 }, 500)
|
|
||||||
}
|
|
||||||
searchCount++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (searchCount === 0) {
|
|
||||||
layer.msg('没有匹配结果', { icon: 5 })
|
|
||||||
} else {
|
|
||||||
treetable.expandAll('#dept-table')
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
render()
|
|
||||||
|
|
||||||
table.on('tool(dept-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.remove(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.edit(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(dept-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.add()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refresh()
|
|
||||||
} else if (obj.event === 'batchRemove') {
|
|
||||||
{#window.batchRemove(obj)#}
|
|
||||||
console.log(table.checkStatus(obj.config.id).data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(dept-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/dept/' + operate,
|
|
||||||
data: JSON.stringify({ deptId: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg)
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.add = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['450px', '500px'],
|
|
||||||
content: MODULE_PATH + 'add'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.edit = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['450px', '500px'],
|
|
||||||
content: MODULE_PATH + 'edit?deptId=' + obj.data['deptId']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.remove = function (obj) {
|
|
||||||
layer.confirm('确定要删除该部门', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: MODULE_PATH + 'remove/' + obj.data['deptId'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>字典增加</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="typeName" lay-verify="title" autocomplete="off" placeholder="请输入名称"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="typeCode" lay-verify="title" autocomplete="off" placeholder="请输入标识"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" name="enable" value="1" title="开启">
|
|
||||||
<input type="radio" name="enable" value="0" title="关闭" checked>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="description" class="layui-textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="dict-type-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(dict-type-save)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictType/save',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'post',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.layui.table.reload('dict-type-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>字典增加</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标签</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="dataLabel" lay-verify="title" autocomplete="off" placeholder="请输入标签"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">值</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="dataValue" lay-verify="title" autocomplete="off" placeholder="请输入值"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ type_code }}" readonly="readonly" name="typeCode"
|
|
||||||
lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" name="enable" value="1" title="开启">
|
|
||||||
<input type="radio" name="enable" value="0" title="关闭" checked>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="remark" class="layui-textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="dict-data-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(dict-data-save)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictData/save',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'post',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.layui.table.reload('dict-data-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>字典增加</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item layui-hide">
|
|
||||||
<label class="layui-form-label">编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_data.id }}" name="dataId" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标签</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_data.data_label }}" name="dataLabel" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">值</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_data.data_value }}" name="dataValue" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_data.type_code }}" readonly="readonly" name="typeCode"
|
|
||||||
lay-verify="title" autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" {% if dict_data.enable == 1 %} } checked{% endif %} name="enable" value="1"
|
|
||||||
title="开启">
|
|
||||||
<input type="radio" {% if dict_data.enable == 0 %} } checked{% endif %} name="enable" value="0"
|
|
||||||
title="关闭">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="remark"
|
|
||||||
class="layui-textarea">{{ dict_data.remark }}</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="dict-data-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(dict-data-save)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictData/update',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.layui.table.reload('dict-data-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>字典增加</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item layui-hide">
|
|
||||||
<label class="layui-form-label">编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_type.id }}" name="id" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_type.type_name }}" name="typeName" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ dict_type.type_code }}" readonly name="typeCode"
|
|
||||||
lay-verify="title" autocomplete="off" placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" {% if dict_type.enable == 1 %} } checked{% endif %} name="enable" value="1"
|
|
||||||
title="开启">
|
|
||||||
<input type="radio" {% if dict_type.enable == 0 %} } checked{% endif %} name="enable" value="0"
|
|
||||||
title="关闭">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="description"
|
|
||||||
class="layui-textarea">{{ dict_type.description }}</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="dict-type-update">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(dict-type-update)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictType/update',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.layui.table.reload('dict-type-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,374 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>字典管理</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-row layui-col-space10">
|
|
||||||
<div class="layui-col-md12">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">字典名称</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="typeName" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="dict-type-query">
|
|
||||||
<i class="layui-icon layui-icon-search"></i>
|
|
||||||
查询
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-md">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="dict-type-table" lay-filter="dict-type-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<svg class="empty" style="margin-top: 50px;margin-left: 220px;margin-bottom: 80px;" width="184"
|
|
||||||
height="152" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g fill="none" fillRule="evenodd">
|
|
||||||
<g transform="translate(24 31.67)">
|
|
||||||
<ellipse fillOpacity=".8" fill="#F5F5F7" cx="67.797" cy="106.89" rx="67.797"
|
|
||||||
ry="12.668"></ellipse>
|
|
||||||
<path d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
|
|
||||||
fill="#AEB8C2"></path>
|
|
||||||
<path d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
|
|
||||||
fill="url(#linearGradient-1)" transform="translate(13.56)"></path>
|
|
||||||
<path d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
|
|
||||||
fill="#F5F5F7"></path>
|
|
||||||
<path d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
|
|
||||||
fill="#DCE0E6"></path>
|
|
||||||
</g>
|
|
||||||
<path d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
|
|
||||||
fill="#DCE0E6"></path>
|
|
||||||
<g transform="translate(149.65 15.383)" fill="#FFF">
|
|
||||||
<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
|
|
||||||
<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
<table id="dict-data-table" lay-filter="dict-data-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
<script type="text/html" id="dict-type-toolbar">
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dict-type-bar">
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit">
|
|
||||||
<i class="layui-icon layui-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="pear-btn pear-btn-warming pear-btn-sm" lay-event="details">
|
|
||||||
<i class="layui-icon layui-icon-transfer"></i>
|
|
||||||
</button>
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
</button>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dict-type-enable">
|
|
||||||
<input type="checkbox" value="{{ "{{ d.id }}" }}" lay-skin="switch" lay-text="启用|禁用" lay-filter="dict-type-enable"
|
|
||||||
{{ "{{# if(d.enable==1){ }} checked {{# } }}" }}>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dict-data-toolbar">
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dict-data-bar">
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i>
|
|
||||||
</button>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="dict-data-enable">
|
|
||||||
<input type="checkbox" value="{{ "{{ d.dataId }}" }}" lay-skin="switch" lay-text="启用|禁用"
|
|
||||||
lay-filter="dict-data-enable"
|
|
||||||
{{ "{{# if(d.enable==1){ }} checked {{# } }}" }}>
|
|
||||||
</script>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery', 'popup'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let popup = layui.popup
|
|
||||||
|
|
||||||
let typeCode
|
|
||||||
|
|
||||||
let cols = [
|
|
||||||
[
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{ title: '字典名称', field: 'typeName', align: 'center', width: 120 },
|
|
||||||
{ title: '描述', field: 'description', align: 'center' },
|
|
||||||
{ title: '字典状态', field: 'enable', align: 'center', templet: '#dict-type-enable' },
|
|
||||||
{ title: '操作', toolbar: '#dict-type-bar', align: 'center', width: 180 }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
let dataCols = [
|
|
||||||
[
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{ title: '标签', field: 'dataLabel', align: 'center', width: 120 },
|
|
||||||
{ title: '对应值', field: 'dataValue', align: 'center' },
|
|
||||||
{ title: '状态', field: 'enable', align: 'center', templet: '#dict-data-enable' },
|
|
||||||
{ title: '操作', toolbar: '#dict-data-bar', align: 'center', width: 180 }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
table.render({
|
|
||||||
elem: '#dict-type-table',
|
|
||||||
url: '/admin/dict/dictType/data',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
height: 'full-148',
|
|
||||||
toolbar: '#dict-type-toolbar',
|
|
||||||
defaultToolbar: [{
|
|
||||||
layEvent: 'refresh',
|
|
||||||
icon: 'layui-icon-refresh',
|
|
||||||
}, 'filter', 'print', 'exports']
|
|
||||||
})
|
|
||||||
|
|
||||||
window.renderData = function (code) {
|
|
||||||
typeCode = code
|
|
||||||
$('.empty').hide()
|
|
||||||
table.render({
|
|
||||||
elem: '#dict-data-table',
|
|
||||||
url: '/admin/dict/dictData/data?typeCode=' + typeCode,
|
|
||||||
page: true,
|
|
||||||
height: 'full-148',
|
|
||||||
cols: dataCols,
|
|
||||||
skin: 'line',
|
|
||||||
toolbar: '#dict-data-toolbar'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
table.on('tool(dict-type-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.removeType(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.editType(obj)
|
|
||||||
} else if (obj.event === 'details') {
|
|
||||||
window.renderData(obj.data['typeCode'])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(dict-type-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.addType()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refreshType()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(dict-type-query)', function (data) {
|
|
||||||
table.reload('dict-type-table', { where: data.field })
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(dict-type-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictType/' + operate,
|
|
||||||
data: JSON.stringify({ id: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg)
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.addType = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '400px'],
|
|
||||||
content: '/admin/dict/dictType/add'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.editType = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '400px'],
|
|
||||||
content: '/admin/dict/dictType/edit?dictTypeId=' + obj.data['id']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.removeType = function (obj) {
|
|
||||||
layer.confirm('确定要删除该字典分类', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictType/remove/' + obj.data['id'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
if (typeCode === obj.data['typeCode']) {
|
|
||||||
$('[lay-id=\'dict-data-table\']').remove()
|
|
||||||
$('.empty').show()
|
|
||||||
}
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.refreshType = function () {
|
|
||||||
table.reload('dict-type-table')
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addData = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '450px'],
|
|
||||||
content: '/admin/dict/dictData/add?typeCode=' + typeCode
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.editData = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '450px'],
|
|
||||||
content: '/admin/dict/dictData/edit?dataId=' + obj.data['dataId']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.removeData = function (obj) {
|
|
||||||
layer.confirm('确定要删除该字典值', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictData/remove/' + obj.data['dataId'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
table.on('tool(dict-data-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.removeData(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.editData(obj)
|
|
||||||
} else if (obj.event === 'details') {
|
|
||||||
window.details(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(dict-data-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.addData()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refreshData()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(dict-data-query)', function (data) {
|
|
||||||
data.field.typeCode = typeCode
|
|
||||||
table.reload('dict-data-table', { where: data.field })
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(dict-data-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/dict/dictData/' + operate,
|
|
||||||
data: JSON.stringify({ dataId: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg)
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.refreshData = function () {
|
|
||||||
table.reload('dict-data-table')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>登录</title>
|
|
||||||
<!-- 样 式 文 件 -->
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='/admin/component/pear/css/pear.css') }}"/>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='/admin/admin/css/other/login.css') }}"/>
|
|
||||||
</head>
|
|
||||||
<!-- 代 码 结 构 -->
|
|
||||||
<body background="{{ url_for('static', filename='/admin/admin/images/background.svg') }}"
|
|
||||||
style="background-size: cover;">
|
|
||||||
<form class="layui-form" action="javascript:void(0);">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<img class="logo" src="{{ url_for('static', filename='/admin/admin/images/logo.png') }}"/>
|
|
||||||
<div class="title">Pear Admin</div>
|
|
||||||
<div class="desc">
|
|
||||||
明 湖 区 最 具 影 响 力 的 设 计 规 范 之 一
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<input name="username" type="text" placeholder="账 户 : admin " value="admin" hover class="layui-input"/>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<input name="password" type="password" placeholder="密 码 : 123456 " value="123456" hover class="layui-input"/>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<input placeholder="验证码 : " name="captcha" hover class="code layui-input layui-input-inline"/>
|
|
||||||
<img src="{{ url_for('passport.get_captcha') }}" class="codeImage" id="captchaImage"/>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<input type="checkbox" name="remember-me" title="记住密码" lay-skin="primary">
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<button class="pear-btn pear-btn-success login" lay-submit lay-filter="login">
|
|
||||||
登 入
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery', 'layer', 'button', 'popup'], function () {
|
|
||||||
let form = layui.form;
|
|
||||||
let $ = layui.jquery;
|
|
||||||
let layer = layui.layer;
|
|
||||||
let button = layui.button;
|
|
||||||
let popup = layui.popup;
|
|
||||||
let captchaPath = "{{ url_for('passport.get_captcha') }}";
|
|
||||||
|
|
||||||
form.on('submit(login)', function (data) {
|
|
||||||
let loader = layer.load();
|
|
||||||
let btn = button.load({elem: '.login'});
|
|
||||||
$.ajax({
|
|
||||||
data: data.field,
|
|
||||||
type: "post",
|
|
||||||
dataType: 'json',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loader);
|
|
||||||
btn.stop(function () {
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
location.href = "{{ url_for('admin.index') }}";
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg, function () {
|
|
||||||
document.getElementById("captchaImage").src = captchaPath + "?" + Math.random();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#captchaImage").click(function () {
|
|
||||||
document.getElementById("captchaImage").src = captchaPath + "?" + Math.random();
|
|
||||||
});
|
|
||||||
setInterval(function () {
|
|
||||||
document.getElementById("captchaImage").src = captchaPath + "?" + Math.random();
|
|
||||||
}, 30 * 1000);
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
if (window !== top) {
|
|
||||||
top.location.href = location.href;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,408 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>首页</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='/admin/admin/css/other/console2.css') }}"/>
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-row layui-col-space10">
|
|
||||||
<div class="layui-col-md8">
|
|
||||||
<div class="layui-row layui-col-space10">
|
|
||||||
<div class="layui-col-md6">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-header">
|
|
||||||
主机信息
|
|
||||||
</div>
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<div class="layui-row layui-col-space10">
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">核心数</div>
|
|
||||||
<div class="count pear-text">{{ cpu_count }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">空闲率</div>
|
|
||||||
<div class="count pear-text"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">等待率</div>
|
|
||||||
<div class="count pear-text"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">使用率</div>
|
|
||||||
<div class="count pear-text">{{ cpus_percent }}%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-header">
|
|
||||||
内存监控
|
|
||||||
</div>
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<div class="layui-row layui-col-space10">
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">空闲内存</div>
|
|
||||||
<div class="count pear-text">{{ memory_free }}M</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">最大内存</div>
|
|
||||||
<div class="count pear-text">{{ memory_total }}M</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">已用内存</div>
|
|
||||||
<div class="count pear-text">{{ memory_used }}M</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
||||||
<div class="pear-card2">
|
|
||||||
<div class="title">内存使用</div>
|
|
||||||
<div class="count pear-text">{{ memory_usage }}%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md12">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-header">主机监控</div>
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<div class="layui-tab custom-tab layui-tab-brief" lay-filter="docDemoTabBrief">
|
|
||||||
<div id="echarts-records" style="background-color:#ffffff;min-height:400px;"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-col-md4">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-header">磁盘信息</div>
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<ul class="pear-card-status">
|
|
||||||
{% for i in disk_partitions_list %}
|
|
||||||
<li>
|
|
||||||
<p>{{ i.device }}</p>
|
|
||||||
<p>{{ i.fstype }}</p>
|
|
||||||
磁盘大小 <span>{{ i.total }}M</span>
|
|
||||||
空闲大小 <span>{{ i.free }}M</span>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
已经使用 <span>{{ i.used }}M</span>
|
|
||||||
使用概率 <span>{{ i.percent }}%</span>
|
|
||||||
<br/>
|
|
||||||
<a href="javascript:;" data-id="1" class="pear-btn pear-btn-xs pear-btn-primary pear-reply">详情</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-header">主机信息</div>
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table class="layui-table" lay-skin="line">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>属性</th>
|
|
||||||
<th>值</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>名称</td>
|
|
||||||
<td>{{ hostname }}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>系统</td>
|
|
||||||
<td>{{ system_version }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>开机时间</td>
|
|
||||||
<td>{{ boot_time }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>运行时长</td>
|
|
||||||
<td>{{ up_time_format }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>python版本</td>
|
|
||||||
<td>{{ python_version }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['layer', 'echarts', 'popup'], function () {
|
|
||||||
var $ = layui.jquery,
|
|
||||||
echarts = layui.echarts;
|
|
||||||
let popup = layui.popup;
|
|
||||||
|
|
||||||
var echartsRecords = echarts.init(document.getElementById('echarts-records'), 'walden');
|
|
||||||
|
|
||||||
$("body").on("click", "[data-url]", function () {
|
|
||||||
parent.layui.tab.addTabOnlyByElem("content", {
|
|
||||||
id: $(this).attr("data-id"),
|
|
||||||
title: $(this).attr("data-title"),
|
|
||||||
url: $(this).attr("data-url"),
|
|
||||||
close: true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
let bgColor = "#fff";
|
|
||||||
let color = [
|
|
||||||
"#0090FF",
|
|
||||||
"#36CE9E",
|
|
||||||
"#FFC005",
|
|
||||||
"#FF515A",
|
|
||||||
"#8B5CFF",
|
|
||||||
"#00CA69"
|
|
||||||
];
|
|
||||||
|
|
||||||
let echartData = [
|
|
||||||
{
|
|
||||||
name: "{{time_now}}",
|
|
||||||
cpu_percent: {{ cpus_percent }},
|
|
||||||
memory_percent: {{ memory_usage }}
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
var xAxisData = echartData.map(v => v.name);
|
|
||||||
// ["1", "2", "3", "4", "5", "6", "7", "8"]
|
|
||||||
var yAxisData1 = echartData.map(v => v.cpu_percent);
|
|
||||||
// [100, 138, 350, 173, 180, 150, 180, 230]
|
|
||||||
var yAxisData2 = echartData.map(v => v.memory_percent);
|
|
||||||
// [233, 233, 200, 180, 199, 233, 210, 180]
|
|
||||||
const hexToRgba = (hex, opacity) => {
|
|
||||||
let rgbaColor = "";
|
|
||||||
let reg = /^#[\da-f]{6}$/i;
|
|
||||||
if (reg.test(hex)) {
|
|
||||||
rgbaColor =
|
|
||||||
`rgba(${parseInt("0x" + hex.slice(1, 3))},${parseInt(
|
|
||||||
"0x" + hex.slice(3, 5)
|
|
||||||
)},${parseInt("0x" + hex.slice(5, 7))},${opacity})`;
|
|
||||||
}
|
|
||||||
return rgbaColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
option = {
|
|
||||||
backgroundColor: bgColor,
|
|
||||||
color: color,
|
|
||||||
legend: {
|
|
||||||
right: 10,
|
|
||||||
top: 10
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: "axis",
|
|
||||||
formatter: function (params) {
|
|
||||||
let html = '';
|
|
||||||
params.forEach(v => {
|
|
||||||
html +=
|
|
||||||
`<div style="color: #666;font-size: 14px;line-height: 24px">
|
|
||||||
<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${color[v.componentIndex]};"></span>
|
|
||||||
${v.seriesName}.${v.name}
|
|
||||||
<span style="color:${color[v.componentIndex]};font-weight:700;font-size: 18px">${v.value}</span>
|
|
||||||
%`;
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return html
|
|
||||||
},
|
|
||||||
extraCssText: 'background: #fff; border-radius: 0;box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);color: #333;',
|
|
||||||
axisPointer: {
|
|
||||||
type: 'shadow',
|
|
||||||
shadowStyle: {
|
|
||||||
color: '#ffffff',
|
|
||||||
shadowColor: 'rgba(225,225,225,1)',
|
|
||||||
shadowBlur: 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: 100,
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: [{
|
|
||||||
type: "category",
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLabel: {
|
|
||||||
formatter: '{value}',
|
|
||||||
textStyle: {
|
|
||||||
color: "#333"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: "#D9D9D9"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: xAxisData
|
|
||||||
}],
|
|
||||||
yAxis: [{
|
|
||||||
type: "value",
|
|
||||||
name: '单位:百分比',
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: "#666"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nameTextStyle: {
|
|
||||||
color: "#666",
|
|
||||||
fontSize: 12,
|
|
||||||
lineHeight: 40
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
type: "dashed",
|
|
||||||
color: "#E9E9E9"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
series: [{
|
|
||||||
name: "CPU",
|
|
||||||
type: "line",
|
|
||||||
smooth: true,
|
|
||||||
symbolSize: 8,
|
|
||||||
zlevel: 3,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
color: color[0],
|
|
||||||
shadowBlur: 3,
|
|
||||||
shadowColor: hexToRgba(color[0], 0.5),
|
|
||||||
shadowOffsetY: 8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
[{
|
|
||||||
offset: 0,
|
|
||||||
color: hexToRgba(color[0], 0.3)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: hexToRgba(color[0], 0.1)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
shadowColor: hexToRgba(color[0], 0.1),
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: yAxisData1
|
|
||||||
}, {
|
|
||||||
name: '内存',
|
|
||||||
type: "line",
|
|
||||||
smooth: true,
|
|
||||||
symbolSize: 8,
|
|
||||||
zlevel: 3,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
color: color[1],
|
|
||||||
shadowBlur: 3,
|
|
||||||
shadowColor: hexToRgba(color[1], 0.5),
|
|
||||||
shadowOffsetY: 8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
[{
|
|
||||||
offset: 0,
|
|
||||||
color: hexToRgba(color[1], 0.3)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: hexToRgba(color[1], 0.1)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
shadowColor: hexToRgba(color[1], 0.1),
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: yAxisData2
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
echartsRecords.setOption(option);
|
|
||||||
|
|
||||||
window.onresize = function () {
|
|
||||||
echartsRecords.resize();
|
|
||||||
};
|
|
||||||
|
|
||||||
setInterval(ajaxPolling, 1000 * 10);
|
|
||||||
|
|
||||||
function ajaxPolling() {
|
|
||||||
$.ajax({
|
|
||||||
url: "/admin/monitor/polling",
|
|
||||||
success: function (data) {
|
|
||||||
echartData.push({
|
|
||||||
name: data.time_now,
|
|
||||||
cpu_percent: data.cups_percent,
|
|
||||||
memory_percent: data.memory_used
|
|
||||||
});
|
|
||||||
if (echartData.length > 8) {
|
|
||||||
echartData.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
xAxisData = echartData.map(v => v.name);
|
|
||||||
yAxisData1 = echartData.map(v => v.cpu_percent);
|
|
||||||
yAxisData2 = echartData.map(v => v.memory_percent);
|
|
||||||
|
|
||||||
option.xAxis[0].data = xAxisData;
|
|
||||||
option.series[0].data = yAxisData1;
|
|
||||||
option.series[1].data = yAxisData2;
|
|
||||||
|
|
||||||
echartsRecords.setOption(option);
|
|
||||||
|
|
||||||
},
|
|
||||||
error: function (xhr, type, errorThrown) {
|
|
||||||
popup.failure("api错误");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>图片上传</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="dataTable" lay-filter="dataTable"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/html" id="toolbar">
|
|
||||||
{% if authorize("admin:file:add") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:file:delete") %}
|
|
||||||
<button class="pear-btn pear-btn-sm" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="user-bar">
|
|
||||||
{% if authorize("admin:file:delete") %}
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i
|
|
||||||
class="layui-icon layui-icon-delete"></i></button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
<script type="text/html" id="file-uploadTime">
|
|
||||||
{{ ' {{layui.util.toDateString(d.create_time, "yyyy-MM-dd HH:mm:ss")}' |safe }}}
|
|
||||||
</script>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let cols = [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
type: 'checkbox'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'id',
|
|
||||||
title: 'ID',
|
|
||||||
sort: true,
|
|
||||||
align: 'center',
|
|
||||||
unresize: true,
|
|
||||||
width: 80
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'name',
|
|
||||||
title: '文件名称',
|
|
||||||
unresize: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'href',
|
|
||||||
title: '图片',
|
|
||||||
unresize: true,
|
|
||||||
align: 'center',
|
|
||||||
templet: function (d) {
|
|
||||||
return '<img class="photo" style="max-width: 100%;\n' +
|
|
||||||
' height: 100%;\n' +
|
|
||||||
' cursor: pointer;" lay-event="photo" src=" ' + d.href + '"></i>'
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'mime',
|
|
||||||
title: 'mime类型',
|
|
||||||
unresize: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'size',
|
|
||||||
title: '文件大小',
|
|
||||||
unresize: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'create_time',
|
|
||||||
title: '创建时间',
|
|
||||||
templet: '#file-uploadTime',
|
|
||||||
unresize: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
toolbar: '#user-bar',
|
|
||||||
align: 'center',
|
|
||||||
unresize: true,
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
table.render({
|
|
||||||
elem: '#dataTable',
|
|
||||||
url: 'table',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
toolbar: '#toolbar',
|
|
||||||
defaultToolbar: [{
|
|
||||||
layEvent: 'refresh',
|
|
||||||
icon: 'layui-icon-refresh',
|
|
||||||
}, 'filter', 'print', 'exports']
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(dataTable)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.remove(obj)
|
|
||||||
} else if (obj.event === 'photo') {
|
|
||||||
window.photo(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(dataTable)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.add()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refresh()
|
|
||||||
} else if (obj.event === 'batchRemove') {
|
|
||||||
window.batchRemove(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
//弹出窗设置 自己设置弹出百分比
|
|
||||||
function screen () {
|
|
||||||
if (typeof width !== 'number' || width === 0) {
|
|
||||||
width = $(window).width() * 0.8
|
|
||||||
}
|
|
||||||
if (typeof height !== 'number' || height === 0) {
|
|
||||||
height = $(window).height() - 20
|
|
||||||
}
|
|
||||||
return [width + 'px', height + 'px']
|
|
||||||
}
|
|
||||||
|
|
||||||
window.add = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
maxmin: true,
|
|
||||||
title: '新增图片',
|
|
||||||
shade: 0.1,
|
|
||||||
area: screen(),
|
|
||||||
content: 'upload'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.remove = function (obj) {
|
|
||||||
layer.confirm('确定要删除该图片', {
|
|
||||||
icon: 3,
|
|
||||||
title: '提示'
|
|
||||||
}, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: 'delete',
|
|
||||||
data: { id: obj.data['id'] },
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'POST',
|
|
||||||
success: function (res) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (res.success) {
|
|
||||||
layer.msg(res.msg, {
|
|
||||||
icon: 1,
|
|
||||||
time: 1000
|
|
||||||
}, function () {
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(res.msg, {
|
|
||||||
icon: 2,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.batchRemove = function (obj) {
|
|
||||||
let data = table.checkStatus(obj.config.id).data
|
|
||||||
if (data.length === 0) {
|
|
||||||
layer.msg('未选中数据', {
|
|
||||||
icon: 3,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var ids = []
|
|
||||||
var hasCheck = table.checkStatus('dataTable')
|
|
||||||
var hasCheckData = hasCheck.data
|
|
||||||
if (hasCheckData.length > 0) {
|
|
||||||
$.each(hasCheckData, function (index, element) {
|
|
||||||
ids.push(element.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
layer.confirm('确定要删除这些图片', {
|
|
||||||
icon: 3,
|
|
||||||
title: '提示'
|
|
||||||
}, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: "{{ url_for('adminFile.batch_remove') }}",
|
|
||||||
data: { ids: ids },
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'POST',
|
|
||||||
success: function (res) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (res.success) {
|
|
||||||
layer.msg(res.msg, {
|
|
||||||
icon: 1,
|
|
||||||
time: 1000
|
|
||||||
}, function () {
|
|
||||||
table.reload('dataTable')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(res.msg, {
|
|
||||||
icon: 2,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.refresh = function () {
|
|
||||||
table.reload('dataTable')
|
|
||||||
}
|
|
||||||
// 查看大图
|
|
||||||
window.photo = function (obj) {
|
|
||||||
if (!obj.data.href || obj.data.href === '') {
|
|
||||||
layer.msg('图片地址错误!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var auto_img = {}
|
|
||||||
var img = new Image()
|
|
||||||
img.src = obj.data.href
|
|
||||||
img.onload = function () {
|
|
||||||
var max_height = $(window).height() - 100
|
|
||||||
var max_width = $(window).width()
|
|
||||||
var rate1 = max_height / img.height
|
|
||||||
var rate2 = max_width / img.width
|
|
||||||
var rate3 = 1
|
|
||||||
var rate = Math.min(rate1, rate2, rate3)
|
|
||||||
auto_img.height = img.height * rate
|
|
||||||
auto_img.width = img.width * rate
|
|
||||||
layer.open({
|
|
||||||
type: 1,
|
|
||||||
title: false,
|
|
||||||
area: ['auto'],
|
|
||||||
skin: 'layui-layer-nobg', //没有背景色
|
|
||||||
shadeClose: true,
|
|
||||||
content: '<img src=\'' + obj.data['href'] + '\' width=\'' + auto_img.width + 'px\' height=\'' + auto_img.height + 'px\'>'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
<style>
|
|
||||||
.pear-container {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="layui-row layui-col-space15">
|
|
||||||
<div class="layui-col-md12">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-tab-content">
|
|
||||||
<fieldset class="layui-elem-field layui-field-title">
|
|
||||||
<legend>新增图片</legend>
|
|
||||||
</fieldset>
|
|
||||||
<form class="layui-form edit-form">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">
|
|
||||||
新增图片
|
|
||||||
</label>
|
|
||||||
<button type="button" class="layui-btn layui-btn-normal" id="logo-img">选择文件</button>
|
|
||||||
<button type="button" class="layui-btn" id="logo-upload-button">开始上传</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['jquery', 'element', 'form', 'upload'], function () {
|
|
||||||
var $ = layui.jquery;
|
|
||||||
var element = layui.element;
|
|
||||||
var form = layui.form;
|
|
||||||
var upload = layui.upload;
|
|
||||||
//选完文件后不自动上传
|
|
||||||
upload.render({
|
|
||||||
elem: '#logo-img'
|
|
||||||
, url: "{{ url_for('adminFile.upload') }}"
|
|
||||||
, auto: false
|
|
||||||
, exts: 'jpg|png|gif|bmp|jpeg'
|
|
||||||
, size: 1000
|
|
||||||
, bindAction: '#logo-upload-button'
|
|
||||||
, done: function (res) {
|
|
||||||
if (res.success) {
|
|
||||||
layer.msg(res.msg, {icon: 1, time: 500}, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name));//关闭当前页
|
|
||||||
window.parent.location.reload();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg(res.msg, {icon: 2});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>权限编辑</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item layui-hide">
|
|
||||||
<label class="layui-form-label">编号</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ power.id }}" name="powerId" lay-verify="title"
|
|
||||||
autocomplete="off" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">父级</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<ul id="selectParent" name="parentId" class="dtree" data-id="-1"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ power.name }}" name="powerName" lay-verify="title"
|
|
||||||
autocomplete="off" placeholder="权限名称" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item" id="powerCodeItem">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" id="powerCode" value="{{ power.code }}" name="powerCode"
|
|
||||||
autocomplete="off" placeholder="权限标识" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" lay-filter="powerType" {% if power.type == "0" %} checked{% endif %}
|
|
||||||
name="powerType" value="0" title="目录">
|
|
||||||
<input type="radio" lay-filter="powerType" {% if power.type == "1" %} checked{% endif %}
|
|
||||||
name="powerType" value="1" title="菜单">
|
|
||||||
<input type="radio" lay-filter="powerType" {% if power.type == "2" %} checked{% endif %}
|
|
||||||
name="powerType" value="2" title="按钮">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item" id="powerUrlItem">
|
|
||||||
<label class="layui-form-label">路径</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" id="powerUrl" value="{{ power.url }}" name="powerUrl"
|
|
||||||
autocomplete="off" placeholder="菜单路径" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item" id="openTypeItem">
|
|
||||||
<label class="layui-form-label">打开</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<select name="openType" id="openType">
|
|
||||||
<option value=""></option>
|
|
||||||
<option value="_iframe" {% if power.open_type == "_iframe" %} selected{% endif %}>框架
|
|
||||||
</option>
|
|
||||||
<option value="_blank" {% if power.open_type == "_blank" %} selected{% endif %}>签页</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">图标</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" id="icon" value="{{ power.icon }}" name="icon" lay-filter="icon"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">排序</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" value="{{ power.sort }}" name="sort" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="排序" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="power-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery', 'iconPicker', 'dtree'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let iconPicker = layui.iconPicker
|
|
||||||
let dtree = layui.dtree
|
|
||||||
|
|
||||||
dtree.renderSelect({
|
|
||||||
elem: '#selectParent',
|
|
||||||
url: '/admin/power/selectParent',
|
|
||||||
method: 'get',
|
|
||||||
selectInputName: { nodeId: 'parentId', context: 'powerName' },
|
|
||||||
skin: 'layui',
|
|
||||||
dataFormat: 'list',
|
|
||||||
response: { treeId: 'powerId', parentId: 'parentId', title: 'powerName' },
|
|
||||||
selectInitVal: "{{ power.parent_id }}"
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('radio(powerType)', function (data) {
|
|
||||||
if (this.value == '0') {
|
|
||||||
$('#powerUrlItem').hide()
|
|
||||||
$('#powerCodeItem').hide()
|
|
||||||
$('#openTypeItem').hide()
|
|
||||||
$('#powerUrl').val('')
|
|
||||||
$('#powerCode').val('')
|
|
||||||
$('#openType').val('')
|
|
||||||
} else if (this.value == '1') {
|
|
||||||
$('#powerUrlItem').show()
|
|
||||||
$('#powerCodeItem').show()
|
|
||||||
$('#openTypeItem').show()
|
|
||||||
} else if (this.value == '2') {
|
|
||||||
$('#powerUrlItem').hide()
|
|
||||||
$('#openTypeItem').hide()
|
|
||||||
$('#powerCodeItem').show()
|
|
||||||
$('#powerUrl').val('')
|
|
||||||
$('#openType').val('')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(power-save)', function (data) {
|
|
||||||
data.field.icon = 'layui-icon ' + data.field.icon
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/power/update',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.render()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
iconPicker.render({
|
|
||||||
elem: '#icon',
|
|
||||||
type: 'fontClass',
|
|
||||||
search: true,
|
|
||||||
page: true,
|
|
||||||
limit: 12,
|
|
||||||
click: function (data) {
|
|
||||||
console.log(data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
iconPicker.checkIcon('icon', "{{ icon }}")
|
|
||||||
|
|
||||||
window.init = function (type) {
|
|
||||||
if (type == '0') {
|
|
||||||
$('#powerUrlItem').hide()
|
|
||||||
$('#powerCodeItem').hide()
|
|
||||||
$('#openTypeItem').hide()
|
|
||||||
$('#powerUrl').val('')
|
|
||||||
$('#powerCode').val('')
|
|
||||||
$('#openType').val('')
|
|
||||||
} else if (type == '1') {
|
|
||||||
$('#powerUrlItem').show()
|
|
||||||
$('#powerCodeItem').show()
|
|
||||||
$('#openTypeItem').show()
|
|
||||||
} else if (type == '2') {
|
|
||||||
$('#powerUrlItem').hide()
|
|
||||||
$('#openTypeItem').hide()
|
|
||||||
$('#powerCodeItem').show()
|
|
||||||
$('#powerUrl').val('')
|
|
||||||
$('#openType').val('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.init("{{ power.type}}")
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>权限</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">权限名称</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="powerName" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="power-query">
|
|
||||||
<i class="layui-icon layui-icon-search"></i>
|
|
||||||
查询
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-md">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="power-table" lay-filter="power-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/html" id="power-toolbar">
|
|
||||||
{% if authorize("admin:power:add") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="power-bar">
|
|
||||||
{% if authorize("admin:role:edit") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i
|
|
||||||
class="layui-icon layui-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i
|
|
||||||
class="layui-icon layui-icon-delete"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="power-type">
|
|
||||||
{{ "
|
|
||||||
{{#if (d.powerType == '0') { }}
|
|
||||||
<span>目录</span>
|
|
||||||
{{# }else if(d.powerType == '1'){ }}
|
|
||||||
<span>菜单</span>
|
|
||||||
{{# }else if(d.powerType == '2'){ }}
|
|
||||||
<span>按钮</span>
|
|
||||||
{{# } }}
|
|
||||||
|
|
||||||
" |safe }}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="power-enable">
|
|
||||||
<input type="checkbox" name="enable" value="{{ "{{d.powerId}}" }}" lay-skin="switch" lay-text="启用|禁用"
|
|
||||||
lay-filter="power-enable" {{ "{{# if(d.enable==1){ }} checked {{# } }}" }}>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="icon">
|
|
||||||
<i class="layui-icon {{ "{{d.icon}}" }}"></i>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery', 'treetable', 'popup'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let treetable = layui.treetable
|
|
||||||
let popup = layui.popup
|
|
||||||
|
|
||||||
let MODULE_PATH = '/admin/power/'
|
|
||||||
|
|
||||||
window.render = function () {
|
|
||||||
treetable.render({
|
|
||||||
treeColIndex: 1,
|
|
||||||
treeSpid: 0,
|
|
||||||
treeIdName: 'powerId',
|
|
||||||
treePidName: 'parentId',
|
|
||||||
skin: 'line',
|
|
||||||
method: 'post',
|
|
||||||
treeDefaultClose: true,
|
|
||||||
toolbar: '#power-toolbar',
|
|
||||||
elem: '#power-table',
|
|
||||||
url: '/admin/power/data',
|
|
||||||
page: false,
|
|
||||||
cols: [
|
|
||||||
[
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{% endif %}
|
|
||||||
{ field: 'powerName', minWidth: 200, title: '权限名称' },
|
|
||||||
{ field: 'icon', title: '图标', templet: '#icon' },
|
|
||||||
{ field: 'powerType', title: '权限类型', templet: '#power-type' },
|
|
||||||
{ field: 'enable', title: '是否可用', templet: '#power-enable' },
|
|
||||||
{ field: 'sort', title: '排序' },
|
|
||||||
{ title: '操作', templet: '#power-bar', width: 150, align: 'center' }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render()
|
|
||||||
|
|
||||||
form.on('submit(power-query)', function (data) {
|
|
||||||
var keyword = data.field.powerName
|
|
||||||
var $tds = $('#power-table').next('.treeTable').find('.layui-table-body tbody tr td')
|
|
||||||
if (!keyword) {
|
|
||||||
$tds.css('background-color', 'transparent')
|
|
||||||
layer.msg('请输入关键字', { icon: 5 })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var searchCount = 0
|
|
||||||
$tds.each(function () {
|
|
||||||
$(this).css('background-color', 'transparent')
|
|
||||||
if ($(this).text().indexOf(keyword) >= 0) {
|
|
||||||
$(this).css('background-color', 'rgba(250,230,160,0.5)')
|
|
||||||
if (searchCount === 0) {
|
|
||||||
$('body,html').stop(true)
|
|
||||||
$('body,html').animate({ scrollTop: $(this).offset().top - 150 }, 500)
|
|
||||||
}
|
|
||||||
searchCount++
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (searchCount === 0) {
|
|
||||||
layer.msg('没有匹配结果', { icon: 5 })
|
|
||||||
} else {
|
|
||||||
treetable.expandAll('#power-table')
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(power-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.remove(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.edit(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(power-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.add()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refresh()
|
|
||||||
} else if (obj.event === 'batchRemove') {
|
|
||||||
window.batchRemove(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(power-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/power/' + operate,
|
|
||||||
data: JSON.stringify({ powerId: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg)
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.add = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['450px', '500px'],
|
|
||||||
content: MODULE_PATH + 'add'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.edit = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['450px', '500px'],
|
|
||||||
content: MODULE_PATH + 'edit/' + obj.data['powerId']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
window.remove = function (obj) {
|
|
||||||
layer.confirm('确定要删除该权限', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: MODULE_PATH + 'remove/' + obj.data['powerId'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
console.log(obj)
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.batchRemove = function (obj) {
|
|
||||||
let data = table.checkStatus(obj.config.id).data
|
|
||||||
if (data.length === 0) {
|
|
||||||
layer.msg('未选中数据', {
|
|
||||||
icon: 3,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var ids = []
|
|
||||||
var hasCheck = table.checkStatus('power-table')
|
|
||||||
var hasCheckData = hasCheck.data
|
|
||||||
if (hasCheckData.length > 0) {
|
|
||||||
$.each(hasCheckData, function (index, element) {
|
|
||||||
ids.push(element.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
layer.confirm('确定要删除选中权限', {
|
|
||||||
icon: 3,
|
|
||||||
title: '提示'
|
|
||||||
}, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: MODULE_PATH + 'batchRemove',
|
|
||||||
data: { ids: ids },
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
console.log(obj)
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>角色新增</title>
|
|
||||||
{% include 'admin/common/header.html' %}</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">名称</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="roleName" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">标识</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="roleCode" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">状态</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="radio" name="enable" value="0" title="开启">
|
|
||||||
<input type="radio" name="enable" value="1" title="关闭" checked>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">排序</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="text" name="sort" lay-verify="title" autocomplete="off" placeholder="请输入标题"
|
|
||||||
class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item layui-form-text">
|
|
||||||
<label class="layui-form-label">描述</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<textarea placeholder="请输入描述" name="details" class="layui-textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="role-save">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
|
|
||||||
form.on('submit(role-save)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/role/save',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'post',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
|
||||||
parent.layui.table.reload('role-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>用户管理</title>
|
|
||||||
{% include 'admin/common/header.html' %}</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">角色名</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="roleName" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<label class="layui-form-label">角色标识</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="roleCode" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="role-query">
|
|
||||||
<i class="layui-icon layui-icon-search"></i>
|
|
||||||
查询
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-md">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="role-table" lay-filter="role-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
<script type="text/html" id="role-toolbar">
|
|
||||||
{% if authorize("admin:role:add") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="layui-icon layui-icon-add-1"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="layui-icon layui-icon-delete"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="role-bar">
|
|
||||||
{% if authorize("admin:role:edit") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i
|
|
||||||
class="layui-icon layui-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:role:power") %}
|
|
||||||
<button class="pear-btn pear-btn-warming pear-btn-sm" lay-event="power"><i
|
|
||||||
class="layui-icon layui-icon-vercode"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i
|
|
||||||
class="layui-icon layui-icon-delete"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/html" id="role-enable">
|
|
||||||
<input type="checkbox" name="enable" value="{{ "{{d.id}}" }}" lay-skin="switch" lay-text="启用|禁用"
|
|
||||||
lay-filter="role-enable" {{ "{{# if(d.enable==1){ }} checked {{# } }}" }}>
|
|
||||||
</script>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'form', 'jquery', 'popup', 'common'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let popup = layui.popup
|
|
||||||
|
|
||||||
let MODULE_PATH = '/admin/role/'
|
|
||||||
|
|
||||||
let cols = [
|
|
||||||
[
|
|
||||||
{% if authorize("admin:role:remove") %}
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{% endif %}
|
|
||||||
{ title: '角色名', field: 'roleName', align: 'center', width: 100 },
|
|
||||||
{ title: 'Key值', field: 'roleCode', align: 'center' },
|
|
||||||
{ title: '描述', field: 'details', align: 'center' },
|
|
||||||
{ title: '是否可用', field: 'enable', align: 'center', templet: '#role-enable' },
|
|
||||||
{ title: '排序', field: 'sort', align: 'center' },
|
|
||||||
{ title: '操作', toolbar: '#role-bar', align: 'center', width: 195 }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
table.render({
|
|
||||||
elem: '#role-table',
|
|
||||||
url: MODULE_PATH + 'data',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
toolbar: '#role-toolbar',
|
|
||||||
defaultToolbar: [{
|
|
||||||
layEvent: 'refresh',
|
|
||||||
icon: 'layui-icon-refresh',
|
|
||||||
}, 'filter', 'print', 'exports']
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(role-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.remove(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.edit(obj)
|
|
||||||
} else if (obj.event === 'power') {
|
|
||||||
window.power(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(role-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.add()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refresh()
|
|
||||||
} else if (obj.event === 'batchRemove') {
|
|
||||||
window.batchRemove(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(role-query)', function (data) {
|
|
||||||
table.reload('role-table', { where: data.field })
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(role-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/role/' + operate,
|
|
||||||
data: JSON.stringify({ roleId: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 })
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.add = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '500px'],
|
|
||||||
content: MODULE_PATH + 'add'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.power = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '授权',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['320px', '400px'],
|
|
||||||
content: MODULE_PATH + 'power/' + obj.data['id']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.edit = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['500px', '500px'],
|
|
||||||
content: MODULE_PATH + 'edit/' + obj.data['id']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.remove = function (obj) {
|
|
||||||
layer.confirm('确定要删除该角色', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: MODULE_PATH + 'remove/' + obj.data['id'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
layer.msg(result.msg, { icon: 2, time: 1000 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.batchRemove = function (obj) {
|
|
||||||
let data = table.checkStatus(obj.config.id).data
|
|
||||||
if (data.length === 0) {
|
|
||||||
layer.msg('未选中数据', {
|
|
||||||
icon: 3,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var ids = []
|
|
||||||
var hasCheck = table.checkStatus('role-table')
|
|
||||||
var hasCheckData = hasCheck.data
|
|
||||||
if (hasCheckData.length > 0) {
|
|
||||||
$.each(hasCheckData, function (index, element) {
|
|
||||||
ids.push(element.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
console.log(ids)
|
|
||||||
layer.confirm('确定要删除选中角色', {
|
|
||||||
icon: 3,
|
|
||||||
title: '提示'
|
|
||||||
}, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
|
|
||||||
url: MODULE_PATH + 'batchRemove',
|
|
||||||
data: { ids: ids },
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
table.reload('role-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.refresh = function () {
|
|
||||||
table.reload('role-table')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>修改密码</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form class="layui-form" action="">
|
|
||||||
<div class="mainBox">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="main-container">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">旧密码</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="password" name="oldPassword" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">新密码</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="password" name="newPassword" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">确认密码</label>
|
|
||||||
<div class="layui-input-block">
|
|
||||||
<input type="password" name="confirmPassword" lay-verify="title" autocomplete="off"
|
|
||||||
placeholder="请输入标题" class="layui-input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div class="button-container">
|
|
||||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
|
||||||
lay-filter="edit-password">
|
|
||||||
<i class="layui-icon layui-icon-ok"></i>
|
|
||||||
提交
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-sm">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
<script>
|
|
||||||
layui.use(['form', 'jquery', 'popup'], function () {
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let popup = layui.popup
|
|
||||||
|
|
||||||
// 修改密码提交
|
|
||||||
form.on('submit(edit-password)', function (data) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/user/editPassword',
|
|
||||||
data: JSON.stringify(data.field),
|
|
||||||
contentType: 'application/json',
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
parent.layer.close(parent.layer.getFrameIndex(window.name))
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>用户管理</title>
|
|
||||||
{% include 'admin/common/header.html' %}
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='/admin/admin/css/other/user.css') }}"/>
|
|
||||||
</head>
|
|
||||||
<body class="pear-container">
|
|
||||||
{# 查询表单 #}
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<form class="layui-form" action="" lay-filter="user-query-form">
|
|
||||||
<div class="layui-form-item">
|
|
||||||
<label class="layui-form-label">用户</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="realName" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<label class="layui-form-label">账号</label>
|
|
||||||
<div class="layui-input-inline">
|
|
||||||
<input type="text" name="username" placeholder="" class="layui-input">
|
|
||||||
</div>
|
|
||||||
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="user-query">
|
|
||||||
<i class="layui-icon layui-icon-search"></i>
|
|
||||||
查询
|
|
||||||
</button>
|
|
||||||
<button type="reset" class="pear-btn pear-btn-md">
|
|
||||||
<i class="layui-icon layui-icon-refresh"></i>
|
|
||||||
重置
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="user-left user-collasped">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<div class="button button-primary user-group" user-group=""> 全 部 用 户</div>
|
|
||||||
<div class="button button-default user-group" user-group="-1"> 默 认 分 组</div>
|
|
||||||
<div style="overflow: auto">
|
|
||||||
<ul id="dept-tree" class="dept-tree" data-id="0"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{# 用户表格 #}
|
|
||||||
<div class="user-main user-collasped">
|
|
||||||
<div class="layui-card">
|
|
||||||
<div class="layui-card-body">
|
|
||||||
<table id="user-table" lay-filter="user-table"></table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
{# 表格操作 #}
|
|
||||||
<script type="text/html" id="user-toolbar">
|
|
||||||
{% if authorize("admin:user:add") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
|
|
||||||
<i class="pear-icon pear-icon-add"></i>
|
|
||||||
新增
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:user:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="batchRemove">
|
|
||||||
<i class="pear-icon pear-icon-ashbin"></i>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
<button class="pear-btn pear-btn-md" lay-event="collasped">
|
|
||||||
<i class="pear-icon pear-icon-modular"></i>
|
|
||||||
高级
|
|
||||||
</button>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{# 用户修改操作 #}
|
|
||||||
<script type="text/html" id="user-bar">
|
|
||||||
{% if authorize("admin:user:edit") %}
|
|
||||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i class="pear-icon pear-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if authorize("admin:user:remove") %}
|
|
||||||
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i
|
|
||||||
class="pear-icon pear-icon-ashbin"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{# 启动与禁用 #}
|
|
||||||
<script type="text/html" id="user-enable">
|
|
||||||
<input type="checkbox" name="enable" value="{{ "{{ d.id }}" }}" lay-skin="switch" lay-text="启用|禁用"
|
|
||||||
lay-filter="user-enable"
|
|
||||||
{{ "{{# if(d.enable==1){ }} checked {{# } }}" }} />
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{# 用户注册时间 #}
|
|
||||||
<script type="text/html" id="user-createTime">
|
|
||||||
{{ ' {{layui.util.toDateString(d.create_at, "yyyy-MM-dd HH:mm:ss")}' |safe }}}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{# 用户更新时间 #}
|
|
||||||
<script type="text/html" id="user-updateTime">
|
|
||||||
{{ ' {{layui.util.toDateString(d.update_at, "yyyy-MM-dd HH:mm:ss")}' |safe }}}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% include 'admin/common/footer.html' %}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
layui.use(['table', 'dtree', 'form', 'jquery', 'popup', 'common'], function () {
|
|
||||||
let table = layui.table
|
|
||||||
let form = layui.form
|
|
||||||
let $ = layui.jquery
|
|
||||||
let dtree = layui.dtree
|
|
||||||
let popup = layui.popup
|
|
||||||
let common = layui.common
|
|
||||||
let MODULE_PATH = '/admin/user/'
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
let cols = [
|
|
||||||
[
|
|
||||||
{% if authorize("admin:user:remove") %}
|
|
||||||
{ type: 'checkbox' },
|
|
||||||
{% endif %}
|
|
||||||
{ title: '姓名', field: 'realname', align: 'center', width: 110 },
|
|
||||||
{ title: '账号', field: 'username', align: 'center' },
|
|
||||||
{ title: '部门', field: 'dept', align: 'center' },
|
|
||||||
{ title: '启用', field: 'enable', align: 'center', templet: '#user-enable', width: 120 },
|
|
||||||
{ title: '注册时间', field: 'create_at', templet: '#user-createTime', align: 'center' },
|
|
||||||
{ title: '更新时间', field: 'update_at', templet: '#user-updateTime', align: 'center' },
|
|
||||||
{ title: '操作', toolbar: '#user-bar', align: 'center', width: 130 }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
// 渲染表格数据
|
|
||||||
table.render({
|
|
||||||
elem: '#user-table',
|
|
||||||
url: MODULE_PATH + 'data',
|
|
||||||
page: true,
|
|
||||||
cols: cols,
|
|
||||||
skin: 'line',
|
|
||||||
height: 'full-148',
|
|
||||||
toolbar: '#user-toolbar', /*工具栏*/
|
|
||||||
text: { none: '暂无人员信息' },
|
|
||||||
defaultToolbar: [{ layEvent: 'refresh', icon: 'layui-icon-refresh' }, 'filter', 'print', 'exports'] /*默认工具栏*/
|
|
||||||
})
|
|
||||||
|
|
||||||
// 公司部门树状图菜单
|
|
||||||
dtree.render({
|
|
||||||
elem: '#dept-tree',
|
|
||||||
method: 'get',
|
|
||||||
url: '/dept/tree',
|
|
||||||
dataFormat: 'list',
|
|
||||||
line: true,
|
|
||||||
skin: 'laySimple',
|
|
||||||
icon: '-1',
|
|
||||||
response: { treeId: 'deptId', parentId: 'parentId', title: 'deptName' },
|
|
||||||
})
|
|
||||||
|
|
||||||
// 菜单栏渲染
|
|
||||||
dtree.on('node(\'dept-tree\')', function (obj) {
|
|
||||||
let field = form.val('user-query-form') /*用户账号查询*/
|
|
||||||
field.deptId = obj.param.nodeId
|
|
||||||
window.refresh(field)
|
|
||||||
})
|
|
||||||
|
|
||||||
//
|
|
||||||
$('.user-group').click(function () {
|
|
||||||
let group = $(this).attr('user-group')
|
|
||||||
let field = form.val('user-query-form')
|
|
||||||
if (group === '-1') {
|
|
||||||
field.deptId = group
|
|
||||||
$(this).removeClass('button-default')
|
|
||||||
$(this).prev().removeClass('button-primary')
|
|
||||||
$(this).prev().addClass('button-default')
|
|
||||||
$(this).addClass('button-primary')
|
|
||||||
} else {
|
|
||||||
field.deptId = group
|
|
||||||
$(this).removeClass('button-default')
|
|
||||||
$(this).next().removeClass('button-primary')
|
|
||||||
$(this).next().addClass('button-default')
|
|
||||||
$(this).addClass('button-primary')
|
|
||||||
}
|
|
||||||
window.refresh(field)
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('tool(user-table)', function (obj) {
|
|
||||||
if (obj.event === 'remove') {
|
|
||||||
window.remove(obj)
|
|
||||||
} else if (obj.event === 'edit') {
|
|
||||||
window.edit(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
table.on('toolbar(user-table)', function (obj) {
|
|
||||||
if (obj.event === 'add') {
|
|
||||||
window.add()
|
|
||||||
} else if (obj.event === 'refresh') {
|
|
||||||
window.refresh()
|
|
||||||
} else if (obj.event === 'batchRemove') {
|
|
||||||
window.batchRemove(obj)
|
|
||||||
} else if (obj.event === 'collasped') {
|
|
||||||
$('.user-left').toggleClass('user-collasped')
|
|
||||||
$('.user-main').toggleClass('user-collasped')
|
|
||||||
table.resize()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('submit(user-query)', function (data) {
|
|
||||||
window.refresh(data.field)
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
form.on('switch(user-enable)', function (obj) {
|
|
||||||
let operate
|
|
||||||
if (obj.elem.checked) {
|
|
||||||
operate = 'enable'
|
|
||||||
} else {
|
|
||||||
operate = 'disable'
|
|
||||||
}
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: '/admin/user/' + operate,
|
|
||||||
data: JSON.stringify({ userId: this.value }),
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'put',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg)
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.add = function () {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '新增',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['550px', '550px'],
|
|
||||||
content: MODULE_PATH + 'add'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.edit = function (obj) {
|
|
||||||
layer.open({
|
|
||||||
type: 2,
|
|
||||||
title: '修改',
|
|
||||||
shade: 0.1,
|
|
||||||
area: ['550px', '500px'],
|
|
||||||
content: MODULE_PATH + 'edit/' + obj.data['id']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.remove = function (obj) {
|
|
||||||
layer.confirm('确定要删除该用户', { icon: 3, title: '提示' }, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
url: MODULE_PATH + 'remove/' + obj.data['id'],
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
obj.del()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.batchRemove = function (obj) {
|
|
||||||
let data = table.checkStatus(obj.config.id).data
|
|
||||||
if (data.length === 0) {
|
|
||||||
layer.msg('未选中数据', {
|
|
||||||
icon: 3,
|
|
||||||
time: 1000
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var ids = []
|
|
||||||
var hasCheck = table.checkStatus('user-table')
|
|
||||||
var hasCheckData = hasCheck.data
|
|
||||||
if (hasCheckData.length > 0) {
|
|
||||||
$.each(hasCheckData, function (index, element) {
|
|
||||||
ids.push(element.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{#console.log(ids);#}
|
|
||||||
layer.confirm('确定要删除选中角色', {
|
|
||||||
icon: 3,
|
|
||||||
title: '提示'
|
|
||||||
}, function (index) {
|
|
||||||
layer.close(index)
|
|
||||||
let loading = layer.load()
|
|
||||||
$.ajax({
|
|
||||||
|
|
||||||
url: MODULE_PATH + 'batchRemove',
|
|
||||||
data: { ids: ids },
|
|
||||||
dataType: 'json',
|
|
||||||
type: 'delete',
|
|
||||||
success: function (result) {
|
|
||||||
layer.close(loading)
|
|
||||||
if (result.success) {
|
|
||||||
popup.success(result.msg, function () {
|
|
||||||
table.reload('role-table')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
popup.failure(result.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.refresh = function (param) {
|
|
||||||
table.reload('user-table', { where: param })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from common import register_api
|
||||||
|
from .user import UserApi, user_role_resource, user_info
|
||||||
|
|
||||||
|
|
||||||
|
def register_users_api(api_bp):
|
||||||
|
api_bp.add_url_rule('/users/user/<int:_id>/<action>',
|
||||||
|
view_func=user_info,
|
||||||
|
methods=['PUT'])
|
||||||
|
|
||||||
|
register_api(UserApi, 'users_api', '/users/user/', pk='_id', app=api_bp)
|
||||||
|
|
||||||
|
api_bp.add_url_rule('/users/user/<int:_id>/role',
|
||||||
|
view_func=user_role_resource,
|
||||||
|
methods=['PUT'])
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
import typing as t
|
||||||
|
|
||||||
|
from flask import request, jsonify
|
||||||
|
from flask.views import MethodView
|
||||||
|
from flask_login import current_user
|
||||||
|
from flask_pydantic import validate
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
from common.utils.http import fail_api, success_api, table_api
|
||||||
|
from extensions import db
|
||||||
|
from models import LogModel
|
||||||
|
from models import UserModel, RoleModel, DepartmentModel
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_user_logs():
|
||||||
|
""" 获取当前用户日志 """
|
||||||
|
log = LogModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||||
|
desc(LogModel.create_at)).limit(10)
|
||||||
|
return log
|
||||||
|
|
||||||
|
|
||||||
|
def is_user_exists(username):
|
||||||
|
""" 判断用户是否存在 """
|
||||||
|
res = UserModel.query.filter_by(username=username).count()
|
||||||
|
return bool(res)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_by_id(_id):
|
||||||
|
""" 删除用户 """
|
||||||
|
user = UserModel.query.filter_by(id=_id).first()
|
||||||
|
roles_id = []
|
||||||
|
for role in user.role:
|
||||||
|
roles_id.append(role.id)
|
||||||
|
roles = RoleModel.query.filter(RoleModel.id.in_(roles_id)).all()
|
||||||
|
for r in roles:
|
||||||
|
user.role.remove(r)
|
||||||
|
res = UserModel.query.filter_by(id=_id).delete()
|
||||||
|
db.session.commit()
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def batch_remove(ids):
|
||||||
|
""" 批量删除 """
|
||||||
|
for _id in ids:
|
||||||
|
delete_by_id(_id)
|
||||||
|
|
||||||
|
|
||||||
|
def update_user_role(_id, roles_list):
|
||||||
|
user = UserModel.query.filter_by(id=_id).first()
|
||||||
|
roles_id = []
|
||||||
|
for role in user.role:
|
||||||
|
roles_id.append(role.id)
|
||||||
|
roles = RoleModel.query.filter(RoleModel.id.in_(roles_id)).all()
|
||||||
|
for r in roles:
|
||||||
|
user.role.remove(r)
|
||||||
|
roles = RoleModel.query.filter(RoleModel.id.in_(roles_list)).all()
|
||||||
|
for r in roles:
|
||||||
|
user.role.append(r)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def users_delete():
|
||||||
|
"""批量删除"""
|
||||||
|
ids = request.form.getlist('ids[]')
|
||||||
|
batch_remove(ids)
|
||||||
|
return success_api(message="批量删除成功")
|
||||||
|
|
||||||
|
|
||||||
|
class QueryModel(BaseModel):
|
||||||
|
page: int = 1
|
||||||
|
limit: int = 10
|
||||||
|
real_name: t.Optional[str] = Field(alias='realName')
|
||||||
|
username: t.Optional[str]
|
||||||
|
dept_id: t.Optional[str] = Field(alias='deptId', default=0)
|
||||||
|
phone: t.Optional[str]
|
||||||
|
sort: t.Optional[int]
|
||||||
|
status: t.Optional[int]
|
||||||
|
|
||||||
|
|
||||||
|
class PersonModel(BaseModel):
|
||||||
|
role_ids: str = Field(alias='roleIds')
|
||||||
|
username: str
|
||||||
|
real_name: str = Field(alias='realName')
|
||||||
|
password: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserApi(MethodView):
|
||||||
|
"""修改用户数据"""
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def get(self, _id, query: QueryModel):
|
||||||
|
|
||||||
|
filters = []
|
||||||
|
|
||||||
|
if query.real_name:
|
||||||
|
filters.append(UserModel.realname.like('%' + query.real_name + '%'))
|
||||||
|
if query.username:
|
||||||
|
filters.append(UserModel.username.like('%' + query.username + '%'))
|
||||||
|
if query.dept_id:
|
||||||
|
filters.append(UserModel.dept_id == query.dept_id)
|
||||||
|
|
||||||
|
paginate = UserModel.query.filter(
|
||||||
|
*filters).paginate(
|
||||||
|
page=query.page, per_page=query.limit, error_out=False)
|
||||||
|
|
||||||
|
dept_name = lambda _id: DepartmentModel.query.filter_by(id=_id).first().dept_name if _id else ""
|
||||||
|
user_data = [{
|
||||||
|
'id': item.id,
|
||||||
|
'username': item.username,
|
||||||
|
'realname': item.realname,
|
||||||
|
'enable': item.enable,
|
||||||
|
'create_at': str(item.create_at),
|
||||||
|
'update_at': str(item.update_at),
|
||||||
|
'dept': dept_name(item.dept_id),
|
||||||
|
} for item in paginate.items]
|
||||||
|
return table_api(
|
||||||
|
result={
|
||||||
|
'items': user_data,
|
||||||
|
'total': paginate.total,
|
||||||
|
}
|
||||||
|
, code=0
|
||||||
|
)
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def post(self, body: PersonModel):
|
||||||
|
"""新建单个用户"""
|
||||||
|
|
||||||
|
role_ids = body.role_ids.split(',')
|
||||||
|
|
||||||
|
if is_user_exists(body.username):
|
||||||
|
return fail_api(message="用户已经存在")
|
||||||
|
|
||||||
|
user = UserModel()
|
||||||
|
user.username = body.username
|
||||||
|
user.realname = body.real_name
|
||||||
|
user.set_password(body.password)
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
""" 增加用户角色 """
|
||||||
|
user = UserModel.query.filter_by(id=user.id).first()
|
||||||
|
roles = RoleModel.query.filter(RoleModel.id.in_(role_ids)).all()
|
||||||
|
for r in roles:
|
||||||
|
user.role.append(r)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success_api(message="增加成功", code=0)
|
||||||
|
|
||||||
|
def delete(self, _id):
|
||||||
|
# 删除用户
|
||||||
|
res = delete_by_id(_id)
|
||||||
|
if not res:
|
||||||
|
return fail_api(message="删除失败")
|
||||||
|
return success_api(message="删除成功")
|
||||||
|
|
||||||
|
|
||||||
|
class PersonModel2(BaseModel):
|
||||||
|
role_ids: str = Field(alias='roleIds')
|
||||||
|
user_id: str = Field(alias='userId')
|
||||||
|
username: str
|
||||||
|
real_name: str = Field(alias='realName')
|
||||||
|
dept_id: str = Field(alias='deptId')
|
||||||
|
|
||||||
|
|
||||||
|
@validate()
|
||||||
|
def user_role_resource(_id, body: PersonModel2):
|
||||||
|
role_ids = body.role_ids.split(',')
|
||||||
|
|
||||||
|
# 更新用户数据
|
||||||
|
UserModel.query.filter_by(id=_id).update({'username': body.username,
|
||||||
|
'realname': body.real_name,
|
||||||
|
'dept_id': body.dept_id})
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
update_user_role(_id, role_ids)
|
||||||
|
|
||||||
|
return success_api(message="更新成功")
|
||||||
|
|
||||||
|
|
||||||
|
def user_info(_id, action):
|
||||||
|
if action == 'info':
|
||||||
|
real_name = request.json.get('realName', '')
|
||||||
|
username = request.json.get('username', '')
|
||||||
|
remark = request.json.get('remark', '')
|
||||||
|
details = request.json.get('details', '')
|
||||||
|
|
||||||
|
ret = UserModel.query.get(_id)
|
||||||
|
ret.username = username
|
||||||
|
ret.realname = real_name
|
||||||
|
ret.remark = details
|
||||||
|
db.session.commit()
|
||||||
|
if not ret:
|
||||||
|
return fail_api(message="出错啦")
|
||||||
|
return success_api(message="更新成功")
|
||||||
|
elif action == 'status':
|
||||||
|
user_id = int(request.json.get('userId', 0)) # int
|
||||||
|
operate = int(request.json.get('operate', 0)) # int
|
||||||
|
if operate not in [0, 1]:
|
||||||
|
return {'status': 'error', 'message': '请求有误'}
|
||||||
|
|
||||||
|
if operate == 1:
|
||||||
|
user = UserModel.query.get(_id)
|
||||||
|
user.enable = operate
|
||||||
|
message = success_api(message="启动成功")
|
||||||
|
else:
|
||||||
|
user = UserModel.query.filter_by(id=user_id).update({"enable": operate})
|
||||||
|
message = success_api(message="禁用成功")
|
||||||
|
if user:
|
||||||
|
db.session.commit()
|
||||||
|
else:
|
||||||
|
return fail_api(message="出错啦")
|
||||||
|
return message
|
||||||
|
elif action == 'avatar':
|
||||||
|
url = request.json.get("avatar").get("src")
|
||||||
|
ret = UserModel.query.get(_id)
|
||||||
|
ret.avatar = url
|
||||||
|
db.session.commit()
|
||||||
|
if not ret:
|
||||||
|
return fail_api(message="出错啦")
|
||||||
|
return success_api(message="修改成功")
|
||||||
|
elif action == 'password':
|
||||||
|
oldPassword = request.json.get('oldPassword', '')
|
||||||
|
newPassword = request.json.get('newPassword', '')
|
||||||
|
confirmPassword = request.json.get('confirmPassword', '')
|
||||||
|
if not all([oldPassword, newPassword, confirmPassword]):
|
||||||
|
return {'status': 'error', 'message': '密码不能为空'}
|
||||||
|
|
||||||
|
if newPassword != confirmPassword:
|
||||||
|
return fail_api(message='确认密码不一致')
|
||||||
|
|
||||||
|
""" 修改当前用户密码 """
|
||||||
|
user = UserModel.query.get(_id)
|
||||||
|
is_right = user.validate_password(oldPassword)
|
||||||
|
if not is_right:
|
||||||
|
return jsonify(success=False, message="旧密码错误")
|
||||||
|
user.set_password(newPassword)
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify(success=True, message="更改成功")
|
||||||
|
else:
|
||||||
|
return jsonify(success=False, message="操作有误")
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
from applications.view.admin import register_admin_views
|
from flask import Flask
|
||||||
from applications.view.index import register_index_views
|
|
||||||
from applications.view.passport import register_passport_views
|
from .index import index_bp
|
||||||
from applications.view.rights import register_rights_view
|
from .logs_view import logs_bp
|
||||||
from applications.view.department import register_dept_views
|
from .roles import role_bp
|
||||||
|
|
||||||
|
from . import department
|
||||||
|
from . import file
|
||||||
|
from . import rights
|
||||||
|
from . import passport
|
||||||
|
from . import users
|
||||||
|
|
||||||
|
|
||||||
def init_view(app):
|
def init_view(app: Flask):
|
||||||
register_admin_views(app)
|
app.register_blueprint(index_bp)
|
||||||
register_index_views(app)
|
app.register_blueprint(logs_bp)
|
||||||
register_rights_view(app)
|
app.register_blueprint(role_bp)
|
||||||
register_passport_views(app)
|
|
||||||
register_dept_views(app)
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
|
|
||||||
from applications.view.admin.admin_log import admin_log
|
|
||||||
from applications.view.admin.dict import admin_dict
|
|
||||||
from applications.view.admin.index import admin_bp
|
|
||||||
from applications.view.admin.file import admin_file
|
|
||||||
from applications.view.admin.power import admin_power
|
|
||||||
from applications.view.admin.role import admin_role
|
|
||||||
from applications.view.admin.user import admin_user
|
|
||||||
from applications.view.admin.monitor import admin_monitor_bp
|
|
||||||
|
|
||||||
|
|
||||||
def register_admin_views(app: Flask):
|
|
||||||
app.register_blueprint(admin_bp)
|
|
||||||
app.register_blueprint(admin_user)
|
|
||||||
app.register_blueprint(admin_file)
|
|
||||||
app.register_blueprint(admin_monitor_bp)
|
|
||||||
app.register_blueprint(admin_log)
|
|
||||||
app.register_blueprint(admin_power)
|
|
||||||
app.register_blueprint(admin_role)
|
|
||||||
app.register_blueprint(admin_dict)
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
from flask import Blueprint, request, render_template
|
|
||||||
from sqlalchemy import desc
|
|
||||||
|
|
||||||
from applications.common.utils.http import table_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.models import AdminLog, LogSchema
|
|
||||||
from applications.common.curd import model_to_dicts
|
|
||||||
|
|
||||||
admin_log = Blueprint('adminLog', __name__, url_prefix='/admin/log')
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
# ------------------------- 日志管理 --------------------------
|
|
||||||
# ----------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
@admin_log.get('/')
|
|
||||||
@authorize("admin:log:main")
|
|
||||||
def index():
|
|
||||||
return render_template('admin/admin_log/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
# ==========================================================
|
|
||||||
# 登录日志
|
|
||||||
# ==========================================================
|
|
||||||
|
|
||||||
|
|
||||||
@admin_log.get('/loginLog')
|
|
||||||
@authorize("admin:log:main")
|
|
||||||
def login_log():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
log = AdminLog.query.filter_by(url='/admin/login').order_by(desc(AdminLog.create_time)).paginate(page=page,
|
|
||||||
per_page=limit,
|
|
||||||
error_out=False)
|
|
||||||
count = AdminLog.query.filter_by(url='/admin/login').count()
|
|
||||||
data = model_to_dicts(Schema=LogSchema, model=log.items)
|
|
||||||
|
|
||||||
return table_api(data=data, count=count)
|
|
||||||
|
|
||||||
|
|
||||||
# ==========================================================
|
|
||||||
# 操作日志
|
|
||||||
# ==========================================================
|
|
||||||
|
|
||||||
|
|
||||||
@admin_log.get('/operateLog')
|
|
||||||
@authorize("admin:log:main")
|
|
||||||
def operate_log():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
log = AdminLog.query.filter(
|
|
||||||
AdminLog.url != '/admin/login').order_by(
|
|
||||||
desc(AdminLog.create_time)).paginate(
|
|
||||||
page=page, per_page=limit, error_out=False)
|
|
||||||
count = AdminLog.query.filter(AdminLog.url != '/admin/login').count()
|
|
||||||
data = model_to_dicts(Schema=LogSchema, model=log.items)
|
|
||||||
return table_api(data=data, count=count)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
admin_curd = Blueprint('adminCurd', __name__, url_prefix='/admin/curd')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_curd.route('/')
|
|
||||||
def index():
|
|
||||||
return "功能开发中"
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify
|
|
||||||
|
|
||||||
from applications.common.utils.http import table_api, success_api, fail_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.models import DictType, DictData
|
|
||||||
from applications.common.admin import dict_curd
|
|
||||||
|
|
||||||
admin_dict = Blueprint('adminDict', __name__, url_prefix='/admin/dict')
|
|
||||||
|
|
||||||
|
|
||||||
# 数据字典
|
|
||||||
@admin_dict.get('/')
|
|
||||||
@authorize("admin:dict:main", log=True)
|
|
||||||
def main():
|
|
||||||
return render_template('admin/dict/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_dict.get('/dictType/data')
|
|
||||||
@authorize("admin:dict:main", log=True)
|
|
||||||
def dict_type_data():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
type_name = xss_escape(request.args.get('typeName', type=str))
|
|
||||||
data, count = dict_curd.get_dict_type(page=page, limit=limit, type_name=type_name)
|
|
||||||
return table_api(data=data,count=count)
|
|
||||||
|
|
||||||
|
|
||||||
@admin_dict.get('/dictType/add')
|
|
||||||
@authorize("admin:dict:add", log=True)
|
|
||||||
def dict_type_add():
|
|
||||||
return render_template('admin/dict/add.html')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_dict.post('/dictType/save')
|
|
||||||
@authorize("admin:dict:add", log=True)
|
|
||||||
def dict_type_save():
|
|
||||||
req_json = request.json
|
|
||||||
res = dict_curd.save_dict_type(req_json=req_json)
|
|
||||||
if res is None:
|
|
||||||
return fail_api(msg="增加失败")
|
|
||||||
return success_api(msg="增加成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典类型
|
|
||||||
@admin_dict.get('/dictType/edit')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_type_edit():
|
|
||||||
_id = request.args.get('dictTypeId', type=int)
|
|
||||||
dict_type = DictType.query.filter_by(id=_id).first()
|
|
||||||
return render_template('admin/dict/edit.html', dict_type=dict_type)
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典类型
|
|
||||||
@admin_dict.put('/dictType/update')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_type_update():
|
|
||||||
req_json = request.json
|
|
||||||
dict_curd.update_dict_type(req_json)
|
|
||||||
return success_api(msg="更新成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 启用字典
|
|
||||||
@admin_dict.put('/dictType/enable')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_type_enable():
|
|
||||||
_id = request.json.get('id')
|
|
||||||
if id:
|
|
||||||
res = dict_curd.enable_dict_type_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api("启动成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用字典
|
|
||||||
@admin_dict.put('/dictType/disable')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_type_dis_enable():
|
|
||||||
_id = request.json.get('id')
|
|
||||||
if id:
|
|
||||||
res = dict_curd.disable_dict_type_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api("禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 删除字典类型
|
|
||||||
@admin_dict.delete('/dictType/remove/<int:_id>')
|
|
||||||
@authorize("admin:dict:remove", log=True)
|
|
||||||
def dict_type_delete(_id):
|
|
||||||
res = dict_curd.delete_type_by_id(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
|
|
||||||
|
|
||||||
@admin_dict.get('/dictData/data')
|
|
||||||
@authorize("admin:dict:main", log=True)
|
|
||||||
def dict_code_data():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
type_code = xss_escape(request.args.get('typeCode', type=str))
|
|
||||||
data, count = dict_curd.get_dict_data(page=page, limit=limit, type_code=type_code)
|
|
||||||
return table_api(data=data,count=count)
|
|
||||||
|
|
||||||
|
|
||||||
# 增加字典数据
|
|
||||||
@admin_dict.get('/dictData/add')
|
|
||||||
@authorize("admin:dict:add", log=True)
|
|
||||||
def dict_data_add():
|
|
||||||
type_code = request.args.get('typeCode', type=str)
|
|
||||||
return render_template('admin/dict/data/add.html', type_code=type_code)
|
|
||||||
|
|
||||||
|
|
||||||
# 增加字典数据
|
|
||||||
@admin_dict.get('/dictData/save')
|
|
||||||
@authorize("admin:dict:add", log=True)
|
|
||||||
def dict_data_save():
|
|
||||||
req_json = request.json
|
|
||||||
res = dict_curd.save_dict_data(req_json=req_json)
|
|
||||||
if not res:
|
|
||||||
return jsonify(success=False, msg="增加失败")
|
|
||||||
return jsonify(success=True, msg="增加成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典数据
|
|
||||||
@admin_dict.get('/dictData/edit')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_data_edit():
|
|
||||||
_id = request.args.get('dataId', type=str)
|
|
||||||
dict_data = DictData.query.filter_by(id=_id).first()
|
|
||||||
return render_template('admin/dict/data/edit.html', dict_data=dict_data)
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑字典数据
|
|
||||||
@admin_dict.put('/dictData/update')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_data_update():
|
|
||||||
req_json = request.json
|
|
||||||
dict_curd.update_dict_data(req_json)
|
|
||||||
return success_api(msg="更新成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 启用字典数据
|
|
||||||
@admin_dict.put('/dictData/enable')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_data_enable():
|
|
||||||
_id = request.json.get('dataId')
|
|
||||||
if _id:
|
|
||||||
res = dict_curd.enable_dict_data_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="启动成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用字典数据
|
|
||||||
@admin_dict.put('/dictData/disable')
|
|
||||||
@authorize("admin:dict:edit", log=True)
|
|
||||||
def dict_data_disenable():
|
|
||||||
_id = request.json.get('dataId')
|
|
||||||
if _id:
|
|
||||||
res = dict_curd.disable_dict_data_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 删除字典类型
|
|
||||||
@admin_dict.delete('dictData/remove/<int:id>')
|
|
||||||
@authorize("admin:dict:remove", log=True)
|
|
||||||
def dict_data_delete(id):
|
|
||||||
res = dict_curd.delete_data_by_id(id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import os
|
|
||||||
from flask import Blueprint, request, render_template, jsonify, current_app
|
|
||||||
|
|
||||||
from applications.common.utils.http import fail_api, success_api, table_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.extensions import db
|
|
||||||
from applications.models import Photo
|
|
||||||
from applications.common.admin import file_curd
|
|
||||||
|
|
||||||
admin_file = Blueprint('adminFile', __name__, url_prefix='/admin/file')
|
|
||||||
|
|
||||||
|
|
||||||
# 图片管理
|
|
||||||
@admin_file.get('/')
|
|
||||||
@authorize("admin:file:main", log=True)
|
|
||||||
def index():
|
|
||||||
return render_template('admin/photo/photo.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 图片数据
|
|
||||||
@admin_file.get('/table')
|
|
||||||
@authorize("admin:file:main", log=True)
|
|
||||||
def table():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
data, count = file_curd.get_photo(page=page, limit=limit)
|
|
||||||
return table_api(data=data, count=count)
|
|
||||||
|
|
||||||
|
|
||||||
# 上传
|
|
||||||
@admin_file.get('/upload')
|
|
||||||
@authorize("admin:file:add", log=True)
|
|
||||||
def upload():
|
|
||||||
return render_template('admin/photo/photo_add.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 上传接口
|
|
||||||
@admin_file.post('/upload')
|
|
||||||
@authorize("admin:file:add", log=True)
|
|
||||||
def upload_api():
|
|
||||||
if 'file' in request.files:
|
|
||||||
photo = request.files['file']
|
|
||||||
mime = request.files['file'].content_type
|
|
||||||
file_url = file_curd.upload_one(photo=photo, mime=mime)
|
|
||||||
res = {
|
|
||||||
"msg": "上传成功",
|
|
||||||
"code": 0,
|
|
||||||
"success": True,
|
|
||||||
"data":
|
|
||||||
{"src": file_url}
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
return fail_api()
|
|
||||||
|
|
||||||
|
|
||||||
# 图片删除
|
|
||||||
@admin_file.route('/delete', methods=['GET', 'POST'])
|
|
||||||
@authorize("admin:file:delete", log=True)
|
|
||||||
def delete():
|
|
||||||
_id = request.form.get('id')
|
|
||||||
res = file_curd.delete_photo_by_id(_id)
|
|
||||||
if res:
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
else:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
|
|
||||||
|
|
||||||
# 图片批量删除
|
|
||||||
@admin_file.route('/batchRemove', methods=['GET', 'POST'])
|
|
||||||
@authorize("admin:file:delete", log=True)
|
|
||||||
def batch_remove():
|
|
||||||
ids = request.form.getlist('ids[]')
|
|
||||||
photo_name = Photo.query.filter(Photo.id.in_(ids)).all()
|
|
||||||
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
|
|
||||||
for p in photo_name:
|
|
||||||
os.remove(upload_url + '/' + p.name)
|
|
||||||
photo = Photo.query.filter(Photo.id.in_(ids)).delete(synchronize_session=False)
|
|
||||||
db.session.commit()
|
|
||||||
if photo:
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
else:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
from flask import Blueprint, render_template
|
|
||||||
from flask_login import login_required, current_user
|
|
||||||
|
|
||||||
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
|
|
||||||
|
|
||||||
|
|
||||||
# 首页
|
|
||||||
@admin_bp.get('/')
|
|
||||||
@login_required
|
|
||||||
def index():
|
|
||||||
user = current_user
|
|
||||||
return render_template('admin/index.html', user=user)
|
|
||||||
|
|
||||||
|
|
||||||
# 控制台页面
|
|
||||||
@admin_bp.get('/welcome')
|
|
||||||
@login_required
|
|
||||||
def welcome():
|
|
||||||
return render_template('admin/console/console.html')
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
import os
|
|
||||||
import platform
|
|
||||||
import re
|
|
||||||
from datetime import datetime
|
|
||||||
import time
|
|
||||||
import psutil
|
|
||||||
from flask import Blueprint, render_template, jsonify
|
|
||||||
from flask_marshmallow import Marshmallow
|
|
||||||
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
|
|
||||||
ma = Marshmallow()
|
|
||||||
admin_monitor_bp = Blueprint('adminMonitor', __name__, url_prefix='/admin/monitor')
|
|
||||||
|
|
||||||
|
|
||||||
# 系统监控
|
|
||||||
@admin_monitor_bp.get('/')
|
|
||||||
@authorize("admin:monitor:main", log=True)
|
|
||||||
def main():
|
|
||||||
# 主机名称
|
|
||||||
hostname = platform.node()
|
|
||||||
# 系统版本
|
|
||||||
system_version = platform.platform()
|
|
||||||
# python版本
|
|
||||||
python_version = platform.python_version()
|
|
||||||
# 逻辑cpu数量
|
|
||||||
cpu_count = psutil.cpu_count()
|
|
||||||
# cup使用率
|
|
||||||
cpus_percent = psutil.cpu_percent(interval=0.1)
|
|
||||||
# 内存
|
|
||||||
memory_information = psutil.virtual_memory()
|
|
||||||
# 内存使用率
|
|
||||||
memory_usage = memory_information.percent
|
|
||||||
memory_used = str(round(memory_information.used / 1024 / 1024))
|
|
||||||
memory_total = str(round(memory_information.total / 1024 / 1024))
|
|
||||||
memory_free = str(round(memory_information.free / 1024 / 1024))
|
|
||||||
# 磁盘信息
|
|
||||||
|
|
||||||
disk_partitions_list = []
|
|
||||||
# 判断是否在容器中
|
|
||||||
if not os.path.exists('/.dockerenv'):
|
|
||||||
disk_partitions = psutil.disk_partitions()
|
|
||||||
for i in disk_partitions:
|
|
||||||
a = psutil.disk_usage(i.device)
|
|
||||||
disk_partitions_dict = {
|
|
||||||
'device': i.device,
|
|
||||||
'fstype': i.fstype,
|
|
||||||
'total': str(round(a.total / 1024 / 1024)),
|
|
||||||
'used': str(round(a.used / 1024 / 1024)),
|
|
||||||
'free': str(round(a.free / 1024 / 1024)),
|
|
||||||
'percent': a.percent
|
|
||||||
}
|
|
||||||
disk_partitions_list.append(disk_partitions_dict)
|
|
||||||
|
|
||||||
# 开机时间
|
|
||||||
boot_time = datetime.fromtimestamp(psutil.boot_time()).replace(microsecond=0)
|
|
||||||
up_time = datetime.now().replace(microsecond=0) - boot_time
|
|
||||||
up_time_list = re.split(r':', str(up_time))
|
|
||||||
up_time_format = " {} 小时{} 分钟{} 秒".format(up_time_list[0], up_time_list[1], up_time_list[2])
|
|
||||||
|
|
||||||
# 当前时间
|
|
||||||
time_now = time.strftime('%H:%M:%S ', time.localtime(time.time()))
|
|
||||||
return render_template('admin/monitor.html',
|
|
||||||
hostname=hostname,
|
|
||||||
system_version=system_version,
|
|
||||||
python_version=python_version,
|
|
||||||
cpus_percent=cpus_percent,
|
|
||||||
memory_usage=memory_usage,
|
|
||||||
cpu_count=cpu_count,
|
|
||||||
memory_used=memory_used,
|
|
||||||
memory_total=memory_total,
|
|
||||||
memory_free=memory_free,
|
|
||||||
boot_time=boot_time,
|
|
||||||
up_time_format=up_time_format,
|
|
||||||
disk_partitions_list=disk_partitions_list,
|
|
||||||
time_now=time_now
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# 图表 api
|
|
||||||
@admin_monitor_bp.get('/polling')
|
|
||||||
@authorize("admin:monitor:main")
|
|
||||||
def ajax_polling():
|
|
||||||
# 获取cup使用率
|
|
||||||
cpus_percent = psutil.cpu_percent(interval=0.1)
|
|
||||||
# 获取内存使用率
|
|
||||||
memory_information = psutil.virtual_memory()
|
|
||||||
memory_usage = memory_information.percent
|
|
||||||
time_now = time.strftime('%H:%M:%S ', time.localtime(time.time()))
|
|
||||||
return jsonify(cups_percent=cpus_percent, memory_used=memory_usage, time_now=time_now)
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify
|
|
||||||
from applications.common.admin import power_curd
|
|
||||||
from applications.common.utils.http import success_api, fail_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
|
|
||||||
admin_power = Blueprint('adminPower', __name__, url_prefix='/admin/power')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_power.get('/')
|
|
||||||
@authorize("admin:power:main", log=True)
|
|
||||||
def index():
|
|
||||||
return render_template('admin/power/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_power.get('/data')
|
|
||||||
@authorize("admin:power:main", log=True)
|
|
||||||
def data():
|
|
||||||
power_data = power_curd.get_power_dict()
|
|
||||||
res = {
|
|
||||||
"data": power_data
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
@admin_power.get('/add')
|
|
||||||
@authorize("admin:power:add", log=True)
|
|
||||||
def add():
|
|
||||||
return render_template('admin/power/add.html')
|
|
||||||
|
|
||||||
|
|
||||||
@admin_power.get('/selectParent')
|
|
||||||
@authorize("admin:power:main", log=True)
|
|
||||||
def select_parent():
|
|
||||||
power_data = power_curd.select_parent()
|
|
||||||
res = {
|
|
||||||
"status": {"code": 200, "message": "默认"},
|
|
||||||
"data": power_data
|
|
||||||
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
# 增加
|
|
||||||
@admin_power.post('/save')
|
|
||||||
@authorize("admin:power:add", log=True)
|
|
||||||
def save():
|
|
||||||
req = request.json
|
|
||||||
power_curd.save_power(req)
|
|
||||||
return success_api(msg="成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 权限编辑
|
|
||||||
@admin_power.get('/edit/<int:_id>')
|
|
||||||
@authorize("admin:power:edit", log=True)
|
|
||||||
def edit(_id):
|
|
||||||
power = power_curd.get_power_by_id(_id)
|
|
||||||
icon = str(power.icon).split()
|
|
||||||
if len(icon) == 2:
|
|
||||||
icon = icon[1]
|
|
||||||
else:
|
|
||||||
icon = None
|
|
||||||
return render_template('admin/power/edit.html', power=power, icon=icon)
|
|
||||||
|
|
||||||
|
|
||||||
# 权限更新
|
|
||||||
@admin_power.put('/update')
|
|
||||||
@authorize("admin:power:edit", log=True)
|
|
||||||
def update():
|
|
||||||
res = power_curd.update_power(request.json)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="更新权限失败")
|
|
||||||
return success_api(msg="更新权限成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 启用权限
|
|
||||||
@admin_power.put('/enable')
|
|
||||||
@authorize("admin:power:edit", log=True)
|
|
||||||
def enable():
|
|
||||||
_id = request.json.get('powerId')
|
|
||||||
if id:
|
|
||||||
res = power_curd.enable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="启用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用权限
|
|
||||||
@admin_power.put('/disable')
|
|
||||||
@authorize("admin:power:edit", log=True)
|
|
||||||
def dis_enable():
|
|
||||||
_id = request.json.get('powerId')
|
|
||||||
if id:
|
|
||||||
res = power_curd.disable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 权限删除
|
|
||||||
@admin_power.delete('/remove/<int:_id>')
|
|
||||||
@authorize("admin:power:remove", log=True)
|
|
||||||
def remove(_id):
|
|
||||||
r = power_curd.remove_power(_id)
|
|
||||||
if r:
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
else:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除
|
|
||||||
@admin_power.delete('/batchRemove')
|
|
||||||
@authorize("admin:power:remove", log=True)
|
|
||||||
def batch_remove():
|
|
||||||
ids = request.form.getlist('ids[]')
|
|
||||||
power_curd.batch_remove(ids)
|
|
||||||
return success_api(msg="批量删除成功")
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify
|
|
||||||
from flask_login import login_required
|
|
||||||
from applications.common.admin import role_curd
|
|
||||||
from applications.common.utils.http import table_api, success_api, fail_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
|
|
||||||
admin_role = Blueprint('adminRole', __name__, url_prefix='/admin/role')
|
|
||||||
|
|
||||||
|
|
||||||
# 用户管理
|
|
||||||
@admin_role.get('/')
|
|
||||||
@authorize("admin:role:main", log=True)
|
|
||||||
def main():
|
|
||||||
return render_template('admin/role/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 表格数据
|
|
||||||
@admin_role.get('/data')
|
|
||||||
@authorize("admin:role:main", log=True)
|
|
||||||
def table():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
role_name = xss_escape(request.args.get('roleName', type=str))
|
|
||||||
role_code = xss_escape(request.args.get('roleCode', type=str))
|
|
||||||
filters = {}
|
|
||||||
if role_name:
|
|
||||||
filters["name"] = ('%' + role_name + '%')
|
|
||||||
if role_code:
|
|
||||||
filters["code"] = ('%' + role_code + '%')
|
|
||||||
data, count = role_curd.get_role_data_dict(page=page, limit=limit, filters=filters)
|
|
||||||
return table_api(data=data, count=count)
|
|
||||||
|
|
||||||
|
|
||||||
# 角色增加
|
|
||||||
@admin_role.get('/add')
|
|
||||||
@authorize("admin:role:add", log=True)
|
|
||||||
@login_required
|
|
||||||
def add():
|
|
||||||
return render_template('admin/role/add.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 角色增加
|
|
||||||
@admin_role.post('/save')
|
|
||||||
@authorize("admin:role:add", log=True)
|
|
||||||
def save():
|
|
||||||
req = request.json
|
|
||||||
role_curd.add_role(req=req)
|
|
||||||
return success_api(msg="成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 角色授权
|
|
||||||
@admin_role.get('/power/<int:_id>')
|
|
||||||
@authorize("admin:role:power", log=True)
|
|
||||||
def power(_id):
|
|
||||||
return render_template('admin/role/power.html', id=_id)
|
|
||||||
|
|
||||||
|
|
||||||
# 获取角色权限
|
|
||||||
@admin_role.get('/getRolePower/<int:id>')
|
|
||||||
@authorize("admin:role:main", log=True)
|
|
||||||
def get_role_power(id):
|
|
||||||
powers = role_curd.get_role_power(id)
|
|
||||||
res = {
|
|
||||||
"data": powers,
|
|
||||||
"status": {"code": 200, "message": "默认"}
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
# 保存角色权限
|
|
||||||
@admin_role.put('/saveRolePower')
|
|
||||||
@authorize("admin:role:edit", log=True)
|
|
||||||
def save_role_power():
|
|
||||||
req_form = request.form
|
|
||||||
power_ids = req_form.get("powerIds")
|
|
||||||
power_list = power_ids.split(',')
|
|
||||||
role_id = req_form.get("roleId")
|
|
||||||
role_curd.update_role_power(id=role_id, power_list=power_list)
|
|
||||||
return success_api(msg="授权成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 角色编辑
|
|
||||||
@admin_role.get('/edit/<int:_id>')
|
|
||||||
@authorize("admin:role:edit", log=True)
|
|
||||||
def edit(_id):
|
|
||||||
role = role_curd.get_role_by_id(_id)
|
|
||||||
return render_template('admin/role/edit.html', role=role)
|
|
||||||
|
|
||||||
|
|
||||||
# 更新角色
|
|
||||||
@admin_role.put('/update')
|
|
||||||
@authorize("admin:role:edit", log=True)
|
|
||||||
def update():
|
|
||||||
res = role_curd.update_role(request.json)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="更新角色失败")
|
|
||||||
return success_api(msg="更新角色成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 启用用户
|
|
||||||
@admin_role.put('/enable')
|
|
||||||
@authorize("admin:role:edit", log=True)
|
|
||||||
def enable():
|
|
||||||
id = request.json.get('roleId')
|
|
||||||
# print(id)
|
|
||||||
if id:
|
|
||||||
res = role_curd.enable_status(id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="启动成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用用户
|
|
||||||
@admin_role.put('/disable')
|
|
||||||
@authorize("admin:role:edit", log=True)
|
|
||||||
def dis_enable():
|
|
||||||
_id = request.json.get('roleId')
|
|
||||||
if _id:
|
|
||||||
res = role_curd.disable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 角色删除
|
|
||||||
@admin_role.delete('/remove/<int:_id>')
|
|
||||||
@authorize("admin:role:remove", log=True)
|
|
||||||
def remove(_id):
|
|
||||||
res = role_curd.remove_role(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="角色删除失败")
|
|
||||||
return success_api(msg="角色删除成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除
|
|
||||||
@admin_role.delete('/batchRemove')
|
|
||||||
@authorize("admin:role:remove", log=True)
|
|
||||||
@login_required
|
|
||||||
def batch_remove():
|
|
||||||
ids = request.form.getlist('ids[]')
|
|
||||||
role_curd.batch_remove(ids)
|
|
||||||
return success_api(msg="批量删除成功")
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, request
|
|
||||||
from flask_login import login_required, current_user
|
|
||||||
|
|
||||||
from applications.common.utils.http import table_api, fail_api, success_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.common.utils.validate import xss_escape
|
|
||||||
from applications.models import User
|
|
||||||
from applications.models import Role
|
|
||||||
from applications.common.admin import user_curd
|
|
||||||
|
|
||||||
admin_user = Blueprint('adminUser', __name__, url_prefix='/admin/user')
|
|
||||||
|
|
||||||
|
|
||||||
# 用户管理
|
|
||||||
@admin_user.get('/')
|
|
||||||
@authorize("admin:user:main", log=True)
|
|
||||||
def main():
|
|
||||||
return render_template('admin/user/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 用户分页查询
|
|
||||||
@admin_user.get('/data')
|
|
||||||
@authorize("admin:user:main", log=True)
|
|
||||||
def data():
|
|
||||||
page = request.args.get('page', type=int)
|
|
||||||
limit = request.args.get('limit', type=int)
|
|
||||||
real_name = xss_escape(request.args.get('realName', type=str))
|
|
||||||
username = xss_escape(request.args.get('username', type=str))
|
|
||||||
dept_id = request.args.get('deptId', type=int)
|
|
||||||
filters = {}
|
|
||||||
if real_name:
|
|
||||||
filters["realname"] = ('%' + real_name + '%')
|
|
||||||
if username:
|
|
||||||
filters["username"] = ('%' + username + '%')
|
|
||||||
user_data, count = user_curd.get_user_data_dict(page=page, limit=limit, filters=filters, deptId=dept_id)
|
|
||||||
return table_api(data=user_data, count=count)
|
|
||||||
|
|
||||||
|
|
||||||
# 用户增加
|
|
||||||
@admin_user.get('/add')
|
|
||||||
@authorize("admin:user:add", log=True)
|
|
||||||
def add():
|
|
||||||
roles = Role.query.all()
|
|
||||||
return render_template('admin/user/add.html', roles=roles)
|
|
||||||
|
|
||||||
|
|
||||||
@admin_user.post('/save')
|
|
||||||
@authorize("admin:user:add", log=True)
|
|
||||||
def save():
|
|
||||||
req_json = request.json
|
|
||||||
a = req_json.get("roleIds")
|
|
||||||
username = xss_escape(req_json.get('username'))
|
|
||||||
real_name = xss_escape(req_json.get('realName'))
|
|
||||||
password = xss_escape(req_json.get('password'))
|
|
||||||
role_ids = a.split(',')
|
|
||||||
|
|
||||||
if not username or not real_name or not password:
|
|
||||||
return fail_api(msg="账号姓名密码不得为空")
|
|
||||||
|
|
||||||
if user_curd.is_user_exists(username):
|
|
||||||
return fail_api(msg="用户已经存在")
|
|
||||||
|
|
||||||
_id = user_curd.add_user(username, real_name, password)
|
|
||||||
user_curd.add_user_role(_id, role_ids)
|
|
||||||
|
|
||||||
return success_api(msg="增加成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 删除用户
|
|
||||||
@admin_user.delete('/remove/<int:_id>')
|
|
||||||
@authorize("admin:user:remove", log=True)
|
|
||||||
def delete(_id):
|
|
||||||
res = user_curd.delete_by_id(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑用户
|
|
||||||
@admin_user.get('/edit/<int:_id>')
|
|
||||||
@authorize("admin:user:edit", log=True)
|
|
||||||
def edit(_id):
|
|
||||||
user = User.query.filter_by(id=_id).first()
|
|
||||||
roles = Role.query.all()
|
|
||||||
checked_roles = []
|
|
||||||
for r in user.role:
|
|
||||||
checked_roles.append(r.id)
|
|
||||||
return render_template('admin/user/edit.html', user=user, roles=roles, checked_roles=checked_roles)
|
|
||||||
|
|
||||||
|
|
||||||
# 编辑用户
|
|
||||||
@admin_user.put('/update')
|
|
||||||
@authorize("admin:user:edit", log=True)
|
|
||||||
def update():
|
|
||||||
req_json = request.json
|
|
||||||
a = xss_escape(req_json.get("roleIds"))
|
|
||||||
_id = xss_escape(req_json.get("userId"))
|
|
||||||
username = xss_escape(req_json.get('username'))
|
|
||||||
real_name = xss_escape(req_json.get('realName'))
|
|
||||||
dept_id = xss_escape(req_json.get('deptId'))
|
|
||||||
role_ids = a.split(',')
|
|
||||||
user_curd.update_user(id, username, real_name, dept_id)
|
|
||||||
user_curd.update_user_role(_id, role_ids)
|
|
||||||
return success_api(msg="更新成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 个人中心
|
|
||||||
@admin_user.get('/center')
|
|
||||||
@login_required
|
|
||||||
def center():
|
|
||||||
user_info = current_user
|
|
||||||
user_logs = user_curd.get_current_user_logs()
|
|
||||||
return render_template('admin/user/center.html', user_info=user_info, user_logs=user_logs)
|
|
||||||
|
|
||||||
|
|
||||||
# 修改头像
|
|
||||||
@admin_user.get('/profile')
|
|
||||||
@login_required
|
|
||||||
def profile():
|
|
||||||
return render_template('admin/user/profile.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 修改头像
|
|
||||||
@admin_user.put('/updateAvatar')
|
|
||||||
@login_required
|
|
||||||
def update_avatar():
|
|
||||||
url = request.json.get("avatar").get("src")
|
|
||||||
if not user_curd.update_avatar(url):
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="修改成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 修改当前用户信息
|
|
||||||
@admin_user.put('/updateInfo')
|
|
||||||
@login_required
|
|
||||||
def update_info():
|
|
||||||
res_json = request.json
|
|
||||||
if not user_curd.update_current_user_info(req_json=res_json):
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="更新成功")
|
|
||||||
|
|
||||||
|
|
||||||
# 修改当前用户密码
|
|
||||||
@admin_user.get('/editPassword')
|
|
||||||
@login_required
|
|
||||||
def edit_password():
|
|
||||||
return render_template('admin/user/edit_password.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 修改当前用户密码
|
|
||||||
@admin_user.put('/editPassword')
|
|
||||||
@login_required
|
|
||||||
def edit_password_put():
|
|
||||||
res_json = request.json
|
|
||||||
return user_curd.edit_password(res_json=res_json)
|
|
||||||
|
|
||||||
|
|
||||||
# 启用用户
|
|
||||||
@admin_user.put('/enable')
|
|
||||||
@authorize("admin:user:edit", log=True)
|
|
||||||
def enable():
|
|
||||||
_id = request.json.get('userId')
|
|
||||||
if _id:
|
|
||||||
res = user_curd.enable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="启动成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用用户
|
|
||||||
@admin_user.put('/disable')
|
|
||||||
@authorize("admin:user:edit", log=True)
|
|
||||||
def dis_enable():
|
|
||||||
_id = request.json.get('userId')
|
|
||||||
if _id:
|
|
||||||
res = user_curd.disable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 批量删除
|
|
||||||
@admin_user.delete('/batchRemove')
|
|
||||||
@authorize("admin:user:remove", log=True)
|
|
||||||
def batch_remove():
|
|
||||||
ids = request.form.getlist('ids[]')
|
|
||||||
user_curd.batch_remove(ids)
|
|
||||||
return success_api(msg="批量删除成功")
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
from flask import render_template, request
|
||||||
|
|
||||||
|
from models import DepartmentModel
|
||||||
|
from common.utils.rights import permission_required, view_logging_required
|
||||||
|
from applications.view import index_bp
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/dept')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:dept:main")
|
||||||
|
def dept_index():
|
||||||
|
return render_template('admin/department/dept.html')
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/dept/add')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:dept:add")
|
||||||
|
def add():
|
||||||
|
return render_template('admin/department/dept_add.html')
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/dept/edit')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:dept:edit")
|
||||||
|
def edit():
|
||||||
|
dept_id = request.args.get("deptId", type=int)
|
||||||
|
dept = DepartmentModel.query.get(dept_id)
|
||||||
|
return render_template('admin/department/dept_edit.html', dept=dept)
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify
|
|
||||||
from marshmallow import INCLUDE
|
|
||||||
|
|
||||||
from applications.common.utils.http import success_api, fail_api
|
|
||||||
from applications.common.utils.rights import authorize
|
|
||||||
from applications.common.utils.validate import check_data
|
|
||||||
from applications.models import DeptSchema
|
|
||||||
from applications.common.admin import dept_curd as dept_curd
|
|
||||||
|
|
||||||
dept_bp = Blueprint('dept', __name__, url_prefix='/dept')
|
|
||||||
|
|
||||||
|
|
||||||
def register_dept_views(app):
|
|
||||||
app.register_blueprint(dept_bp)
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.get('/')
|
|
||||||
@authorize("admin:dept:main", log=True)
|
|
||||||
def main():
|
|
||||||
return render_template('admin/dept/main.html')
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.get('/data')
|
|
||||||
@authorize("admin:dept:main", log=True)
|
|
||||||
def data():
|
|
||||||
power_data = dept_curd.get_dept_dict()
|
|
||||||
res = {
|
|
||||||
"data": power_data
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.get('/add')
|
|
||||||
@authorize("admin:dept:add", log=True)
|
|
||||||
def add():
|
|
||||||
return render_template('admin/dept/add.html')
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.get('/tree')
|
|
||||||
@authorize("admin:dept:main", log=True)
|
|
||||||
def tree():
|
|
||||||
power_data = dept_curd.get_dept_dict()
|
|
||||||
res = {
|
|
||||||
"status": {"code": 200, "message": "默认"},
|
|
||||||
"data": power_data
|
|
||||||
|
|
||||||
}
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.post('/save')
|
|
||||||
@authorize("admin:dept:add", log=True)
|
|
||||||
def save():
|
|
||||||
req = request.json
|
|
||||||
check_data(DeptSchema(unknown=INCLUDE), req)
|
|
||||||
dept_curd.save_dept(req)
|
|
||||||
return success_api(msg="成功")
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.get('/edit')
|
|
||||||
@authorize("admin:dept:edit", log=True)
|
|
||||||
def edit():
|
|
||||||
_id = request.args.get("deptId")
|
|
||||||
dept = dept_curd.get_dept_by_id(_id)
|
|
||||||
return render_template('admin/dept/edit.html', dept=dept)
|
|
||||||
|
|
||||||
|
|
||||||
# 启用
|
|
||||||
@dept_bp.put('/enable')
|
|
||||||
@authorize("admin:dept:edit", log=True)
|
|
||||||
def enable():
|
|
||||||
_id = request.json.get('deptId')
|
|
||||||
if id:
|
|
||||||
res = dept_curd.enable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="启用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 禁用
|
|
||||||
@dept_bp.put('/disable')
|
|
||||||
@authorize("admin:dept:edit", log=True)
|
|
||||||
def dis_enable():
|
|
||||||
_id = request.json.get('deptId')
|
|
||||||
if id:
|
|
||||||
res = dept_curd.disable_status(_id)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="出错啦")
|
|
||||||
return success_api(msg="禁用成功")
|
|
||||||
return fail_api(msg="数据错误")
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.put('/update')
|
|
||||||
@authorize("admin:dept:edit", log=True)
|
|
||||||
def update():
|
|
||||||
req = request.json
|
|
||||||
check_data(DeptSchema(unknown=INCLUDE), req)
|
|
||||||
res = dept_curd.update_dept(req)
|
|
||||||
if not res:
|
|
||||||
return fail_api(msg="更新失败")
|
|
||||||
return success_api(msg="更新成功")
|
|
||||||
|
|
||||||
|
|
||||||
@dept_bp.delete('/remove/<int:_id>')
|
|
||||||
@authorize("admin:dept:remove", log=True)
|
|
||||||
def remove(_id):
|
|
||||||
res = dept_curd.remove_dept(_id)
|
|
||||||
if res:
|
|
||||||
return success_api(msg="删除成功")
|
|
||||||
else:
|
|
||||||
return fail_api(msg="删除失败")
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from flask import render_template
|
||||||
|
|
||||||
|
from applications.view import index_bp
|
||||||
|
from common.utils.rights import view_logging_required, permission_required
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/file')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:file:main")
|
||||||
|
def file_index():
|
||||||
|
return render_template('admin/file/photo.html')
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/file/photo/add')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:file:main")
|
||||||
|
def file_photo_add():
|
||||||
|
return render_template('admin/file/photo_add.html')
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
from flask import render_template
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
|
index_bp = Blueprint('index', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template('index/index.html')
|
||||||
|
|
||||||
|
|
||||||
|
# 首页
|
||||||
|
@index_bp.get('/admin/')
|
||||||
|
@login_required
|
||||||
|
def admin_index():
|
||||||
|
return render_template('index/admin_index.html', user=current_user)
|
||||||
|
|
||||||
|
|
||||||
|
# 控制台页面
|
||||||
|
@index_bp.get('/admin/welcome')
|
||||||
|
@login_required
|
||||||
|
def welcome():
|
||||||
|
return render_template('index/welcome.html')
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
index_bp = Blueprint('Index', __name__, url_prefix='/')
|
|
||||||
|
|
||||||
from . import index
|
|
||||||
|
|
||||||
|
|
||||||
def register_index_views(app):
|
|
||||||
"""
|
|
||||||
初始化蓝图
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
app.register_blueprint(index_bp)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from flask import render_template
|
|
||||||
|
|
||||||
from . import index_bp
|
|
||||||
|
|
||||||
|
|
||||||
@index_bp.route('/')
|
|
||||||
def index():
|
|
||||||
return render_template('index/index.html')
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
from flask import Blueprint, request, render_template
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
from common.utils.http import table_api
|
||||||
|
from common.utils.rights import permission_required
|
||||||
|
from models import LogModel
|
||||||
|
|
||||||
|
logs_bp = Blueprint('logs', __name__, url_prefix='/logs')
|
||||||
|
|
||||||
|
|
||||||
|
@logs_bp.get('/')
|
||||||
|
@permission_required("admin:log:main")
|
||||||
|
def index():
|
||||||
|
return render_template('admin/logs_temp/main.html')
|
||||||
|
|
||||||
|
|
||||||
|
@logs_bp.get('/login_log')
|
||||||
|
@permission_required("admin:log:main")
|
||||||
|
def login_log():
|
||||||
|
page = request.args.get('page', type=int)
|
||||||
|
limit = request.args.get('limit', type=int)
|
||||||
|
log_paginate = LogModel.query.filter_by(
|
||||||
|
url='/api/v1/passport/login').order_by(
|
||||||
|
desc(LogModel.create_at)).paginate(
|
||||||
|
page=page, per_page=limit, error_out=False)
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
'id': item.id,
|
||||||
|
'method': item.method,
|
||||||
|
'uid': item.uid,
|
||||||
|
'url': item.url,
|
||||||
|
'desc': item.desc,
|
||||||
|
'ip': item.ip,
|
||||||
|
'success': item.success,
|
||||||
|
'user_agent': item.user_agent,
|
||||||
|
'create_at': item.create_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
} for item in log_paginate.items
|
||||||
|
]
|
||||||
|
|
||||||
|
return table_api(result={'items': data,
|
||||||
|
'total': log_paginate.total, },
|
||||||
|
code=0)
|
||||||
|
|
||||||
|
|
||||||
|
@logs_bp.get('/access_log')
|
||||||
|
@permission_required("admin:log:main")
|
||||||
|
def operate_log():
|
||||||
|
page = request.args.get('page', type=int)
|
||||||
|
limit = request.args.get('limit', type=int)
|
||||||
|
log_paginate = LogModel.query.filter(
|
||||||
|
LogModel.url != '/api/v1/passport/login').order_by(
|
||||||
|
desc(LogModel.create_at)).paginate(
|
||||||
|
page=page, per_page=limit, error_out=False)
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
'id': item.id,
|
||||||
|
'method': item.method,
|
||||||
|
'uid': item.uid,
|
||||||
|
'url': item.url,
|
||||||
|
'desc': item.desc,
|
||||||
|
'ip': item.ip,
|
||||||
|
'success': item.success,
|
||||||
|
'user_agent': item.user_agent,
|
||||||
|
'create_at': item.create_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
} for item in log_paginate.items
|
||||||
|
]
|
||||||
|
return table_api(result={'items': data,
|
||||||
|
'total': log_paginate.total, },
|
||||||
|
code=0)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
from flask import session, redirect, render_template, url_for
|
||||||
|
from flask_login import login_required, logout_user, current_user
|
||||||
|
|
||||||
|
from common.gen_captcha import get_captcha_image
|
||||||
|
from common.utils.http import success_api
|
||||||
|
|
||||||
|
# 获取验证码
|
||||||
|
from applications.view import index_bp
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/passport/getCaptcha')
|
||||||
|
def get_captcha():
|
||||||
|
resp, code = get_captcha_image()
|
||||||
|
session["code"] = code
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
# 退出登录
|
||||||
|
@index_bp.post('/passport/logout')
|
||||||
|
@login_required
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
session.pop('permissions')
|
||||||
|
return success_api(message="注销成功")
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/passport/login')
|
||||||
|
def login():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('admin.index'))
|
||||||
|
# TODO 分离视图操作 最终实现接口登录与视图登录两套逻辑
|
||||||
|
return render_template('index/login.html')
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
from flask import Blueprint, session, redirect, url_for, render_template, request
|
|
||||||
from flask_login import current_user, login_user, login_required, logout_user
|
|
||||||
|
|
||||||
from applications.common.admin import index_curd
|
|
||||||
from applications.common.admin_log import login_log
|
|
||||||
from applications.common.utils.http import fail_api, success_api
|
|
||||||
from applications.models import User
|
|
||||||
|
|
||||||
passport_bp = Blueprint('passport', __name__, url_prefix='/passport')
|
|
||||||
|
|
||||||
|
|
||||||
def register_passport_views(app):
|
|
||||||
app.register_blueprint(passport_bp)
|
|
||||||
|
|
||||||
|
|
||||||
# 获取验证码
|
|
||||||
@passport_bp.get('/getCaptcha')
|
|
||||||
def get_captcha():
|
|
||||||
resp, code = index_curd.get_captcha()
|
|
||||||
session["code"] = code
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
# 登录
|
|
||||||
@passport_bp.get('/login')
|
|
||||||
def login():
|
|
||||||
if current_user.is_authenticated:
|
|
||||||
return redirect(url_for('admin.index'))
|
|
||||||
return render_template('admin/login.html')
|
|
||||||
|
|
||||||
|
|
||||||
# 登录
|
|
||||||
@passport_bp.post('/login')
|
|
||||||
def login_post():
|
|
||||||
req = request.form
|
|
||||||
username = req.get('username')
|
|
||||||
password = req.get('password')
|
|
||||||
code = req.get('captcha')
|
|
||||||
|
|
||||||
if not username or not password or not code:
|
|
||||||
return fail_api(msg="用户名或密码没有输入")
|
|
||||||
s_code = session.get("code", None)
|
|
||||||
|
|
||||||
if not all([code, s_code]):
|
|
||||||
return fail_api(msg="参数错误")
|
|
||||||
|
|
||||||
if code != s_code:
|
|
||||||
return fail_api(msg="验证码错误")
|
|
||||||
user = User.query.filter_by(username=username).first()
|
|
||||||
|
|
||||||
if user is None:
|
|
||||||
return fail_api(msg="不存在的用户")
|
|
||||||
|
|
||||||
if user.enable is 0:
|
|
||||||
return fail_api(msg="用户被暂停使用")
|
|
||||||
|
|
||||||
if username == user.username and user.validate_password(password):
|
|
||||||
# 登录
|
|
||||||
login_user(user)
|
|
||||||
# 记录登录日志
|
|
||||||
login_log(request, uid=user.id, is_access=True)
|
|
||||||
# 存入权限
|
|
||||||
index_curd.add_auth_session()
|
|
||||||
return success_api(msg="登录成功")
|
|
||||||
login_log(request, uid=user.id, is_access=False)
|
|
||||||
return fail_api(msg="用户名或密码错误")
|
|
||||||
|
|
||||||
|
|
||||||
# 退出登录
|
|
||||||
@passport_bp.post('/logout')
|
|
||||||
@login_required
|
|
||||||
def logout():
|
|
||||||
logout_user()
|
|
||||||
session.pop('permissions')
|
|
||||||
return success_api(msg="注销成功")
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
from flask import render_template
|
||||||
|
|
||||||
|
from common.utils.rights import permission_required, view_logging_required
|
||||||
|
from models import RightModel
|
||||||
|
from applications.view import index_bp
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/rights/')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:power:main")
|
||||||
|
def rights_index():
|
||||||
|
return render_template('admin/rights/rights.html')
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/rights/power/<int:power_id>')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:power:edit")
|
||||||
|
def rights_edit(power_id):
|
||||||
|
power = RightModel.query.filter_by(id=power_id).first()
|
||||||
|
icon = str(power.icon).split()
|
||||||
|
if len(icon) == 2:
|
||||||
|
icon = icon[1]
|
||||||
|
else:
|
||||||
|
icon = None
|
||||||
|
return render_template('admin/rights/rights_edit.html', power=power, icon=icon)
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/rights/add')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:power:main")
|
||||||
|
def rights_add():
|
||||||
|
return render_template('admin/rights/rights_add.html')
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from flask import Blueprint, Flask
|
|
||||||
|
|
||||||
rights_bp = Blueprint('rights', __name__, url_prefix='/rights')
|
|
||||||
|
|
||||||
from . import routes
|
|
||||||
|
|
||||||
|
|
||||||
def register_rights_view(app: Flask):
|
|
||||||
app.register_blueprint(rights_bp)
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# 渲染配置
|
|
||||||
from flask import jsonify
|
|
||||||
from flask_login import login_required
|
|
||||||
|
|
||||||
from . import rights_bp
|
|
||||||
from ...common.admin import index_curd
|
|
||||||
|
|
||||||
|
|
||||||
@rights_bp.get('/configs')
|
|
||||||
@login_required
|
|
||||||
def configs():
|
|
||||||
return index_curd.get_render_config()
|
|
||||||
|
|
||||||
|
|
||||||
# 菜单
|
|
||||||
@rights_bp.get('/menu')
|
|
||||||
@login_required
|
|
||||||
def menu():
|
|
||||||
menu_tree = index_curd.make_menu_tree()
|
|
||||||
return jsonify(menu_tree)
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
from flask import Blueprint, render_template
|
||||||
|
|
||||||
|
from common.utils.rights import permission_required, view_logging_required
|
||||||
|
|
||||||
|
from models import RoleModel
|
||||||
|
|
||||||
|
role_bp = Blueprint('role', __name__, url_prefix='/admin/role')
|
||||||
|
|
||||||
|
|
||||||
|
# 角色而管理
|
||||||
|
@role_bp.get('/')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:role:main")
|
||||||
|
def main():
|
||||||
|
return render_template('admin/roles/roles.html')
|
||||||
|
|
||||||
|
|
||||||
|
# 角色授权操作
|
||||||
|
@role_bp.get('/power/<int:role_id>')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:role:power")
|
||||||
|
def power(role_id):
|
||||||
|
return render_template('admin/roles/roles_power.html', role_id=role_id)
|
||||||
|
|
||||||
|
|
||||||
|
# 角色编辑
|
||||||
|
@role_bp.get('/edit/<int:role_id>')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:role:edit")
|
||||||
|
def role_editor(role_id):
|
||||||
|
role = RoleModel.query.filter_by(id=role_id).first()
|
||||||
|
return render_template('admin/roles/roles_edit.html', role=role)
|
||||||
|
|
||||||
|
|
||||||
|
@role_bp.get('/add')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:role:edit")
|
||||||
|
def role_add():
|
||||||
|
return render_template('admin/roles/roles_add.html')
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
from flask import render_template
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
from common.utils.rights import permission_required, view_logging_required
|
||||||
|
from models import LogModel, RoleModel, UserModel
|
||||||
|
from . import index_bp
|
||||||
|
|
||||||
|
|
||||||
|
# 用户增加
|
||||||
|
@index_bp.get('/users/')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:user:main")
|
||||||
|
def users_main():
|
||||||
|
return render_template('admin/users/users.html')
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/users/add')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:user:add")
|
||||||
|
def users_add_view():
|
||||||
|
roles = RoleModel.query.all()
|
||||||
|
return render_template('admin/users/users_add.html', roles=roles)
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/users/<user_id>')
|
||||||
|
@view_logging_required
|
||||||
|
@permission_required("admin:user:edit")
|
||||||
|
def users_user_id_view(user_id):
|
||||||
|
# 获取编辑用户信息
|
||||||
|
user = UserModel.query.filter_by(id=user_id).first()
|
||||||
|
roles = RoleModel.query.all()
|
||||||
|
checked_roles = []
|
||||||
|
for r in user.role:
|
||||||
|
checked_roles.append(r.id)
|
||||||
|
return render_template('admin/users/users_edit.html', user=user, roles=roles, checked_roles=checked_roles)
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/users/center')
|
||||||
|
@login_required
|
||||||
|
def users_center():
|
||||||
|
user_logs = LogModel.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||||
|
desc(LogModel.create_at)).limit(10)
|
||||||
|
return render_template('admin/users/profile.html', user_info=current_user, user_logs=user_logs)
|
||||||
|
|
||||||
|
|
||||||
|
@index_bp.get('/users/avatar')
|
||||||
|
def users_avatar_view():
|
||||||
|
return render_template('admin/users/profile_avatar.html')
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user