Skip to content

Commit 96ff7e4

Browse files
committed
fix(openlist): 增加登录超时处理和重试机制
1 parent 2988382 commit 96ff7e4

3 files changed

Lines changed: 69 additions & 34 deletions

File tree

src/main.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ async function appStart(setStartStr: SetStartStrFn) {
4444
if (appStarting) { return }//避免重新执行
4545
appStarting = true
4646

47-
await init(setStartStr)//初始化功能
47+
try {
48+
await init(setStartStr)//初始化功能
49+
} catch (e) {
50+
appStarting = false
51+
console.error('App init failed:', e)
52+
return
53+
}
4854

4955
reactRoot.render(<React.StrictMode>
5056
<BrowserRouter future={{ v7_relativeSplatPath: true }}>

src/page/mount/add.tsx

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export default function AddMount_page() {
189189
<div>
190190

191191
<h2 style={{ fontSize: '1.5rem', marginBottom: '2rem', marginLeft: '1.8rem' }}>{!isEditMode ? t('add_mount') : t('edit_mount')}</h2>
192-
192+
193193
{/* 基础选项 - 始终显示 */}
194194
<div style={{ marginBottom: showAllOptions ? '1rem' : '0' }}>
195195
<FormItem label={t('storage')}>
@@ -271,24 +271,23 @@ export default function AddMount_page() {
271271
<Button type={cacheMode === 'minimal' ? 'primary' : 'secondary'} onClick={() => applyCachePreset('minimal')}>{t('preset_low_disk')}</Button>
272272
<Button type={cacheMode === 'off' ? 'primary' : 'secondary'} onClick={() => applyCachePreset('off')}>{t('preset_compatibility')}</Button>
273273
</Space>
274+
<Alert
275+
style={{ marginTop: '0.5rem' }}
276+
type={cacheMode === 'full' ? 'warning' : 'info'}
277+
content={
278+
cacheMode === 'full'
279+
? t('cache_mode_tip_full')
280+
: cacheMode === 'off'
281+
? t('cache_mode_tip_off')
282+
: cacheMode === 'minimal'
283+
? t('cache_mode_tip_minimal')
284+
: t('cache_mode_tip_writes')
285+
}
286+
/>
274287
</FormItem>
288+
275289
</>
276290
}
277-
{!showAllOptions && (
278-
<Alert
279-
style={{ marginTop: '0.5rem' }}
280-
type={cacheMode === 'full' ? 'warning' : 'info'}
281-
content={
282-
cacheMode === 'full'
283-
? t('cache_mode_tip_full')
284-
: cacheMode === 'off'
285-
? t('cache_mode_tip_off')
286-
: cacheMode === 'minimal'
287-
? t('cache_mode_tip_minimal')
288-
: t('cache_mode_tip_writes')
289-
}
290-
/>
291-
)}
292291
{showAllOptions && isMacOS && (
293292
<FormItem label={t('mount_backend')}>
294293
<Select
@@ -333,7 +332,7 @@ export default function AddMount_page() {
333332
<Button disabled={!storageName || !mountPath} onClick={async () => {
334333
// 编辑模式下获取原始路径
335334
const originalMountPath = isEditMode ? getURLSearchParam('mountPath') : '';
336-
335+
337336
if (!isEditMode && getMountStorage(mountPath)) {
338337
Notification.error({
339338
title: t('error'),
@@ -354,13 +353,13 @@ export default function AddMount_page() {
354353
}
355354

356355
mountPathTemp = formatPath(mountPathTemp, isWindows)
357-
356+
358357
if (isEditMode) {
359-
await editMountStorage({
360-
storageName: storageName!,
361-
mountPath: mountPathTemp,
362-
parameters: parameters,
363-
autoMount: autoMount
358+
await editMountStorage({
359+
storageName: storageName!,
360+
mountPath: mountPathTemp,
361+
parameters: parameters,
362+
autoMount: autoMount
364363
}, originalMountPath)
365364
} else {
366365
await addMountStorage(storageName!, mountPathTemp, parameters, autoMount)

src/utils/openlist/openlist.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,30 @@ type OpenlistLoginResponse = {
2121
async function openlist_login(username: string, password: string): Promise<string> {
2222
const url = openlistInfo.endpoint.url + '/api/auth/login'
2323
const controller = new AbortController()
24-
const timeoutId = setTimeout(() => controller.abort(), 8000)
24+
const timeoutMs = 15_000
25+
const timeoutId = setTimeout(
26+
() => controller.abort(new DOMException(`OpenList login timeout after ${timeoutMs}ms`, 'TimeoutError')),
27+
timeoutMs
28+
)
2529
try {
26-
const res = await fetch(url, {
27-
method: 'POST',
28-
headers: { 'Content-Type': 'application/json' },
29-
body: JSON.stringify({ username, password }),
30-
signal: controller.signal
31-
})
30+
let res: Response
31+
try {
32+
res = await fetch(url, {
33+
method: 'POST',
34+
headers: { 'Content-Type': 'application/json' },
35+
body: JSON.stringify({ username, password }),
36+
signal: controller.signal
37+
})
38+
} catch (e) {
39+
if (controller.signal.aborted) {
40+
const reason = controller.signal.reason
41+
const reasonMessage = reason instanceof Error
42+
? reason.message
43+
: (typeof reason === 'string' ? reason : 'request aborted')
44+
throw new Error(`OpenList login timed out: ${reasonMessage}`)
45+
}
46+
throw e
47+
}
3248

3349
const text = await res.text().catch(() => '')
3450
let json: OpenlistLoginResponse | undefined
@@ -61,9 +77,23 @@ async function getOpenlistToken(): Promise<string> {
6177
}
6278
const username = nmConfig.framework.openlist.user
6379
const password = nmConfig.framework.openlist.password
64-
const token = await openlist_login(username, password)
65-
openlistInfo.endpoint.auth.token = token
66-
return token
80+
81+
const maxAttempts = 3
82+
let lastError: unknown
83+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
84+
try {
85+
const token = await openlist_login(username, password)
86+
openlistInfo.endpoint.auth.token = token
87+
return token
88+
} catch (e) {
89+
lastError = e
90+
if (attempt < maxAttempts) {
91+
await new Promise(resolve => setTimeout(resolve, 500))
92+
}
93+
}
94+
}
95+
96+
throw new Error(`OpenList login failed after ${maxAttempts} attempts: ${String(lastError)}`)
6797
}
6898

6999
async function setOpenlistPass(pass: string) {

0 commit comments

Comments
 (0)