├── .gitignore ├── docker-compose.yml ├── postcss.config.js ├── nginx.conf ├── vitest.config.ts ├── Dockerfile ├── tailwind.config.js ├── vite.config.ts ├── index.html ├── ARCHITECTURE.md ├── tsconfig.json ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules] 2 | dist 3 | .vscode 4 | .DS_Store 5 | .env 6 | .env.local 7 | coverage 8 | pnpm-lock.yaml 9 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | web: 5 | build: . 6 | ports: 7 | - "8080:80" 8 | restart: unless-stopped 9 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /** WARNING: DON'T EDIT THIS FILE */ 2 | /** WARNING: DON'T EDIT THIS FILE */ 3 | /** WARNING: DON'T EDIT THIS FILE */ 4 | 5 | export default { 6 | plugins: { 7 | tailwindcss: {}, 8 | autoprefixer: {}, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | location /txt/ { 6 | alias /usr/share/nginx/html/; 7 | index index.html; 8 | try_files $uri $uri/ /txt/index.html; 9 | } 10 | 11 | error_page 500 502 503 504 /50x.html; 12 | location = /50x.html { 13 | root /usr/share/nginx/html; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | export default defineConfig({ 5 | plugins: [react()], 6 | test: { 7 | environment: 'jsdom', 8 | globals: true, 9 | setupFiles: './src/setupTests.ts', 10 | coverage: { 11 | reporter: ['text', 'json', 'html'], 12 | }, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:20-alpine AS build 3 | WORKDIR /app 4 | COPY package.json pnpm-lock.yaml ./ 5 | RUN npm install -g pnpm && pnpm install 6 | COPY . . 7 | RUN pnpm build 8 | 9 | # Production stage 10 | FROM nginx:alpine 11 | COPY --from=build /app/dist/static /usr/share/nginx/html 12 | COPY nginx.conf /etc/nginx/conf.d/default.conf 13 | EXPOSE 80 14 | CMD ["nginx", "-g", "daemon off;"] 15 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** WARNING: DON'T EDIT THIS FILE */ 2 | /** WARNING: DON'T EDIT THIS FILE */ 3 | /** WARNING: DON'T EDIT THIS FILE */ 4 | 5 | /** @type {import('tailwindcss').Config} */ 6 | 7 | export default { 8 | darkMode: "class", 9 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], 10 | theme: { 11 | container: { 12 | center: true, 13 | }, 14 | extend: {}, 15 | }, 16 | plugins: [], 17 | }; 18 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | /** WARNING: DON'T EDIT THIS FILE */ 2 | /** WARNING: DON'T EDIT THIS FILE */ 3 | /** WARNING: DON'T EDIT THIS FILE */ 4 | 5 | import { defineConfig } from "vite"; 6 | import react from "@vitejs/plugin-react"; 7 | import tsconfigPaths from "vite-tsconfig-paths"; 8 | 9 | function getPlugins() { 10 | const plugins = [react(), tsconfigPaths()]; 11 | return plugins; 12 | } 13 | 14 | export default defineConfig({ 15 | plugins: getPlugins(), 16 | }); 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 极简笔记本 7 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ARCHITECTURE.md: -------------------------------------------------------------------------------- 1 | # 项目架构文档 2 | 3 | ## 整体架构 4 | 应用采用前后端分离架构,前端使用React构建,数据存储在浏览器本地存储中。 5 | 6 | ## 技术架构图 7 | ``` 8 | 浏览器客户端(React) ↔ 本地存储(IndexedDB/localStorage) 9 | ``` 10 | 11 | ## 核心模块 12 | 13 | ### 1. 笔记管理模块 14 | - 负责笔记的创建、编辑和保存 15 | - 使用localStorage持久化数据 16 | - 自动保存机制 17 | 18 | ### 2. 路由模块 19 | - 基于react-router-dom 20 | - 动态路由匹配笔记ID 21 | - 默认重定向逻辑 22 | 23 | ### 3. 主题模块 24 | - 支持暗黑/明亮主题 25 | - 使用CSS变量实现主题切换 26 | - 主题状态持久化 27 | 28 | ### 4. 分享模块 29 | - 生成随机笔记ID 30 | - 复制笔记链接功能 31 | 32 | ## 数据流 33 | 1. 用户输入 → 笔记内容更新 → 自动保存到localStorage 34 | 2. 主题切换 → 更新CSS变量 → 保存到localStorage 35 | 36 | ## 性能优化 37 | - 使用React.memo优化组件渲染 38 | - 按需加载组件 39 | - 生产环境代码压缩 40 | 41 | ## 测试策略 42 | - 单元测试: 核心工具函数 43 | - 组件测试: 关键UI组件 44 | - E2E测试: 用户工作流 45 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /** WARNING: DON'T EDIT THIS FILE */ 2 | /** WARNING: DON'T EDIT THIS FILE */ 3 | /** WARNING: DON'T EDIT THIS FILE */ 4 | 5 | { 6 | "compilerOptions": { 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | "target": "ES2020", 9 | "useDefineForClassFields": true, 10 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 11 | "module": "ESNext", 12 | "skipLibCheck": true, 13 | 14 | /* Bundler mode */ 15 | "moduleResolution": "bundler", 16 | "allowImportingTsExtensions": true, 17 | "isolatedModules": true, 18 | "moduleDetection": "force", 19 | "noEmit": true, 20 | "jsx": "react-jsx", 21 | 22 | /* Linting */ 23 | "strict": true, 24 | "noUnusedLocals": true, 25 | "noUnusedParameters": true, 26 | "noFallthroughCasesInSwitch": true, 27 | "noUncheckedSideEffectImports": true, 28 | 29 | /* Paths */ 30 | "baseUrl": "./", 31 | "paths": { 32 | "@/*": ["./src/*"] 33 | } 34 | }, 35 | "include": ["src"] 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "minimal-notebook", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "一个极简的在线笔记本应用,支持自动保存、主题切换和链接分享功能", 6 | "type": "module", 7 | "scripts": { 8 | "dev:client": "vite --host --port 3000", 9 | "dev": "pnpm dev:client", 10 | "build:client": "vite build --outDir dist/static", 11 | "build": "rm -rf dist && pnpm build:client && cp package.json dist && touch dist/build.flag", 12 | "test": "vitest", 13 | "test:watch": "vitest watch", 14 | "test:coverage": "vitest run --coverage" 15 | }, 16 | "dependencies": { 17 | "clsx": "^2.1.1", 18 | "framer-motion": "^12.9.2", 19 | "react": "^18.3.1", 20 | "react-dom": "^18.3.1", 21 | "react-error-boundary": "^4.0.13", 22 | "react-router-dom": "^7.3.0", 23 | "recharts": "^2.15.1", 24 | "sonner": "^2.0.2", 25 | "tailwind-merge": "^3.0.2", 26 | 27 | "zod": "^3.24.2" 28 | }, 29 | "devDependencies": { 30 | "@testing-library/jest-dom": "^6.4.2", 31 | "@testing-library/react": "^14.2.1", 32 | "@testing-library/user-event": "^14.5.1", 33 | "@types/react": "^18.3.12", 34 | "@types/react-dom": "^18.3.1", 35 | "@vitejs/plugin-react": "^4.3.4", 36 | "autoprefixer": "^10.4.21", 37 | "jsdom": "^24.0.0", 38 | "postcss": "^8.5.3", 39 | "tailwindcss": "^3.4.17", 40 | "typescript": "~5.7.2", 41 | "vite": "^6.2.0", 42 | "vitest": "^1.5.0", 43 | "vite-tsconfig-paths": "^5.1.4" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 极简笔记本应用 2 | 3 | 一个基于React的极简在线笔记本应用,支持自动保存、主题切换和笔记关联功能,数据存储在浏览器本地存储中。 4 | 5 | ## 功能特性 6 | 7 | - 📝 极简笔记编辑 - 专注于写作的简洁界面 8 | - 💾 自动保存 - 内容实时保存到本地存储 9 | - 🌗 主题切换 - 支持明亮/暗黑主题 10 | - 🔗 笔记关联 - 可以关联相关笔记 11 | - 📋 链接分享 - 一键复制笔记链接 12 | - 🆕 笔记创建 - 快速创建新笔记 13 | 14 | ## 技术栈 15 | 16 | - 前端: React 18 + TypeScript 17 | - 样式: Tailwind CSS 18 | - 路由: react-router-dom 19 | - 图标: Font Awesome 20 | - 构建: Vite 21 | 22 | ## 快速开始 23 | 24 | ### 开发环境 25 | 26 | 1. 确保已安装Node.js (v18+) 27 | 2. 克隆仓库: 28 | ```bash 29 | git clone <仓库地址> 30 | ``` 31 | 3. 安装依赖: 32 | ```bash 33 | npm install 34 | ``` 35 | 4. 启动开发服务器: 36 | ```bash 37 | npm run dev 38 | ``` 39 | 5. 访问 http://localhost:3000 40 | 41 | ### 生产构建 42 | 43 | ```bash 44 | npm run build 45 | ``` 46 | 47 | 构建产物将生成在 `dist/static` 目录。 48 | 49 | ## 项目结构 50 | 51 | ``` 52 | ├── src 53 | │ ├── App.tsx # 应用根组件 54 | │ ├── components # 公共组件 55 | │ ├── hooks # 自定义Hook 56 | │ ├── lib # 工具函数和API 57 | │ ├── pages # 页面组件 58 | │ └── index.css # 全局样式 59 | ├── vite.config.ts # Vite配置 60 | └── tailwind.config.js # Tailwind配置 61 | ``` 62 | 63 | ## 特色功能使用指南 64 | 65 | ### 创建新笔记 66 | 67 | 点击右上角"新建"按钮,可以创建新笔记。系统会自动生成4位随机ID作为路径。 68 | 69 | ### 关联笔记 70 | 71 | 1. 点击"关联"按钮 72 | 2. 输入要关联的笔记路径或完整URL 73 | 3. 确认后两篇笔记将建立双向关联 74 | 75 | ### 主题切换 76 | 77 | 点击右上角主题切换按钮,可以在明亮/暗黑主题间切换,设置会自动保存。 78 | 79 | ## 部署 80 | 81 | ### Docker部署 82 | 83 | ```bash 84 | docker-compose up --build 85 | ``` 86 | 87 | 应用将在 http://localhost:8080 可用 88 | 89 | ## 许可证 90 | 91 | MIT 92 | --------------------------------------------------------------------------------