├── .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 |
--------------------------------------------------------------------------------