diff --git a/applications/api/__init__.py b/applications/api/__init__.py index a0ca06c..9aeccea 100644 --- a/applications/api/__init__.py +++ b/applications/api/__init__.py @@ -5,6 +5,10 @@ api_bp = Blueprint('api', __name__, url_prefix='/api/v1') from . import department from . import file from . import roles +from . import rights +from . import passport +from . import users + def init_api(app: Flask): app.register_blueprint(api_bp) diff --git a/applications/view/passport/api.py b/applications/api/passport.py similarity index 92% rename from applications/view/passport/api.py rename to applications/api/passport.py index 1e3c606..268c44b 100644 --- a/applications/view/passport/api.py +++ b/applications/api/passport.py @@ -1,15 +1,16 @@ from flask import session, redirect, url_for, request from flask_login import current_user, login_user from flask_restful import Resource, reqparse, Api + +from applications.api import api_bp from applications.common.admin_log import login_log +from applications.common.gen_captcha import add_auth_session from applications.common.utils.http import fail_api, success_api from applications.models import User -from . import passport_bp -from ._utils import add_auth_session from flask import render_template, make_response -passport_api = Api(passport_bp) +passport_api = Api(api_bp, prefix='/passport') @passport_api.resource('/login') diff --git a/applications/api/rights.py b/applications/api/rights.py new file mode 100644 index 0000000..d1cc354 --- /dev/null +++ b/applications/api/rights.py @@ -0,0 +1,321 @@ +import copy +from collections import OrderedDict + +from flask import request, jsonify, current_app +from flask_login import current_user, login_required +from flask_restful import Resource, reqparse, Api, marshal + +from applications.api import api_bp +from applications.common.serialization import power2_fields, power_fields +from applications.common.utils.http import success_api, fail_api +from applications.common.utils.rights import authorize +from applications.extensions import db +from applications.models import Power, Role + + +def get_render_config(): + # 网站配置 + config = dict(logo={ + # 网站名称 + "title": current_app.config.get("SYSTEM_NAME"), + # 网站图标 + "image": "/static/admin/admin/images/logo.png" + # 菜单配置 + }, menu={ + # 菜单数据来源 + "data": "/api/v1/rights/menu", + "collaspe": True, + # 是否同时只打开一个菜单目录 + "accordion": True, + "method": "GET", + # 是否开启多系统菜单模式 + "control": False, + # 默认选中的菜单项 + "select": "0", + # 是否开启异步菜单,false 时 data 属性设置为菜单数据,false 时为 json 文件或后端接口 + "async": True + }, tab={ + # 是否开启多选项卡 + "muiltTab": True, + # 切换选项卡时,是否刷新页面状态 + "keepState": True, + # 是否开启 Tab 记忆 + "session": True, + # 最大可打开的选项卡数量 + "tabMax": 30, + "index": { + # 标识 ID , 建议与菜单项中的 ID 一致 + "id": "10", + # 页面地址 + "href": "/admin/welcome", + # 标题 + "title": "首页" + } + }, theme={ + # 默认主题色,对应 colors 配置中的 ID 标识 + "defaultColor": "2", + # 默认的菜单主题 dark-theme 黑 / light-theme 白 + "defaultMenu": "dark-theme", + # 是否允许用户切换主题,false 时关闭自定义主题面板 + "allowCustom": True + }, colors=[{ + "id": "1", + "color": "#2d8cf0" + }, + { + "id": "2", + "color": "#5FB878" + }, + { + "id": "3", + "color": "#1E9FFF" + }, { + "id": "4", + "color": "#FFB800" + }, { + "id": "5", + "color": "darkgray" + } + ], links=current_app.config.get("SYSTEM_PANEL_LINKS"), other={ + # 主页动画时长 + "keepLoad": 1200, + # 布局顶部主题 + "autoHead": False + }, header=False) + return config + + +# 生成菜单树 +def make_menu_tree(): + role = current_user.role + powers = [] + for i in role: + # 如果角色没有被启用就直接跳过 + if i.enable == 0: + continue + # 变量角色用户的权限 + for p in i.power: + # 如果权限关闭了就直接跳过 + if p.enable == 0: + continue + # 一二级菜单 + if p.type == 0 or p.type == 1: + powers.append(p) + + power_dict = 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) + + +rights_api = Api(api_bp, prefix='/rights') + +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_api.resource('/data') +class RightsData(Resource): + @authorize("admin:power:main", log=True) + def get(self): + power_data = get_power_dict() + + res = { + "data": power_data + } + return jsonify(res) + + +@rights_api.resource('/select_parent') +class RightsSelectParent(Resource): + @authorize("admin:power:main", log=True) + def get(self): + """获取选择父节点""" + power_data = select_power_dict() + res = { + "status": {"code": 200, "message": "默认"}, + "data": power_data + + } + return jsonify(res) + + +@rights_api.resource('/enable') +class RightsEnable(Resource): + @authorize("admin:power:edit", log=True) + def put(self): + 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_api.resource('/batch_remove') +class RightsBatchRemove(Resource): + @authorize("admin:power:remove", log=True) + def delete(self): + 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('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/') +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('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="更新权限成功") + + +@rights_api.resource('/configs') +class AdminConfigs(Resource): + @login_required + def get(self): + return get_render_config() + + +@rights_api.resource('/menu') +class AdminMenu(Resource): + @login_required + def get(self): + menu_tree = make_menu_tree() + return jsonify(menu_tree) diff --git a/applications/api/users/__init__.py b/applications/api/users/__init__.py new file mode 100644 index 0000000..ce61160 --- /dev/null +++ b/applications/api/users/__init__.py @@ -0,0 +1,7 @@ +from flask_restful import Api + +from applications.api import api_bp + +users_api = Api(api_bp, prefix='/users') + +from . import user, profile diff --git a/applications/view/users/profile.py b/applications/api/users/profile.py similarity index 63% rename from applications/view/users/profile.py rename to applications/api/users/profile.py index d4691aa..8eb5559 100644 --- a/applications/view/users/profile.py +++ b/applications/api/users/profile.py @@ -6,19 +6,14 @@ from flask_restful import Resource, reqparse from applications.common.utils.http import fail_api, success_api from applications.extensions import db from applications.models import User -from applications.view.users import users_bp, user_api -# TODO 分离视图操作 -from flask import render_template, make_response +from . import users_api -@user_api.resource('/avatar') +@users_api.resource('/avatar') class Avatar(Resource): """修改头像""" - def get(self): - return make_response(render_template('users/avatar.html')) - def put(self): url = request.json.get("avatar").get("src") ret = User.query.filter_by(id=current_user.id).update({"avatar": url}) @@ -28,32 +23,29 @@ class Avatar(Resource): 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): - """前用户密码""" +@users_api.resource('/updateInfo') +class ProfileInfo(Resource): @login_required - def get(self): - return make_response(render_template('users/edit_password.html')) + def put(self): + 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="更新成功") + + +@users_api.resource('/editPassword') +class EditPassword(Resource): + """前用户密码""" @login_required def put(self): diff --git a/applications/api/users/user.py b/applications/api/users/user.py new file mode 100644 index 0000000..dbfdda9 --- /dev/null +++ b/applications/api/users/user.py @@ -0,0 +1,222 @@ +from flask import request + +from flask_restful import Resource, reqparse +from flask_login import current_user +from sqlalchemy import desc + +from applications.extensions import db +from applications.common.utils.http import fail_api, success_api, table_api +from applications.common.utils.rights import authorize +from applications.models import User, Role, Dept +from applications.models import AdminLog +from . import users_api + + +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() + + +@users_api.resource('/add') +class Users(Resource): + """用户列表数据操作""" + + # @authorize("admin:user:add", log=True) + # def get(self): + # roles = Role.query.all() + # return make_response(render_template('users/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 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="增加成功", code=0) + + +@users_api.resource('/') +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('users/edit_users.html', user=user, roles=roles, checked_roles=checked_roles)) + + @authorize("admin:user:remove", log=True) + def delete(self, user_id): + # 删除用户 + res = 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() + + update_user_role(user_id, role_ids) + + return success_api(msg="更新成功") + + +@users_api.resource('/batchRemove') +class UserBatchRemove(Resource): + """批量删除""" + + @authorize("admin:user:remove", log=True) + def delete(self): + ids = request.form.getlist('ids[]') + batch_remove(ids) + return success_api(msg="批量删除成功") + + +@users_api.resource('/enable') +class UserEnable(Resource): + def put(self): + # 启用或者禁用用户 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 + + +@users_api.resource('/data') +class UsersData(Resource): + @authorize("admin:user:main", log=True) + def get(self): + 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 if dept_id else "" + 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, code=0) diff --git a/applications/view/passport/_utils.py b/applications/common/gen_captcha.py similarity index 100% rename from applications/view/passport/_utils.py rename to applications/common/gen_captcha.py diff --git a/applications/common/users.py b/applications/common/users.py new file mode 100644 index 0000000..e69de29 diff --git a/applications/common/utils/rights.py b/applications/common/utils/rights.py index f110059..2e4f8cc 100644 --- a/applications/common/utils/rights.py +++ b/applications/common/utils/rights.py @@ -23,3 +23,5 @@ def authorize(power: str, log: bool = False): return wrapper return decorator + + diff --git a/applications/extensions/init_login.py b/applications/extensions/init_login.py index 5047912..e49f6c0 100644 --- a/applications/extensions/init_login.py +++ b/applications/extensions/init_login.py @@ -5,7 +5,7 @@ def init_login_manager(app): login_manager = LoginManager() login_manager.init_app(app) - login_manager.login_view = 'passport.login' + login_manager.login_view = 'index.login' login_manager.login_message = u'请登录以访问此页面' @login_manager.user_loader diff --git a/applications/templates/file/photo.html b/applications/templates/file/photo.html index 4edb7e5..0663154 100644 --- a/applications/templates/file/photo.html +++ b/applications/templates/file/photo.html @@ -67,6 +67,7 @@ let form = layui.form let $ = layui.jquery let upload = layui.upload + let MODULE_PATH = '/api/v1/file/' let cols = [ diff --git a/applications/templates/index/admin_index.html b/applications/templates/index/admin_index.html index 17f6e37..5578dbe 100644 --- a/applications/templates/index/admin_index.html +++ b/applications/templates/index/admin_index.html @@ -84,12 +84,13 @@ let $ = layui.jquery let layer = layui.layer let popup = layui.popup + let MODULE_PATH = '/api/v1/rights/' // 框架初始化时会读取 根目录下 pear.configs.yml 文件作为初始化配置 // 你可以通过 admin.setConfigPath 方法修改配置文件位置 // 你可以通过 admin.setConfigType 方法修改配置文件类型 admin.setConfigType('json') - admin.setConfigPath("{{ url_for('rights.configs') }}") + admin.setConfigPath(MODULE_PATH + 'configs') admin.render() diff --git a/applications/templates/index/login.html b/applications/templates/index/login.html index 1da87db..13d8fe4 100644 --- a/applications/templates/index/login.html +++ b/applications/templates/index/login.html @@ -26,7 +26,7 @@
- +
@@ -45,13 +45,14 @@ let layer = layui.layer let button = layui.button let popup = layui.popup - let captchaPath = "{{ url_for('passport.get_captcha') }}" + let captchaPath = "/passport/getCaptcha" form.on('submit(login)', function (data) { // data 是表单的数据 let loader = layer.load() // 加载按钮 let btn = button.load({ elem: '.login' }) $.ajax({ + url: '/api/v1/passport/login', data: data.field, type: 'post', dataType: 'json', @@ -61,7 +62,7 @@ btn.stop(function () { if (result.success) { popup.success(result.msg, function () { - location.href = "{{ url_for('index.admin_index') }}" + location.href = "/admin" }) } else { popup.failure(result.msg, function () { diff --git a/applications/templates/rights/edit.html b/applications/templates/rights/edit.html index 2621626..8907598 100644 --- a/applications/templates/rights/edit.html +++ b/applications/templates/rights/edit.html @@ -102,10 +102,11 @@ let $ = layui.jquery let iconPicker = layui.iconPicker let dtree = layui.dtree + let MODULE_PATH = '/api/v1/rights/' dtree.renderSelect({ elem: '#selectParent', - url: '{{ url_for('rights.select_parent')}}', + url: MODULE_PATH + 'select_parent', method: 'get', selectInputName: { nodeId: 'parentId', context: 'powerName' }, skin: 'layui', @@ -142,7 +143,7 @@ data.field.icon = 'layui-icon ' + data.field.icon console.log(data.field) $.ajax({ - url: '/rights/power/' + data.field.powerId, + url: MODULE_PATH + 'power/' + data.field.powerId, data: JSON.stringify(data.field), dataType: 'json', contentType: 'application/json', diff --git a/applications/templates/rights/main.html b/applications/templates/rights/main.html index 51a13c9..bccf69d 100644 --- a/applications/templates/rights/main.html +++ b/applications/templates/rights/main.html @@ -175,7 +175,7 @@ let iconPicker = layui.iconPicker let dtree = layui.dtree - let MODULE_PATH = '/rights/' + let MODULE_PATH = '/api/v1/rights/' window.render = function () { treetable.render({ @@ -188,7 +188,7 @@ treeDefaultClose: true, toolbar: '#power-toolbar', elem: '#power_table', - url: '{{ url_for('rights.data') }}', + url: MODULE_PATH + 'data', page: false, cols: [ [ @@ -295,7 +295,7 @@ title: '修改', shade: 0.1, area: ['450px', '500px'], - content: MODULE_PATH + 'power/' + obj.data['powerId'] + content: '/rights/power/' + obj.data['powerId'] }) } window.remove = function (obj) { @@ -367,7 +367,7 @@ {#添加权限数据页面#} dtree.renderSelect({ elem: '#select_parent_dept', - url: '{{ url_for('rights.select_parent') }}', + url: MODULE_PATH + 'select_parent', method: 'get', selectInputName: { nodeId: 'parentId', context: 'powerName' }, skin: 'layui', @@ -400,7 +400,7 @@ form.on('submit(power-save)', function (data) { data.field.icon = 'layui-icon ' + data.field.icon $.ajax({ - url: '/rights/power', + url: MODULE_PATH + 'power', data: JSON.stringify(data.field), dataType: 'json', contentType: 'application/json', diff --git a/applications/templates/users/add.html b/applications/templates/users/add.html index b34e67d..88573cc 100644 --- a/applications/templates/users/add.html +++ b/applications/templates/users/add.html @@ -62,6 +62,8 @@ layui.use(['form', 'jquery'], function () { let form = layui.form let $ = layui.jquery + let MODULE_PATH = '/api/v1/users/' + form.on('submit(user-save)', function (data) { let roleIds = '' $('input[type=checkbox]:checked').each(function () { @@ -71,7 +73,7 @@ data.field.roleIds = roleIds $.ajax({ - url: '/users/add', + url: MODULE_PATH + 'add', data: JSON.stringify(data.field), dataType: 'json', contentType: 'application/json', diff --git a/applications/templates/users/edit_password.html b/applications/templates/users/edit_password.html deleted file mode 100644 index fae762d..0000000 --- a/applications/templates/users/edit_password.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - 修改密码 - {% include 'common/header.html' %} - - -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
- - -
-
-
-{% include 'common/footer.html' %} - - - \ No newline at end of file diff --git a/applications/templates/users/edit_users.html b/applications/templates/users/edit_users.html index 5ab5653..d677cfe 100644 --- a/applications/templates/users/edit_users.html +++ b/applications/templates/users/edit_users.html @@ -74,10 +74,11 @@ let form = layui.form let $ = layui.jquery let dtree = layui.dtree + let MODULE_PATH = '/api/v1/users/' dtree.renderSelect({ elem: '#selectParent', - url: '/dept/tree', + url: '/api/v1/dept/tree', method: 'get', selectInputName: { nodeId: 'deptId', context: 'deptName' }, skin: 'layui', @@ -93,7 +94,7 @@ roleIds = roleIds.substr(0, roleIds.length - 1) data.field.roleIds = roleIds $.ajax({ - url: '/users/' + data.field.userId, + url: MODULE_PATH + data.field.userId, data: JSON.stringify(data.field), dataType: 'json', contentType: 'application/json', @@ -101,7 +102,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.layui.table.reload('user-table') }) } else { diff --git a/applications/templates/users/main.html b/applications/templates/users/main.html index d94f8c3..22ac79d 100644 --- a/applications/templates/users/main.html +++ b/applications/templates/users/main.html @@ -111,7 +111,7 @@ let dtree = layui.dtree let popup = layui.popup let common = layui.common - let MODULE_PATH = '/users/' + let MODULE_PATH = '/api/v1/users/' // 表格数据 let cols = [ @@ -146,7 +146,7 @@ dtree.render({ elem: '#dept-tree', method: 'get', - url: '/dept/tree', + url: '/api/v1/dept/tree', dataFormat: 'list', line: true, skin: 'laySimple', @@ -239,7 +239,7 @@ title: '新增', shade: 0.1, area: ['550px', '550px'], - content: MODULE_PATH + 'add' + content: '/users/' + 'add' }) } @@ -249,7 +249,7 @@ title: '修改', shade: 0.1, area: ['550px', '500px'], - content: MODULE_PATH + obj.data['id'] + content: '/users/' + obj.data['id'] }) } diff --git a/applications/templates/users/profile.html b/applications/templates/users/profile.html index 6b8742b..aee6d37 100644 --- a/applications/templates/users/profile.html +++ b/applications/templates/users/profile.html @@ -171,19 +171,66 @@
{% include 'common/footer.html' %} + + + - diff --git a/applications/view/__init__.py b/applications/view/__init__.py index 3ccfb53..782470b 100644 --- a/applications/view/__init__.py +++ b/applications/view/__init__.py @@ -2,19 +2,16 @@ from flask import Flask from .index import index_bp from .logs_view import logs_bp -from .passport import passport_bp -from .rights import rights_bp from .roles import role_bp -from .users import users_bp from . import department from . import file +from . import rights +from . import passport +from . import users def init_view(app: Flask): app.register_blueprint(index_bp) app.register_blueprint(logs_bp) - app.register_blueprint(passport_bp) - app.register_blueprint(rights_bp) app.register_blueprint(role_bp) - app.register_blueprint(users_bp) diff --git a/applications/view/logs_view.py b/applications/view/logs_view.py index 5a9dd9d..ab3ad6c 100644 --- a/applications/view/logs_view.py +++ b/applications/view/logs_view.py @@ -27,7 +27,7 @@ def login_log(): page=page, per_page=limit, error_out=False) data = marshal(log_paginate.items, log_fields) - return table_api(data=data, count=log_paginate.total) + return table_api(data=data, count=log_paginate.total, code=0) @logs_bp.get('/access_log') diff --git a/applications/view/passport.py b/applications/view/passport.py new file mode 100644 index 0000000..09023fb --- /dev/null +++ b/applications/view/passport.py @@ -0,0 +1,32 @@ +from flask import Blueprint, session, redirect, render_template, url_for +from flask_login import login_required, logout_user, current_user + +from applications.common.gen_captcha import get_captcha_image +from applications.common.utils.http import success_api + +# 获取验证码 +from applications.view import index_bp + + +@index_bp.get('/passport/getCaptcha') +def get_captcha(): + resp, code = get_captcha_image() + session["code"] = code + return resp + + +# 退出登录 +@index_bp.post('/passport/logout') +@login_required +def logout(): + logout_user() + session.pop('permissions') + return success_api(msg="注销成功") + + +@index_bp.get('/passport/login') +def login(): + if current_user.is_authenticated: + return redirect(url_for('admin.index')) + # TODO 分离视图操作 最终实现接口登录与视图登录两套逻辑 + return render_template('index/login.html') diff --git a/applications/view/passport/__init__.py b/applications/view/passport/__init__.py deleted file mode 100644 index 7ff048c..0000000 --- a/applications/view/passport/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask import Blueprint, session -from flask_login import login_required, logout_user - -from applications.common.utils.http import success_api -from ._utils import get_captcha_image, add_auth_session - -passport_bp = Blueprint('passport', __name__, url_prefix='/passport') - - -# 获取验证码 -@passport_bp.get('/getCaptcha') -def get_captcha(): - resp, code = get_captcha_image() - session["code"] = code - return resp - - -# 退出登录 -@passport_bp.post('/logout') -@login_required -def logout(): - logout_user() - session.pop('permissions') - return success_api(msg="注销成功") - - -from . import api diff --git a/applications/view/rights.py b/applications/view/rights.py new file mode 100644 index 0000000..1a128f6 --- /dev/null +++ b/applications/view/rights.py @@ -0,0 +1,23 @@ +from flask import render_template + +from applications.common.utils.rights import authorize +from applications.models import Power +from applications.view import index_bp + + +@index_bp.get('/rights/') +@authorize("admin:power:main", log=True) +def rights_index(): + return render_template('rights/main.html') + + +@index_bp.get('/rights/power/') +@authorize("admin:power:edit", log=True) +def get(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 render_template('rights/edit.html', power=power, icon=icon) diff --git a/applications/view/rights/__init__.py b/applications/view/rights/__init__.py deleted file mode 100644 index 8184896..0000000 --- a/applications/view/rights/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from flask import Blueprint, render_template -from flask_restful import Api - -from ...common.utils.rights import authorize - -rights_bp = Blueprint('rights', __name__, url_prefix='/rights') -rights_api = Api(rights_bp) - - -@rights_bp.get('/') -@authorize("admin:power:main", log=True) -def index(): - return render_template('rights/main.html') - - -from . import routes -from . import right diff --git a/applications/view/rights/_utils.py b/applications/view/rights/_utils.py deleted file mode 100644 index e94745f..0000000 --- a/applications/view/rights/_utils.py +++ /dev/null @@ -1,154 +0,0 @@ -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.serialization import power_fields -from applications.extensions import db -from applications.models import Power, Role, User - -from applications.common.serialization import power2_fields - - -def get_render_config(): - # 网站配置 - config = dict(logo={ - # 网站名称 - "title": current_app.config.get("SYSTEM_NAME"), - # 网站图标 - "image": "/static/admin/admin/images/logo.png" - # 菜单配置 - }, menu={ - # 菜单数据来源 - "data": "/rights/menu", - "collaspe": True, - # 是否同时只打开一个菜单目录 - "accordion": True, - "method": "GET", - # 是否开启多系统菜单模式 - "control": False, - # 默认选中的菜单项 - "select": "0", - # 是否开启异步菜单,false 时 data 属性设置为菜单数据,false 时为 json 文件或后端接口 - "async": True - }, tab={ - # 是否开启多选项卡 - "muiltTab": True, - # 切换选项卡时,是否刷新页面状态 - "keepState": True, - # 是否开启 Tab 记忆 - "session": True, - # 最大可打开的选项卡数量 - "tabMax": 30, - "index": { - # 标识 ID , 建议与菜单项中的 ID 一致 - "id": "10", - # 页面地址 - "href": "/admin/welcome", - # 标题 - "title": "首页" - } - }, theme={ - # 默认主题色,对应 colors 配置中的 ID 标识 - "defaultColor": "2", - # 默认的菜单主题 dark-theme 黑 / light-theme 白 - "defaultMenu": "dark-theme", - # 是否允许用户切换主题,false 时关闭自定义主题面板 - "allowCustom": True - }, colors=[{ - "id": "1", - "color": "#2d8cf0" - }, - { - "id": "2", - "color": "#5FB878" - }, - { - "id": "3", - "color": "#1E9FFF" - }, { - "id": "4", - "color": "#FFB800" - }, { - "id": "5", - "color": "darkgray" - } - ], links=current_app.config.get("SYSTEM_PANEL_LINKS"), other={ - # 主页动画时长 - "keepLoad": 1200, - # 布局顶部主题 - "autoHead": False - }, header=False) - return config - - -# 生成菜单树 -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) diff --git a/applications/view/rights/right.py b/applications/view/rights/right.py deleted file mode 100644 index 0562eb0..0000000 --- a/applications/view/rights/right.py +++ /dev/null @@ -1,158 +0,0 @@ -from flask import request, jsonify -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 - -# TODO 分离视图操作 -from flask import render_template, make_response - -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('/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('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/') -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('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="更新权限成功") diff --git a/applications/view/rights/routes.py b/applications/view/rights/routes.py deleted file mode 100644 index 0fa21a4..0000000 --- a/applications/view/rights/routes.py +++ /dev/null @@ -1,21 +0,0 @@ -# 渲染配置 -from flask import jsonify -from flask_login import login_required - -from . import rights_bp - -from ._utils import get_render_config, make_menu_tree - - -@rights_bp.get('/configs') -@login_required -def configs(): - return get_render_config() - - -# 菜单 -@rights_bp.get('/menu') -@login_required -def menu(): - menu_tree = make_menu_tree() - return jsonify(menu_tree) diff --git a/applications/view/users.py b/applications/view/users.py new file mode 100644 index 0000000..561bfdb --- /dev/null +++ b/applications/view/users.py @@ -0,0 +1,47 @@ +from flask import render_template +from flask_login import login_required, current_user +from sqlalchemy import desc + +from applications.common.utils.rights import authorize +from applications.models import AdminLog, Role, User + +from . import index_bp + + +# 用户增加 +@index_bp.get('/users/') +@authorize("admin:user:main", log=True) +def users_main(): + return render_template('users/main.html') + + +@index_bp.get('/users/center') +@login_required +def users_center(): + 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('users/profile.html', user_info=current_user, user_logs=user_logs) + + +@index_bp.get('/users/add') +@authorize("admin:user:add", log=True) +def users_get_user(): + roles = Role.query.all() + return render_template('users/add.html', roles=roles) + + +@index_bp.get('/users/') +@authorize("admin:user:edit", log=True) +def users_user_id_view(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 render_template('users/edit_users.html', user=user, roles=roles, checked_roles=checked_roles) + + +@index_bp.get('/users/avatar') +def users_avatar_view(): + return render_template('users/avatar.html') diff --git a/applications/view/users/__init__.py b/applications/view/users/__init__.py deleted file mode 100644 index 396d1f1..0000000 --- a/applications/view/users/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -from flask import Blueprint, render_template -from flask_login import login_required, current_user -from flask_restful import Api -from sqlalchemy import desc - -from applications.common.utils.rights import authorize -from ...models import AdminLog - -users_bp = Blueprint('users', __name__, url_prefix='/users') - - -# 用户增加 -@users_bp.get('/') -@authorize("admin:user:main", log=True) -def get(): - return render_template('users/main.html') - - -@users_bp.get('/center') -@login_required -def center(): - 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('users/profile.html', user_info=current_user, user_logs=user_logs) - - -user_api = Api(users_bp) -from . import profile, _utils -from . import user_view diff --git a/applications/view/users/_utils.py b/applications/view/users/_utils.py deleted file mode 100644 index e1d6270..0000000 --- a/applications/view/users/_utils.py +++ /dev/null @@ -1,55 +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 -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() diff --git a/applications/view/users/user_view.py b/applications/view/users/user_view.py deleted file mode 100644 index c10a849..0000000 --- a/applications/view/users/user_view.py +++ /dev/null @@ -1,171 +0,0 @@ -from flask import request -from flask_restful import Resource, reqparse -from applications.extensions import db - -from applications.common.utils.http import fail_api, success_api, table_api -from applications.common.utils.rights import authorize -from applications.models import User, Role, Dept -from applications.view.users import user_api, users_bp, _utils - -# TODO 分离视图操作 -from flask import render_template, make_response - - -@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('users/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('/') -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('users/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 - - -@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 if dept_id else "" - 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)