优化一些bug

This commit is contained in:
24kycj
2026-05-27 00:17:13 +08:00
parent 79174e7e03
commit 22b17aed35
48 changed files with 1529 additions and 388 deletions
+87 -29
View File
@@ -11,8 +11,11 @@ import {
startUsbPoll,
stopAllPolls,
stopJobPoll,
stopUsbPoll
stopUsbPoll,
getPollMainWindow
} from '../services/poll-manager'
import { cleanPathPattern, getDirectorySizeBytes } from '../utils/dir-size'
import { parseSoonTemplate } from '../utils/parse-soon'
import {
dllAdminJobCancel,
dllCopyFromUsb,
@@ -34,12 +37,18 @@ function fail(code: number, message: string) {
return { ok: false as const, code, message }
}
let dllInitAttempted = false
export function registerIpcHandlers(): void {
ipcMain.handle('dll:init', (_e, params) => {
if (dllInitAttempted) {
return fail(CS_FAIL, '请勿重复初始化,请完全退出应用后重新启动再试')
}
stopAllPolls()
try {
const sharedDir = params?.sharedDir || (configStore.get('sharedDir') as string)
fs.mkdirSync(sharedDir, { recursive: true })
log.info(`SAPI_Init starting, sharedDir=${sharedDir}`)
const code = dllInit({
sharedDir,
keepCombinedImage: params?.keepCombinedImage,
@@ -50,17 +59,16 @@ export function registerIpcHandlers(): void {
logLevel: params?.logLevel,
outBack: params?.outBack
})
if (code === CS_OK) {
mainAppState.initialized = true
configStore.set('sharedDir', sharedDir)
return ok({ printerDetected: true })
}
log.info(`SAPI_Init finished, code=${code}`)
dllInitAttempted = true
mainAppState.initialized = true
configStore.set('sharedDir', sharedDir)
if (code === CS_OK) {
return ok()
}
log.warn(`SAPI_Init returned ${code}; UI ready, printer ops may fail until device connected`)
return ok({
printerDetected: false,
warning: '打印机未连接或驱动未就绪,界面可浏览,业务操作需接真机后重试 Init'
warning: '打印机未连接或驱动未就绪,界面可浏览,接好设备后可在设置中重试 Init'
})
} catch (err) {
mainAppState.initialized = false
@@ -129,7 +137,7 @@ export function registerIpcHandlers(): void {
try {
assertReady()
const id = jobId || mainAppState.activeJobId
stopJobPoll()
stopJobPoll(true)
let code = CS_OK
if (isCancelApiAvailable()) {
code = dllAdminJobCancel(id)
@@ -166,7 +174,7 @@ export function registerIpcHandlers(): void {
})
ipcMain.handle('poll:job-stop', () => {
stopJobPoll()
stopJobPoll(true)
return ok()
})
@@ -182,13 +190,17 @@ export function registerIpcHandlers(): void {
})
ipcMain.handle('dialog:open-directory', async () => {
const r = await dialog.showOpenDialog({ properties: ['openDirectory', 'multiSelections'] })
const win = getPollMainWindow()
const r = await dialog.showOpenDialog(win ?? undefined, {
properties: ['openDirectory', 'multiSelections']
})
if (r.canceled || !r.filePaths.length) return ok({ paths: [] as string[] })
return ok({ paths: r.filePaths })
})
ipcMain.handle('dialog:open-file', async (_e, filters?: { name: string; extensions: string[] }[]) => {
const r = await dialog.showOpenDialog({
const win = getPollMainWindow()
const r = await dialog.showOpenDialog(win ?? undefined, {
properties: ['openFile'],
filters: filters ?? [{ name: 'Soon', extensions: ['soon'] }]
})
@@ -197,23 +209,67 @@ export function registerIpcHandlers(): void {
})
ipcMain.handle('fs:path-exists', (_e, paths: string[]) => {
const missing = paths.filter((p) => {
const clean = p.replace(/\\\*\\.\\*$/i, '').replace(/\/\*\.\*$/i, '')
return !fs.existsSync(clean)
})
const missing = paths
.map((raw) => ({ raw, dir: cleanPathPattern(raw) }))
.filter(({ dir }) => !dir || !fs.existsSync(dir))
.map(({ dir, raw }) => dir || raw)
return ok({ missing })
})
ipcMain.handle('config:get', () =>
ok({
sharedDir: configStore.get('sharedDir'),
templateDir: configStore.get('templateDir'),
skipDllInit: configStore.get('skipDllInit', !app.isPackaged)
ipcMain.handle('fs:dir-size', (_e, paths: string[]) => {
const items = paths.map((raw) => {
const dir = cleanPathPattern(raw)
if (!fs.existsSync(dir)) return { path: raw, bytes: 0, missing: true as const }
try {
const st = fs.statSync(dir)
if (!st.isDirectory()) return { path: raw, bytes: st.size }
return { path: raw, bytes: getDirectorySizeBytes(dir) }
} catch {
return { path: raw, bytes: 0, missing: true as const }
}
})
)
return ok({ items })
})
ipcMain.handle('config:set', (_e, patch: Record<string, string>) => {
Object.entries(patch).forEach(([k, v]) => configStore.set(k, v))
ipcMain.handle('fs:parse-soon', (_e, filePath: string) => {
try {
const soonPath = String(filePath || '').trim()
if (!soonPath) return fail(CS_FAIL, '模板路径为空')
if (!fs.existsSync(soonPath)) return fail(CS_FAIL, '模板文件不存在')
const raw = JSON.parse(fs.readFileSync(soonPath, 'utf8')) as Record<string, unknown>
return ok(parseSoonTemplate(soonPath, raw))
} catch (err) {
log.error('fs:parse-soon', err)
return fail(CS_FAIL, err instanceof Error ? err.message : String(err))
}
})
ipcMain.handle('config:get', () => {
const payload: {
sharedDir: string
templateDir: string
skipDllInit?: boolean
} = {
sharedDir: configStore.get('sharedDir'),
templateDir: configStore.get('templateDir')
}
if (!app.isPackaged) {
payload.skipDllInit = configStore.get('skipDllInit', false)
}
return ok(payload)
})
ipcMain.handle('config:set', (_e, patch: Record<string, unknown>) => {
Object.entries(patch).forEach(([k, v]) => {
if (k === 'skipDllInit') {
if (app.isPackaged) return
const b =
v === true || v === 'true' || v === 1 || v === '1' || String(v).toLowerCase() === 'true'
configStore.set(k, b)
return
}
configStore.set(k, v as string)
})
return ok(configStore.store)
})
@@ -228,17 +284,19 @@ export function registerIpcHandlers(): void {
}
export async function handleBeforeQuit(): Promise<void> {
stopAllPolls()
if (
const shouldCancel =
mainAppState.mode === 'distributing' &&
mainAppState.activeJobId &&
!!mainAppState.activeJobId &&
isCancelApiAvailable()
) {
const cancelJobId = mainAppState.activeJobId
stopAllPolls()
if (shouldCancel && cancelJobId) {
try {
dllAdminJobCancel(mainAppState.activeJobId)
dllAdminJobCancel(cancelJobId)
} catch (e) {
log.warn('before-quit cancel', e)
}
}
mainAppState.mode = 'ready'
mainAppState.activeJobId = ''
}