更新
This commit is contained in:
@@ -6,35 +6,35 @@ local cjson = require("cjson")
|
||||
|
||||
M.start = function(dirpath)
|
||||
local storage = localstorage.new()
|
||||
fw.set_ptr("localstorage_cache",storage:self())
|
||||
fw.set_ptr("alocalstorage_cache",storage:self())
|
||||
if storage:open(dirpath) == false then
|
||||
return false,storage:last_error()
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
M.close = function()
|
||||
localstorage.new(localstorage_cache):close()
|
||||
end
|
||||
M.get = function(key)
|
||||
return localstorage.new(localstorage_cache):read(key)
|
||||
end
|
||||
M.get_json = function(key)
|
||||
local value = M.get(key)
|
||||
if value then
|
||||
return cjson.decode(value)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
M.set = function(key,value)
|
||||
localstorage.new(localstorage_cache):write(key,value)
|
||||
end
|
||||
M.set_json = function(key,value)
|
||||
M.set(key,cjson.encode(value))
|
||||
end
|
||||
M.del = function(key)
|
||||
localstorage.new(localstorage_cache):del(key)
|
||||
end
|
||||
-- M.close = function()
|
||||
-- localstorage.new(localstorage_cache):close()
|
||||
-- end
|
||||
-- M.get = function(key)
|
||||
-- return localstorage.new(localstorage_cache):read(key)
|
||||
-- end
|
||||
-- M.get_json = function(key)
|
||||
-- local value = M.get(key)
|
||||
-- if value then
|
||||
-- return cjson.decode(value)
|
||||
-- end
|
||||
-- return nil
|
||||
-- end
|
||||
-- M.set = function(key,value)
|
||||
-- localstorage.new(localstorage_cache):write(key,value)
|
||||
-- end
|
||||
-- M.set_json = function(key,value)
|
||||
-- M.set(key,cjson.encode(value))
|
||||
-- end
|
||||
-- M.del = function(key)
|
||||
-- localstorage.new(localstorage_cache):del(key)
|
||||
-- end
|
||||
return M
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
local fwutils_config = require("fwutils.config")
|
||||
local develop_menu = require("fwutils.develop.function.menu")
|
||||
|
||||
local function get_by_id()
|
||||
local M = {}
|
||||
M.get_by_id = function()
|
||||
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
succ(develop_menu.get_by_id(pint("id"),conn))
|
||||
end
|
||||
|
||||
local function add()
|
||||
M.add = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_menu.add(data,conn) then
|
||||
@@ -16,7 +17,7 @@ local function add()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function update()
|
||||
M.update = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_menu.update(data,conn) then
|
||||
@@ -25,7 +26,7 @@ local function update()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function delete()
|
||||
M.delete = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_menu.delete(data.id,conn) then
|
||||
@@ -34,23 +35,26 @@ local function delete()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function list()
|
||||
M.list = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
local d = develop_menu.list(data.search,data.limit,conn)
|
||||
succ(d)
|
||||
end
|
||||
local function refresh()
|
||||
M.refresh = function()
|
||||
local module_menu = require("fwutils.develop.function.menu")
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
module_menu.make_bytecode(nil,conn)
|
||||
succ({})
|
||||
end
|
||||
exec({
|
||||
get_by_id = get_by_id,
|
||||
list = list,
|
||||
add = add,
|
||||
update = update,
|
||||
delete = delete,
|
||||
refresh = refresh,
|
||||
})
|
||||
M.exec = function()
|
||||
exec({
|
||||
get_by_id = M.get_by_id,
|
||||
list = M.list,
|
||||
add = M.add,
|
||||
update = M.update,
|
||||
delete = M.delete,
|
||||
refresh = M.refresh,
|
||||
})
|
||||
end
|
||||
return M
|
||||
@@ -2,12 +2,19 @@ require("app.app")
|
||||
|
||||
local fwutils_config = require("fwutils.config")
|
||||
local develop_role = require("fwutils.develop.function.role")
|
||||
local function list()
|
||||
|
||||
|
||||
local M = {}
|
||||
M.list = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
local d = develop_role.list(data.search,data.limit,conn)
|
||||
succ(d)
|
||||
succ(develop_role.list(data.search,data.limit,conn))
|
||||
|
||||
end
|
||||
exec({
|
||||
list = list,
|
||||
})
|
||||
M.exec = function()
|
||||
exec({
|
||||
list = M.list,
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -3,12 +3,13 @@ require("app.app")
|
||||
local fwutils_config = require("fwutils.config")
|
||||
local develop_role_permissions = require("fwutils.develop.function.role_permissions")
|
||||
|
||||
local function get_by_id()
|
||||
local M = {}
|
||||
M.get_by_id = function()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
succ(develop_role_permissions.get_by_id(pint("id"),conn))
|
||||
end
|
||||
|
||||
local function add()
|
||||
M.add = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_role_permissions.add(data,conn) then
|
||||
@@ -17,7 +18,7 @@ local function add()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function update()
|
||||
M.update = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_role_permissions.update(data,conn) then
|
||||
@@ -26,7 +27,7 @@ local function update()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function delete()
|
||||
M.delete = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_role_permissions.delete(data.id,conn) then
|
||||
@@ -35,23 +36,26 @@ local function delete()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function list()
|
||||
M.list = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
local d = develop_role_permissions.list(data.search,data.limit,conn)
|
||||
succ(d)
|
||||
end
|
||||
local function refresh()
|
||||
M.refresh = function()
|
||||
local module_acl = require("fwutils.develop.function.role_permissions")
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
module_acl.make_bytecode(nil,conn)
|
||||
succ({})
|
||||
end
|
||||
exec({
|
||||
get_by_id = get_by_id,
|
||||
list = list,
|
||||
add = add,
|
||||
update = update,
|
||||
delete = delete,
|
||||
refresh = refresh,
|
||||
})
|
||||
M.exec = function()
|
||||
exec({
|
||||
get_by_id = M.get_by_id,
|
||||
list = M.list,
|
||||
add = M.add,
|
||||
update = M.update,
|
||||
delete = M.delete,
|
||||
refresh = M.refresh,
|
||||
})
|
||||
end
|
||||
return M
|
||||
@@ -3,12 +3,13 @@ require("app.app")
|
||||
local fwutils_config = require("fwutils.config")
|
||||
local develop_template = require("fwutils.develop.function.template")
|
||||
|
||||
local function get_by_id()
|
||||
local M = {}
|
||||
M.get_by_id = function()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
succ(develop_template.get_by_id(pint("id"),conn))
|
||||
end
|
||||
|
||||
local function add()
|
||||
M.add = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_template.add(data,conn) then
|
||||
@@ -17,7 +18,7 @@ local function add()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function update()
|
||||
M.update = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_template.update(data,conn) then
|
||||
@@ -26,7 +27,7 @@ local function update()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function delete()
|
||||
M.delete = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
if develop_template.delete(data.id,conn) then
|
||||
@@ -35,23 +36,26 @@ local function delete()
|
||||
error("")
|
||||
end
|
||||
end
|
||||
local function list()
|
||||
M.list = function()
|
||||
local data = pjson()
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
local d = develop_template.list(data.search,data.limit,conn)
|
||||
succ(d)
|
||||
end
|
||||
local function refresh()
|
||||
M.refresh = function()
|
||||
local module_template = require("fwutils.template_engine")
|
||||
local conn = mysql.new(_G[fwutils_config.db.mysql_pool_name]):get()
|
||||
module_template.update(conn)
|
||||
succ()
|
||||
end
|
||||
exec({
|
||||
get_by_id = get_by_id,
|
||||
list = list,
|
||||
add = add,
|
||||
update = update,
|
||||
delete = delete,
|
||||
refresh = refresh,
|
||||
})
|
||||
M.exec = function()
|
||||
exec({
|
||||
get_by_id = M.get_by_id,
|
||||
list = M.list,
|
||||
add = M.add,
|
||||
update = M.update,
|
||||
delete = M.delete,
|
||||
refresh = M.refresh,
|
||||
})
|
||||
end
|
||||
return M
|
||||
@@ -8,7 +8,16 @@ require("fwutils.webapi")
|
||||
-- PRIMARY KEY (`id`),
|
||||
-- UNIQUE KEY `role_id` (`role_id`,`key`)
|
||||
-- ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Fastweb-关键词模板';
|
||||
local M = {}
|
||||
local M = {
|
||||
cfg = nil,
|
||||
template_engine_bc_this_role = nil
|
||||
}
|
||||
-- 允许的扩展名
|
||||
local allowed_extensions = {
|
||||
"shtml",
|
||||
"html",
|
||||
"js"
|
||||
}
|
||||
|
||||
function M.get_by_id(id,conn)
|
||||
local select = conn:select()
|
||||
@@ -98,5 +107,259 @@ function M.list(search,limit,conn)
|
||||
sel_data:orderby("fw_template.enable DESC")
|
||||
end)
|
||||
end
|
||||
-- 更新
|
||||
M.make_bytecode = function(conn)
|
||||
-- 查询权限表
|
||||
local select = conn:select()
|
||||
select:table("fw_template")
|
||||
select:where_i32("enable","=",1)
|
||||
local result = select:query()
|
||||
local bc = {
|
||||
public = {}
|
||||
}
|
||||
while result:next() do
|
||||
local id = result:get("id")
|
||||
local role_id = string.format("%d",result:get("role_id"))
|
||||
local key = result:get("key")
|
||||
local value = result:get("value")
|
||||
|
||||
|
||||
if bc[role_id] == nil then
|
||||
bc[role_id] = {}
|
||||
end
|
||||
if role_id == "0" then
|
||||
bc["public"][key] = value
|
||||
else
|
||||
bc[role_id][key] = value
|
||||
end
|
||||
end
|
||||
local code = "return " .. require("serpent").serialize(bc, {comment = false})
|
||||
utils.save_file(fw.website_dir().."/"..(fwutils_config.path.luabytecode:gsub("%.", "/")).."/template_engine_bc.lua",code)
|
||||
return true
|
||||
end
|
||||
-- 处理
|
||||
-- @param static_content 静态内容
|
||||
-- @param cfg 配置
|
||||
-- @return 是否替换(TRUE则不需要继续处理,FALSE则继续处理)
|
||||
M.handle = function(__cfg,functions)
|
||||
|
||||
local function has_ext(ext)
|
||||
for _, v in ipairs(allowed_extensions) do
|
||||
if v == ext then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
M.cfg = __cfg
|
||||
M.template_engine_bc_this_role = {
|
||||
template = {
|
||||
private = {},
|
||||
public = {}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
local ext = utils.ext(M.cfg.filepath())
|
||||
local static_content = nil
|
||||
if ext ~= nil then
|
||||
if not has_ext(ext) then
|
||||
return false
|
||||
end
|
||||
-- 读取资源文件
|
||||
static_content = utils.read_file(fw.website_dir()..M.cfg.filepath())
|
||||
if static_content == nil or static_content == "" then
|
||||
return false
|
||||
end
|
||||
else
|
||||
-- 无需替换的扩展名
|
||||
return false
|
||||
end
|
||||
local template_engine_bc = require(fwutils_config.path.luabytecode..".template_engine_bc")
|
||||
M.template_engine_bc_this_role["template"]["private"] = template_engine_bc[string.format("%d",M.cfg.role_id())]
|
||||
M.template_engine_bc_this_role["template"]["public"] = template_engine_bc["public"]
|
||||
|
||||
|
||||
local replaced,content = M.replace(static_content)
|
||||
if replaced then
|
||||
static_content = content
|
||||
end
|
||||
-- 执行函数
|
||||
static_content, n = static_content:gsub("%${<<<%s*(.-)%s*>>>}", function(code)
|
||||
-- 尝试编译代码(Lua 5.2+ 使用 load;Lua 5.1 可用 loadstring)
|
||||
local env = {}
|
||||
_G["engine"] = M
|
||||
local env = require("fwutils.funs").regist(env)
|
||||
if functions ~= nil then
|
||||
env = functions.regist(env)
|
||||
end
|
||||
env["_G"] = _G
|
||||
local chunk, errmsg = load(code,nil,nil,env)
|
||||
if not chunk then
|
||||
fw.throw_string(errmsg)
|
||||
end
|
||||
-- 使用 pcall 安全执行代码块
|
||||
local status, result = pcall(chunk)
|
||||
if not status then
|
||||
fw.throw_string(result)
|
||||
end
|
||||
-- 如果代码没有返回值,则替换为空字符串,否则转换成字符串返回
|
||||
return tostring(result)
|
||||
end)
|
||||
|
||||
if n > 0 then
|
||||
replaced = true
|
||||
end
|
||||
|
||||
if replaced then
|
||||
if ext == "shtml" or ext == "html" then
|
||||
response.header("Content-Type","text/html")
|
||||
elseif ext == "js" then
|
||||
response.header("Content-Type","application/javascript")
|
||||
end
|
||||
response.send(static_content)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
M.replace = function (content)
|
||||
if content == nil or content == "" then
|
||||
return false
|
||||
end
|
||||
-- 支持多级kvs替换,如 ${people.age}
|
||||
local function flatten_kvs(tbl, prefix, out)
|
||||
if tbl == nil then
|
||||
return {}
|
||||
end
|
||||
out = out or {}
|
||||
prefix = prefix or ""
|
||||
for k, v in pairs(tbl) do
|
||||
local key = prefix ~= "" and (prefix .. "." .. k) or k
|
||||
if type(v) == "table" then
|
||||
flatten_kvs(v, key, out)
|
||||
else
|
||||
out[key] = v
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- 先提取 content 中所有需要替换的占位符
|
||||
-- 需要正确处理 ${<<<...>>>} 块:块内部的 ${...} 需要替换,但块本身不替换
|
||||
local placeholders = {}
|
||||
|
||||
-- 第一步:提取所有 ${<<<...>>>} 块,临时替换它们,并收集所有占位符
|
||||
local blocks = {}
|
||||
local block_index = 0
|
||||
local temp_content = content:gsub("%${<<<%s*(.-)%s*>>>}", function(block_content)
|
||||
block_index = block_index + 1
|
||||
local placeholder = "${__TEMP_BLOCK_" .. block_index .. "__}"
|
||||
-- 收集块内部的 ${...} 占位符
|
||||
for ph in string.gmatch(block_content, "%${([^}]+)}") do
|
||||
placeholders[ph] = true
|
||||
end
|
||||
blocks[block_index] = {
|
||||
placeholder = placeholder,
|
||||
content = block_content
|
||||
}
|
||||
return placeholder
|
||||
end)
|
||||
|
||||
-- 第二步:提取外部(不在 ${<<<...>>>} 块中)的 ${...} 占位符
|
||||
for placeholder in string.gmatch(temp_content, "%${([^}]+)}") do
|
||||
-- 忽略临时占位符
|
||||
if not placeholder:match("^__TEMP_BLOCK_%d+__$") then
|
||||
placeholders[placeholder] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- print("PLACEHOLDERS:",cjson.encode(placeholders))
|
||||
|
||||
-- 如果没有任何占位符,直接返回
|
||||
if next(placeholders) == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
-- 合并所有数据源到一个查找表中(只 flatten 一次)
|
||||
local value_map = {}
|
||||
|
||||
-- PUBLIC
|
||||
local flat_kvs = flatten_kvs(M.template_engine_bc_this_role["template"]["public"])
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- PRIVATE
|
||||
flat_kvs = flatten_kvs(M.template_engine_bc_this_role["template"]["private"])
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- REQUEST
|
||||
flat_kvs = flatten_kvs(request.gets(), "request")
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- TOKEN
|
||||
flat_kvs = flatten_kvs(M.cfg.user_data(), "token")
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
|
||||
-- 转义函数:将 Lua 模式特殊字符转义为字面匹配
|
||||
local function escape_pattern(str)
|
||||
return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
|
||||
end
|
||||
|
||||
-- 第三步:先处理 ${<<<...>>>} 块内部的占位符
|
||||
local replaced = false
|
||||
for i, block in ipairs(blocks) do
|
||||
local block_content = block.content
|
||||
for placeholder, _ in pairs(placeholders) do
|
||||
if value_map[placeholder] ~= nil then
|
||||
local escaped_placeholder = escape_pattern(placeholder)
|
||||
local new_content, count = string.gsub(block_content, "%${" .. escaped_placeholder .. "}", tostring(value_map[placeholder]))
|
||||
if count > 0 then
|
||||
block_content = new_content
|
||||
replaced = true
|
||||
end
|
||||
end
|
||||
end
|
||||
blocks[i].processed_content = block_content
|
||||
end
|
||||
|
||||
-- 第四步:替换外部的 ${...} 占位符(在临时内容中,此时块已被替换为临时占位符)
|
||||
local n = 0
|
||||
for placeholder, _ in pairs(placeholders) do
|
||||
if value_map[placeholder] ~= nil then
|
||||
local escaped_placeholder = escape_pattern(placeholder)
|
||||
temp_content, n = string.gsub(temp_content, "%${" .. escaped_placeholder .. "}", tostring(value_map[placeholder]))
|
||||
if n > 0 then
|
||||
replaced = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 第五步:恢复 ${<<<...>>>} 块(使用处理后的内容)
|
||||
for i, block in ipairs(blocks) do
|
||||
local processed_block = "${<<<" .. blocks[i].processed_content .. ">>>}"
|
||||
temp_content = temp_content:gsub(block.placeholder:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1"), processed_block)
|
||||
end
|
||||
content = temp_content
|
||||
|
||||
if replaced then
|
||||
return true, content
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 检查内容中是否有TOKEN变量
|
||||
-- @return boolean
|
||||
M.hasToken = function()
|
||||
if M.static_content == nil or M.static_content == "" then
|
||||
return false
|
||||
end
|
||||
return M.static_content:match("%${token%.") ~= nil
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -1,4 +1,3 @@
|
||||
local mysql_pool = require("mysql.pool")
|
||||
local fw = require("fastweb")
|
||||
local utils = require("utils")
|
||||
|
||||
@@ -13,6 +12,19 @@ M.initialization = function(conn)
|
||||
return false,err
|
||||
end
|
||||
|
||||
--生成字节码
|
||||
local module_menu = require("fwutils.develop.function.menu")
|
||||
local module_acl = require("fwutils.develop.function.role_permissions")
|
||||
local module_template = require("fwutils.develop.function.template")
|
||||
if not module_menu.make_bytecode(nil,conn) then
|
||||
return false,"menu bytecode generation failed"
|
||||
end
|
||||
if not module_acl.make_bytecode(nil,conn) then
|
||||
return false,"acl bytecode generation failed"
|
||||
end
|
||||
if not module_template.make_bytecode(conn) then
|
||||
return false,"template bytecode generation failed"
|
||||
end
|
||||
return true
|
||||
end
|
||||
M.__get_guest_role_id = function(mysql_conn)
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
local utils = require("utils")
|
||||
local fw = require("fastweb")
|
||||
local config = require("fwutils.config")
|
||||
local request = require("fastweb.request")
|
||||
local response = require("fastweb.response")
|
||||
local cjson = require("cjson")
|
||||
local funs = require("fwutils.funs")
|
||||
-- 允许的扩展名
|
||||
local allowed_extensions = {
|
||||
"shtml",
|
||||
"html",
|
||||
"js"
|
||||
}
|
||||
local M = {
|
||||
cfg = nil,
|
||||
template_engine_bc_this_role = nil
|
||||
}
|
||||
|
||||
-- 更新
|
||||
M.update = function(conn)
|
||||
-- 查询权限表
|
||||
local select = conn:select()
|
||||
select:table("fw_template")
|
||||
select:where_i32("enable","=",1)
|
||||
local result = select:query()
|
||||
local bc = {
|
||||
public = {}
|
||||
}
|
||||
while result:next() do
|
||||
local id = result:get("id")
|
||||
local role_id = string.format("%d",result:get("role_id"))
|
||||
local key = result:get("key")
|
||||
local value = result:get("value")
|
||||
|
||||
|
||||
if bc[role_id] == nil then
|
||||
bc[role_id] = {}
|
||||
end
|
||||
if role_id == "0" then
|
||||
bc["public"][key] = value
|
||||
else
|
||||
bc[role_id][key] = value
|
||||
end
|
||||
end
|
||||
local code = "return " .. require("serpent").serialize(bc, {comment = false})
|
||||
utils.save_file(fw.website_dir().."/"..(fwutils_config.path.luabytecode:gsub("%.", "/")).."/template_engine_bc.lua",code)
|
||||
return true
|
||||
end
|
||||
-- 处理
|
||||
-- @param static_content 静态内容
|
||||
-- @param cfg 配置
|
||||
-- @return 是否替换(TRUE则不需要继续处理,FALSE则继续处理)
|
||||
M.handle = function(__cfg,functions)
|
||||
|
||||
local function has_ext(ext)
|
||||
for _, v in ipairs(allowed_extensions) do
|
||||
if v == ext then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
M.cfg = __cfg
|
||||
M.template_engine_bc_this_role = {
|
||||
template = {
|
||||
private = {},
|
||||
public = {}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
local ext = utils.ext(M.cfg.filepath())
|
||||
local static_content = nil
|
||||
if ext ~= nil then
|
||||
if not has_ext(ext) then
|
||||
return false
|
||||
end
|
||||
-- 读取资源文件
|
||||
static_content = utils.read_file(fw.website_dir()..M.cfg.filepath())
|
||||
if static_content == nil or static_content == "" then
|
||||
return false
|
||||
end
|
||||
else
|
||||
-- 无需替换的扩展名
|
||||
return false
|
||||
end
|
||||
local template_engine_bc = require(fwutils_config.path.luabytecode..".template_engine_bc")
|
||||
M.template_engine_bc_this_role["template"]["private"] = template_engine_bc[string.format("%d",M.cfg.role_id())]
|
||||
M.template_engine_bc_this_role["template"]["public"] = template_engine_bc["public"]
|
||||
|
||||
|
||||
local replaced,content = M.replace(static_content)
|
||||
if replaced then
|
||||
static_content = content
|
||||
end
|
||||
-- 执行函数
|
||||
static_content, n = static_content:gsub("%${<<<%s*(.-)%s*>>>}", function(code)
|
||||
-- 尝试编译代码(Lua 5.2+ 使用 load;Lua 5.1 可用 loadstring)
|
||||
local env = {}
|
||||
_G["engine"] = M
|
||||
local env = funs.regist(env)
|
||||
if functions ~= nil then
|
||||
env = functions.regist(env)
|
||||
end
|
||||
env["_G"] = _G
|
||||
local chunk, errmsg = load(code,nil,nil,env)
|
||||
if not chunk then
|
||||
fw.throw_string(errmsg)
|
||||
end
|
||||
-- 使用 pcall 安全执行代码块
|
||||
local status, result = pcall(chunk)
|
||||
if not status then
|
||||
fw.throw_string(result)
|
||||
end
|
||||
-- 如果代码没有返回值,则替换为空字符串,否则转换成字符串返回
|
||||
return tostring(result)
|
||||
end)
|
||||
|
||||
if n > 0 then
|
||||
replaced = true
|
||||
end
|
||||
|
||||
if replaced then
|
||||
if ext == "shtml" or ext == "html" then
|
||||
response.header("Content-Type","text/html")
|
||||
elseif ext == "js" then
|
||||
response.header("Content-Type","application/javascript")
|
||||
end
|
||||
response.send(static_content)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
M.replace = function (content)
|
||||
if content == nil or content == "" then
|
||||
return false
|
||||
end
|
||||
-- 支持多级kvs替换,如 ${people.age}
|
||||
local function flatten_kvs(tbl, prefix, out)
|
||||
if tbl == nil then
|
||||
return {}
|
||||
end
|
||||
out = out or {}
|
||||
prefix = prefix or ""
|
||||
for k, v in pairs(tbl) do
|
||||
local key = prefix ~= "" and (prefix .. "." .. k) or k
|
||||
if type(v) == "table" then
|
||||
flatten_kvs(v, key, out)
|
||||
else
|
||||
out[key] = v
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- 先提取 content 中所有需要替换的占位符
|
||||
-- 需要正确处理 ${<<<...>>>} 块:块内部的 ${...} 需要替换,但块本身不替换
|
||||
local placeholders = {}
|
||||
|
||||
-- 第一步:提取所有 ${<<<...>>>} 块,临时替换它们,并收集所有占位符
|
||||
local blocks = {}
|
||||
local block_index = 0
|
||||
local temp_content = content:gsub("%${<<<%s*(.-)%s*>>>}", function(block_content)
|
||||
block_index = block_index + 1
|
||||
local placeholder = "${__TEMP_BLOCK_" .. block_index .. "__}"
|
||||
-- 收集块内部的 ${...} 占位符
|
||||
for ph in string.gmatch(block_content, "%${([^}]+)}") do
|
||||
placeholders[ph] = true
|
||||
end
|
||||
blocks[block_index] = {
|
||||
placeholder = placeholder,
|
||||
content = block_content
|
||||
}
|
||||
return placeholder
|
||||
end)
|
||||
|
||||
-- 第二步:提取外部(不在 ${<<<...>>>} 块中)的 ${...} 占位符
|
||||
for placeholder in string.gmatch(temp_content, "%${([^}]+)}") do
|
||||
-- 忽略临时占位符
|
||||
if not placeholder:match("^__TEMP_BLOCK_%d+__$") then
|
||||
placeholders[placeholder] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- print("PLACEHOLDERS:",cjson.encode(placeholders))
|
||||
|
||||
-- 如果没有任何占位符,直接返回
|
||||
if next(placeholders) == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
-- 合并所有数据源到一个查找表中(只 flatten 一次)
|
||||
local value_map = {}
|
||||
|
||||
-- PUBLIC
|
||||
local flat_kvs = flatten_kvs(M.template_engine_bc_this_role["template"]["public"])
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- PRIVATE
|
||||
flat_kvs = flatten_kvs(M.template_engine_bc_this_role["template"]["private"])
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- REQUEST
|
||||
flat_kvs = flatten_kvs(request.gets(), "request")
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
-- TOKEN
|
||||
flat_kvs = flatten_kvs(M.cfg.user_data(), "token")
|
||||
for k, v in pairs(flat_kvs) do
|
||||
value_map[k] = v
|
||||
end
|
||||
|
||||
-- 转义函数:将 Lua 模式特殊字符转义为字面匹配
|
||||
local function escape_pattern(str)
|
||||
return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
|
||||
end
|
||||
|
||||
-- 第三步:先处理 ${<<<...>>>} 块内部的占位符
|
||||
local replaced = false
|
||||
for i, block in ipairs(blocks) do
|
||||
local block_content = block.content
|
||||
for placeholder, _ in pairs(placeholders) do
|
||||
if value_map[placeholder] ~= nil then
|
||||
local escaped_placeholder = escape_pattern(placeholder)
|
||||
local new_content, count = string.gsub(block_content, "%${" .. escaped_placeholder .. "}", tostring(value_map[placeholder]))
|
||||
if count > 0 then
|
||||
block_content = new_content
|
||||
replaced = true
|
||||
end
|
||||
end
|
||||
end
|
||||
blocks[i].processed_content = block_content
|
||||
end
|
||||
|
||||
-- 第四步:替换外部的 ${...} 占位符(在临时内容中,此时块已被替换为临时占位符)
|
||||
local n = 0
|
||||
for placeholder, _ in pairs(placeholders) do
|
||||
if value_map[placeholder] ~= nil then
|
||||
local escaped_placeholder = escape_pattern(placeholder)
|
||||
temp_content, n = string.gsub(temp_content, "%${" .. escaped_placeholder .. "}", tostring(value_map[placeholder]))
|
||||
if n > 0 then
|
||||
replaced = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 第五步:恢复 ${<<<...>>>} 块(使用处理后的内容)
|
||||
for i, block in ipairs(blocks) do
|
||||
local processed_block = "${<<<" .. blocks[i].processed_content .. ">>>}"
|
||||
temp_content = temp_content:gsub(block.placeholder:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1"), processed_block)
|
||||
end
|
||||
content = temp_content
|
||||
|
||||
if replaced then
|
||||
return true, content
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 检查内容中是否有TOKEN变量
|
||||
-- @return boolean
|
||||
M.hasToken = function()
|
||||
if M.static_content == nil or M.static_content == "" then
|
||||
return false
|
||||
end
|
||||
return M.static_content:match("%${token%.") ~= nil
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user