diff --git a/applications/view/system/power.py b/applications/view/system/power.py index 479874c..fa838cb 100644 --- a/applications/view/system/power.py +++ b/applications/view/system/power.py @@ -1,7 +1,7 @@ from flask import Blueprint, render_template, request, jsonify from applications.common import curd -from applications.common.utils.http import success_api, fail_api +from applications.common.utils.http import success_api, fail_api, table_api from applications.common.utils.rights import authorize from applications.common.utils.validate import str_escape from applications.extensions import db @@ -22,10 +22,25 @@ def index(): @authorize("system:power:main") def data(): power = Power.query.all() - res = { - "data": PowerSchema(many=True).dump(power) - } - return jsonify(res) + data = PowerSchema(many=True).dump(power) + + # 创建一个字典,用于存储每个节点的子节点 + tree = {} + for item in data: + item["children"] = [] + tree[item["id"]] = item + + # 构建树形结构 + root_nodes = [] + for item in data: + parent_id = item["parent_id"] if item["parent_id"] != 0 else None + if parent_id is None: + root_nodes.append(item) + else: + if parent_id in tree: + tree[parent_id]["children"].append(item) + + return table_api(msg="请求成功", data=root_nodes) @bp.get('/add') @@ -53,28 +68,25 @@ def select_parent(): @authorize("system:power:add", log=True) def save(): req = request.get_json(force=True) - icon = str_escape(req.get("icon")) - openType = str_escape(req.get("openType")) - parentId = str_escape(req.get("parentId")) - powerCode = str_escape(req.get("powerCode")) - powerName = str_escape(req.get("powerName")) - powerType = str_escape(req.get("powerType")) - powerUrl = str_escape(req.get("powerUrl")) - sort = str_escape(req.get("sort")) - power = Power( - icon=icon, - open_type=openType, - parent_id=parentId, - code=powerCode, - name=powerName, - type=powerType, - url=powerUrl, - sort=sort, - enable=1 - ) - r = db.session.add(power) + + data = { + "icon": str_escape(req.get("icon")), + "open_type": str_escape(req.get("openType")), + "parent_id": str_escape(req.get("parentId")), + "code": str_escape(req.get("powerCode")), + "name": str_escape(req.get("powerName")), + "type": str_escape(req.get("powerType")), + "url": str_escape(req.get("powerUrl")), + "sort": str_escape(req.get("sort")) + } + + if not data['sort'].isdigit(): + return fail_api(msg="参数 sort 需为整数") + + power = Power(**data) + db.session.add(power) db.session.commit() - return success_api(msg="成功") + return success_api(msg="权限添加成功") # 权限编辑 @@ -96,6 +108,7 @@ def edit(_id): def update(): req_json = request.get_json(force=True) id = request.get_json(force=True).get("powerId") + data = { "icon": str_escape(req_json.get("icon")), "open_type": str_escape(req_json.get("openType")), @@ -106,6 +119,10 @@ def update(): "url": str_escape(req_json.get("powerUrl")), "sort": str_escape(req_json.get("sort")) } + + if not data['sort'].isdigit(): + return fail_api(msg="参数 sort 需为整数") + res = Power.query.filter_by(id=id).update(data) db.session.commit() if not res: @@ -118,7 +135,7 @@ def update(): @authorize("system:power:edit", log=True) def enable(): _id = request.get_json(force=True).get('powerId') - if id: + if _id: res = curd.enable_status(Power, _id) if not res: return fail_api(msg="出错啦") @@ -144,11 +161,40 @@ def dis_enable(): @authorize("system:power:remove", log=True) def remove(id): power = Power.query.filter_by(id=id).first() - power.role = [] + + if power: + power.role = [] r = Power.query.filter_by(id=id).delete() db.session.commit() if r: return success_api(msg="删除成功") else: - return fail_api(msg="删除失败") \ No newline at end of file + return fail_api(msg="删除失败") + + +# 批量删除 +@bp.delete('/batchRemove') +@authorize("system:power:remove", log=True) +def batch_remove(): + ids = request.form.getlist('ids[]') + + if not ids: + return fail_api(msg="未提供删除 ID") + + for id in ids: + + if not id.isdigit(): + db.session.rollback() + return fail_api(msg="参数提供错误") + + id = int(id) + + power = Power.query.filter_by(id=id).first() + if power: + # 清空关联的角色(如果需要) + power.role = [] + db.session.delete(power) + + db.session.commit() + return success_api(msg="批量删除成功") diff --git a/static/system/component/pear/css/module/treetable.css b/static/system/component/pear/css/module/treetable.css deleted file mode 100644 index da849b8..0000000 --- a/static/system/component/pear/css/module/treetable.css +++ /dev/null @@ -1,25 +0,0 @@ -.treeTable-icon i:last-child{ - display: none!important; -} - -.treeTable-empty{ - margin-left: -3px; -} -.treeTable-empty { - width: 20px; - display: inline-block; -} - -.treeTable-icon { - cursor: pointer; -} - -.treeTable-icon .layui-icon-triangle-d:before { - content: "\e623"; -} - -.treeTable-icon.open .layui-icon-triangle-d:before { - content: "\e625"; - background-color: transparent; -} - diff --git a/static/system/component/pear/css/pear.css b/static/system/component/pear/css/pear.css index e35a690..82ca512 100644 --- a/static/system/component/pear/css/pear.css +++ b/static/system/component/pear/css/pear.css @@ -14,4 +14,4 @@ @import url("module/dtree/font/dtreefont.css"); @import url("module/dtree/dtree.css"); @import url("module/layer.css"); -@import url("module/layout.css"); +@import url("module/layout.css"); \ No newline at end of file diff --git a/static/system/component/pear/module/treetable.js b/static/system/component/pear/module/treetable.js deleted file mode 100644 index ab0d7a9..0000000 --- a/static/system/component/pear/module/treetable.js +++ /dev/null @@ -1,253 +0,0 @@ -layui.define(['layer', 'table'], function (exports) { - var $ = layui.jquery; - var layer = layui.layer; - var table = layui.table; - - var instances = []; - - var treetable = { - - render: function (param) { - param.method = param.method?param.method:"GET"; - if (!treetable.checkParam(param)) { - return; - } - if (param.data) { - treetable.init(param, param.data); - } else { - if(param.method === 'post' || param.method === 'POST') { - $.post(param.url, param.where, function(res){ - if(param.parseData){ - res = param.parseData(res); - param.data = res.data; - } - treetable.init(param, res.data); - }); - } else { - $.get(param.url, param.where, function(res){ - if(param.parseData){ - res = param.parseData(res); - param.data = res.data; - } - treetable.init(param, res.data); - }); - } - } - }, - // 渲染表格 - init: function (param, data) { - var mData = []; - var doneCallback = param.done; - var tNodes = data; - for (var i = 0; i < tNodes.length; i++) { - var tt = tNodes[i]; - if (!tt.id) { - tt.id = tt[param.treeIdName]; - } - if (!tt.pid) { - tt.pid = tt[param.treePidName]; - } - } - - var sort = function (s_pid, data) { - for (var i = 0; i < data.length; i++) { - if (data[i].pid == s_pid) { - var len = mData.length; - if (len > 0 && mData[len - 1].id == s_pid) { - mData[len - 1].isParent = true; - } - mData.push(data[i]); - sort(data[i].id, data); - } - } - }; - sort(param.treeSpid, tNodes); - - param.prevUrl = param.url; - param.url = undefined; - param.data = mData; - param.page = { - count: param.data.length, - limit: param.data.length - }; - param.cols[0][param.treeColIndex].templet = function (d) { - var mId = d.id; - var mPid = d.pid; - var isDir = d.isParent; - var emptyNum = treetable.getEmptyNum(mPid, mData); - var iconHtml = ''; - for (var i = 0; i < emptyNum; i++) { - iconHtml += ''; - } - if (isDir) { - iconHtml += ' '; - } else { - iconHtml += ''; - } - iconHtml += '  '; - var ttype = isDir ? 'dir' : 'file'; - var vg = ''; - return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '' - }; - - param.done = function (res, curr, count) { - $(param.elem).next().addClass('treeTable'); - $('.treeTable .layui-table-page').css('display', 'none'); - $(param.elem).next().attr('treeLinkage', param.treeLinkage); - if (param.treeDefaultClose) { - treetable.foldAll(param.elem); - } - if (doneCallback) { - doneCallback(res, curr, count); - } - }; - - // 渲染表格 - table.render(param); - var result = instances.some(item=>item.key===param.elem); - if(!result){ - instances.push({key:param.elem,value:param}); - } - }, - reload: function(elem) { - instances.forEach(function(item){ - if(item.key === elem) { - $(elem).next().remove(); - item.value.data = undefined; - item.value.url = item.value.prevUrl; - treetable.render(item.value); - } - }) - }, - search: function(elem,keyword) { - var $tds = $(elem).next('.treeTable').find('.layui-table-body tbody tr td'); - if (!keyword) { - $tds.css('background-color', 'transparent'); - layer.msg("请输入关键字", {icon: 5}); - return; - } - var searchCount = 0; - $tds.each(function () { - $(this).css('background-color', 'transparent'); - if ($(this).text().indexOf(keyword) >= 0) { - $(this).css('background-color', 'rgba(250,230,160,0.5)'); - if (searchCount == 0) { - $('body,html').stop(true); - $('body,html').animate({scrollTop: $(this).offset().top - 150}, 500); - } - searchCount++; - } - }); - if (searchCount == 0) { - layer.msg("没有匹配结果", {icon: 5}); - } else { - treetable.expandAll(elem); - } - }, - getEmptyNum: function (pid, data) { - var num = 0; - if (!pid) { - return num; - } - var tPid; - for (var i = 0; i < data.length; i++) { - if (pid == data[i].id) { - num += 1; - tPid = data[i].pid; - break; - } - } - return num + treetable.getEmptyNum(tPid, data); - }, - // 展开/折叠行 - toggleRows: function ($dom, linkage) { - var type = $dom.attr('lay-ttype'); - if ('file' == type) { - return; - } - var mId = $dom.attr('lay-tid'); - var isOpen = $dom.hasClass('open'); - if (isOpen) { - $dom.removeClass('open'); - } else { - $dom.addClass('open'); - } - $dom.closest('tbody').find('tr').each(function () { - var $ti = $(this).find('.treeTable-icon'); - var pid = $ti.attr('lay-tpid'); - var ttype = $ti.attr('lay-ttype'); - var tOpen = $ti.hasClass('open'); - if (mId == pid) { - if (isOpen) { - $(this).hide(); - if ('dir' == ttype && tOpen == isOpen) { - $ti.trigger('click'); - } - } else { - $(this).show(); - if (linkage && 'dir' == ttype && tOpen == isOpen) { - $ti.trigger('click'); - } - } - } - }); - }, - // 检查参数 - checkParam: function (param) { - if (!param.treeSpid && param.treeSpid != 0) { - layer.msg('参数treeSpid不能为空', {icon: 5}); - return false; - } - - if (!param.treeIdName) { - layer.msg('参数treeIdName不能为空', {icon: 5}); - return false; - } - - if (!param.treePidName) { - layer.msg('参数treePidName不能为空', {icon: 5}); - return false; - } - - if (!param.treeColIndex && param.treeColIndex != 0) { - layer.msg('参数treeColIndex不能为空', {icon: 5}); - return false; - } - return true; - }, - // 展开所有 - expandAll: function (dom) { - $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { - var $ti = $(this).find('.treeTable-icon'); - var ttype = $ti.attr('lay-ttype'); - var tOpen = $ti.hasClass('open'); - if ('dir' == ttype && !tOpen) { - $ti.trigger('click'); - } - }); - }, - // 折叠所有 - foldAll: function (dom) { - $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { - var $ti = $(this).find('.treeTable-icon'); - var ttype = $ti.attr('lay-ttype'); - var tOpen = $ti.hasClass('open'); - if ('dir' == ttype && tOpen) { - $ti.trigger('click'); - } - }); - } - }; - - // 给图标列绑定事件 - $('body').on('click', '.treeTable .treeTable-icon', function () { - var treeLinkage = $(this).parents('.treeTable').attr('treeLinkage'); - if ('true' == treeLinkage) { - treetable.toggleRows($(this), true); - } else { - treetable.toggleRows($(this), false); - } - }); - - exports('treetable', treetable); -}); \ No newline at end of file diff --git a/templates/system/power/add.html b/templates/system/power/add.html index 9460fb3..188a193 100644 --- a/templates/system/power/add.html +++ b/templates/system/power/add.html @@ -18,7 +18,7 @@
-
@@ -26,7 +26,7 @@
+ class="layui-input" lay-verify="required">
@@ -41,15 +41,15 @@
+ class="layui-input" lay-verify="required">
@@ -62,9 +62,9 @@
-
- +
+
@@ -72,11 +72,11 @@
- - diff --git a/templates/system/power/edit.html b/templates/system/power/edit.html index aa7c695..6312122 100644 --- a/templates/system/power/edit.html +++ b/templates/system/power/edit.html @@ -12,7 +12,7 @@
-
@@ -25,7 +25,7 @@
-
@@ -59,9 +59,16 @@
@@ -74,9 +81,9 @@
-
- +
+
@@ -84,11 +91,11 @@
- - diff --git a/templates/system/power/main.html b/templates/system/power/main.html index 67617ff..0211bcd 100644 --- a/templates/system/power/main.html +++ b/templates/system/power/main.html @@ -8,16 +8,16 @@
-
+
- - @@ -33,13 +33,13 @@ @@ -85,198 +84,198 @@ {% include 'system/common/footer.html' %} \ No newline at end of file diff --git a/templates/system/role/add.html b/templates/system/role/add.html index 17075e3..93b41e7 100644 --- a/templates/system/role/add.html +++ b/templates/system/role/add.html @@ -11,14 +11,14 @@
-
-
@@ -32,7 +32,7 @@
-
diff --git a/templates/system/role/edit.html b/templates/system/role/edit.html index 360bcf6..3a595a6 100644 --- a/templates/system/role/edit.html +++ b/templates/system/role/edit.html @@ -11,21 +11,21 @@
-
-
-
@@ -41,7 +41,7 @@
-
diff --git a/templates/system/role/main.html b/templates/system/role/main.html index 8463b11..20f92ad 100644 --- a/templates/system/role/main.html +++ b/templates/system/role/main.html @@ -81,7 +81,7 @@ [ {title: '编号', field: 'id', align: 'center'}, {title: '角色名', field: 'name', align: 'center', width: 100}, - {title: 'Key值', field: 'code', align: 'center'}, + {title: '标识', field: 'code', align: 'center'}, {title: '描述', field: 'details', align: 'center'}, {title: '是否可用', field: 'enable', align: 'center', templet: '#role-enable'}, {title: '排序', field: 'sort', align: 'center'},