🐤 Sync 2025-11-09 00:09:52
This commit is contained in:
@@ -176,13 +176,13 @@ local api = require "luci.passwall.api"
|
||||
<div id="add_link_div">
|
||||
<div id="add_link_modal_container">
|
||||
<h3><%:Add the node via the link%></h3>
|
||||
<div class="cbi-value">
|
||||
<div class="value-custom">
|
||||
<textarea id="nodes_link" rows="10"></textarea>
|
||||
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
||||
</div>
|
||||
<div class="cbi-value modal-center">
|
||||
<label class="cbi-value-title"><%:Group Name%></label>
|
||||
<div class="cbi-value-field">
|
||||
<div class="value-custom">
|
||||
<div class="value-field-custom">
|
||||
<label class="value-title-custom"><%:Group Name%></label>
|
||||
<div id="addlink_group_custom" class="custom-dropdown">
|
||||
<div class="selected-display">
|
||||
<span class="text"><%:default%></span>
|
||||
@@ -252,13 +252,12 @@ local api = require "luci.passwall.api"
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
#nodes_link_text {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
margin-top: 0;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -271,43 +270,40 @@ local api = require "luci.passwall.api"
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center {
|
||||
.value-custom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
padding: 0px 5px 0px 5px;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-title {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
.value-field-custom {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.value-title-custom {
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-field {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
width: 200px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.custom-dropdown {
|
||||
position: relative;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
width: 200px;
|
||||
width: 180px;
|
||||
height: 28px;
|
||||
font-size: 13px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.selected-display {
|
||||
@@ -315,7 +311,9 @@ local api = require "luci.passwall.api"
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.selected-display:hover {
|
||||
@@ -331,7 +329,7 @@ local api = require "luci.passwall.api"
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
width: 180px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-top: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||||
@@ -339,7 +337,7 @@ local api = require "luci.passwall.api"
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: 250px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 100;
|
||||
@@ -349,6 +347,7 @@ local api = require "luci.passwall.api"
|
||||
.dropdown-item {
|
||||
padding: 4px 8px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown-item.selected {
|
||||
@@ -356,13 +355,17 @@ local api = require "luci.passwall.api"
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.create-item-input::placeholder {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dropdown-item.custom-input input {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
border: 1px solid #ccc;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -134,6 +134,7 @@ function link_add_node()
|
||||
local chunk = http.formvalue("chunk")
|
||||
local chunk_index = tonumber(http.formvalue("chunk_index"))
|
||||
local total_chunks = tonumber(http.formvalue("total_chunks"))
|
||||
local group = http.formvalue("group") or "default"
|
||||
|
||||
if chunk and chunk_index ~= nil and total_chunks ~= nil then
|
||||
-- 按顺序拼接到文件
|
||||
@@ -148,7 +149,7 @@ function link_add_node()
|
||||
end
|
||||
-- 如果是最后一片,才执行
|
||||
if chunk_index + 1 == total_chunks then
|
||||
luci.sys.call("lua /usr/share/passwall2/subscribe.lua add log")
|
||||
luci.sys.call("lua /usr/share/passwall2/subscribe.lua add " .. group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,10 +23,12 @@ o.default = translate("Remarks")
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "group", translate("Group Name"))
|
||||
o.default = ""
|
||||
o:value("", translate("default"))
|
||||
local groups = {}
|
||||
m.uci:foreach(appname, "nodes", function(s)
|
||||
if s[".name"] ~= arg[1] then
|
||||
if s.group then
|
||||
if s.group and s.group ~= "" then
|
||||
groups[s.group] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1208,11 +1208,18 @@ function set_apply_on_parse(map)
|
||||
return
|
||||
end
|
||||
if is_js_luci() == true then
|
||||
map.apply_on_parse = false
|
||||
map.on_after_apply = function(self)
|
||||
if self.redirect then
|
||||
os.execute("sleep 1")
|
||||
luci.http.redirect(self.redirect)
|
||||
local hide_popup_box = nil
|
||||
if hide_popup_box == true then
|
||||
map.apply_on_parse = false
|
||||
map.on_after_apply = function(self)
|
||||
if self.redirect then
|
||||
os.execute("sleep 1")
|
||||
luci.http.redirect(self.redirect)
|
||||
end
|
||||
end
|
||||
else
|
||||
map.on_after_save = function(self)
|
||||
map:set("@global[0]", "timestamp", os.time())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ local api = require "luci.passwall2.api"
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function ajax_add_node(link) {
|
||||
function ajax_add_node(link, group) {
|
||||
const chunkSize = 1000; // 分片发送以突破uhttpd的限制,每块1000字符
|
||||
const totalChunks = Math.ceil(link.length / chunkSize);
|
||||
let currentChunk = 0;
|
||||
@@ -31,6 +31,7 @@ local api = require "luci.passwall2.api"
|
||||
formData.append("chunk", chunk);
|
||||
formData.append("chunk_index", currentChunk);
|
||||
formData.append("total_chunks", totalChunks);
|
||||
formData.append("group", group);
|
||||
xhr.send(formData);
|
||||
} else {
|
||||
window.location.href = '<%=api.url("node_list")%>';
|
||||
@@ -50,11 +51,12 @@ local api = require "luci.passwall2.api"
|
||||
|
||||
function add_node() {
|
||||
var nodes_link = document.getElementById("nodes_link").value;
|
||||
var group = (document.querySelector('#addlink_group_custom input[type="hidden"]')?.value || "default");
|
||||
nodes_link = nodes_link.replace(/\t/g, "").replace(/\r\n|\r/g, "\n").trim();
|
||||
if (nodes_link != "") {
|
||||
var s = nodes_link.split('://');
|
||||
if (s.length > 1) {
|
||||
ajax_add_node(nodes_link);
|
||||
ajax_add_node(nodes_link, group);
|
||||
}
|
||||
else {
|
||||
alert("<%:Please enter the correct link.%>");
|
||||
@@ -83,6 +85,92 @@ local api = require "luci.passwall2.api"
|
||||
window.location.href = '<%=api.url("add_node")%>?redirect=1';
|
||||
}
|
||||
|
||||
|
||||
//自定义分组下拉列表事件
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var dropdown = document.getElementById("addlink_group_custom");
|
||||
if (!dropdown) return;
|
||||
|
||||
var display = dropdown.querySelector(".selected-display");
|
||||
var displayText = display.querySelector(".text");
|
||||
var list = dropdown.querySelector(".dropdown-list");
|
||||
var hidden = dropdown.querySelector('input[type="hidden"]');
|
||||
var input = dropdown.querySelector(".create-item-input");
|
||||
|
||||
display.addEventListener("click", function() {
|
||||
list.style.display = list.style.display === "none" ? "block" : "none";
|
||||
input.value = "";
|
||||
input.focus();
|
||||
});
|
||||
|
||||
function selectItem(li) {
|
||||
list.querySelectorAll(".dropdown-item").forEach(function(el){
|
||||
el.classList.remove("selected");
|
||||
});
|
||||
li.classList.add("selected");
|
||||
hidden.value = li.dataset.value;
|
||||
displayText.textContent = li.dataset.value || "<%:default%>";
|
||||
list.style.display = "none";
|
||||
}
|
||||
|
||||
list.addEventListener("click", function(e){
|
||||
var li = e.target.closest(".dropdown-item");
|
||||
if (!li || li.classList.contains("custom-input")) return;
|
||||
selectItem(li);
|
||||
});
|
||||
|
||||
input.addEventListener("keydown", function(e){
|
||||
if (e.keyCode !== 13) return;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
var val = input.value.trim();
|
||||
if (!val) return;
|
||||
|
||||
var li = Array.from(list.querySelectorAll(".dropdown-item")).find(function(el){
|
||||
return el.dataset.value === val;
|
||||
});
|
||||
if (!li) {
|
||||
li = document.createElement("li");
|
||||
li.className = "dropdown-item";
|
||||
li.dataset.value = val;
|
||||
li.textContent = val;
|
||||
list.insertBefore(li, input.parentNode);
|
||||
}
|
||||
|
||||
input.value = "";
|
||||
selectItem(li);
|
||||
});
|
||||
// 从tab中读取分组名称
|
||||
var observer = new MutationObserver(function(mutations, obs){
|
||||
var tabs = document.querySelectorAll(".cbi-tabmenu li");
|
||||
if(!tabs.length) return;
|
||||
|
||||
tabs.forEach(function(li){
|
||||
var group = li.id.split('.').pop();
|
||||
if(group === "default") return;
|
||||
if(Array.from(list.querySelectorAll(".dropdown-item")).some(el => el.dataset.value === group)) return;
|
||||
|
||||
var newLi = document.createElement("li");
|
||||
newLi.className = "dropdown-item";
|
||||
newLi.dataset.value = group;
|
||||
newLi.textContent = group;
|
||||
|
||||
list.insertBefore(newLi, input.parentNode);
|
||||
});
|
||||
|
||||
obs.disconnect();
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
|
||||
// 点击外部时自动收起
|
||||
document.addEventListener("click", function(e) {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
list.style.display = "none";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
@@ -93,6 +181,24 @@ local api = require "luci.passwall2.api"
|
||||
<textarea id="nodes_link" rows="10"></textarea>
|
||||
<p id="nodes_link_text"><%:Enter share links, one per line. Subscription links are not supported!%></p>
|
||||
</div>
|
||||
<div class="cbi-value modal-center">
|
||||
<label class="cbi-value-title"><%:Group Name%></label>
|
||||
<div class="cbi-value-field">
|
||||
<div id="addlink_group_custom" class="custom-dropdown">
|
||||
<div class="selected-display">
|
||||
<span class="text"><%:default%></span>
|
||||
<span class="arrow">▾</span>
|
||||
</div>
|
||||
<ul class="dropdown-list" style="display:none;">
|
||||
<li class="dropdown-item" data-value=""><%:default%></li>
|
||||
<li class="dropdown-item custom-input">
|
||||
<input type="text" placeholder="-- <%:custom%> --" class="create-item-input">
|
||||
</li>
|
||||
</ul>
|
||||
<input type="hidden" name="addlink_group" value="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="add_link_button_container">
|
||||
<input class="btn cbi-button cbi-button-add" type="button" onclick="add_node()" value="<%:Add%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="close_add_link_div()" value="<%:Close%>" />
|
||||
@@ -107,7 +213,7 @@ local api = require "luci.passwall2.api"
|
||||
<input class="btn cbi-button cbi-button-add" type="button" onclick="open_add_link_div()" value="<%:Add the node via the link%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="clear_all_nodes()" value="<%:Clear all nodes%>" />
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" onclick="delete_select_nodes()" value="<%:Delete select nodes%>" />
|
||||
<input class="btn cbi-button" type="button" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button" type="button" id="select_all_btn" onclick="checked_all_node(this)" value="<%:Select all%>" />
|
||||
<input class="btn cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:Save & Apply%>" />
|
||||
<input class="btn cbi-button cbi-button-save" type="submit" name="cbi.save" value="<%:Save%>" />
|
||||
<input class="btn cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
|
||||
@@ -147,12 +253,13 @@ local api = require "luci.passwall2.api"
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
#nodes_link_text {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
margin-top: 5px;
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -164,4 +271,99 @@ local api = require "luci.passwall2.api"
|
||||
max-width: 300px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-title {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#add_link_modal_container .modal-center .cbi-value-field {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.custom-dropdown {
|
||||
position: relative;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
width: 200px;
|
||||
font-size: 13px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.selected-display {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.selected-display:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.selected-display .arrow {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dropdown-list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-top: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||||
background: #fff;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 100;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 4px 8px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.dropdown-item.selected {
|
||||
background-color: #1e90ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dropdown-item.custom-input input {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -76,6 +76,12 @@ table td, .table .td {
|
||||
|
||||
function cbi_t_switch(section, tab) {
|
||||
if( cbi_t[section] && cbi_t[section][tab] ) {
|
||||
//在切换选项卡之前,先取消当前激活选项卡的全选状态
|
||||
var btn = document.getElementById("select_all_btn");
|
||||
if (btn) {
|
||||
dechecked_all_node(btn);
|
||||
}
|
||||
|
||||
var o = cbi_t[section][tab];
|
||||
var h = document.getElementById('tab.' + section);
|
||||
for( var tid in cbi_t[section] ) {
|
||||
@@ -191,7 +197,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function checked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall2-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall2-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = true;
|
||||
@@ -202,7 +210,9 @@ table td, .table .td {
|
||||
}
|
||||
|
||||
function dechecked_all_node(btn) {
|
||||
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall2-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall2-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
doms[i].checked = false;
|
||||
@@ -214,7 +224,9 @@ table td, .table .td {
|
||||
|
||||
function delete_select_nodes() {
|
||||
var ids = [];
|
||||
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
|
||||
var visibleContainer = document.querySelector('#cbi-passwall2-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-passwall2-nodes > .cbi-tabcontainer[style*="display: block"]');
|
||||
if (!visibleContainer) return;
|
||||
var doms = visibleContainer.getElementsByClassName("nodes_select");
|
||||
if (doms && doms.length > 0) {
|
||||
for (var i = 0 ; i < doms.length; i++) {
|
||||
if (doms[i].checked) {
|
||||
@@ -554,7 +566,7 @@ table td, .table .td {
|
||||
var group_nodes = {}
|
||||
for (let i = 0; i < node_list.length; i++) {
|
||||
let _node = node_list[i]
|
||||
if (!_node.group) {
|
||||
if (!_node.group || _node.group === "") {
|
||||
_node.group = "default"
|
||||
}
|
||||
if (!group_nodes[_node.group]) {
|
||||
@@ -617,10 +629,15 @@ table td, .table .td {
|
||||
_html = _html.split("{{node-tr}}").join(node_tr_html);
|
||||
table_html = _html;
|
||||
}
|
||||
|
||||
var group_name = group
|
||||
if (group === "default") {
|
||||
group_name = "<%:default%>"
|
||||
}
|
||||
|
||||
tab_ul_li_html +=
|
||||
'<li id="tab.passwall2.nodes.' + group + '" class="cbi-tab">' +
|
||||
'<a onclick="this.blur(); return cbi_t_switch(\'passwall2.nodes\', \'' + group + '\')" href="<%=REQUEST_URI%>?tab.passwall2.nodes=' + group + '">' + group + " | " + "<font style='color: red'>" + group_nodes[group].length + '</font></a>' +
|
||||
'<a onclick="this.blur(); return cbi_t_switch(\'passwall2.nodes\', \'' + group + '\')" href="<%=REQUEST_URI%>?tab.passwall2.nodes=' + group + '">' + group_name + " | " + "<font style='color: red'>" + group_nodes[group].length + '</font></a>' +
|
||||
'</li>'
|
||||
tab_content_html +=
|
||||
'<div class="cbi-tabcontainer" id="container.passwall2.nodes.' + group + '" style="display: none;">' +
|
||||
|
||||
@@ -553,8 +553,8 @@ load_acl() {
|
||||
}
|
||||
|
||||
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
nft "add $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
|
||||
nft "add $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 counter meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"默认\""
|
||||
if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
|
||||
echolog " - ${msg}不代理 UDP 端口[${UDP_NO_REDIR_PORTS}]"
|
||||
else
|
||||
@@ -1085,7 +1085,7 @@ gen_include() {
|
||||
PR_INDEX=\$(sh ${MY_PATH} RULE_LAST_INDEX "$NFTABLE_NAME" PSW2_MANGLE_V6 WAN6_IP_RETURN -1)
|
||||
if [ \$PR_INDEX -ge 0 ]; then
|
||||
WAN6_IP=\$(sh ${MY_PATH} get_wan6_ip)
|
||||
[ ! -z "\${WAN_IP}" ] && nft "replace rule $NFTABLE_NAME PSW2_MANGLE_V6 handle \$PR_INDEX ip6 daddr "\${WAN6_IP}" counter return comment \"WAN6_IP_RETURN\""
|
||||
[ ! -z "\${WAN6_IP}" ] && nft "replace rule $NFTABLE_NAME PSW2_MANGLE_V6 handle \$PR_INDEX ip6 daddr "\${WAN6_IP}" counter return comment \"WAN6_IP_RETURN\""
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
|
||||
@@ -1739,7 +1739,9 @@ local function update_node(manual)
|
||||
if type(vvv) == "table" and next(vvv) ~= nil then
|
||||
uci:set_list(appname, cfgid, kkk, vvv)
|
||||
else
|
||||
uci:set(appname, cfgid, kkk, vvv)
|
||||
if kkk ~= "group" or vvv ~= "default" then
|
||||
uci:set(appname, cfgid, kkk, vvv)
|
||||
end
|
||||
-- sing-box 域名解析策略
|
||||
if kkk == "type" and vvv == "sing-box" then
|
||||
uci:set(appname, cfgid, "domain_strategy", domain_strategy_node)
|
||||
@@ -2034,7 +2036,7 @@ if arg[1] then
|
||||
local f = assert(io.open("/tmp/links.conf", 'r'))
|
||||
local raw = f:read('*all')
|
||||
f:close()
|
||||
parse_link(raw, "1", "导入")
|
||||
parse_link(raw, "1", arg[2])
|
||||
update_node(1)
|
||||
luci.sys.call("rm -f /tmp/links.conf")
|
||||
elseif arg[1] == "truncate" then
|
||||
|
||||
@@ -4944,73 +4944,3 @@ div#add_link_div {
|
||||
max-width: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "easeicon"; /* Project id 3156136 */
|
||||
src: url('../fonts/iconfont.woff2') format('woff2'),
|
||||
url('../fonts/iconfont.woff') format('woff'),
|
||||
url('../fonts/iconfont.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.easeicon {
|
||||
font-family: "easeicon" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.eicon-wifi:before {
|
||||
content: "\e627";
|
||||
}
|
||||
|
||||
.eicon-store:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
||||
.eicon-docker:before {
|
||||
content: "\e659";
|
||||
}
|
||||
|
||||
.eicon-network:before {
|
||||
content: "\ecc7";
|
||||
}
|
||||
|
||||
.eicon-dashboard:before {
|
||||
content: "\e664";
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=Docker]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=Docker]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e659" !important;
|
||||
color: #0c93f3;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=iStore]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=iStore]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e60f" !important;
|
||||
color: #8965e0;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=QuickStart]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=QuickStart]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e664" !important;
|
||||
color: #11cdef;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=NetworkGuide]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=NetworkGuide]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\ecc7" !important;
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=Wireless]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=Wireless]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e627" !important;
|
||||
color: #03cdf0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
@font-face {
|
||||
font-family: "easeicon"; /* Project id 3156136 */
|
||||
src: url('iconfont.woff2?t=1749538073338') format('woff2'),
|
||||
url('iconfont.woff?t=1749538073338') format('woff'),
|
||||
url('iconfont.ttf?t=1749538073338') format('truetype');
|
||||
}
|
||||
|
||||
.easeicon {
|
||||
font-family: "easeicon" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.eicon-wifi:before {
|
||||
content: "\e627";
|
||||
}
|
||||
|
||||
.eicon-store:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
||||
.eicon-docker:before {
|
||||
content: "\e659";
|
||||
}
|
||||
|
||||
.eicon-network:before {
|
||||
content: "\ecc7";
|
||||
}
|
||||
|
||||
.eicon-dashboard:before {
|
||||
content: "\e664";
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=Docker]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=Docker]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e659" !important;
|
||||
color: #0c93f3;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=iStore]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=iStore]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e60f" !important;
|
||||
color: #8965e0;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=QuickStart]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=QuickStart]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e664" !important;
|
||||
color: #11cdef;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=NetworkGuide]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=NetworkGuide]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\ecc7" !important;
|
||||
color: #fb6340;
|
||||
}
|
||||
|
||||
.main>.main-left>.nav>li.slide>.menu[data-title=Wireless]:before,
|
||||
.main>.main-left>.nav>li>a[data-title=Wireless]:before {
|
||||
font-family: 'easeicon' !important;
|
||||
content: "\e627" !important;
|
||||
color: #03cdf0;
|
||||
}
|
||||
@@ -133,6 +133,7 @@
|
||||
<% end -%>
|
||||
</style>
|
||||
<link rel="shortcut icon" type="image/ico" href="<%=media%>/favicon.ico">
|
||||
<link rel="stylesheet" href="<%=resource%>/easepi/easeicon.css?t=1749538073338">
|
||||
<% if node and node.css then %>
|
||||
<link rel="stylesheet" href="<%=resource%>/<%=node.css%>">
|
||||
<% end -%>
|
||||
|
||||
Reference in New Issue
Block a user