require("fwutils.webapi") -- CREATE TABLE `fw_menu` ( -- `id` int NOT NULL AUTO_INCREMENT, -- `role_id` int DEFAULT NULL, -- `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, -- `path` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, -- `icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, -- `sort` int DEFAULT NULL, -- `parent_id` int DEFAULT NULL, -- `create_time` datetime DEFAULT NULL, -- `update_time` datetime DEFAULT NULL, -- `delete_time` datetime DEFAULT NULL, -- PRIMARY KEY (`id`) -- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; local M = {} function M.get_by_id(id,conn) local select = conn:select() select:table("fw_menu LEFT JOIN fw_role ON fw_menu.role_id = fw_role.id") select:field({ "fw_menu.id", "fw_menu.title", "fw_menu.path", "fw_menu.icon", "fw_menu.sort", "fw_menu.parent_id", "fw_menu.create_time", "fw_menu.update_time", "fw_menu.delete_time", "fw_role.title as role_title", "fw_role.id as role_id", }) select:where_i32("fw_menu.id","=",id) select:where_expression("AND fw_menu.delete_time IS NULL") select:limit(0,1) local result = select:query() if result:row_count() == 0 then return nil end local d = result:table()[1] return d end function M.add(data,conn) local insert = conn:insert() insert:table("fw_menu") insert:set_str("title",data.title) insert:set_str("path",data.path) insert:set_i32("role_id",data.role_id) if data.icon ~= nil then insert:set_str("icon",data.icon) end if data.sort ~= nil then insert:set_i32("sort",data.sort) end if data.parent_id ~= nil and data.parent_id ~= 0 then insert:set_i32("parent_id",data.parent_id) end insert:set_not_ppst("create_time","NOW()") local d = insert:exec() return d == 1 end function M.update(data,conn) local update = conn:update() update:table("fw_menu") if data.title ~= nil then update:set_str("title",data.title) end if data.path ~= nil then update:set_str("path",data.path) end if data.role_id ~= nil then update:set_i32("role_id",data.role_id) end if data.icon ~= nil then update:set_str("icon",data.icon) end if data.sort ~= nil then update:set_i32("sort",data.sort) end if data.parent_id ~= nil then update:set_i32("parent_id",data.parent_id) end update:set("update_time=NOW()") update:where_i32("id","=",data.id) local d = update:exec() return d == 1 end function M.delete(id,conn) local update = conn:update() update:table("fw_menu") update:set("delete_time=NOW()") update:where_i32("id","=",id) local d = update:exec() return d == 1 end function M.list(search,limit,conn) if search.role_id == -1 then return { count = 0, data = {} } end return query_model_ex(conn,[=[ fw_menu LEFT JOIN fw_role ON fw_menu.role_id = fw_role.id ]=],{ "fw_menu.id", "fw_menu.title", "fw_menu.path", "fw_menu.icon", "fw_menu.sort", "fw_menu.parent_id", "fw_menu.create_time", "fw_menu.update_time", "fw_menu.delete_time", "fw_role.title as role_title", "fw_role.id as role_id", },limit.start,limit.length,function(sel) if search.role_id ~= nil and search.role_id ~= 0 then sel:where_i32("fw_menu.role_id","=",search.role_id) end sel:where_expression("AND fw_menu.delete_time IS NULL") end,function(sel_data) sel_data:orderby("fw_menu.sort DESC") end) end M.make_bytecode = function(role_id,conn) -- 查询菜单表 local select = conn:select() select:table("fw_menu") select:where_expression("AND delete_time IS NULL") if role_id ~= nil then select:where_i32("role_id", "=", role_id) end local result = select:query() local bc = {} local items_by_id = {} -- 通过id快速查找菜单项:{id = {role_id, title, item, parent_id}} local items_with_parent = {} -- 存储有父级的菜单项 -- 第一遍:读取所有菜单项并存储 while result:next() do local id = result:get("id") local role_id = tostring(result:get("role_id")) local title = result:get("title") local path = result:get("path") local icon = result:get("icon") local sort = result:get("sort") local parent_id = result:get("parent_id") if not title or title == "" then goto continue end if bc[role_id] == nil then bc[role_id] = {} end local item = { path = path, icon = icon, sort = sort, } -- 存储所有菜单项信息 items_by_id[id] = { role_id = role_id, title = title, item = item, parent_id = parent_id } -- 如果parent_id为空,则作为顶层菜单项 if parent_id == nil or parent_id == 0 then bc[role_id][title] = item else -- 有父级,记录下来稍后处理 table.insert(items_with_parent, { id = id, role_id = role_id, title = title, item = item, parent_id = parent_id }) end ::continue:: end -- 第二遍:处理有父级的菜单项,构建children结构 for _, menu_item in ipairs(items_with_parent) do local parent_info = items_by_id[menu_item.parent_id] if parent_info then local parent_item = parent_info.item -- 如果父项还没有children表,创建它 if not parent_item.children then parent_item.children = {} end -- 将子项添加到父项的children中 parent_item.children[menu_item.title] = menu_item.item end end local code = "return " .. require("serpent").serialize(bc, {comment = false}) utils.save_file(fw.website_dir().."/"..(fwutils_config.path.luabytecode:gsub("%.", "/")).."/menu_bc.lua",code) return true end M.bytecode = function(role_id) local menu_bc = require(fwutils_config.path.luabytecode..".menu_bc") return menu_bc[string.format("%d",role_id)] end return M