
按tab键可切换搜索分组,按管理打开编辑模式
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>浮岛分组搜索 Pro</title>
<style>
html,body{
margin:0;
width:100%;
height:100%;
overflow:hidden;
background:transparent;
font-family:"Microsoft YaHei",sans-serif;
}
.card{
width:100%;
height:100%;
box-sizing:border-box;
padding:12px;
border-radius:18px;
background:linear-gradient(135deg,#0b1220,#0f172a 55%,#0a0f1c);
border:1px solid rgba(120,180,255,.18);
box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 10px 30px rgba(0,0,0,.35);
display:flex;
flex-direction:column;
gap:10px;
}
.top{
display:flex;
gap:8px;
}
input{
flex:1;
height:38px;
border-radius:12px;
border:1px solid rgba(255,255,255,.08);
background:rgba(255,255,255,.04);
color:#e5e7eb;
padding:0 12px;
outline:none;
}
button{
height:38px;
padding:0 12px;
border-radius:12px;
border:1px solid rgba(59,130,246,.35);
background:rgba(59,130,246,.22);
color:#fff;
cursor:pointer;
}
/* 横向分组栏 */
.groupBar{
display:flex;
gap:6px;
overflow-x:auto;
padding-bottom:4px;
scrollbar-width:none;
}
.groupBar::-webkit-scrollbar{
display:none;
}
.groupTab{
flex-shrink:0;
padding:6px 10px;
border-radius:999px;
font-size:12px;
color:rgba(200,220,255,.8);
border:1px solid rgba(255,255,255,.08);
background:rgba(255,255,255,.03);
cursor:pointer;
transition:.15s;
white-space:nowrap;
}
.groupTab.active{
background:rgba(59,130,246,.25);
border-color:rgba(120,180,255,.35);
color:#fff;
}
.addTab{
color:#9ecbff;
}
.panel{
flex:1;
overflow-y:auto;
border-radius:12px;
background:rgba(255,255,255,.02);
border:1px solid rgba(255,255,255,.05);
padding:8px;
}
.item{
display:flex;
justify-content:space-between;
padding:8px;
border-radius:10px;
margin-bottom:6px;
background:rgba(255,255,255,.02);
border:1px solid rgba(255,255,255,.04);
cursor:pointer;
}
.item:hover{
background:rgba(255,255,255,.05);
}
.name{color:#e5e7eb;font-size:13px;}
.url{font-size:11px;color:rgba(147,197,253,.7);max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
</style>
</head>
<body>
<div class="card">
<div class="top">
<input id="input" placeholder="输入搜索内容">
<button id="search">搜索</button>
<button id="manage">管理</button>
</div>
<div class="groupBar" id="groupBar"></div>
<div class="panel" id="panel"></div>
</div>
<script>
(function(){
let manage=false;
let data={
current:0,
groups:[
{name:"影视",sites:[
{name:"B站影视",url:"https://search.bilibili.com/all?keyword={q} 剧"}
]},
{name:"图片",sites:[
{name:"Pinterest",url:"https://www.pinterest.com/search/pins/?q={q}"}
]},
{name:"全部",sites:[
{name:"Google",url:"https://www.google.com/search?q={q}"},
{name:"B站",url:"https://search.bilibili.com/all?keyword={q}"}
]}
]
};
const input=document.getElementById("input");
const bar=document.getElementById("groupBar");
const panel=document.getElementById("panel");
function ready(){ return window.fudao && window.fudao.invoke; }
async function load(){
if(ready()){
try{
const r=await window.fudao.invoke("state.read",{key:"groups",defaultValue:JSON.stringify(data)});
data=JSON.parse(r||JSON.stringify(data));
}catch(e){}
}
render();
}
async function save(){
if(ready()){
await window.fudao.invoke("state.write",{key:"groups",value:JSON.stringify(data)});
}
}
function renderGroups(){
bar.innerHTML="";
// 按顺序渲染:普通分组 + 全部放最后
const normalGroups=data.groups.filter(g=>g.name!=="全部");
const allGroups=data.groups.filter(g=>g.name==="全部");
const renderList=[...normalGroups,...allGroups];
renderList.forEach((g,i)=>{
const idx=data.groups.indexOf(g);
const tab=document.createElement("div");
tab.className="groupTab"+(idx===data.current?" active":"");
tab.innerText=g.name;
tab.onclick=()=>{
data.current=idx;
render();
save();
};
bar.appendChild(tab);
});
if(manage){
const add=document.createElement("div");
add.className="groupTab addTab";
add.innerText="+ 新增";
add.onclick=()=>{
const name=prompt("分组名");
if(name){
data.groups.push({name,sites:[]});
render();save();
}
};
bar.appendChild(add);
}
}
function renderSites(){
const g=data.groups[data.current];
panel.innerHTML="";
g.sites.forEach((s,i)=>{
const div=document.createElement("div");
div.className="item";
div.innerHTML=`
<div>
<div class="name">${s.name}</div>
<div class="url">${s.url}</div>
</div>
<div>
${manage?'<button>✏</button><button>🗑</button>':''}
</div>
`;
div.onclick=()=>{ if(!manage) open(s.url); };
panel.appendChild(div);
});
if(manage){
const add=document.createElement("div");
add.className="item";
add.innerHTML="<div class='name'>+ 新增网站</div>";
add.onclick=()=>{
const name=prompt("网站名");
const url=prompt("URL (用 {q})");
if(name && url){ g.sites.push({name,url}); render(); save(); }
};
panel.appendChild(add);
}
}
function open(url){
const q=encodeURIComponent(input.value.trim());
if(!q) return;
const final=url.replace("{q}",q);
if(ready()){
window.fudao.invoke("url.open",{url:final});
}else{
window.open(final);
}
}
function render(){
renderGroups();
renderSites();
}
document.getElementById("manage").onclick=()=>{ manage=!manage; render(); };
document.getElementById("search").onclick=()=>{ data.groups[data.current].sites.forEach(s=>open(s.url)); };
input.addEventListener("keydown",e=>{
if(e.key==="Tab"){ e.preventDefault(); data.current=(data.current+1)%data.groups.length; render(); save(); }
if(e.key==="Enter"){ document.getElementById("search").click(); }
});
setTimeout(load,300);
})();
</script>
</body>
</html>