13 lines
2.6 KiB
TypeScript
13 lines
2.6 KiB
TypeScript
'use client'
|
||
import {useEffect,useState} from 'react'
|
||
import BrandLogo from '@/components/BrandLogo'
|
||
import {DEFAULT_LOGIN_LOGO_URL} from '@/lib/brand-assets'
|
||
import './authorize.css'
|
||
export default function AuthorizeClient({account,request}:{account:{id:string;name:string};request:Record<string,string>}){
|
||
const [busy,setBusy]=useState(false),[error,setError]=useState(''),[devices,setDevices]=useState<{id:string;deviceName:string;createdAt:string}[]>([])
|
||
useEffect(()=>{void fetch('/api/desktop/devices',{cache:'no-store'}).then(r=>r.json()).then(r=>setDevices(r.devices||[])).catch(()=>{})},[])
|
||
async function approve(){setBusy(true);setError('');try{const response=await fetch('/api/desktop/authorize',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(request)});const value=await response.json();if(!response.ok)throw new Error(value.error);window.location.assign(value.redirect)}catch(error){setError(error instanceof Error?error.message:'授权未完成,请重试');setBusy(false)}}
|
||
function cancel(){const url=new URL(request.redirect_uri);url.searchParams.set('error','access_denied');url.searchParams.set('state',request.state);window.location.assign(url)}
|
||
return <main className="client-authorize"><div className="authorize-brand"><BrandLogo src={DEFAULT_LOGIN_LOGO_URL} fallbackSrc={DEFAULT_LOGIN_LOGO_URL} alt="由壹点素材库" width={44} height={44} className="authorize-logo"/><span>由壹点 · 素材库</span></div><h1>授权详情页工作台</h1><p className="authorize-account">使用 <strong>{account.name}</strong> 的账户继续</p><ul><li>查看、继续处理本人项目</li><li>同步草稿、对话和项目文件</li><li>读取管理员开放的模型列表</li></ul><p className="authorize-note">授权只用于当前客户端。你可以随时撤销,客户端不会获取网页登录密码。</p>{error&&<p role="alert">{error}</p>}<div className="authorize-actions"><button disabled={busy} onClick={cancel}>取消</button><button disabled={busy} className="authorize-primary" onClick={()=>void approve()}>{busy?'正在授权…':'授权并返回客户端'}</button></div>{devices.length>0&&<details><summary>已授权的客户端</summary>{devices.map(device=><div className="authorize-device" key={device.id}><span>{device.deviceName}<small>{new Date(device.createdAt).toLocaleDateString('zh-CN')}</small></span><button onClick={async()=>{const r=await fetch('/api/desktop/devices/'+encodeURIComponent(device.id),{method:'DELETE'});if(r.ok)setDevices(v=>v.filter(d=>d.id!==device.id));else setError('撤销未完成,请重试')}}>撤销授权</button></div>)}</details>}</main>
|
||
}
|