diff --git a/dae/Makefile b/dae/Makefile
index b6b1a201..a2c371a5 100644
--- a/dae/Makefile
+++ b/dae/Makefile
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dae
-PKG_VERSION:=2026.07.13
+PKG_VERSION:=2026.07.16
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
-PKG_SOURCE_VERSION:=f303e94cebeda73de63a5ab00652009a12f2384e
+PKG_SOURCE_VERSION:=eee7c94db84bca2a0384c7bb5d4f6d7d8a539ec7
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
PKG_MIRROR_HASH:=skip
diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua
index 860f9106..e3f3d9a1 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua
@@ -15,7 +15,8 @@ o.rmempty = false
o.default = false
-- [[ ACLs Settings ]]--
-s = m:section(TypedSection, "acl_rule")
+local cfgname = "acl_rule"
+s = m:section(TypedSection, cfgname)
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
@@ -103,4 +104,9 @@ o:value("1:65535", translate("All"))
o:value("53", "53")
]]--
+local sortable = Template(appname .. "/cbi/sortable")
+sortable.api = api
+sortable.target_cfgname = cfgname
+m:append(sortable)
+
return api.return_map(m)
diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua
index abff0091..c4784a87 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua
@@ -103,7 +103,8 @@ end
o:depends("health_check_type", "passwall_logic")
-- [[ Balancing Settings ]]--
-s = m:section(TypedSection, "haproxy_config", translate("Node List"))
+local cfgname = "haproxy_config"
+s = m:section(TypedSection, cfgname, translate("Node List"))
s.description = "" ..
translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. "
" ..
translate("Note that the node configuration parameters for load balancing must be consistent when use TCP health check type, otherwise it cannot be used normally!") .. ""
@@ -179,6 +180,11 @@ o:value(0, translate("Primary"))
o:value(1, translate("Standby"))
o.rmempty = false
+local sortable = Template(appname .. "/cbi/sortable")
+sortable.api = api
+sortable.target_cfgname = cfgname
+m:append(sortable)
+
m:append(Template(appname .. "/haproxy/js"))
return api.return_map(m)
diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua
index 326b2df0..276f2813 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua
@@ -129,7 +129,8 @@ o.cfgvalue = function(self, section)
translate("Manual subscription All"))
end
-s = m:section(TypedSection, "subscribe_list", "", "" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "")
+local cfgname = "subscribe_list"
+s = m:section(TypedSection, cfgname, "", "" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "")
s.addremove = true
s.anonymous = true
s.sortable = true
@@ -150,7 +151,7 @@ o.validate = function(self, value, section)
return nil, translate("Remark cannot be empty.")
end
local duplicate = false
- m.uci:foreach(appname, "subscribe_list", function(e)
+ m.uci:foreach(appname, cfgname, function(e)
if e[".name"] ~= section and e["remark"] and e["remark"]:lower() == value:lower() then
duplicate = true
return false
@@ -225,6 +226,11 @@ o.cfgvalue = function(self, section)
section, translate("Manual subscription"))
end
+local sortable = Template(appname .. "/cbi/sortable")
+sortable.api = api
+sortable.target_cfgname = cfgname
+m:append(sortable)
+
m:append(Template(appname .. "/node_subscribe/js"))
return api.return_map(m)
diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
index 8ad9e7e1..979d4fe4 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua
@@ -142,8 +142,10 @@ end
s:append(Template(appname .. "/rule/rule_version"))
+local cfgname = "shunt_rules"
+
if has_xray or has_singbox then
- s = m:section(TypedSection, "shunt_rules", "Sing-Box/Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "")
+ s = m:section(TypedSection, cfgname, "Sing-Box/Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "")
s.template = "cbi/tblsection"
s.anonymous = false
s.addremove = true
@@ -165,4 +167,9 @@ if has_xray or has_singbox then
o = s:option(DummyValue, "remarks", translate("Remarks"))
end
+local sortable = Template(appname .. "/cbi/sortable")
+sortable.api = api
+sortable.target_cfgname = cfgname
+m:append(sortable)
+
return api.return_map(m)
diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua
index 752c306e..f3a147a5 100644
--- a/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua
+++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua
@@ -13,7 +13,8 @@ t.addremove = false
e = t:option(Flag, "enable", translate("Enable"))
e.rmempty = false
-t = m:section(TypedSection, "user", translate("Users Manager"))
+local cfgname = "user"
+t = m:section(TypedSection, cfgname, translate("Users Manager"))
t.anonymous = true
t.addremove = true
t.sortable = true
@@ -88,6 +89,12 @@ e = t:option(Flag, "log", translate("Log"))
e.default = "1"
e.rmempty = false
+local sortable = Template(appname .. "/cbi/sortable")
+sortable.api = api
+sortable.appname = m.config
+sortable.target_cfgname = cfgname
+m:append(sortable)
+
m:append(Template(appname .. "/server/log"))
m:append(Template(appname .. "/server/users_list_status"))
diff --git a/luci-app-passwall/luasrc/view/passwall/cbi/nodes_listvalue_com.htm b/luci-app-passwall/luasrc/view/passwall/cbi/nodes_listvalue_com.htm
index 9de708e5..0e8940ef 100644
--- a/luci-app-passwall/luasrc/view/passwall/cbi/nodes_listvalue_com.htm
+++ b/luci-app-passwall/luasrc/view/passwall/cbi/nodes_listvalue_com.htm
@@ -403,7 +403,7 @@
function lv_expandGroupOfCurrent(cbid, listContainer, hiddenSelect) {
const key = hiddenSelect.options[0].value;
if (!key) return;
- const targetLi = listContainer.querySelector("li[data-key='" + key.replace(/'/g,"\\'") + "']");
+ const targetLi = listContainer.querySelector(`li[data-key='${CSS.escape(key)}']`);
if (!targetLi) return;
let parentGroup = targetLi.closest(".lv-group");
if (parentGroup) {
diff --git a/luci-app-passwall/luasrc/view/passwall/cbi/nodes_value_com.htm b/luci-app-passwall/luasrc/view/passwall/cbi/nodes_value_com.htm
index 1f784d04..d470ea4b 100644
--- a/luci-app-passwall/luasrc/view/passwall/cbi/nodes_value_com.htm
+++ b/luci-app-passwall/luasrc/view/passwall/cbi/nodes_value_com.htm
@@ -402,7 +402,7 @@
function v_expandGroupOfCurrent(cbid, listContainer, hiddenInput) {
const key = hiddenInput.value;
if (!key) return;
- const targetLi = listContainer.querySelector("li[data-key='" + key.replace(/'/g,"\\'") + "']");
+ const targetLi = listContainer.querySelector(`li[data-key='${CSS.escape(key)}']`);
if (!targetLi) return;
let parentGroup = targetLi.closest(".v-group");
if (parentGroup) {
diff --git a/luci-app-passwall/luasrc/view/passwall/cbi/sortable.htm b/luci-app-passwall/luasrc/view/passwall/cbi/sortable.htm
new file mode 100644
index 00000000..2f508eaf
--- /dev/null
+++ b/luci-app-passwall/luasrc/view/passwall/cbi/sortable.htm
@@ -0,0 +1,159 @@
+<%
+local api = self.api
+local appname = self.appname or api.appname
+local target_cfgname = self.target_cfgname
+-%>
+
+
+
\ No newline at end of file
diff --git a/luci-app-passwall/luasrc/view/passwall/haproxy/js.htm b/luci-app-passwall/luasrc/view/passwall/haproxy/js.htm
index 22256df1..6c84ed97 100644
--- a/luci-app-passwall/luasrc/view/passwall/haproxy/js.htm
+++ b/luci-app-passwall/luasrc/view/passwall/haproxy/js.htm
@@ -2,46 +2,8 @@
local api = require "luci.passwall.api"
local appname = api.appname
-%>
-
diff --git a/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm b/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm
index c0834a1c..d8ec0378 100644
--- a/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm
+++ b/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm
@@ -4,16 +4,8 @@ local fs = api.fs
local has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat")
local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
-%>
-