@@ -0,0 +1,17 @@
|
||||
# MySql配置信息
|
||||
MYSQL_HOST=127.0.0.1
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DATABASE=PearAdminFlask
|
||||
MYSQL_USERNAME=root
|
||||
MYSQL_PASSWORD=123456
|
||||
|
||||
# Redis 配置
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
|
||||
# 密钥配置
|
||||
SECRET_KEY='pear-admin-flask2'
|
||||
|
||||
FLASK_ENV=development
|
||||
FLASK_RUN_HOST=0.0.0.0
|
||||
FLASK_APP='applications:create_app("development")'
|
||||
|
||||
+7
-1
@@ -115,4 +115,10 @@ dmypy.json
|
||||
.pyre/
|
||||
|
||||
#ide
|
||||
.idea/
|
||||
.idea/
|
||||
|
||||
# 数据库文件
|
||||
*.db
|
||||
#上传到本地的图片文件
|
||||
*upload*
|
||||
migrations/
|
||||
@@ -30,17 +30,23 @@
|
||||
</div>
|
||||
|
||||
#### 项目简介
|
||||
>Pear Admin Flask 基于 Flask 的后台管理系统,拥抱应用广泛的python语言,通过使用本系统,即可快速构建你的功能业务
|
||||
>
|
||||
>项目旨在为python开发者提供一个后台管理系统的模板,成为您构建信息管理系统,物联网后台....等等应用时灵活,简单的工具
|
||||
>
|
||||
>各位Python爱好者多多指教
|
||||
Pear Admin Flask 基于 Flask 生态的后台管理系统,该项目旨在为 python 开发者提供一个快速开发前后端半分离的后台管理系统的模板
|
||||
|
||||
Pear Admin Flask 分为 Common / Simple 两个版本:
|
||||
在使用本项目之前最好掌握以下知识点
|
||||
|
||||
[** Common 通用版本 **](https://gitee.com/pear-admin/pear-admin-flask/tree/master/)
|
||||
+ html、css、JavaScript
|
||||
+ jQuery
|
||||
+ layui
|
||||
+ flask
|
||||
+ flask-login
|
||||
+ flask-sqlalchemy
|
||||
+ flask-restful
|
||||
|
||||
[** Simple 简洁版本 **](https://gitee.com/pear-admin/pear-admin-flask/tree/simple/)
|
||||
|
||||
Pear Admin Flask 分为 Common / Simple 两个版本:
|
||||
|
||||
[Common 通用版本](https://gitee.com/pear-admin/pear-admin-flask/tree/master/)
|
||||
[Simple 简洁版本](https://gitee.com/pear-admin/pear-admin-flask/tree/simple/)
|
||||
|
||||
#### 内置功能
|
||||
|
||||
@@ -49,9 +55,7 @@ Pear Admin Flask 分为 Common / Simple 两个版本:
|
||||
- [x] 角色管理:角色菜单权限分配。
|
||||
- [x] 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||
- [x] 登录日志:系统登录日志记录查询包含登录异常。
|
||||
- [x] 服务监控:监视当前系统CPU、内存、磁盘、python版本,运行时长等相关信息。
|
||||
- [x] 文件上传: 图片上传示例
|
||||
- [ ] 代码生成: 构想中....
|
||||
- [x] 文件上传: 图片上传示例
|
||||
|
||||
#### 项目结构
|
||||
|
||||
@@ -73,62 +77,46 @@ Pear Admin Flask
|
||||
├─requirement # 依赖文件
|
||||
├─test # 测试文件夹(占坑)
|
||||
└─.env # 项目的配置文件
|
||||
|
||||
```
|
||||
|
||||
#### 项目启动
|
||||
|
||||
|
||||
#### 项目安装
|
||||
|
||||
##### 1. 下载源码
|
||||
```bash
|
||||
# 下 载
|
||||
git clone https://gitee.com/pear-admin/pear-admin-flask
|
||||
|
||||
# 安 装
|
||||
pip install -r requirement\requirement-dev.txt
|
||||
|
||||
# 配 置
|
||||
.env
|
||||
|
||||
# 切换分支
|
||||
git checkout mini
|
||||
```
|
||||
|
||||
#### 修改配置
|
||||
|
||||
```python
|
||||
# 主 机
|
||||
HOST = '127.0.0.1'
|
||||
|
||||
# 端 口
|
||||
PORT = '3306'
|
||||
|
||||
# 数 据 库
|
||||
DATABASE = 'PearAdminFlask'
|
||||
|
||||
# 账 户
|
||||
USERNAME = 'root'
|
||||
|
||||
# 密 码
|
||||
PASSWORD = 'root'
|
||||
|
||||
```
|
||||
|
||||
#### Venv 安装
|
||||
|
||||
##### 2. 安装依赖
|
||||
```bash
|
||||
# 创建虚拟环境
|
||||
python -m venv venv
|
||||
|
||||
# 然后使虚拟环境生效(windows,Linux自行解决)
|
||||
venv\Scripts\activate
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirement\requirement-dev.txt
|
||||
```
|
||||
|
||||
#### 运行项目
|
||||
|
||||
##### 3. 数据迁移
|
||||
默认的使用 `sqlite3` 作为开发环境的数据库进行演示,如果需要二次开发,建议改成 `mysql` 。
|
||||
```bash
|
||||
# 初 始 化 数 据 库
|
||||
python test\init_databases.py
|
||||
flask db init
|
||||
flask db migrate -m '数据初始化'
|
||||
flask db upgrade
|
||||
|
||||
flask init-db
|
||||
```
|
||||
|
||||
执行 flask run 命令启动项目
|
||||
|
||||
##### 4. 其他事项
|
||||
|
||||
如果需要在开发环境使用 mysql 作为数据库,请查看 `applications/configs/config.py` 文件里面的相关配置文件
|
||||
|
||||
如果需要修改数据的配置信息,请在 `.flaskenv` 里面调整即可
|
||||
|
||||
#### 预览项目
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
from applications import create_app
|
||||
|
||||
app = create_app()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -30,10 +30,29 @@ def create_app(config_name=None):
|
||||
configure_uploads(app, photos)
|
||||
|
||||
logo()
|
||||
|
||||
register_shell(app)
|
||||
return app
|
||||
|
||||
|
||||
def register_shell(app: Flask):
|
||||
@app.cli.command()
|
||||
def create():
|
||||
"""测试关系"""
|
||||
from .extensions import db
|
||||
from .models import Power, User
|
||||
from .models import PowerSchema
|
||||
power_schema = PowerSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
|
||||
user = User.query.get(1)
|
||||
power_list = []
|
||||
for role in user.role:
|
||||
if role.enable:
|
||||
for power in role.power:
|
||||
# 权限被启用
|
||||
if power.enable and power:
|
||||
power_list.append(power)
|
||||
power_dict = sorted(power_list, key=lambda i: i['sort'])
|
||||
|
||||
|
||||
def logo():
|
||||
print('''
|
||||
_____ _ _ ______ _ _
|
||||
|
||||
@@ -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,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()
|
||||
@@ -0,0 +1,76 @@
|
||||
from flask_restful import fields
|
||||
|
||||
power_fields = {
|
||||
'powerId': fields.String(attribute="id"),
|
||||
'powerName': fields.String(attribute="name"),
|
||||
'powerType': fields.String(attribute="type"),
|
||||
'powerUrl': fields.String(attribute="url"),
|
||||
'openType': fields.String(attribute="open_type"),
|
||||
'parentId': fields.String(attribute="parent_id"),
|
||||
'icon': fields.String,
|
||||
'sort': fields.Integer,
|
||||
'create_time': fields.DateTime,
|
||||
'update_time': fields.DateTime,
|
||||
'enable': fields.Integer,
|
||||
}
|
||||
|
||||
power2_fields = {
|
||||
'id': fields.Integer,
|
||||
'title': fields.String(attribute="name"),
|
||||
'type': fields.String,
|
||||
'code': fields.String,
|
||||
'href': fields.String(attribute="url"),
|
||||
'openType': fields.String(attribute="open_type"),
|
||||
'parent_id': fields.Integer,
|
||||
'icon': fields.String,
|
||||
'sort': fields.Integer,
|
||||
'create_time': fields.DateTime,
|
||||
'update_time': fields.DateTime,
|
||||
'enable': fields.Integer,
|
||||
}
|
||||
|
||||
role_fields = {
|
||||
'id': fields.Integer,
|
||||
'roleName': fields.String(attribute="name"),
|
||||
'roleCode': fields.String(attribute="code"),
|
||||
'enable': fields.String,
|
||||
'remark': fields.String,
|
||||
'details': fields.String,
|
||||
'sort': fields.Integer,
|
||||
'create_at': fields.DateTime,
|
||||
'update_at': fields.DateTime,
|
||||
}
|
||||
|
||||
log_fields = {
|
||||
'id': fields.Integer,
|
||||
'method': fields.String,
|
||||
'uid': fields.String,
|
||||
'url': fields.String,
|
||||
'desc': fields.String,
|
||||
'ip': fields.String,
|
||||
'user_agent': fields.String,
|
||||
'success': fields.Boolean,
|
||||
'create_time': fields.DateTime,
|
||||
}
|
||||
|
||||
dept_fields = {
|
||||
'deptId': fields.Integer(attribute="id"),
|
||||
'parentId': fields.Integer(attribute="parent_id"),
|
||||
'deptName': fields.String(attribute="dept_name"),
|
||||
'leader': fields.String,
|
||||
'phone': fields.String,
|
||||
'email': fields.String,
|
||||
'address': fields.String,
|
||||
'status': fields.Integer,
|
||||
'sort': fields.Integer,
|
||||
}
|
||||
|
||||
photo_fields = {
|
||||
'id': fields.Integer,
|
||||
'name': fields.String,
|
||||
'href': fields.String,
|
||||
'mime': fields.String,
|
||||
'size': fields.String,
|
||||
'ext': fields.String,
|
||||
'create_time': fields.DateTime,
|
||||
}
|
||||
@@ -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
|
||||
@@ -9,7 +9,7 @@ def authorize(power: str, log: bool = False):
|
||||
@login_required
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not power in session.get('permissions'):
|
||||
if power not in session.get('permissions'):
|
||||
if log:
|
||||
admin_log(request=request, is_access=False)
|
||||
if request.method == 'GET':
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
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():
|
||||
|
||||
@@ -31,9 +31,12 @@ class TestingConfig(BaseConfig):
|
||||
|
||||
class DevelopmentConfig(BaseConfig):
|
||||
""" 开发配置 """
|
||||
SQLALCHEMY_DATABASE_URI = r'sqlite:///../sql_pear_admin.db'
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||
SQLALCHEMY_ECHO = False
|
||||
|
||||
UPLOADED_PHOTOS_DEST = os.path.join(os.path.dirname(os.path.abspath(__name__)), 'applications', 'static', 'upload')
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
"""生成环境配置"""
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
from flask import Flask
|
||||
|
||||
from .init_sqlalchemy import db, ma, init_databases
|
||||
from .init_databases import register_script
|
||||
from .init_sqlalchemy import db, init_databases
|
||||
from .init_login import init_login_manager
|
||||
from .init_debug_tool import init_debug_tool
|
||||
from .init_template_directives import init_template_directives
|
||||
from .init_error_views import init_error_views
|
||||
|
||||
|
||||
def init_plugs(app: Flask) -> None:
|
||||
# init_debug_tool(app)
|
||||
init_login_manager(app)
|
||||
init_databases(app)
|
||||
init_template_directives(app)
|
||||
init_error_views(app)
|
||||
register_script(app)
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
from flask import Flask
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
date_str = re.compile('\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$')
|
||||
|
||||
|
||||
def add_data(fields, data_list, obj):
|
||||
from applications.extensions import db
|
||||
|
||||
for _data in data_list:
|
||||
dept = obj()
|
||||
for key, value in dict(zip(fields, _data)).items():
|
||||
|
||||
if isinstance(value, str) and date_str.match(value):
|
||||
value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
setattr(dept, key, value)
|
||||
db.session.add(dept)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def create_dept_data():
|
||||
"""创建化部门数据"""
|
||||
from applications.models import Dept
|
||||
_data_list = [
|
||||
(1, 0, '总公司', 1, '就眠仪式', '12312345679', '123qq.com', 1, None, '这是总公司', None, '2021-06-01 17:23:20'),
|
||||
(4, 1, '济南分公司', 2, '就眠仪式', '12312345678', '1234qq.com', 1, None, '这是济南', '2021-06-01 17:24:33',
|
||||
'2021-06-01 17:25:19'),
|
||||
(5, 1, '唐山分公司', 4, 'mkg', '12312345678', '123@qq.com', 1, None, '这是唐山', '2021-06-01 17:25:15',
|
||||
'2021-06-01 17:25:20'),
|
||||
(7, 4, '济南分公司开发部', 5, '就眠仪式', '12312345678', '123@qq.com', 1, None, '测试', '2021-06-01 17:27:39',
|
||||
'2021-06-01 17:27:39'),
|
||||
(8, 5, '唐山测试部', 6, 'mkg', '12312345678', '123@qq.com', 1, None, '测试部', '2021-06-01 17:28:27',
|
||||
'2021-06-01 17:28:27'),
|
||||
]
|
||||
_fields = ['id', 'parent_id', 'dept_name', 'sort', 'leader', 'phone', 'email', 'status', 'remark', 'address',
|
||||
'create_at', 'update_at']
|
||||
|
||||
_data_list = [item for item in _data_list]
|
||||
|
||||
add_data(_fields, _data_list, Dept)
|
||||
|
||||
|
||||
def create_admin_photo():
|
||||
from applications.models import Photo
|
||||
|
||||
_fields = [
|
||||
'id',
|
||||
'name',
|
||||
'href',
|
||||
'mime',
|
||||
'size',
|
||||
'create_time',
|
||||
]
|
||||
_data_list = [
|
||||
(3, '6958819_pear-admin_1607443454_1.png',
|
||||
'http://127.0.0.1:5000/_uploads/photos/6958819_pear-admin_1607443454_1.png', 'image/png', '2204',
|
||||
'2021-03-19 18:53:02'),
|
||||
(17, '1617291580000.jpg', 'http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg', 'image/png', '94211',
|
||||
'2021-04-01 23:39:41'),
|
||||
]
|
||||
add_data(_fields, _data_list, Photo)
|
||||
|
||||
|
||||
def create_admin_power():
|
||||
from applications.models import Power
|
||||
|
||||
_data_list = \
|
||||
[
|
||||
(1, '系统管理', '0', '', None, None, '0', 'layui-icon layui-icon-set-fill', 1, None, None, 1),
|
||||
(3, '用户管理', '1', 'admin:user:main', '/users/', '_iframe', '1',
|
||||
'layui-icon layui-icon layui-icon layui-icon layui-icon-rate', 1, None, None, 1),
|
||||
(4, '权限管理', '1', 'admin:power:main', '/rights/', '_iframe', '1', None, 2, None, None, 1),
|
||||
(9, '角色管理', '1', 'admin:role:main', '/admin/role', '_iframe', '1', 'layui-icon layui-icon-username', 2,
|
||||
'2021-03-16 22:24:58', '2021-03-25 19:15:24', 1),
|
||||
(13, '日志管理', '1', 'admin:log:main', '/logs', '_iframe', '1', 'layui-icon layui-icon-read', 4,
|
||||
'2021-03-18 22:37:10', '2021-06-03 11:06:25', 1),
|
||||
(17, '文件管理', '0', '', '', '', '0', 'layui-icon layui-icon-camera', 2, '2021-03-19 18:56:23',
|
||||
'2021-03-25 19:15:08', 1),
|
||||
(18, '图片上传', '1', 'admin:file:main', '/file', '_iframe', '17', 'layui-icon layui-icon-camera', 5,
|
||||
'2021-03-19 18:57:19', '2021-03-25 19:15:13', 1),
|
||||
(21, '权限增加', '2', 'admin:power:add', '', '', '4', 'layui-icon layui-icon-add-circle', 1,
|
||||
'2021-03-22 19:43:52',
|
||||
'2021-03-25 19:15:22', 1),
|
||||
(22, '用户增加', '2', 'admin:user:add', '', '', '3', 'layui-icon layui-icon-add-circle', 1,
|
||||
'2021-03-22 19:45:40',
|
||||
'2021-03-25 19:15:17', 1),
|
||||
(23, '用户编辑', '2', 'admin:user:edit', '', '', '3', 'layui-icon layui-icon-rate', 2, '2021-03-22 19:46:15',
|
||||
'2021-03-25 19:15:18', 1),
|
||||
(24, '用户删除', '2', 'admin:user:remove', '', '', '3', 'layui-icon None', 3, '2021-03-22 19:46:51',
|
||||
'2021-03-25 19:15:18', 1),
|
||||
(25, '权限编辑', '2', 'admin:power:edit', '', '', '4', 'layui-icon layui-icon-edit', 2, '2021-03-22 19:47:36',
|
||||
'2021-03-25 19:15:22', 1),
|
||||
(26, '用户删除', '2', 'admin:power:remove', '', '', '4', 'layui-icon layui-icon-delete', 3,
|
||||
'2021-03-22 19:48:17',
|
||||
'2021-03-25 19:15:23', 1),
|
||||
(27, '用户增加', '2', 'admin:role:add', '', '', '9', 'layui-icon layui-icon-add-circle', 1,
|
||||
'2021-03-22 19:49:09',
|
||||
'2021-03-25 19:15:24', 1),
|
||||
(28, '角色编辑', '2', 'admin:role:edit', '', '', '9', 'layui-icon layui-icon-edit', 2, '2021-03-22 19:49:41',
|
||||
'2021-03-25 19:15:25', 1),
|
||||
(
|
||||
29, '角色删除', '2', 'admin:role:remove', '', '', '9', 'layui-icon layui-icon-delete', 3,
|
||||
'2021-03-22 19:50:15',
|
||||
'2021-03-25 19:15:26', 1),
|
||||
(30, '角色授权', '2', 'admin:role:power', '', '', '9', 'layui-icon layui-icon-component', 4,
|
||||
'2021-03-22 19:50:54',
|
||||
'2021-03-25 19:15:26', 1),
|
||||
(31, '图片增加', '2', 'admin:file:add', '', '', '18', 'layui-icon layui-icon-add-circle', 1,
|
||||
'2021-03-22 19:58:05',
|
||||
'2021-03-25 19:15:28', 1),
|
||||
(32, '图片删除', '2', 'admin:file:delete', '', '', '18', 'layui-icon layui-icon-delete', 2,
|
||||
'2021-03-22 19:58:45',
|
||||
'2021-03-25 19:15:29', 1),
|
||||
(48, '部门管理', '1', 'admin:dept:main', '/dept', '_iframe', '1', 'layui-icon layui-icon-group', 3,
|
||||
'2021-06-01 16:22:11', '2021-06-01 16:22:11', 1),
|
||||
(49, '部门增加', '2', 'admin:dept:add', '', '', '48', 'layui-icon None', 1, '2021-06-01 17:35:52',
|
||||
'2021-06-01 17:36:15', 1),
|
||||
(50, '部门编辑', '2', 'admin:dept:edit', '', '', '48', 'layui-icon ', 2, '2021-06-01 17:36:41',
|
||||
'2021-06-01 17:36:41', 1),
|
||||
(51, '部门删除', '2', 'admin:dept:remove', '', '', '48', 'layui-icon None', 3, '2021-06-01 17:37:15',
|
||||
'2021-06-01 17:37:26', 1),
|
||||
]
|
||||
_fields = [
|
||||
'id',
|
||||
'name',
|
||||
'type',
|
||||
'code',
|
||||
'url',
|
||||
'open_type',
|
||||
'parent_id',
|
||||
'icon',
|
||||
'sort',
|
||||
'create_time',
|
||||
'update_time',
|
||||
'enable',
|
||||
]
|
||||
|
||||
add_data(_fields, _data_list, Power)
|
||||
|
||||
|
||||
def create_admin_role():
|
||||
from applications.models import Role
|
||||
|
||||
_fields = [
|
||||
'id',
|
||||
'name',
|
||||
'code',
|
||||
'remark',
|
||||
'details',
|
||||
'sort',
|
||||
'create_time',
|
||||
'update_time',
|
||||
'enable',
|
||||
]
|
||||
_data_list = [
|
||||
(1, '管理员', 'admin', None, '管理员', 1, None, None, 1),
|
||||
(2, '普通用户', 'common', None, '只有查看,没有增删改权限', 2, '2021-03-22 20:02:38', '2021-04-01 22:29:56', 1),
|
||||
]
|
||||
|
||||
add_data(_fields, _data_list, Role)
|
||||
|
||||
|
||||
def create_admin_role_power():
|
||||
from applications.extensions import db
|
||||
|
||||
_data_list = [
|
||||
(237, 1, 1),
|
||||
(238, 3, 1),
|
||||
(239, 4, 1),
|
||||
(240, 9, 1),
|
||||
(241, 12, 1),
|
||||
(242, 13, 1),
|
||||
(243, 17, 1),
|
||||
(244, 18, 1),
|
||||
(245, 21, 1),
|
||||
(246, 22, 1),
|
||||
(247, 23, 1),
|
||||
(248, 24, 1),
|
||||
(249, 25, 1),
|
||||
(250, 26, 1),
|
||||
(251, 27, 1),
|
||||
(252, 28, 1),
|
||||
(253, 29, 1),
|
||||
(254, 30, 1),
|
||||
(255, 31, 1),
|
||||
(256, 32, 1),
|
||||
(257, 44, 1),
|
||||
(258, 45, 1),
|
||||
(259, 46, 1),
|
||||
(260, 47, 1),
|
||||
(261, 48, 1),
|
||||
(262, 49, 1),
|
||||
(263, 50, 1),
|
||||
(264, 51, 1),
|
||||
(265, 1, 2),
|
||||
(266, 3, 2),
|
||||
(267, 4, 2),
|
||||
(268, 9, 2),
|
||||
(269, 12, 2),
|
||||
(270, 13, 2),
|
||||
(271, 17, 2),
|
||||
(272, 18, 2),
|
||||
(273, 44, 2),
|
||||
(274, 48, 2),
|
||||
]
|
||||
|
||||
# add_data(_fields, _data_list, UserRole)
|
||||
for data in _data_list:
|
||||
db.session.execute('insert into rt_role_power VALUES (%s, %s, %s);' % data)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def create_admin_user():
|
||||
from applications.models import User
|
||||
|
||||
_fields = [
|
||||
'id',
|
||||
'username',
|
||||
'password_hash',
|
||||
'create_at',
|
||||
'update_at',
|
||||
'enable',
|
||||
'realname',
|
||||
'remark',
|
||||
'avatar',
|
||||
'dept_id',
|
||||
]
|
||||
_data_list = [
|
||||
(1, 'admin', 'pbkdf2:sha256:150000$raM7mDSr$58fe069c3eac01531fc8af85e6fc200655dd2588090530084d182e6ec9d52c85',
|
||||
None, '2021-06-01 17:28:55', 1, '超级管理', '要是不能把握时机,就要终身蹭蹬,一事无成!',
|
||||
'http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg', 1),
|
||||
(7, 'test', 'pbkdf2:sha256:150000$cRS8bYNh$adb57e64d929863cf159f924f74d0634f1fecc46dba749f1bfaca03da6d2e3ac',
|
||||
'2021-03-22 20:03:42', '2021-06-01 17:29:47', 1, '超级管理', '要是不能把握时机,就要终身蹭蹬,一事无成',
|
||||
'/static/admin/admin/images/avatar.jpg', 1),
|
||||
(8, 'wind', 'pbkdf2:sha256:150000$skME1obT$6a2c20cd29f89d7d2f21d9e373a7e3445f70ebce3ef1c3a555e42a7d17170b37',
|
||||
'2021-06-01 17:30:39', '2021-06-01 17:30:52', 1, '风', None, '/static/admin/admin/images/avatar.jpg', 7),
|
||||
]
|
||||
|
||||
add_data(_fields, _data_list, User)
|
||||
|
||||
|
||||
def create_admin_user_role() -> object:
|
||||
from applications.extensions import db
|
||||
|
||||
_data_list = [
|
||||
(21, 1, 1),
|
||||
(22, 7, 2),
|
||||
(24, 8, 2),
|
||||
]
|
||||
|
||||
# add_data(_fields, _data_list, UserRole)
|
||||
for data in _data_list:
|
||||
db.session.execute('insert into rt_user_role VALUES (%s, %s, %s);' % data)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def register_script(app: Flask):
|
||||
@app.cli.command()
|
||||
def init_db():
|
||||
"""数据库初始化"""
|
||||
create_dept_data()
|
||||
create_admin_photo()
|
||||
create_admin_power()
|
||||
create_admin_role()
|
||||
create_admin_role_power()
|
||||
create_admin_user()
|
||||
create_admin_user_role()
|
||||
|
||||
@app.cli.command()
|
||||
def turn():
|
||||
"""清空数据库"""
|
||||
from applications.extensions import db
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
@@ -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 +1,11 @@
|
||||
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": "不是合法布尔值"
|
||||
}
|
||||
from flask_migrate import Migrate
|
||||
|
||||
db = SQLAlchemy()
|
||||
ma = Marshmallow()
|
||||
migrate = Migrate()
|
||||
|
||||
|
||||
def init_databases(app: Flask):
|
||||
db.init_app(app)
|
||||
ma.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
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
|
||||
from applications.models.company import Dept, User
|
||||
from applications.models.log import AdminLog
|
||||
from applications.models.file.photo import Photo
|
||||
from applications.models.rights.power import Power
|
||||
from applications.models.rights.role import Role
|
||||
from applications.models.rights.role_power import role_power
|
||||
from applications.models.rights.user_role import user_role
|
||||
|
||||
@@ -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,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,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,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,2 @@
|
||||
from .dept import Dept
|
||||
from .users import User
|
||||
@@ -1,10 +1,9 @@
|
||||
import datetime
|
||||
from applications.extensions import db, ma
|
||||
from marshmallow import fields, validate
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class Dept(db.Model):
|
||||
__tablename__ = 'admin_dept'
|
||||
__tablename__ = 'cp_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="部门名称")
|
||||
@@ -17,15 +16,3 @@ class Dept(db.Model):
|
||||
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,16 +1,15 @@
|
||||
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
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class User(db.Model, UserMixin):
|
||||
__tablename__ = 'admin_user'
|
||||
__tablename__ = 'cp_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='真实名字')
|
||||
mobile = db.Column(db.String(11), 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='哈希密码')
|
||||
@@ -18,7 +17,8 @@ class User(db.Model, UserMixin):
|
||||
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')
|
||||
|
||||
role = db.relationship('Role', secondary="rt_user_role", backref=db.backref('user'), lazy='dynamic')
|
||||
|
||||
def set_password(self, password):
|
||||
self.password_hash = generate_password_hash(password)
|
||||
@@ -26,19 +26,3 @@ class User(db.Model, UserMixin):
|
||||
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,11 +1,10 @@
|
||||
import datetime
|
||||
|
||||
from applications.extensions import db, ma
|
||||
from marshmallow import fields
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class Photo(db.Model):
|
||||
__tablename__ = 'admin_photo'
|
||||
__tablename__ = 'file_photo'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255), nullable=False)
|
||||
href = db.Column(db.String(255))
|
||||
@@ -13,12 +12,3 @@ class Photo(db.Model):
|
||||
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()
|
||||
@@ -0,0 +1,15 @@
|
||||
from datetime import datetime
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
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.now)
|
||||
@@ -0,0 +1,20 @@
|
||||
import datetime
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class Power(db.Model):
|
||||
__tablename__ = 'rt_power'
|
||||
id = db.Column(db.Integer, primary_key=True, comment='权限编号')
|
||||
name = db.Column(db.String(255), comment='权限名称')
|
||||
type = db.Column(db.SMALLINT, 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, db.ForeignKey("rt_power.id"), 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='是否开启')
|
||||
|
||||
parent = db.relationship("Power", remote_side=[id]) # 自关联
|
||||
@@ -1,10 +1,9 @@
|
||||
import datetime
|
||||
from applications.extensions import db, ma
|
||||
from marshmallow import fields
|
||||
from applications.extensions import db
|
||||
|
||||
|
||||
class Role(db.Model):
|
||||
__tablename__ = 'admin_role'
|
||||
__tablename__ = 'rt_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='角色标识')
|
||||
@@ -14,16 +13,4 @@ class Role(db.Model):
|
||||
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()
|
||||
power = db.relationship('Power', secondary="rt_role_power", backref=db.backref('role'))
|
||||
@@ -0,0 +1,9 @@
|
||||
from applications.extensions import db
|
||||
|
||||
# 创建中间表
|
||||
role_power = db.Table(
|
||||
"rt_role_power", # 中间表名称
|
||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
||||
db.Column("power_id", db.Integer, db.ForeignKey("rt_power.id"), comment='用户编号'), # 属性 外键
|
||||
db.Column("role_id", db.Integer, db.ForeignKey("rt_role.id"), comment='角色编号'), # 属性 外键
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
from applications.extensions import db
|
||||
|
||||
# 创建中间表
|
||||
user_role = db.Table(
|
||||
"rt_user_role", # 中间表名称
|
||||
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
|
||||
db.Column("user_id", db.Integer, db.ForeignKey("cp_user.id"), comment='用户编号'), # 属性 外键
|
||||
db.Column("role_id", db.Integer, db.ForeignKey("rt_role.id"), comment='角色编号'), # 属性 外键
|
||||
)
|
||||
@@ -12,14 +12,14 @@
|
||||
<div class="layui-tab layui-tab-card">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this">登录日志</li>
|
||||
<li>操作日志</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>
|
||||
<table style="margin-top: 10px;" id="log-access-table" lay-filter="log-access-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +44,7 @@
|
||||
let table = layui.table
|
||||
let form = layui.form
|
||||
|
||||
let MODULE_PATH = '/admin/log/'
|
||||
let MODULE_PATH = '/logs/'
|
||||
|
||||
let cols = [
|
||||
[
|
||||
@@ -61,8 +61,8 @@
|
||||
]
|
||||
|
||||
table.render({
|
||||
elem: '#log-operate-table',
|
||||
url: MODULE_PATH + 'operateLog',
|
||||
elem: '#log-access-table',
|
||||
url: MODULE_PATH + 'access_log',
|
||||
page: true,
|
||||
cols: cols,
|
||||
skin: 'line',
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
table.render({
|
||||
elem: '#log-login-table',
|
||||
url: MODULE_PATH + 'loginLog',
|
||||
url: MODULE_PATH + 'login_log',
|
||||
page: true,
|
||||
cols: cols,
|
||||
skin: 'line',
|
||||
|
||||
+4
-1
@@ -12,6 +12,7 @@
|
||||
<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>
|
||||
@@ -86,6 +87,7 @@
|
||||
let $ = layui.jquery
|
||||
let dtree = layui.dtree
|
||||
|
||||
/*渲染下拉选择组件*/
|
||||
dtree.renderSelect({
|
||||
elem: '#selectParent',
|
||||
url: '/dept/tree',
|
||||
@@ -97,9 +99,10 @@
|
||||
selectInitVal: '1'
|
||||
})
|
||||
|
||||
/*表单组件,提交按钮之后触发的事件*/
|
||||
form.on('submit(dept-save)', function (data) {
|
||||
$.ajax({
|
||||
url: '/dept/save',
|
||||
url: '/dept/add',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
+3
-2
@@ -97,9 +97,10 @@
|
||||
let form = layui.form
|
||||
let $ = layui.jquery
|
||||
|
||||
// 当点击更新之后,获取数据
|
||||
form.on('submit(dept-update)', function (data) {
|
||||
$.ajax({
|
||||
url: '/dept/update',
|
||||
url: '/dept/edit' + data.field.deptId,
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
@@ -107,7 +108,7 @@
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
layer.msg(result.msg, { icon: 1, time: 1000 }, function () {
|
||||
parent.layer.close(parent.layer.getFrameIndex(window.name))//关闭当前页
|
||||
parent.layer.close(parent.layer.getFrameIndex(window.name)) //关闭当前页
|
||||
parent.render()
|
||||
})
|
||||
} else {
|
||||
+49
-30
@@ -4,19 +4,24 @@
|
||||
<title>部门新增</title>
|
||||
{% include 'admin/common/header.html' %}
|
||||
</head>
|
||||
{#pear 后台边框#}
|
||||
<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>
|
||||
{#查询按钮--需要触发layui事件#}
|
||||
<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>
|
||||
重置
|
||||
@@ -28,10 +33,12 @@
|
||||
|
||||
<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">
|
||||
@@ -47,19 +54,17 @@
|
||||
{% 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 %}
|
||||
<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="dept-status">
|
||||
<input type="checkbox" name="status" value="{{ "{{ d.deptId }}" }}" lay-skin="switch" lay-text="启用|禁用"
|
||||
lay-filter="dept-enable"
|
||||
@@ -78,20 +83,23 @@
|
||||
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',
|
||||
treeIdName: 'deptId', /*表格的顶级字段*/
|
||||
treePidName: 'parentId', /*父级id选项*/
|
||||
skin: 'line',
|
||||
method: 'post',
|
||||
method: 'post', /**/
|
||||
treeDefaultClose: false,
|
||||
toolbar: '#dept-toolbar',
|
||||
elem: '#dept-table',
|
||||
url: '/dept/data',
|
||||
toolbar: '#dept-toolbar', /*表格的工具栏*/
|
||||
elem: '#dept-table', /*表格挂载的对象*/
|
||||
url: '/dept/data', /*数据来源接口*/
|
||||
page: false,
|
||||
cols: [
|
||||
[
|
||||
@@ -105,19 +113,22 @@
|
||||
{ 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')
|
||||
let keyword = $.trim(data.field.deptName)
|
||||
/*获取所有的公司节点*/
|
||||
let $tds = $('#dept-table').next('.treeTable').find('.layui-table-body tbody tr td')
|
||||
if (!keyword) {
|
||||
$tds.css('background-color', 'transparent')
|
||||
layer.msg('请输入关键字', { icon: 5 })
|
||||
return
|
||||
return false
|
||||
}
|
||||
var searchCount = 0
|
||||
/*本地查询并且标注高亮*/
|
||||
let searchCount = 0
|
||||
$tds.each(function () {
|
||||
$(this).css('background-color', 'transparent')
|
||||
if ($(this).text().indexOf(keyword) >= 0) {
|
||||
@@ -139,36 +150,44 @@
|
||||
|
||||
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) {
|
||||
console.log(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)
|
||||
layer.msg('禁止批量删除')
|
||||
return false
|
||||
{#console.log(table.checkStatus(obj.config.id).data)#}
|
||||
}
|
||||
})
|
||||
|
||||
/*切换选择状态*/
|
||||
form.on('switch(dept-enable)', function (obj) {
|
||||
let operate
|
||||
if (obj.elem.checked) {
|
||||
operate = 'enable'
|
||||
operate = 1
|
||||
} else {
|
||||
operate = 'disable'
|
||||
operate = 0
|
||||
}
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: '/dept/' + operate,
|
||||
data: JSON.stringify({ deptId: this.value }),
|
||||
url: '/dept/enable',
|
||||
data: JSON.stringify({ deptId: this.value, operate: operate }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
@@ -188,8 +207,8 @@
|
||||
type: 2,
|
||||
title: '新增',
|
||||
shade: 0.1,
|
||||
area: ['450px', '500px'],
|
||||
content: MODULE_PATH + 'add'
|
||||
area: ['450px', '500px'], /*新增窗口的大小*/
|
||||
content: MODULE_PATH + 'add' /*新增窗口从那里来*/
|
||||
})
|
||||
}
|
||||
|
||||
@@ -199,7 +218,7 @@
|
||||
title: '修改',
|
||||
shade: 0.1,
|
||||
area: ['450px', '500px'],
|
||||
content: MODULE_PATH + 'edit?deptId=' + obj.data['deptId']
|
||||
content: MODULE_PATH + 'edit/' + obj.data['deptId'] /*编辑修改窗口从那里来*/
|
||||
})
|
||||
}
|
||||
|
||||
@@ -208,7 +227,7 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: MODULE_PATH + 'remove/' + obj.data['deptId'],
|
||||
url: MODULE_PATH + 'edit/' + obj.data['deptId'],
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
success: function (result) {
|
||||
@@ -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>
|
||||
+3
-3
@@ -162,10 +162,10 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: 'delete',
|
||||
url: 'upload',
|
||||
data: { id: obj.data['id'] },
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
type: 'delete',
|
||||
success: function (res) {
|
||||
layer.close(loading)
|
||||
if (res.success) {
|
||||
@@ -210,7 +210,7 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: "{{ url_for('adminFile.batch_remove') }}",
|
||||
url: "{{ url_for('file.batch_remove') }}",
|
||||
data: { ids: ids },
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
//选完文件后不自动上传
|
||||
upload.render({
|
||||
elem: '#logo-img'
|
||||
, url: "{{ url_for('adminFile.upload') }}"
|
||||
, url: "{{ url_for('file.upload') }}"
|
||||
, auto: false
|
||||
, exts: 'jpg|png|gif|bmp|jpeg'
|
||||
, size: 1000
|
||||
@@ -17,9 +17,12 @@
|
||||
<div class="layui-header">
|
||||
<!-- 顶 部 左 侧 功 能 -->
|
||||
<ul class="layui-nav layui-layout-left">
|
||||
<li class="collaspe layui-nav-item"><a href="#" class="layui-icon layui-icon-shrink-right"></a></li>
|
||||
<li class="refresh layui-nav-item"><a href="#" class="layui-icon layui-icon-refresh-1" title="刷新页面"
|
||||
loading=600></a></li>
|
||||
<li class="collaspe layui-nav-item">
|
||||
<a href="#" class="layui-icon layui-icon-shrink-right"></a>
|
||||
</li>
|
||||
<li class="refresh layui-nav-item">
|
||||
<a href="#" class="layui-icon layui-icon-refresh-1" title="刷新页面" loading=600></a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- 顶 部 右 侧 菜 单 -->
|
||||
<div id="control" class="layui-layout-control"></div>
|
||||
@@ -39,7 +42,7 @@
|
||||
</a>
|
||||
<!-- 功 能 菜 单 -->
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a user-menu-url="/admin/user/center" user-menu-id="5555" user-menu-title="基本资料">基本资料</a></dd>
|
||||
<dd><a user-menu-url="/users/center" user-menu-id="5555" user-menu-title="基本资料">基本资料</a></dd>
|
||||
<dd><a href="javascript:void(0);" class="logout">注销登录</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
@@ -58,6 +61,7 @@
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内容主题 -->
|
||||
<div class="layui-body">
|
||||
<div id="content"></div>
|
||||
</div>
|
||||
@@ -65,7 +69,9 @@
|
||||
<!-- 遮 盖 层 -->
|
||||
<div class="pear-cover"></div>
|
||||
<!-- 移 动 端 便 捷 操 作 -->
|
||||
<div class="pear-collasped-pe collaspe"><a href="#" class="layui-icon layui-icon-shrink-right"></a></div>
|
||||
<div class="pear-collasped-pe collaspe">
|
||||
<a href="#" class="layui-icon layui-icon-shrink-right"></a>
|
||||
</div>
|
||||
<!-- 加 载 动 画-->
|
||||
<div class="loader-main">
|
||||
<div class="loader"></div>
|
||||
|
||||
@@ -39,51 +39,56 @@
|
||||
</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') }}";
|
||||
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);
|
||||
form.on('submit(login)', function (data) {
|
||||
// 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;
|
||||
}
|
||||
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>
|
||||
+2
-2
@@ -93,7 +93,7 @@
|
||||
|
||||
dtree.renderSelect({
|
||||
elem: '#selectParent',
|
||||
url: '/admin/power/selectParent',
|
||||
url: '{{ url_for('rights.select_parent') }}',
|
||||
method: 'get',
|
||||
selectInputName: { nodeId: 'parentId', context: 'powerName' },
|
||||
skin: 'layui',
|
||||
@@ -126,7 +126,7 @@
|
||||
form.on('submit(power-save)', function (data) {
|
||||
data.field.icon = 'layui-icon ' + data.field.icon
|
||||
$.ajax({
|
||||
url: '/admin/power/save',
|
||||
url: '/rights/power',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
+4
-3
@@ -105,7 +105,7 @@
|
||||
|
||||
dtree.renderSelect({
|
||||
elem: '#selectParent',
|
||||
url: '/admin/power/selectParent',
|
||||
url: '{{ url_for('rights.select_parent')}}',
|
||||
method: 'get',
|
||||
selectInputName: { nodeId: 'parentId', context: 'powerName' },
|
||||
skin: 'layui',
|
||||
@@ -137,8 +137,9 @@
|
||||
|
||||
form.on('submit(power-save)', function (data) {
|
||||
data.field.icon = 'layui-icon ' + data.field.icon
|
||||
console.log(data.field)
|
||||
$.ajax({
|
||||
url: '/admin/power/update',
|
||||
url: '/rights/power/' + data.field.powerId ,
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
@@ -191,7 +192,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
window.init("{{ power.type}}")
|
||||
window.init("{{ power.type }}")
|
||||
})
|
||||
</script>
|
||||
<script>
|
||||
+9
-9
@@ -92,7 +92,7 @@
|
||||
let treetable = layui.treetable
|
||||
let popup = layui.popup
|
||||
|
||||
let MODULE_PATH = '/admin/power/'
|
||||
let MODULE_PATH = '/rights/'
|
||||
|
||||
window.render = function () {
|
||||
treetable.render({
|
||||
@@ -105,7 +105,7 @@
|
||||
treeDefaultClose: true,
|
||||
toolbar: '#power-toolbar',
|
||||
elem: '#power-table',
|
||||
url: '/admin/power/data',
|
||||
url: '{{ url_for('rights.data') }}',
|
||||
page: false,
|
||||
cols: [
|
||||
[
|
||||
@@ -174,14 +174,14 @@
|
||||
form.on('switch(power-enable)', function (obj) {
|
||||
let operate
|
||||
if (obj.elem.checked) {
|
||||
operate = 'enable'
|
||||
operate = 1 /*启用*/
|
||||
} else {
|
||||
operate = 'disable'
|
||||
operate = 0 /*禁用*/
|
||||
}
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: '/admin/power/' + operate,
|
||||
data: JSON.stringify({ powerId: this.value }),
|
||||
url: MODULE_PATH + 'enable',
|
||||
data: JSON.stringify({ powerId: this.value, operate: operate }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
@@ -202,7 +202,7 @@
|
||||
title: '新增',
|
||||
shade: 0.1,
|
||||
area: ['450px', '500px'],
|
||||
content: MODULE_PATH + 'add'
|
||||
content: MODULE_PATH + 'power'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
title: '修改',
|
||||
shade: 0.1,
|
||||
area: ['450px', '500px'],
|
||||
content: MODULE_PATH + 'edit/' + obj.data['powerId']
|
||||
content: MODULE_PATH + 'power/' + obj.data['powerId']
|
||||
})
|
||||
}
|
||||
window.remove = function (obj) {
|
||||
@@ -220,7 +220,7 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: MODULE_PATH + 'remove/' + obj.data['powerId'],
|
||||
url: MODULE_PATH + 'power/' + obj.data['powerId'],
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
success: function (result) {
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
form.on('submit(role-save)', function (data) {
|
||||
$.ajax({
|
||||
url: '/admin/role/save',
|
||||
url: '/admin/role/add',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="enable" {% if role.enable == 0 %}checked {% endif %}value="0"
|
||||
<input type="radio" name="enable" {% if role.enable == 1 %}checked {% endif %}value="0"
|
||||
title="开启">
|
||||
<input type="radio" name="enable" {% if role.enable == 1 %}checked {% endif %} value="1"
|
||||
<input type="radio" name="enable" {% if role.enable == 0 %}checked {% endif %} value="1"
|
||||
title="关闭">
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
form.on('submit(role-update)', function (data) {
|
||||
$.ajax({
|
||||
url: '/admin/role/update',
|
||||
url: '/admin/role/edit/' + data.field.roleId,
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
@@ -96,6 +96,7 @@
|
||||
})
|
||||
return false
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>用户管理</title>
|
||||
<title>角色管理</title>
|
||||
{% include 'admin/common/header.html' %}</head>
|
||||
<body class="pear-container">
|
||||
<div class="layui-card">
|
||||
@@ -137,14 +137,14 @@
|
||||
form.on('switch(role-enable)', function (obj) {
|
||||
let operate
|
||||
if (obj.elem.checked) {
|
||||
operate = 'enable'
|
||||
operate = 1
|
||||
} else {
|
||||
operate = 'disable'
|
||||
operate = 0
|
||||
}
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: '/admin/role/' + operate,
|
||||
data: JSON.stringify({ roleId: this.value }),
|
||||
url: '/admin/role/enable',
|
||||
data: JSON.stringify({ roleId: this.value, operate: operate }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
@@ -194,7 +194,7 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: MODULE_PATH + 'remove/' + obj.data['id'],
|
||||
url: MODULE_PATH + 'role_power/' + obj.data['id'],
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
success: function (result) {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
dtree.render({
|
||||
elem: '#role-power',
|
||||
method: 'get',
|
||||
url: '/admin/role/getRolePower/' + {{id}},
|
||||
url: '/admin/role/role_power/' + {{id}},
|
||||
dataFormat: 'list',
|
||||
checkbar: true,
|
||||
skin: 'layui',
|
||||
@@ -56,7 +56,7 @@
|
||||
data.field.powerIds = ids
|
||||
|
||||
$.ajax({
|
||||
url: '/admin/role/saveRolePower',
|
||||
url: '/admin/role/role_power/' + data.field.roleId,
|
||||
data: data.field,
|
||||
dataType: 'json',
|
||||
type: 'put',
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
data.field.roleIds = roleIds
|
||||
|
||||
$.ajax({
|
||||
url: '/admin/user/save',
|
||||
url: '/users/add',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>头像上传</title>
|
||||
{% include 'admin/common/header.html' %}
|
||||
</head>
|
||||
<body class="pear-container">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-xs9">
|
||||
<div style="height:325px;background-color: rgb(247, 247, 247);">
|
||||
<img id="sourceImage" src="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3" style="padding-left:0px;">
|
||||
<div id="previewImage"
|
||||
style="width:210px;height:210px;border: 1px solid rgb(200, 200, 200);border-radius: 50%;overflow:hidden;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-inline layui-btn-container" style="width: auto;vertical-align:top;">
|
||||
<button class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-left" cropper-event="rotate"
|
||||
data-option="-15" title="左旋15°"></button>
|
||||
<button class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-right" cropper-event="rotate"
|
||||
data-option="15" title="右旋15°"></button>
|
||||
<button class="pear-btn pear-btn-sm pear-btn-danger layui-icon layui-icon-refresh" cropper-event="reset"
|
||||
title="重置"></button>
|
||||
<label for="uploadPicture" class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-upload"
|
||||
title="选择图片"></label>
|
||||
<input class="layui-upload-file" id="uploadPicture" type="file" value="选择图片">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">建议:图片的尺寸宽高比为1:1,大小在5m以内。</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
{% include 'admin/common/footer.html' %}
|
||||
<script>
|
||||
layui.use(['jquery', 'layer', 'cropper', 'popup'], function () {
|
||||
let $ = layui.jquery
|
||||
let layer = layui.layer
|
||||
let cropper = layui.cropper
|
||||
let popup = layui.popup
|
||||
|
||||
let options = {
|
||||
aspectRatio: 1 / 1, // 裁剪框比例
|
||||
preview: '#previewImage', // 预览div
|
||||
viewmode: 1
|
||||
}
|
||||
|
||||
$('#sourceImage').attr('src', parent.layui.$('#avatar').attr('src'))
|
||||
$('#sourceImage').cropper(options)
|
||||
|
||||
window.submitForm = function () {
|
||||
$('#sourceImage').crossOrigin = 'anonymous'//解决跨域图片问题
|
||||
$('#sourceImage').cropper('getCroppedCanvas', {
|
||||
width: 280,
|
||||
height: 140
|
||||
}).toBlob(function (blob) {
|
||||
let timeStamp = Date.parse(new Date())
|
||||
let fileName = timeStamp + '.jpg'
|
||||
let formData = new FormData()
|
||||
formData.append('file', blob, fileName)
|
||||
formData.append('fileName', fileName)
|
||||
formData.append('fileToken', timeStamp)
|
||||
$.ajax({
|
||||
method: 'post',
|
||||
url: '/admin/file/upload', //用于文件上传的服务器端请求地址
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
// 修改 avatar 字段
|
||||
$.ajax({
|
||||
method: 'put',
|
||||
url: '/users/avatar',
|
||||
data: JSON.stringify({ avatar: result.data }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
success: function (res) {
|
||||
if (res.success) {
|
||||
// 关闭当前弹层
|
||||
parent.layui.$('#avatar').attr('src', result.data.src)
|
||||
top.layui.$('#avatar').attr('src', result.data.src)
|
||||
parent.layer.close(parent.layer.getFrameIndex(window.name))
|
||||
} else {
|
||||
popup.failure('上传失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
popup.failure('上传失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
$('.pear-btn').on('click', function () {
|
||||
let event = $(this).attr('cropper-event')
|
||||
if (event === 'rotate') {
|
||||
let option = $(this).attr('data-option')
|
||||
$('#sourceImage').cropper('rotate', option)
|
||||
} else if (event === 'reset') {
|
||||
$('#sourceImage').cropper('reset')
|
||||
}
|
||||
$('#uploadPicture').change(function () {
|
||||
let r = new FileReader()
|
||||
let f = this.files[0]
|
||||
let uploadFileSize = f.size / 1024
|
||||
if (uploadFileSize > 5120) {
|
||||
parent.layer.msg('上传文件不得超过5m', { icon: 5 })
|
||||
return false
|
||||
}
|
||||
r.readAsDataURL(f)
|
||||
r.onload = function (e) {
|
||||
$('#sourceImage')
|
||||
.cropper('destroy')
|
||||
.attr('src', this.result)
|
||||
.cropper(options)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@@ -1,227 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>个人中心</title>
|
||||
{% include 'admin/common/header.html' %}
|
||||
<style>
|
||||
.layui-form-item {
|
||||
margin-top: 17px !important;
|
||||
margin-bottom: 17px !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="pear-container">
|
||||
<div class="layui-row layui-col-space10">
|
||||
{# 左侧栏 #}
|
||||
<div class="layui-col-md3">
|
||||
{# 个人信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body" style="padding: 25px;">
|
||||
<div class="text-center layui-text">
|
||||
<div class="user-info-head" id="userInfoHead">
|
||||
<img id="avatar" src="{{ user_info.avatar }}" width="115px" height="115px" alt="">
|
||||
</div>
|
||||
<h2 style="padding-top: 20px;font-size: 20px;">{{ user_info.realname }}</h2>
|
||||
<p style="padding-top: 8px;margin-top: 10px;font-size: 13.5px;">China , 中国</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 45px;border-top: 1px whitesmoke solid;text-align: center;line-height: 45px;font-size: 13.5px;">
|
||||
<span>{{ user_info.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{# 登录信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
登录记录
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<ul class="list">
|
||||
{% for log in user_logs %}
|
||||
<li class="list-item">
|
||||
<span class="title">{{ log.url }}</span>
|
||||
<span class="footer">{{ log.create_time }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# 右侧栏 #}
|
||||
<div class="layui-col-md9">
|
||||
{# 个人信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">个人信息</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<form class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input value="{{ user_info.username }}" type="text" readonly name="username"
|
||||
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 value="{{ user_info.realname }}" type="text" name="realName"
|
||||
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">{{ user_info.remark }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-submit
|
||||
lay-filter="user-update">修改资料
|
||||
</button>
|
||||
<button class="pear-btn pear-btn-sm edit-password">更改密码</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# 个人文章记录 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
我的文章
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'admin/common/footer.html' %}
|
||||
<script>
|
||||
layui.use(['element', 'jquery', 'layer', 'form'], function () {
|
||||
let $ = layui.jquery
|
||||
let layer = layui.layer
|
||||
let form = layui.form
|
||||
// 修改密码页面
|
||||
$('.edit-password').click(function () {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '修改密码',
|
||||
shade: 0.1,
|
||||
area: ['550px', '280px'],
|
||||
content: '/admin/user/editPassword'
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
||||
// 修改头像
|
||||
$('#avatar').click(function () {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '更换图片',
|
||||
shade: 0.1,
|
||||
area: ['900px', '500px'],
|
||||
content: '/admin/user/profile',
|
||||
btn: ['确定', '取消'],
|
||||
yes: function (index, layero) {
|
||||
window['layui-layer-iframe' + index].submitForm()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 表单提交更改个人信息数据
|
||||
form.on('submit(user-update)', function (data) {
|
||||
$.ajax({
|
||||
url: '/admin/user/updateInfo',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
layer.msg('修改成功', { icon: 1, time: 1000 })
|
||||
} else {
|
||||
layer.msg('修改失败', { icon: 2, time: 1000 })
|
||||
}
|
||||
}
|
||||
})
|
||||
return false
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -57,7 +57,7 @@
|
||||
// 修改密码提交
|
||||
form.on('submit(edit-password)', function (data) {
|
||||
$.ajax({
|
||||
url: '/admin/user/editPassword',
|
||||
url: '/users/editPassword',
|
||||
data: JSON.stringify(data.field),
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
|
||||
+3
-4
@@ -44,7 +44,7 @@
|
||||
<label class="layui-form-label">角色</label>
|
||||
<div class="layui-input-block">
|
||||
{% for role in roles %}
|
||||
<input{% if role.id in checked_roles %}
|
||||
<input {% if role.id in checked_roles %}
|
||||
checked
|
||||
{% endif %}
|
||||
value="{{ role.id }}" title="{{ role.name }}" type="checkbox"
|
||||
@@ -57,8 +57,7 @@
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="button-container">
|
||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
|
||||
lay-filter="user-update">
|
||||
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="user-update">
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
提交
|
||||
</button>
|
||||
@@ -94,7 +93,7 @@
|
||||
roleIds = roleIds.substr(0, roleIds.length - 1)
|
||||
data.field.roleIds = roleIds
|
||||
$.ajax({
|
||||
url: '/admin/user/update',
|
||||
url: '/users/' + data.field.userId,
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
@@ -111,7 +111,7 @@
|
||||
let dtree = layui.dtree
|
||||
let popup = layui.popup
|
||||
let common = layui.common
|
||||
let MODULE_PATH = '/admin/user/'
|
||||
let MODULE_PATH = '/users/'
|
||||
|
||||
// 表格数据
|
||||
let cols = [
|
||||
@@ -211,14 +211,14 @@
|
||||
form.on('switch(user-enable)', function (obj) {
|
||||
let operate
|
||||
if (obj.elem.checked) {
|
||||
operate = 'enable'
|
||||
operate = 1
|
||||
} else {
|
||||
operate = 'disable'
|
||||
operate = 0
|
||||
}
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: '/admin/user/' + operate,
|
||||
data: JSON.stringify({ userId: this.value }),
|
||||
url: MODULE_PATH + 'enable',
|
||||
data: JSON.stringify({ operate: operate, userId: this.value }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
@@ -249,7 +249,7 @@
|
||||
title: '修改',
|
||||
shade: 0.1,
|
||||
area: ['550px', '500px'],
|
||||
content: MODULE_PATH + 'edit/' + obj.data['id']
|
||||
content: MODULE_PATH + obj.data['id']
|
||||
})
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
layer.close(index)
|
||||
let loading = layer.load()
|
||||
$.ajax({
|
||||
url: MODULE_PATH + 'remove/' + obj.data['id'],
|
||||
url: MODULE_PATH + obj.data['id'],
|
||||
dataType: 'json',
|
||||
type: 'delete',
|
||||
success: function (result) {
|
||||
|
||||
@@ -1,126 +1,227 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>头像上传</title>
|
||||
<title>个人中心</title>
|
||||
{% include 'admin/common/header.html' %}
|
||||
<style>
|
||||
.layui-form-item {
|
||||
margin-top: 17px !important;
|
||||
margin-bottom: 17px !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="pear-container">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-xs9">
|
||||
<div style="height:325px;background-color: rgb(247, 247, 247);">
|
||||
<img id="sourceImage" src="">
|
||||
<div class="layui-row layui-col-space10">
|
||||
{# 左侧栏 #}
|
||||
<div class="layui-col-md3">
|
||||
{# 个人信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body" style="padding: 25px;">
|
||||
<div class="text-center layui-text">
|
||||
<div class="user-info-head" id="userInfoHead">
|
||||
<img id="avatar" src="{{ user_info.avatar }}" width="115px" height="115px" alt="">
|
||||
</div>
|
||||
<h2 style="padding-top: 20px;font-size: 20px;">{{ user_info.realname }}</h2>
|
||||
<p style="padding-top: 8px;margin-top: 10px;font-size: 13.5px;">China , 中国</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 45px;border-top: 1px whitesmoke solid;text-align: center;line-height: 45px;font-size: 13.5px;">
|
||||
<span>{{ user_info.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{# 登录信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
登录记录
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<ul class="list">
|
||||
{% for log in user_logs %}
|
||||
<li class="list-item">
|
||||
<span class="title">{{ log.url }}</span>
|
||||
<span class="footer">{{ log.create_time }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3" style="padding-left:0px;">
|
||||
<div id="previewImage"
|
||||
style="width:210px;height:210px;border: 1px solid rgb(200, 200, 200);border-radius: 50%;overflow:hidden;">
|
||||
{# 右侧栏 #}
|
||||
<div class="layui-col-md9">
|
||||
{# 个人信息卡片 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">个人信息</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<form class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input value="{{ user_info.username }}" type="text" readonly name="username"
|
||||
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 value="{{ user_info.realname }}" type="text" name="realName"
|
||||
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">{{ user_info.remark }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-submit
|
||||
lay-filter="user-update">修改资料
|
||||
</button>
|
||||
<button class="pear-btn pear-btn-sm edit-password">更改密码</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# 个人文章记录 #}
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
我的文章
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row layui-col-space10" style="margin: 15px;">
|
||||
<div class="layui-col-md1">
|
||||
<img src="{{ url_for('static', filename='admin/admin/images/act.jpg') }}"
|
||||
style="width: 100%;height: 100%;border-radius: 5px;"/>
|
||||
</div>
|
||||
<div class="layui-col-md11" style="height: 80px;">
|
||||
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习?</div>
|
||||
<div class="content">
|
||||
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处,在于理解了Git的精髓。”来一句我们程序员们接地气的话:分享是一种快乐~
|
||||
</div>
|
||||
<div class="comment">2020-06-12 评论 5 点赞 12 转发
|
||||
4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-row">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-inline layui-btn-container" style="width: auto;vertical-align:top;">
|
||||
<button class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-left" cropper-event="rotate"
|
||||
data-option="-15" title="左旋15°"></button>
|
||||
<button class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-right" cropper-event="rotate"
|
||||
data-option="15" title="右旋15°"></button>
|
||||
<button class="pear-btn pear-btn-sm pear-btn-danger layui-icon layui-icon-refresh" cropper-event="reset"
|
||||
title="重置"></button>
|
||||
<label for="uploadPicture" class="pear-btn pear-btn-sm pear-btn-primary layui-icon layui-icon-upload"
|
||||
title="选择图片"></label>
|
||||
<input class="layui-upload-file" id="uploadPicture" type="file" value="选择图片">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">建议:图片的尺寸宽高比为1:1,大小在5m以内。</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
{% include 'admin/common/footer.html' %}
|
||||
<script>
|
||||
layui.use(['jquery', 'layer', 'cropper', 'popup'], function () {
|
||||
layui.use(['element', 'jquery', 'layer', 'form'], function () {
|
||||
let $ = layui.jquery
|
||||
let layer = layui.layer
|
||||
let cropper = layui.cropper
|
||||
let popup = layui.popup
|
||||
|
||||
let options = {
|
||||
aspectRatio: 1 / 1, // 裁剪框比例
|
||||
preview: '#previewImage', // 预览div
|
||||
viewmode: 1
|
||||
}
|
||||
|
||||
$('#sourceImage').attr('src', parent.layui.$('#avatar').attr('src'))
|
||||
$('#sourceImage').cropper(options)
|
||||
|
||||
window.submitForm = function () {
|
||||
$('#sourceImage').crossOrigin = 'anonymous'//解决跨域图片问题
|
||||
$('#sourceImage').cropper('getCroppedCanvas', {
|
||||
width: 280,
|
||||
height: 140
|
||||
}).toBlob(function (blob) {
|
||||
let timeStamp = Date.parse(new Date())
|
||||
let fileName = timeStamp + '.jpg'
|
||||
let formData = new FormData()
|
||||
formData.append('file', blob, fileName)
|
||||
formData.append('fileName', fileName)
|
||||
formData.append('fileToken', timeStamp)
|
||||
$.ajax({
|
||||
method: 'post',
|
||||
url: '/admin/file/upload', //用于文件上传的服务器端请求地址
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
// 修改 avatar 字段
|
||||
$.ajax({
|
||||
method: 'put',
|
||||
url: '/admin/user/updateAvatar',
|
||||
data: JSON.stringify({ avatar: result.data }),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
success: function (res) {
|
||||
if (res.success) {
|
||||
// 关闭当前弹层
|
||||
parent.layui.$('#avatar').attr('src', result.data.src)
|
||||
top.layui.$('#avatar').attr('src', result.data.src)
|
||||
parent.layer.close(parent.layer.getFrameIndex(window.name))
|
||||
} else {
|
||||
popup.failure('上传失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
popup.failure('上传失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
let form = layui.form
|
||||
// 修改密码页面
|
||||
$('.edit-password').click(function () {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '修改密码',
|
||||
shade: 0.1,
|
||||
area: ['550px', '280px'],
|
||||
content: '/users/editPassword'
|
||||
})
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
$('.pear-btn').on('click', function () {
|
||||
let event = $(this).attr('cropper-event')
|
||||
if (event === 'rotate') {
|
||||
let option = $(this).attr('data-option')
|
||||
$('#sourceImage').cropper('rotate', option)
|
||||
} else if (event === 'reset') {
|
||||
$('#sourceImage').cropper('reset')
|
||||
}
|
||||
$('#uploadPicture').change(function () {
|
||||
let r = new FileReader()
|
||||
let f = this.files[0]
|
||||
let uploadFileSize = f.size / 1024
|
||||
if (uploadFileSize > 5120) {
|
||||
parent.layer.msg('上传文件不得超过5m', { icon: 5 })
|
||||
return false
|
||||
}
|
||||
r.readAsDataURL(f)
|
||||
r.onload = function (e) {
|
||||
$('#sourceImage')
|
||||
.cropper('destroy')
|
||||
.attr('src', this.result)
|
||||
.cropper(options)
|
||||
// 修改头像
|
||||
$('#avatar').click(function () {
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '更换图片',
|
||||
shade: 0.1,
|
||||
area: ['900px', '500px'],
|
||||
content: '/users/avatar',
|
||||
btn: ['确定', '取消'],
|
||||
yes: function (index, layero) {
|
||||
window['layui-layer-iframe' + index].submitForm()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 表单提交更改个人信息数据
|
||||
form.on('submit(user-update)', function (data) {
|
||||
$.ajax({
|
||||
url: '/users/updateInfo',
|
||||
data: JSON.stringify(data.field),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'put',
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
layer.msg('修改成功', { icon: 1, time: 1000 })
|
||||
} else {
|
||||
layer.msg('修改失败', { icon: 2, time: 1000 })
|
||||
}
|
||||
}
|
||||
})
|
||||
return false
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from applications.view.admin import register_admin_views
|
||||
from applications.view.system import register_system_views
|
||||
from applications.view.index import register_index_views
|
||||
from applications.view.passport import register_passport_views
|
||||
from applications.view.rights import register_rights_view
|
||||
@@ -6,7 +6,7 @@ from applications.view.department import register_dept_views
|
||||
|
||||
|
||||
def init_view(app):
|
||||
register_admin_views(app)
|
||||
register_system_views(app)
|
||||
register_index_views(app)
|
||||
register_rights_view(app)
|
||||
register_passport_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,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="批量删除成功")
|
||||
@@ -1,13 +1,16 @@
|
||||
from flask import Blueprint, render_template, request, jsonify
|
||||
from marshmallow import INCLUDE
|
||||
from flask import Blueprint, render_template, jsonify, make_response
|
||||
from flask_restful import marshal, Api, Resource, reqparse
|
||||
|
||||
from applications.common.serialization import dept_fields
|
||||
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
|
||||
from applications.extensions import db
|
||||
from applications.models import Dept, User
|
||||
|
||||
# from applications.view.company.department import dept_curd
|
||||
|
||||
dept_bp = Blueprint('dept', __name__, url_prefix='/dept')
|
||||
dept_api = Api(dept_bp)
|
||||
|
||||
|
||||
def register_dept_views(app):
|
||||
@@ -17,96 +20,124 @@ def register_dept_views(app):
|
||||
@dept_bp.get('/')
|
||||
@authorize("admin:dept:main", log=True)
|
||||
def main():
|
||||
return render_template('admin/dept/main.html')
|
||||
return render_template('admin/department/main.html')
|
||||
|
||||
|
||||
@dept_bp.get('/data')
|
||||
@authorize("admin:dept:main", log=True)
|
||||
def data():
|
||||
power_data = dept_curd.get_dept_dict()
|
||||
dept_data = Dept.query.order_by(Dept.sort).all()
|
||||
|
||||
res = {
|
||||
"data": power_data
|
||||
"data": marshal(dept_data, dept_fields)
|
||||
}
|
||||
return jsonify(res)
|
||||
|
||||
|
||||
@dept_bp.get('/add')
|
||||
@authorize("admin:dept:add", log=True)
|
||||
def add():
|
||||
return render_template('admin/dept/add.html')
|
||||
@dept_api.resource('/add')
|
||||
class AddDepartment(Resource):
|
||||
@authorize("admin:dept:add", log=True)
|
||||
def get(self):
|
||||
return make_response(render_template('admin/department/add.html'))
|
||||
|
||||
@authorize("admin:dept:add", log=True)
|
||||
def post(self):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('address', type=str)
|
||||
parser.add_argument('deptName', type=str, dest='dept_name')
|
||||
parser.add_argument('email', type=str)
|
||||
parser.add_argument('leader', type=str)
|
||||
parser.add_argument('parentId', type=int, dest='parent_id')
|
||||
parser.add_argument('phone', type=str)
|
||||
parser.add_argument('sort', type=int)
|
||||
parser.add_argument('status', type=int)
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
dept = Dept(
|
||||
parent_id=res.parent_id,
|
||||
dept_name=res.dept_name,
|
||||
sort=res.sort,
|
||||
leader=res.leader,
|
||||
phone=res.phone,
|
||||
email=res.email,
|
||||
status=res.status,
|
||||
address=res.address
|
||||
)
|
||||
db.session.add(dept)
|
||||
db.session.commit()
|
||||
|
||||
return success_api(msg="成功")
|
||||
|
||||
|
||||
@dept_bp.get('/tree')
|
||||
@authorize("admin:dept:main", log=True)
|
||||
def tree():
|
||||
power_data = dept_curd.get_dept_dict()
|
||||
dept_data = Dept.query.order_by(Dept.sort).all()
|
||||
res = {
|
||||
"status": {"code": 200, "message": "默认"},
|
||||
"data": power_data
|
||||
"data": marshal(dept_data, dept_fields)
|
||||
|
||||
}
|
||||
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)
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('deptId', type=int, dest='dept_id', required=True)
|
||||
parser.add_argument('operate', type=int, choices=[0, 1], required=True)
|
||||
|
||||
res = parser.parse_args()
|
||||
d = Dept.query.filter_by(id=res.dept_id).update({"status": res.operate})
|
||||
if d:
|
||||
db.session.commit()
|
||||
message = '启用成功' if res.operate else '禁用成功'
|
||||
return success_api(msg=message)
|
||||
return fail_api(msg="出错啦")
|
||||
|
||||
|
||||
@dept_api.resource('/edit/<int:dept_id>')
|
||||
class DeptURD(Resource):
|
||||
@authorize("admin:dept:edit", log=True)
|
||||
def get(self, dept_id):
|
||||
dept = Dept.query.filter_by(id=dept_id).first()
|
||||
return make_response(render_template('admin/department/edit.html', dept=dept))
|
||||
|
||||
@authorize("admin:dept:edit", log=True)
|
||||
def put(self, dept_id):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('address', type=str)
|
||||
parser.add_argument('deptName', type=str, dest='dept_name')
|
||||
parser.add_argument('email', type=str)
|
||||
parser.add_argument('leader', type=str)
|
||||
parser.add_argument('phone', type=str)
|
||||
parser.add_argument('sort', type=int)
|
||||
parser.add_argument('status', type=int)
|
||||
|
||||
res = parser.parse_args()
|
||||
data = {
|
||||
"dept_name": res.dept_name,
|
||||
"sort": res.sort,
|
||||
"leader": res.leader,
|
||||
"phone": res.phone,
|
||||
"email": res.email,
|
||||
"status": res.status,
|
||||
"address": res.address
|
||||
}
|
||||
res = Dept.query.filter_by(id=dept_id).update(data)
|
||||
if not res:
|
||||
return fail_api(msg="出错啦")
|
||||
return success_api(msg="启用成功")
|
||||
return fail_api(msg="数据错误")
|
||||
return fail_api(msg="更新失败")
|
||||
db.session.commit()
|
||||
return success_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:
|
||||
@authorize("admin:dept:remove", log=True)
|
||||
def delete(self, dept_id):
|
||||
ret = Dept.query.filter_by(id=dept_id).delete()
|
||||
User.query.filter_by(dept_id=dept_id).update({"dept_id": None})
|
||||
db.session.commit()
|
||||
if ret:
|
||||
return success_api(msg="删除成功")
|
||||
return fail_api(msg="删除失败")
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
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
|
||||
from applications.models import Photo
|
||||
|
||||
|
||||
def upload_one(photo, mime):
|
||||
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
from flask import Blueprint, request, render_template, jsonify, current_app, make_response
|
||||
from flask_restful import Api, Resource, marshal
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.serialization import photo_fields
|
||||
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.view.file._utils import delete_photo_by_id, upload_one
|
||||
|
||||
file_bp = Blueprint('file', __name__, url_prefix='/file')
|
||||
file_api = Api(file_bp)
|
||||
|
||||
|
||||
# 图片管理
|
||||
@file_bp.get('/')
|
||||
@authorize("admin:file:main", log=True)
|
||||
def index():
|
||||
return render_template('admin/file/photo.html')
|
||||
|
||||
|
||||
# 图片数据
|
||||
@file_bp.get('/table')
|
||||
@authorize("admin:file:main", log=True)
|
||||
def table():
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
photo_paginate = Photo.query.order_by(desc(Photo.create_time)).paginate(page=page, per_page=limit, error_out=False)
|
||||
data = marshal(photo_paginate.items, photo_fields)
|
||||
return table_api(data=data, count=photo_paginate.total)
|
||||
|
||||
|
||||
@file_api.resource('/upload')
|
||||
class Upload(Resource):
|
||||
@authorize("admin:file:add", log=True)
|
||||
def get(self):
|
||||
return make_response(render_template('admin/file/photo_add.html'))
|
||||
|
||||
@authorize("admin:file:add", log=True)
|
||||
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 = {
|
||||
"msg": "上传成功",
|
||||
"code": 0,
|
||||
"success": True,
|
||||
"data":
|
||||
{"src": file_url}
|
||||
}
|
||||
return jsonify(res)
|
||||
return fail_api()
|
||||
|
||||
@authorize("admin:file:delete", log=True)
|
||||
def delete(self):
|
||||
_id = request.form.get('id')
|
||||
res = delete_photo_by_id(_id)
|
||||
if res:
|
||||
return success_api(msg="删除成功")
|
||||
else:
|
||||
return fail_api(msg="删除失败")
|
||||
|
||||
|
||||
# 图片批量删除
|
||||
@file_bp.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,6 +1,6 @@
|
||||
from flask import Blueprint
|
||||
|
||||
index_bp = Blueprint('Index', __name__, url_prefix='/')
|
||||
index_bp = Blueprint('index', __name__, url_prefix='/')
|
||||
|
||||
from . import index
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
from flask import Blueprint, session, redirect, url_for, render_template, request
|
||||
from flask import Blueprint, session, redirect, url_for, render_template, request, make_response
|
||||
from flask_login import current_user, login_user, login_required, logout_user
|
||||
|
||||
from applications.common.admin import index_curd
|
||||
from flask_restful import Resource, Api, reqparse
|
||||
from applications.common.admin_log import login_log
|
||||
from applications.common.utils.http import fail_api, success_api
|
||||
from applications.models import User
|
||||
from ._utils import get_captcha_image, add_auth_session
|
||||
|
||||
passport_bp = Blueprint('passport', __name__, url_prefix='/passport')
|
||||
passport_api = Api(passport_bp)
|
||||
|
||||
|
||||
def register_passport_views(app):
|
||||
@@ -16,54 +17,50 @@ def register_passport_views(app):
|
||||
# 获取验证码
|
||||
@passport_bp.get('/getCaptcha')
|
||||
def get_captcha():
|
||||
resp, code = index_curd.get_captcha()
|
||||
resp, code = get_captcha_image()
|
||||
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_api.resource('/login')
|
||||
class Login(Resource):
|
||||
login_req = reqparse.RequestParser(bundle_errors=True)
|
||||
login_req.add_argument('username', type=str, help='请输入用户名', required=True)
|
||||
login_req.add_argument('password', type=str, help='请输入密码', required=True)
|
||||
login_req.add_argument('captcha', type=str, help='请输入验证码', required=True)
|
||||
|
||||
def get(self):
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for('admin.index'))
|
||||
|
||||
# 登录
|
||||
@passport_bp.post('/login')
|
||||
def login_post():
|
||||
req = request.form
|
||||
username = req.get('username')
|
||||
password = req.get('password')
|
||||
code = req.get('captcha')
|
||||
return make_response(render_template('admin/login.html'))
|
||||
|
||||
if not username or not password or not code:
|
||||
return fail_api(msg="用户名或密码没有输入")
|
||||
s_code = session.get("code", None)
|
||||
def post(self):
|
||||
|
||||
if not all([code, s_code]):
|
||||
return fail_api(msg="参数错误")
|
||||
req = self.login_req.parse_args()
|
||||
|
||||
if code != s_code:
|
||||
return fail_api(msg="验证码错误")
|
||||
user = User.query.filter_by(username=username).first()
|
||||
s_code = session.get("code", None)
|
||||
|
||||
if user is None:
|
||||
return fail_api(msg="不存在的用户")
|
||||
if req.captcha != s_code:
|
||||
return fail_api(msg="验证码错误")
|
||||
user = User.query.filter_by(username=req.username).first()
|
||||
|
||||
if user.enable is 0:
|
||||
return fail_api(msg="用户被暂停使用")
|
||||
if user is None:
|
||||
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="用户名或密码错误")
|
||||
if user.enable is 0:
|
||||
return fail_api(msg="用户被暂停使用")
|
||||
|
||||
if user.validate_password(req.password):
|
||||
# 登录
|
||||
login_user(user)
|
||||
# 记录登录日志
|
||||
login_log(request, uid=user.id, is_access=True)
|
||||
# 存入权限
|
||||
add_auth_session()
|
||||
return success_api(msg="登录成功")
|
||||
login_log(request, uid=user.id, is_access=False)
|
||||
return fail_api(msg="用户名或密码错误")
|
||||
|
||||
|
||||
# 退出登录
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from captcha.image import ImageCaptcha
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
from random import choices
|
||||
|
||||
from flask import session, make_response
|
||||
from flask_login import current_user
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
# 生成验证码
|
||||
def get_captcha_image():
|
||||
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
|
||||
|
||||
|
||||
# 授权路由存入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
|
||||
@@ -1,8 +1,11 @@
|
||||
from flask import Blueprint, Flask
|
||||
from flask_restful import Api
|
||||
|
||||
rights_bp = Blueprint('rights', __name__, url_prefix='/rights')
|
||||
rights_api = Api(rights_bp)
|
||||
|
||||
from . import routes
|
||||
from . import right
|
||||
|
||||
|
||||
def register_rights_view(app: Flask):
|
||||
|
||||
@@ -1,83 +1,15 @@
|
||||
from io import BytesIO
|
||||
from flask import session, make_response, current_app
|
||||
import copy
|
||||
from collections import OrderedDict
|
||||
|
||||
from flask import current_app
|
||||
from flask_login import current_user
|
||||
from flask_restful import marshal
|
||||
|
||||
from applications.common.utils.gen_captcha import gen_captcha
|
||||
from applications.models.admin_power import PowerSchema
|
||||
from applications.common.serialization import power_fields
|
||||
from applications.extensions import db
|
||||
from applications.models import Power, Role, User
|
||||
|
||||
|
||||
# 授权路由存入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
|
||||
from applications.common.serialization import power2_fields
|
||||
|
||||
|
||||
def get_render_config():
|
||||
@@ -150,3 +82,73 @@ def get_render_config():
|
||||
"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 = marshal(powers, power2_fields) # 生成可序列化对象
|
||||
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']])
|
||||
# 删除子节点
|
||||
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 menu_dict.get(0)
|
||||
|
||||
|
||||
# 选择父节点
|
||||
def select_power_dict():
|
||||
power = Power.query.all()
|
||||
res = marshal(power, power_fields)
|
||||
res.append({"powerId": 0, "powerName": "顶级权限", "parentId": -1})
|
||||
return res
|
||||
|
||||
|
||||
def get_power_dict():
|
||||
power = Power.query.all()
|
||||
res = marshal(power, power_fields)
|
||||
return res
|
||||
|
||||
|
||||
# 删除权限(目前没有判断父节点自动删除子节点)
|
||||
def remove_power(power_id):
|
||||
power = Power.query.filter_by(id=power_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=power_id).delete()
|
||||
db.session.commit()
|
||||
return r
|
||||
|
||||
|
||||
# 批量删除权限
|
||||
def batch_remove_power(ids):
|
||||
for _id in ids:
|
||||
remove_power(_id)
|
||||
@@ -0,0 +1,161 @@
|
||||
from flask import render_template, request, jsonify, make_response
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from . import rights_bp, rights_api
|
||||
from ._utils import select_power_dict, get_power_dict, batch_remove_power
|
||||
from ...common.utils.http import success_api, fail_api
|
||||
from ...common.utils.rights import authorize
|
||||
from ...extensions import db
|
||||
from ...models import Power, Role
|
||||
|
||||
parser_power = reqparse.RequestParser(bundle_errors=True)
|
||||
parser_power.add_argument('icon', type=str)
|
||||
parser_power.add_argument('openType', type=str, dest='open_type')
|
||||
parser_power.add_argument('parentId', type=str, dest='parent_id')
|
||||
parser_power.add_argument('powerCode', type=str, dest='power_code')
|
||||
parser_power.add_argument('powerName', type=str, dest='power_name')
|
||||
parser_power.add_argument('powerType', type=str, dest='power_type')
|
||||
parser_power.add_argument('powerUrl', type=str, dest='power_url')
|
||||
parser_power.add_argument('sort', type=int, dest='sort')
|
||||
|
||||
|
||||
@rights_bp.get('/')
|
||||
@authorize("admin:power:main", log=True)
|
||||
def index():
|
||||
return render_template('admin/rights/main.html')
|
||||
|
||||
|
||||
@rights_bp.get('/data')
|
||||
@authorize("admin:power:main", log=True)
|
||||
def data():
|
||||
power_data = get_power_dict()
|
||||
|
||||
res = {
|
||||
"data": power_data
|
||||
}
|
||||
return jsonify(res)
|
||||
|
||||
|
||||
@rights_bp.get('/selectParent')
|
||||
@authorize("admin:power:main", log=True)
|
||||
def select_parent():
|
||||
"""获取选择父节点"""
|
||||
power_data = select_power_dict()
|
||||
res = {
|
||||
"status": {"code": 200, "message": "默认"},
|
||||
"data": power_data
|
||||
|
||||
}
|
||||
return jsonify(res)
|
||||
|
||||
|
||||
# 启用权限
|
||||
@rights_bp.put('/enable')
|
||||
@authorize("admin:power:edit", log=True)
|
||||
def enable():
|
||||
parser = reqparse.RequestParser(bundle_errors=True)
|
||||
parser.add_argument('powerId', dest='power_id', type=int, required=True)
|
||||
parser.add_argument('operate', type=int, required=True, choices=[0, 1])
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
power = Power.query.filter_by(id=res.power_id).update({"enable": res.operate})
|
||||
if power:
|
||||
db.session.commit()
|
||||
message = "启用成功" if res.operate else '禁用成功'
|
||||
return success_api(msg=message)
|
||||
else:
|
||||
return fail_api(msg="出错啦")
|
||||
|
||||
|
||||
# 批量删除
|
||||
@rights_bp.delete('/batchRemove')
|
||||
@authorize("admin:power:remove", log=True)
|
||||
def batch_remove_view():
|
||||
ids = request.form.getlist('ids[]')
|
||||
batch_remove_power(ids)
|
||||
return success_api(msg="批量删除成功")
|
||||
|
||||
|
||||
@rights_api.resource('/power')
|
||||
class AddRight(Resource):
|
||||
@authorize("admin:power:add", log=True)
|
||||
def get(self):
|
||||
"""获取增加视图"""
|
||||
return make_response(render_template('admin/rights/add.html'))
|
||||
|
||||
@authorize("admin:power:add", log=True)
|
||||
def post(self):
|
||||
res = parser_power.parse_args()
|
||||
power = Power(
|
||||
icon=res.icon,
|
||||
open_type=res.open_type,
|
||||
parent_id=res.parent_id,
|
||||
code=res.power_code,
|
||||
name=res.power_name,
|
||||
type=res.power_type,
|
||||
url=res.power_url,
|
||||
sort=res.sort,
|
||||
enable=1
|
||||
)
|
||||
try:
|
||||
db.session.add(power)
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return fail_api(msg='数据提交失败')
|
||||
|
||||
return success_api(msg="成功")
|
||||
|
||||
|
||||
@rights_api.resource('/power/<int:power_id>')
|
||||
class RightsURD(Resource):
|
||||
@authorize("admin:power:edit", log=True)
|
||||
def get(self, power_id):
|
||||
power = Power.query.filter_by(id=power_id).first()
|
||||
icon = str(power.icon).split()
|
||||
if len(icon) == 2:
|
||||
icon = icon[1]
|
||||
else:
|
||||
icon = None
|
||||
return make_response(render_template('admin/rights/edit.html', power=power, icon=icon))
|
||||
|
||||
@authorize("admin:power:remove", log=True)
|
||||
def delete(self, power_id):
|
||||
# 删除权限(目前没有判断父节点自动删除子节点)
|
||||
power = Power.query.filter_by(id=power_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=power_id).delete()
|
||||
db.session.commit()
|
||||
|
||||
if r:
|
||||
return success_api(msg="删除成功")
|
||||
else:
|
||||
return fail_api(msg="删除失败")
|
||||
|
||||
@authorize("admin:power:edit", log=True)
|
||||
def put(self, power_id):
|
||||
|
||||
res = parser_power.parse_args()
|
||||
data = {
|
||||
"icon": res.icon,
|
||||
"open_type": res.open_type,
|
||||
"parent_id": res.parent_id,
|
||||
"code": res.power_code,
|
||||
"name": res.power_name,
|
||||
"type": res.power_type,
|
||||
"url": res.power_url,
|
||||
"sort": res.sort
|
||||
}
|
||||
power = Power.query.filter_by(id=power_id).update(data)
|
||||
db.session.commit()
|
||||
|
||||
if not power:
|
||||
return fail_api(msg="更新权限失败")
|
||||
return success_api(msg="更新权限成功")
|
||||
@@ -3,18 +3,19 @@ from flask import jsonify
|
||||
from flask_login import login_required
|
||||
|
||||
from . import rights_bp
|
||||
from ...common.admin import index_curd
|
||||
|
||||
from ._utils import get_render_config, make_menu_tree
|
||||
|
||||
|
||||
@rights_bp.get('/configs')
|
||||
@login_required
|
||||
def configs():
|
||||
return index_curd.get_render_config()
|
||||
return get_render_config()
|
||||
|
||||
|
||||
# 菜单
|
||||
@rights_bp.get('/menu')
|
||||
@login_required
|
||||
def menu():
|
||||
menu_tree = index_curd.make_menu_tree()
|
||||
menu_tree = make_menu_tree()
|
||||
return jsonify(menu_tree)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
from applications.extensions import db
|
||||
from applications.models import Power, Role, User
|
||||
|
||||
|
||||
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_role(ids):
|
||||
""" 批量删除 """
|
||||
for _id in ids:
|
||||
remove_role(_id)
|
||||
@@ -0,0 +1,223 @@
|
||||
from flask import Blueprint, render_template, jsonify, make_response
|
||||
from flask_login import login_required
|
||||
|
||||
from flask_restful import Resource, Api, reqparse
|
||||
|
||||
from applications.extensions import db
|
||||
from applications.models import Role, Power
|
||||
from applications.common.utils.http import table_api, success_api, fail_api
|
||||
from applications.common.utils.rights import authorize
|
||||
from flask_restful import reqparse, marshal
|
||||
|
||||
from applications.common.serialization import power_fields
|
||||
|
||||
from applications.view.roles._utils import remove_role, batch_remove_role
|
||||
|
||||
role_bp = Blueprint('role', __name__, url_prefix='/admin/role')
|
||||
role_api = Api(role_bp)
|
||||
|
||||
|
||||
# 角色而管理
|
||||
@role_bp.get('/')
|
||||
@authorize("admin:role:main", log=True)
|
||||
def main():
|
||||
return render_template('admin/role/main.html')
|
||||
|
||||
|
||||
# 表格数据
|
||||
@role_bp.get('/data')
|
||||
@authorize("admin:role:main", log=True)
|
||||
def table():
|
||||
parser = reqparse.RequestParser(bundle_errors=True)
|
||||
parser.add_argument('page', type=int, default=1)
|
||||
parser.add_argument('limit', type=int, default=10)
|
||||
parser.add_argument('roleName', type=str, dest='role_name', default="")
|
||||
parser.add_argument('roleCode', type=str, dest='role_code', default="")
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
filters = []
|
||||
if res.role_name:
|
||||
filters.append(Role.name.like('%' + res.role_name + '%'))
|
||||
if res.role_code:
|
||||
filters.append(Role.code.like('%' + res.role_code + '%'))
|
||||
|
||||
paginate = Role.query.filter(*filters).paginate(page=res.page, per_page=res.limit, error_out=False)
|
||||
|
||||
return table_api(data=[
|
||||
{
|
||||
'id': item.id,
|
||||
'roleName': item.name,
|
||||
'roleCode': item.code,
|
||||
'enable': item.enable,
|
||||
'remark': item.remark,
|
||||
'details': item.details,
|
||||
'sort': item.sort,
|
||||
'create_at': item.create_time,
|
||||
} for item in paginate.items
|
||||
], count=paginate.total)
|
||||
|
||||
|
||||
@role_api.resource('/add')
|
||||
class AddRole(Resource):
|
||||
@authorize("admin:role:add", log=True)
|
||||
def get(self):
|
||||
return make_response(render_template('admin/role/add.html'))
|
||||
|
||||
@authorize("admin:role:add", log=True)
|
||||
def post(self):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('details', type=str)
|
||||
parser.add_argument('enable', type=int)
|
||||
parser.add_argument('roleCode', type=str, dest='role_code')
|
||||
parser.add_argument('roleName', type=str, dest='role_name')
|
||||
parser.add_argument('sort', type=int)
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
role = Role(
|
||||
details=res.details,
|
||||
enable=res.enable,
|
||||
code=res.role_code,
|
||||
name=res.role_name,
|
||||
sort=res.sort
|
||||
)
|
||||
db.session.add(role)
|
||||
db.session.commit()
|
||||
return success_api(msg="成功")
|
||||
|
||||
|
||||
# 角色授权操作
|
||||
@role_bp.get('/power/<int:_id>')
|
||||
@authorize("admin:role:power", log=True)
|
||||
def power(_id):
|
||||
return render_template('admin/role/power.html', id=_id)
|
||||
|
||||
|
||||
@role_api.resource('/role_power/<int:role_id>')
|
||||
class RolePower(Resource):
|
||||
|
||||
@authorize("admin:role:main", log=True)
|
||||
def get(self, role_id):
|
||||
# 获取角色权限
|
||||
role = Role.query.filter_by(id=role_id).first()
|
||||
# 获取权限列表的 id
|
||||
check_powers_list = [rp.id for rp in role.power]
|
||||
powers = Power.query.all() # 获取所有的权限
|
||||
# power_schema = PowerSchema2(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
|
||||
# 将所有的权限生产可序列化对象 json
|
||||
# powers = power_schema.dump(powers) # 生成可序列化对象
|
||||
powers = marshal(powers, power_fields)
|
||||
for i in powers:
|
||||
if int(i.get("powerId")) in check_powers_list:
|
||||
i["checkArr"] = "1"
|
||||
else:
|
||||
i["checkArr"] = "0"
|
||||
res = {
|
||||
"data": powers,
|
||||
"status": {"code": 200, "message": "默认"}
|
||||
}
|
||||
return jsonify(res)
|
||||
|
||||
# 保存角色权限
|
||||
@authorize("admin:role:edit", log=True)
|
||||
def put(self, role_id):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('powerIds', dest='power_ids')
|
||||
parser.add_argument('roleId', dest='role_id')
|
||||
|
||||
res = parser.parse_args()
|
||||
power_list = res.power_ids.split(',')
|
||||
|
||||
""" 更新角色权限 """
|
||||
role = Role.query.filter_by(id=role_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)
|
||||
powers = Power.query.filter(Power.id.in_(power_list)).all()
|
||||
for p in powers:
|
||||
role.power.append(p)
|
||||
db.session.commit()
|
||||
return success_api(msg="授权成功")
|
||||
|
||||
# 角色删除
|
||||
@authorize("admin:role:remove", log=True)
|
||||
def delete(self, role_id):
|
||||
print(role_id)
|
||||
res = remove_role(role_id)
|
||||
print(res)
|
||||
if not res:
|
||||
return fail_api(msg="角色删除失败")
|
||||
return success_api(msg="角色删除成功")
|
||||
|
||||
|
||||
@role_api.resource('/edit/<int:role_id>')
|
||||
class EditRole(Resource):
|
||||
|
||||
# 角色编辑
|
||||
@authorize("admin:role:edit", log=True)
|
||||
def get(self, role_id):
|
||||
role = Role.query.filter_by(id=role_id).first()
|
||||
return make_response(render_template('admin/role/edit.html', role=role))
|
||||
|
||||
# 更新角色
|
||||
@authorize("admin:role:edit", log=True)
|
||||
def put(self, role_id):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('roleId', dest='role_id', type=int)
|
||||
parser.add_argument('roleCode', dest='role_code', type=str)
|
||||
parser.add_argument('roleName', dest='role_name', type=str)
|
||||
parser.add_argument('sort', type=int)
|
||||
parser.add_argument('enable', type=int)
|
||||
parser.add_argument('details', type=str)
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
data = {
|
||||
"code": res.role_code,
|
||||
"name": res.role_name,
|
||||
"sort": res.sort,
|
||||
"enable": res.enable,
|
||||
"details": res.details
|
||||
}
|
||||
|
||||
role = Role.query.filter_by(id=role_id).update(data)
|
||||
db.session.commit()
|
||||
if not role:
|
||||
return fail_api(msg="更新角色失败")
|
||||
return success_api(msg="更新角色成功")
|
||||
|
||||
|
||||
# 启用用户
|
||||
@role_bp.put('/enable')
|
||||
@authorize("admin:role:edit", log=True)
|
||||
def enable():
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('roleId', dest='role_id', required=True, type=int)
|
||||
parser.add_argument('operate', required=True, type=int)
|
||||
|
||||
res = parser.parse_args()
|
||||
ret = Role.query.filter_by(id=res.role_id).update({"enable": res.operate})
|
||||
db.session.commit()
|
||||
|
||||
message = "启动成功" if res.operate else "禁用成功"
|
||||
if not ret:
|
||||
return fail_api(msg="出错啦")
|
||||
return success_api(msg=message)
|
||||
|
||||
|
||||
# 批量删除
|
||||
@role_bp.delete('/batchRemove')
|
||||
@authorize("admin:role:remove", log=True)
|
||||
@login_required
|
||||
def batch_remove():
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('ids[]', action='append', dest='ids')
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
batch_remove_role(res.ids)
|
||||
return success_api(msg="批量删除成功")
|
||||
@@ -0,0 +1,15 @@
|
||||
from flask import Flask
|
||||
|
||||
from applications.view.system.logs import admin_log
|
||||
from applications.view.system.index import admin_bp
|
||||
from applications.view.file.file import file_bp
|
||||
from applications.view.roles.role import role_bp
|
||||
from applications.view.users import users_bp
|
||||
|
||||
|
||||
def register_system_views(app: Flask):
|
||||
app.register_blueprint(admin_bp)
|
||||
app.register_blueprint(users_bp)
|
||||
app.register_blueprint(file_bp)
|
||||
app.register_blueprint(admin_log)
|
||||
app.register_blueprint(role_bp)
|
||||
@@ -16,4 +16,4 @@ def index():
|
||||
@admin_bp.get('/welcome')
|
||||
@login_required
|
||||
def welcome():
|
||||
return render_template('admin/console/console.html')
|
||||
return render_template('admin/console/welcome.html')
|
||||
@@ -0,0 +1,43 @@
|
||||
from flask import Blueprint, request, render_template
|
||||
from sqlalchemy import desc
|
||||
from flask_restful import marshal
|
||||
from applications.common.serialization import log_fields
|
||||
|
||||
from applications.common.utils.http import table_api
|
||||
from applications.common.utils.rights import authorize
|
||||
from applications.models import AdminLog
|
||||
|
||||
admin_log = Blueprint('logs', __name__, url_prefix='/logs')
|
||||
|
||||
|
||||
@admin_log.get('/')
|
||||
@authorize("admin:log:main")
|
||||
def index():
|
||||
return render_template('admin/admin_log/main.html')
|
||||
|
||||
|
||||
@admin_log.get('/login_log')
|
||||
@authorize("admin:log:main")
|
||||
def login_log():
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
log_paginate = AdminLog.query.filter_by(
|
||||
url='/passport/login').order_by(
|
||||
desc(AdminLog.create_time)).paginate(
|
||||
page=page, per_page=limit, error_out=False)
|
||||
data = marshal(log_paginate.items, log_fields)
|
||||
|
||||
return table_api(data=data, count=log_paginate.total)
|
||||
|
||||
|
||||
@admin_log.get('/access_log')
|
||||
@authorize("admin:log:main")
|
||||
def operate_log():
|
||||
page = request.args.get('page', type=int)
|
||||
limit = request.args.get('limit', type=int)
|
||||
log_paginate = AdminLog.query.filter(
|
||||
AdminLog.url != '/passport/login').order_by(
|
||||
desc(AdminLog.create_time)).paginate(
|
||||
page=page, per_page=limit, error_out=False)
|
||||
data = marshal(log_paginate.items, log_fields)
|
||||
return table_api(data=data, count=log_paginate.total)
|
||||
@@ -0,0 +1,60 @@
|
||||
from flask import Blueprint, request, render_template
|
||||
from flask_restful import Api, reqparse
|
||||
|
||||
from applications.common.utils.http import table_api
|
||||
from applications.common.utils.rights import authorize
|
||||
from applications.models import Role, User, Dept
|
||||
|
||||
users_bp = Blueprint('users', __name__, url_prefix='/users')
|
||||
user_api = Api(users_bp)
|
||||
|
||||
|
||||
# 用户分页查询
|
||||
@users_bp.get('/data')
|
||||
@authorize("admin:user:main", log=True)
|
||||
def data():
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('page', type=int, default=1)
|
||||
parser.add_argument('limit', type=int, default=10)
|
||||
parser.add_argument('realName', type=str, dest='real_name')
|
||||
parser.add_argument('username', type=str)
|
||||
parser.add_argument('deptId', type=int, dest='dept_id', default=0)
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
filters = []
|
||||
|
||||
if res.real_name:
|
||||
filters.append(User.realname.like('%' + res.real_name + '%'))
|
||||
if res.username:
|
||||
filters.append(User.username.like('%' + res.username + '%'))
|
||||
if res.dept_id:
|
||||
filters.append(User.dept_id == res.dept_id)
|
||||
|
||||
paginate = User.query.filter(*filters).paginate(page=res.page,
|
||||
per_page=res.limit,
|
||||
error_out=False)
|
||||
|
||||
dept_name = lambda dept_id: Dept.query.filter_by(id=dept_id).first().dept_name
|
||||
user_data = [{
|
||||
'id': item.id,
|
||||
'username': item.username,
|
||||
'realname': item.realname,
|
||||
'enable': item.enable,
|
||||
'create_at': item.create_at,
|
||||
'update_at': item.update_at,
|
||||
'dept': dept_name(item.dept_id),
|
||||
} for item in paginate.items]
|
||||
|
||||
return table_api(data=user_data, count=paginate.total)
|
||||
|
||||
|
||||
# 用户增加
|
||||
@users_bp.get('/')
|
||||
@authorize("admin:user:main", log=True)
|
||||
def get():
|
||||
return render_template('admin/user/main.html')
|
||||
|
||||
|
||||
from . import profile, _utils
|
||||
from . import user_view
|
||||
@@ -0,0 +1,55 @@
|
||||
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
|
||||
from applications.models import Role
|
||||
from applications.models import AdminLog
|
||||
|
||||
|
||||
|
||||
def get_current_user_logs():
|
||||
""" 获取当前用户日志 """
|
||||
log = AdminLog.query.filter_by(url='/passport/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 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 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()
|
||||
@@ -0,0 +1,86 @@
|
||||
# 个人中心
|
||||
from flask import render_template, request, make_response, jsonify
|
||||
from flask_login import login_required, current_user
|
||||
from flask_restful import Resource, reqparse
|
||||
from sqlalchemy import desc
|
||||
|
||||
from applications.common.utils.http import fail_api, success_api
|
||||
from applications.extensions import db
|
||||
from applications.models import User, AdminLog
|
||||
from applications.view.users import users_bp, user_api
|
||||
|
||||
|
||||
@users_bp.get('/center')
|
||||
@login_required
|
||||
def center():
|
||||
user_info = current_user
|
||||
user_logs = AdminLog.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
|
||||
desc(AdminLog.create_time)).limit(10)
|
||||
return render_template('admin/user/profile.html', user_info=user_info, user_logs=user_logs)
|
||||
|
||||
|
||||
@user_api.resource('/avatar')
|
||||
class Avatar(Resource):
|
||||
"""修改头像"""
|
||||
|
||||
def get(self):
|
||||
return make_response(render_template('admin/user/avatar.html'))
|
||||
|
||||
def put(self):
|
||||
url = request.json.get("avatar").get("src")
|
||||
ret = User.query.filter_by(id=current_user.id).update({"avatar": url})
|
||||
db.session.commit()
|
||||
if not ret:
|
||||
return fail_api(msg="出错啦")
|
||||
return success_api(msg="修改成功")
|
||||
|
||||
|
||||
# 修改当前用户信息
|
||||
@users_bp.put('/updateInfo')
|
||||
@login_required
|
||||
def update_info():
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('realname', type=str, dest='real_name')
|
||||
parser.add_argument('remark', type=str)
|
||||
parser.add_argument('details', type=str)
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
ret = User.query.filter_by(
|
||||
id=current_user.id).update({"realname": res.real_name,
|
||||
"remark": res.details})
|
||||
if not ret:
|
||||
return fail_api(msg="出错啦")
|
||||
return success_api(msg="更新成功")
|
||||
|
||||
|
||||
@user_api.resource('/editPassword')
|
||||
class EditPassword(Resource):
|
||||
"""前用户密码"""
|
||||
|
||||
@login_required
|
||||
def get(self):
|
||||
return make_response(render_template('admin/user/edit_password.html'))
|
||||
|
||||
@login_required
|
||||
def put(self):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('oldPassword', type=str, required=True, help='旧密码不得为空')
|
||||
parser.add_argument('newPassword', type=str, required=True, help='新密码不得为空')
|
||||
parser.add_argument('confirmPassword', type=str, required=True, help='确认密码不能为空')
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
if res.newPassword != res.confirmPassword:
|
||||
return fail_api(msg='确认密码不一致')
|
||||
|
||||
""" 修改当前用户密码 """
|
||||
is_right = current_user.validate_password(res.oldPassword)
|
||||
if not is_right:
|
||||
return jsonify(success=False, msg="旧密码错误")
|
||||
current_user.set_password(res.newPassword)
|
||||
db.session.add(current_user)
|
||||
db.session.commit()
|
||||
|
||||
return jsonify(success=True, msg="更改成功")
|
||||
@@ -0,0 +1,129 @@
|
||||
from flask import render_template, request, make_response
|
||||
from flask_restful import Resource, reqparse
|
||||
from applications.extensions import db
|
||||
|
||||
from applications.common.utils.http import fail_api, success_api
|
||||
from applications.common.utils.rights import authorize
|
||||
from applications.models import User, Role
|
||||
from applications.view.users import user_api, users_bp, _utils
|
||||
|
||||
|
||||
@user_api.resource('/add')
|
||||
class Users(Resource):
|
||||
"""用户列表数据操作"""
|
||||
|
||||
@authorize("admin:user:add", log=True)
|
||||
def get(self):
|
||||
roles = Role.query.all()
|
||||
return make_response(render_template('admin/user/add.html', roles=roles))
|
||||
|
||||
@authorize("admin:user:add", log=True)
|
||||
def post(self):
|
||||
"""新建单个用户"""
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument("roleIds", type=str, dest='role_ids')
|
||||
parser.add_argument("username", type=str, required=True, help="用户名不能为空")
|
||||
parser.add_argument("realName", type=str, required=True, help="真实姓名不能为空", dest='real_name')
|
||||
parser.add_argument("password", type=str, required=True, help="密码不得为空")
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
role_ids = res.role_ids.split(',')
|
||||
|
||||
if _utils.is_user_exists(res.username):
|
||||
return fail_api(msg="用户已经存在")
|
||||
|
||||
user = User()
|
||||
user.username = res.username
|
||||
user.realname = res.real_name
|
||||
user.set_password(res.password)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
|
||||
""" 增加用户角色 """
|
||||
user = User.query.filter_by(id=user.id).first()
|
||||
roles = Role.query.filter(Role.id.in_(role_ids)).all()
|
||||
for r in roles:
|
||||
user.role.append(r)
|
||||
db.session.commit()
|
||||
|
||||
return success_api(msg="增加成功")
|
||||
|
||||
|
||||
@user_api.resource('/<user_id>')
|
||||
class CURDUser(Resource):
|
||||
"""修改用户数据"""
|
||||
|
||||
@authorize("admin:user:edit", log=True)
|
||||
def get(self, user_id):
|
||||
# 获取编辑用户信息
|
||||
user = User.query.filter_by(id=user_id).first()
|
||||
roles = Role.query.all()
|
||||
checked_roles = []
|
||||
for r in user.role:
|
||||
checked_roles.append(r.id)
|
||||
return make_response(
|
||||
render_template('admin/user/edit_users.html', user=user, roles=roles, checked_roles=checked_roles))
|
||||
|
||||
@authorize("admin:user:remove", log=True)
|
||||
def delete(self, user_id):
|
||||
# 删除用户
|
||||
res = _utils.delete_by_id(user_id)
|
||||
if not res:
|
||||
return fail_api(msg="删除失败")
|
||||
return success_api(msg="删除成功")
|
||||
|
||||
@authorize("admin:user:edit", log=True)
|
||||
def put(self, user_id):
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('roleIds', type=str, dest='role_ids')
|
||||
parser.add_argument('userId', type=str, dest='user_id')
|
||||
parser.add_argument('username', type=str)
|
||||
parser.add_argument('realName', type=str, dest='real_name')
|
||||
parser.add_argument('deptId', type=str, dest='dept_id')
|
||||
|
||||
res = parser.parse_args()
|
||||
role_ids = res.role_ids.split(',')
|
||||
|
||||
# 更新用户数据
|
||||
User.query.filter_by(id=user_id).update({'username': res.username,
|
||||
'realname': res.real_name,
|
||||
'dept_id': res.dept_id})
|
||||
db.session.commit()
|
||||
|
||||
_utils.update_user_role(user_id, role_ids)
|
||||
|
||||
return success_api(msg="更新成功")
|
||||
|
||||
|
||||
# 批量删除
|
||||
@users_bp.delete('/batchRemove')
|
||||
@authorize("admin:user:remove", log=True)
|
||||
def batch_remove():
|
||||
ids = request.form.getlist('ids[]')
|
||||
_utils.batch_remove(ids)
|
||||
return success_api(msg="批量删除成功")
|
||||
|
||||
|
||||
@users_bp.put('/enable')
|
||||
def user_enable():
|
||||
# 启用或者禁用用户 enable disable
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('userId', type=int, required=True, dest='user_id')
|
||||
parser.add_argument('operate', type=int, required=True, dest='operate', choices=[0, 1])
|
||||
|
||||
res = parser.parse_args()
|
||||
|
||||
if res.operate == 1:
|
||||
user = User.query.filter_by(id=res.user_id).update({"enable": res.operate})
|
||||
message = success_api(msg="启动成功")
|
||||
else:
|
||||
user = User.query.filter_by(id=res.user_id).update({"enable": res.operate})
|
||||
message = success_api(msg="禁用成功")
|
||||
if user:
|
||||
db.session.commit()
|
||||
else:
|
||||
return fail_api(msg="出错啦")
|
||||
return message
|
||||
@@ -1 +0,0 @@
|
||||
Generic single-database configuration.
|
||||
@@ -1,45 +0,0 @@
|
||||
# A generic, single database configuration.
|
||||
|
||||
[alembic]
|
||||
# template used to generate migration files
|
||||
# file_template = %%(rev)s_%%(slug)s
|
||||
|
||||
# set to 'true' to run the environment during
|
||||
# the 'revision' command, regardless of autogenerate
|
||||
# revision_environment = false
|
||||
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
keys = root,sqlalchemy,alembic
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARN
|
||||
handlers = console
|
||||
qualname =
|
||||
|
||||
[logger_sqlalchemy]
|
||||
level = WARN
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
|
||||
[logger_alembic]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = alembic
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stderr,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||
datefmt = %H:%M:%S
|
||||
@@ -1,96 +0,0 @@
|
||||
from __future__ import with_statement
|
||||
|
||||
import logging
|
||||
from logging.config import fileConfig
|
||||
|
||||
from sqlalchemy import engine_from_config
|
||||
from sqlalchemy import pool
|
||||
from flask import current_app
|
||||
|
||||
from alembic import context
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
config = context.config
|
||||
|
||||
# Interpret the configs file for Python logging.
|
||||
# This line sets up loggers basically.
|
||||
fileConfig(config.config_file_name)
|
||||
logger = logging.getLogger('alembic.env')
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
config.set_main_option(
|
||||
'sqlalchemy.url',
|
||||
str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
|
||||
target_metadata = current_app.extensions['migrate'].db.metadata
|
||||
|
||||
# other values from the configs, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
# my_important_option = configs.get_main_option("my_important_option")
|
||||
# ... etc.
|
||||
|
||||
|
||||
def run_migrations_offline():
|
||||
"""Run migrations in 'offline' mode.
|
||||
|
||||
This configures the context with just a URL
|
||||
and not an Engine, though an Engine is acceptable
|
||||
here as well. By skipping the Engine creation
|
||||
we don't even need a DBAPI to be available.
|
||||
|
||||
Calls to context.execute() here emit the given string to the
|
||||
script output.
|
||||
|
||||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url, target_metadata=target_metadata, literal_binds=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online():
|
||||
"""Run migrations in 'online' mode.
|
||||
|
||||
In this scenario we need to create an Engine
|
||||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
|
||||
# this callback is used to prevent an auto-migration from being generated
|
||||
# when there are no changes to the schema
|
||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||
def process_revision_directives(context, revision, directives):
|
||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||
script = directives[0]
|
||||
if script.upgrade_ops.is_empty():
|
||||
directives[:] = []
|
||||
logger.info('No changes in schema detected.')
|
||||
|
||||
connectable = engine_from_config(
|
||||
config.get_section(config.config_ini_section),
|
||||
prefix='sqlalchemy.',
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
process_revision_directives=process_revision_directives,
|
||||
**current_app.extensions['migrate'].configure_args
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
@@ -1,24 +0,0 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade():
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade():
|
||||
${downgrades if downgrades else "pass"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user