feat: implement user authentication system

- Add SessionManager for managing user sessions (singleton pattern)
- Add BIPUsersDAO for database authentication
- Add LoginDialog component for username/password login
- Add UserSelectionDialog component for admin user selection
- Support silent login by computer name
- Implement main page with navigation to Extractor and Cleaner

Database:
- Table: dbo_BIPUsers
- Fields: UserName, Password, UserType, ComputerNmae

UI Flow:
1. Silent login on startup via computer name
2. Show login dialog if silent login fails
3. Display main page with user info and navigation
4. Support logout and re-login
This commit is contained in:
Misaka
2026-03-01 17:46:15 +08:00
parent 450eb41f96
commit 829851e3ca
12 changed files with 1671 additions and 112 deletions

View File

@@ -1,5 +1,13 @@
import type { FileAPI, ExtractorAPI, CleanerAPI, DatabaseAPI } from '../main/types/ipc-api.types'
import type { ResolverInput, ResolverResponse } from '../main/ipc/resolver-handler'
import type { UserInfo } from '../main/types/user.types'
import type {
LoginRequest,
LoginResponse,
SilentLoginResponse,
UserSelectionResponse,
CurrentUserResponse
} from '../main/ipc/auth-handler'
/**
* Order number resolver API
@@ -21,6 +29,46 @@ export interface ResolverAPI {
}>
}
/**
* Authentication API
*/
export interface AuthAPI {
/**
* Get computer name
*/
getComputerName: () => Promise<string>
/**
* Silent login by computer name
*/
silentLogin: () => Promise<SilentLoginResponse>
/**
* Login with username and password
* @param request - Login request with username and password
*/
login: (request: LoginRequest) => Promise<LoginResponse>
/**
* Logout
*/
logout: () => Promise<void>
/**
* Get current user
*/
getCurrentUser: () => Promise<CurrentUserResponse>
/**
* Get all users (for admin user selection)
*/
getAllUsers: () => Promise<UserInfo[]>
/**
* Switch user (admin only)
* @param userInfo - User info to switch to
*/
switchUser: (userInfo: UserInfo) => Promise<UserSelectionResponse>
/**
* Check if current user is admin
*/
isAdmin: () => Promise<boolean>
}
declare global {
interface Window {
electron: {
@@ -44,6 +92,7 @@ declare global {
cleaner: CleanerAPI
database: DatabaseAPI
resolver: ResolverAPI
auth: AuthAPI
}
api: unknown
}

View File

@@ -4,6 +4,8 @@ import type { MySqlConfig, SqlServerConfig } from '../main/types/ipc-api.types'
import type { ExtractorInput } from '../main/types/extractor.types'
import type { CleanerInput } from '../main/types/cleaner.types'
import type { ResolverInput } from '../main/ipc/resolver-handler'
import type { LoginRequest } from '../main/ipc/auth-handler'
import type { UserInfo } from '../main/types/user.types'
// Custom APIs for renderer
const api = {
@@ -32,6 +34,18 @@ const api = {
validateFormat: (inputs: string[]) => ipcRenderer.invoke('resolver:validateFormat', inputs)
},
// Authentication service
auth: {
getComputerName: () => ipcRenderer.invoke('auth:getComputerName'),
silentLogin: () => ipcRenderer.invoke('auth:silentLogin'),
login: (request: LoginRequest) => ipcRenderer.invoke('auth:login', request),
logout: () => ipcRenderer.invoke('auth:logout'),
getCurrentUser: () => ipcRenderer.invoke('auth:getCurrentUser'),
getAllUsers: () => ipcRenderer.invoke('auth:getAllUsers'),
switchUser: (userInfo: UserInfo) => ipcRenderer.invoke('auth:switchUser', userInfo),
isAdmin: () => ipcRenderer.invoke('auth:isAdmin')
},
// Database service
database: {
connectMySql: (config: MySqlConfig) => ipcRenderer.invoke('database:mysql:connect', config),