去除首页面,优化命名,优化schema

This commit is contained in:
不胜舟
2023-06-21 01:15:56 +08:00
parent d71e2e220f
commit 4e7a85bead
838 changed files with 1588 additions and 1725 deletions
+9 -2
View File
@@ -114,7 +114,14 @@ dmypy.json
# Pyre type checker
.pyre/
#ide
# idea
.idea/
# 迁移文件
migrations/
migrations/
# sqlite
*.db
# 文件上传
static/upload/
+2 -2
View File
@@ -113,7 +113,7 @@ MYSQL_USERNAME=root
MYSQL_PASSWORD=root
# 密钥配置
SECRET_KEY='pear-admin-flask'
SECRET_KEY='pear-system-flask'
# 邮箱配置
MAIL_SERVER='smtp.qq.com'
@@ -134,7 +134,7 @@ python -m venv venv
flask db init
flask db migrate
flask db upgrade
flask admin init
flask system init
# windows
run.bat
+5 -5
View File
@@ -3,19 +3,19 @@ from flask import Flask
from applications.common.script import init_script
from applications.config import BaseConfig
from applications.extensions import init_plugs
from applications.view import init_view
from applications.view import init_bps
def create_app():
app = Flask(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# 引入数据库配置
# 引入配置
app.config.from_object(BaseConfig)
# 注册各种插
# 注册flask组
init_plugs(app)
# 注册路由
init_view(app)
# 注册蓝图
init_bps(app)
# 注册命令
init_script(app)
+42 -42
View File
@@ -17,7 +17,7 @@ userdata = [
enable=1,
realname='超级管理',
remark='要是不能把握时机,就要终身蹭蹬,一事无成!',
avatar='http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg',
avatar='/static/system/admin/images/avatar.jpg',
dept_id=1,
),
User(
@@ -28,7 +28,7 @@ userdata = [
enable=1,
realname='测试',
remark='要是不能把握时机,就要终身蹭蹬,一事无成!',
avatar='http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg',
avatar='/static/system/admin/images/avatar.jpg',
dept_id=1,
),
User(
@@ -39,7 +39,7 @@ userdata = [
enable=1,
realname='',
remark='要是不能把握时机,就要终身蹭蹬,一事无成!',
avatar='http://127.0.0.1:5000/_uploads/photos/1617291580000.jpg',
avatar='/static/system/admin/images/avatar.jpg',
dept_id=7,
),
]
@@ -147,8 +147,8 @@ powerdata = [
id=3,
name='用户管理',
type='1',
code='admin:user:main',
url='/admin/user/',
code='system:user:main',
url='/system/user/',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon layui-icon layui-icon layui-icon-rate',
@@ -160,8 +160,8 @@ powerdata = [
id=4,
name='权限管理',
type='1',
code='admin:power:main',
url='/admin/power/',
code='system:power:main',
url='/system/power/',
open_type='_iframe',
parent_id='1',
icon=None,
@@ -173,8 +173,8 @@ powerdata = [
id=9,
name='角色管理',
type='1',
code='admin:role:main',
url='/admin/role',
code='system:role:main',
url='/system/role',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon-username',
@@ -186,8 +186,8 @@ powerdata = [
id=12,
name='系统监控',
type='1',
code='admin:monitor:main',
url='/admin/monitor',
code='system:monitor:main',
url='/system/monitor',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon-vercode',
@@ -199,8 +199,8 @@ powerdata = [
id=13,
name='日志管理',
type='1',
code='admin:log:main',
url='/admin/log',
code='system:log:main',
url='/system/log',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon-read',
@@ -225,8 +225,8 @@ powerdata = [
id=18,
name='图片上传',
type='1',
code='admin:file:main',
url='/admin/file',
code='system:file:main',
url='/system/file',
open_type='_iframe',
parent_id='17',
icon='layui-icon layui-icon-camera',
@@ -238,7 +238,7 @@ powerdata = [
id=21,
name='权限增加',
type='2',
code='admin:power:add',
code='system:power:add',
url='',
open_type='',
parent_id='4',
@@ -251,7 +251,7 @@ powerdata = [
id=22,
name='用户增加',
type='2',
code='admin:user:add',
code='system:user:add',
url='',
open_type='',
parent_id='3',
@@ -264,7 +264,7 @@ powerdata = [
id=23,
name='用户编辑',
type='2',
code='admin:user:edit',
code='system:user:edit',
url='',
open_type='',
parent_id='3',
@@ -277,7 +277,7 @@ powerdata = [
id=24,
name='用户删除',
type='2',
code='admin:user:remove',
code='system:user:remove',
url='',
open_type='',
parent_id='3',
@@ -290,7 +290,7 @@ powerdata = [
id=25,
name='权限编辑',
type='2',
code='admin:power:edit',
code='system:power:edit',
url='',
open_type='',
parent_id='4',
@@ -303,7 +303,7 @@ powerdata = [
id=26,
name='用户删除',
type='2',
code='admin:power:remove',
code='system:power:remove',
url='',
open_type='',
parent_id='4',
@@ -316,7 +316,7 @@ powerdata = [
id=27,
name='用户增加',
type='2',
code='admin:role:add',
code='system:role:add',
url='',
open_type='',
parent_id='9',
@@ -329,7 +329,7 @@ powerdata = [
id=28,
name='角色编辑',
type='2',
code='admin:role:edit',
code='system:role:edit',
url='',
open_type='',
parent_id='9',
@@ -342,7 +342,7 @@ powerdata = [
id=29,
name='角色删除',
type='2',
code='admin:role:remove',
code='system:role:remove',
url='',
open_type='',
parent_id='9',
@@ -355,7 +355,7 @@ powerdata = [
id=30,
name='角色授权',
type='2',
code='admin:role:power',
code='system:role:power',
url='',
open_type='',
parent_id='9',
@@ -368,7 +368,7 @@ powerdata = [
id=31,
name='图片增加',
type='2',
code='admin:file:add',
code='system:file:add',
url='',
open_type='',
parent_id='18',
@@ -381,7 +381,7 @@ powerdata = [
id=32,
name='图片删除',
type='2',
code='admin:file:delete',
code='system:file:delete',
url='',
open_type='',
parent_id='18',
@@ -394,8 +394,8 @@ powerdata = [
id=44,
name='数据字典',
type='1',
code='admin:dict:main',
url='/admin/dict',
code='system:dict:main',
url='/system/dict',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon-console',
@@ -407,7 +407,7 @@ powerdata = [
id=45,
name='字典增加',
type='2',
code='admin:dict:add',
code='system:dict:add',
url='',
open_type='',
parent_id='44',
@@ -420,7 +420,7 @@ powerdata = [
id=46,
name='字典修改',
type='2',
code='admin:dict:edit',
code='system:dict:edit',
url='',
open_type='',
parent_id='44',
@@ -433,7 +433,7 @@ powerdata = [
id=47,
name='字典删除',
type='2',
code='admin:dict:remove',
code='system:dict:remove',
url='',
open_type='',
parent_id='44',
@@ -446,8 +446,8 @@ powerdata = [
id=48,
name='部门管理',
type='1',
code='admin:dept:main',
url='/dept',
code='system:dept:main',
url='/system/dept',
open_type='_iframe',
parent_id='1',
icon='layui-icon layui-icon-group',
@@ -459,7 +459,7 @@ powerdata = [
id=49,
name='部门增加',
type='2',
code='admin:dept:add',
code='system:dept:add',
url='',
open_type='',
parent_id='48',
@@ -472,7 +472,7 @@ powerdata = [
id=50,
name='部门编辑',
type='2',
code='admin:dept:edit',
code='system:dept:edit',
url='',
open_type='',
parent_id='48',
@@ -485,7 +485,7 @@ powerdata = [
id=51,
name='部门删除',
type='2',
code='admin:dept:remove',
code='system:dept:remove',
url='',
open_type='',
parent_id='48',
@@ -498,8 +498,8 @@ powerdata = [
id=57,
name='邮件管理',
type='1',
code='admin:mail:main',
url='/admin/mail',
code='system:mail:main',
url='/system/mail',
open_type='_iframe',
parent_id='1',
icon='layui-icon ',
@@ -511,7 +511,7 @@ powerdata = [
id=58,
name='邮件发送',
type='2',
code='admin:mail:add',
code='system:mail:add',
url='',
open_type='',
parent_id='57',
@@ -524,7 +524,7 @@ powerdata = [
id=59,
name='邮件删除',
type='2',
code='admin:mail:remove',
code='system:mail:remove',
url='',
open_type='',
parent_id='57',
@@ -572,4 +572,4 @@ def init_db():
print("用户角色数据存入")
add_role_power()
print("角色权限数据存入")
print("数据初始化完成,请使用python app.py命令运行")
print("数据初始化完成,请使用run脚本运行")
+11 -10
View File
@@ -1,5 +1,5 @@
import logging
from urllib.parse import quote_plus as urlquote
# from urllib.parse import quote_plus as urlquote
class BaseConfig:
@@ -32,17 +32,18 @@ class BaseConfig:
# JSON配置
JSON_AS_ASCII = False
SECRET_KEY = "pear-admin-flask"
SECRET_KEY = "pear-system-flask"
# mysql 配置
MYSQL_USERNAME = "root"
MYSQL_PASSWORD = "123456"
MYSQL_HOST = "127.0.0.1"
MYSQL_PORT = 3306
MYSQL_DATABASE = "PearAdminFlask"
# MYSQL_USERNAME = "root"
# MYSQL_PASSWORD = "123456"
# MYSQL_HOST = "127.0.0.1"
# MYSQL_PORT = 3306
# MYSQL_DATABASE = "PearAdminFlask"
# mysql 数据库的配置信息
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{urlquote(MYSQL_PASSWORD)}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}?charset=utf8mb4"
# 数据库的配置信息
SQLALCHEMY_DATABASE_URI = 'sqlite:///../pear.db'
# SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{urlquote(MYSQL_PASSWORD)}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}?charset=utf8mb4"
# 默认日志等级
LOG_LEVEL = logging.WARN
@@ -61,7 +62,7 @@ class BaseConfig:
# 配置多个数据库连接的连接串写法示例
# HOSTNAME: 指数据库的IP地址、USERNAME:指数据库登录的用户名、PASSWORD:指数据库登录密码、PORT:指数据库开放的端口、DATABASE:指需要连接的数据库名称
# MSSQL: f"mssql+pymssql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=cp936"
# MySQL: f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8"
# MySQL: f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
# Oracle: f"oracle+cx_oracle://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
# SQLite "sqlite:/// database.db"
# Postgres f"postgresql+psycopg2://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
+2 -21
View File
@@ -1,4 +1,4 @@
from flask import render_template, jsonify
from flask import render_template
def init_error_views(app):
@@ -12,23 +12,4 @@ def init_error_views(app):
@app.errorhandler(500)
def internal_server_error(e):
return render_template('errors/500.html'), 500
# Return validation errors as JSON
@app.errorhandler(422)
@app.errorhandler(400)
def handle_error(err):
headers = err.data.get("headers", None)
messages = err.data.get("messages", ["Invalid request."]).get('json')
print(err.data.get("messages"))
print(messages.items())
msg = ''
for i in messages.items():
msg = str(i[0]) + str(i[1][0])
break
if headers:
return jsonify({"success": False, "msg": msg})
else:
return jsonify({"success": False, "msg": msg})
return render_template('errors/500.html'), 500
+1 -2
View File
@@ -5,8 +5,7 @@ def init_login_manager(app):
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'passport.login'
login_manager.login_message = u'请登录以访问此页面'
login_manager.login_view = 'system.passport.login'
@login_manager.user_loader
def load_user(user_id):
+1 -1
View File
@@ -9,7 +9,7 @@ class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
username = db.Column(db.String(20), comment='用户名')
realname = db.Column(db.String(20), comment='真实名字')
avatar = db.Column(db.String(255), comment='头像', default="/static/admin/admin/images/avatar.jpg")
avatar = db.Column(db.String(255), comment='头像', default="/static/system/admin/images/avatar.jpg")
remark = db.Column(db.String(255), comment='备注')
password_hash = db.Column(db.String(128), comment='哈希密码')
enable = db.Column(db.Integer, default=0, comment='启用')
+1 -1
View File
@@ -2,7 +2,7 @@
from .admin_role import RoleOutSchema
from .admin_power import PowerOutSchema, PowerOutSchema2
from .admin_dict import DictDataOutSchema, DictTypeOutSchema
from .admin_dept import DeptOutSchema
from .admin_dept import DeptSchema
from .admin_log import LogOutSchema
from .admin_photo import PhotoOutSchema
from .admin_mail import MailOutSchema
+10 -23
View File
@@ -1,25 +1,12 @@
from applications.extensions import ma
from marshmallow import fields, validate
from flask_marshmallow.sqla import SQLAlchemyAutoSchema
from applications.models import Dept
class DeptInSchema(ma.Schema):
parentId = fields.Integer(required=True)
deptName = fields.Str(required=True)
leader = fields.Str(required=True)
phone = fields.Str(required=True)
email = fields.Str(validate=validate.Email())
address = fields.Str()
status = fields.Str(validate=validate.OneOf(["0", "1"]))
sort = fields.Integer()
class DeptOutSchema(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()
class DeptSchema(SQLAlchemyAutoSchema):
class Meta:
model = Dept # table = models.Album.__table__
# include_relationships = True # 输出模型对象时同时对外键,是否也一并进行处理
include_fk = True # 序列化阶段是否也一并返回主键
# fields= ["id","name"] # 启动的字段列表
# exclude = ["id","name"] # 排除字段列表
+12
View File
@@ -1,6 +1,18 @@
from flask_marshmallow.sqla import SQLAlchemyAutoSchema
from applications.extensions import ma
from marshmallow import fields
from applications.models import Power
class PowerSchema(SQLAlchemyAutoSchema):
class Meta:
model = Power # table = models.Album.__table__
# include_relationships = True # 输出模型对象时同时对外键,是否也一并进行处理
include_fk = True # 序列化阶段是否也一并返回主键
# fields= ["id","name"] # 启动的字段列表
# exclude = ["id","name"] # 排除字段列表
# 权限models序列化类
class PowerOutSchema(ma.Schema):
+10 -12
View File
@@ -1,14 +1,12 @@
from applications.extensions import ma
from marshmallow import fields
from flask_marshmallow.sqla import SQLAlchemyAutoSchema
from applications.models import Role
class RoleOutSchema(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()
class RoleOutSchema(SQLAlchemyAutoSchema):
class Meta:
model = Role # table = models.Album.__table__
# include_relationships = True # 输出模型对象时同时对外键,是否也一并进行处理
include_fk = True # 序列化阶段是否也一并返回主键
# fields= ["id","name"] # 启动的字段列表
# exclude = ["id","name"] # 排除字段列表
+4 -11
View File
@@ -1,14 +1,7 @@
from applications.view.admin import register_admin_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
from applications.view.department import register_dept_views
from applications.view.system import register_system_bps
from applications.view.plugin import register_plugin_views
def init_view(app):
register_admin_views(app)
register_index_views(app)
register_rights_view(app)
register_passport_views(app)
register_dept_views(app)
def init_bps(app):
register_system_bps(app)
register_plugin_views(app)
-23
View File
@@ -1,23 +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
from applications.view.admin.mail import admin_mail
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)
app.register_blueprint(admin_mail)
-19
View File
@@ -1,19 +0,0 @@
from flask import Blueprint, render_template
from flask_login import login_required, current_user
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
# 首页
@admin_bp.get('/')
@login_required
def index():
user = current_user
return render_template('admin/index.html', user=user)
# 控制台页面
@admin_bp.get('/welcome')
@login_required
def welcome():
return render_template('admin/console/console.html')
-12
View File
@@ -1,12 +0,0 @@
from applications.view.index.index import index_bp
from . import index
def register_index_views(app):
"""
初始化蓝图
"""
app.register_blueprint(index_bp)
-8
View File
@@ -1,8 +0,0 @@
from flask import render_template, Blueprint
index_bp = Blueprint('Index', __name__, url_prefix='/')
@index_bp.route('/')
def index():
return render_template('index/index.html')
+2 -2
View File
@@ -17,7 +17,7 @@ def configs():
# 网站名称
"title": current_app.config.get("SYSTEM_NAME"),
# 网站图标
"image": "/static/admin/admin/images/logo.png"
"image": "/static/system/system/images/logo.png"
# 菜单配置
}, menu={
# 菜单数据来源
@@ -47,7 +47,7 @@ def configs():
# 标识 ID , 建议与菜单项中的 ID 一致
"id": "10",
# 页面地址
"href": "/admin/welcome",
"href": "/system/welcome",
# 标题
"title": "首页"
}
+34
View File
@@ -0,0 +1,34 @@
from flask import Flask, Blueprint
from applications.view.system.dict import bp as dict_bp
from applications.view.system.file import bp as file_bp
from applications.view.system.index import bp as index_bp
from applications.view.system.log import bp as log_bp
from applications.view.system.mail import bp as mail_bp
from applications.view.system.monitor import bp as monitor_bp
from applications.view.system.passport import bp as passport_bp
from applications.view.system.power import bp as power_bp
from applications.view.system.rights import bp as right_bp
from applications.view.system.role import bp as role_bp
from applications.view.system.user import bp as user_bp
from applications.view.system.dept import bp as dept_bp
# 创建sys
system_bp = Blueprint('system', __name__, url_prefix='/system')
def register_system_bps(app: Flask):
# 在admin_bp下注册子蓝图
system_bp.register_blueprint(user_bp)
system_bp.register_blueprint(file_bp)
system_bp.register_blueprint(monitor_bp)
system_bp.register_blueprint(log_bp)
system_bp.register_blueprint(power_bp)
system_bp.register_blueprint(role_bp)
system_bp.register_blueprint(dict_bp)
system_bp.register_blueprint(mail_bp)
system_bp.register_blueprint(passport_bp)
system_bp.register_blueprint(right_bp)
system_bp.register_blueprint(dept_bp)
app.register_blueprint(index_bp)
app.register_blueprint(system_bp)
@@ -7,43 +7,38 @@ from applications.common.utils.rights import authorize
from applications.common.utils.validate import str_escape
from applications.extensions import db
from applications.models import Dept, User
from applications.schemas import DeptOutSchema
from applications.schemas import DeptSchema
dept_bp = Blueprint('dept', __name__, url_prefix='/dept')
bp = Blueprint('dept', __name__, url_prefix='/dept')
def register_dept_views(app):
app.register_blueprint(dept_bp)
@dept_bp.get('/')
@authorize("admin:dept:main", log=True)
@bp.get('/')
@authorize("system:dept:main", log=True)
def main():
return render_template('admin/dept/main.html')
return render_template('system/dept/main.html')
@dept_bp.post('/data')
@authorize("admin:dept:main", log=True)
@bp.post('/data')
@authorize("system:dept:main", log=True)
def data():
dept = Dept.query.order_by(Dept.sort).all()
power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept)
data = Dept.query.order_by(Dept.sort).all()
res = {
"data": power_data
"data": DeptSchema(many=True).dump(data)
}
return jsonify(res)
@dept_bp.get('/add')
@authorize("admin:dept:add", log=True)
@bp.get('/add')
@authorize("system:dept:add", log=True)
def add():
return render_template('admin/dept/add.html')
return render_template('system/dept/add.html')
@dept_bp.get('/tree')
@authorize("admin:dept:main", log=True)
@bp.get('/tree')
@authorize("system:dept:main", log=True)
def tree():
dept = Dept.query.order_by(Dept.sort).all()
power_data = curd.model_to_dicts(schema=DeptOutSchema, data=dept)
power_data = curd.model_to_dicts(schema=DeptSchema, data=dept)
res = {
"status": {"code": 200, "message": "默认"},
"data": power_data
@@ -52,8 +47,8 @@ def tree():
return jsonify(res)
@dept_bp.post('/save')
@authorize("admin:dept:add", log=True)
@bp.post('/save')
@authorize("system:dept:add", log=True)
def save():
req_json = request.get_json(force=True)
dept = Dept(
@@ -71,17 +66,17 @@ def save():
return success_api(msg="成功")
@dept_bp.get('/edit')
@authorize("admin:dept:edit", log=True)
@bp.get('/edit')
@authorize("system:dept:edit", log=True)
def edit():
_id = request.args.get("deptId")
dept = curd.get_one_by_id(model=Dept, id=_id)
return render_template('admin/dept/edit.html', dept=dept)
return render_template('system/dept/edit.html', dept=dept)
# 启用
@dept_bp.put('/enable')
@authorize("admin:dept:edit", log=True)
@bp.put('/enable')
@authorize("system:dept:edit", log=True)
def enable():
id = request.get_json(force=True).get('deptId')
if id:
@@ -95,8 +90,8 @@ def enable():
# 禁用
@dept_bp.put('/disable')
@authorize("admin:dept:edit", log=True)
@bp.put('/disable')
@authorize("system:dept:edit", log=True)
def dis_enable():
id = request.get_json(force=True).get('deptId')
if id:
@@ -109,8 +104,8 @@ def dis_enable():
return fail_api(msg="数据错误")
@dept_bp.put('/update')
@authorize("admin:dept:edit", log=True)
@bp.put('/update')
@authorize("system:dept:edit", log=True)
def update():
json = request.get_json(force=True)
id = json.get("deptId"),
@@ -130,8 +125,8 @@ def update():
return success_api(msg="更新成功")
@dept_bp.delete('/remove/<int:_id>')
@authorize("admin:dept:remove", log=True)
@bp.delete('/remove/<int:_id>')
@authorize("system:dept:remove", log=True)
def remove(_id):
d = Dept.query.filter_by(id=_id).delete()
if not d:
@@ -9,18 +9,18 @@ from applications.extensions import db
from applications.models import DictType, DictData
from applications.schemas import DictTypeOutSchema, DictDataOutSchema
admin_dict = Blueprint('adminDict', __name__, url_prefix='/admin/dict')
bp = Blueprint('dict', __name__, url_prefix='/dict')
# 数据字典
@admin_dict.get('/')
@authorize("admin:dict:main")
@bp.get('/')
@authorize("system:dict:main")
def main():
return render_template('admin/dict/main.html')
return render_template('system/dict/main.html')
@admin_dict.get('/dictType/data')
@authorize("admin:dict:main")
@bp.get('/dictType/data')
@authorize("system:dict:main")
def dict_type_data():
# 获取请求参数
type_name = str_escape(request.args.get('typeName', type=str))
@@ -36,14 +36,14 @@ def dict_type_data():
return table_api(data=data, count=count)
@admin_dict.get('/dictType/add')
@authorize("admin:dict:add", log=True)
@bp.get('/dictType/add')
@authorize("system:dict:add", log=True)
def dict_type_add():
return render_template('admin/dict/add.html')
return render_template('system/dict/add.html')
@admin_dict.post('/dictType/save')
@authorize("admin:dict:add", log=True)
@bp.post('/dictType/save')
@authorize("system:dict:add", log=True)
def dict_type_save():
req_json = request.get_json(force=True)
description = str_escape(req_json.get("description"))
@@ -59,17 +59,17 @@ def dict_type_save():
# 编辑字典类型
@admin_dict.get('/dictType/edit')
@authorize("admin:dict:edit", log=True)
@bp.get('/dictType/edit')
@authorize("system: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)
return render_template('system/dict/edit.html', dict_type=dict_type)
# 编辑字典类型
@admin_dict.put('/dictType/update')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictType/update')
@authorize("system:dict:edit", log=True)
def dict_type_update():
req_json = request.get_json(force=True)
id = str_escape(req_json.get("id"))
@@ -88,8 +88,8 @@ def dict_type_update():
# 启用字典
@admin_dict.put('/dictType/enable')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictType/enable')
@authorize("system:dict:edit", log=True)
def dict_type_enable():
_id = request.get_json(force=True).get('id')
if id:
@@ -101,8 +101,8 @@ def dict_type_enable():
# 禁用字典
@admin_dict.put('/dictType/disable')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictType/disable')
@authorize("system:dict:edit", log=True)
def dict_type_dis_enable():
_id = request.get_json(force=True).get('id')
if id:
@@ -114,8 +114,8 @@ def dict_type_dis_enable():
# 删除字典类型
@admin_dict.delete('/dictType/remove/<int:_id>')
@authorize("admin:dict:remove", log=True)
@bp.delete('/dictType/remove/<int:_id>')
@authorize("system:dict:remove", log=True)
def dict_type_delete(_id):
res = curd.delete_one_by_id(DictType,_id)
if not res:
@@ -123,8 +123,8 @@ def dict_type_delete(_id):
return success_api(msg="删除成功")
@admin_dict.get('/dictData/data')
@authorize("admin:dict:main", log=True)
@bp.get('/dictData/data')
@authorize("system:dict:main", log=True)
def dict_code_data():
type_code = str_escape(request.args.get('typeCode', type=str))
dict_data = DictData.query.filter_by(type_code=type_code).layui_paginate()
@@ -134,16 +134,16 @@ def dict_code_data():
# 增加字典数据
@admin_dict.get('/dictData/add')
@authorize("admin:dict:add", log=True)
@bp.get('/dictData/add')
@authorize("system: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)
return render_template('system/dict/data/add.html', type_code=type_code)
# 增加字典数据
@admin_dict.post('/dictData/save')
@authorize("admin:dict:add", log=True)
@bp.post('/dictData/save')
@authorize("system:dict:add", log=True)
def dict_data_save():
req_json = request.get_json(force=True)
data_label = str_escape(req_json.get("dataLabel"))
@@ -160,17 +160,17 @@ def dict_data_save():
# 编辑字典数据
@admin_dict.get('/dictData/edit')
@authorize("admin:dict:edit", log=True)
@bp.get('/dictData/edit')
@authorize("system:dict:edit", log=True)
def dict_data_edit():
_id = request.args.get('dataId', type=str)
dict_data = curd.get_one_by_id(DictData, _id)
return render_template('admin/dict/data/edit.html', dict_data=dict_data)
return render_template('system/dict/data/edit.html', dict_data=dict_data)
# 编辑字典数据
@admin_dict.put('/dictData/update')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictData/update')
@authorize("system:dict:edit", log=True)
def dict_data_update():
req_json = request.get_json(force=True)
id = req_json.get("dataId")
@@ -186,8 +186,8 @@ def dict_data_update():
# 启用字典数据
@admin_dict.put('/dictData/enable')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictData/enable')
@authorize("system:dict:edit", log=True)
def dict_data_enable():
_id = request.get_json(force=True).get('dataId')
if _id:
@@ -199,8 +199,8 @@ def dict_data_enable():
# 禁用字典数据
@admin_dict.put('/dictData/disable')
@authorize("admin:dict:edit", log=True)
@bp.put('/dictData/disable')
@authorize("system:dict:edit", log=True)
def dict_data_disenable():
_id = request.get_json(force=True).get('dataId')
if _id:
@@ -212,8 +212,8 @@ def dict_data_disenable():
# 删除字典类型
@admin_dict.delete('dictData/remove/<int:id>')
@authorize("admin:dict:remove", log=True)
@bp.delete('dictData/remove/<int:id>')
@authorize("system:dict:remove", log=True)
def dict_data_delete(id):
res = curd.delete_one_by_id(model=DictData, id=id)
if not res:
@@ -7,19 +7,19 @@ from applications.extensions import db
from applications.models import Photo
from applications.common.utils import upload as upload_curd
admin_file = Blueprint('adminFile', __name__, url_prefix='/admin/file')
bp = Blueprint('adminFile', __name__, url_prefix='/file')
# 图片管理
@admin_file.get('/')
@authorize("admin:file:main")
@bp.get('/')
@authorize("system:file:main")
def index():
return render_template('admin/photo/photo.html')
return render_template('system/photo/photo.html')
# 图片数据
@admin_file.get('/table')
@authorize("admin:file:main")
@bp.get('/table')
@authorize("system:file:main")
def table():
page = request.args.get('page', type=int)
limit = request.args.get('limit', type=int)
@@ -28,15 +28,15 @@ def table():
# 上传
@admin_file.get('/upload')
@authorize("admin:file:add", log=True)
@bp.get('/upload')
@authorize("system:file:add", log=True)
def upload():
return render_template('admin/photo/photo_add.html')
return render_template('system/photo/photo_add.html')
# 上传接口
@admin_file.post('/upload')
@authorize("admin:file:add", log=True)
@bp.post('/upload')
@authorize("system:file:add", log=True)
def upload_api():
if 'file' in request.files:
photo = request.files['file']
@@ -55,8 +55,8 @@ def upload_api():
# 图片删除
@admin_file.route('/delete', methods=['GET', 'POST'])
@authorize("admin:file:delete", log=True)
@bp.route('/delete', methods=['GET', 'POST'])
@authorize("system:file:delete", log=True)
def delete():
_id = request.form.get('id')
res = upload_curd.delete_photo_by_id(_id)
@@ -67,8 +67,8 @@ def delete():
# 图片批量删除
@admin_file.route('/batchRemove', methods=['GET', 'POST'])
@authorize("admin:file:delete", log=True)
@bp.route('/batchRemove', methods=['GET', 'POST'])
@authorize("system:file:delete", log=True)
def batch_remove():
ids = request.form.getlist('ids[]')
photo_name = Photo.query.filter(Photo.id.in_(ids)).all()
+14
View File
@@ -0,0 +1,14 @@
from flask import Blueprint, render_template
from flask_login import login_required, current_user
bp = Blueprint('index', __name__, url_prefix='/')
# 首页
@bp.get('/')
@login_required
def index():
user = current_user
return render_template('system/index.html', user=user)
@@ -6,21 +6,19 @@ from applications.models import AdminLog
from applications.schemas import LogOutSchema
from applications.common.curd import model_to_dicts
admin_log = Blueprint('adminLog', __name__, url_prefix='/admin/log')
bp = Blueprint('log', __name__, url_prefix='/log')
# 日志管理
@admin_log.get('/')
@authorize("admin:log:main")
@bp.get('/')
@authorize("system:log:main")
def index():
from markupsafe import escape
escape
return render_template('admin/admin_log/main.html')
return render_template('system/admin_log/main.html')
# 登录日志
@admin_log.get('/loginLog')
@authorize("admin:log:main")
@bp.get('/loginLog')
@authorize("system:log:main")
def login_log():
# orm查询
# 使用分页获取data需要.items
@@ -30,8 +28,8 @@ def login_log():
# 操作日志
@admin_log.get('/operateLog')
@authorize("admin:log:main")
@bp.get('/operateLog')
@authorize("system:log:main")
def operate_log():
# orm查询
# 使用分页获取data需要.items
@@ -10,19 +10,19 @@ from applications.extensions import db, flask_mail
from applications.models import Mail
from applications.schemas import MailOutSchema
admin_mail = Blueprint('adminMail', __name__, url_prefix='/admin/mail')
bp = Blueprint('adminMail', __name__, url_prefix='/mail')
# 用户管理
@admin_mail.get('/')
@authorize("admin:mail:main")
@bp.get('/')
@authorize("system:mail:main")
def main():
return render_template('admin/mail/main.html')
return render_template('system/mail/main.html')
# 用户分页查询
@admin_mail.get('/data')
@authorize("admin:mail:main")
@bp.get('/data')
@authorize("system:mail:main")
def data():
# 获取请求参数
receiver = str_escape(request.args.get("receiver"))
@@ -45,14 +45,14 @@ def data():
# 用户增加
@admin_mail.get('/add')
@authorize("admin:mail:add", log=True)
@bp.get('/add')
@authorize("system:mail:add", log=True)
def add():
return render_template('admin/mail/add.html')
return render_template('system/mail/add.html')
@admin_mail.post('/save')
@authorize("admin:mail:add", log=True)
@bp.post('/save')
@authorize("system:mail:add", log=True)
def save():
req_json = request.get_json(force=True)
receiver = str_escape(req_json.get("receiver"))
@@ -75,8 +75,8 @@ def save():
# 删除用户
@admin_mail.delete('/remove/<int:id>')
@authorize("admin:mail:remove", log=True)
@bp.delete('/remove/<int:id>')
@authorize("system:mail:remove", log=True)
def delete(id):
res = Mail.query.filter_by(id=id).delete()
if not res:
@@ -86,8 +86,8 @@ def delete(id):
# 批量删除
@admin_mail.delete('/batchRemove')
@authorize("admin:mail:remove", log=True)
@bp.delete('/batchRemove')
@authorize("system:mail:remove", log=True)
def batch_remove():
ids = request.form.getlist('ids[]')
for id in ids:
@@ -8,12 +8,12 @@ from datetime import datetime
from flask import Blueprint, render_template, jsonify
from applications.common.utils.rights import authorize
admin_monitor_bp = Blueprint('adminMonitor', __name__, url_prefix='/admin/monitor')
bp = Blueprint('adminMonitor', __name__, url_prefix='/monitor')
# 系统监控
@admin_monitor_bp.get('/')
@authorize("admin:monitor:main")
@bp.get('/')
@authorize("system:monitor:main")
def main():
# 主机名称
hostname = platform.node()
@@ -58,7 +58,7 @@ def main():
# 当前时间
time_now = time.strftime('%H:%M:%S ', time.localtime(time.time()))
return render_template('admin/monitor.html',
return render_template('system/monitor.html',
hostname=hostname,
system_version=system_version,
python_version=python_version,
@@ -77,8 +77,8 @@ def main():
# 图表 api
@admin_monitor_bp.get('/polling')
@authorize("admin:monitor:main")
@bp.get('/polling')
@authorize("system:monitor:main")
def ajax_polling():
# 获取cpu使用率
cpus_percent = psutil.cpu_percent(interval=0.1, percpu=False) # percpu 获取主使用率
@@ -88,11 +88,12 @@ def ajax_polling():
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)
# 关闭程序
@admin_monitor_bp.get('/kill')
@authorize("admin:monitor:main")
@bp.get('/kill')
@authorize("system:monitor:main")
def kill():
for proc in psutil.process_iter():
if proc.pid == os.getpid():
proc.kill()
sys.exit(1)
sys.exit(1)
@@ -6,15 +6,13 @@ from applications.common.admin_log import login_log
from applications.common.utils.http import fail_api, success_api
from applications.models import User
passport_bp = Blueprint('passport', __name__, url_prefix='/passport')
bp = Blueprint('passport', __name__, url_prefix='/passport')
def register_passport_views(app):
app.register_blueprint(passport_bp)
# 获取验证码
@passport_bp.get('/getCaptcha')
@bp.get('/getCaptcha')
def get_captcha():
resp, code = index_curd.get_captcha()
session["code"] = code
@@ -22,15 +20,15 @@ def get_captcha():
# 登录
@passport_bp.get('/login')
@bp.get('/login')
def login():
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
return render_template('admin/login.html')
return redirect(url_for('system.index'))
return render_template('system/login.html')
# 登录
@passport_bp.post('/login')
@bp.post('/login')
def login_post():
req = request.form
username = req.get('username')
@@ -83,7 +81,7 @@ def login_post():
# 退出登录
@passport_bp.post('/logout')
@bp.post('/logout')
@login_required
def logout():
logout_user()
@@ -7,34 +7,35 @@ from applications.common.utils.validate import str_escape
from applications.extensions import db
from applications.models import Power
from applications.schemas import PowerOutSchema2
from applications.schemas.admin_power import PowerSchema
admin_power = Blueprint('adminPower', __name__, url_prefix='/admin/power')
bp = Blueprint('power', __name__, url_prefix='/power')
@admin_power.get('/')
@authorize("admin:power:main")
@bp.get('/')
@authorize("system:power:main")
def index():
return render_template('admin/power/main.html')
return render_template('system/power/main.html')
@admin_power.post('/data')
@authorize("admin:power:main")
@bp.post('/data')
@authorize("system:power:main")
def data():
power = Power.query.all()
res = {
"data": curd.model_to_dicts(schema=PowerOutSchema2, data=power)
"data": PowerSchema(many=True).dump(power)
}
return jsonify(res)
@admin_power.get('/add')
@authorize("admin:power:add", log=True)
@bp.get('/add')
@authorize("system:power:add", log=True)
def add():
return render_template('admin/power/add.html')
return render_template('system/power/add.html')
@admin_power.get('/selectParent')
@authorize("admin:power:main", log=True)
@bp.get('/selectParent')
@authorize("system:power:main", log=True)
def select_parent():
power = Power.query.all()
res = curd.model_to_dicts(schema=PowerOutSchema2, data=power)
@@ -48,8 +49,8 @@ def select_parent():
# 增加
@admin_power.post('/save')
@authorize("admin:power:add", log=True)
@bp.post('/save')
@authorize("system:power:add", log=True)
def save():
req = request.get_json(force=True)
icon = str_escape(req.get("icon"))
@@ -77,8 +78,8 @@ def save():
# 权限编辑
@admin_power.get('/edit/<int:_id>')
@authorize("admin:power:edit", log=True)
@bp.get('/edit/<int:_id>')
@authorize("system:power:edit", log=True)
def edit(_id):
power = curd.get_one_by_id(Power, _id)
icon = str(power.icon).split()
@@ -86,12 +87,12 @@ def edit(_id):
icon = icon[1]
else:
icon = None
return render_template('admin/power/edit.html', power=power, icon=icon)
return render_template('system/power/edit.html', power=power, icon=icon)
# 权限更新
@admin_power.put('/update')
@authorize("admin:power:edit", log=True)
@bp.put('/update')
@authorize("system:power:edit", log=True)
def update():
req_json = request.get_json(force=True)
id = request.get_json(force=True).get("powerId")
@@ -113,8 +114,8 @@ def update():
# 启用权限
@admin_power.put('/enable')
@authorize("admin:power:edit", log=True)
@bp.put('/enable')
@authorize("system:power:edit", log=True)
def enable():
_id = request.get_json(force=True).get('powerId')
if id:
@@ -126,8 +127,8 @@ def enable():
# 禁用权限
@admin_power.put('/disable')
@authorize("admin:power:edit", log=True)
@bp.put('/disable')
@authorize("system:power:edit", log=True)
def dis_enable():
_id = request.get_json(force=True).get('powerId')
if id:
@@ -139,8 +140,8 @@ def dis_enable():
# 权限删除
@admin_power.delete('/remove/<int:id>')
@authorize("admin:power:remove", log=True)
@bp.delete('/remove/<int:id>')
@authorize("system:power:remove", log=True)
def remove(id):
power = Power.query.filter_by(id=id).first()
power.role = []
@@ -150,18 +151,4 @@ def remove(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[]')
for id in ids:
power = Power.query.filter_by(id=id).first()
power.role = []
r = Power.query.filter_by(id=id).delete()
db.session.commit()
return success_api(msg="批量删除成功")
return fail_api(msg="删除失败")
+154
View File
@@ -0,0 +1,154 @@
import copy
from collections import OrderedDict
from flask import jsonify, current_app, Blueprint, render_template
from flask_login import login_required, current_user
from ...models import Power
from ...schemas import PowerOutSchema
bp = Blueprint('rights', __name__, url_prefix='/rights')
# 渲染配置
@bp.get('/configs')
@login_required
def configs():
# 网站配置
config = dict(logo={
# 网站名称
"title": current_app.config.get("SYSTEM_NAME"),
# 网站图标
"image": "/static/system/admin/images/logo.png"
# 菜单配置
}, menu={
# 菜单数据来源
"data": "/system/rights/menu",
"collaspe": False,
# 是否同时只打开一个菜单目录
"accordion": True,
"method": "GET",
# 是否开启多系统菜单模式
"control": False,
# 顶部菜单宽度 PX
"controlWidth": 500,
# 默认选中的菜单项
"select": "0",
# 是否开启异步菜单,false 时 data 属性设置为菜单数据,false 时为 json 文件或后端接口
"async": True
}, tab={
# 是否开启多选项卡
"enable": True,
# 切换选项卡时,是否刷新页面状态
"keepState": True,
# 是否开启 Tab 记忆
"session": True,
# 最大可打开的选项卡数量
"max": 30,
"index": {
# 标识 ID , 建议与菜单项中的 ID 一致
"id": "10",
# 页面地址
"href": "/system/rights/welcome",
# 标题
"title": "首页"
}
}, theme={
# 默认主题色,对应 colors 配置中的 ID 标识
"defaultColor": "2",
# 默认的菜单主题 dark-theme 黑 / light-theme 白
"defaultMenu": "dark-theme",
# 是否允许用户切换主题,false 时关闭自定义主题面板
"allowCustom": True
}, colors=[{
"id": "1",
"color": "#2d8cf0"
},
{
"id": "2",
"color": "#5FB878"
},
{
"id": "3",
"color": "#1E9FFF"
}, {
"id": "4",
"color": "#FFB800"
}, {
"id": "5",
"color": "darkgray"
}
], links=current_app.config.get("SYSTEM_PANEL_LINKS"), other={
# 主页动画时长
"keepLoad": 0,
# 布局顶部主题
"autoHead": False
}, header=False)
return jsonify(config)
# 菜单
@bp.get('/menu')
@login_required
def menu():
if current_user.username != current_app.config.get("SUPERADMIN"):
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 int(p.type) in [0, 1] and p not in powers:
powers.append(p)
power_schema = PowerOutSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
power_dict = power_schema.dump(powers) # 生成可序列化对象
power_dict.sort(key=lambda x: (x['parent_id'], x['id']), reverse=True)
menu_dict = OrderedDict()
for _dict in power_dict:
if _dict['id'] in menu_dict:
# 当前节点添加子节点
_dict['children'] = copy.deepcopy(menu_dict[_dict['id']])
_dict['children'].sort(key=lambda item: item['sort'])
# 删除子节点
del menu_dict[_dict['id']]
if _dict['parent_id'] not in menu_dict:
menu_dict[_dict['parent_id']] = [_dict]
else:
menu_dict[_dict['parent_id']].append(_dict)
return jsonify(sorted(menu_dict.get(0), key=lambda item: item['sort']))
else:
powers = Power.query.all()
power_schema = PowerOutSchema(many=True) # 用已继承 ma.ModelSchema 类的自定制类生成序列化类
power_dict = power_schema.dump(powers) # 生成可序列化对象
power_dict.sort(key=lambda x: (x['parent_id'], x['id']), reverse=True)
menu_dict = OrderedDict()
for _dict in power_dict:
if _dict['id'] in menu_dict:
# 当前节点添加子节点
_dict['children'] = copy.deepcopy(menu_dict[_dict['id']])
_dict['children'].sort(key=lambda item: item['sort'])
# 删除子节点
del menu_dict[_dict['id']]
if _dict['parent_id'] not in menu_dict:
menu_dict[_dict['parent_id']] = [_dict]
else:
menu_dict[_dict['parent_id']].append(_dict)
return jsonify(sorted(menu_dict.get(0), key=lambda item: item['sort']))
# 控制台页面
@bp.get('/welcome')
@login_required
def welcome():
return render_template('system/console/console.html')
@@ -8,19 +8,19 @@ from applications.common.utils.validate import str_escape
from applications.extensions import db
from applications.models import Role, Power, User
from applications.schemas import RoleOutSchema, PowerOutSchema2
admin_role = Blueprint('adminRole', __name__, url_prefix='/admin/role')
bp = Blueprint('role', __name__, url_prefix='/role')
# 用户管理
@admin_role.get('/')
@authorize("admin:role:main")
@bp.get('/')
@authorize("system:role:main")
def main():
return render_template('admin/role/main.html')
return render_template('system/role/main.html')
# 表格数据
@admin_role.get('/data')
@authorize("admin:role:main")
@bp.get('/data')
@authorize("system:role:main")
def table():
role_name = str_escape(request.args.get('roleName', type=str))
role_code = str_escape(request.args.get('roleCode', type=str))
@@ -30,19 +30,19 @@ def table():
if role_code:
filters.append(Role.code.contains(role_code))
roles = Role.query.filter(*filters).layui_paginate()
return table_api(data=model_to_dicts(schema=RoleOutSchema, data=roles.items), count=roles.total)
return table_api(data=RoleOutSchema(many=True).dump(roles), count=roles.total)
# 角色增加
@admin_role.get('/add')
@authorize("admin:role:add", log=True)
@bp.get('/add')
@authorize("system:role:add", log=True)
def add():
return render_template('admin/role/add.html')
return render_template('system/role/add.html')
# 角色增加
@admin_role.post('/save')
@authorize("admin:role:add", log=True)
@bp.post('/save')
@authorize("system:role:add", log=True)
def save():
req = request.get_json(force=True)
details = str_escape(req.get("details"))
@@ -63,15 +63,15 @@ def save():
# 角色授权
@admin_role.get('/power/<int:_id>')
@authorize("admin:role:power", log=True)
@bp.get('/power/<int:_id>')
@authorize("system:role:power", log=True)
def power(_id):
return render_template('admin/role/power.html', id=_id)
return render_template('system/role/power.html', id=_id)
# 获取角色权限
@admin_role.get('/getRolePower/<int:id>')
@authorize("admin:role:main", log=True)
@bp.get('/getRolePower/<int:id>')
@authorize("system:role:main", log=True)
def get_role_power(id):
role = Role.query.filter_by(id=id).first()
check_powers = role.power
@@ -94,8 +94,8 @@ def get_role_power(id):
# 保存角色权限
@admin_role.put('/saveRolePower')
@authorize("admin:role:edit", log=True)
@bp.put('/saveRolePower')
@authorize("system:role:edit", log=True)
def save_role_power():
req_form = request.form
power_ids = req_form.get("powerIds")
@@ -111,16 +111,16 @@ def save_role_power():
# 角色编辑
@admin_role.get('/edit/<int:id>')
@authorize("admin:role:edit", log=True)
@bp.get('/edit/<int:id>')
@authorize("system:role:edit", log=True)
def edit(id):
r = get_one_by_id(model=Role, id=id)
return render_template('admin/role/edit.html', role=r)
return render_template('system/role/edit.html', role=r)
# 更新角色
@admin_role.put('/update')
@authorize("admin:role:edit", log=True)
@bp.put('/update')
@authorize("system:role:edit", log=True)
def update():
req_json = request.get_json(force=True)
id = req_json.get("roleId")
@@ -139,8 +139,8 @@ def update():
# 启用用户
@admin_role.put('/enable')
@authorize("admin:role:edit", log=True)
@bp.put('/enable')
@authorize("system:role:edit", log=True)
def enable():
id = request.get_json(force=True).get('roleId')
if id:
@@ -152,8 +152,8 @@ def enable():
# 禁用用户
@admin_role.put('/disable')
@authorize("admin:role:edit", log=True)
@bp.put('/disable')
@authorize("system:role:edit", log=True)
def dis_enable():
_id = request.get_json(force=True).get('roleId')
if _id:
@@ -165,8 +165,8 @@ def dis_enable():
# 角色删除
@admin_role.delete('/remove/<int:id>')
@authorize("admin:role:remove", log=True)
@bp.delete('/remove/<int:id>')
@authorize("system:role:remove", log=True)
def remove(id):
role = Role.query.filter_by(id=id).first()
# 删除该角色的权限和用户
@@ -178,19 +178,3 @@ def remove(id):
if not r:
return fail_api(msg="角色删除失败")
return success_api(msg="角色删除成功")
# 批量删除
@admin_role.delete('/batchRemove')
@authorize("admin:role:remove", log=True)
def batch_remove():
ids = request.form.getlist('ids[]')
for id in ids:
role = Role.query.filter_by(id=id).first()
# 删除该角色的权限和用户
role.power = []
role.user = []
r = Role.query.filter_by(id=id).delete()
db.session.commit()
return success_api(msg="批量删除成功")
@@ -1,4 +1,4 @@
from flask import Blueprint, render_template, request, session
from flask import Blueprint, render_template, request
from flask_login import login_required, current_user
from sqlalchemy import desc
@@ -11,22 +11,22 @@ from applications.extensions import db
from applications.models import Role, Dept
from applications.models import User, AdminLog
admin_user = Blueprint('adminUser', __name__, url_prefix='/admin/user')
bp = Blueprint('user', __name__, url_prefix='/user')
# 用户管理
@admin_user.get('/')
@authorize("admin:user:main")
@bp.get('/')
@authorize("system:user:main")
def main():
return render_template('admin/user/main.html')
return render_template('system/user/main.html')
# 用户分页查询
@admin_user.get('/data')
@authorize("admin:user:main")
@bp.get('/data')
@authorize("system:user:main")
def data():
# 获取请求参数
real_name = str_escape(request.args.get('realName', type=str))
real_name = str_escape(request.args.get('realname', type=str))
username = str_escape(request.args.get('username', type=str))
dept_id = request.args.get('deptId', type=int)
@@ -35,9 +35,9 @@ def data():
if real_name:
filters.append(User.realname.contains(real_name))
if username:
filters.append(User.realname.contains(username))
filters.append(User.username.contains(username))
if dept_id:
filters.append(User.realname == dept_id)
filters.append(User.dept_id == dept_id)
# print(*filters)
query = db.session.query(
@@ -60,15 +60,15 @@ def data():
# 用户增加
@admin_user.get('/add')
@authorize("admin:user:add", log=True)
@bp.get('/add')
@authorize("system:user:add", log=True)
def add():
roles = Role.query.all()
return render_template('admin/user/add.html', roles=roles)
return render_template('system/user/add.html', roles=roles)
@admin_user.post('/save')
@authorize("admin:user:add", log=True)
@bp.post('/save')
@authorize("system:user:add", log=True)
def save():
req_json = request.get_json(force=True)
a = req_json.get("roleIds")
@@ -82,7 +82,7 @@ def save():
if bool(User.query.filter_by(username=username).count()):
return fail_api(msg="用户已经存在")
user = User(username=username, realname=real_name)
user = User(username=username, realname=real_name,enable=1)
user.set_password(password)
db.session.add(user)
roles = Role.query.filter(Role.id.in_(role_ids)).all()
@@ -93,8 +93,8 @@ def save():
# 删除用户
@admin_user.delete('/remove/<int:id>')
@authorize("admin:user:remove", log=True)
@bp.delete('/remove/<int:id>')
@authorize("system:user:remove", log=True)
def delete(id):
user = User.query.filter_by(id=id).first()
user.role = []
@@ -107,20 +107,20 @@ def delete(id):
# 编辑用户
@admin_user.get('/edit/<int:id>')
@authorize("admin:user:edit", log=True)
@bp.get('/edit/<int:id>')
@authorize("system:user:edit", log=True)
def edit(id):
user = curd.get_one_by_id(User, id)
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)
return render_template('system/user/edit.html', user=user, roles=roles, checked_roles=checked_roles)
# 编辑用户
@admin_user.put('/update')
@authorize("admin:user:edit", log=True)
@bp.put('/update')
@authorize("system:user:edit", log=True)
def update():
req_json = request.get_json(force=True)
a = str_escape(req_json.get("roleIds"))
@@ -140,24 +140,24 @@ def update():
# 个人中心
@admin_user.get('/center')
@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/center.html', user_info=user_info, user_logs=user_logs)
return render_template('system/user/center.html', user_info=user_info, user_logs=user_logs)
# 修改头像
@admin_user.get('/profile')
@bp.get('/profile')
@login_required
def profile():
return render_template('admin/user/profile.html')
return render_template('system/user/profile.html')
# 修改头像
@admin_user.put('/updateAvatar')
@bp.put('/updateAvatar')
@login_required
def update_avatar():
url = request.get_json(force=True).get("avatar").get("src")
@@ -169,7 +169,7 @@ def update_avatar():
# 修改当前用户信息
@admin_user.put('/updateInfo')
@bp.put('/updateInfo')
@login_required
def update_info():
req_json = request.get_json(force=True)
@@ -182,14 +182,14 @@ def update_info():
# 修改当前用户密码
@admin_user.get('/editPassword')
@bp.get('/editPassword')
@login_required
def edit_password():
return render_template('admin/user/edit_password.html')
return render_template('system/user/edit_password.html')
# 修改当前用户密码
@admin_user.put('/editPassword')
@bp.put('/editPassword')
@login_required
def edit_password_put():
res_json = request.get_json(force=True)
@@ -208,8 +208,8 @@ def edit_password_put():
# 启用用户
@admin_user.put('/enable')
@authorize("admin:user:edit", log=True)
@bp.put('/enable')
@authorize("system:user:edit", log=True)
def enable():
_id = request.get_json(force=True).get('userId')
if _id:
@@ -221,8 +221,8 @@ def enable():
# 禁用用户
@admin_user.put('/disable')
@authorize("admin:user:edit", log=True)
@bp.put('/disable')
@authorize("system:user:edit", log=True)
def dis_enable():
_id = request.get_json(force=True).get('userId')
if _id:
@@ -231,24 +231,3 @@ def dis_enable():
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[]')
for id in ids:
user = User.query.filter_by(id=id).first()
user.role = []
res = User.query.filter_by(id=id).delete()
db.session.commit()
return success_api(msg="批量删除成功")
@admin_user.get("test")
def test():
print(session)
print(session.get('role')[0])
return '6'
+2 -2
View File
@@ -10,7 +10,7 @@ class BaseConfig:
HOST = '127.0.0.1'
PORT = 5000
SUPERADMIN = 'admin'
SUPERADMIN = 'system'
SYSTEM_NAME = 'Pear Admin'
# 主题面板的链接列表配置
@@ -39,7 +39,7 @@ class BaseConfig:
# JSON配置
JSON_AS_ASCII = False
SECRET_KEY = "pear-admin-flask"
SECRET_KEY = "pear-system-flask"
# redis配置
REDIS_HOST = "127.0.0.1"
+5 -5
View File
@@ -29,7 +29,7 @@ def authorize(power: str, log: bool = False):
from applications.common.utils.rights import authorize
@app.route("/test")
@authorize("admin:power:remove", log=True)
@authorize("system:power:remove", log=True)
def test_index():
return 'You are allowed.'
```
@@ -47,12 +47,12 @@ def test_index():
例如
```python
{% if authorize("admin:user:edit") %}
{% if authorize("system:user:edit") %}
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit">
<i class="pear-icon pear-icon-edit"></i>
</button>
{% endif %}
{% if authorize("admin:user:remove") %}
{% if authorize("system:user:remove") %}
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove">
<i class="pear-icon pear-icon-ashbin"></i>
</button>
@@ -255,7 +255,7 @@ def table_api(msg: str = "", count=0, data=None, limit=10):
from applications.common.utils.http import success_api, fail_api, table_api
@admin_log.get('/operateLog')
@authorize("admin:log:main")
@authorize("system:log:main")
def operate_log():
# orm查询
# 使用分页获取data需要.items
@@ -270,7 +270,7 @@ def operate_log():
from applications.common.utils.http import success_api, fail_api, table_api
@admin_power.post('/save')
@authorize("admin:power:add", log=True)
@authorize("system:power:add", log=True)
def save():
... # 若干操作
if success:
+1 -1
View File
@@ -70,7 +70,7 @@ python -m pip install -r requirement.txt
flask db init
flask db migrate
flask db upgrade
flask admin init
flask system init
```
#### 运行项目
+1
View File
@@ -0,0 +1 @@
flask db migrate && flask db upgrade
+1
View File
@@ -0,0 +1 @@
flask db migrate && flask db upgrade
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<title>pear-admin-flask</title>
<meta name="description" content="pear-admin-flask">
{% include 'admin/common/header.html' %}
{% include 'system/common/header.html' %}
<link rel="stylesheet" href="{{ url_for('static', filename='index/layui/css/layui.css') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='index/css/main.css') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='index/css/load.css') }}"/>
@@ -30,7 +30,7 @@
<a lay-href="/">首页</a>
</li>
<li class="layui-nav-item">
<a href="/admin" target="_blank">后台</a>
<a href="/system" target="_blank">后台</a>
</li>
</ul>
</div>
@@ -52,8 +52,8 @@
</div>
<!-- js部分 -->
<script src="{{ url_for('static', filename='admin/component/layui/layui.js') }}"></script>
<script src="{{ url_for('static', filename='admin/component/pear/pear.js') }}"></script>
<script src="{{ url_for('static', filename='system/component/layui/layui.js') }}"></script>
<script src="{{ url_for('static', filename='system/component/pear/pear.js') }}"></script>
<script>
layui.use(['layer', 'form', 'jquery'], function () {
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<title>pear-admin-flask</title>
<meta name="description" content="pear-admin-flask">
{% include 'admin/common/header.html' %}
{% include 'system/common/header.html' %}
<link rel="stylesheet" href="{{ url_for('static', filename='index/layui/css/layui.css') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='index/css/main.css') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='index/css/load.css') }}"/>
@@ -30,7 +30,7 @@
<a lay-href="/">首页</a>
</li>
<li class="layui-nav-item">
<a href="/admin" target="_blank">后台</a>
<a href="/system" target="_blank">后台</a>
</li>
</ul>
</div>
@@ -52,8 +52,8 @@
</div>
<!-- js部分 -->
<script src="{{ url_for('static', filename='admin/component/layui/layui.js') }}"></script>
<script src="{{ url_for('static', filename='admin/component/pear/pear.js') }}"></script>
<script src="{{ url_for('static', filename='system/component/layui/layui.js') }}"></script>
<script src="{{ url_for('static', filename='system/component/pear/pear.js') }}"></script>
<script>
layui.use(['layer', 'form', 'jquery'], function () {
-1
View File
@@ -10,5 +10,4 @@ PyMySQL
psutil
Flask-Mail
Pillow
validators
cryptography
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -27,7 +27,7 @@ layui.define(['layer', 'element'], function (exports) {
param.area = (param.type == 2) ? ['360px', '300px'] : '360px';
}
if (!param.skin) {
param.skin = 'layui-layer-admin';
param.skin = 'layui-layer-system';
}
if (param.fixed == undefined) {
param.fixed = false;
@@ -204,7 +204,7 @@ layui.define(['layer', 'element'], function (exports) {
var url = $(this).data('url');
layer.confirm('确定要退出登录吗?', {
title: '温馨提示',
skin: 'layui-layer-admin',
skin: 'layui-layer-system',
shade: .1
}, function () {
location.replace(url ? url : '/');

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 197 KiB

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 296 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long
@@ -14,14 +14,36 @@
/>
<missing-glyph />
<glyph glyph-name="edge" unicode="&#59019;" d="M240.185509 821.062741C322.180562 871.479699 415.37494 897.48813 509.969233 895.934224 845.948962 895.934224 1023.938224 648.353161 1023.938224 456.964708c-0.199988-65.396055-25.998431-127.79229-71.795669-174.389479-45.797237-46.397201-107.993485-72.995596-173.389539-73.995536-150.390927 0-182.98896 46.197213-182.98896 63.996139 0 7.599542 2.399855 12.399252 9.599421 18.798866l1.99988 2.399855 0.799951 3.199807c20.998733 22.998612 31.798082 52.396839 31.798082 83.194981 0 157.390504-164.390082 285.382782-367.977799 285.382782-75.075471 0.599964-149.071006-17.798926-215.027027-53.796754 53.996742 115.03306 165.430019 195.188224 182.628981 207.627473 1.599903 1.099934 0.599964 1.679899 0.599964 1.679899z m31.198118-636.081624c-2.799831-59.99638 9.199445-119.992761 32.798021-174.389479 27.198359-52.796815 65.396055-101.993847 112.993183-138.591638-118.992821 22.998612-222.966548 87.794703-298.781974 178.589225C42.237452 143.383627 0 259.176641 0 380.169341c0 102.393822 124.792471 188.78861 271.983591 188.78861 73.195584 1.199928 144.791264-21.798685 203.587717-65.396054l-7.199566-2.399856c-102.993786-35.197876-196.988115-181.389056-196.988115-316.180924zM939.543315 95.986486l-1.399915-0.199987c-23.598576-37.597732-51.796875-70.195765-84.394908-98.994028-61.596284-55.996622-136.191783-90.99451-217.586873-99.793979-37.197756-0.599964-73.59556 6.399614-107.593509 22.798624-51.196911 20.598757-94.194317 59.99638-123.192567 105.993605-28.798263 47.797116-42.197454 103.393762-37.997708 159.190396-1.199928 40.197575 10.799348 80.595138 29.99819 116.392978 27.798323-66.196006 74.995475-122.592604 135.191844-161.590251 60.196368-38.997647 130.992097-58.996441 202.787766-57.196549 61.99626-0.599964 124.192507 13.399192 180.389116 40.997526l3.799771 1.799892c7.799529 4.599722 15.399071 7.799529 23.1986 0 8.999457-9.799409 3.599783-18.39889-2.399855-27.998311-0.399976-0.399976-0.599964-0.99994-0.799952-1.399916z" horiz-adv-x="1024" />
<glyph glyph-name="leaf" unicode="&#59137;" d="M1017.948269 886.876437c-4.863707 5.785251-12.031275 9.113051-19.557222 9.113051l-26.110427 0c-258.032454 0.102394-461.847374 0.153591-611.905533-35.735447-80.635142-19.301237-142.992985-48.432282-190.606116-89.031436-51.401703-43.82456-86.420393-101.216302-107.155144-175.554223-13.77197-49.353826-20.222782-138.487656 6.96278-227.160714 10.034595-32.766026 25.700852-63.688963 46.589193-92.103251-62.255449-97.530124-116.063407-225.983185-116.063407-378.805977 0-14.130349 11.468109-25.598458 25.598458-25.598458s25.598458 11.468109 25.598458 25.598458c0 235.761795 139.665185 410.650458 222.91137 493.845446 59.7468 59.7468 127.275532 110.175762 195.367429 145.808815 63.381781 33.175601 123.947732 51.4529 170.536925 51.4529 14.130349 0 25.598458 11.468109 25.598458 25.598458s-11.468109 25.598458-25.598458 25.598458c-55.497456 0-122.667809-19.813206-194.241097-57.340545-72.597226-38.039308-144.477695-91.591282-207.80828-154.973063-26.72479-26.72479-58.876453-62.357843-90.823328-105.977615-12.389654 19.506025-22.014674 40.189579-28.619076 61.794677-25.598458 83.553366-16.178225 164.034917-6.604402 198.388047 73.211589 262.384191 351.313233 263.049751 855.858835 262.896161-60.156376-321.926204-172.328817-530.29765-333.599101-619.533873-149.597387-82.785412-297.966048-37.629733-354.845821-14.335136-11.980078 4.914904-24.06255 10.95614-35.786644 17.91892-12.133669 7.218765-27.851122 3.225406-35.069887-8.908263s-3.225406-27.851122 8.908263-35.069887c13.925561-8.2939 28.260697-15.461468 42.595834-21.349114 31.844481-13.004017 83.143791-29.694211 146.679163-35.172281 14.027955-1.228726 27.902319-1.791892 41.674289-1.791892 75.208269 0 145.860012 18.072511 210.675307 53.910352 82.375837 45.565255 153.641943 119.749585 211.904033 220.351524 68.296685 118.00889 119.698388 274.51786 152.720399 465.175173 1.279923 7.423553-0.767954 15.051893-5.631661 20.837145z" horiz-adv-x="1025" />
<glyph glyph-name="folder" unicode="&#60094;" d="M970.666667 682.666667H542.173333L429.793333 795.046667A52.986667 52.986667 0 0 1 392.08 810.666667H96a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h874.666667a53.393333 53.393333 0 0 1 53.333333 53.333333V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334zM96 768h296.08a10.573333 10.573333 0 0 0 7.54-3.126667L481.826667 682.666667H96a53.546667 53.546667 0 0 1-10.666667-1.073334V757.333333a10.666667 10.666667 0 0 0 10.666667 10.666667z m885.333333-714.666667a10.666667 10.666667 0 0 0-10.666666-10.666666H96a10.666667 10.666667 0 0 0-10.666667 10.666666V629.333333a10.666667 10.666667 0 0 0 10.666667 10.666667h874.666667a10.666667 10.666667 0 0 0 10.666666-10.666667z" horiz-adv-x="1024" />
<glyph glyph-name="folder-open" unicode="&#60097;" d="M1003.153333 491.04a52.933333 52.933333 0 0 1-42.38 20.96H896V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334H461.253333a10.573333 10.573333 0 0 0-7.54 3.126666L344.46 795.046667A52.986667 52.986667 0 0 1 306.746667 810.666667H53.333333a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h796.893334a53.453333 53.453333 0 0 1 51.453333 39.333333l110.546667 405.333334a52.953333 52.953333 0 0 1-9.073334 46.373333zM53.333333 768h253.413334a10.573333 10.573333 0 0 0 7.54-3.126667l109.253333-109.253333A52.986667 52.986667 0 0 1 461.253333 640H842.666667a10.666667 10.666667 0 0 0 10.666666-10.666667v-117.333333H173.773333a53.453333 53.453333 0 0 1-51.453333-39.333333L42.666667 180.633333V757.333333a10.666667 10.666667 0 0 0 10.666666 10.666667z m917.726667-312.14l-110.546667-405.333333a10.666667 10.666667 0 0 0-10.286666-7.86H63.226667a10.666667 10.666667 0 0 0-10.286667 13.473333l110.546667 405.333333A10.666667 10.666667 0 0 0 173.773333 469.333333h787a10.666667 10.666667 0 0 0 10.286667-13.473333z" horiz-adv-x="1024" />
<glyph glyph-name="gitee" unicode="&#59035;" d="M512-128C229.222-128 0 101.222 0 384S229.222 896 512 896s512-229.222 512-512-229.222-512-512-512z m259.149 568.883h-290.74a25.293 25.293 0 0 1-25.292-25.293l-0.026-63.206c0-13.952 11.315-25.293 25.267-25.293h177.024c13.978 0 25.293-11.315 25.293-25.267v-12.646a75.853 75.853 0 0 0-75.853-75.853h-240.23a25.293 25.293 0 0 0-25.267 25.293V478.797a75.853 75.853 0 0 0 75.827 75.853h353.946a25.293 25.293 0 0 1 25.267 25.292l0.077 63.207a25.293 25.293 0 0 1-25.268 25.293H417.152a189.62 189.62 0 0 1-189.62-189.645V124.85c0-13.977 11.316-25.293 25.294-25.293h372.94a170.65 170.65 0 0 1 170.65 170.65V415.616a25.293 25.293 0 0 1-25.293 25.267z" horiz-adv-x="1024" />
<glyph glyph-name="github" unicode="&#59047;" d="M512 883.32190493c275.66730126 0 499.32190493-223.65460366 499.32190493-499.32190493 0-220.40901063-143.01411555-407.65472541-341.32813256-473.98131826-25.34058667-4.53550763-34.45321159 11.06830222-34.45321159 24.05067207 0 16.26957255 0.6657627 70.19633778 0.66576271 137.18869334 0 46.81142841-15.60380985 76.72913237-33.7874489 92.33294222 111.18234397 12.35821682 228.19011015 54.63413874 228.1901113 246.41536 0 54.63413874-19.51516445 98.82412715-51.34693604 133.9431003 5.20127033 13.02397952 22.09499477 63.70515285-5.20127033 132.61157604-41.61015922 13.02397952-137.18869333-51.34693603-137.18869333-51.34693604a469.36259015 469.36259015 0 0 1-249.6609519 0S291.63259904 689.58500523 250.02244096 676.56102571c-27.29626397-68.90642318-10.40253952-119.62920619-5.20127033-132.61157604-31.87338126-35.11897429-51.34693603-79.3089627-51.34693604-133.9431003 0-191.15706937 116.38361429-234.05714318 227.56595826-246.41536-14.31389411-13.02397952-27.29626397-35.11897429-31.87338126-66.95074588-28.62778937-13.02397952-101.44556715-35.11897429-144.96979285 41.61015921-27.29626397 47.47719111-76.72913237 51.34693603-76.72913351 51.34693604-48.76710571 0.6657627-3.24559189-30.54185699-3.2455919-30.541857 32.49753429-14.93804715 55.25829063-72.81777778 55.25829064-72.81777777 29.25194126-89.08735033 168.39631189-59.16964523 168.39631302-59.16964523 0-41.61015922 0.6657627-80.5988773 0.66576157-92.95709525 0-13.02397952-9.11262493-28.62778937-34.45321045-24.05067094C155.77543111-23.61311459000001 12.76131555 163.63259903999995 12.76131555 384.04160967c0 275.66730126 223.65460366 499.32190493 499.32190493 499.32190492zM201.87948715 166.21242937c1.28991459 2.62144-0.6657627 5.86703189-4.53550763 7.78109952-3.91135459 1.28991459-7.15694763 0.6657627-8.44686222-1.2899146-1.28991459-2.62144 0.6657627-5.86703189 4.53550763-7.78109952 3.24559189-1.9556773 7.15694763-1.28991459 8.44686222 1.2899146z m20.13931634-22.13660444c2.62144 1.9556773 1.9556773 6.49118493-1.2899146 10.40253952-3.24559189 3.24559189-7.78109952 4.53550763-10.40253952 1.95567729-2.62144-1.9556773-1.9556773-6.49118493 1.2899146-10.40253952 3.24559189-3.24559189 7.78109952-4.53550763 10.40253952-1.95567729z m19.51516444-29.25194127c3.24559189 2.62144 3.24559189 7.78109952 0 12.35821682-2.62144 4.53550763-7.78109952 6.49118493-11.06830222 3.91135459-3.24559189-1.9556773-3.24559189-7.15694763 0-11.69245411s8.44686222-6.49118493 11.06830222-4.53550763z m27.29626396-27.2962651c2.62144 2.62144 1.28991459 8.44686222-2.62144 12.35821795-4.53550763 4.53550763-10.40253952 5.20127033-13.02397952 1.9556773-3.24559189-2.62144-1.9556773-8.44686222 2.62144-12.35821682 4.53550763-4.53550763 10.40253952-5.20127033 13.02397952-1.95567843z m37.0746516-16.26957141c1.28991459 3.91135459-2.62144 8.44686222-8.44686223 10.40253952-5.20127033 1.28991459-11.06830222-0.6657627-12.35821681-4.53550763s2.62144-8.44686222 8.44686222-9.73677682c5.20127033-1.9556773 11.06830222 0 12.35821682 3.9113546z m40.94439651-3.24559304c0 4.53550763-5.20127033 7.78109952-11.06830222 7.15694763-5.86703189 0-10.40253952-3.24559189-10.40253952-7.15694763 0-4.53550763 4.53550763-7.78109952 11.06830222-7.15694648 5.86703189 0 10.40253952 3.24559189 10.40253952 7.15694648z m37.69880349 6.49118493c-0.6657627 3.91135459-5.86703189 6.49118493-11.69245412 5.86703303-5.86703189-1.28991459-9.73677682-5.20127033-9.11262492-9.73677796 0.6657627-3.91135459 5.86703189-6.49118493 11.69245411-5.20126918s9.73677682 5.20127033 9.11262493 9.11262492z" horiz-adv-x="1024" />
<glyph glyph-name="disabled" unicode="&#59084;" d="M509.20496914 834c-245.9627332 0-447.20496914-201.24223594-447.20496914-447.20496914s201.24223594-447.20496914 447.20496914-447.20496914 447.20496914 201.24223594 447.20496914 447.20496914-201.24223594 447.20496914-447.20496914 447.20496914zM509.20496914-10.09937930000001C291.19254628-10.09937930000001 112.31055898 168.78260888 112.31055898 386.79503086c0 95.03105625 33.54037295 184.4720499 95.03105625 257.14285752l553.41614883-553.41614883C693.67701904 23.440993649999996 604.23602451-10.09937930000001 509.20496914-10.09937930000001z m296.27329131 134.16149092l-559.00621055 553.41614883C319.14285752 738.96894375 408.58385117 778.0993793 509.20496914 778.0993793c218.01242197 0 396.89441016-178.8819873 396.89441016-396.89441016 0-95.03105625-39.13043467-190.06211162-100.62111885-257.14285752z" horiz-adv-x="1024" />
<glyph glyph-name="moon" unicode="&#59074;" d="M696.832 680.448c98.816-62.976 162.304-173.056 162.304-294.912 0-192.512-156.672-349.184-349.184-349.184-121.856 0-232.448 63.488-294.912 162.816h5.12c263.168 0 477.184 214.016 477.184 477.184-0.512 1.536-0.512 3.072-0.512 4.096m-78.336 103.936c9.216-34.304 14.336-70.656 14.336-108.032 0-228.352-184.832-413.184-413.184-413.184-37.376 0-73.728 5.12-108.544 14.336 47.616-175.616 207.872-305.152 398.848-305.152 228.352 0 413.184 184.832 413.184 413.184 0 190.976-129.024 351.232-304.64 398.848z" horiz-adv-x="1024" />
<glyph glyph-name="error" unicode="&#59027;" d="M512-60.09287109000002c-245.26845703 0-444.09550781 198.82880859-444.09550781 444.09550781s198.82705078 444.09287109 444.09550781 444.09287109c245.26669922 0 444.09550781-198.82880859 444.09550781-444.09550781s-198.82880859-444.09287109-444.09550781-444.09287109zM512 772.58378906c-214.60166016 0-388.58378906-173.97861328-388.58378906-388.58378906s173.98125-388.58115234 388.58378906-388.58115234c214.60166016 0 388.58115234 173.97861328 388.58115234 388.58115234s-173.97861328 388.58378906-388.58115234 388.58378906zM551.41103516 383.85585937999997l117.60029297-117.62138672c10.84306641-10.82460938 10.84306641-28.40625 0-39.24580079-10.83955078-10.84306641-28.42119141-10.84306641-39.24580079 0l-117.62138671 117.60029297-118.39570313-118.39570312c-10.93271484-10.93095703-28.64091797-10.93095703-39.55517578 0-10.93271484 10.93095703-10.93271484 28.64091797 0 39.55693359l118.39570312 118.41240235-117.60292968 117.60292968c-10.84130859 10.84130859-10.84130859 28.40625 0 39.24931641 10.84306641 10.83955078 28.40625 10.83955078 39.2493164 0l117.60292969-117.60292969 119.28164063 119.28164063c10.93095703 10.91513672 28.64091797 10.91513672 39.55693359 0 10.93095703-10.93095703 10.93095703-28.64091797 0-39.57363281l-119.26757813-119.26582032z" horiz-adv-x="1024" />
<glyph glyph-name="success" unicode="&#59031;" d="M661.31818174 521.04545479c10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090868 12.27272695-10.22727305 14.31818174-30.68181826 4.09090957-42.95454521l-204.54545478-243.40909131c-10.22727305-12.27272695-30.68181826-14.31818174-42.95454522-4.09090869L327.90909131 345.13636347c-12.27272695 10.22727305-14.31818174 30.68181826-4.09090957 42.95454522 10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090957l110.4545461-92.04545478 184.09090869 220.90909131zM512-66C262.45454521-66 62 134.45454521 62 384S262.45454521 834 512 834s450-200.45454521 450-450-200.45454521-450-450-450z m0 40.90909131c225 0 409.09090869 184.09090869 409.09090869 409.09090869S737 793.09090869 512 793.09090869 102.90909131 609 102.90909131 384s184.09090869-409.09090869 409.09090869-409.09090869z" horiz-adv-x="1024" />
<glyph glyph-name="question" unicode="&#59033;" d="M468.125 159a37.50000029 37.50000029 0 1 1 37.50000029 37.50000029 37.50000029 37.50000029 0 0 1-37.50000029-37.50000029z m37.50000029 92.62500029h-3.00000058a31.5 31.5 0 0 0-28.49999942 34.49999971A203.24999971 203.24999971 0 0 0 549.50000029 400.12500029c56.62500029 56.62500029 57.75000029 74.99999971 58.5 93.74999942a81.37500029 81.37500029 0 0 1-23.25000058 60.75A98.62499971 98.62499971 0 0 1 512 584.99999971a94.5 94.5 0 0 1-94.5-94.5 31.5 31.5 0 1 0-63.37500029 0A157.5 157.5 0 0 0 512 646.50000029a162.37500029 162.37500029 0 0 0 117.74999971-50.25000058 144.37500029 144.37500029 0 0 0 39.75000029-105.75c-2.25-40.87500029-14.625-72.74999971-77.24999971-135-31.5-31.5-51.75-55.50000029-53.62500058-74.99999971a31.5 31.5 0 0 0-31.12499971-29.99999971z m277.875-139.87500029A386.62499971 386.62499971 0 1 0 361.99999971 740.24999971a386.62499971 386.62499971 0 0 0 423.37500029-629.62499971zM512 834a450 450 0 1 1 450-450A450 450 0 0 1 512 834z" horiz-adv-x="1024" />
<glyph glyph-name="lock" unicode="&#59034;" d="M512-66A450 450 0 1 0 962 384 450.39130401 450.39130401 0 0 0 512-66z m0 860.86956533A410.86956533 410.86956533 0 1 1 922.86956533 384 411.26086934 411.26086934 0 0 1 512 794.86956533zM665.78260888 398.86956533h-14.47826132v78.26086934a139.69565244 139.69565244 0 0 1-279-7.82608711v-70.04347823h-11.73912979a19.95652177 19.95652177 0 0 1-19.95652178-20.34782577v-199.56521778a19.95652177 19.95652177 0 0 1 19.95652178-20.34782578h302.86956445a19.95652177 19.95652177 0 0 1 19.95652179 20.34782578v199.56521778a20.73913067 20.73913067 0 0 1-17.60869513 19.95652177z m-254.34782665 70.43478223a100.56521777 100.56521777 0 0 0 200.73913066 4.69565244v-74.73913067H411.43478223z" horiz-adv-x="1024" />
<glyph glyph-name="eye" unicode="&#59029;" d="M513.92 449.493333a64 64 0 1 0-64-64 64 64 0 0 0 64 64m0 64a128 128 0 1 1 128-128 128 128 0 0 1-128 128zM512 606.2933330000001c128 0 257.706667-67.84 397.226667-207.146666a21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004s-257.28 67.84-396.8 207.146666a21.333333 21.333333 0 0 0 0 30.08c139.52 139.52 268.8 207.36 396.8 207.36m0 64c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666C220.586667 173.013333 366.506667 97.70666700000004 512 97.70666700000004s292.266667 75.306667 442.666667 225.92a85.333333 85.333333 0 0 1 0 120.746666C804.266667 594.986667 658.346667 670.293333 512 670.293333z" horiz-adv-x="1024" />
<glyph glyph-name="eye-invisible" unicode="&#59030;" d="M386.346667 391.466667l121.813333 121.813333a128 128 0 0 1-121.813333-121.813333z m238.72 57.6L576 400.213333a64 64 0 0 0-76.8-76.8l-48.853333-48.853333a128 128 0 0 1 174.506666 174.506667zM109.013333 384a21.333333 21.333333 0 0 0 6.186667 15.146667c139.52 139.306667 268.8 207.146667 396.8 207.146666a372.266667 372.266667 0 0 0 79.786667-8.96l52.266666 52.266667a443.52 443.52 0 0 1-132.053333 21.333333c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666 1063.04 1063.04 0 0 1 134.186666-115.2l45.866667 45.866666a985.813333 985.813333 0 0 0-134.4 114.133334 21.333333 21.333333 0 0 0-6.186667 14.933333z m845.653334 60.373333a966.613333 966.613333 0 0 1-185.813334 149.333334l-46.72-46.72a877.653333 877.653333 0 0 0 187.306667-147.2 21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004a393.386667 393.386667 0 0 0-145.706667 29.013333l-48.64-48.64A466.133333 466.133333 0 0 1 512 97.70666700000004c145.92 0 291.84 75.306667 442.453333 225.92a85.333333 85.333333 0 0 1 0.213334 120.746666zM777.267604 692.049287m22.627417-22.627417l0 0q22.627417-22.627417 0-45.254834l-527.973064-527.973063q-22.627417-22.627417-45.254834 0l0 0q-22.627417 22.627417 0 45.254834l527.973064 527.973063q22.627417 22.627417 45.254834 0Z" horiz-adv-x="1024" />
<glyph glyph-name="backspace" unicode="&#59028;" d="M484.46100645 268.09861505000003a28.76779355 28.76779355 0 0 0-20.34016344 49.107957l174.2671828 174.27268816a28.76779355 28.76779355 0 0 0 40.68473118-40.68032687l-174.2671828-174.27819355a28.6940215 28.6940215 0 0 0-20.34456774-8.42322581zM658.72708818 268.09861505000003a28.68301076 28.68301076 0 0 0-20.34016345 8.42322581l-174.26718279 174.27709248a28.76228818 28.76228818 0 0 0 0 40.68032687 28.75127742 28.75127742 0 0 0 40.68142795 0l174.2671828-174.27268816a28.77990537 28.77990537 0 0 0-20.34126451-49.107957zM834.5379785 74.81145805999995H340.57028818c-28.46940215 0-55.25305806 12.53684301-73.49016775 34.39428818L75.75838279 339.01887310999996c-10.54830108 13.06205592-16.20232258 28.91974194-16.1968172 44.98663226 0.00660645 15.39083011 4.67406452 29.85015053 13.50248602 41.81333334 0.33803011 0.45694624 0.68266666 0.90288172 1.04822366 1.33009892L266.70685592 658.36593548a95.32449032 95.32449032 0 0 0 73.86233118 34.82921291H834.5379785c51.98286452 0 94.27516559-42.28789677 94.27516558-94.27076129v-429.83776344c0-51.98286452-42.29230108-94.27516559-94.27516558-94.2751656zM119.01522581 391.16579785c-0.90728602-1.35872689-1.91587097-3.52344086-1.91587097-7.17680861 0-2.92005161 1.14952258-6.01517419 3.15568172-8.50140214l191.02114409-229.45307528a38.55965592 38.55965592 0 0 1 29.29300645-13.69297203H834.5379785a36.78472258 36.78472258 0 0 1 36.74508387 36.74508387v429.83776344a36.78472258 36.78472258 0 0 1-36.74508387 36.73957849H340.5691871a38.60590108 38.60590108 0 0 1-29.53524302-13.96934193L119.01522581 391.16579785z" horiz-adv-x="1024" />
<glyph glyph-name="help-circle" unicode="&#59260;" d="M505.181 153.98199999999997c-26.499 0-47.972-21.481-47.972-47.968s21.474-47.977 47.972-47.977c26.48 0 47.948 21.488 47.948 47.977s-21.469 47.968-47.948 47.968zM505.181 825.872c-246.883 0-447.689-200.826-447.689-447.683 0-246.874 200.806-447.705 447.689-447.705 246.849 0 447.683 200.83 447.683 447.705 0 246.858-200.836 447.683-447.683 447.683zM505.181-5.273000000000025c-211.46 0-383.455 172.045-383.455 383.459 0 211.431 171.995 383.436 383.455 383.436 211.391 0 383.455-172.003 383.455-383.436 0-211.417-172.064-383.459-383.455-383.459zM505.162 664.795c-88.146 0-159.892-71.093-159.892-158.448 0-17.648 14.347-31.981 31.981-31.981 17.675 0 31.985 14.332 31.985 31.981 0 52.987 42.167 94.498 95.946 94.498 52.873 0 95.926-43.366 95.926-96.677 0-21.324-26.753-48.058-52.634-73.965-35.309-35.267-75.282-75.237-75.282-127.563v-54.067c0-17.663 14.341-31.985 31.989-31.985 17.634 0 31.97 14.363 31.97 32.016v54.071c0 25.807 28.719 54.524 56.54 82.282 35.074 35.074 71.383 71.346 71.383 119.221-0.002 88.573-71.718 160.617-159.914 160.617z" horiz-adv-x="1024" />
<glyph glyph-name="tips-fill" unicode="&#60206;" d="M512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m-32-232c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-272c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8V600z m32-440c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z" horiz-adv-x="1024" />
<glyph glyph-name="test" unicode="&#59026;" d="M513.058-31.072000000000003c-56.004 0-110.35 10.976-161.528 32.622-49.416 20.901-93.789 50.816-131.887 88.914-38.098 38.099-68.013 82.472-88.915 131.888-21.646 51.178-32.622 105.524-32.622 161.528s10.976 110.35 32.622 161.528c20.901 49.416 50.816 93.789 88.915 131.887s82.471 68.013 131.887 88.915c51.178 21.646 105.524 32.622 161.528 32.622 64.817 0 126.912-14.538 184.56-43.209 54.937-27.323 104.055-67.35 142.042-115.754 10.911-13.903 8.486-34.019-5.417-44.93-13.903-10.91-34.018-8.485-44.929 5.417-67.071 85.461-167.763 134.476-276.256 134.476-193.516 0-350.952-157.436-350.952-350.952s157.436-350.952 350.952-350.952c200.075 0 350.952 141.419 350.952 328.952 0 17.673 14.327 32 32 32s32-14.327 32-32c0-109.988-43.501-210.61-122.49-283.33-76.785-70.692-180.65-109.622-292.462-109.622zM636.555 275.40700000000004c-5.39 0-10.85 1.362-15.862 4.23-15.34 8.776-20.66 28.327-11.884 43.667L781.3 624.79c8.776 15.341 28.33 20.661 43.667 11.884 15.34-8.777 20.66-28.327 11.884-43.667L664.359 291.52099999999996c-5.908-10.327-16.703-16.114-27.804-16.114zM628.023 263.38199999999995a31.856 31.856 0 0 0-19.204 6.424L403.383 424.242c-14.127 10.62-16.97 30.681-6.35 44.807 10.62 14.127 30.68 16.97 44.807 6.35l205.437-154.438c14.127-10.619 16.97-30.68 6.35-44.807-6.289-8.363-15.888-12.772-25.604-12.772zM219.079 140.418a31.849 31.849 0 0 0-18.931 6.222c-14.238 10.47-17.293 30.499-6.823 44.737l202.489 275.372c10.468 14.239 30.499 17.294 44.737 6.823 14.238-10.47 17.293-30.499 6.823-44.737L244.885 153.46299999999997c-6.271-8.528-15.974-13.045-25.806-13.045z" horiz-adv-x="1024" />
@@ -46,8 +68,6 @@
<glyph glyph-name="chrome" unicode="&#59018;" d="M515.436 583.685H914.285C840.842 730.955 688.748 832.132 513 832.132c-141.284 0-267.274-65.395-349.42-167.546l151.66-262.682c8.535 102.325 95.704 181.781 200.196 181.781zM514.218 550.803c-91.476 0-165.631-74.155-165.631-165.631s74.155-165.631 165.631-165.631c52.7 0 99.615 24.642 129.95 62.999l1.428 2.474 0.355-0.205c21.252 27.852 33.898 62.624 33.898 100.363 0 84.774-63.702 154.626-145.841 164.413l-6.393 0.632c-4.424 0.354-8.882 0.586-13.397 0.586zM929.561 549.585H627.443c52.209-36.066 86.506-96.297 86.506-164.413 0-45.547-18.268-81.598-41.12-121.192L483.898-63.257c9.624-0.617 19.322-0.966 29.102-0.966 247.521 0 448.177 200.656 448.177 448.177 0 58.508-11.225 114.391-31.616 165.631zM514.218 185.441c-83.583 0-144.927 54.804-185.034 124.651l-0.235-0.136-187.482 324.727C93.081 563.124 64.823 476.84 64.823 383.954c0-225.02 165.839-411.288 381.958-443.298l152.278 263.752c-25.769-12.143-54.518-18.967-84.841-18.967z" horiz-adv-x="1024" />
<glyph glyph-name="edge" unicode="&#59019;" d="M854.794 669.297C797.923 743.783 683.626 823.59 548.62 830.822 136.707 852.889 85.742 435.448 85.742 435.448c55.449 53.038 58.01 97.116 163.936 154.293C673.983 818.768 676.394 476.432 676.394 476.432H346.111c-7.232 65.092 62.681 137.417 62.681 137.417-202.509-98.844-216.974-284.477-216.974-284.477s-28.93-279.655 219.385-364.034 452.029 42.189 452.029 42.189V193.16c-59.065-32.546-102.292-54.405-153.087-63.887-361.623-67.503-364.034 188.044-364.034 188.044h585.83c0 0.001 39.075 199.761-77.147 351.98z" horiz-adv-x="1024" />
<glyph glyph-name="heart" unicode="&#59020;" d="M512 4.100000000000023c-108.9 0-447.3 277.5-447.3 522.2 0 131 106.6 237.6 237.6 237.6 94.9 0 174.8-50.2 209.7-76.1 34.9 25.9 114.8 76.1 209.7 76.1 131 0 237.6-106.6 237.6-237.6 0-244.7-338.4-522.2-447.3-522.2zM302.3 708c-100.2 0-181.7-81.5-181.7-181.7 0-221 326.8-466.3 391.4-466.3s391.4 245.3 391.4 466.3c0 100.2-81.5 181.7-181.7 181.7-103.9 0-190.2-76-191.1-76.8-10.6-9.5-26.7-9.5-37.3 0-0.8 0.8-87.7 76.8-191 76.8z" horiz-adv-x="1024" />
<glyph glyph-name="key" unicode="&#59011;" d="M819.2 588.8c0-172.8-140.8-307.2-307.2-307.2-172.8 0-307.2 140.8-307.2 307.2C204.8 755.2 339.2 896 512 896S819.2 755.2 819.2 588.8L819.2 588.8zM512 838.4c-140.8 0-249.6-115.2-249.6-249.6 0-134.4 108.8-256 249.6-256s256 115.2 256 249.6S652.8 838.4 512 838.4L512 838.4zM480 300.79999999999995l64 0L544-128l-64 0L480 300.79999999999995 480 300.79999999999995zM512 192l192 0 0-64L512 128 512 192 512 192zM512 64l192 0 0-64L512 0 512 64 512 64z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Some files were not shown because too many files have changed in this diff Show More