(() => { 'use strict'; const form = document.getElementById('auth-form'); const username = document.getElementById('username'); const password = document.getElementById('password'); const remember = document.getElementById('auth-remember'); const submit = document.getElementById('auth-submit'); const feedback = document.getElementById('auth-feedback'); const serviceButton = document.getElementById('auth-service'); const serviceName = document.getElementById('auth-service-name'); const subtitle = document.getElementById('auth-subtitle'); const passwordToggle = document.getElementById('auth-toggle-password'); const dialog = document.getElementById('auth-dialog'); const dialogContent = document.getElementById('auth-dialog-content'); const DEMO = Object.freeze({username:'demo', password:'Demo123!'}); const keys = {account:'yuexin-terminal-login-account',connection:'yuexin-terminal-login-connection'}; const escape = value => String(value).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); const read = key => {try{return JSON.parse(localStorage.getItem(key)||'null');}catch{return null;}}; const write = (key,value) => {try{if(value===null)localStorage.removeItem(key);else localStorage.setItem(key,JSON.stringify(value));return true;}catch{return false;}}; function validEndpoint(value) { try { const u = new URL(value); if (u.username || u.password || u.search || u.hash) return null; if (u.protocol !== 'https:' && !(u.protocol === 'http:' && ['localhost','127.0.0.1','[::1]'].includes(u.hostname))) return null; return u.href.replace(/\/$/,''); } catch {return null;} } const savedConnection = read(keys.connection); let connection = savedConnection?.mode === 'enterprise' && validEndpoint(savedConnection.url) ? {mode:'enterprise',url:validEndpoint(savedConnection.url),organization:String(savedConnection.organization||'').slice(0,80)} : {mode:'cloud',url:'',organization:''}; let mode = connection.mode, serviceIntent = '', busy = false, loginTimer, modalTimer, modalBusy = false; let credentials = null; let serviceDraft = {url:connection.url,organization:connection.organization}; function restoreAccount() { const saved = read(keys.account); username.value = typeof saved?.username === 'string' ? saved.username.slice(0,100) : ''; remember.checked = saved?.remember !== false; } function updateService() { serviceName.textContent = connection.mode === 'enterprise' ? '企业部署' : '云端服务'; serviceButton.setAttribute('aria-label',serviceName.textContent+',打开连接设置'); serviceButton.title = connection.mode === 'enterprise' ? connection.url : '云端服务'; subtitle.textContent = connection.mode === 'enterprise' ? '使用企业工作账号继续' : '使用云端工作账号继续'; } function message(text,error = false) { feedback.textContent = text; feedback.classList.toggle('error',error); } function clearInvalid() { username.removeAttribute('aria-invalid');password.removeAttribute('aria-invalid'); } function setBusy(value) { busy = value; form.setAttribute('aria-busy',String(value)); form.querySelectorAll('input,button').forEach(el=>{el.disabled=value;}); serviceButton.disabled=value; submit.innerHTML=value?'登录中…':'登 录'; } function concealPassword() { password.type='password';passwordToggle.setAttribute('aria-pressed','false');passwordToggle.setAttribute('aria-label','显示密码'); } function enterWorkspace(identity) { clearTimeout(loginTimer);credentials=null;password.value='';concealPassword();setBusy(false);message(''); document.dispatchEvent(new CustomEvent('terminal:login',{detail:identity})); } function submitLogin(event) { event.preventDefault(); if(busy)return; clearInvalid(); const account=username.value.trim(); if(!account){username.setAttribute('aria-invalid','true');message('请输入工作账号',true);username.focus();return;} if(!password.value){password.setAttribute('aria-invalid','true');message('请输入密码',true);password.focus();return;} credentials={username:account,password:password.value}; setBusy(true);message('正在验证工作账号…'); loginTimer=setTimeout(()=>{ const accepted=credentials?.username===DEMO.username&&credentials?.password===DEMO.password; credentials=null;setBusy(false); if(!accepted){password.value='';concealPassword();password.setAttribute('aria-invalid','true');message('账号或密码不正确,请重试或查看体验账号',true);password.focus();return;} write(keys.account,{username:remember.checked?account:'',remember:remember.checked}); enterWorkspace({name:account,mode:'account',service:connection.mode,organization:connection.organization}); },900); } const heading = (title,sub) => `

${title}

${sub?`

${sub}

`:''}
`; const cancel = (label='取消') => ``; function showDialog(html) { clearTimeout(modalTimer);modalBusy=false; dialogContent.innerHTML=html; if(!dialog.open)dialog.showModal(); } function closeDialog() {clearTimeout(modalTimer);modalBusy=false;dialog.close();} function rememberDraft() { const url=dialogContent.querySelector('#auth-enterprise-url'),org=dialogContent.querySelector('#auth-enterprise-org'); if(url){serviceDraft.url=url.value;serviceDraft.organization=org.value;} } function serviceDialog(intent='') { serviceIntent=intent;mode=intent==='sso'?'enterprise':connection.mode; serviceDraft={url:connection.url,organization:connection.organization}; renderService(); } function renderService() { showDialog(heading('连接设置','选择云端服务或企业部署入口。')+ `
`+ `
${mode==='enterprise'?``:`
云端服务

使用工作账号登录云桌面,无需填写企业服务地址。

`}

${cancel()}
`); } function saveService(event) { event.preventDefault(); rememberDraft(); let url=''; if(mode==='enterprise'){ const input=dialogContent.querySelector('#auth-enterprise-url');url=validEndpoint(input.value.trim()); if(!url){input.setAttribute('aria-invalid','true');dialogContent.querySelector('#auth-service-error').textContent='请输入有效的 HTTPS 企业服务地址';input.focus();return;} } connection=mode==='enterprise'?{mode,url,organization:serviceDraft.organization.trim()}:{mode:'cloud',url:'',organization:''}; const stored=write(keys.connection,connection);updateService(); if(serviceIntent==='sso'&&connection.mode==='enterprise'){ssoDialog();return;} closeDialog();message(stored?'连接设置已保存':'连接设置已应用,本次预览内有效');username.focus(); } function demoDialog() { showDialog(heading('体验账号','用于预览登录、桌面选择和连接设置流程。')+ `
工作账号
${DEMO.username}
密码
${DEMO.password}
这是交互原型的公开体验账号,未连接真实认证服务。请使用体验信息。
${cancel('返回')}
`); } function forgotDialog() { showDialog(heading('忘记密码','企业工作账号由管理员统一管理。')+ `
请联系越欣科技管理员重置密码

可提供工作账号与设备序列号 VDI-8F42A1,协助管理员定位。

原型体验账号无法修改密码,可重新查看体验信息。

${cancel('返回登录')}
`); } function ssoDialog() { if(connection.mode!=='enterprise'){serviceDialog('sso');return;} showDialog(heading('企业账号登录','通过企业统一身份进入云桌面。')+ `
企业服务
${escape(connection.url)}
${connection.organization?`
组织
${escape(connection.organization)}
`:''}
体验身份
越欣科技 · 体验用户

当前为统一身份登录预览,不会跳转或访问真实企业身份服务。

${cancel('取消登录')}
`); } function ssoContinue(button) { if(modalBusy)return; modalBusy=true;button.disabled=true;button.innerHTML='登录中…'; dialogContent.querySelector('#auth-sso-status').textContent='正在验证企业身份…'; modalTimer=setTimeout(()=>{closeDialog();enterWorkspace({name:'企业体验用户',mode:'sso',service:'enterprise',organization:connection.organization});},900); } function offlineDialog() { showDialog(heading('离线体验','先了解桌面列表和终端设置。')+ `
无需工作账号

可预览桌面、收藏和连接设置,设备与桌面信息为示例。配置仅保存在当前浏览器,不连接真实远程桌面。

${cancel()}
`); } form.addEventListener('submit',submitLogin); form.addEventListener('input',event=>{ if(event.target===username||event.target===password){event.target.removeAttribute('aria-invalid');if(!busy)message('');} }); remember.addEventListener('change',()=>{ if(!remember.checked)write(keys.account,{username:'',remember:false}); }); passwordToggle.addEventListener('click',()=>{ const reveal=password.type==='password';password.type=reveal?'text':'password';passwordToggle.setAttribute('aria-pressed',String(reveal));passwordToggle.setAttribute('aria-label',reveal?'隐藏密码':'显示密码'); }); serviceButton.addEventListener('click',()=>serviceDialog()); document.getElementById('auth-demo').addEventListener('click',demoDialog); document.getElementById('auth-forgot').addEventListener('click',forgotDialog); document.getElementById('auth-sso').addEventListener('click',ssoDialog); document.getElementById('auth-offline').addEventListener('click',offlineDialog); dialog.addEventListener('submit',event=>{if(event.target.id==='auth-service-form')saveService(event);}); dialog.addEventListener('input',event=>{event.target.removeAttribute('aria-invalid');const error=dialogContent.querySelector('#auth-service-error');if(error)error.textContent='';}); dialog.addEventListener('click',event=>{ const button=event.target.closest('[data-auth-action]'); if(!button||button.disabled)return; switch(button.dataset.authAction){ case 'close':closeDialog();break; case 'service-mode':rememberDraft();mode=button.dataset.mode;renderService();dialogContent.querySelector(`[data-mode="${mode}"]`).focus();break; case 'fill-demo':username.value=DEMO.username;password.value=DEMO.password;concealPassword();clearInvalid();message('已填入体验账号,点击登录继续');closeDialog();submit.focus();break; case 'demo':demoDialog();break; case 'sso-continue':ssoContinue(button);break; case 'offline-continue':closeDialog();enterWorkspace({name:'离线体验',mode:'offline',service:'offline',organization:'越欣科技'});break; } }); dialog.addEventListener('keydown',event=>{ const tab=event.target.closest('[role=tab]'); if(!tab||!['ArrowLeft','ArrowRight','Home','End'].includes(event.key))return; event.preventDefault();rememberDraft(); mode=event.key==='Home'?'cloud':event.key==='End'?'enterprise':mode==='cloud'?'enterprise':'cloud'; renderService();dialogContent.querySelector(`[data-mode="${mode}"]`).focus(); }); dialog.addEventListener('cancel',()=>{clearTimeout(modalTimer);modalBusy=false;}); dialog.addEventListener('close',()=>{clearTimeout(modalTimer);modalBusy=false;}); document.addEventListener('terminal:logout',()=>{ clearTimeout(loginTimer);clearTimeout(modalTimer);credentials=null;setBusy(false);password.value='';concealPassword();clearInvalid();restoreAccount();message('已退出登录');username.focus(); }); document.addEventListener('terminal:open-workspace',()=>{ clearTimeout(loginTimer);credentials=null;setBusy(false);password.value='';concealPassword();if(dialog.open)closeDialog(); }); restoreAccount();updateService(); })();