mirror of
https://github.com/VirtualHotBar/NetMount.git
synced 2026-06-09 08:02:20 +08:00
fix(openlist): 增加登录超时处理和重试机制
This commit is contained in:
@@ -44,7 +44,13 @@ async function appStart(setStartStr: SetStartStrFn) {
|
||||
if (appStarting) { return }//避免重新执行
|
||||
appStarting = true
|
||||
|
||||
await init(setStartStr)//初始化功能
|
||||
try {
|
||||
await init(setStartStr)//初始化功能
|
||||
} catch (e) {
|
||||
appStarting = false
|
||||
console.error('App init failed:', e)
|
||||
return
|
||||
}
|
||||
|
||||
reactRoot.render(<React.StrictMode>
|
||||
<BrowserRouter future={{ v7_relativeSplatPath: true }}>
|
||||
|
||||
@@ -189,7 +189,7 @@ export default function AddMount_page() {
|
||||
<div>
|
||||
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '2rem', marginLeft: '1.8rem' }}>{!isEditMode ? t('add_mount') : t('edit_mount')}</h2>
|
||||
|
||||
|
||||
{/* 基础选项 - 始终显示 */}
|
||||
<div style={{ marginBottom: showAllOptions ? '1rem' : '0' }}>
|
||||
<FormItem label={t('storage')}>
|
||||
@@ -271,24 +271,23 @@ export default function AddMount_page() {
|
||||
<Button type={cacheMode === 'minimal' ? 'primary' : 'secondary'} onClick={() => applyCachePreset('minimal')}>{t('preset_low_disk')}</Button>
|
||||
<Button type={cacheMode === 'off' ? 'primary' : 'secondary'} onClick={() => applyCachePreset('off')}>{t('preset_compatibility')}</Button>
|
||||
</Space>
|
||||
<Alert
|
||||
style={{ marginTop: '0.5rem' }}
|
||||
type={cacheMode === 'full' ? 'warning' : 'info'}
|
||||
content={
|
||||
cacheMode === 'full'
|
||||
? t('cache_mode_tip_full')
|
||||
: cacheMode === 'off'
|
||||
? t('cache_mode_tip_off')
|
||||
: cacheMode === 'minimal'
|
||||
? t('cache_mode_tip_minimal')
|
||||
: t('cache_mode_tip_writes')
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
</>
|
||||
}
|
||||
{!showAllOptions && (
|
||||
<Alert
|
||||
style={{ marginTop: '0.5rem' }}
|
||||
type={cacheMode === 'full' ? 'warning' : 'info'}
|
||||
content={
|
||||
cacheMode === 'full'
|
||||
? t('cache_mode_tip_full')
|
||||
: cacheMode === 'off'
|
||||
? t('cache_mode_tip_off')
|
||||
: cacheMode === 'minimal'
|
||||
? t('cache_mode_tip_minimal')
|
||||
: t('cache_mode_tip_writes')
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{showAllOptions && isMacOS && (
|
||||
<FormItem label={t('mount_backend')}>
|
||||
<Select
|
||||
@@ -333,7 +332,7 @@ export default function AddMount_page() {
|
||||
<Button disabled={!storageName || !mountPath} onClick={async () => {
|
||||
// 编辑模式下获取原始路径
|
||||
const originalMountPath = isEditMode ? getURLSearchParam('mountPath') : '';
|
||||
|
||||
|
||||
if (!isEditMode && getMountStorage(mountPath)) {
|
||||
Notification.error({
|
||||
title: t('error'),
|
||||
@@ -354,13 +353,13 @@ export default function AddMount_page() {
|
||||
}
|
||||
|
||||
mountPathTemp = formatPath(mountPathTemp, isWindows)
|
||||
|
||||
|
||||
if (isEditMode) {
|
||||
await editMountStorage({
|
||||
storageName: storageName!,
|
||||
mountPath: mountPathTemp,
|
||||
parameters: parameters,
|
||||
autoMount: autoMount
|
||||
await editMountStorage({
|
||||
storageName: storageName!,
|
||||
mountPath: mountPathTemp,
|
||||
parameters: parameters,
|
||||
autoMount: autoMount
|
||||
}, originalMountPath)
|
||||
} else {
|
||||
await addMountStorage(storageName!, mountPathTemp, parameters, autoMount)
|
||||
|
||||
@@ -21,14 +21,30 @@ type OpenlistLoginResponse = {
|
||||
async function openlist_login(username: string, password: string): Promise<string> {
|
||||
const url = openlistInfo.endpoint.url + '/api/auth/login'
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 8000)
|
||||
const timeoutMs = 15_000
|
||||
const timeoutId = setTimeout(
|
||||
() => controller.abort(new DOMException(`OpenList login timeout after ${timeoutMs}ms`, 'TimeoutError')),
|
||||
timeoutMs
|
||||
)
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
signal: controller.signal
|
||||
})
|
||||
let res: Response
|
||||
try {
|
||||
res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
signal: controller.signal
|
||||
})
|
||||
} catch (e) {
|
||||
if (controller.signal.aborted) {
|
||||
const reason = controller.signal.reason
|
||||
const reasonMessage = reason instanceof Error
|
||||
? reason.message
|
||||
: (typeof reason === 'string' ? reason : 'request aborted')
|
||||
throw new Error(`OpenList login timed out: ${reasonMessage}`)
|
||||
}
|
||||
throw e
|
||||
}
|
||||
|
||||
const text = await res.text().catch(() => '')
|
||||
let json: OpenlistLoginResponse | undefined
|
||||
@@ -61,9 +77,23 @@ async function getOpenlistToken(): Promise<string> {
|
||||
}
|
||||
const username = nmConfig.framework.openlist.user
|
||||
const password = nmConfig.framework.openlist.password
|
||||
const token = await openlist_login(username, password)
|
||||
openlistInfo.endpoint.auth.token = token
|
||||
return token
|
||||
|
||||
const maxAttempts = 3
|
||||
let lastError: unknown
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
try {
|
||||
const token = await openlist_login(username, password)
|
||||
openlistInfo.endpoint.auth.token = token
|
||||
return token
|
||||
} catch (e) {
|
||||
lastError = e
|
||||
if (attempt < maxAttempts) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`OpenList login failed after ${maxAttempts} attempts: ${String(lastError)}`)
|
||||
}
|
||||
|
||||
async function setOpenlistPass(pass: string) {
|
||||
|
||||
Reference in New Issue
Block a user