├── electron ├── fallback.html ├── icon.txt ├── preload.js ├── check-environment.js └── static-server.js ├── pnpm-workspace.yaml ├── public ├── logo │ ├── Qwen.jpg │ └── Deepseek.jpg └── quiz │ └── banks │ └── manage │ └── index.html ├── resources └── icon.jpg ├── postcss.config.mjs ├── src ├── lib │ ├── utils.ts │ └── deepseek.ts ├── app │ ├── quiz │ │ ├── banks │ │ │ ├── [bankId] │ │ │ │ └── layout.tsx │ │ │ └── manage │ │ │ │ ├── index.html │ │ │ │ └── index │ │ │ │ └── page.tsx │ │ ├── review │ │ │ └── practice │ │ │ │ └── page.tsx │ │ ├── page.tsx │ │ ├── layout.tsx │ │ ├── settings │ │ │ └── page.tsx │ │ └── import-export │ │ │ └── page.tsx │ ├── layout.tsx │ ├── page.tsx │ ├── api │ │ └── ai │ │ │ ├── deepseek │ │ │ └── route.ts │ │ │ └── alibaba │ │ │ └── route.ts │ └── globals.css ├── utils │ ├── array.ts │ └── quiz.ts ├── types │ ├── electron.d.ts │ └── quiz.ts ├── store │ ├── themeStore.ts │ └── quizStore.ts ├── components │ ├── ui │ │ ├── textarea.tsx │ │ ├── progress.tsx │ │ ├── input.tsx │ │ ├── checkbox.tsx │ │ ├── badge.tsx │ │ ├── scroll-area.tsx │ │ ├── alert.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── dialog.tsx │ │ └── select.tsx │ ├── ThemeSwitcher.tsx │ ├── CreateBankModal.tsx │ ├── NumQuestionsModal.tsx │ ├── quiz │ │ ├── WrongQuestionItem.tsx │ │ └── SimilarQuestionsModal.tsx │ └── QuestionFormModal.tsx ├── hooks │ └── useElectron.ts └── constants │ ├── quiz.ts │ └── ai.ts ├── .eslintrc.json ├── tailwind.config.js ├── .npmrc ├── next.config.ts ├── eslint.config.mjs ├── components.json ├── .gitignore ├── tsconfig.json ├── offline-electron.md ├── generate ├── build-mac.sh ├── build-linux.sh ├── build-win.sh ├── README.md └── build-all.sh ├── tauri-guide.md ├── LICENSE ├── README.md └── package.json /electron/fallback.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "." 3 | # 如果有子包或其他目录需要管理,可以在这里添加 4 | # - "packages/*" -------------------------------------------------------------------------------- /public/logo/Qwen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KurodaKayn/AHF-QDS-EOE/HEAD/public/logo/Qwen.jpg -------------------------------------------------------------------------------- /resources/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KurodaKayn/AHF-QDS-EOE/HEAD/resources/icon.jpg -------------------------------------------------------------------------------- /public/logo/Deepseek.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KurodaKayn/AHF-QDS-EOE/HEAD/public/logo/Deepseek.jpg -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "@typescript-eslint/no-explicit-any": "off", 5 | "@typescript-eslint/no-unused-vars": "off", 6 | "react-hooks/exhaustive-deps": "warn" 7 | } 8 | } -------------------------------------------------------------------------------- /src/app/quiz/banks/[bankId]/layout.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 为静态导出生成路径参数 3 | * 由于这是服务器组件,因此服务端生成的参数用于静态导出 4 | */ 5 | export function generateStaticParams() { 6 | return [{ bankId: 'default' }]; 7 | } 8 | 9 | export default function BankLayout({ children }: { children: React.ReactNode }) { 10 | return <>{children}; 11 | } -------------------------------------------------------------------------------- /src/app/quiz/banks/manage/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 题库管理 7 | 8 | 9 |

正在跳转到题库管理页面...

