mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix: settings save button and multiple UI bugs
- Fix duplicate :min attributes on a-input-number (webPort, subPort, tgCpu) - Fix mismatched closing tags (a-input/a-switch instead of a-input-number) - Fix twoFactorEnable toggle receiving MouseEvent instead of boolean - Fix noise input handlers referencing undefined global `event` - Add error handling to settings change detection polling loop - Bump version to v1.5.4-beta
This commit is contained in:
parent
5ec81ea3d0
commit
582037ae70
8 changed files with 62 additions and 12 deletions
|
|
@ -1 +1 @@
|
|||
v1.5.3-beta
|
||||
v1.5.4-beta
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# 2026-04-24 Fix Settings Save Button and UI Bugs
|
||||
|
||||
## Problem
|
||||
Settings page save button would not enable when user changed settings.
|
||||
|
||||
## Root Cause Analysis
|
||||
Systematic debugging found multiple UI bugs affecting the settings page:
|
||||
|
||||
1. **Duplicate `:min` attributes on `a-input-number`** (3 locations)
|
||||
- `general.html:42` — webPort had `:min="1" :min="65535"` (second should be `:max`)
|
||||
- `subscription/general.html:43` — subPort had same issue
|
||||
- `telegram.html:64` — tgCpu had `:min="0" :min="100"` (second should be `:max`)
|
||||
|
||||
2. **Mismatched closing tags**
|
||||
- `general.html:42` — `<a-input-number>` closed with `</a-input>`
|
||||
- `telegram.html:64` — `<a-input-number>` closed with `</a-switch>`
|
||||
|
||||
3. **twoFactorEnable toggle broken** (`security.html:39`)
|
||||
- Used `@click="toggleTwoFactor" :checked="..."` instead of proper event handling
|
||||
- `@click` passes MouseEvent as first arg, not the boolean toggle value
|
||||
- Method expected boolean but received Event → always truthy → always triggered enable flow
|
||||
|
||||
4. **Noise input handlers referenced undefined `event`** (`json.html:91,99`)
|
||||
- `(value) => updateNoisePacket(index, event.target.value)` — `event` is not defined
|
||||
- Arrow function parameter named `value` but code accessed global `event`
|
||||
|
||||
5. **Polling loop had no error handling** (`settings.html:653-656`)
|
||||
- Any error in the `while(true)` loop would silently stop change detection
|
||||
|
||||
## Changes
|
||||
- Fixed `:min`/`:max` attributes on all `a-input-number` components
|
||||
- Fixed closing tags to match opening tags
|
||||
- Changed twoFactorEnable to use `@click.prevent="toggleTwoFactor(!allSetting.twoFactorEnable)"`
|
||||
- Updated `toggleTwoFactor` method to only set `twoFactorEnable` on success
|
||||
- Fixed noise input handlers to use `(e) => ... e.target.value`
|
||||
- Added try/catch around polling loop comparison
|
||||
|
||||
## Files Modified
|
||||
- `web/html/settings/panel/general.html` — webPort input fix
|
||||
- `web/html/settings/panel/subscription/general.html` — subPort input fix
|
||||
- `web/html/settings/panel/telegram.html` — tgCpu input fix
|
||||
- `web/html/settings/panel/security.html` — twoFactorEnable toggle fix
|
||||
- `web/html/settings/panel/subscription/json.html` — noise input handler fix
|
||||
- `web/html/settings.html` — toggleTwoFactor method + polling error handling
|
||||
|
||||
## Verification
|
||||
- Visual inspection of all modified templates
|
||||
- Confirmed `ObjectUtil.equals()` shallow comparison works correctly with Vue 2 reactivity
|
||||
- Confirmed `AllSetting` class properties match Go struct fields
|
||||
|
|
@ -396,11 +396,9 @@
|
|||
confirm: (success) => {
|
||||
if (success) {
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
|
||||
|
||||
this.allSetting.twoFactorToken = newTwoFactorToken
|
||||
this.allSetting.twoFactorEnable = true
|
||||
}
|
||||
|
||||
this.allSetting.twoFactorEnable = success
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
|
@ -412,7 +410,6 @@
|
|||
confirm: (success) => {
|
||||
if (success) {
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
|
||||
|
||||
this.allSetting.twoFactorEnable = false
|
||||
this.allSetting.twoFactorToken = ""
|
||||
}
|
||||
|
|
@ -655,7 +652,11 @@
|
|||
}
|
||||
while (true) {
|
||||
await PromiseUtil.sleep(1000);
|
||||
this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting);
|
||||
try {
|
||||
this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting);
|
||||
} catch (e) {
|
||||
console.error('Settings change detection error:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
<template #title>{{ i18n "pages.settings.panelPort"}}</template>
|
||||
<template #description>{{ i18n "pages.settings.panelPortDesc"}}</template>
|
||||
<template #control>
|
||||
<a-input-number :min="1" :min="65535" v-model="allSetting.webPort" :style="{ width: '100%' }"></a-input>
|
||||
<a-input-number :min="1" :max="65535" v-model="allSetting.webPort" :style="{ width: '100%' }"></a-input-number>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
<a-setting-list-item paddings="small">
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
<template #title>{{ i18n "pages.settings.security.twoFactorEnable" }}</template>
|
||||
<template #description>{{ i18n "pages.settings.security.twoFactorEnableDesc" }}</template>
|
||||
<template #control>
|
||||
<a-switch @click="toggleTwoFactor" :checked="allSetting.twoFactorEnable"></a-switch>
|
||||
<a-switch :checked="allSetting.twoFactorEnable" @click.prevent="toggleTwoFactor(!allSetting.twoFactorEnable)"></a-switch>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
</a-collapse-panel>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
<template #title>{{ i18n "pages.settings.subPort"}}</template>
|
||||
<template #description>{{ i18n "pages.settings.subPortDesc"}}</template>
|
||||
<template #control>
|
||||
<a-input-number v-model="allSetting.subPort" :min="1" :min="65535"
|
||||
<a-input-number v-model="allSetting.subPort" :min="1" :max="65535"
|
||||
:style="{ width: '100%' }"></a-input-number>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
<template #title>Packet</template>
|
||||
<template #control>
|
||||
<a-input type="text" :value="noise.packet"
|
||||
@input="(value) => updateNoisePacket(index, event.target.value)"
|
||||
@input="(e) => updateNoisePacket(index, e.target.value)"
|
||||
placeholder="5-10"></a-input>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<template #title>Delay (ms)</template>
|
||||
<template #control>
|
||||
<a-input type="text" :value="noise.delay"
|
||||
@input="(value) => updateNoiseDelay(index, event.target.value)"
|
||||
@input="(e) => updateNoiseDelay(index, e.target.value)"
|
||||
placeholder="10-20"></a-input>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
<template #title>{{ i18n "pages.settings.tgNotifyCpu" }}</template>
|
||||
<template #description>{{ i18n "pages.settings.tgNotifyCpuDesc" }}</template>
|
||||
<template #control>
|
||||
<a-input-number :min="0" :min="100" v-model="allSetting.tgCpu" :style="{ width: '100%' }"></a-switch>
|
||||
<a-input-number :min="0" :max="100" v-model="allSetting.tgCpu" :style="{ width: '100%' }"></a-input-number>
|
||||
</template>
|
||||
</a-setting-list-item>
|
||||
</a-collapse-panel>
|
||||
|
|
|
|||
Loading…
Reference in a new issue