fix: 修复了确认对话框操作的变量在点击时被重置的bug

This commit is contained in:
Fridayssheep
2026-02-11 15:16:42 +08:00
parent 21bea797e4
commit ba6ec56cee
6 changed files with 36 additions and 17 deletions

View File

@@ -258,6 +258,7 @@ impl AtxKeyExecutor {
/// Pulse Serial relay /// Pulse Serial relay
async fn pulse_serial(&self, duration: Duration) -> Result<()> { async fn pulse_serial(&self, duration: Duration) -> Result<()> {
info!("Pulse serial relay on {} pin {}", self.config.device, self.config.pin);
// Turn relay on // Turn relay on
self.send_serial_relay_command(true)?; self.send_serial_relay_command(true)?;
@@ -272,13 +273,19 @@ impl AtxKeyExecutor {
/// Send Serial relay command using cached handle /// Send Serial relay command using cached handle
fn send_serial_relay_command(&self, on: bool) -> Result<()> { fn send_serial_relay_command(&self, on: bool) -> Result<()> {
// user config pin should be 1 for most LCUS modules (A0 01 01 A2)
// if user set 0, it will send A0 00 01 A1 which might not work
let channel = self.config.pin as u8; let channel = self.config.pin as u8;
// LCUS-Type Protocol // LCUS-Type Protocol
// Frame: [StopByte(A0), Channel, State, Checksum]
// Checksum = A0 + channel + state // Checksum = A0 + channel + state
let state = if on { 1 } else { 0 }; let state = if on { 1 } else { 0 };
let checksum = 0xA0u8.wrapping_add(channel).wrapping_add(state); let checksum = 0xA0u8.wrapping_add(channel).wrapping_add(state);
// Example for Channel 1:
// ON: A0 01 01 A2
// OFF: A0 01 00 A1
let cmd = [0xA0, channel, state, checksum]; let cmd = [0xA0, channel, state, checksum];
let mut guard = self.serial_handle.lock().unwrap(); let mut guard = self.serial_handle.lock().unwrap();

View File

@@ -33,7 +33,7 @@ pub enum AtxDriverType {
Gpio, Gpio,
/// USB HID relay module /// USB HID relay module
UsbRelay, UsbRelay,
/// Serial/COM port relay (LCUS type) /// Serial/COM port relay (taobao LCUS type)
Serial, Serial,
/// Disabled / Not configured /// Disabled / Not configured
None, None,

View File

@@ -2641,6 +2641,7 @@ pub async fn atx_power(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(req): Json<AtxPowerControlRequest>, Json(req): Json<AtxPowerControlRequest>,
) -> Result<Json<LoginResponse>> { ) -> Result<Json<LoginResponse>> {
tracing::info!("Received ATX power request: action={}", req.action);
let atx_guard = state.atx.read().await; let atx_guard = state.atx.read().await;
let atx = atx_guard let atx = atx_guard
.as_ref() .as_ref()

View File

@@ -33,7 +33,9 @@ const activeTab = ref('atx')
// ATX state // ATX state
const powerState = ref<'on' | 'off' | 'unknown'>('unknown') const powerState = ref<'on' | 'off' | 'unknown'>('unknown')
const confirmAction = ref<'short' | 'long' | 'reset' | null>(null) // Decouple action data from dialog visibility to prevent race conditions
const pendingAction = ref<'short' | 'long' | 'reset' | null>(null)
const confirmDialogOpen = ref(false)
// WOL state // WOL state
const wolMacAddress = ref('') const wolMacAddress = ref('')
@@ -56,15 +58,21 @@ const powerStateText = computed(() => {
} }
}) })
function requestAction(action: 'short' | 'long' | 'reset') {
pendingAction.value = action
confirmDialogOpen.value = true
}
function handleAction() { function handleAction() {
if (confirmAction.value === 'short') emit('powerShort') console.log('[AtxPopover] Confirming action:', pendingAction.value)
else if (confirmAction.value === 'long') emit('powerLong') if (pendingAction.value === 'short') emit('powerShort')
else if (confirmAction.value === 'reset') emit('reset') else if (pendingAction.value === 'long') emit('powerLong')
confirmAction.value = null else if (pendingAction.value === 'reset') emit('reset')
confirmDialogOpen.value = false
} }
const confirmTitle = computed(() => { const confirmTitle = computed(() => {
switch (confirmAction.value) { switch (pendingAction.value) {
case 'short': return t('atx.confirmShortTitle') case 'short': return t('atx.confirmShortTitle')
case 'long': return t('atx.confirmLongTitle') case 'long': return t('atx.confirmLongTitle')
case 'reset': return t('atx.confirmResetTitle') case 'reset': return t('atx.confirmResetTitle')
@@ -73,14 +81,13 @@ const confirmTitle = computed(() => {
}) })
const confirmDescription = computed(() => { const confirmDescription = computed(() => {
switch (confirmAction.value) { switch (pendingAction.value) {
case 'short': return t('atx.confirmShortDesc') case 'short': return t('atx.confirmShortDesc')
case 'long': return t('atx.confirmLongDesc') case 'long': return t('atx.confirmLongDesc')
case 'reset': return t('atx.confirmResetDesc') case 'reset': return t('atx.confirmResetDesc')
default: return '' default: return ''
} }
}) })
// MAC address validation // MAC address validation
const isValidMac = computed(() => { const isValidMac = computed(() => {
const mac = wolMacAddress.value.trim() const mac = wolMacAddress.value.trim()
@@ -169,7 +176,7 @@ if (savedHistory) {
variant="outline" variant="outline"
size="sm" size="sm"
class="w-full justify-start gap-2 h-8 text-xs" class="w-full justify-start gap-2 h-8 text-xs"
@click="confirmAction = 'short'" @click="requestAction('short')"
> >
<Power class="h-3.5 w-3.5" /> <Power class="h-3.5 w-3.5" />
{{ t('atx.shortPress') }} {{ t('atx.shortPress') }}
@@ -179,7 +186,7 @@ if (savedHistory) {
variant="outline" variant="outline"
size="sm" size="sm"
class="w-full justify-start gap-2 h-8 text-xs text-orange-600 hover:text-orange-700 hover:bg-orange-50 dark:hover:bg-orange-950" class="w-full justify-start gap-2 h-8 text-xs text-orange-600 hover:text-orange-700 hover:bg-orange-50 dark:hover:bg-orange-950"
@click="confirmAction = 'long'" @click="requestAction('long')"
> >
<CircleDot class="h-3.5 w-3.5" /> <CircleDot class="h-3.5 w-3.5" />
{{ t('atx.longPress') }} {{ t('atx.longPress') }}
@@ -189,7 +196,7 @@ if (savedHistory) {
variant="outline" variant="outline"
size="sm" size="sm"
class="w-full justify-start gap-2 h-8 text-xs text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950" class="w-full justify-start gap-2 h-8 text-xs text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950"
@click="confirmAction = 'reset'" @click="requestAction('reset')"
> >
<RotateCcw class="h-3.5 w-3.5" /> <RotateCcw class="h-3.5 w-3.5" />
{{ t('atx.reset') }} {{ t('atx.reset') }}
@@ -247,7 +254,7 @@ if (savedHistory) {
</div> </div>
<!-- Confirm Dialog --> <!-- Confirm Dialog -->
<AlertDialog :open="!!confirmAction" @update:open="confirmAction = null"> <AlertDialog :open="confirmDialogOpen" @update:open="confirmDialogOpen = $event">
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle>{{ confirmTitle }}</AlertDialogTitle> <AlertDialogTitle>{{ confirmTitle }}</AlertDialogTitle>

View File

@@ -1310,15 +1310,19 @@ function openTerminalInNewTab() {
// ATX actions // ATX actions
async function handlePowerShort() { async function handlePowerShort() {
console.log('[ConsoleView] Handling power short press')
try { try {
await atxApi.power('short') const res = await atxApi.power('short')
console.log('[ConsoleView] Power short API result:', res)
await systemStore.fetchAtxState() await systemStore.fetchAtxState()
} catch { } catch (e) {
console.error('[ConsoleView] Power short API failed:', e)
// ATX action failed // ATX action failed
} }
} }
async function handlePowerLong() { async function handlePowerLong() {
console.log('[ConsoleView] Handling power long press')
try { try {
await atxApi.power('long') await atxApi.power('long')
await systemStore.fetchAtxState() await systemStore.fetchAtxState()

View File

@@ -930,6 +930,7 @@ async function saveAtxConfig() {
driver: atxConfig.value.power.driver, driver: atxConfig.value.power.driver,
device: atxConfig.value.power.device || undefined, device: atxConfig.value.power.device || undefined,
pin: atxConfig.value.power.pin, pin: atxConfig.value.power.pin,
active_level: atxConfig.value.power.active_level,
baud_rate: atxConfig.value.power.baud_rate, baud_rate: atxConfig.value.power.baud_rate,
}, },
reset: { reset: {
@@ -937,8 +938,7 @@ async function saveAtxConfig() {
device: atxConfig.value.reset.device || undefined, device: atxConfig.value.reset.device || undefined,
pin: atxConfig.value.reset.pin, pin: atxConfig.value.reset.pin,
active_level: atxConfig.value.reset.active_level, active_level: atxConfig.value.reset.active_level,
baud_rate: atxConfig.value.reset.baud_rate baud_rate: atxConfig.value.reset.baud_rate,
active_level: atxConfig.value.reset.active_level,
}, },
led: { led: {
enabled: atxConfig.value.led.enabled, enabled: atxConfig.value.led.enabled,