account-link.html 5.1 KB

1234567891011121314151617181920212223242526272829303132333435
  1. <!doctype html>
  2. <html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="referrer" content="no-referrer">
  3. <title>确认本人账号 · 康师傅工作坊</title>
  4. <style>
  5. *{box-sizing:border-box}body{margin:0;padding:36px 18px;background:#f2f5f9;color:#19304b;font:16px/1.75 system-ui,sans-serif}main{max-width:560px;margin:5vh auto;background:white;border:1px solid #dce4ef;border-radius:24px;padding:32px;box-shadow:0 16px 55px #102d4810}.brand{color:#2869a5;font-size:14px}h1{font-size:28px;line-height:1.4;margin:14px 0}p{color:#526479}label{display:block;margin:16px 0 5px}input,button{font:inherit;width:100%;padding:12px 14px;border-radius:10px;border:1px solid #bdccdc}button{margin-top:22px;background:#176bba;color:white;border:0;cursor:pointer}button:disabled{opacity:.5;cursor:wait}.message{padding:14px;background:#f0f6fc;border-radius:10px;overflow-wrap:anywhere;margin-top:18px}.small{font-size:13px}[hidden]{display:none!important}@media(max-width:400px){main{padding:22px}h1{font-size:24px}}
  6. </style>
  7. <main><div class="brand">康师傅 · 产品创新工作坊</div><h1>把成果关联到本人账号</h1><p>仅首次关联时确认。后续课题、会话和报告都归入同一位成员。</p>
  8. <div id="message" class="message" role="status">正在检查登录状态…</div>
  9. <form id="login" hidden><label for="username">工作坊账号</label><input id="username" autocomplete="username" autocapitalize="none" spellcheck="false" required maxlength="200"><label for="password">密码</label><input id="password" type="password" autocomplete="current-password" required maxlength="1024"><button>登录本人账号</button></form>
  10. <button id="confirm" hidden>确认关联到此账号</button><button id="switch" hidden>改用其他账号登录</button>
  11. <p class="small">密码仅交给平台登录服务。请勿把密码、验证码或 Token 发给数字人。确认成功后回到原对话,告诉数字人“已完成账号绑定”。</p>
  12. </main>
  13. <script nonce="__NONCE__">
  14. const ticket=new URLSearchParams(location.hash.slice(1)).get('ticket');
  15. history.replaceState(null,'',location.pathname+location.search);
  16. const el=id=>document.getElementById(id),say=s=>{el('message').textContent=s;};
  17. const base='https://server.fmode.cn/parse',headers={'X-Parse-Application-Id':'ncloudmaster','Content-Type':'application/json'};
  18. let token='',username='',busy=false;
  19. async function platform(path,body){
  20. const r=await fetch(base+path,{method:body?'POST':'GET',headers:{...headers,...(token?{'X-Parse-Session-Token':token}:{})},...(body?{body:JSON.stringify(body)}:{}),credentials:'omit',redirect:'error',cache:'no-store',signal:AbortSignal.timeout(15000)});
  21. const j=await r.json();if(!r.ok)throw Error('账号登录失败或已过期,请核对账号和密码。');return j;
  22. }
  23. function loggedOut(){token='';el('login').hidden=false;el('confirm').hidden=true;el('switch').hidden=true;say('请登录在对话中确认的本人工作坊账号。');}
  24. async function showUser(){const u=await platform('/users/me');if(u.company?.objectId!=='FKieRbIoGt')throw Error('请使用康师傅工作坊账号登录。');username=u.username;el('login').hidden=true;el('confirm').hidden=false;el('switch').hidden=false;say('当前登录账号:'+username+'。请确认这是您在数字人对话中提供的账号。');}
  25. el('login').onsubmit=async e=>{e.preventDefault();if(busy)return;busy=true;el('login').querySelector('button').disabled=true;try{token='';const u=await platform('/login',{username:el('username').value.trim(),password:el('password').value});token=u.sessionToken;await showUser();}catch{loggedOut();say('登录未成功,请核对账号、密码及企业归属后重试。');}finally{el('password').value='';busy=false;el('login').querySelector('button').disabled=false;}};
  26. el('switch').onclick=()=>{loggedOut();};
  27. el('confirm').onclick=async()=>{if(busy)return;busy=true;el('confirm').disabled=true;try{
  28. const r=await fetch(location.pathname+location.search,{method:'POST',headers:{'Content-Type':'application/json','X-Parse-Application-Id':'FKieRbIoGt_main','X-Fmode-Session-Token':token},body:JSON.stringify({path:'/ksfWorkshopAccount',params:{action:'confirm',ticket}}),credentials:'omit',redirect:'error',cache:'no-store',signal:AbortSignal.timeout(20000)});
  29. const j=await r.json(),result=j.result;if(!r.ok||!result?.ok)throw Error(result?.errors?.[0]?.message||'绑定暂未完成,请回到对话核对。');
  30. if(result.data.status!=='bound')throw Error('绑定回执不完整,请回到对话核对。');
  31. say('已关联:'+result.data.displayName+'('+result.data.username+')。请回到数字人对话回复“已完成账号绑定”。');el('confirm').hidden=true;el('switch').hidden=true;token='';
  32. }catch(e){say(e.message||'绑定暂未完成,请稍后重试。');}finally{busy=false;el('confirm').disabled=false;}};
  33. if(!ticket){say('缺少绑定链接。请回到数字人对话获取新的链接。');}
  34. else{try{token=JSON.parse(sessionStorage.getItem('ksf-board:platform-session.v1')||'null')?.token||'';}catch{}if(token)showUser().catch(loggedOut);else loggedOut();}
  35. </script></html>