10 | 13 | 14 | -------------------------------------------------------------------------------- /src/utils/array.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 使用Fisher-Yates算法对数组进行原地洗牌。 3 | * @param array 要洗牌的数组。 4 | * @returns 洗牌后的数组(相同实例)。 5 | */ 6 | export function shuffleArray(array: T[]): T[] { 7 | for (let i = array.length - 1; i > 0; i--) { 8 | const j = Math.floor(Math.random() * (i + 1)); 9 | [array[i], array[j]] = [array[j], array[i]]; // 交换元素 10 | } 11 | return array; 12 | } -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 5 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 7 | ], 8 | darkMode: 'class', 9 | theme: { 10 | extend: {}, 11 | }, 12 | plugins: [ 13 | require('@tailwindcss/typography'), 14 | ], 15 | }; -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | electron_mirror=https://npmmirror.com/mirrors/electron/ 2 | ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ 3 | registry=https://registry.npmmirror.com/ 4 | electron-builder-binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ 5 | 6 | # pnpm配置 7 | node-linker=hoisted 8 | strict-peer-dependencies=false 9 | shamefully-hoist=true 10 | # 可选:如果你希望使用 workspace 功能 11 | # use-node-version=18.x -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | // 恢复静态导出设置 6 | output: 'export', 7 | distDir: 'out', 8 | // 启用图片优化 9 | images: { 10 | unoptimized: true, 11 | }, 12 | // 禁用React严格模式以避免Electron中的一些问题 13 | reactStrictMode: false, 14 | // 导出时生成基于路由的HTML文件 15 | trailingSlash: true, 16 | }; 17 | 18 | export default nextConfig; 19 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /electron/icon.txt: -------------------------------------------------------------------------------- 1 | Electron应用图标说明: 2 | 3 | 为了给应用添加图标,请按照以下步骤操作: 4 | 5 | 1. 创建一个名为"build"的文件夹在项目根目录 6 | 2. 添加以下图标文件到build文件夹: 7 | - icon.icns (macOS, 大小至少为512x512像素) 8 | - icon.ico (Windows, 大小建议为256x256像素) 9 | - icon.png (通用, 大小至少为512x512像素) 10 | 11 | 这些图标将被electron-builder自动识别并用于构建过程。 12 | 13 | 图标可以使用图像编辑软件创建,如Photoshop, GIMP或在线工具如: 14 | - https://www.electron.build/icons.html (官方说明) 15 | - https://cloudconvert.com/png-to-icns (转换PNG到ICNS) 16 | - https://cloudconvert.com/png-to-ico (转换PNG到ICO) 17 | 18 | 注意: 确保图标分辨率足够高,以提供良好的显示效果。 -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /src/app/quiz/banks/manage/index/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useEffect } from 'react'; 4 | import { useRouter } from 'next/navigation'; 5 | 6 | export default function ManageBankIndexRedirect() { 7 | const router = useRouter(); 8 | 9 | useEffect(() => { 10 | if (typeof window !== 'undefined') { 11 | // 重定向到上级目录 12 | router.replace('/quiz/banks/manage/'); 13 | } 14 | }, [router]); 15 | 16 | return ( 17 |
18 |

重定向中...

19 |
20 | ); 21 | } -------------------------------------------------------------------------------- /src/types/electron.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Electron API 类型声明 3 | * 为Electron在渲染进程中提供的API定义接口 4 | */ 5 | interface ElectronAPI { 6 | /** 7 | * 发送消息到主进程 8 | * @param channel 通信通道名称 9 | * @param data 要发送的数据 10 | */ 11 | sendMessage: (channel: string, data: any) => void; 12 | 13 | /** 14 | * 接收来自主进程的消息 15 | * @param channel 通信通道名称 16 | * @param func 处理接收到消息的回调函数 17 | */ 18 | receiveMessage: (channel: string, func: (...args: any[]) => void) => void; 19 | } 20 | 21 | declare global { 22 | interface Window { 23 | /** 24 | * 通过preload脚本暴露的Electron API 25 | */ 26 | electron: ElectronAPI; 27 | } 28 | } -------------------------------------------------------------------------------- /src/store/themeStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { persist } from 'zustand/middleware'; 3 | 4 | type Theme = 'light' | 'dark'; 5 | 6 | interface ThemeState { 7 | theme: Theme; 8 | toggleTheme: () => void; 9 | setTheme: (theme: Theme) => void; 10 | } 11 | 12 | /** 13 | * 主题状态管理 14 | */ 15 | export const useThemeStore = create()( 16 | persist( 17 | (set) => ({ 18 | theme: 'light', 19 | toggleTheme: () => set((state) => ({ 20 | theme: state.theme === 'light' ? 'dark' : 'light' 21 | })), 22 | setTheme: (theme) => set({ theme }), 23 | }), 24 | { 25 | name: 'theme-storage', 26 | } 27 | ) 28 | ); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | /.pnp 4 | .pnp.* 5 | .yarn/* 6 | !.yarn/patches 7 | !.yarn/plugins 8 | !.yarn/releases 9 | !.yarn/versions 10 | .pnpm-store/ 11 | .pnpm-debug.log* 12 | pnpm-lock.yaml 13 | 14 | # testing 15 | /coverage 16 | 17 | # next.js 18 | .next/ 19 | out/ 20 | 21 | # production 22 | build/ 23 | dist/ 24 | 25 | # misc 26 | .DS_Store 27 | *.pem 28 | 29 | # debug 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | .pnpm-debug.log* 34 | 35 | # env files (can opt-in for committing if needed) 36 | Frontend/.env* 37 | 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | 43 | #executable files 44 | *.exe 45 | *.exe~ 46 | *.dll 47 | *.so 48 | *.dylib 49 | *.test 50 | *.out 51 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |