1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| {% raw %} <div id="links-root"></div> <style> #links-root{--gap:16px;--radius:14px;--card-bg:rgba(255,255,255,0.7);--card-border:rgba(0,0,0,0.06);--card-hover-bg:rgba(0,0,0,0.04);--shadow:0 6px 18px rgba(0,0,0,0.06);margin:0 auto;max-width:1100px} #links-root .links-category{margin:28px 0 22px} #links-root .links-category h2{margin:0 0 12px;font-size:1.25rem;font-weight:700;line-height:1.2} #links-root .links-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gap)} @media (max-width:768px){#links-root .links-grid{grid-template-columns:repeat(2,minmax(0,1fr))}} #links-root .friend-card{display:block;text-decoration:none;color:inherit;border-radius:var(--radius);border:1px solid var(--card-border);background:var(--card-bg);padding:10px;transition:transform .15s ease,box-shadow .15s ease,background .2s} #links-root .friend-card:hover{background:var(--card-hover-bg);transform:translateY(-2px);box-shadow:var(--shadow)} #links-root .avatar-wrap{position:relative;border-radius:12px;overflow:hidden;aspect-ratio:1/1} #links-root .avatar-wrap img{width:100%;height:100%;object-fit:cover;display:block} #links-root .avatar-wrap .desc{position:absolute;left:0;right:0;bottom:0;transform:translateY(100%);padding:10px 12px;background:rgba(0,0,0,.72);color:#fff;font-size:.875rem;line-height:1.35;transition:transform .2s ease;pointer-events:none} #links-root .avatar-wrap.reveal .desc{transform:translateY(0)} #links-root .meta{padding-top:8px} #links-root .name{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .post-title{display:none!important} </style> <script> const LINKS_DATA=[{links_category:"Team",list:[{name:"su-team",link:"https://su-team.cn/",description:"不止是CTF!",avatar:"https://baozongwi.xyz/images/su_logo/SU4.jpg"}]},{links_category:"friends🤩",list:[{name:"fushuling",link:"https://fushuling.com/",description:"带我进SU的好哥哥",avatar:"https://fushuling-1309926051.cos.ap-shanghai.myqcloud.com/2022/08/QQ%E5%9B%BE%E7%89%8720220812001845.jpg"},{name:"Y4tacker",link:"https://y4tacker.github.io/",description:"Y4师傅诶~",avatar:"https://y4tacker.github.io/images/me.jpeg"}]}]; const escapeHTML=(s)=>String(s).replace(/[&<>"']/g,(m)=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m])); function shuffle(arr){for(let i=arr.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[arr[i],arr[j]]=[arr[j],arr[i]]}return arr} function createCard(item){ const a=document.createElement('a'); a.className='friend-card'; a.href=item.link; a.target='_blank'; a.rel='noopener noreferrer'; a.setAttribute('aria-label',`${item.name} - ${item.description||''}`); a.innerHTML=` <div class="avatar-wrap"> <img src="${escapeHTML(item.avatar)}" alt="${escapeHTML(item.name)} avatar" loading="lazy" referrerpolicy="no-referrer"> <div class="desc" aria-hidden="true">${escapeHTML(item.description||'')}</div> </div> <div class="meta"> <div class="name" title="${escapeHTML(item.name)}">${escapeHTML(item.name)}</div> </div> `; const wrap=a.querySelector('.avatar-wrap'); let shownOnce=false; wrap.addEventListener('mouseenter',()=>{if(!shownOnce){wrap.classList.add('reveal');shownOnce=true}}); wrap.addEventListener('mouseleave',()=>{wrap.classList.remove('reveal');shownOnce=false}); wrap.addEventListener('touchstart',(e)=>{e.preventDefault();const willShow=!wrap.classList.contains('reveal');wrap.classList.toggle('reveal',willShow);shownOnce=willShow},{passive:false}); a.querySelector('img').addEventListener('error',(ev)=>{ev.target.src='data:image/svg+xml;utf8,'+encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400"><rect width="100%" height="100%" fill="#ddd"/><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="#555" font-size="22">${escapeHTML(item.name)}</text></svg>`)});return a} (function(){ const root=document.getElementById('links-root');if(!root)return; LINKS_DATA.forEach(cat=>{ const section=document.createElement('section'); section.className='links-category'; section.innerHTML=`<h2>${escapeHTML(cat.links_category)}</h2><div class="links-grid"></div>`; const grid=section.querySelector('.links-grid'); shuffle(cat.list.slice()).forEach(item=>grid.appendChild(createCard(item))); root.appendChild(section); }); })(); </script> {% endraw %}
|