update 2026-09-20 16:59:13

This commit is contained in:
action committed 2026-09-20 16:59:13 +08:00
1 parent 4dd6850a75
commit 735d247cbe
23 files changed
+237 -115

No files matched your search

@@ -96,6 +96,7 @@ if load_urltest_options then -- [[ URLTest Start ]]
o = s:option(MultiValue, "urltest_node", translate("URLTest node list"), translate("List of nodes to test, <a target='_blank' href='https://sing-box.sagernet.org/configuration/outbound/urltest'>document</a>"))
o:depends({ node_add_mode = "manual" })
o.widget = "checkbox"
o.cast = "table"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
for k1, v1 in pairs(node_list) do
@@ -106,30 +107,6 @@ if load_urltest_options then -- [[ URLTest Start ]]
end
end
end
-- 读取旧 DynamicList
function o.cfgvalue(self, section)
return table.concat(m:get(section, "urltest_node") or {}, " ")
end
-- 写入保持 DynamicList
function o.write(self, section, value)
local old = m:get(section, "urltest_node") or {}
local new, set = {}, {}
for v in value:gmatch("%S+") do
new[#new + 1] = v
set[v] = 1
end
for _, v in ipairs(old) do
if not set[v] then
m:set(section, "urltest_node", new)
return
end
set[v] = nil
end
for _ in pairs(set) do
m:set(section, "urltest_node", new)
return
end
end
o = s:option(MultiValue, "node_group", translate("Select Group"))
o:depends({ node_add_mode = "batch" })
@@ -90,6 +90,7 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o = s:option(MultiValue, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://xtls.github.io/config/routing.html#balancerobject'>document</a>"))
o:depends({ node_add_mode = "manual" })
o.widget = "checkbox"
o.cast = "table"
o.template = m:template_path("/cbi/nodes_multivalue")
o.group = {}
for k1, v1 in pairs(node_list) do
@@ -100,30 +101,6 @@ if load_balancing_options then -- [[ Load balancing Start ]]
end
end
end
-- 读取旧 DynamicList
function o.cfgvalue(self, section)
return table.concat(m:get(section, "balancing_node") or {}, " ")
end
-- 写入保持 DynamicList
function o.write(self, section, value)
local old = m:get(section, "balancing_node") or {}
local new, set = {}, {}
for v in value:gmatch("%S+") do
new[#new + 1] = v
set[v] = 1
end
for _, v in ipairs(old) do
if not set[v] then
m:set(section, "balancing_node", new)
return
end
set[v] = nil
end
for _ in pairs(set) do
m:set(section, "balancing_node", new)
return
end
end
o = s:option(MultiValue, "node_group", translate("Select Group"))
o:depends({ node_add_mode = "batch" })
@@ -36,7 +36,7 @@ o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
o.default = "0"
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
@@ -50,7 +50,7 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
@@ -79,7 +79,8 @@ o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
o:depends({ custom = false })
o = s:option(DynamicList, "users", translate("User"))
o = s:option(MultiValue, "users", translate("User"))
o.cast = "table"
for i, v in ipairs(user_list) do
o:value(v[".name"], v.username)
end
@@ -535,7 +536,7 @@ o.default = "0"
o:depends({ custom = false })
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
@@ -46,7 +46,7 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
@@ -72,7 +72,8 @@ o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
o:depends({ custom = false })
o = s:option(DynamicList, "users", translate("User"))
o = s:option(MultiValue, "users", translate("User"))
o.cast = "table"
for i, v in ipairs(user_list) do
o:value(v[".name"], v.username)
end
@@ -521,7 +522,7 @@ o.default = "0"
o:depends({ custom = false })
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
@@ -41,7 +41,7 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
@@ -79,7 +79,7 @@ o.default = "0"
o:depends({ custom = false })
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
@@ -54,7 +54,7 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
@@ -110,7 +110,7 @@ o.default = "0"
o:depends({ custom = false })
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
@@ -31,7 +31,7 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
@@ -45,7 +45,8 @@ o = s:option(Value, "port", translate("Listen Port"))
o.datatype = "port"
o:depends({ custom = false })
o = s:option(DynamicList, "users", translate("User"))
o = s:option(MultiValue, "users", translate("User"))
o.cast = "table"
for i, v in ipairs(user_list) do
o:value(v[".name"], v.username)
end
@@ -168,7 +169,7 @@ o.default = "0"
o:depends({ custom = false })
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
o.rmempty = false
o.rmempty = not m.is_js_luci
o.nocreate = true
o.allowany = true
o.default = "wan"
+25 -2
View File
@@ -1542,11 +1542,18 @@ function set_type_cbi(s)
obj.option_prefix = s_self.option_prefix
obj.option = s_self.option_prefix .. option
obj.cfgvalue = function(self, section)
local v
if self.rewrite_option then
return self.map:get(section, self.rewrite_option)
v = self.map:get(section, self.rewrite_option)
else
return self.map:get(section, self.config_option)
v = self.map:get(section, self.config_option)
end
if util.instanceof(self, cbi.MultiValue) then
if v and self.cast == "table" then
return table.concat(v, " ")
end
end
return v
end
obj.write = function(self, section, value)
if s1.fields["type"]:formvalue(s_self.section) == s_self.type_name then
@@ -1564,6 +1571,21 @@ function set_type_cbi(s)
new_val = new_t
end
end
if util.instanceof(self, cbi.MultiValue) then
local new_t = {}
if type(value) == "table" then
new_t = table_remove_duplicates(value)
else
string.gsub(value, '[^' .. " " .. ']+', function(v)
new_t[#new_t + 1] = v
end)
end
if self.cast == "string" then
new_val = table.concat(new_t, " ")
else
new_val = new_t
end
end
if self.rewrite_option then
self.map:set(section, self.rewrite_option, new_val)
else
@@ -1619,6 +1641,7 @@ end
function type_cbi_section(s, s2)
for i, v in ipairs(s2.children) do
local o = s2.children[i]
o.section = s
s:append(o)
s.fields[o.option] = o
end