Initial commit

This commit is contained in:
2026-06-25 01:57:07 +08:00
commit 1c5841833f
103 changed files with 16911 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
import { contextBridge, ipcRenderer, webUtils } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
// Custom APIs for renderer
const api = {
deleteClass: (classId: string) => ipcRenderer.invoke('student:delete-class', classId),
deleteStudentProfile: (profileId: string) =>
ipcRenderer.invoke('student:delete-profile', profileId),
exportEmptyClassFolder: (payload: { className: string; classId: string; childNames: string[] }) =>
ipcRenderer.invoke('classes:export-empty-folder', payload),
loadStudentData: () => ipcRenderer.invoke('student:load'),
listStudentProfiles: (payload: {
page: number
pageSize: number
query?: string
classId?: string
}) => ipcRenderer.invoke('student:list', payload),
updateStudentProfile: (profile: {
id: string
classId: string
className: string
name: string
englishName: string
gender: string
birthday: string
zodiac: string
friends: string[]
hobbies: string[]
favoriteGames: string[]
favoriteFoods: string[]
traits: string
comment: string
commentGeneratedAt: string
importedAt: string
}) => ipcRenderer.invoke('student:update-profile', profile),
generateStudentComment: (payload: { profileId: string }) =>
ipcRenderer.invoke('student:generate-comment', payload),
listModels: (payload: { baseUrl: string; apiKey: string }) =>
ipcRenderer.invoke('models:list', payload),
testModelConnection: (modelConfig: {
provider: string
baseUrl: string
apiKey: string
model: string
temperature: string
maxTokens: string
systemPrompt: string
}) => ipcRenderer.invoke('models:test-connection', modelConfig),
replaceClassProfiles: (payload: {
classItem: {
id: string
name: string
type: 'cheap' | 'noble'
familyPhoto?: string
}
profiles: Array<{
id: string
classId: string
className: string
name: string
englishName: string
gender: string
birthday: string
zodiac: string
friends: string[]
hobbies: string[]
favoriteGames: string[]
favoriteFoods: string[]
traits: string
importedAt: string
}>
}) => ipcRenderer.invoke('student:replace-class-profiles', payload),
migrateLocalStudentData: (payload: {
classes: Array<{
id: string
name: string
type: 'cheap' | 'noble'
familyPhoto?: string
}>
profiles: Array<{
id: string
classId: string
className: string
name: string
englishName: string
gender: string
birthday: string
zodiac: string
friends: string[]
hobbies: string[]
favoriteGames: string[]
favoriteFoods: string[]
traits: string
importedAt: string
}>
}) => ipcRenderer.invoke('student:migrate-local', payload),
saveClasses: (
classes: Array<{
id: string
name: string
type: 'cheap' | 'noble'
familyPhoto?: string
}>
) => ipcRenderer.invoke('student:save-classes', classes),
loadSettings: () => ipcRenderer.invoke('settings:load'),
saveSettings: (modelConfig: {
provider: string
baseUrl: string
apiKey: string
model: string
temperature: string
maxTokens: string
systemPrompt: string
}) => ipcRenderer.invoke('settings:save', modelConfig),
loadTemplates: () => ipcRenderer.invoke('templates:load'),
selectTemplateFile: () => ipcRenderer.invoke('templates:select-file'),
parseTemplatePlaceholders: (filePath: string) =>
ipcRenderer.invoke('templates:parse-placeholders', filePath),
getDroppedFilePath: (file: File) => webUtils.getPathForFile(file),
saveTemplate: (template: {
id?: string
name: string
grade: string
semester: 'first' | 'second'
type: 'portrait' | 'landscape'
sourceFilePath: string
fieldMappings?: Record<string, string>
}) => ipcRenderer.invoke('templates:save', template),
openTemplate: (filePath: string) => ipcRenderer.invoke('templates:open', filePath),
deleteTemplate: (id: string) => ipcRenderer.invoke('templates:delete', id),
loadReports: () => ipcRenderer.invoke('reports:load'),
generateReports: (payload: { templateId: string; classId: string; studentIds?: string[] }) =>
ipcRenderer.invoke('reports:generate', payload),
openReport: (filePath: string) => ipcRenderer.invoke('reports:open', filePath),
deleteReport: (id: string) => ipcRenderer.invoke('reports:delete', id)
}
// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', electronAPI)
contextBridge.exposeInMainWorld('api', api)
} catch (error) {
console.error(error)
}
} else {
// @ts-ignore (define in dts)
window.electron = electronAPI
// @ts-ignore (define in dts)
window.api = api
}