├── .all-contributorsrc ├── .editorconfig ├── .envrc ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── ClassTools.iml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── discord.xml ├── git_toolbox_prj.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── modules.xml └── vcs.xml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── build └── app.ico ├── electron-builder.json ├── introduction ├── gplv3.png ├── homework.png ├── settings.png ├── slogan.png ├── views.png └── wallpaper.png ├── package.json ├── pnpm-lock.yaml ├── privacy.md ├── scripts ├── build.mjs └── watch.mjs ├── src ├── main │ ├── components │ │ └── tray.ts │ ├── constants.ts │ ├── index.ts │ ├── ipc │ │ └── window.ts │ ├── types │ │ └── WindowName.d.ts │ ├── utils │ │ ├── checkForUpdate.ts │ │ ├── createShortcuts.ts │ │ ├── getSettings.ts │ │ ├── setAsWallpaper.ts │ │ └── windowManager.ts │ └── vite.config.ts ├── preload │ ├── index.ts │ └── vite.config.ts └── renderer │ ├── components.d.ts │ ├── index.html │ ├── src │ ├── App.vue │ ├── assets │ │ ├── avatars │ │ │ ├── clansty.webp │ │ │ └── rainbowBird.webp │ │ ├── icon.webp │ │ ├── icons │ │ │ ├── Close.svg │ │ │ ├── Edit.svg │ │ │ ├── Github.svg │ │ │ └── Minimize.svg │ │ └── weather-icons │ │ │ ├── 100.svg │ │ │ ├── 1001.svg │ │ │ ├── 1002.svg │ │ │ ├── 1003.svg │ │ │ ├── 1004.svg │ │ │ ├── 1005.svg │ │ │ ├── 1006.svg │ │ │ ├── 1007.svg │ │ │ ├── 1008.svg │ │ │ ├── 1009.svg │ │ │ ├── 101.svg │ │ │ ├── 1010.svg │ │ │ ├── 1011.svg │ │ │ ├── 1012.svg │ │ │ ├── 1013.svg │ │ │ ├── 1014.svg │ │ │ ├── 1015.svg │ │ │ ├── 1016.svg │ │ │ ├── 1017.svg │ │ │ ├── 1018.svg │ │ │ ├── 1019.svg │ │ │ ├── 102.svg │ │ │ ├── 1020.svg │ │ │ ├── 1021.svg │ │ │ ├── 1022.svg │ │ │ ├── 1023.svg │ │ │ ├── 1024.svg │ │ │ ├── 1025.svg │ │ │ ├── 1026.svg │ │ │ ├── 1027.svg │ │ │ ├── 1028.svg │ │ │ ├── 1029.svg │ │ │ ├── 103.svg │ │ │ ├── 1030.svg │ │ │ ├── 1031.svg │ │ │ ├── 1032.svg │ │ │ ├── 1033.svg │ │ │ ├── 1034.svg │ │ │ ├── 1035.svg │ │ │ ├── 1036.svg │ │ │ ├── 1037.svg │ │ │ ├── 1038.svg │ │ │ ├── 1039.svg │ │ │ ├── 104.svg │ │ │ ├── 1040.svg │ │ │ ├── 1041.svg │ │ │ ├── 1042.svg │ │ │ ├── 1043.svg │ │ │ ├── 1044.svg │ │ │ ├── 1045.svg │ │ │ ├── 1046.svg │ │ │ ├── 1047.svg │ │ │ ├── 1048.svg │ │ │ ├── 1049.svg │ │ │ ├── 1050.svg │ │ │ ├── 1051.svg │ │ │ ├── 1052.svg │ │ │ ├── 1053.svg │ │ │ ├── 1054.svg │ │ │ ├── 1055.svg │ │ │ ├── 1056.svg │ │ │ ├── 1057.svg │ │ │ ├── 1058.svg │ │ │ ├── 1059.svg │ │ │ ├── 1061.svg │ │ │ ├── 1064.svg │ │ │ ├── 1101.svg │ │ │ ├── 1302.svg │ │ │ ├── 1402.svg │ │ │ ├── 150.svg │ │ │ ├── 151.svg │ │ │ ├── 152.svg │ │ │ ├── 153.svg │ │ │ ├── 1601.svg │ │ │ ├── 1602.svg │ │ │ ├── 1603.svg │ │ │ ├── 1604.svg │ │ │ ├── 1605.svg │ │ │ ├── 1606.svg │ │ │ ├── 1607.svg │ │ │ ├── 2001.svg │ │ │ ├── 2002.svg │ │ │ ├── 2003.svg │ │ │ ├── 2004.svg │ │ │ ├── 2005.svg │ │ │ ├── 2006.svg │ │ │ ├── 2007.svg │ │ │ ├── 2008.svg │ │ │ ├── 2009.svg │ │ │ ├── 2010.svg │ │ │ ├── 2011.svg │ │ │ ├── 2012.svg │ │ │ ├── 2013.svg │ │ │ ├── 2014.svg │ │ │ ├── 2015.svg │ │ │ ├── 2016.svg │ │ │ ├── 2017.svg │ │ │ ├── 2018.svg │ │ │ ├── 2019.svg │ │ │ ├── 2020.svg │ │ │ ├── 2021.svg │ │ │ ├── 2022.svg │ │ │ ├── 2023.svg │ │ │ ├── 2024.svg │ │ │ ├── 2025.svg │ │ │ ├── 2026.svg │ │ │ ├── 2027.svg │ │ │ ├── 2028.svg │ │ │ ├── 300.svg │ │ │ ├── 301.svg │ │ │ ├── 302.svg │ │ │ ├── 303.svg │ │ │ ├── 304.svg │ │ │ ├── 305.svg │ │ │ ├── 306.svg │ │ │ ├── 307.svg │ │ │ ├── 308.svg │ │ │ ├── 309.svg │ │ │ ├── 310.svg │ │ │ ├── 311.svg │ │ │ ├── 312.svg │ │ │ ├── 313.svg │ │ │ ├── 314.svg │ │ │ ├── 315.svg │ │ │ ├── 316.svg │ │ │ ├── 317.svg │ │ │ ├── 318.svg │ │ │ ├── 350.svg │ │ │ ├── 351.svg │ │ │ ├── 399.svg │ │ │ ├── 400.svg │ │ │ ├── 401.svg │ │ │ ├── 402.svg │ │ │ ├── 403.svg │ │ │ ├── 404.svg │ │ │ ├── 405.svg │ │ │ ├── 406.svg │ │ │ ├── 407.svg │ │ │ ├── 408.svg │ │ │ ├── 409.svg │ │ │ ├── 410.svg │ │ │ ├── 456.svg │ │ │ ├── 457.svg │ │ │ ├── 499.svg │ │ │ ├── 500.svg │ │ │ ├── 501.svg │ │ │ ├── 502.svg │ │ │ ├── 503.svg │ │ │ ├── 504.svg │ │ │ ├── 507.svg │ │ │ ├── 508.svg │ │ │ ├── 509.svg │ │ │ ├── 510.svg │ │ │ ├── 511.svg │ │ │ ├── 512.svg │ │ │ ├── 513.svg │ │ │ ├── 514.svg │ │ │ ├── 515.svg │ │ │ ├── 800.svg │ │ │ ├── 801.svg │ │ │ ├── 802.svg │ │ │ ├── 803.svg │ │ │ ├── 804.svg │ │ │ ├── 805.svg │ │ │ ├── 806.svg │ │ │ ├── 807.svg │ │ │ ├── 900.svg │ │ │ ├── 901.svg │ │ │ ├── 999.svg │ │ │ ├── 9998.svg │ │ │ └── 9999.svg │ ├── components │ │ ├── DateAndCountDown.vue │ │ ├── DebouncedSlider.vue │ │ ├── FileSelectButton.vue │ │ ├── FontSelector.vue │ │ ├── FontSizeSliderFormItem.vue │ │ ├── HomeworkDisplay.vue │ │ ├── ScheduleDisplay.vue │ │ ├── SloganDisplay.vue │ │ └── Weather │ │ │ ├── Degree.vue │ │ │ ├── Hourly.vue │ │ │ ├── Props.vue │ │ │ ├── RainWarning.vue │ │ │ ├── Realtime.vue │ │ │ ├── WeatherIcon.vue │ │ │ ├── Week.vue │ │ │ └── index.vue │ ├── data │ │ └── cities.json │ ├── env.d.ts │ ├── global.d.ts │ ├── hooks │ │ ├── createAutoUpdateStorage.ts │ │ └── systemWallpaper.ts │ ├── language │ │ └── zh_CN.yaml │ ├── main.ts │ ├── router.ts │ ├── stores │ │ ├── homeworkHistory.ts │ │ ├── homeworkHistoryList.ts │ │ ├── homeworks.ts │ │ ├── lotsSettings.ts │ │ ├── settings.ts │ │ └── slogan.ts │ ├── types │ │ ├── HomeworkRecord.d.ts │ │ └── QWeather.d.ts │ ├── utils │ │ ├── getTime.ts │ │ ├── newDay.ts │ │ ├── parseNamelist.ts │ │ ├── random.ts │ │ ├── sendHomeworkWebhook.ts │ │ └── supportedFonts.ts │ └── views │ │ ├── About.vue │ │ ├── Demo.vue │ │ ├── HomeworkEdit.vue │ │ ├── HomeworkHistory.vue │ │ ├── HomeworkHistoryView.vue │ │ ├── HomeworkView.vue │ │ ├── Lots.vue │ │ ├── Settings.vue │ │ ├── SloganEdit.vue │ │ ├── Wallpaper.vue │ │ └── settings │ │ ├── Basic.vue │ │ ├── Countdown.vue │ │ ├── Duty.vue │ │ ├── HomeworkViewer.vue │ │ ├── Lessons.vue │ │ ├── Namelist.vue │ │ ├── Schedule.vue │ │ ├── Wallpaper.vue │ │ └── Weather.vue │ ├── tsconfig.json │ └── vite.config.ts ├── static ├── tray.ico └── tray.png ├── tools └── city-list-generator │ ├── China-City-List-latest.csv │ └── index.mjs ├── tsconfig.json └── types.d.ts /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "Clansty", 10 | "name": "凌莞~(=^▽^=)", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/18461360?v=4", 12 | "profile": "https://0w.al", 13 | "contributions": [ 14 | "code" 15 | ] 16 | }, 17 | { 18 | "login": "luoling8192", 19 | "name": "RainbowBird", 20 | "avatar_url": "https://avatars.githubusercontent.com/u/44741987?v=4", 21 | "profile": "https://blog.luoling8192.top/", 22 | "contributions": [ 23 | "code" 24 | ] 25 | } 26 | ], 27 | "contributorsPerLine": 7, 28 | "projectName": "ClassTools", 29 | "projectOwner": "ClassToolsOfficial", 30 | "repoType": "github", 31 | "repoHost": "https://github.com", 32 | "skipCi": true 33 | } 34 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | 7 | tmp 8 | **/.tmp 9 | release 10 | 11 | .pnp.* 12 | .yarn/* 13 | !.yarn/patches 14 | !.yarn/plugins 15 | !.yarn/releases 16 | !.yarn/sdks 17 | !.yarn/versions 18 | 19 | .direnv 20 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | ClassTools -------------------------------------------------------------------------------- /.idea/ClassTools.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/discord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/git_toolbox_prj.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "arcanis.vscode-zipfs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/.yarn": true, 4 | "**/.pnp.*": true 5 | }, 6 | "typescript.tsdk": ".yarn/sdks/typescript/lib", 7 | "typescript.enablePromptUseWorkspaceTsdk": true 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "prebuild", 7 | "group": "build", 8 | "problemMatcher": [], 9 | "label": "npm: prebuild", 10 | "detail": "vue-tsc --project packages/renderer/tsconfig.json --noEmit && node scripts/build.mjs" 11 | }, 12 | { 13 | "type": "npm", 14 | "script": "debug", 15 | "problemMatcher": [], 16 | "label": "npm: debug", 17 | "detail": "npm run prebuild && vite ./packages/renderer", 18 | "group": "build" 19 | }, 20 | ] 21 | } -------------------------------------------------------------------------------- /build/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/build/app.ico -------------------------------------------------------------------------------- /electron-builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "ClassTools", 3 | "asar": false, 4 | "directories": { 5 | "output": "release" 6 | }, 7 | "files": [ 8 | "dist", 9 | "static" 10 | ], 11 | "mac": { 12 | "target": [ 13 | "dir" 14 | ] 15 | }, 16 | "win": { 17 | "icon": "build/app.ico", 18 | "target": [ 19 | { 20 | "target": "dir", 21 | "arch": [ 22 | "x64", 23 | "ia32" 24 | ] 25 | } 26 | ], 27 | "artifactName": "${productName}_${version}.${ext}" 28 | }, 29 | "nsis": { 30 | "oneClick": true, 31 | "perMachine": false, 32 | "allowToChangeInstallationDirectory": false, 33 | "deleteAppDataOnUninstall": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /introduction/gplv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/gplv3.png -------------------------------------------------------------------------------- /introduction/homework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/homework.png -------------------------------------------------------------------------------- /introduction/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/settings.png -------------------------------------------------------------------------------- /introduction/slogan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/slogan.png -------------------------------------------------------------------------------- /introduction/views.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/views.png -------------------------------------------------------------------------------- /introduction/wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/introduction/wallpaper.png -------------------------------------------------------------------------------- /privacy.md: -------------------------------------------------------------------------------- 1 | # 个人隐私策略 2 | 3 | 我们十分重视您的隐私。本隐私声明解释了我们从您那里收集的个人数据内容以及我们将如何使用这些数据。 4 | 5 | 本应用只会收集与传输以下数据,或与以下服务通信: 6 | 7 | - 设置的天气城市与和风天气的 API KEY。此数据只会发送到和风天气服务器获取天气信息 8 | - 非应用商店版本与我们的服务器通信来获取最新版本的信息 9 | -------------------------------------------------------------------------------- /scripts/build.mjs: -------------------------------------------------------------------------------- 1 | import { build } from 'vite' 2 | 3 | await build({ configFile: 'src/main/vite.config.ts' }) 4 | await build({ configFile: 'src/preload/vite.config.ts' }) 5 | await build({ configFile: 'src/renderer/vite.config.ts' }) 6 | -------------------------------------------------------------------------------- /src/main/constants.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { app } from 'electron'; 3 | 4 | export const STATIC_PATH = path.join(app.getAppPath(), 'static'); 5 | -------------------------------------------------------------------------------- /src/main/ipc/window.ts: -------------------------------------------------------------------------------- 1 | import { ipcMain, BrowserWindow } from 'electron'; 2 | import windowManager from '../utils/windowManager'; 3 | import WindowName from '../types/WindowName'; 4 | 5 | const ipcWindow = { 6 | register() { 7 | ipcMain.on('window:minimize', (event) => { 8 | const window = BrowserWindow.fromId(event.sender.id); 9 | window.minimize(); 10 | }); 11 | ipcMain.on('window:open', (event, name: WindowName) => { 12 | return windowManager.createByName(name); 13 | }); 14 | }, 15 | }; 16 | 17 | export default ipcWindow; 18 | -------------------------------------------------------------------------------- /src/main/types/WindowName.d.ts: -------------------------------------------------------------------------------- 1 | type WindowName = 'homeworkEdit' | 'homeworkView' | 'settings' | 'sloganEdit' | 'about' | 'lots'; 2 | 3 | export default WindowName; 4 | -------------------------------------------------------------------------------- /src/main/utils/createShortcuts.ts: -------------------------------------------------------------------------------- 1 | import { shell, app } from 'electron'; 2 | import path from 'path'; 3 | import * as Sentry from '@sentry/electron/main'; 4 | 5 | const shortcuts = [ 6 | { 7 | name: '作业看版', 8 | params: '--window=homeworkView', 9 | iconIndex: 1, 10 | }, 11 | { 12 | name: '作业编辑', 13 | params: '--window=homeworkEdit', 14 | iconIndex: 2, 15 | }, 16 | { 17 | name: '标语编辑', 18 | params: '--window=sloganEdit', 19 | iconIndex: 3, 20 | }, 21 | ]; 22 | 23 | export default function () { 24 | // 只有非商店版本使用这个 25 | if (process.windowsStore) return; 26 | if (process.platform !== 'win32') return; 27 | const desktopPath = app.getPath('desktop'); 28 | for (const shortcut of shortcuts) { 29 | try { 30 | const isOk = shell.writeShortcutLink(path.join(desktopPath, shortcut.name + '.lnk'), { 31 | target: process.execPath, 32 | args: shortcut.params, 33 | icon: process.execPath, 34 | iconIndex: shortcut.iconIndex, 35 | }); 36 | if (!isOk) throw new Error('快捷方式创建失败'); 37 | } 38 | catch (e) { 39 | Sentry.captureException(e); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/utils/getSettings.ts: -------------------------------------------------------------------------------- 1 | import windowManager from './windowManager'; 2 | 3 | export default async function () { 4 | const settingsJson: string = await windowManager.createWallpaperWindow().webContents 5 | .executeJavaScript('localStorage.getItem("settings");'); 6 | const settings = JSON.parse(settingsJson); 7 | return Object.freeze(settings); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { builtinModules } from 'module'; 2 | import { defineConfig } from 'vite'; 3 | import pkg from '../../package.json'; 4 | 5 | export default defineConfig({ 6 | root: __dirname, 7 | build: { 8 | outDir: '../../dist/main', 9 | lib: { 10 | entry: 'index.ts', 11 | formats: ['cjs'], 12 | fileName: () => '[name].cjs', 13 | }, 14 | minify: process.env./* from mode option */NODE_ENV === 'production', 15 | emptyOutDir: true, 16 | sourcemap: true, 17 | rollupOptions: { 18 | external: [ 19 | 'electron', 20 | 'ref-napi', 21 | 'ffi-napi', 22 | ...builtinModules, 23 | // @ts-ignore 24 | ...Object.keys(pkg.dependencies || {}), 25 | ], 26 | }, 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /src/preload/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { contextBridge, ipcRenderer } from 'electron'; 3 | import path from 'path'; 4 | 5 | // --------- Expose some API to the Renderer process. --------- 6 | contextBridge.exposeInMainWorld('fs', fs); 7 | contextBridge.exposeInMainWorld('path', path); 8 | contextBridge.exposeInMainWorld('exePath', process.execPath); 9 | contextBridge.exposeInMainWorld('isAppx', process.windowsStore); 10 | contextBridge.exposeInMainWorld('env', { ...process.env }); 11 | contextBridge.exposeInMainWorld('ipcRenderer', withPrototype(ipcRenderer)); 12 | 13 | // `exposeInMainWorld` can't detect attributes and methods of `prototype`, manually patching it. 14 | function withPrototype(obj: Record) { 15 | const protos = Object.getPrototypeOf(obj); 16 | 17 | for (const [key, value] of Object.entries(protos)) { 18 | if (Object.prototype.hasOwnProperty.call(obj, key)) continue; 19 | 20 | if (typeof value === 'function') { 21 | // Some native APIs, like `NodeJS.EventEmitter['on']`, don't work in the Renderer process. Wrapping them into a function. 22 | obj[key] = function (...args: any) { 23 | return value.call(obj, ...args); 24 | }; 25 | } 26 | else { 27 | obj[key] = value; 28 | } 29 | } 30 | return obj; 31 | } 32 | -------------------------------------------------------------------------------- /src/preload/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { builtinModules } from 'module'; 2 | import { defineConfig } from 'vite'; 3 | import pkg from '../../package.json'; 4 | 5 | export default defineConfig({ 6 | root: __dirname, 7 | build: { 8 | outDir: '../../dist/preload', 9 | lib: { 10 | entry: 'index.ts', 11 | formats: ['cjs'], 12 | fileName: () => '[name].cjs', 13 | }, 14 | minify: process.env./* from mode option */NODE_ENV === 'production', 15 | emptyOutDir: true, 16 | sourcemap: true, 17 | rollupOptions: { 18 | external: [ 19 | 'electron', 20 | ...builtinModules, 21 | // @ts-ignore 22 | ...Object.keys(pkg.dependencies || {}), 23 | ], 24 | }, 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /src/renderer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/renderer/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /src/renderer/src/assets/avatars/clansty.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/src/renderer/src/assets/avatars/clansty.webp -------------------------------------------------------------------------------- /src/renderer/src/assets/avatars/rainbowBird.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/src/renderer/src/assets/avatars/rainbowBird.webp -------------------------------------------------------------------------------- /src/renderer/src/assets/icon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/src/renderer/src/assets/icon.webp -------------------------------------------------------------------------------- /src/renderer/src/assets/icons/Close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/icons/Edit.svg: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /src/renderer/src/assets/icons/Github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/renderer/src/assets/icons/Minimize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/100.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1001.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1003.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1005.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1006.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1007.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1008.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1009.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/101.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1010.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1011.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1012.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1014.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1015.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1016.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1017.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1018.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1019.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/102.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1020.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1021.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1022.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1023.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1024.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1025.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1026.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1027.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1028.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1029.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/103.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1030.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1031.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1032.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1033.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1034.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1035.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1037.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1038.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1039.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/104.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1040.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1041.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1042.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1043.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1044.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1045.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1046.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1048.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1049.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1050.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1051.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1052.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1053.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1054.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1055.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1056.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1057.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1058.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1059.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1061.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1064.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1101.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1302.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1402.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/150.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/151.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/152.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/153.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1601.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1602.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1603.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1604.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1605.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1606.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/1607.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2001.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2002.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2003.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2004.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2005.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2006.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2007.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2008.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2009.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2010.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2011.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2012.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2013.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2014.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2015.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2016.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2017.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2020.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2022.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2023.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2024.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2025.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2026.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2027.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/2028.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/300.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/301.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/302.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/303.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/304.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/305.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/306.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/307.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/308.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/309.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/310.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/311.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/312.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/313.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/314.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/315.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/316.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/317.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/318.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/350.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/351.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/399.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/400.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/401.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/404.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/405.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/406.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/408.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/409.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/456.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/457.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/499.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/500.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/501.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/502.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/503.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/504.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/507.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/508.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/509.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/510.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/511.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/512.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/513.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/514.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/515.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/800.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/801.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/802.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/803.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/804.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/805.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/806.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/807.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/900.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/901.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/999.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/9998.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/assets/weather-icons/9999.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/renderer/src/components/DateAndCountDown.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 42 | -------------------------------------------------------------------------------- /src/renderer/src/components/DebouncedSlider.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /src/renderer/src/components/FileSelectButton.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 26 | -------------------------------------------------------------------------------- /src/renderer/src/components/FontSelector.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 27 | -------------------------------------------------------------------------------- /src/renderer/src/components/FontSizeSliderFormItem.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /src/renderer/src/components/HomeworkDisplay.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 25 | -------------------------------------------------------------------------------- /src/renderer/src/components/ScheduleDisplay.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 31 | 32 | 41 | -------------------------------------------------------------------------------- /src/renderer/src/components/SloganDisplay.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 38 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/Degree.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/Hourly.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 26 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/Props.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 31 | 32 | 41 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/RainWarning.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/Realtime.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | -------------------------------------------------------------------------------- /src/renderer/src/components/Weather/WeatherIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /src/renderer/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare module '*.vue' { 5 | import { DefineComponent } from 'vue'; 6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 7 | const component: DefineComponent<{}, {}, any>; 8 | export default component; 9 | } 10 | 11 | declare module '*.yaml' 12 | -------------------------------------------------------------------------------- /src/renderer/src/global.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare global { 4 | interface Window { 5 | // Expose some Api through preload script 6 | fs: typeof import('fs'); 7 | path: typeof import('path'); 8 | exePath: string; 9 | isAppx: string; 10 | ipcRenderer: import('electron').IpcRenderer; 11 | env: NodeJS.ProcessEnv; 12 | COMMIT_HASH: string; 13 | BUILD_DATE: number; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/renderer/src/hooks/createAutoUpdateStorage.ts: -------------------------------------------------------------------------------- 1 | import { RemovableRef, useStorage } from '@vueuse/core'; 2 | 3 | export default (name: string, initialValue: T): RemovableRef => { 4 | const storage = useStorage(name, initialValue); 5 | for (const initialValueKey in initialValue) { 6 | if (!(initialValueKey in storage.value)) { 7 | storage.value[initialValueKey] = initialValue[initialValueKey]; 8 | } 9 | } 10 | return storage; 11 | }; 12 | -------------------------------------------------------------------------------- /src/renderer/src/hooks/systemWallpaper.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue'; 2 | 3 | const fs = window.fs; 4 | const path = window.path; 5 | 6 | const APPDATA = window.env?.APPDATA; 7 | 8 | const useSystemWallpaper = () => { 9 | if (!APPDATA) return ref(''); 10 | const wallpaperPath = path.join(APPDATA, 'Microsoft', 'Windows', 'Themes', 'TranscodedWallpaper'); 11 | const wallpaperPathWeb = wallpaperPath.replace(/\\/g, '/'); 12 | const wallpaper = ref(wallpaperPathWeb); 13 | fs.watchFile(wallpaperPath, () => { 14 | wallpaper.value = wallpaperPathWeb + '?t=' + new Date().getTime(); 15 | }); 16 | return wallpaper; 17 | }; 18 | 19 | export default useSystemWallpaper; 20 | -------------------------------------------------------------------------------- /src/renderer/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import router from './router'; 3 | import App from './App.vue'; 4 | import * as Sentry from '@sentry/vue'; 5 | import { BrowserTracing } from '@sentry/tracing'; 6 | import pkg from '../../../package.json'; 7 | 8 | const app = createApp(App); 9 | 10 | app.use(router); 11 | app.mount('#app'); 12 | 13 | Sentry.init({ 14 | app, 15 | dsn: 'https://79464d2a06ec43b9a99d1d4009ce0b99@o1243132.ingest.sentry.io/6398404', 16 | integrations: [ 17 | new BrowserTracing({ 18 | routingInstrumentation: Sentry.vueRouterInstrumentation(router), 19 | }), 20 | ], 21 | release: pkg.version, 22 | // Set tracesSampleRate to 1.0 to capture 100% 23 | // of transactions for performance monitoring. 24 | // We recommend adjusting this value in production 25 | tracesSampleRate: 1.0, 26 | }); 27 | -------------------------------------------------------------------------------- /src/renderer/src/stores/homeworkHistory.ts: -------------------------------------------------------------------------------- 1 | import { useStorage } from '@vueuse/core'; 2 | import HomeworkRecord from '../types/HomeworkRecord'; 3 | 4 | const useHomeworkHistory = (date: number, homeworks: HomeworkRecord = { date, homeworks: {} }) => 5 | useStorage(`homework${date}`, homeworks); 6 | 7 | export default useHomeworkHistory; 8 | -------------------------------------------------------------------------------- /src/renderer/src/stores/homeworkHistoryList.ts: -------------------------------------------------------------------------------- 1 | import { useStorage } from '@vueuse/core'; 2 | 3 | export default useStorage('historyHomeworkList', [] as number[]); 4 | -------------------------------------------------------------------------------- /src/renderer/src/stores/homeworks.ts: -------------------------------------------------------------------------------- 1 | import createAutoUpdateStorage from '../hooks/createAutoUpdateStorage'; 2 | import HomeworkRecord from '../types/HomeworkRecord'; 3 | 4 | export default createAutoUpdateStorage('homeworks', { 5 | date: new Date().getTime(), 6 | homeworks: {}, 7 | } as HomeworkRecord); 8 | 9 | // 本来以为 useStorage 不能实时同步 localStorage 的变化,只能获取 localStorage 的初始值,然后随着输入更新 localStorage,但是实际上可以实时同步 localStorage 的变化。 10 | // 所以本来是准备用 pinia 然后自己写一个 pinia 的插件来同步 localStorage,现在不需要了,直接用 useStorage 就可以了。 11 | -------------------------------------------------------------------------------- /src/renderer/src/stores/lotsSettings.ts: -------------------------------------------------------------------------------- 1 | import createAutoUpdateStorage from '../hooks/createAutoUpdateStorage'; 2 | 3 | export default createAutoUpdateStorage('lotsSettings', { 4 | min: 1, 5 | max: 50, 6 | count: 10, 7 | }); 8 | -------------------------------------------------------------------------------- /src/renderer/src/stores/slogan.ts: -------------------------------------------------------------------------------- 1 | import createAutoUpdateStorage from '../hooks/createAutoUpdateStorage'; 2 | 3 | export default createAutoUpdateStorage('slogan', { 4 | content: '', 5 | author: '', 6 | // 这里的大小以 em 为单位 7 | size: 2, 8 | authorSize: 2, 9 | color: '#ff0000', 10 | authorColor: '#303133', 11 | font: '"Microsoft Yahei", "MicrosoftJhengHei", sans-serif', 12 | }); 13 | -------------------------------------------------------------------------------- /src/renderer/src/types/HomeworkRecord.d.ts: -------------------------------------------------------------------------------- 1 | export default interface HomeworkRecord { 2 | date: number; 3 | homeworks: { [subject: string]: string }; 4 | } 5 | -------------------------------------------------------------------------------- /src/renderer/src/utils/getTime.ts: -------------------------------------------------------------------------------- 1 | // 获取从今天 0 点到现在的秒数 2 | export default (time: Date | string) => { 3 | if (typeof time === 'object') { 4 | return time.getHours() * 60 * 60 + time.getMinutes() * 60 + time.getSeconds(); 5 | } 6 | if (/^(\d+):(\d+)$/.test(time)) { 7 | time += ':00'; 8 | } 9 | const exec = /(\d+):(\d+):(\d+)/.exec(time); 10 | const hours = Number(exec[1]); 11 | const minutes = Number(exec[2]); 12 | const seconds = Number(exec[3]); 13 | return hours * 60 * 60 + minutes * 60 + seconds; 14 | }; 15 | -------------------------------------------------------------------------------- /src/renderer/src/utils/newDay.ts: -------------------------------------------------------------------------------- 1 | import useHistoryHomeworks from '../stores/homeworkHistory'; 2 | import homeworks from '../stores/homeworks'; 3 | import historyHomeworkList from '../stores/homeworkHistoryList'; 4 | 5 | export default () => { 6 | useHistoryHomeworks(homeworks.value.date, homeworks.value); 7 | historyHomeworkList.value.push(homeworks.value.date); 8 | homeworks.value = { 9 | date: new Date().getTime(), 10 | homeworks: {}, 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /src/renderer/src/utils/parseNamelist.ts: -------------------------------------------------------------------------------- 1 | export default (namesStr: string) => { 2 | return namesStr.split(/[\s\n]/) 3 | .filter(them => !!them) 4 | .filter(them => !['姓名'].includes(them)); 5 | } 6 | -------------------------------------------------------------------------------- /src/renderer/src/utils/random.ts: -------------------------------------------------------------------------------- 1 | const random = { 2 | int(min: number, max: number) { 3 | min = Math.ceil(min); 4 | max = Math.floor(max); 5 | return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 6 | }, 7 | pick(...array: T[]) { 8 | const index = random.int(0, array.length - 1); 9 | return array[index]; 10 | }, 11 | shuffle(arr: T[]) { 12 | let i = arr.length; 13 | while (i) { 14 | const j = Math.floor(Math.random() * i--); 15 | [arr[j], arr[i]] = [arr[i], arr[j]]; 16 | } 17 | return arr; 18 | }, 19 | }; 20 | 21 | export default random; 22 | -------------------------------------------------------------------------------- /src/renderer/src/utils/sendHomeworkWebhook.ts: -------------------------------------------------------------------------------- 1 | import settings from '../stores/settings'; 2 | import { NotificationApiInjection } from 'naive-ui/es/notification/src/NotificationProvider'; 3 | import storeHomeworks from '../stores/homeworks'; 4 | import { formatDate } from '@vueuse/core'; 5 | 6 | export default async (notification: NotificationApiInjection, isDebug = false) => { 7 | if (!settings.value.homeworkWebHookUrl) return; 8 | if (!Object.entries(storeHomeworks.value).length) return; 9 | try { 10 | const homeworks = Object.entries(storeHomeworks.value.homeworks) 11 | .filter(([subject, content]) => content) 12 | .map(([subject, content]) => subject + ':\n' + content) 13 | .join('\n\n'); 14 | const body = settings.value.homeworkWebHookContent.replaceAll('${}', 15 | `${formatDate(new Date(storeHomeworks.value.date), 'YYYY/MM/DD')} 日作业\n` + homeworks); 16 | const res = await fetch(settings.value.homeworkWebHookUrl, { 17 | headers: { 'Content-Type': 'application/json' }, 18 | method: 'POST', 19 | body, 20 | }); 21 | if (!res.ok) { 22 | throw new Error(await res.text()); 23 | } 24 | if (isDebug) { 25 | notification.success({ 26 | content: await res.text(), 27 | title: '测试成功', 28 | duration: 10000, 29 | }); 30 | } 31 | } 32 | catch (e) { 33 | console.log(e); 34 | notification.error({ 35 | content: e.message, 36 | title: '错误', 37 | duration: 10000, 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/renderer/src/utils/supportedFonts.ts: -------------------------------------------------------------------------------- 1 | // https://www.zhangxinxu.com/wordpress/2018/02/js-detect-suppot-font-family/ 2 | const isSupportFontFamily = (f: string) => { 3 | const h = 'Arial'; 4 | if (f.toLowerCase() == h.toLowerCase()) { 5 | return true; 6 | } 7 | const e = 'a'; 8 | const d = 100; 9 | const a = 100, i = 100; 10 | const c = document.createElement('canvas'); 11 | const b = c.getContext('2d'); 12 | c.width = a; 13 | c.height = i; 14 | b.textAlign = 'center'; 15 | b.fillStyle = 'black'; 16 | b.textBaseline = 'middle'; 17 | const g = function (j) { 18 | b.clearRect(0, 0, a, i); 19 | b.font = d + 'px ' + j + ', ' + h; 20 | b.fillText(e, a / 2, i / 2); 21 | const k = b.getImageData(0, 0, a, i).data; 22 | return [].slice.call(k).filter(function (l) { 23 | return l != 0; 24 | }); 25 | }; 26 | return g(h).join('') !== g(f).join(''); 27 | }; 28 | 29 | const fonts = { 30 | 'PingFang SC': '苹方', 31 | STHeiti: '华文黑体', 32 | STXihei: '华文细黑', 33 | STKaiti: '华文楷体', 34 | STSong: '华文宋体', 35 | STLiti: '华文隶书', 36 | STXingkai: '华文行楷', 37 | 'Microsoft Yahei': '微软雅黑', 38 | 'Microsoft JhengHei': '微软正黑', 39 | SimSun: '宋体', 40 | SimHei: '黑体', 41 | KaiTi: '楷体', 42 | YouYuan: '幼圆', 43 | LiSu: '隶书', 44 | 'Source Han Sans CN': '思源黑体', 45 | 'Source Han Serif SC': '思源宋体', 46 | }; 47 | 48 | const supportedFonts = Object.fromEntries( 49 | Object.entries(fonts) 50 | .filter(([id, name]) => isSupportFontFamily(id)), 51 | ); 52 | 53 | export default supportedFonts; 54 | -------------------------------------------------------------------------------- /src/renderer/src/views/Demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 29 | 30 | 36 | -------------------------------------------------------------------------------- /src/renderer/src/views/HomeworkHistory.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 39 | -------------------------------------------------------------------------------- /src/renderer/src/views/HomeworkHistoryView.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 34 | -------------------------------------------------------------------------------- /src/renderer/src/views/Settings.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 31 | -------------------------------------------------------------------------------- /src/renderer/src/views/settings/Countdown.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /src/renderer/src/views/settings/Lessons.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | -------------------------------------------------------------------------------- /src/renderer/src/views/settings/Namelist.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /src/renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "useDefineForClassFields": true, 6 | "module": "esnext", 7 | "moduleResolution": "node", 8 | "jsx": "preserve", 9 | "jsxFactory": "h", 10 | "jsxFragmentFactory": "Fragment", 11 | "sourceMap": true, 12 | "resolveJsonModule": true, 13 | "esModuleInterop": true, 14 | "lib": [ 15 | "esnext", 16 | "dom" 17 | ] 18 | }, 19 | "include": [ 20 | "src/**/*.ts", 21 | "src/**/*.d.ts", 22 | "src/**/*.tsx", 23 | "src/**/*.vue" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /static/tray.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/static/tray.ico -------------------------------------------------------------------------------- /static/tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clansty/ClassTools/6507f27058c76d65fc58dce2089976874bde9a68/static/tray.png -------------------------------------------------------------------------------- /tools/city-list-generator/index.mjs: -------------------------------------------------------------------------------- 1 | import fsP from 'fs/promises'; 2 | 3 | const csvText = await fsP.readFile('./tools/city-list-generator/China-City-List-latest.csv', 'utf8'); 4 | // 前两行不是数据 5 | const csv = csvText.split('\n') 6 | .splice(2) 7 | .filter(it => it) 8 | .map(row => row.split(',')); 9 | 10 | // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 11 | // 101010100,Beijing,北京,CN,China,中国,Beijing,北京市,Beijing,北京市,Asia/Shanghai,39.904987,116.405289,110000 12 | 13 | const result = []; 14 | 15 | for (const row of csv) { 16 | // 省 17 | let province = result.find(it => it.value === row[6]); 18 | if (!province) { 19 | province = { 20 | label: row[7], 21 | value: row[6], 22 | children: [], 23 | }; 24 | result.push(province); 25 | } 26 | 27 | // 市 28 | // 直辖市可以不用增加一级 29 | let city = row[6] === row[8] ? province : province.children.find(it => it.value === `${row[6]}-${row[8]}`); 30 | if (!city) { 31 | city = { 32 | label: row[9], 33 | value: `${row[6]}-${row[8]}`, 34 | children: [], 35 | }; 36 | province.children.push(city); 37 | } 38 | 39 | // 地区 40 | city.children.push({ 41 | label: row[2], 42 | value: row[3] + row[0], 43 | }); 44 | } 45 | 46 | await fsP.writeFile('./src/renderer/src/data/cities.json', JSON.stringify(result, undefined, 2), 'utf8'); 47 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "importHelpers": true, 7 | "jsx": "preserve", 8 | "esModuleInterop": true, 9 | "resolveJsonModule": true, 10 | "sourceMap": true, 11 | "baseUrl": "./", 12 | "paths": {}, 13 | "allowSyntheticDefaultImports": true, 14 | "skipLibCheck": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /types.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare namespace NodeJS { 3 | interface ProcessEnv { 4 | NODE_ENV: 'development' | 'production' 5 | readonly VITE_DEV_SERVER_HOST: string 6 | readonly VITE_DEV_SERVER_PORT: string 7 | } 8 | } 9 | --------------------------------------------------------------------------------