feat: add material type management feature

- Add MaterialTypeManagementDialog component for managing material type keywords
- Add MaterialsTypeToBeDeletedDAO for database operations
- Add material-type-handler IPC handlers
- Update CleanerPage with type management button
- Add database fix scripts for AUTO_INCREMENT
- Update documentation for settings partial save and validation flow

Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-03-03 22:51:11 +08:00
parent 7aa1abbc22
commit e23cf71f78
23 changed files with 1764 additions and 213 deletions

View File

@@ -11,6 +11,7 @@ import { registerResolverHandlers } from './resolver-handler'
import { registerAuthHandlers } from './auth-handler'
import { registerValidationHandlers } from './validation-handler'
import { registerSettingsHandlers } from './settings-handler'
import { registerMaterialTypeHandlers } from './material-type-handler'
import { createLogger } from '../services/logger'
import { getErrorMessage, getErrorCode, isBaseError } from '../types/errors'
@@ -73,5 +74,6 @@ export function registerIpcHandlers(): void {
registerAuthHandlers()
registerValidationHandlers()
registerSettingsHandlers()
registerMaterialTypeHandlers()
log.info('All IPC handlers registered')
}

View File

@@ -0,0 +1,154 @@
/**
* IPC handlers for material type management operations
*
* Provides endpoints for:
* - Getting all material type records
* - Getting records by manager
* - Getting list of managers
* - Upserting (insert/update) records
* - Deleting records
* - Batch operations
*/
import { ipcMain } from 'electron'
import {
MaterialsTypeToBeDeletedDAO,
type MaterialTypeRecord,
type MaterialTypeBatchRequest
} from '../services/database/materials-type-to-be-deleted-dao'
import { createLogger } from '../services/logger'
const log = createLogger('MaterialTypeHandler')
/**
* Register IPC handlers for material type operations
*/
export function registerMaterialTypeHandlers(): void {
const dao = new MaterialsTypeToBeDeletedDAO()
/**
* Get all material type records
*/
ipcMain.handle(
'materialType:getAll',
async (): Promise<{ success: boolean; data?: MaterialTypeRecord[]; error?: string }> => {
try {
const records = await dao.getAllMaterials()
return { success: true, data: records }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Get all material types error', { error: message })
return { success: false, error: message }
}
}
)
/**
* Get material types by manager
*/
ipcMain.handle(
'materialType:getByManager',
async (
_event,
managerName: string
): Promise<{ success: boolean; data?: MaterialTypeRecord[]; error?: string }> => {
try {
const records = await dao.getMaterialsByManager(managerName)
return { success: true, data: records }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Get material types by manager error', { error: message })
return { success: false, error: message }
}
}
)
/**
* Get list of managers
*/
ipcMain.handle(
'materialType:getManagers',
async (): Promise<{ success: boolean; data?: string[]; error?: string }> => {
try {
const managers = await dao.getManagers()
return { success: true, data: managers }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Get managers error', { error: message })
return { success: false, error: message }
}
}
)
/**
* Upsert (insert or update) a material type record
*/
ipcMain.handle(
'materialType:upsert',
async (
_event,
{ materialName, managerName }: { materialName: string; managerName: string }
): Promise<{ success: boolean; error?: string }> => {
try {
const result = await dao.upsertMaterial(materialName, managerName)
if (!result) {
return { success: false, error: 'Failed to upsert material type' }
}
return { success: true }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Upsert material type error', { error: message })
return { success: false, error: message }
}
}
)
/**
* Delete a material type record
*/
ipcMain.handle(
'materialType:delete',
async (
_event,
{ materialName, managerName }: { materialName: string; managerName: string }
): Promise<{ success: boolean; error?: string }> => {
try {
const result = await dao.deleteMaterial(materialName, managerName)
if (!result) {
return { success: false, error: 'Failed to delete material type' }
}
return { success: true }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Delete material type error', { error: message })
return { success: false, error: message }
}
}
)
/**
* Batch operation for material types (insert, update, delete)
*/
ipcMain.handle(
'materialType:upsertBatch',
async (
_event,
request: MaterialTypeBatchRequest
): Promise<{
success: boolean
stats?: { total: number; success: number; failed: number }
error?: string
}> => {
try {
const stats = await dao.upsertBatch(request)
return { success: true, stats }
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error'
log.error('Batch upsert material types error', { error: message })
return { success: false, error: message }
}
}
)
log.info('Material type handlers registered')
}