修复备卡位 13 自动续做:卡位 API 解析与会话同步

兼容 workDll 返回值即卡位编号的语义,启动卡位轮询时同步主进程 mode,并修正续做失败时的 phase 时序。
This commit is contained in:
24kycj
2026-06-03 10:27:04 +08:00
parent 3ec168350c
commit 75490d8647
5 changed files with 53 additions and 21 deletions
+4 -1
View File
@@ -287,9 +287,12 @@ export function registerIpcHandlers(): void {
return ok() return ok()
}) })
tracedHandle('poll:card-position-start', async () => { tracedHandle('poll:card-position-start', async (_e, sessionMode?: 'distributing' | 'usbCopying') => {
try { try {
assertReady() assertReady()
if (sessionMode === 'distributing' || sessionMode === 'usbCopying') {
mainAppState.mode = sessionMode
}
const dll = await loadDllModule() const dll = await loadDllModule()
if (!dll.isCardPositionApiAvailable()) { if (!dll.isCardPositionApiAvailable()) {
return fail(CS_FAIL, '当前 DLL 不支持卡位查询,无法自动续做') return fail(CS_FAIL, '当前 DLL 不支持卡位查询,无法自动续做')
+4 -3
View File
@@ -1,6 +1,7 @@
import path from 'path' import path from 'path'
import koffi from 'koffi' import koffi from 'koffi'
import log from 'electron-log' import log from 'electron-log'
import { normalizeCardPositionQuery } from '@shared/card-position'
import { CS_OK, JOB_ID_BUF_SIZE, LOG_FATAL_FLAG } from '../constants' import { CS_OK, JOB_ID_BUF_SIZE, LOG_FATAL_FLAG } from '../constants'
import { emitTrace, isTraceEnabled } from '../utils/trace-bridge' import { emitTrace, isTraceEnabled } from '../utils/trace-bridge'
import { getNativeDir } from './native-path' import { getNativeDir } from './native-path'
@@ -396,9 +397,9 @@ export function dllGetPrinterCardPosition(): { queryCode: number; position: numb
return traceCall('SAPI_GetPrinterCardPosition', undefined, () => { return traceCall('SAPI_GetPrinterCardPosition', undefined, () => {
loadLibrary() loadLibrary()
if (!SAPI_GetPrinterCardPosition) throw new Error('CARD_POSITION_API_UNAVAILABLE') if (!SAPI_GetPrinterCardPosition) throw new Error('CARD_POSITION_API_UNAVAILABLE')
const position = [0] const out = [0]
const queryCode = SAPI_GetPrinterCardPosition!(position) as number const ret = SAPI_GetPrinterCardPosition!(out) as number
return { queryCode, position: position[0] } return normalizeCardPositionQuery(ret, out[0])
}) })
} }
+4 -2
View File
@@ -73,8 +73,10 @@ export async function pollUsbStop(opts?: { resetMode?: boolean }): Promise<IpcRe
return api().invoke('poll:usb-stop', opts) as Promise<IpcResult> return api().invoke('poll:usb-stop', opts) as Promise<IpcResult>
} }
export async function pollCardPositionStart(): Promise<IpcResult> { export async function pollCardPositionStart(
return api().invoke('poll:card-position-start') as Promise<IpcResult> sessionMode?: 'distributing' | 'usbCopying'
): Promise<IpcResult> {
return api().invoke('poll:card-position-start', sessionMode) as Promise<IpcResult>
} }
export async function pollCardPositionStop(): Promise<IpcResult> { export async function pollCardPositionStop(): Promise<IpcResult> {
@@ -218,16 +218,18 @@ async function stopTaskPollsOnly(): Promise<void> {
} }
} }
async function startCardPositionWatch(): Promise<void> { async function startCardPositionWatch(
sessionMode: 'distributing' | 'usbCopying'
): Promise<void> {
await pollCardPositionStop() await pollCardPositionStop()
const cardStarted = await pollCardPositionStart()
if (!cardStarted.ok) {
notify.warning(cardStarted.message || '无法监控卡位,请手动点击返回或重新提交')
}
unsubCard?.() unsubCard?.()
unsubCard = onCardPositionTick((payload) => unsubCard = onCardPositionTick((payload) =>
applyCardPosition(payload as CardPositionPollPayload) applyCardPosition(payload as CardPositionPollPayload)
) )
const cardStarted = await pollCardPositionStart(sessionMode)
if (!cardStarted.ok) {
notify.warning(cardStarted.message || '无法监控卡位,请手动点击返回或重新提交')
}
} }
async function enterWaitPhase(next: 'completed' | 'failed', errorText = ''): Promise<void> { async function enterWaitPhase(next: 'completed' | 'failed', errorText = ''): Promise<void> {
@@ -253,9 +255,10 @@ async function enterWaitPhase(next: 'completed' | 'failed', errorText = ''): Pro
failureErrorText.value = errorText failureErrorText.value = errorText
} }
await stopTaskPollsOnly() await stopTaskPollsOnly()
appStore.setMode(isCollect.value ? 'usbCopying' : 'distributing') const sessionMode = isCollect.value ? 'usbCopying' : 'distributing'
appStore.setMode(sessionMode)
lastCardPosition = -1 lastCardPosition = -1
await startCardPositionWatch() await startCardPositionWatch(sessionMode)
} }
async function enterFailedPhase(errorText = ''): Promise<void> { async function enterFailedPhase(errorText = ''): Promise<void> {
@@ -287,16 +290,8 @@ async function resubmitTask(): Promise<void> {
await pollCardPositionStop() await pollCardPositionStop()
unsubCard?.() unsubCard?.()
unsubCard = null unsubCard = null
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
collectHint.value = ''
waitCard.value = false
queryFailStreak = 0
usbQueryFailStreak = 0
const backToWait = async (message?: string): Promise<void> => { const backToWait = async (message?: string): Promise<void> => {
resubmitting = false
if (message) notify.error(message) if (message) notify.error(message)
if (fromWaitPhase === 'failed') { if (fromWaitPhase === 'failed') {
await enterFailedPhase(message || failureErrorText.value) await enterFailedPhase(message || failureErrorText.value)
@@ -312,6 +307,12 @@ async function resubmitTask(): Promise<void> {
await backToWait('导入目录无效,无法继续') await backToWait('导入目录无效,无法继续')
return return
} }
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
collectHint.value = ''
queryFailStreak = 0
usbQueryFailStreak = 0
const r = await dllUsbCopy(dest, collectStore.cardOutput, { resubmit: true }) const r = await dllUsbCopy(dest, collectStore.cardOutput, { resubmit: true })
if (!r.ok) { if (!r.ok) {
await backToWait(r.message || '重新提交收集任务失败') await backToWait(r.message || '重新提交收集任务失败')
@@ -329,6 +330,11 @@ async function resubmitTask(): Promise<void> {
await backToWait() await backToWait()
return return
} }
phase.value = 'running'
setProgress(0)
workflowStep.value = 1
waitCard.value = false
queryFailStreak = 0
const created = await createDistributeJob(formStore, { resubmit: true }) const created = await createDistributeJob(formStore, { resubmit: true })
if (!created.ok) { if (!created.ok) {
await backToWait(created.message) await backToWait(created.message)
@@ -341,6 +347,8 @@ async function resubmitTask(): Promise<void> {
return return
} }
unsubJob = onJobPollTick((payload) => applyJobProgress(payload as JobPollPayload)) unsubJob = onJobPollTick((payload) => applyJobProgress(payload as JobPollPayload))
} catch (e) {
await backToWait(String(e))
} finally { } finally {
resubmitting = false resubmitting = false
} }
+18
View File
@@ -1 +1,19 @@
/** workDll 备卡位:检测到后可自动续做 */
export const POSITION_PREPARE = 13 export const POSITION_PREPARE = 13
/** 卡位编号合理上限(用于解析 DLL 返回值) */
export const POSITION_MAX = 32
/** 归一化 SAPI_GetPrinterCardPosition:兼容返回值=CS_OK 与返回值=卡位编号两种 DLL */
export function normalizeCardPositionQuery(
ret: number,
outPosition: number
): { queryCode: number; position: number } {
if (ret === 0) {
return { queryCode: 0, position: outPosition }
}
if (ret > 0 && ret <= POSITION_MAX) {
return { queryCode: 0, position: ret }
}
return { queryCode: ret, position: outPosition }
}