style: format code with Prettier
Apply Prettier formatting to maintain consistent code style across the codebase. Changes include formatting improvements for: - IPC handlers (database, file, material-type, resolver, user-erp-config, validation) - Type definitions (ipc-api.types) - React components (MaterialTypeManagementDialog) - React hooks (useAuth, useCleaner, useValidation) - Pages (SettingsPage) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,10 @@ const mysqlServices = new Map<string, MySqlService>()
|
|||||||
const sqlServerServices = new Map<string, SqlServerService>()
|
const sqlServerServices = new Map<string, SqlServerService>()
|
||||||
const cleanupBoundWindows = new Set<string>()
|
const cleanupBoundWindows = new Set<string>()
|
||||||
|
|
||||||
function bindWindowCleanup(windowId: string, sender: { once: (event: string, listener: () => void) => void }): void {
|
function bindWindowCleanup(
|
||||||
|
windowId: string,
|
||||||
|
sender: { once: (event: string, listener: () => void) => void }
|
||||||
|
): void {
|
||||||
if (cleanupBoundWindows.has(windowId)) {
|
if (cleanupBoundWindows.has(windowId)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -31,7 +34,9 @@ function bindWindowCleanup(windowId: string, sender: { once: (event: string, lis
|
|||||||
const sqlServer = getSqlServerService(windowId)
|
const sqlServer = getSqlServerService(windowId)
|
||||||
|
|
||||||
if (mysql) {
|
if (mysql) {
|
||||||
mysql.disconnect().catch((error) => log.warn('MySQL disconnect on window destroy failed', { error }))
|
mysql
|
||||||
|
.disconnect()
|
||||||
|
.catch((error) => log.warn('MySQL disconnect on window destroy failed', { error }))
|
||||||
deleteMySqlService(windowId)
|
deleteMySqlService(windowId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,39 +104,48 @@ export function registerDatabaseHandlers(): void {
|
|||||||
IPC_CHANNELS.DATABASE_MYSQL_CONNECT,
|
IPC_CHANNELS.DATABASE_MYSQL_CONNECT,
|
||||||
async (event, config: MySqlConfig): Promise<IpcResult<void>> => {
|
async (event, config: MySqlConfig): Promise<IpcResult<void>> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
// Use window ID as connection identifier
|
// Use window ID as connection identifier
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
bindWindowCleanup(windowId, event.sender as { once: (event: string, listener: () => void) => void })
|
bindWindowCleanup(
|
||||||
log.info('Connecting to MySQL', { windowId })
|
windowId,
|
||||||
const service = new MySqlService(config)
|
event.sender as { once: (event: string, listener: () => void) => void }
|
||||||
await service.connect()
|
)
|
||||||
setMySqlService(windowId, service)
|
log.info('Connecting to MySQL', { windowId })
|
||||||
log.info('MySQL connected', { windowId })
|
const service = new MySqlService(config)
|
||||||
|
await service.connect()
|
||||||
|
setMySqlService(windowId, service)
|
||||||
|
log.info('MySQL connected', { windowId })
|
||||||
}, 'database:mysql:connect')
|
}, 'database:mysql:connect')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Disconnect from MySQL
|
// Disconnect from MySQL
|
||||||
ipcMain.handle(IPC_CHANNELS.DATABASE_MYSQL_DISCONNECT, async (event): Promise<IpcResult<void>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.DATABASE_MYSQL_DISCONNECT,
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
async (event): Promise<IpcResult<void>> => {
|
||||||
const service = getMySqlService(windowId)
|
return withErrorHandling(async () => {
|
||||||
if (service) {
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
await service.disconnect()
|
const service = getMySqlService(windowId)
|
||||||
deleteMySqlService(windowId)
|
if (service) {
|
||||||
log.info('MySQL disconnected', { windowId })
|
await service.disconnect()
|
||||||
}
|
deleteMySqlService(windowId)
|
||||||
}, 'database:mysql:disconnect')
|
log.info('MySQL disconnected', { windowId })
|
||||||
})
|
}
|
||||||
|
}, 'database:mysql:disconnect')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Check if MySQL is connected
|
// Check if MySQL is connected
|
||||||
ipcMain.handle(IPC_CHANNELS.DATABASE_MYSQL_IS_CONNECTED, async (event): Promise<IpcResult<boolean>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.DATABASE_MYSQL_IS_CONNECTED,
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
async (event): Promise<IpcResult<boolean>> => {
|
||||||
const service = getMySqlService(windowId)
|
return withErrorHandling(async () => {
|
||||||
return service ? service.isConnected() : false
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
}, 'database:mysql:isConnected')
|
const service = getMySqlService(windowId)
|
||||||
})
|
return service ? service.isConnected() : false
|
||||||
|
}, 'database:mysql:isConnected')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Execute MySQL query
|
// Execute MySQL query
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
@@ -160,7 +174,10 @@ export function registerDatabaseHandlers(): void {
|
|||||||
async (event, config: SqlServerConfig): Promise<IpcResult<void>> => {
|
async (event, config: SqlServerConfig): Promise<IpcResult<void>> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
bindWindowCleanup(windowId, event.sender as { once: (event: string, listener: () => void) => void })
|
bindWindowCleanup(
|
||||||
|
windowId,
|
||||||
|
event.sender as { once: (event: string, listener: () => void) => void }
|
||||||
|
)
|
||||||
log.info('Connecting to SQL Server', { windowId })
|
log.info('Connecting to SQL Server', { windowId })
|
||||||
const service = new SqlServerService(config)
|
const service = new SqlServerService(config)
|
||||||
await service.connect()
|
await service.connect()
|
||||||
@@ -171,26 +188,32 @@ export function registerDatabaseHandlers(): void {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Disconnect from SQL Server
|
// Disconnect from SQL Server
|
||||||
ipcMain.handle(IPC_CHANNELS.DATABASE_SQLSERVER_DISCONNECT, async (event): Promise<IpcResult<void>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.DATABASE_SQLSERVER_DISCONNECT,
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
async (event): Promise<IpcResult<void>> => {
|
||||||
const service = getSqlServerService(windowId)
|
return withErrorHandling(async () => {
|
||||||
if (service) {
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
await service.disconnect()
|
const service = getSqlServerService(windowId)
|
||||||
deleteSqlServerService(windowId)
|
if (service) {
|
||||||
log.info('SQL Server disconnected', { windowId })
|
await service.disconnect()
|
||||||
}
|
deleteSqlServerService(windowId)
|
||||||
}, 'database:sqlserver:disconnect')
|
log.info('SQL Server disconnected', { windowId })
|
||||||
})
|
}
|
||||||
|
}, 'database:sqlserver:disconnect')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Check if SQL Server is connected
|
// Check if SQL Server is connected
|
||||||
ipcMain.handle(IPC_CHANNELS.DATABASE_SQLSERVER_IS_CONNECTED, async (event): Promise<IpcResult<boolean>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.DATABASE_SQLSERVER_IS_CONNECTED,
|
||||||
const windowId = (event.sender as { id: number }).id.toString()
|
async (event): Promise<IpcResult<boolean>> => {
|
||||||
const service = getSqlServerService(windowId)
|
return withErrorHandling(async () => {
|
||||||
return service ? service.isConnected() : false
|
const windowId = (event.sender as { id: number }).id.toString()
|
||||||
}, 'database:sqlserver:isConnected')
|
const service = getSqlServerService(windowId)
|
||||||
})
|
return service ? service.isConnected() : false
|
||||||
|
}, 'database:sqlserver:isConnected')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Execute SQL Server query
|
// Execute SQL Server query
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
|
|||||||
@@ -31,13 +31,16 @@ function normalizeAndValidatePath(inputPath: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerFileHandlers(): void {
|
export function registerFileHandlers(): void {
|
||||||
ipcMain.handle(IPC_CHANNELS.FILE_READ, async (_event, filePath: string): Promise<IpcResult<string>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.FILE_READ,
|
||||||
const safePath = normalizeAndValidatePath(filePath)
|
async (_event, filePath: string): Promise<IpcResult<string>> => {
|
||||||
log.debug('Reading file', { filePath: safePath })
|
return withErrorHandling(async () => {
|
||||||
return await fs.readFile(safePath, 'utf-8')
|
const safePath = normalizeAndValidatePath(filePath)
|
||||||
}, 'file:read')
|
log.debug('Reading file', { filePath: safePath })
|
||||||
})
|
return await fs.readFile(safePath, 'utf-8')
|
||||||
|
}, 'file:read')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_CHANNELS.FILE_WRITE,
|
IPC_CHANNELS.FILE_WRITE,
|
||||||
@@ -52,36 +55,45 @@ export function registerFileHandlers(): void {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ipcMain.handle(IPC_CHANNELS.FILE_EXISTS, async (_event, filePath: string): Promise<IpcResult<boolean>> => {
|
ipcMain.handle(
|
||||||
return withErrorHandling(async () => {
|
IPC_CHANNELS.FILE_EXISTS,
|
||||||
const safePath = normalizeAndValidatePath(filePath)
|
async (_event, filePath: string): Promise<IpcResult<boolean>> => {
|
||||||
try {
|
return withErrorHandling(async () => {
|
||||||
|
const safePath = normalizeAndValidatePath(filePath)
|
||||||
|
try {
|
||||||
|
await fs.access(safePath)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}, 'file:exists')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
IPC_CHANNELS.FILE_LIST,
|
||||||
|
async (_event, dirPath: string): Promise<IpcResult<string[]>> => {
|
||||||
|
return withErrorHandling(async () => {
|
||||||
|
const safePath = normalizeAndValidatePath(dirPath)
|
||||||
|
log.debug('Listing directory', { dirPath: safePath })
|
||||||
|
const entries = await fs.readdir(safePath, { withFileTypes: true })
|
||||||
|
return entries
|
||||||
|
.filter((entry) => entry.isFile())
|
||||||
|
.map((entry) => entry.name)
|
||||||
|
.sort()
|
||||||
|
}, 'file:list')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
IPC_CHANNELS.FILE_OPEN_PATH,
|
||||||
|
async (_event, filePath: string): Promise<IpcResult<void>> => {
|
||||||
|
return withErrorHandling(async () => {
|
||||||
|
const safePath = normalizeAndValidatePath(filePath)
|
||||||
|
log.debug('Opening path in explorer', { filePath: safePath })
|
||||||
await fs.access(safePath)
|
await fs.access(safePath)
|
||||||
return true
|
await shell.openPath(safePath)
|
||||||
} catch {
|
}, 'file:openPath')
|
||||||
return false
|
}
|
||||||
}
|
)
|
||||||
}, 'file:exists')
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle(IPC_CHANNELS.FILE_LIST, async (_event, dirPath: string): Promise<IpcResult<string[]>> => {
|
|
||||||
return withErrorHandling(async () => {
|
|
||||||
const safePath = normalizeAndValidatePath(dirPath)
|
|
||||||
log.debug('Listing directory', { dirPath: safePath })
|
|
||||||
const entries = await fs.readdir(safePath, { withFileTypes: true })
|
|
||||||
return entries
|
|
||||||
.filter((entry) => entry.isFile())
|
|
||||||
.map((entry) => entry.name)
|
|
||||||
.sort()
|
|
||||||
}, 'file:list')
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle(IPC_CHANNELS.FILE_OPEN_PATH, async (_event, filePath: string): Promise<IpcResult<void>> => {
|
|
||||||
return withErrorHandling(async () => {
|
|
||||||
const safePath = normalizeAndValidatePath(filePath)
|
|
||||||
log.debug('Opening path in explorer', { filePath: safePath })
|
|
||||||
await fs.access(safePath)
|
|
||||||
await shell.openPath(safePath)
|
|
||||||
}, 'file:openPath')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,7 @@ export function registerMaterialTypeHandlers(): void {
|
|||||||
*/
|
*/
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_CHANNELS.MATERIAL_TYPE_GET_BY_MANAGER,
|
IPC_CHANNELS.MATERIAL_TYPE_GET_BY_MANAGER,
|
||||||
async (
|
async (_event, managerName: string): Promise<IpcResult<MaterialTypeRecord[]>> => {
|
||||||
_event,
|
|
||||||
managerName: string
|
|
||||||
): Promise<IpcResult<MaterialTypeRecord[]>> => {
|
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
const records = await dao.getMaterialsByManager(managerName)
|
const records = await dao.getMaterialsByManager(managerName)
|
||||||
return records
|
return records
|
||||||
@@ -127,4 +124,3 @@ export function registerMaterialTypeHandlers(): void {
|
|||||||
|
|
||||||
log.info('Material type handlers registered')
|
log.info('Material type handlers registered')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ export function registerResolverHandlers(): void {
|
|||||||
async (
|
async (
|
||||||
_event,
|
_event,
|
||||||
inputs: string[]
|
inputs: string[]
|
||||||
): Promise<IpcResult<Array<{ input: string; type: 'productionId' | 'orderNumber' | 'unknown' }>>> => {
|
): Promise<
|
||||||
|
IpcResult<Array<{ input: string; type: 'productionId' | 'orderNumber' | 'unknown' }>>
|
||||||
|
> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
// Create a mock resolver without database connection
|
// Create a mock resolver without database connection
|
||||||
const resolver = new OrderNumberResolver({
|
const resolver = new OrderNumberResolver({
|
||||||
|
|||||||
@@ -42,7 +42,10 @@ export function registerUserErpConfigHandlers(): void {
|
|||||||
const credentials = await erpConfigService.getCurrentUserErpConfig()
|
const credentials = await erpConfigService.getCurrentUserErpConfig()
|
||||||
|
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
throw new ValidationError('未找到 ERP 配置。请先配置 ERP 账号和密码。', 'VAL_INVALID_INPUT')
|
throw new ValidationError(
|
||||||
|
'未找到 ERP 配置。请先配置 ERP 账号和密码。',
|
||||||
|
'VAL_INVALID_INPUT'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const configManager = ConfigManager.getInstance()
|
const configManager = ConfigManager.getInstance()
|
||||||
@@ -86,7 +89,10 @@ export function registerUserErpConfigHandlers(): void {
|
|||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_CHANNELS.USER_ERP_CONFIG_TEST_CONNECTION,
|
IPC_CHANNELS.USER_ERP_CONFIG_TEST_CONNECTION,
|
||||||
async (_event, credentials: ErpCredentialsRequest): Promise<IpcResult<ConnectionTestResult>> => {
|
async (
|
||||||
|
_event,
|
||||||
|
credentials: ErpCredentialsRequest
|
||||||
|
): Promise<IpcResult<ConnectionTestResult>> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
if (!credentials.username || !credentials.password) {
|
if (!credentials.username || !credentials.password) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
@@ -139,4 +145,3 @@ export function registerUserErpConfigHandlers(): void {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -497,18 +497,21 @@ export function registerValidationHandlers(): void {
|
|||||||
/**
|
/**
|
||||||
* Get unique manager names
|
* Get unique manager names
|
||||||
*/
|
*/
|
||||||
ipcMain.handle(IPC_CHANNELS.MATERIALS_GET_MANAGERS, async (_event): Promise<{ managers: string[] }> => {
|
ipcMain.handle(
|
||||||
try {
|
IPC_CHANNELS.MATERIALS_GET_MANAGERS,
|
||||||
const dao = new MaterialsToBeDeletedDAO()
|
async (_event): Promise<{ managers: string[] }> => {
|
||||||
const managers = await dao.getManagers()
|
try {
|
||||||
return { managers }
|
const dao = new MaterialsToBeDeletedDAO()
|
||||||
} catch (error) {
|
const managers = await dao.getManagers()
|
||||||
log.error('Get managers error', {
|
return { managers }
|
||||||
error: error instanceof Error ? error.message : String(error)
|
} catch (error) {
|
||||||
})
|
log.error('Get managers error', {
|
||||||
return { managers: [] }
|
error: error instanceof Error ? error.message : String(error)
|
||||||
|
})
|
||||||
|
return { managers: [] }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update manager for a single material
|
* Update manager for a single material
|
||||||
|
|||||||
@@ -76,9 +76,7 @@ export interface ExtractorAPI {
|
|||||||
* Run ERP data extractor
|
* Run ERP data extractor
|
||||||
* @param input - Extractor input parameters
|
* @param input - Extractor input parameters
|
||||||
*/
|
*/
|
||||||
runExtractor: (
|
runExtractor: (input: ExtractorInput) => Promise<IpcResult<ExtractorResult>>
|
||||||
input: ExtractorInput
|
|
||||||
) => Promise<IpcResult<ExtractorResult>>
|
|
||||||
/**
|
/**
|
||||||
* Subscribe to progress updates
|
* Subscribe to progress updates
|
||||||
* @param callback - Callback function receiving progress data
|
* @param callback - Callback function receiving progress data
|
||||||
@@ -101,9 +99,7 @@ export interface CleanerAPI {
|
|||||||
* Run ERP cleaner service
|
* Run ERP cleaner service
|
||||||
* @param input - Cleaner input parameters
|
* @param input - Cleaner input parameters
|
||||||
*/
|
*/
|
||||||
runCleaner: (
|
runCleaner: (input: CleanerInput) => Promise<IpcResult<CleanerResult>>
|
||||||
input: CleanerInput
|
|
||||||
) => Promise<IpcResult<CleanerResult>>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export validation results to Excel
|
* Export validation results to Excel
|
||||||
|
|||||||
@@ -154,13 +154,16 @@ export const MaterialTypeManagementDialog: React.FC<MaterialTypeManagementDialog
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// Start editing a cell
|
// Start editing a cell
|
||||||
const startEdit = useCallback((rowIndex: number, field: string) => {
|
const startEdit = useCallback(
|
||||||
const row = rows[rowIndex]
|
(rowIndex: number, field: string) => {
|
||||||
if (row.state === 'deleted') return
|
const row = rows[rowIndex]
|
||||||
|
if (row.state === 'deleted') return
|
||||||
|
|
||||||
setEditingCell({ rowIndex, field })
|
setEditingCell({ rowIndex, field })
|
||||||
setEditValue(row.record[field as keyof MaterialTypeRecord] as string)
|
setEditValue(row.record[field as keyof MaterialTypeRecord] as string)
|
||||||
}, [rows])
|
},
|
||||||
|
[rows]
|
||||||
|
)
|
||||||
|
|
||||||
// Save edit
|
// Save edit
|
||||||
const saveEdit = useCallback(() => {
|
const saveEdit = useCallback(() => {
|
||||||
@@ -252,7 +255,9 @@ export const MaterialTypeManagementDialog: React.FC<MaterialTypeManagementDialog
|
|||||||
toUpdate,
|
toUpdate,
|
||||||
toDelete
|
toDelete
|
||||||
})
|
})
|
||||||
const payload = result.success ? (result.data as { stats?: { success?: number; failed?: number } } | undefined) : undefined
|
const payload = result.success
|
||||||
|
? (result.data as { stats?: { success?: number; failed?: number } } | undefined)
|
||||||
|
: undefined
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
alert(
|
alert(
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ export function useAuth(): UseAuthReturn {
|
|||||||
return true
|
return true
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const silentLogin = useCallback(async (): Promise<{ success: boolean; requiresUserSelection?: boolean }> => {
|
const silentLogin = useCallback(async (): Promise<{
|
||||||
|
success: boolean
|
||||||
|
requiresUserSelection?: boolean
|
||||||
|
}> => {
|
||||||
setState((prev) => ({ ...prev, loading: true, error: null }))
|
setState((prev) => ({ ...prev, loading: true, error: null }))
|
||||||
const result = await window.electron.auth.silentLogin()
|
const result = await window.electron.auth.silentLogin()
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ export function useCleaner() {
|
|||||||
// Load managers
|
// Load managers
|
||||||
if (admin) {
|
if (admin) {
|
||||||
const resp = await window.electron.materials.getManagers()
|
const resp = await window.electron.materials.getManagers()
|
||||||
const managersPayload = resp.success ? (resp.data as { managers: string[] } | undefined) : undefined
|
const managersPayload = resp.success
|
||||||
|
? (resp.data as { managers: string[] } | undefined)
|
||||||
|
: undefined
|
||||||
const managerList = managersPayload?.managers ?? []
|
const managerList = managersPayload?.managers ?? []
|
||||||
setManagers(managerList)
|
setManagers(managerList)
|
||||||
setSelectedManagers(new Set(managerList))
|
setSelectedManagers(new Set(managerList))
|
||||||
@@ -108,7 +110,9 @@ export function useCleaner() {
|
|||||||
|
|
||||||
// Get shared Production IDs
|
// Get shared Production IDs
|
||||||
const result = await window.electron.validation.getSharedProductionIds()
|
const result = await window.electron.validation.getSharedProductionIds()
|
||||||
const idsPayload = result.success ? (result.data as { productionIds?: string[] } | undefined) : undefined
|
const idsPayload = result.success
|
||||||
|
? (result.data as { productionIds?: string[] } | undefined)
|
||||||
|
: undefined
|
||||||
setSharedProductionIdsCount(idsPayload?.productionIds?.length ?? 0)
|
setSharedProductionIdsCount(idsPayload?.productionIds?.length ?? 0)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Initialization failed:', err)
|
console.error('Initialization failed:', err)
|
||||||
@@ -297,7 +301,9 @@ export function useCleaner() {
|
|||||||
|
|
||||||
if (materialsToUpsert.length > 0) {
|
if (materialsToUpsert.length > 0) {
|
||||||
const res = await window.electron.materials.upsertBatch(materialsToUpsert)
|
const res = await window.electron.materials.upsertBatch(materialsToUpsert)
|
||||||
const payload = res.success ? (res.data as { stats?: { success?: number } } | undefined) : undefined
|
const payload = res.success
|
||||||
|
? (res.data as { stats?: { success?: number } } | undefined)
|
||||||
|
: undefined
|
||||||
if (!res.success) throw new Error(res.error || '写入物料失败')
|
if (!res.success) throw new Error(res.error || '写入物料失败')
|
||||||
msgParts.push(`写入/更新成功:${payload?.stats?.success || 0} 条`)
|
msgParts.push(`写入/更新成功:${payload?.stats?.success || 0} 条`)
|
||||||
}
|
}
|
||||||
@@ -314,7 +320,9 @@ export function useCleaner() {
|
|||||||
// Reload managers if admin
|
// Reload managers if admin
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
const resp = await window.electron.materials.getManagers()
|
const resp = await window.electron.materials.getManagers()
|
||||||
const payload = resp.success ? (resp.data as { managers?: string[] } | undefined) : undefined
|
const payload = resp.success
|
||||||
|
? (resp.data as { managers?: string[] } | undefined)
|
||||||
|
: undefined
|
||||||
setManagers(payload?.managers ?? [])
|
setManagers(payload?.managers ?? [])
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -52,28 +52,39 @@ export function useValidation(): UseValidationReturn {
|
|||||||
error: null
|
error: null
|
||||||
})
|
})
|
||||||
|
|
||||||
const validate = useCallback(async (request: ValidationRequest): Promise<ValidationResponse | null> => {
|
const validate = useCallback(
|
||||||
setState((prev) => ({ ...prev, loading: true, error: null }))
|
async (request: ValidationRequest): Promise<ValidationResponse | null> => {
|
||||||
const response = await window.electron.validation.validate(request)
|
setState((prev) => ({ ...prev, loading: true, error: null }))
|
||||||
if (!response.success || !response.data) {
|
const response = await window.electron.validation.validate(request)
|
||||||
setState((prev) => ({ ...prev, loading: false, error: response.error || 'Validation failed' }))
|
if (!response.success || !response.data) {
|
||||||
return response.success ? null : { success: false, error: response.error }
|
setState((prev) => ({
|
||||||
}
|
...prev,
|
||||||
|
loading: false,
|
||||||
|
error: response.error || 'Validation failed'
|
||||||
|
}))
|
||||||
|
return response.success ? null : { success: false, error: response.error }
|
||||||
|
}
|
||||||
|
|
||||||
const result = response.data as ValidationResponse
|
const result = response.data as ValidationResponse
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
setState((prev) => ({ ...prev, loading: false, error: result.error || 'Validation failed' }))
|
setState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
loading: false,
|
||||||
|
error: result.error || 'Validation failed'
|
||||||
|
}))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
setState({
|
||||||
|
loading: false,
|
||||||
|
data: result.results || null,
|
||||||
|
stats: result.stats || null,
|
||||||
|
error: null
|
||||||
|
})
|
||||||
return result
|
return result
|
||||||
}
|
},
|
||||||
|
[]
|
||||||
setState({
|
)
|
||||||
loading: false,
|
|
||||||
data: result.results || null,
|
|
||||||
stats: result.stats || null,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const setSharedProductionIds = useCallback(async (ids: string[]): Promise<void> => {
|
const setSharedProductionIds = useCallback(async (ids: string[]): Promise<void> => {
|
||||||
await window.electron.validation.setSharedProductionIds(ids)
|
await window.electron.validation.setSharedProductionIds(ids)
|
||||||
@@ -88,7 +99,10 @@ export function useValidation(): UseValidationReturn {
|
|||||||
return payload.productionIds || []
|
return payload.productionIds || []
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const getCleanerData = useCallback(async (): Promise<{ orderNumbers: string[]; materialCodes: string[] } | null> => {
|
const getCleanerData = useCallback(async (): Promise<{
|
||||||
|
orderNumbers: string[]
|
||||||
|
materialCodes: string[]
|
||||||
|
} | null> => {
|
||||||
const result = await window.electron.validation.getCleanerData()
|
const result = await window.electron.validation.getCleanerData()
|
||||||
if (!result.success || !result.data) {
|
if (!result.success || !result.data) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ const SettingsPage: React.FC = () => {
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
// ERP credentials are loaded from database (current user's config)
|
// ERP credentials are loaded from database (current user's config)
|
||||||
const response = await window.electron.settings.getSettings()
|
const response = await window.electron.settings.getSettings()
|
||||||
const config = response.success ? (response.data as { erp?: ErpCredentials } | undefined) : undefined
|
const config = response.success
|
||||||
|
? (response.data as { erp?: ErpCredentials } | undefined)
|
||||||
|
: undefined
|
||||||
|
|
||||||
// Extract ERP credentials from the config
|
// Extract ERP credentials from the config
|
||||||
if (config?.erp) {
|
if (config?.erp) {
|
||||||
@@ -60,7 +62,9 @@ const SettingsPage: React.FC = () => {
|
|||||||
password: credentials.password
|
password: credentials.password
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const saveData = result.success ? (result.data as { success?: boolean; error?: string } | undefined) : undefined
|
const saveData = result.success
|
||||||
|
? (result.data as { success?: boolean; error?: string } | undefined)
|
||||||
|
: undefined
|
||||||
|
|
||||||
if (result.success && saveData?.success !== false) {
|
if (result.success && saveData?.success !== false) {
|
||||||
setIsModified(false)
|
setIsModified(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user