Ports the subscription/general partial — four collapse panels covering
the master enable switches, presentation/template fields, certs, and
update interval.
- Sub path goes through a strip-on-input + normalize-on-blur computed:
legacy stripped `:` and `*` and ensured the value starts and ends
with a single `/` — same here.
- Both `subEnableRouting` and the announce/profile/title/support URLs
are bound directly on AllSetting.
- The "Subscription URI override" placeholder mirrors the legacy
pattern for the manual full-URL form.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ports the panel/telegram partial: bot enable/token/chatId/lang in the
General panel, schedule/backup/login/CPU-threshold in Notifications,
and proxy/API-server overrides in the third panel. All bindings live
on the shared AllSetting reactive — no fetch/save logic in this tab.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ports the panel/security partial: change-credentials form and 2FA
toggle. The 2FA modal is a new shared component since enabling 2FA,
disabling 2FA, and changing credentials all funnel through it with
slightly different copy.
- TwoFactorModal.vue: 'set' flow renders a QR code + manual key + a
6-digit verifier; 'confirm' flow renders just the verifier. The
parent passes a confirm(success) callback that fires only when the
entered code matches the live TOTP value (otpauth lib).
- SecurityTab.vue: holds the local user form (oldUsername/oldPassword/
new*), POSTs /panel/setting/updateUser, and on success force-redirects
to logout. When 2FA is on, the credentials change goes through the
confirm-modal first.
- toggleTwoFactor leaves the switch read-only (the v-bound :checked
matches AllSetting) and only flips after the modal succeeds, so
cancelling out leaves state unchanged.
- Adds otpauth ^9.5.1 dep (qrious was already present).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ports the panel/general partial (the largest single tab) — six
collapse panels: General, Notifications, Certificates, External
traffic webhook, Date and time, LDAP.
- GeneralTab.vue receives the reactive AllSetting via props and binds
fields directly with v-model:value; SettingsPage stays the sole
fetch/save owner.
- remarkModel/remarkSeparator surfaced as computed v-models that
read+write the underlying single-string field (legacy stores them
packed as <separator><orderedKeys>, e.g. "-ieo").
- LDAP inbound-tags select binds to a CSV ↔ array computed; inbound
options come from /panel/api/inbounds/list on mount.
- Language select stays cookie-based via LanguageManager and reloads
on change — same UX as legacy.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the settings entry as a new Vite multi-page input. Lays down the
shared page chrome (sidebar, save bar, restart, security alert) and the
AllSetting fetch/dirty-poll lifecycle so 5d-ii through 5d-vi can drop
in tab partials without re-implementing it.
- settings.html + src/settings.js: third Vite entry; mounts SettingsPage.
- SettingsPage.vue: page chrome with the legacy two-button save/restart
bar, conf-alerts banner, and 5 a-tabs (4 always-visible + the formats
tab gated on subJsonEnable || subClashEnable). Each tab body is an
a-empty placeholder until 5d-ii…vi fill them in.
- useAllSetting.js composable: POST /panel/setting/all on mount, mirrors
the legacy 1s busy-loop dirty check via setInterval, and exposes
fetchAll/saveAll. saveDisabled flips off as soon as the user diverges
from the server snapshot.
- restartPanel rebuilds the URL (host/port/scheme/base path) from the
saved settings so users land on the new endpoint after a port or
cert change.
- models/setting.js: adopts the @/utils alias and a leading file-level
doc — semantics unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>