update 2026-07-16 18:02:58
BIN
doc/lucky1.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
doc/lucky2.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
doc/lucky3.png
Normal file
|
After Width: | Height: | Size: 389 KiB |
|
Before Width: | Height: | Size: 640 KiB |
|
Before Width: | Height: | Size: 550 KiB |
|
Before Width: | Height: | Size: 547 KiB |
BIN
doc/view.png
|
Before Width: | Height: | Size: 659 KiB |
BIN
doc/view2.png
|
Before Width: | Height: | Size: 650 KiB |
@ -0,0 +1,38 @@
|
||||
function is_json(str) {
|
||||
try {
|
||||
const result = JSON.parse(str);
|
||||
return typeof result === 'object' && result !== null;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function is_timehhmm(str) {
|
||||
const match = String(str).match(/^(\d?\d):(\d\d)$/);
|
||||
if (match) {
|
||||
const hour = parseInt(match[1], 10);
|
||||
const minute = parseInt(match[2], 10);
|
||||
if (hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof cbi_validators !== 'undefined' && cbi_validators !== null) {
|
||||
cbi_validators['json'] = function() {
|
||||
return is_json(this);
|
||||
}
|
||||
cbi_validators['timehhmm'] = function() {
|
||||
return is_timehhmm(this);
|
||||
}
|
||||
} else {
|
||||
L.require('validation').then(function(validation) {
|
||||
validation.types['json'] = function() {
|
||||
return this.assert(is_json(this.value), _('Must be JSON text!'));
|
||||
}
|
||||
validation.types['timehhmm'] = function() {
|
||||
return this.assert(is_timehhmm(this.value), _('valid time (hh:mm)'));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -2,6 +2,8 @@ local api = require "luci.passwall.api"
|
||||
local appname = "passwall"
|
||||
local sys = api.sys
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -101,4 +103,4 @@ o:value("1:65535", translate("All"))
|
||||
o:value("53", "53")
|
||||
]]--
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
local api = require "luci.passwall.api"
|
||||
local appname = "passwall"
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
m.redirect = api.url("acl")
|
||||
api.set_apply_on_parse(m)
|
||||
@ -601,4 +603,4 @@ for k, v in pairs(nodes_table) do
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -2,6 +2,8 @@ local api = require "luci.passwall.api"
|
||||
local com = require "luci.passwall.com"
|
||||
local appname = "passwall"
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -34,4 +36,4 @@ o.cfgvalue = function(t, n)
|
||||
return string.format('<font color="red">%s</font>', translate("if you want to run from memory, change the path, /tmp beginning then save the application and update it manually."))
|
||||
end
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -8,6 +8,8 @@ local has_gfwlist = fs.access("/usr/share/passwall/rules/gfwlist")
|
||||
local has_chnlist = fs.access("/usr/share/passwall/rules/chnlist")
|
||||
local has_chnroute = fs.access("/usr/share/passwall/rules/chnroute")
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -839,4 +841,4 @@ footer.global_cfgid = global_cfgid
|
||||
footer.shunt_list = api.jsonc.stringify(shunt_list)
|
||||
m:append(footer)
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -15,6 +15,8 @@ for k, e in ipairs(api.get_valid_nodes()) do
|
||||
end
|
||||
end
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname, "HAPROXY " .. translate("Load Balancing"))
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -179,4 +181,4 @@ o.rmempty = false
|
||||
|
||||
m:append(Template(appname .. "/haproxy/js"))
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
api = require "luci.passwall.api"
|
||||
appname = "passwall"
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname, translate("Node Config"))
|
||||
m.redirect = api.url("node_list")
|
||||
api.set_apply_on_parse(m)
|
||||
@ -120,7 +122,6 @@ local footer = Template(appname .. "/node_config/footer")
|
||||
footer.api = api
|
||||
footer.config = m.config
|
||||
footer.section = arg[1]
|
||||
|
||||
m:append(footer)
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -3,6 +3,8 @@ local appname = "passwall"
|
||||
local sys = api.sys
|
||||
local datatypes = api.datatypes
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -33,4 +35,4 @@ s:append(Template(appname .. "/node_list/link_add_node"))
|
||||
|
||||
m:append(Template(appname .. "/node_list/node_list"))
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -38,6 +38,8 @@ if has_hysteria2 then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -225,4 +227,4 @@ end
|
||||
|
||||
m:append(Template(appname .. "/node_subscribe/js"))
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -2,6 +2,8 @@ local api = require "luci.passwall.api"
|
||||
local uci = api.uci
|
||||
local appname = "passwall"
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
m.redirect = api.url("node_subscribe")
|
||||
api.set_apply_on_parse(m)
|
||||
@ -244,13 +246,7 @@ o:value(0, translate("Every Sunday"))
|
||||
o = s:option(Value, "update_time_mode", translate("Update Time"))
|
||||
for t = 0, 23 do o:value(t .. ":00") end
|
||||
o.default = "0:00"
|
||||
o.validate = function(self, value)
|
||||
local b = api.is_timehhmm(value)
|
||||
if b then
|
||||
return value
|
||||
end
|
||||
return nil
|
||||
end
|
||||
o.datatype = "timehhmm"
|
||||
o:depends("update_week_mode", "0")
|
||||
o:depends("update_week_mode", "1")
|
||||
o:depends("update_week_mode", "2")
|
||||
@ -321,4 +317,4 @@ for k, v in pairs(nodes_table) do
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -8,6 +8,8 @@ local port_validate = function(self, value, t)
|
||||
return value:gsub("-", ":")
|
||||
end
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -43,13 +45,7 @@ for index, value in ipairs({"stop", "start", "restart"}) do
|
||||
o = s:option(Value, value .. "_time_mode", translate(value .. " Time"))
|
||||
for t = 0, 23 do o:value(t .. ":00") end
|
||||
o.default = "0:00"
|
||||
o.validate = function(self, value)
|
||||
local b = api.is_timehhmm(value)
|
||||
if b then
|
||||
return value
|
||||
end
|
||||
return nil
|
||||
end
|
||||
o.datatype = "timehhmm"
|
||||
o:depends(value .. "_week_mode", "0")
|
||||
o:depends(value .. "_week_mode", "1")
|
||||
o:depends(value .. "_week_mode", "2")
|
||||
@ -271,4 +267,4 @@ if has_singbox then
|
||||
o.default = 0
|
||||
end
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -3,6 +3,8 @@ local appname = "passwall"
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_singbox = api.finded_com("sing-box")
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
@ -112,13 +114,7 @@ o:value(0, translate("Every Sunday"))
|
||||
o = s:option(Value, "update_time_mode", translate("Update Time"))
|
||||
for t = 0, 23 do o:value(t .. ":00") end
|
||||
o.default = "0:00"
|
||||
o.validate = function(self, value)
|
||||
local b = api.is_timehhmm(value)
|
||||
if b then
|
||||
return value
|
||||
end
|
||||
return nil
|
||||
end
|
||||
o.datatype = "timehhmm"
|
||||
o:depends("update_week_mode", "0")
|
||||
o:depends("update_week_mode", "1")
|
||||
o:depends("update_week_mode", "2")
|
||||
@ -169,4 +165,4 @@ if has_xray or has_singbox then
|
||||
o = s:option(DummyValue, "remarks", translate("Remarks"))
|
||||
end
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
local api = require "luci.passwall.api"
|
||||
local appname = "passwall"
|
||||
local appname = api.appname
|
||||
local fs = api.fs
|
||||
local sys = api.sys
|
||||
local uci = api.uci
|
||||
|
||||
@ -2,6 +2,8 @@ local api = require "luci.passwall.api"
|
||||
local appname = "passwall"
|
||||
local datatypes = api.datatypes
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname, "Sing-Box/Xray " .. translate("Shunt Rule"))
|
||||
m.redirect = api.url("rule")
|
||||
api.set_apply_on_parse(m)
|
||||
@ -245,4 +247,4 @@ ip_list.description = "<br /><ul>"
|
||||
|
||||
o = s:option(Flag, "invert", "Invert", translate("Invert match result.") .. " " .. translate("Only support Sing-Box."))
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
local api = require "luci.passwall.api"
|
||||
local appname = "passwall"
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map(appname)
|
||||
m.redirect = api.url()
|
||||
api.set_apply_on_parse(m)
|
||||
@ -166,4 +168,4 @@ o = s:option(DummyValue, "btn")
|
||||
o.template = appname .. "/socks_auto_switch/btn"
|
||||
o:depends("backup_node_add_mode", "manual")
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -667,6 +667,14 @@ o = s:option(TextValue, _n("xhttp_extra"), " ", translate("An XHttpObject in J
|
||||
o:depends({ [_n("use_xhttp_extra")] = true })
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, "XHTTP Extra " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local raw = m:get(section, "xhttp_extra")
|
||||
if raw then
|
||||
@ -689,14 +697,6 @@ o.custom_write = function(self, section, value)
|
||||
m:del(section, "download_address")
|
||||
end
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
|
||||
if api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, "XHTTP Extra " .. translate("Must be JSON text!")
|
||||
end
|
||||
end
|
||||
o.custom_remove = function(self, section, value)
|
||||
m:del(section, "xhttp_extra")
|
||||
m:del(section, "download_address")
|
||||
@ -752,6 +752,14 @@ o.rows = 10
|
||||
o.wrap = "off"
|
||||
o.description = translate("An FinalMaskObject in JSON format, used for sharing.") .. "<br>" ..
|
||||
translate("Custom finalmask overrides mkcp, hysteria2, fragment, noise, and related settings.")
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, "FinalMask " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local raw = m:get(section, "finalmask")
|
||||
if raw then
|
||||
@ -761,14 +769,6 @@ end
|
||||
o.custom_write = function(self, section, value)
|
||||
m:set(section, "finalmask", api.base64Encode(value) or "")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
|
||||
if api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, "FinalMask " .. translate("Must be JSON text!")
|
||||
end
|
||||
end
|
||||
|
||||
--[[Fast Open]]
|
||||
o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
local api = require "luci.passwall.api"
|
||||
local appname = api.appname
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map("passwall_server", translate("Server-Side"))
|
||||
api.set_apply_on_parse(m)
|
||||
@ -85,7 +88,8 @@ e = t:option(Flag, "log", translate("Log"))
|
||||
e.default = "1"
|
||||
e.rmempty = false
|
||||
|
||||
m:append(Template("passwall/server/log"))
|
||||
m:append(Template(appname .. "/server/log"))
|
||||
|
||||
m:append(Template("passwall/server/users_list_status"))
|
||||
return m
|
||||
m:append(Template(appname .. "/server/users_list_status"))
|
||||
|
||||
return api.return_map(m)
|
||||
|
||||
@ -131,12 +131,12 @@ o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("custom")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
|
||||
@ -406,6 +406,7 @@ o = s:option(TextValue, _n("finalmask"), "FinalMask JSON")
|
||||
o:depends({ [_n("use_finalmask")] = true })
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o.datatype = "json"
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local raw = m:get(section, "finalmask")
|
||||
if raw then
|
||||
@ -415,14 +416,6 @@ end
|
||||
o.custom_write = function(self, section, value)
|
||||
m:set(section, "finalmask", api.base64Encode(value) or "")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("^[ \t]*\n", ""):gsub("\n[ \t]*$", ""):gsub("\n[ \t]*\n", "\n")
|
||||
if api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, "FinalMask " .. translate("Must be JSON text!")
|
||||
end
|
||||
end
|
||||
|
||||
--[[acceptProxyProtocol]]
|
||||
o = s:option(Flag, _n("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
|
||||
@ -517,16 +510,16 @@ for _, d in ipairs(netdev_list) do
|
||||
o:value(d.name, d.label)
|
||||
end
|
||||
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("custom")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
|
||||
@ -489,16 +489,16 @@ for _, d in ipairs(netdev_list) do
|
||||
o:value(d.name, d.label)
|
||||
end
|
||||
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("custom")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
|
||||
@ -49,16 +49,16 @@ o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("custom")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
|
||||
@ -76,16 +76,16 @@ o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config"))
|
||||
o = s:option(TextValue, _n("custom_config"), translate("Custom Config") .. " (JSON)")
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ [_n("custom")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and api.jsonc.parse(value) then
|
||||
return value
|
||||
else
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
|
||||
@ -2,6 +2,8 @@ api = require "luci.passwall.api"
|
||||
appname = api.appname
|
||||
fs = api.fs
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map("passwall_server", translate("Server Config"))
|
||||
m.redirect = api.url("server")
|
||||
api.set_apply_on_parse(m)
|
||||
@ -56,4 +58,4 @@ footer.config = m.config
|
||||
footer.section = arg[1]
|
||||
m:append(footer)
|
||||
|
||||
return m
|
||||
return api.return_map(m)
|
||||
|
||||
@ -348,8 +348,16 @@ function strToTable(str)
|
||||
return loadstring("return " .. str)()
|
||||
end
|
||||
|
||||
function is_timehhmm(timeStr)
|
||||
local hour, minute = string.match(timeStr, "^(%d?%d):(%d%d)$")
|
||||
function is_json(str)
|
||||
if str and jsonc.parse(str) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
datatypes.json = is_json
|
||||
|
||||
function is_timehhmm(str)
|
||||
local hour, minute = string.match(str, "^(%d?%d):(%d%d)$")
|
||||
if hour and minute then
|
||||
hour = tonumber(hour)
|
||||
minute = tonumber(minute)
|
||||
@ -359,6 +367,7 @@ function is_timehhmm(timeStr)
|
||||
end
|
||||
return false
|
||||
end
|
||||
datatypes.timehhmm = is_timehhmm
|
||||
|
||||
function is_normal_node(e)
|
||||
if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then
|
||||
@ -1327,6 +1336,40 @@ function to_check_self()
|
||||
}
|
||||
end
|
||||
|
||||
function set_default_cbi()
|
||||
local cbi = require "luci.cbi"
|
||||
if true then
|
||||
--TextValue
|
||||
local TextValue = cbi.TextValue
|
||||
local original_init = TextValue.__init__
|
||||
function TextValue.__init__(self, ...)
|
||||
original_init(self, ...)
|
||||
self.template = appname .. "/cbi/tvalue"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function return_map(map)
|
||||
local cbi = require "luci.cbi"
|
||||
local api = require "luci.passwall.api"
|
||||
if true then
|
||||
-- header
|
||||
local header = cbi.Template(appname .. "/cbi/header")
|
||||
header.api = api
|
||||
header.config = map.config
|
||||
table.insert(map.children, 1, header)
|
||||
end
|
||||
if true then
|
||||
-- footer
|
||||
local footer = cbi.Template(appname .. "/cbi/footer")
|
||||
footer.api = api
|
||||
footer.config = map.config
|
||||
map:append(footer)
|
||||
end
|
||||
|
||||
return map
|
||||
end
|
||||
|
||||
function luci_types(id, m, s, type_name, option_prefix)
|
||||
local fv_type
|
||||
local field_type = s.fields["type"]
|
||||
|
||||
1
luci-app-passwall/luasrc/view/passwall/cbi/footer.htm
Normal file
@ -0,0 +1 @@
|
||||
<!-- map footer -->
|
||||
2
luci-app-passwall/luasrc/view/passwall/cbi/header.htm
Normal file
@ -0,0 +1,2 @@
|
||||
<!-- map header -->
|
||||
<script src="<%=resource%>/view/<%=self.api.appname%>/cbi.js"></script>
|
||||
13
luci-app-passwall/luasrc/view/passwall/cbi/tvalue.htm
Normal file
@ -0,0 +1,13 @@
|
||||
<%+cbi/valueheader%>
|
||||
<textarea class="cbi-input-textarea" <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %>
|
||||
data-update="change"<%=
|
||||
attr("name", cbid) ..
|
||||
attr("id", cbid) ..
|
||||
ifattr(self.rows, "rows") ..
|
||||
ifattr(self.wrap, "wrap") ..
|
||||
ifattr(self.readonly, "readonly") ..
|
||||
ifattr(self.datatype, "data-type", self.datatype)
|
||||
%>>
|
||||
<%-=pcdata(self:cfgvalue(section) or self.default)-%>
|
||||
</textarea>
|
||||
<%+cbi/valuefooter%>
|
||||
@ -635,11 +635,15 @@ table td, .table .td {
|
||||
if (cacheData && cacheData.savetime && (now - cacheData.timestamp) < cacheData.savetime) {
|
||||
const a = ping_value[i].firstElementChild;
|
||||
let color = "red";
|
||||
if (cacheData.value < 100)
|
||||
color = "green";
|
||||
else if (cacheData.value < 200)
|
||||
color = "#fb9a05";
|
||||
a.innerText = cacheData.value + " ms";
|
||||
if (cacheData.value >= 0) {
|
||||
a.innerText = cacheData.value + " ms";
|
||||
if (cacheData.value < 100)
|
||||
color = "green";
|
||||
else if (cacheData.value < 200)
|
||||
color = "#fb9a05";
|
||||
} else {
|
||||
a.innerText = "<%:Timeout%>";
|
||||
}
|
||||
a.style.color = color;
|
||||
a.onclick = function () {
|
||||
ping_node(cbi_id, this, auto_detection_time);
|
||||
@ -679,15 +683,23 @@ table td, .table .td {
|
||||
const cache_data = {
|
||||
dom_id: strs[i],
|
||||
timestamp: Date.now(),
|
||||
savetime: 60 * 1000,
|
||||
savetime: 150 * 1000,
|
||||
value: ping
|
||||
};
|
||||
text = result.ping + " ms";
|
||||
localStorage.setItem(auto_detection_time + ":" + dom.address + ":" + dom.port, JSON.stringify(cache_data));
|
||||
text = result.ping + " ms";
|
||||
if (ping < 100)
|
||||
color = "green";
|
||||
else if (ping < 200)
|
||||
color = "#fb9a05";
|
||||
} else {
|
||||
const cache_data = {
|
||||
dom_id: strs[i],
|
||||
timestamp: Date.now(),
|
||||
savetime: 60 * 1000,
|
||||
value: -1
|
||||
};
|
||||
localStorage.setItem(auto_detection_time + ":" + dom.address + ":" + dom.port, JSON.stringify(cache_data));
|
||||
}
|
||||
a.innerText = text;
|
||||
a.style.color = color;
|
||||
@ -1101,6 +1113,15 @@ table td, .table .td {
|
||||
onChange("auto_detection_time", auto_detection_time);
|
||||
});
|
||||
});
|
||||
|
||||
const links = document.querySelectorAll('a');
|
||||
links.forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
if (link.getAttribute('target') !== '_blank') {
|
||||
ajaxAbortAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
@ -2144,3 +2144,6 @@ msgstr "Gecko 包大小(最小)"
|
||||
|
||||
msgid "Gecko Packet Size (max)"
|
||||
msgstr "Gecko 包大小(最大)"
|
||||
|
||||
msgid "valid time (hh:mm)"
|
||||
msgstr "有效时间(hh:mm)"
|
||||
|
||||