首页/ mobileweb/ 小草心动/ 代码预览

💻 代码预览 · 小草心动

mw_social · 上传者 小草网络
← 返回详情
xiaocao-dating/app.js · 约 12868 字符
1
2(function(){
3  var D = window.DATA;
4  var page = document.body.getAttribute('data-page');
5  function toast(m){var t=document.getElementById('toast');if(!t)return;t.textContent=m;t.classList.add('show');setTimeout(function(){t.classList.remove('show')},1400);}
6  function esc(s){return String(s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]});}
7  // 底部导航高亮
8  if(page){
9    var nav=document.querySelector('.nav a[data-nav="'+page+'"]');
10    if(nav)nav.classList.add('on');
11  }
12
13  /* ========== 首页滑卡 ========== */
14  if(page==='home'){
15    var pool = D.users.slice();
16    var deck = document.getElementById('deck');
17    var emptyEl = document.getElementById('empty');
18    var leftEl = document.getElementById('left');
19    var total = pool.length;
20    function render(){
21      deck.innerHTML='';
22      var show = pool.slice(0,3).reverse();
23      show.forEach(function(u,i){
24        var idx = show.length-1-i;
25        var c = document.createElement('div');
26        c.className='card';
27        c.style.zIndex = idx;
28        c.style.transform = 'scale('+(1-idx*0.05)+') translateY('+(idx*14)+'px)';
29        c.setAttribute('data-id',u.id);
30        var tags = u.tags.map(function(t){return '<span class="tag">'+esc(t)+'</span>';}).join('');
31        c.innerHTML =
32          '<div class="photo" style="background:'+u.grad+'">'+u.emoji+'</div>'+
33          '<div class="scrim"></div>'+
34          '<div class="decision like">心动</div><div class="decision nope">跳过</div>'+
35          '<div class="info"><div class="nm">'+esc(u.name)+' <span>'+u.age+'岁</span>'+
36            (u.verified?'<span class="vbadge">✔ 真人</span>':'')+'</div>'+
37            '<div class="jb">'+esc(u.job)+'</div>'+
38            '<div class="meta">📍 '+esc(u.dist)+' · 在线</div>'+
39            '<div class="tags">'+tags+'</div>'+
40            '<div style="font-size:13px;opacity:.92">'+esc(u.bio)+'</div></div>';
41        deck.appendChild(c);
42        if(idx===0) bindDrag(c,u);
43      });
44      leftEl.textContent = '今日剩余心动 ' + pool.length + ' 位';
45      if(pool.length===0){emptyEl.style.display='flex';deck.style.display='none';document.querySelector('.actbar').style.display='none';}
46    }
47    function like(u,c){
48      if(!c)return;
49      var lk=c.querySelector('.decision.like'); if(lk)lk.style.opacity=1;
50      c.style.transform='translate(120%,-40px) rotate(22deg)'; c.style.opacity=0;
51      setTimeout(function(){pool.shift();render(); showMatch(u);},330);
52    }
53    function nope(u,c){
54      if(!c)return;
55      var n=c.querySelector('.decision.nope'); if(n)n.style.opacity=1;
56      c.style.transform='translate(-120%,-40px) rotate(-22deg)'; c.style.opacity=0;
57      setTimeout(function(){pool.shift();render();},330);
58    }
59    function showMatch(u){
60      var m=document.getElementById('match');
61      document.getElementById('matchName').textContent=u.name;
62      document.getElementById('matchEmoji').textContent=u.emoji;
63      m.classList.add('show');
64    }
65    function bindDrag(c,u){
66      var sx=0,sy=0,dragging=false;
67      function down(e){dragging=true;var p=e.touches?e.touches[0]:e;sx=p.clientX;sy=p.clientY;c.style.transition='none';}
68      function move(e){if(!dragging)return;var p=e.touches?e.touches[0]:e;var dx=p.clientX-sx,dy=p.clientY-sy;
69        c.style.transform='translate('+dx+'px,'+dy+'px) rotate('+(dx/18)+'deg)';
70        var lk=c.querySelector('.decision.like'),np=c.querySelector('.decision.nope');
71        if(lk)lk.style.opacity=dx>40?Math.min(1,dx/90):0;
72        if(np)np.style.opacity=dx<-40?Math.min(1,-dx/90):0;
73        if(e.cancelable)e.preventDefault();}
74      function up(e){if(!dragging)return;dragging=false;c.style.transition='';var p=(e.changedTouches?e.changedTouches[0]:e);
75        var dx=p.clientX-sx;
76        if(dx>90)like(u,c); else if(dx<-90)nope(u,c);
77        else{c.style.transform='';var lk=c.querySelector('.decision.like'),np=c.querySelector('.decision.nope');if(lk)lk.style.opacity=0;if(np)np.style.opacity=0;}}
78      c.addEventListener('mousedown',down);window.addEventListener('mousemove',move);window.addEventListener('mouseup',up);
79      c.addEventListener('touchstart',down,{passive:true});c.addEventListener('touchmove',move,{passive:false});c.addEventListener('touchend',up);
80    }
81    document.getElementById('btnLike').onclick=function(){var c=deck.querySelector('.card');if(c)like(pool[0],c);};
82    document.getElementById('btnNope').onclick=function(){var c=deck.querySelector('.card');if(c)nope(pool[0],c);};
83    document.getElementById('btnStar').onclick=function(){toast('已超级喜欢 ⭐ 会优先被看到');};
84    document.getElementById('matchClose').onclick=function(){document.getElementById('match').classList.remove('show');};
85    render();
86  }
87
88  /* ========== 灵魂测试 ========== */
89  if(page==='soul'){
90    var qi=0, tally={};
91    var qs=D.soul.questions;
92    var step=document.getElementById('step');
93    var prog=document.getElementById('prog');
94    var qtext=document.getElementById('qtext');
95    var opts=document.getElementById('opts');
96    var intro=document.getElementById('intro');
97    var quiz=document.getElementById('quiz');
98    var result=document.getElementById('result');
99    function start(){intro.style.display='none';quiz.style.display='block';showQ();}
100    function showQ(){
101      prog.style.width=((qi)/qs.length*100)+'%';
102      step.textContent='第 '+(qi+1)+' / '+qs.length+' 题';
103      qtext.textContent=qs[qi].q;
104      opts.innerHTML='';
105      qs[qi].options.forEach(function(o){
106        var b=document.createElement('button');b.className='opt';b.textContent=o.t;
107        b.onclick=function(){tally[o.type]=(tally[o.type]||0)+1;qi++;
108          if(qi<qs.length){prog.style.width=(qi/qs.length*100)+'%';showQ();} else showRes();};
109        opts.appendChild(b);
110      });
111    }
112    function showRes(){
113      quiz.style.display='none';result.style.display='block';
114      var best='calm',max=0;for(var k in tally){if(tally[k]>max){max=tally[k];best=k;}}
115      var r=D.soul.results[best];
116      document.getElementById('resBadge').style.background=r.grad;
117      document.getElementById('resEmoji').textContent=r.emoji;
118      document.getElementById('resName').textContent=r.name;
119      document.getElementById('resDesc').textContent=r.desc;
120      var rec=document.getElementById('rec');
121      rec.innerHTML='';
122      D.users.slice(0,3).forEach(function(u){
123        var c=document.createElement('div');c.className='msg glass';
124        c.innerHTML='<div class="av" style="background:'+u.grad+'">'+u.emoji+'</div>'+
125          '<div class="bd"><div class="t">'+esc(u.name)+' <span>'+u.age+'岁</span></div>'+
126          '<div class="l">'+esc(u.tags.join(' · '))+'</div></div>'+
127          '<div class="tm">同频</div>';
128        c.onclick=function(){toast('已向 '+u.name+' 发起灵魂对话 💬');};
129        rec.appendChild(c);
130      });
131    }
132    document.getElementById('startQuiz').onclick=start;
133    document.getElementById('retake').onclick=function(){qi=0;tally={};result.style.display='none';intro.style.display='block';};
134  }
135
136  /* ========== 搭子广场 ========== */
137  if(page==='dazi'){
138    var scene=document.getElementById('scenes');
139    var list=document.getElementById('list');
140    var cur='全部';
141    var posts=D.dazi.posts.slice();
142    D.dazi.scenes.forEach(function(s){
143      var c=document.createElement('span');c.className='chip'+(s==='全部'?' on':'');c.textContent=s;
144      c.onclick=function(){cur=s;[].forEach.call(scene.children,function(x){x.classList.remove('on');});c.classList.add('on');render();};
145      scene.appendChild(c);
146    });
147    function render(){
148      list.innerHTML='';
149      var f=posts.filter(function(p){return cur==='全部'||p.scene===cur;});
150      if(!f.length){list.innerHTML='<div class="card-hint">该场景下还没有搭子,去发起一个吧~</div>';return;}
151      f.forEach(function(p){
152        var el=document.createElement('div');el.className='post glass';
153        el.innerHTML='<div class="ph"><div class="av" style="background:'+p.grad+'">'+p.emoji+'</div>'+
154          '<div class="who"><b>'+esc(p.user)+'</b> · '+esc(p.scene)+'<div>'+esc(p.dist)+' · '+esc(p.time)+'</div></div></div>'+
155          '<h3>'+esc(p.title)+'</h3><div class="de">'+esc(p.desc)+'</div>'+
156          '<div class="ft"><div class="left">已有 '+p.joined+' 人加入</div><div class="join">加入搭子</div></div>';
157        var jb=el.querySelector('.join');
158        jb.onclick=function(){if(jb.classList.contains('done'))return;jb.classList.add('done');jb.textContent='已加入 ✓';p.joined++;toast('已加入「'+p.title+'」搭子群 🎉');};
159        list.appendChild(el);
160      });
161    }
162    render();
163    // 发起搭子
164    var modal=document.getElementById('daziModal');
165    document.getElementById('openDazi').onclick=function(){modal.classList.add('show');};
166    document.getElementById('closeDazi').onclick=function(){modal.classList.remove('show');};
167    document.getElementById('submitDazi').onclick=function(){
168      var title=document.getElementById('dTitle').value.trim();
169      var desc=document.getElementById('dDesc').value.trim();
170      var sc=document.getElementById('dScene').value;
171      var emojis={'饭搭子':'🍜','旅游搭子':'🧳','运动搭子':'🏃','学习搭子':'📚','游戏搭子':'🎮','电影搭子':'🎬'};
172      if(!title||!desc){toast('请填写标题和描述');return;}
173      posts.unshift({scene:sc,title:title,desc:desc,user:'我',time:'刚刚',dist:'0m',joined:1,
174        emoji:emojis[sc]||'✨',grad:'linear-gradient(135deg,#ff4d8d,#8b5cf6)'});
175      modal.classList.remove('show');
176      document.getElementById('dTitle').value='';document.getElementById('dDesc').value='';
177      cur='全部';[].forEach.call(scene.children,function(x,i){x.classList.toggle('on',i===0);});
178      render();toast('搭子已发布,等待同频的人加入 🎉');
179    };
180  }
181
182  /* ========== 动态 ========== */
183  if(page==='moments'){
184    var list=document.getElementById('list');
185    function render(){
186      list.innerHTML='';
187      D.moments.forEach(function(m,i){
188        var el=document.createElement('div');el.className='moment glass';
189        el.innerHTML='<div class="hd"><div class="av" style="background:'+m.grad+'">'+m.emoji+'</div>'+
190          '<div><div class="nm">'+esc(m.user)+'</div><div class="tm">'+esc(m.time)+'</div></div></div>'+
191          '<div class="ct">'+esc(m.content)+'</div>'+
192          '<div class="img" style="background:'+m.img+'"></div>'+
193          '<div class="ft"><div class="lk" data-i="'+i+'">❤ <span>'+m.likes+'</span></div>'+
194          '<div>💬 '+m.comments+'</div></div>';
195        var lk=el.querySelector('.lk');
196        if(m.liked)lk.classList.add('on');
197        lk.onclick=function(){m.liked=!m.liked;m.likes+=m.liked?1:-1;lk.classList.toggle('on');lk.querySelector('span').textContent=m.likes;};
198        list.appendChild(el);
199      });
200    }
201    render();
202  }
203
204  /* ========== 我的 ========== */
205  if(page==='mine'){
206    var p=D.profile;
207    document.getElementById('pAvatar').style.background=p.grad;
208    document.getElementById('pAvatar').textContent=p.emoji;
209    document.getElementById('pName').innerHTML=esc(p.name)+' <span class="vbadge">✔ 真人</span>'+(p.vip?' <span class="vbadge" style="color:#ffd86b;border-color:rgba(255,216,107,.4);background:rgba(255,216,107,.12)">VIP</span>':'');
210    document.getElementById('pJob').textContent=p.age+'岁 · '+esc(p.job)+' · '+esc(p.city);
211    document.getElementById('pBio').textContent=p.bio;
212    document.getElementById('sLike').textContent=p.stats.like;
213    document.getElementById('sMatch').textContent=p.stats.match;
214    document.getElementById('sDazi').textContent=p.stats.dazi;
215    var msgList=document.getElementById('msgs');
216    D.matches.forEach(function(m){
217      var el=document.createElement('div');el.className='msg glass';
218      el.innerHTML='<div class="av" style="background:'+m.grad+'">'+m.emoji+'</div>'+
219        '<div class="bd"><div class="t">'+esc(m.name)+(m.verified?' <span class="vbadge">✔</span>':'')+'</div>'+
220        '<div class="l">'+esc(m.last)+'</div></div><div class="tm">'+esc(m.time)+'</div>';
221      el.onclick=function(){toast('打开与 '+m.name+' 的聊天 💬');};
222      msgList.appendChild(el);
223    });
224    [].forEach.call(document.querySelectorAll('.menu .it'),function(it){
225      it.onclick=function(){toast(it.querySelector('.tx').textContent+' · 演示功能');};
226    });
227  }
228
229  /* 通用:点 logo 回首页 */
230  var logo=document.querySelector('.brand');
231  if(logo && page!=='home'){logo.onclick=function(){location.href='index.html';};}
232})();
233