mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-08-01 12:29:36 +08:00
150 lines
4.0 KiB
HTML
150 lines
4.0 KiB
HTML
<%+cbi/valueheader%>
|
||
<%
|
||
-- Template Developers:
|
||
-- - lwb1978
|
||
-- - snowie2000
|
||
-- Copyright: copyright(c)2025–2027
|
||
-- Description: Passwall(2) UI template
|
||
|
||
local json = require "luci.jsonc"
|
||
|
||
-- 读取值(keylist/vallist/group)
|
||
local values = {}
|
||
for i, key in pairs(self.keylist) do
|
||
values[#values + 1] = {
|
||
key = key,
|
||
label = self.vallist[i] or key,
|
||
group = self.group and self.group[i] or nil
|
||
}
|
||
end
|
||
|
||
-- 获取当前配置值
|
||
local current_key = {}
|
||
local cval = self:cfgvalue(section)
|
||
if type(cval) == "table" then
|
||
for _, v in ipairs(cval) do
|
||
for item in string.gmatch(v, "[^,]+") do
|
||
current_key[#current_key+1] = item
|
||
end
|
||
end
|
||
elseif type(cval) == "string" then
|
||
for item in string.gmatch(cval, "[^,]+") do
|
||
current_key[#current_key+1] = item
|
||
end
|
||
end
|
||
|
||
-- 分离无组节点(ungrouped)与有组节点(grouped),并保持原有顺序
|
||
local ungrouped = {}
|
||
local groups = {}
|
||
local group_order = {}
|
||
for _, item in ipairs(values) do
|
||
if not item.group or item.group == "" then
|
||
table.insert(ungrouped, item)
|
||
else
|
||
local g = item.group
|
||
if not groups[g] then
|
||
groups[g] = {}
|
||
table.insert(group_order, g)
|
||
end
|
||
table.insert(groups[g], item)
|
||
end
|
||
end
|
||
|
||
-- 打包数据给 JS
|
||
local dropdown_data = {
|
||
current_key = current_key,
|
||
ungrouped = ungrouped,
|
||
groups = groups,
|
||
group_order = group_order,
|
||
cbid = cbid,
|
||
}
|
||
%>
|
||
<script>
|
||
window.dl_dropdown_data = window.dl_dropdown_data || {};
|
||
window.dl_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
|
||
</script>
|
||
|
||
<div id="<%=cbid%>.main" class="dl-dropdown-container">
|
||
<select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;">
|
||
<option value>placeholder</option>
|
||
</select>
|
||
|
||
<!-- 已选节点显示区 -->
|
||
<div id="<%=cbid%>.selected" class="dl-selected-list"></div>
|
||
|
||
<!-- 模拟 listvalue 控件外观 -->
|
||
<div class="cbi-input-value cbi-input-select dl-dropdown-display" id="<%=cbid%>.display" tabindex="0">
|
||
<span id="<%=cbid%>.label" class="dl-dropdown-label">
|
||
<%=translate("-- Please choose --")%>
|
||
</span>
|
||
<span class="dl-arrow-down"></span>
|
||
</div>
|
||
<!-- 下拉面板 -->
|
||
<div id="<%=cbid%>.panel" class="cbi-dynamiclist-panel dl-dropdown-panel" style="display:none;">
|
||
<!-- 搜索框 -->
|
||
<div style="padding:8px;border-bottom:1px solid #f0f0f0;">
|
||
<input id="<%=cbid%>.search" class="cbi-input-text dl-dropdown-search" type="text" placeholder="🔍 <%:Search nodes...%>" inputmode="search" enterkeyhint="done" />
|
||
</div>
|
||
<!-- 列表容器 -->
|
||
<div id="<%=cbid%>.list" style="padding:8px;">
|
||
<!-- 首次点击 display 时由 JS 填充 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="text/javascript">
|
||
//<![CDATA[
|
||
(function(){
|
||
const cbid = "<%=cbid%>";
|
||
const panel = document.getElementById(cbid + ".panel");
|
||
const display = document.getElementById(cbid + ".display");
|
||
const labelSpan = document.getElementById(cbid + ".label");
|
||
const searchInput = document.getElementById(cbid + ".search");
|
||
const listContainer = document.getElementById(cbid + ".list");
|
||
|
||
function init(){
|
||
const hidden = document.getElementById(cbid + ".hidden");
|
||
const data = window.dl_dropdown_data[cbid];
|
||
let arr = data.current_key;
|
||
if (!arr || arr.length === 0) return;
|
||
arr.forEach(key=>{
|
||
let label = "";
|
||
data.ungrouped.concat(...Object.values(data.groups)).forEach(v=>{
|
||
if (v.key == key) label = v.label;
|
||
});
|
||
if (label)
|
||
dl_add_item(cbid, key, label);
|
||
});
|
||
}
|
||
|
||
// 点击 display
|
||
display.addEventListener("click", function(e){
|
||
e.stopPropagation();
|
||
dl_render_dropdown_list(cbid,panel,listContainer,labelSpan,searchInput,display);
|
||
document.querySelectorAll(".cbi-dynamiclist-panel").forEach(p=>{
|
||
if (p !== panel) p.style.display = "none";
|
||
});
|
||
if (panel.style.display !== "none") {
|
||
dl_closePanel(cbid,panel,listContainer,searchInput);
|
||
} else {
|
||
dl_openPanel(cbid,display,panel,listContainer,searchInput);
|
||
}
|
||
});
|
||
|
||
dl_registerAdaptive(cbid);
|
||
|
||
init();
|
||
|
||
new Sortable(document.getElementById(cbid + ".selected"), {
|
||
animation: 150,
|
||
ghostClass: "dragging-row",
|
||
onEnd: function(){
|
||
dl_update_hidden(cbid);
|
||
}
|
||
});
|
||
})();
|
||
//]]>
|
||
</script>
|
||
|
||
<%+cbi/valuefooter%>
|