feat: secure pickup flow and add deployment
Release / deploy (push) Successful in 4m1s

This commit is contained in:
loveuer
2026-09-10 02:44:35 -07:00
parent fa4357a3f2
commit 8ca8341d7c
8 changed files with 276 additions and 34 deletions
+18 -7
View File
@@ -31,13 +31,23 @@ function Login() {
const [error, setError] = useState('')
const [busy, setBusy] = useState(false)
const [pickup, setPickup] = useState({ hash: '', code: '' })
const retrieve = (preview = false) => {
const [pickupError, setPickupError] = useState('')
const [pickupBusy, setPickupBusy] = useState(false)
const retrieve = async () => {
const hash = pickup.hash.trim()
if (!hash) return
setPickupError('')
if (hash.length !== 8) return setPickupError('请输入 8 位文件码')
if (pickup.code && pickup.code.length !== 6) return setPickupError('取件码必须是 6 位数字')
const query = new URLSearchParams()
if (pickup.code) query.set('code', pickup.code)
if (preview) query.set('preview', 'true')
window.open(`/uf/${encodeURIComponent(hash)}${query.size ? `?${query}` : ''}`, '_blank')
setPickupBusy(true)
try {
await api(`/api/pickup/${encodeURIComponent(hash)}${query.size ? `?${query}` : ''}`)
const link = document.createElement('a')
link.href = `/uf/${encodeURIComponent(hash)}${query.size ? `?${query}` : ''}`
document.body.appendChild(link); link.click(); link.remove()
} catch (error) { setPickupError(error.message) }
finally { setPickupBusy(false) }
}
const submit = async (event) => {
event.preventDefault(); setBusy(true); setError('')
@@ -54,10 +64,11 @@ function Login() {
<div className="card mt-10 max-w-lg p-5">
<div className="mb-3 flex items-center gap-2 text-sm font-semibold"><ArrowDownToLine size={17} className="text-leaf" />收到分享?直接取件</div>
<div className="grid gap-2 sm:grid-cols-[1fr_130px_auto]">
<input className="field" maxLength={8} placeholder="8 位文件码" value={pickup.hash} onChange={(e) => setPickup({ ...pickup, hash: e.target.value })} />
<input className="field" inputMode="numeric" maxLength={6} placeholder="取件码(可选)" value={pickup.code} onChange={(e) => setPickup({ ...pickup, code: e.target.value.replace(/\D/g, '') })} />
<button className="btn-secondary" onClick={() => retrieve(false)}>下载</button>
<input className="field" maxLength={8} placeholder="8 位文件码" value={pickup.hash} onChange={(e) => { setPickup({ ...pickup, hash: e.target.value }); setPickupError('') }} />
<input className="field" inputMode="numeric" maxLength={6} placeholder="取件码(可选)" value={pickup.code} onChange={(e) => { setPickup({ ...pickup, code: e.target.value.replace(/\D/g, '') }); setPickupError('') }} />
<button className="btn-secondary" disabled={pickupBusy} onClick={retrieve}>{pickupBusy ? <LoaderCircle className="animate-spin" size={17} /> : '下载'}</button>
</div>
{pickupError && <p className="mt-2 text-sm text-red-600">{pickupError}</p>}
</div>
</section>
<section className="mx-auto w-full max-w-md py-8 lg:justify-self-end">