添加复制和下载按钮,统计字数功能
This commit is contained in:
70
.dockerignore
Normal file
70
.dockerignore
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Node.js 相关
|
||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# 源代码和开发文件(精简版不需要)
|
||||||
|
src
|
||||||
|
scripts
|
||||||
|
public
|
||||||
|
package*.json
|
||||||
|
vite.config.js
|
||||||
|
eslint.config.js
|
||||||
|
index.html
|
||||||
|
|
||||||
|
# 构建相关
|
||||||
|
dist
|
||||||
|
.vite
|
||||||
|
|
||||||
|
# 环境文件
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# IDE/Editor files
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Docker 相关(保留 Dockerfile)
|
||||||
|
docker-compose.yml
|
||||||
|
|
||||||
|
# 脚本文件(精简版不需要)
|
||||||
|
docker-entrypoint.sh
|
||||||
|
|
||||||
|
# 文档
|
||||||
|
README*.md
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# ESLint cache
|
||||||
|
.eslintcache
|
||||||
50
Dockerfile
Normal file
50
Dockerfile
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# 极简静态资源镜像
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# 安装 wget 用于健康检查
|
||||||
|
RUN apk add --no-cache wget
|
||||||
|
|
||||||
|
# 极简静态资源镜像
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# 安装 wget 用于健康检查
|
||||||
|
RUN apk add --no-cache wget
|
||||||
|
|
||||||
|
# 创建自定义 nginx 配置,禁用缓存并确保正确读取挂载目录
|
||||||
|
RUN printf 'server {\n\
|
||||||
|
listen 80;\n\
|
||||||
|
server_name localhost;\n\
|
||||||
|
root /usr/share/nginx/html;\n\
|
||||||
|
index index.html index.htm;\n\
|
||||||
|
\n\
|
||||||
|
# 禁用缓存\n\
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";\n\
|
||||||
|
add_header Pragma "no-cache";\n\
|
||||||
|
add_header Expires "0";\n\
|
||||||
|
\n\
|
||||||
|
location / {\n\
|
||||||
|
try_files $uri $uri/ /index.html;\n\
|
||||||
|
# 确保每次都读取最新文件\n\
|
||||||
|
sendfile off;\n\
|
||||||
|
tcp_nodelay on;\n\
|
||||||
|
tcp_nopush off;\n\
|
||||||
|
}\n\
|
||||||
|
\n\
|
||||||
|
# 禁用所有静态文件缓存\n\
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {\n\
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";\n\
|
||||||
|
add_header Pragma "no-cache";\n\
|
||||||
|
add_header Expires "0";\n\
|
||||||
|
}\n\
|
||||||
|
}\n' > /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# 确保挂载目录存在但为空(避免与外部挂载冲突)
|
||||||
|
RUN mkdir -p /usr/share/nginx/html && \
|
||||||
|
rm -rf /usr/share/nginx/html/* && \
|
||||||
|
echo "Waiting for external mount..." > /usr/share/nginx/html/.placeholder
|
||||||
|
|
||||||
|
# 暴露静态服务端口
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# 启动 nginx 前台运行
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
159
README.en.md
159
README.en.md
@@ -1,159 +0,0 @@
|
|||||||
# Markdown To Web
|
|
||||||
|
|
||||||
> Turn a local Markdown notes folder into a deployable static React site.
|
|
||||||
|
|
||||||
This project scans all `.md` files inside `public/mengyanote/`, generates JSON datasets (directory tree, file contents, stats) at build time, and renders them client‑side with React + `react-markdown`. The output is a **pure static site** (no server / no DB) suitable for GitHub Pages, Netlify, Vercel, or any static hosting.
|
|
||||||
|
|
||||||
Chinese documentation: see `README.md`.
|
|
||||||
|
|
||||||
## ✨ Features
|
|
||||||
|
|
||||||
- 🚀 One‑command data generation (recursive scan → JSON assets)
|
|
||||||
- 📦 Fully static deployment (no runtime backend needed)
|
|
||||||
- 🧭 Expandable directory tree with stable IDs / paths
|
|
||||||
- 📝 Rich Markdown: GFM (tables, task lists, strikethrough), soft line breaks, math (KaTeX), code highlighting
|
|
||||||
- 🧮 Math via `remark-math` + `rehype-katex`
|
|
||||||
- 💡 Enhanced code blocks: language label + copy button
|
|
||||||
- 📚 Breadcrumb navigation derived from file path
|
|
||||||
- 🔌 Pluggable remark / rehype pipeline (easy to remove / replace)
|
|
||||||
- 🕶 Dark theme (fully customizable via CSS)
|
|
||||||
- 🔍 Multi-path fallback when fetching generated JSON (`/data` → `/src/data` → `./data`)
|
|
||||||
- 🧯 Ignore mechanism via `ignore.json`
|
|
||||||
- 📊 Basic statistics (file count, folder count, timestamp)
|
|
||||||
|
|
||||||
## 🛠 Tech Stack
|
|
||||||
|
|
||||||
- React 19 + Hooks + Context
|
|
||||||
- Vite
|
|
||||||
- `react-markdown` + remark / rehype plugins:
|
|
||||||
- `remark-gfm`, `remark-math`, `remark-breaks`
|
|
||||||
- `rehype-raw`, `rehype-katex`, `rehype-highlight`
|
|
||||||
- Highlight.js theme (replaceable)
|
|
||||||
- KaTeX (optional)
|
|
||||||
|
|
||||||
## ⚡ Quick Start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install
|
|
||||||
npm run dev # generate data + start dev server
|
|
||||||
npm run build # generate data + build static site (dist/)
|
|
||||||
npm run preview # preview production build
|
|
||||||
npm run generate-data # only regenerate JSON
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📂 Key Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
public/
|
|
||||||
mengyanote/ # Source Markdown tree (add your .md here)
|
|
||||||
data/ # Public copy of generated JSON
|
|
||||||
scripts/
|
|
||||||
generateData.js # Node script: scans + emits JSON
|
|
||||||
src/
|
|
||||||
data/ # Generated JSON (consumed in dev/build)
|
|
||||||
components/ # UI (MarkdownRenderer, Sidebar, ...)
|
|
||||||
context/ # AppContext (state + actions)
|
|
||||||
utils/fileUtils.js # Fetch + helpers + breadcrumbs
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🧬 How It Works
|
|
||||||
|
|
||||||
1. `generateData.js` walks `public/mengyanote/` (applying `ignore.json` rules)
|
|
||||||
2. Builds:
|
|
||||||
- `directoryTree.json` (hierarchical tree)
|
|
||||||
- `fileContents.json` (path → raw markdown text)
|
|
||||||
- `stats.json` (counts + timestamp)
|
|
||||||
3. Writes duplicates to `src/data/` (for imports / dev) and `public/data/` (for runtime fetch in final build)
|
|
||||||
4. Frontend loads JSON (tries `/data` → `/src/data` → `./data`) and renders selected file
|
|
||||||
|
|
||||||
```
|
|
||||||
Markdown(.md) --> generateData.js --> JSON (tree, contents, stats) --> React (render)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🧯 Ignore Rules
|
|
||||||
|
|
||||||
Default ignored: `.obsidian`, `.trash`, `.git`, `node_modules`, any dot‑prefixed file/dir.
|
|
||||||
|
|
||||||
Custom ignore: create `public/mengyanote/ignore.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "ignore": ["Drafts", "private", "Scratch.md"] }
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎨 Customization Cheatsheet
|
|
||||||
|
|
||||||
| Goal | Where | Action |
|
|
||||||
|------|-------|--------|
|
|
||||||
| Remove math | `MarkdownRenderer.jsx` | Drop `remark-math` + `rehype-katex` + CSS import |
|
|
||||||
| Remove code highlighting | `MarkdownRenderer.jsx` | Remove `rehype-highlight` and theme CSS |
|
|
||||||
| New highlight theme | Add dependency | Replace imported highlight style |
|
|
||||||
| Inline code as plain text | Already done | Custom plugin strips inline code styling |
|
|
||||||
| Change image layout | `MarkdownRenderer.css` | Adjust `.markdown-image img` |
|
|
||||||
| Change breadcrumb format | `fileUtils.generateBreadcrumbs` | Modify join logic |
|
|
||||||
|
|
||||||
## 🚢 Deployment
|
|
||||||
|
|
||||||
Build output: `dist/` (fully static).
|
|
||||||
|
|
||||||
Platforms:
|
|
||||||
|
|
||||||
| Platform | Notes |
|
|
||||||
|----------|-------|
|
|
||||||
| GitHub Pages | Push `dist/` to `gh-pages` or use an Action |
|
|
||||||
| Netlify | Build: `npm run build`, Publish: `dist` |
|
|
||||||
| Vercel | Auto-detect Vite |
|
|
||||||
| Any static host / Nginx | Upload `dist/` |
|
|
||||||
|
|
||||||
Example Nginx:
|
|
||||||
|
|
||||||
```
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name example.com;
|
|
||||||
root /var/www/markdown-to-web/dist;
|
|
||||||
location / { try_files $uri /index.html; }
|
|
||||||
add_header Cache-Control "public, max-age=31536000";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
**New file not appearing?** Regenerate data: `npm run generate-data` (or rerun dev/build).
|
|
||||||
|
|
||||||
**Ignore not working?** Ensure `ignore.json` sits directly in `public/mengyanote/` and key is exactly `ignore`.
|
|
||||||
|
|
||||||
**Large number of files causes slow load?** Consider splitting `fileContents.json` into per‑file JSON (enhancement idea).
|
|
||||||
|
|
||||||
**Search support?** Not yet. You can integrate `minisearch` or `lunr` during build.
|
|
||||||
|
|
||||||
**Can I support frontmatter?** Extend the generator to parse YAML frontmatter and attach metadata to each node.
|
|
||||||
|
|
||||||
## Roadmap (Open for Contributions)
|
|
||||||
|
|
||||||
- [ ] Full‑text search
|
|
||||||
- [ ] Per‑file lazy loading
|
|
||||||
- [ ] Recent updates panel / changelog
|
|
||||||
- [ ] Frontmatter tags + filters
|
|
||||||
- [ ] RSS / JSON feed generation
|
|
||||||
- [ ] PDF / print friendly mode
|
|
||||||
- [ ] Service Worker caching
|
|
||||||
- [ ] GitHub Actions deploy workflow example
|
|
||||||
|
|
||||||
## Contributing & License
|
|
||||||
|
|
||||||
Issues / PRs welcome. Please open an issue before large feature work; attach screenshots for UI changes. License: see `LICENSE`.
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
Open an issue describing:
|
|
||||||
|
|
||||||
- Desired visual style (links / screenshots)
|
|
||||||
- Needed deployment pipeline (e.g., GitHub Pages Action)
|
|
||||||
- Theming or performance concerns
|
|
||||||
|
|
||||||
I can suggest patches or configuration examples.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Happy publishing! If you build cool themes (minimal / book‑like / image‑first), consider sharing them back. 🙌
|
|
||||||
31
build.bat
Normal file
31
build.bat
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
echo ============== 开始执行构建 ==============
|
||||||
|
:: 关键:添加 call 确保 npm 执行完后继续执行后续命令
|
||||||
|
call npm run build
|
||||||
|
|
||||||
|
:: 检查构建是否成功
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo 【错误】构建失败!请查看上面的错误信息
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo ============== 构建成功,准备启动服务器 ==============
|
||||||
|
echo 正在进入 dist 目录...
|
||||||
|
cd dist || (
|
||||||
|
echo 【错误】找不到 dist 目录!构建可能未生成该目录
|
||||||
|
echo 当前目录:%cd% (请确认该目录下是否有 dist 文件夹)
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo ============== 服务器启动中(端口 8080) ==============
|
||||||
|
echo 提示:服务器启动后会一直运行,访问 http://localhost:8080 查看
|
||||||
|
echo 若要停止服务器,请按 Ctrl + C,然后按 Y 确认
|
||||||
|
python -m http.server 8080
|
||||||
|
|
||||||
|
:: 服务器停止后执行
|
||||||
|
echo ============== 服务器已停止 ==============
|
||||||
|
pause
|
||||||
16
docker-compose.yml
Normal file
16
docker-compose.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
container_name: markdown-to-web
|
||||||
|
ports:
|
||||||
|
- "5173:80"
|
||||||
|
volumes:
|
||||||
|
- /shumengya/docker/storage/markdown2web/dist:/usr/share/nginx/html
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
4
docker-entrypoint.sh
Normal file
4
docker-entrypoint.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 该脚本在简化后的 Docker 流程中不再使用,保留占位避免误调用。
|
||||||
|
echo "docker-entrypoint.sh 已弃用:当前镜像仅用于静态文件托管。"
|
||||||
536
package-lock.json
generated
536
package-lock.json
generated
@@ -28,6 +28,7 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
"vite": "^7.1.7"
|
"vite": "^7.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -62,6 +63,7 @@
|
|||||||
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
|
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.3",
|
"@babel/generator": "^7.28.3",
|
||||||
@@ -1437,6 +1439,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.15.tgz",
|
||||||
"integrity": "sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==",
|
"integrity": "sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
@@ -1490,6 +1493,7 @@
|
|||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -1547,6 +1551,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/async": {
|
||||||
|
"version": "3.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||||
|
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/bail": {
|
"node_modules/bail": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
||||||
@@ -1574,6 +1585,19 @@
|
|||||||
"baseline-browser-mapping": "dist/cli.js"
|
"baseline-browser-mapping": "dist/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/basic-auth": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "5.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
@@ -1605,6 +1629,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.3",
|
"baseline-browser-mapping": "^2.8.3",
|
||||||
"caniuse-lite": "^1.0.30001741",
|
"caniuse-lite": "^1.0.30001741",
|
||||||
@@ -1619,6 +1644,37 @@
|
|||||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bound": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"get-intrinsic": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/callsites": {
|
"node_modules/callsites": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||||
@@ -1779,6 +1835,16 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/corser": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@@ -1859,6 +1925,21 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.227",
|
"version": "1.5.227",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.227.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.227.tgz",
|
||||||
@@ -1878,6 +1959,39 @@
|
|||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.25.10",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
|
||||||
@@ -1949,6 +2063,7 @@
|
|||||||
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
|
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -2131,6 +2246,13 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eventemitter3": {
|
||||||
|
"version": "4.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||||
|
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/extend": {
|
"node_modules/extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
@@ -2227,6 +2349,27 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
|
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
@@ -2242,6 +2385,16 @@
|
|||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gensync": {
|
"node_modules/gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
@@ -2252,6 +2405,45 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob-parent": {
|
"node_modules/glob-parent": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
@@ -2278,6 +2470,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-flag": {
|
"node_modules/has-flag": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
@@ -2288,6 +2493,32 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-dom": {
|
"node_modules/hast-util-from-dom": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
@@ -2510,6 +2741,16 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/he": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"he": "bin/he"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/highlight.js": {
|
"node_modules/highlight.js": {
|
||||||
"version": "11.11.1",
|
"version": "11.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
||||||
@@ -2519,6 +2760,19 @@
|
|||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/html-encoding-sniffer": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-encoding": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/html-url-attributes": {
|
"node_modules/html-url-attributes": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
||||||
@@ -2539,6 +2793,62 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/http-proxy": {
|
||||||
|
"version": "1.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||||
|
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eventemitter3": "^4.0.0",
|
||||||
|
"follow-redirects": "^1.0.0",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-server": {
|
||||||
|
"version": "14.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
|
||||||
|
"integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"basic-auth": "^2.0.1",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"corser": "^2.0.1",
|
||||||
|
"he": "^1.2.0",
|
||||||
|
"html-encoding-sniffer": "^3.0.0",
|
||||||
|
"http-proxy": "^1.18.1",
|
||||||
|
"mime": "^1.6.0",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"opener": "^1.5.1",
|
||||||
|
"portfinder": "^1.0.28",
|
||||||
|
"secure-compare": "3.0.1",
|
||||||
|
"union": "~0.5.0",
|
||||||
|
"url-join": "^4.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"http-server": "bin/http-server"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@@ -2843,6 +3153,16 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-find-and-replace": {
|
"node_modules/mdast-util-find-and-replace": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
|
||||||
@@ -3740,6 +4060,19 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/mime": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
@@ -3753,6 +4086,16 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -3792,6 +4135,29 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/object-inspect": {
|
||||||
|
"version": "1.13.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/opener": {
|
||||||
|
"version": "1.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
||||||
|
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(WTFPL OR MIT)",
|
||||||
|
"bin": {
|
||||||
|
"opener": "bin/opener-bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
@@ -3925,6 +4291,7 @@
|
|||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -3932,6 +4299,20 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/portfinder": {
|
||||||
|
"version": "1.0.38",
|
||||||
|
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz",
|
||||||
|
"integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"async": "^3.2.6",
|
||||||
|
"debug": "^4.3.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
@@ -3991,11 +4372,28 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/qs": {
|
||||||
|
"version": "6.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
||||||
|
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"side-channel": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "19.1.1",
|
"version": "19.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
||||||
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
|
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -4005,6 +4403,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
||||||
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
|
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
@@ -4235,6 +4634,13 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/resolve-from": {
|
"node_modules/resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||||
@@ -4287,12 +4693,33 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.26.0",
|
"version": "0.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
|
||||||
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
|
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/secure-compare": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
@@ -4332,6 +4759,82 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/side-channel": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"object-inspect": "^1.13.3",
|
||||||
|
"side-channel-list": "^1.0.0",
|
||||||
|
"side-channel-map": "^1.0.1",
|
||||||
|
"side-channel-weakmap": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-list": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"object-inspect": "^1.13.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-map": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.5",
|
||||||
|
"object-inspect": "^1.13.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/side-channel-weakmap": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bound": "^1.0.2",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.5",
|
||||||
|
"object-inspect": "^1.13.3",
|
||||||
|
"side-channel-map": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@@ -4479,6 +4982,18 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/union": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"qs": "^6.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unist-util-find-after": {
|
"node_modules/unist-util-find-after": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
|
||||||
@@ -4616,6 +5131,13 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/url-join": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vfile": {
|
"node_modules/vfile": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
||||||
@@ -4664,6 +5186,7 @@
|
|||||||
"integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==",
|
"integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -4743,6 +5266,19 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/whatwg-encoding": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
"vite": "^7.1.7"
|
"vite": "^7.1.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,64 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "编程语言",
|
"path": "编程语言",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端",
|
||||||
|
"name": "前端",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "编程语言/前端",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题",
|
||||||
|
"name": "JavaScript趣味题",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md",
|
||||||
|
"name": "JavaScript趣味题_128.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md",
|
||||||
|
"name": "JavaScript趣味题_18.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md",
|
||||||
|
"name": "JavaScript趣味题_28.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/纯静态网页的强大功能与应用.md",
|
||||||
|
"name": "纯静态网页的强大功能与应用.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/纯静态网页的强大功能与应用.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/css注入代码合集.md",
|
||||||
|
"name": "css注入代码合集.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/css注入代码合集.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "编程语言/Android",
|
"id": "编程语言/Android",
|
||||||
"name": "Android",
|
"name": "Android",
|
||||||
@@ -335,6 +393,30 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "计算机科普",
|
"path": "计算机科普",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "计算机科普/编程语言科普.md",
|
||||||
|
"name": "编程语言科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/编程语言科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/编程语言之间的划分.md",
|
||||||
|
"name": "编程语言之间的划分.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/编程语言之间的划分.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/操作系统科普.md",
|
||||||
|
"name": "操作系统科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/操作系统科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/多模态大模型识别图片,视频,音频原理.md",
|
"id": "计算机科普/多模态大模型识别图片,视频,音频原理.md",
|
||||||
"name": "多模态大模型识别图片,视频,音频原理.md",
|
"name": "多模态大模型识别图片,视频,音频原理.md",
|
||||||
@@ -343,14 +425,6 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "计算机科普/光纤和网线的特点和区别.md",
|
|
||||||
"name": "光纤和网线的特点和区别.md",
|
|
||||||
"type": "file",
|
|
||||||
"path": "计算机科普/光纤和网线的特点和区别.md",
|
|
||||||
"children": [],
|
|
||||||
"isExpanded": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "计算机科普/科普-Nagle 算法.md",
|
"id": "计算机科普/科普-Nagle 算法.md",
|
||||||
"name": "科普-Nagle 算法.md",
|
"name": "科普-Nagle 算法.md",
|
||||||
@@ -359,6 +433,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语解释-DMZ.md",
|
||||||
|
"name": "术语解释-DMZ.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语解释-DMZ.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/术语科普-CVM.md",
|
"id": "计算机科普/术语科普-CVM.md",
|
||||||
"name": "术语科普-CVM.md",
|
"name": "术语科普-CVM.md",
|
||||||
@@ -383,6 +465,22 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-MQ.md",
|
||||||
|
"name": "术语科普-MQ.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-MQ.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-POI.md",
|
||||||
|
"name": "术语科普-POI.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-POI.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/术语科普-pwn.md",
|
"id": "计算机科普/术语科普-pwn.md",
|
||||||
"name": "术语科普-pwn.md",
|
"name": "术语科普-pwn.md",
|
||||||
@@ -391,6 +489,46 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-QPS.md",
|
||||||
|
"name": "术语科普-QPS.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-QPS.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/网络协议科普.md",
|
||||||
|
"name": "网络协议科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/网络协议科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/游戏行业简单科普.md",
|
||||||
|
"name": "游戏行业简单科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/游戏行业简单科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/游戏引擎科普.md",
|
||||||
|
"name": "游戏引擎科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/游戏引擎科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"name": "C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/clash机场三种代理模式科普.md",
|
"id": "计算机科普/clash机场三种代理模式科普.md",
|
||||||
"name": "clash机场三种代理模式科普.md",
|
"name": "clash机场三种代理模式科普.md",
|
||||||
@@ -407,6 +545,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"name": "IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/IDEA专业版和社区版的区别和特点.md",
|
"id": "计算机科普/IDEA专业版和社区版的区别和特点.md",
|
||||||
"name": "IDEA专业版和社区版的区别和特点.md",
|
"name": "IDEA专业版和社区版的区别和特点.md",
|
||||||
@@ -465,10 +611,26 @@
|
|||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机网络/TCP的三次握手四次握手.md",
|
"id": "计算机网络/HTTP版本协议对比区别.md",
|
||||||
"name": "TCP的三次握手四次握手.md",
|
"name": "HTTP版本协议对比区别.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "计算机网络/TCP的三次握手四次握手.md",
|
"path": "计算机网络/HTTP版本协议对比区别.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机网络/HTTP常见状态码.md",
|
||||||
|
"name": "HTTP常见状态码.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机网络/HTTP常见状态码.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机网络/TCP的三次握手四次握手总结.md",
|
||||||
|
"name": "TCP的三次握手四次握手总结.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机网络/TCP的三次握手四次握手总结.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
@@ -476,24 +638,48 @@
|
|||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "面试八股",
|
"id": "内网穿透",
|
||||||
"name": "面试八股",
|
"name": "内网穿透",
|
||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "面试八股",
|
"path": "内网穿透",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "面试八股/计算机面试经典八股.md",
|
"id": "内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
"name": "计算机面试经典八股.md",
|
"name": "搭建derp和headscale避坑与指南.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "面试八股/计算机面试经典八股.md",
|
"path": "内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "面试八股/Nacos功能与应用场景详解.md",
|
"id": "内网穿透/内网穿透方案.md",
|
||||||
"name": "Nacos功能与应用场景详解.md",
|
"name": "内网穿透方案.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "面试八股/Nacos功能与应用场景详解.md",
|
"path": "内网穿透/内网穿透方案.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/Frp的kcp和quic的区别和特点.md",
|
||||||
|
"name": "Frp的kcp和quic的区别和特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/Frp的kcp和quic的区别和特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/frp服务端配置.md",
|
||||||
|
"name": "frp服务端配置.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/frp服务端配置.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/frp客户端配置.md",
|
||||||
|
"name": "frp客户端配置.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/frp客户端配置.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
@@ -506,6 +692,14 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "嵌入式",
|
"path": "嵌入式",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "嵌入式/光纤和网线的特点和区别.md",
|
||||||
|
"name": "光纤和网线的特点和区别.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "嵌入式/光纤和网线的特点和区别.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "嵌入式/USB拓展坞接口数量决定因素.md",
|
"id": "嵌入式/USB拓展坞接口数量决定因素.md",
|
||||||
"name": "USB拓展坞接口数量决定因素.md",
|
"name": "USB拓展坞接口数量决定因素.md",
|
||||||
@@ -575,6 +769,81 @@
|
|||||||
],
|
],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职",
|
||||||
|
"name": "实习求职",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股",
|
||||||
|
"name": "面试八股",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职/面试八股",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/HTTP 与HTTPS",
|
||||||
|
"name": "HTTP 与HTTPS",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职/面试八股/HTTP 与HTTPS",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/HTTP 与HTTPS/从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"name": "从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/HTTP 与HTTPS/从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/计算机面试经典八股.md",
|
||||||
|
"name": "计算机面试经典八股.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/计算机面试经典八股.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/Nacos功能与应用场景详解.md",
|
||||||
|
"name": "Nacos功能与应用场景详解.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/Nacos功能与应用场景详解.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"name": "27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/术语科普-HC.md",
|
||||||
|
"name": "术语科普-HC.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/术语科普-HC.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/术语科普-PM.md",
|
||||||
|
"name": "术语科普-PM.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/术语科普-PM.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "数据结构与算法",
|
"id": "数据结构与算法",
|
||||||
"name": "数据结构与算法",
|
"name": "数据结构与算法",
|
||||||
@@ -973,6 +1242,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "AI/AI大模型应用拆解.md",
|
||||||
|
"name": "AI大模型应用拆解.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "AI/AI大模型应用拆解.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "AI/Qwen-Code官方文档使用教程.md",
|
"id": "AI/Qwen-Code官方文档使用教程.md",
|
||||||
"name": "Qwen-Code官方文档使用教程.md",
|
"name": "Qwen-Code官方文档使用教程.md",
|
||||||
@@ -1004,6 +1281,14 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "Docker/优秀好用的Docker镜像",
|
"path": "Docker/优秀好用的Docker镜像",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/模板.md",
|
||||||
|
"name": "模板.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/模板.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Docker/优秀好用的Docker镜像/FileCodeBox-文件快递柜.md",
|
"id": "Docker/优秀好用的Docker镜像/FileCodeBox-文件快递柜.md",
|
||||||
"name": "FileCodeBox-文件快递柜.md",
|
"name": "FileCodeBox-文件快递柜.md",
|
||||||
@@ -1012,6 +1297,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/frp-内网穿透神器.md",
|
||||||
|
"name": "frp-内网穿透神器.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/frp-内网穿透神器.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Docker/优秀好用的Docker镜像/Gitea-私有化仓库部署.md",
|
"id": "Docker/优秀好用的Docker镜像/Gitea-私有化仓库部署.md",
|
||||||
"name": "Gitea-私有化仓库部署.md",
|
"name": "Gitea-私有化仓库部署.md",
|
||||||
@@ -1067,6 +1360,22 @@
|
|||||||
"path": "Docker/优秀好用的Docker镜像/Redis-内存数据库.md",
|
"path": "Docker/优秀好用的Docker镜像/Redis-内存数据库.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"name": "SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md",
|
||||||
|
"name": "tailscale-ip-derp.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"totalFiles": 163,
|
"totalFiles": 196,
|
||||||
"totalFolders": 34,
|
"totalFolders": 39,
|
||||||
"generatedAt": "2025-10-02T01:36:14.347Z",
|
"generatedAt": "2025-10-12T11:13:34.210Z",
|
||||||
"sourceDirectory": "E:\\React\\markdown-to-web\\public\\mengyanote"
|
"sourceDirectory": "E:\\React\\markdown-to-web\\public\\mengyanote"
|
||||||
}
|
}
|
||||||
6
public/mengyanote/.obsidian/app.json
vendored
6
public/mengyanote/.obsidian/app.json
vendored
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"promptDelete": false
|
"promptDelete": false,
|
||||||
|
"readableLineLength": false,
|
||||||
|
"strictLineBreaks": false,
|
||||||
|
"showLineNumber": false,
|
||||||
|
"rightToLeft": false
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"usePathObfuscation": false,
|
"usePathObfuscation": false,
|
||||||
"doNotDeleteFolder": false,
|
"doNotDeleteFolder": false,
|
||||||
"resolveConflictsByNewerFile": false,
|
"resolveConflictsByNewerFile": false,
|
||||||
"batchSave": true,
|
"batchSave": false,
|
||||||
"batchSaveMinimumDelay": 5,
|
"batchSaveMinimumDelay": 5,
|
||||||
"batchSaveMaximumDelay": 60,
|
"batchSaveMaximumDelay": 60,
|
||||||
"deviceAndVaultName": "",
|
"deviceAndVaultName": "",
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
"syncInternalFilesIgnorePatterns": "\\/node_modules\\/, \\/\\.git\\/, \\/obsidian-livesync\\/",
|
"syncInternalFilesIgnorePatterns": "\\/node_modules\\/, \\/\\.git\\/, \\/obsidian-livesync\\/",
|
||||||
"syncInternalFilesTargetPatterns": "",
|
"syncInternalFilesTargetPatterns": "",
|
||||||
"syncInternalFilesInterval": 60,
|
"syncInternalFilesInterval": 60,
|
||||||
"additionalSuffixOfDatabaseName": "64ee792396a31ce1",
|
"additionalSuffixOfDatabaseName": "421f688ab570b23d",
|
||||||
"ignoreVersionCheck": false,
|
"ignoreVersionCheck": false,
|
||||||
"lastReadUpdates": 25,
|
"lastReadUpdates": 25,
|
||||||
"deleteMetadataOfDeletedFiles": false,
|
"deleteMetadataOfDeletedFiles": false,
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
"syncAfterMerge": true,
|
"syncAfterMerge": true,
|
||||||
"configPassphraseStore": "",
|
"configPassphraseStore": "",
|
||||||
"encryptedPassphrase": "",
|
"encryptedPassphrase": "",
|
||||||
"encryptedCouchDBConnection": "%$Uukeo12Pgs5baxCUGOX3mFwYVrSAEKjTp71bZM0ksyYOD73jzNGIadNLYC2doeXSXRIOZMe8gzbNAT4xr7/eDVD6PlQZR9sHbSpjf72zzI75i0YefndafQiCQ/0ZD7g3T+7bxS7Xa5421ysRvfiPG/AUxUAp2G2L9wBelAVcOPFSjIDlV83JZvQ8JdSjEGTCrwlXev8HlFvqGoeIaM8Z0ZD4yIn9RNKGnVNAnwugsjkkkReG9YgJBu6ac4lGijbEQct/NrfnZ9h2p9Y9ooUmC64ZiUn9WLaJnp4vocuRZc0UW4gA0VtVLQlsKvckJizSNrr2gftcJqj0Bxgu2e6wSP/8bZZOeTZYwMqCMHS5SchV/I9CHuzOhmFvqoEaZDGK1XPMmalw5S9vKQR0j6m56SzIXaZAQ45KmJIirijXme+FDwabZkafd/Jx4IvU15rP3K0Y13ByhxN37Eklj0vLXOY44F8KdeBvx+0yhTxvzN/pn2iYfM0wmvzxlCMIqlpyd5OiTp+swjs9+Rp7rVmwC7FzDegvBR7ZNHyeKqUP+NSk0ssCSvA9QwXyV7vPvW5npiDh7zPN/RPkHTQCwxbjg5Lth/gCsfyR2bBK3YxlM5x5+GVTw2RUoVdSXn4G9ziH+jdLDTWzBvRORPHel4x753CqL6nIU0bVZZRxIJavXXwm+UosQst53HqptDI2dBSCvDC7Xnk=",
|
"encryptedCouchDBConnection": "%$Lm4s2DqCoARDdP/gXNSI+OA1xLmG7eftRPfa/sz+9NLvRqszRC6f1/bSP/JuvQukUqSMBTGq74zubYyEwq+/vd/MuXsJs2gNvmyTvsBfeV8y75WYXCV5zgg57lVGzWEPBiZ8dX9uXS4HyDmSjT+EPXRsVQn4uGecyPn52nQvHG8TJFz0lwMl0keTpJezd5HlnQAWPqFeVLxTdIoIOh2+uFA83Iyd6X5XsRxDapAwVdy0XATKjB+rUVQnLONWWg1UEJB/kKNlFnfprTrW7LFXXmUr8HueokoPzu/dcKbK0TyVu7EKTnNxGtkPUYCAk+vAxpCoGV/n5ApDaRo49VDMM22WamPbRH4+wZkd2ZAQVJn/5eqwR/3nAVVfm8ctbhaP1uXeDjPz0cpK0MSn2xVmjLKADdVpF/KBW2Vfe4SJnO6QEqOWa+pMRW38OAiv/iKZSAATBGFLv/iFuDYZye/bDf+SlaQQ+ZrqSVflo8Aj8cLPh1Okw3zeuK+4j7P1gJm82jZTZPSZvYBTaiyjeU5qBdGDJjuslrTYezCpWnkgXhdi/nSnw7iJoK5kAtvisZvSNlVDM+t82YjBdoZT9BxsVu1sisXXUzjcw8Ycx1gj4EtH1xiqEoyxiJEC0FASV4r+9Wrg4r+oQESSR9B2/Z0Lhd80WsEMDS1RGV6jJqDLPhvTD38ouRuTbkU4+Xsr9T4mabU1KvQdYpE=",
|
||||||
"permitEmptyPassphrase": false,
|
"permitEmptyPassphrase": false,
|
||||||
"useIndexedDBAdapter": true,
|
"useIndexedDBAdapter": true,
|
||||||
"useTimeouts": false,
|
"useTimeouts": false,
|
||||||
|
|||||||
102
public/mengyanote/.obsidian/workspace.json
vendored
102
public/mengyanote/.obsidian/workspace.json
vendored
@@ -27,12 +27,40 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "编程语言/C/C语言不设置临时变量交换x和y的值(方法).md",
|
"file": "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": true
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "tailscale-ip-derp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2971759a4871130b",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "内网穿透/Frp的kcp和quic的区别和特点.md",
|
||||||
|
"mode": "preview",
|
||||||
|
"source": true
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "Frp的kcp和quic的区别和特点"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a93d6d3811397e7b",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
"mode": "source",
|
"mode": "source",
|
||||||
"source": false
|
"source": false
|
||||||
},
|
},
|
||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "C语言不设置临时变量交换x和y的值(方法)"
|
"title": "搭建derp和headscale避坑与指南"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -50,7 +78,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentTab": 1
|
"currentTab": 3
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "vertical"
|
"direction": "vertical"
|
||||||
@@ -199,41 +227,44 @@
|
|||||||
"obsidian-livesync:Show Customization sync": false
|
"obsidian-livesync:Show Customization sync": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "108d0380d5e0d36b",
|
"active": "f1c17e2d203acce4",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"面试八股/Nacos功能与应用场景详解.md",
|
"Terraria",
|
||||||
"临时/快速开启一个http服务器.md",
|
"临时/快速开启一个http服务器.md",
|
||||||
"Linux/wlan0简单介绍.md",
|
"树萌芽的小本本/重要信息记录.md",
|
||||||
"杂项/计算机刷题网站.md",
|
"计算机科普/IDE,编辑器,编译器区别和特点.md",
|
||||||
"杂项/markdown格式(没什么用).md",
|
"编程语言/前端/css注入代码合集.md",
|
||||||
"杂项/文本颜色测试.md",
|
"编程语言/前端/纯静态网页的强大功能与应用.md",
|
||||||
"杂项/古诗.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md",
|
||||||
"杂项/PTA好题-计算众数.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md",
|
||||||
"杂项/PTA好题-英文单词排序.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md",
|
||||||
"杂项/PTA万能代码.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_28_1756448893571.md",
|
||||||
"杂项/Markdown格式大全.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_18_1756450414057.md",
|
||||||
"杂项/c++如何快速的检测一个字串符在另一个字串符的出现次数.md",
|
"编程语言/前端/JavaScript趣味题/JavaScript趣味题_128_1756449169066.md",
|
||||||
"杂项/10月23日大学英语笔记.md",
|
"编程语言/前端/JavaScript趣味题/未命名",
|
||||||
|
"编程语言/前端/JavaScript趣味题",
|
||||||
|
"计算机科普/编程语言之间的划分.md",
|
||||||
|
"计算机科普/游戏行业简单科普.md",
|
||||||
|
"计算机科普/网络协议科普.md",
|
||||||
|
"计算机科普/C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"计算机科普/编程语言科普.md",
|
||||||
|
"计算机科普/操作系统科普.md",
|
||||||
|
"计算机科普/游戏引擎科普.md",
|
||||||
|
"内网穿透/frp服务端配置.md",
|
||||||
|
"内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
|
"内网穿透/内网穿透方案.md",
|
||||||
|
"内网穿透/frp客户端配置.md",
|
||||||
|
"Docker/优秀好用的Docker镜像/frp-内网穿透神器.md",
|
||||||
|
"Docker/优秀好用的Docker镜像/模板.md",
|
||||||
|
"Docker/Docker命令集合.md",
|
||||||
|
"内网穿透",
|
||||||
|
"实习求职/面试八股/HTTP 与HTTPS",
|
||||||
|
"实习求职/面试八股",
|
||||||
|
"实习求职",
|
||||||
|
"面试八股/HTTP 与HTTPS",
|
||||||
"杂项",
|
"杂项",
|
||||||
"华为ICT/杂项/计算机刷题网站.md",
|
|
||||||
"华为ICT/杂项/文本颜色测试.md",
|
|
||||||
"华为ICT/杂项/古诗.md",
|
|
||||||
"华为ICT/杂项/PTA好题-计算众数.md",
|
|
||||||
"华为ICT/杂项/PTA好题-英文单词排序.md",
|
|
||||||
"华为ICT/杂项/PTA万能代码.md",
|
|
||||||
"华为ICT/杂项/markdown格式(没什么用).md",
|
|
||||||
"华为ICT/杂项/Markdown格式大全.md",
|
|
||||||
"华为ICT/杂项/c++如何快速的检测一个字串符在另一个字串符的出现次数.md",
|
|
||||||
"华为ICT/杂项/10月23日大学英语笔记.md",
|
|
||||||
"华为ICT/杂项",
|
"华为ICT/杂项",
|
||||||
"临时/灵创第15周周报.md",
|
|
||||||
"临时/灵创第14周个人汇报.md",
|
|
||||||
"临时/第16周灵创汇报.md",
|
|
||||||
"临时",
|
"临时",
|
||||||
"游戏引擎/Unity/Unity代码片段",
|
|
||||||
"游戏引擎/Unreal",
|
|
||||||
"游戏引擎/新建文件夹",
|
|
||||||
"游戏引擎/Unity",
|
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/5-04.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/5-04.png",
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/5-03.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/5-03.png",
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/5-02.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/5-02.png",
|
||||||
@@ -243,9 +274,6 @@
|
|||||||
"Minecraft/基岩版服务器/NukkitLearn/images/1-09.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/1-09.png",
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/1-08.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/1-08.png",
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/1-07.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/1-07.png",
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images/1-06.png",
|
"Minecraft/基岩版服务器/NukkitLearn/images/1-06.png"
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/_config.yml",
|
|
||||||
"Minecraft/基岩版服务器/NukkitLearn/images",
|
|
||||||
"Minecraft/基岩版服务器/NukkitLearn"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
19
public/mengyanote/.trash/内网穿透方案.md
Normal file
19
public/mengyanote/.trash/内网穿透方案.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、开源替代方案 /工具清单
|
||||||
|
|
||||||
|
下面是目前社区里比较流行 /有实用性的开源方案:
|
||||||
|
|
||||||
|
|名称|语言 / 技术栈|支持协议 /功能|特点 /亮点|可能缺点 /注意|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|**rathole**|Rust|TCP / HTTP /TLS|轻量、高性能,内存占用低,支持热重载、服务令牌认证等。被设计为 FRP / ngrok 的替代品。 ([GitHub](https://github.com/rathole-org/rathole?utm_source=chatgpt.com "GitHub - rathole-org/rathole: A lightweight and high-performance ..."))|文档 /社区可能不如 FRP 那么成熟;一些边缘功能可能欠缺|
|
||||||
|
|**NSmartProxy**|.NET Core / C#|TCP / HTTP 反向代理 /穿透|跨平台支持好,用异步 I/O 架构驱动穿透代理。 ([GitHub](https://github.com/tmoonlight/NSmartProxy?utm_source=chatgpt.com "GitHub - tmoonlight/NSmartProxy: NSmartProxy是一款开源的内网穿透工具。采用.NET CORE ..."))|在 Linux /非 .NET 平台上的稳定性 /优化要测试;社区规模可能偏小|
|
||||||
|
|**Tunnelmole**|Node.js / TypeScript|HTTP / HTTPS 隧道|100% 开源、可自托管、方便给本地 Web 服务生成公开 URL。 ([tunnelmole.com](https://tunnelmole.com/?utm_source=chatgpt.com "Tunnelmole - A free and open source tunneling tool"))|主要面向 HTTP/HTTPS,游戏 /通用 TCP 服务可能支持不够好;对于高并发 /大流量性能需要评估|
|
||||||
|
|**Reverse Proxy Tool(基于 Netty 的)**|Java / Netty|支持任意 TCP 上层协议和 HTTP|支持 HTTP 升级、SSL 验证、协议透传等功能。 ([Gitee](https://gitee.com/codebanks/reverse-proxy-tool?utm_source=chatgpt.com "Reverse Proxy Tool: Reverse Proxy Tool : 基于Netty实现的 ..."))|Java 程序可能资源占用较高;配置可能稍复杂;性能需要根据 JVM 优化|
|
||||||
|
|**nps / NPS** / **lanproxy** / **holer**|Go /其他|TCP / HTTP /UDP 穿透、反向代理|在「开源内网穿透工具」合集 /对比文章里经常被提及。 ([laoliang.net](https://www.laoliang.net/jsjh/technology/14975.html?utm_source=chatgpt.com "归纳几种免费开源的内网穿透工具(frp、holer、nps、lanproxy)"))|各工具在稳定性、协议支持深度、社区维护度上有差别;需要逐个评估|
|
||||||
|
|**reverse-tunnel(snsi nfu 的项目)**|(未知 /社区项目)|公网 → 私网 隧道 /映射|提供反向隧道映射能力,据社区介绍可以做安全隧道。 ([CSDN.blog](https://blog.csdn.net/gitblog_01080/article/details/141481391?utm_source=chatgpt.com "反向隧道工具 reverse-tunnel 使用指南-CSDN博客"))|项目可能成熟度不高,文档 /示例可能不足;功能边界需自己测试|
|
||||||
|
|**tiny-frpc**|Go / 精简 FRP 客户端|frp 协议子集|体积小、适合资源紧张的嵌入式 /小设备使用。 ([博客园](https://www.cnblogs.com/tang863/p/18274521?utm_source=chatgpt.com "tiny-frpc: frp 反向代理精简版客户端 - AmbiaCode - 博客园"))|只是 frpc 的子集,用于客户端,不是完整替代;功能限制较多|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
388
public/mengyanote/.trash/搭建derp和headscale避坑与指南.md
Normal file
388
public/mengyanote/.trash/搭建derp和headscale避坑与指南.md
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
derp(Docker安装):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#Docker容器一键化启动
|
||||||
|
#默认开启tcp端口33445 udp端口3478
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper1 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp1/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp1.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp1.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp1.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper2 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp2/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp2.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp2.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp2.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper3 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp3/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp3.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp3.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp3.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#默认使用Let's Encrypt签发ssl证书
|
||||||
|
#默认需要关闭nginx占用80端口来签发证书
|
||||||
|
curl -s https://get.acme.sh | sh
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
acme.sh --issue --standalone -d 你的域名
|
||||||
|
#安装依赖
|
||||||
|
apt update && apt install -y socat
|
||||||
|
yum install -y socat
|
||||||
|
dnf install -y socat
|
||||||
|
|
||||||
|
acme.sh --register-account -m 你的邮箱地址
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
headscale(直接部署systemctl运行):
|
||||||
|
|
||||||
|
headscale默认放行:9090~9092 和50443
|
||||||
|
|
||||||
|
配置一个域名:
|
||||||
|
headscale.shumengya.top
|
||||||
|
下载headscale:[https://github.com/juanfont/headscale](headscale)
|
||||||
|
下载headscale-ui:[https://github.com/juanfont/headscale](headscale-ui)
|
||||||
|
|
||||||
|
新建文件夹(用来放相关文件):
|
||||||
|
mkdir -p shumengya/headscale
|
||||||
|
|
||||||
|
安装headscale:
|
||||||
|
dpkg -i headscale_0.26.1_linux_amd64.deb
|
||||||
|
|
||||||
|
修改headscale配置
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# headscale 会按照以下顺序查找名为 `config.yaml` (或 `config.json`) 的配置文件:
|
||||||
|
#
|
||||||
|
# - `/etc/headscale`
|
||||||
|
# - `~/.headscale`
|
||||||
|
# - 当前工作目录
|
||||||
|
|
||||||
|
# 客户端将要连接的 URL。
|
||||||
|
# 通常应为一个域名,例如:
|
||||||
|
#
|
||||||
|
# https://myheadscale.example.com:443
|
||||||
|
#
|
||||||
|
server_url: http://127.0.0.1:9091
|
||||||
|
|
||||||
|
# 服务器监听/绑定的地址
|
||||||
|
#
|
||||||
|
# 生产环境建议:
|
||||||
|
listen_addr: 0.0.0.0:9092
|
||||||
|
#listen_addr: 127.0.0.1:8080
|
||||||
|
|
||||||
|
# /metrics 和 /debug 的监听地址,你可能希望
|
||||||
|
# 将此端点限制在内网
|
||||||
|
metrics_listen_addr: 127.0.0.1:9090
|
||||||
|
|
||||||
|
# gRPC 的监听地址。
|
||||||
|
# gRPC 用于通过 CLI 远程控制 headscale 服务器
|
||||||
|
# 注意:只有在使用有效证书时,远程访问才可用。
|
||||||
|
#
|
||||||
|
# 生产环境建议:
|
||||||
|
grpc_listen_addr: 0.0.0.0:50443
|
||||||
|
#grpc_listen_addr: 127.0.0.1:50443
|
||||||
|
|
||||||
|
# 是否允许 gRPC 管理接口以 **不安全** 模式运行。
|
||||||
|
# 不推荐启用,因为流量将不加密。只有在你完全理解风险时才启用。
|
||||||
|
grpc_allow_insecure: false
|
||||||
|
|
||||||
|
# Noise 部分包含 TS2021 Noise 协议的特定配置
|
||||||
|
noise:
|
||||||
|
# Noise 私钥用于在 headscale 和 Tailscale 客户端之间
|
||||||
|
# 使用新的基于 Noise 的协议加密流量。缺少的密钥将会自动生成。
|
||||||
|
private_key_path: /var/lib/headscale/noise_private.key
|
||||||
|
|
||||||
|
# 为 tailnet 分配地址的 IP 前缀列表。
|
||||||
|
# 每个前缀由 IPv4 或 IPv6 地址 + 前缀长度组成,以斜杠分隔。
|
||||||
|
# 必须在 Tailscale 客户端支持的范围内
|
||||||
|
# 即 100.64.0.0/10 和 fd7a:115c:a1e0::/48 的子网。
|
||||||
|
# 否则会导致异常问题。
|
||||||
|
prefixes:
|
||||||
|
v4: 100.64.0.0/10
|
||||||
|
#v6: fd7a:115c:a1e0::/48
|
||||||
|
|
||||||
|
# 节点 IP 分配策略,可选:
|
||||||
|
# - sequential(默认):按顺序分配下一个可用 IP
|
||||||
|
# - random:使用伪随机生成器分配可用 IP
|
||||||
|
allocation: sequential
|
||||||
|
|
||||||
|
# DERP 是 Tailscale 在无法建立直连时使用的中继系统。
|
||||||
|
# https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
|
||||||
|
#
|
||||||
|
# headscale 需要一个 DERP 服务器列表供客户端使用。
|
||||||
|
derp:
|
||||||
|
server:
|
||||||
|
# 启用后,将运行内置 DERP 服务器并合并到 DERP 配置中
|
||||||
|
# 上面的 server_url 必须使用 https,DERP 需要 TLS
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# 内置 DERP 服务器的区域 ID。
|
||||||
|
# 如果与外部配置的区域 ID 冲突,则本地 DERP 优先。
|
||||||
|
region_id: 999
|
||||||
|
|
||||||
|
# 区域代码和名称会在 Tailscale UI 中显示
|
||||||
|
region_code: "headscale"
|
||||||
|
region_name: "Headscale Embedded DERP"
|
||||||
|
|
||||||
|
# 在指定地址上监听 UDP 端口以支持 STUN 连接(帮助 NAT 穿透)。
|
||||||
|
# 如果启用内置 DERP,必须定义 stun_listen_addr。
|
||||||
|
#
|
||||||
|
# 更多详情可参考:https://tailscale.com/blog/how-tailscale-works/
|
||||||
|
stun_listen_addr: "0.0.0.0:3478"
|
||||||
|
|
||||||
|
# 用于加密 headscale DERP 与 Tailscale 客户端之间流量的私钥。
|
||||||
|
# 缺少时会自动生成。
|
||||||
|
private_key_path: /var/lib/headscale/derp_server_private.key
|
||||||
|
|
||||||
|
# 此标志用于控制是否自动将内置 DERP 写入 DERP map。
|
||||||
|
# 若设为 false,则需通过 DERP.paths 手动配置。
|
||||||
|
automatically_add_embedded_derp_region: true
|
||||||
|
|
||||||
|
# 为了更稳定的连接(特别是 Exit-Node + DNS 不可用时),
|
||||||
|
# 可以选择性地将公网 IPv4/IPv6 地址写入 Derp-Map:
|
||||||
|
ipv4: 1.2.3.4
|
||||||
|
ipv6: 2001:db8::1
|
||||||
|
|
||||||
|
# 外部可用的 DERP map 列表(JSON 格式)
|
||||||
|
urls:
|
||||||
|
# - https://controlplane.tailscale.com/derpmap/default
|
||||||
|
#- https://你的域名/web/derp.json
|
||||||
|
|
||||||
|
# 本地可用的 DERP map 文件(YAML 格式)
|
||||||
|
#
|
||||||
|
# 对于自建 DERP 服务器很有用:
|
||||||
|
# https://tailscale.com/kb/1118/custom-derp-servers/
|
||||||
|
#
|
||||||
|
# paths:
|
||||||
|
# - /etc/headscale/derp-example.yaml
|
||||||
|
paths: []
|
||||||
|
|
||||||
|
# 若启用,将定期刷新上述 DERP 源并更新 derpmap
|
||||||
|
auto_update_enabled: true
|
||||||
|
|
||||||
|
# 检查 DERP 更新的间隔
|
||||||
|
update_frequency: 24h
|
||||||
|
|
||||||
|
# 禁用启动时自动检查 headscale 更新
|
||||||
|
disable_check_updates: false
|
||||||
|
|
||||||
|
# 非活跃临时节点在多久后被删除?
|
||||||
|
ephemeral_node_inactivity_timeout: 30m
|
||||||
|
|
||||||
|
database:
|
||||||
|
# 数据库类型,可选:sqlite, postgres
|
||||||
|
# 注意:强烈不推荐使用 Postgres,仅为遗留原因保留。
|
||||||
|
# 所有新开发和优化都基于 SQLite。
|
||||||
|
type: sqlite
|
||||||
|
|
||||||
|
# 启用调试模式。需要 log.level 设置为 "debug" 或 "trace"。
|
||||||
|
debug: false
|
||||||
|
|
||||||
|
# GORM 配置
|
||||||
|
gorm:
|
||||||
|
# 启用预编译语句。
|
||||||
|
prepare_stmt: true
|
||||||
|
|
||||||
|
# 启用参数化查询。
|
||||||
|
parameterized_queries: true
|
||||||
|
|
||||||
|
# 跳过 “record not found” 错误日志。
|
||||||
|
skip_err_record_not_found: true
|
||||||
|
|
||||||
|
# 慢查询阈值(毫秒)
|
||||||
|
slow_threshold: 1000
|
||||||
|
|
||||||
|
# SQLite 配置
|
||||||
|
sqlite:
|
||||||
|
path: /var/lib/headscale/db.sqlite
|
||||||
|
|
||||||
|
# 启用 WAL 模式。推荐生产环境启用。
|
||||||
|
# https://www.sqlite.org/wal.html
|
||||||
|
write_ahead_log: true
|
||||||
|
|
||||||
|
# WAL 文件在达到多少帧时自动 checkpoint。
|
||||||
|
# 设为 0 可禁用自动 checkpoint。
|
||||||
|
wal_autocheckpoint: 1000
|
||||||
|
|
||||||
|
# # Postgres 配置(不推荐,仅遗留支持)
|
||||||
|
# postgres:
|
||||||
|
# # 使用 Unix socket 时,设置 host 为 socket 路径,port 留空。
|
||||||
|
# host: localhost
|
||||||
|
# port: 5432
|
||||||
|
# name: headscale
|
||||||
|
# user: foo
|
||||||
|
# pass: bar
|
||||||
|
# max_open_conns: 10
|
||||||
|
# max_idle_conns: 10
|
||||||
|
# conn_max_idle_time_secs: 3600
|
||||||
|
#
|
||||||
|
# # SSL 配置,参考官方文档
|
||||||
|
# ssl: false
|
||||||
|
|
||||||
|
### TLS 配置
|
||||||
|
#
|
||||||
|
## Let's Encrypt / ACME
|
||||||
|
#
|
||||||
|
# headscale 支持使用 Let's Encrypt 自动申请 TLS 证书
|
||||||
|
#
|
||||||
|
# ACME 目录 URL
|
||||||
|
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
|
||||||
|
# ACME 注册邮箱
|
||||||
|
acme_email: ""
|
||||||
|
|
||||||
|
# 要申请 TLS 证书的域名
|
||||||
|
tls_letsencrypt_hostname: ""
|
||||||
|
|
||||||
|
# 存储证书和元数据的路径
|
||||||
|
# 生产环境建议:
|
||||||
|
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||||
|
|
||||||
|
# ACME 挑战类型,目前支持:
|
||||||
|
# HTTP-01 或 TLS-ALPN-01
|
||||||
|
# 详见 docs/ref/tls.md
|
||||||
|
tls_letsencrypt_challenge_type: HTTP-01
|
||||||
|
# 使用 HTTP-01 时,letsencrypt 必须监听:
|
||||||
|
# :http = 80 端口
|
||||||
|
tls_letsencrypt_listen: ":http"
|
||||||
|
|
||||||
|
## 使用已有证书
|
||||||
|
tls_cert_path: ""
|
||||||
|
tls_key_path: ""
|
||||||
|
|
||||||
|
log:
|
||||||
|
# 日志输出格式:text 或 json
|
||||||
|
format: text
|
||||||
|
# 日志级别:info, debug, trace
|
||||||
|
level: info
|
||||||
|
|
||||||
|
## 策略
|
||||||
|
# headscale 支持 Tailscale 的 ACL 策略
|
||||||
|
# 文档:https://tailscale.com/kb/1018/acls/
|
||||||
|
policy:
|
||||||
|
# 模式:file 或 database
|
||||||
|
mode: file
|
||||||
|
# 若为 file 模式,指定 HuJSON 文件路径
|
||||||
|
path: ""
|
||||||
|
|
||||||
|
## DNS
|
||||||
|
#
|
||||||
|
# headscale 支持 Tailscale 的 DNS 配置和 MagicDNS。
|
||||||
|
# 文档:
|
||||||
|
# https://tailscale.com/kb/1054/dns/
|
||||||
|
# https://tailscale.com/kb/1081/magicdns/
|
||||||
|
# https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
|
||||||
|
#
|
||||||
|
# 注意:要使 DNS 配置生效,客户端必须启用 `--accept-dns=true`。
|
||||||
|
# 否则将不生效。
|
||||||
|
dns:
|
||||||
|
# 是否启用 MagicDNS
|
||||||
|
magic_dns: true
|
||||||
|
|
||||||
|
# MagicDNS 的基础域名,必须与 server_url 域名不同。
|
||||||
|
base_domain: example.com
|
||||||
|
|
||||||
|
# 是否覆盖本地 DNS 设置
|
||||||
|
override_local_dns: false
|
||||||
|
|
||||||
|
# 全局 DNS 服务器列表
|
||||||
|
nameservers:
|
||||||
|
global:
|
||||||
|
- 1.1.1.1
|
||||||
|
- 1.0.0.1
|
||||||
|
- 2606:4700:4700::1111
|
||||||
|
- 2606:4700:4700::1001
|
||||||
|
# NextDNS 示例
|
||||||
|
# - https://dns.nextdns.io/abc123
|
||||||
|
|
||||||
|
# Split DNS 示例(为特定域使用不同 DNS)
|
||||||
|
split: {}
|
||||||
|
|
||||||
|
# 自定义搜索域
|
||||||
|
search_domains: []
|
||||||
|
|
||||||
|
# 额外 DNS 记录(支持 A/AAAA)
|
||||||
|
extra_records: []
|
||||||
|
# - name: "grafana.myvpn.example.com"
|
||||||
|
# type: "A"
|
||||||
|
# value: "100.64.0.3"
|
||||||
|
|
||||||
|
# CLI 使用的 Unix socket(无认证)
|
||||||
|
# 生产环境建议自定义
|
||||||
|
unix_socket: /var/run/headscale/headscale.sock
|
||||||
|
unix_socket_permission: "0770"
|
||||||
|
|
||||||
|
# OpenID Connect 配置(实验功能)
|
||||||
|
# oidc:
|
||||||
|
# only_start_if_oidc_is_available: true
|
||||||
|
# issuer: "https://your-oidc.issuer.com/path"
|
||||||
|
# client_id: "your-oidc-client-id"
|
||||||
|
# client_secret: "your-oidc-client-secret"
|
||||||
|
# client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
|
||||||
|
# expiry: 180d
|
||||||
|
# use_expiry_from_token: false
|
||||||
|
# scope: ["openid", "profile", "email", "custom"]
|
||||||
|
# extra_params:
|
||||||
|
# domain_hint: example.com
|
||||||
|
# allowed_domains:
|
||||||
|
# - example.com
|
||||||
|
# allowed_groups:
|
||||||
|
# - /headscale
|
||||||
|
# allowed_users:
|
||||||
|
# - alice@example.com
|
||||||
|
# pkce:
|
||||||
|
# enabled: false
|
||||||
|
# method: S256
|
||||||
|
|
||||||
|
# Logtail 配置
|
||||||
|
# Logtail 是 Tailscale 的日志与审计系统
|
||||||
|
logtail:
|
||||||
|
# 启用后,客户端将日志发送到 Tailscale 服务器
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# 启用后,设备将优先使用随机端口进行 WireGuard 流量
|
||||||
|
# 以避免某些防火墙兼容性问题。
|
||||||
|
# 详见:https://tailscale.com/kb/1181/firewalls/
|
||||||
|
randomize_client_port: false
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
设置反向代理:
|
||||||
|
公网域名->127.0.0.1:9092
|
||||||
|
```txt
|
||||||
|
location /web {
|
||||||
|
index index.html;
|
||||||
|
alias /shumengya/headscale/web;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
7
public/mengyanote/AI/AI大模型应用拆解.md
Normal file
7
public/mengyanote/AI/AI大模型应用拆解.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
> 此笔记记录一些AI工具的应用原理,给自己制作此类工具提供一点思路
|
||||||
|
|
||||||
|
AI老师阅卷批改:
|
||||||
|
OCR文字识别->大语言模型文本处理
|
||||||
|
|
||||||
|
AI视频总结(bilinote):
|
||||||
|
下载视频->提取音频->音频转文字->大语言模型文本处理
|
||||||
@@ -1,33 +1,21 @@
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name mysql \
|
--name mysql_latest \
|
||||||
-e MYSQL_ROOT_PASSWORD=shumengya520 \
|
-p 3306:3306 \
|
||||||
-e MYSQL_DATABASE=shumengyadb \
|
-v /shumengya/docker/storage/mysql:/var/lib/mysql \
|
||||||
-e MYSQL_USER=shumengya \
|
-e MYSQL_ROOT_PASSWORD=shumengya520 \
|
||||||
-e MYSQL_PASSWORD=shumengya520 \
|
--memory=4g \
|
||||||
-v /shumengya/docker/storage/mysql:/var/lib/mysql \
|
--cpus=4 \
|
||||||
-p 3306:3306 \
|
mysql:latest
|
||||||
--restart=always \
|
|
||||||
mysql:latest
|
|
||||||
|
|
||||||
|
|
||||||
docker run -d \
|
|
||||||
--name mysql \
|
|
||||||
-e MYSQL_ROOT_PASSWORD=shumengya520 \
|
|
||||||
-e MYSQL_DATABASE=shumengyadb \
|
|
||||||
-e MYSQL_USER=shumengya \
|
|
||||||
-e MYSQL_PASSWORD=shumengya520 \
|
|
||||||
-v /shumengya/docker/storage/mysql:/var/lib/mysql \
|
|
||||||
-p 3306:3306 \
|
|
||||||
--restart=always \
|
|
||||||
mysql:5.7.44
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#典型的非关系型数据库(json)
|
#典型的非关系型数据库(json)
|
||||||
docker pull mysql:5.7.44
|
docker pull mysql:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
#MongoDB数据库
|
#Redis数据库
|
||||||
docker run -d --name mongodb \
|
docker run -d --name redis-server \
|
||||||
-e MONGO_INITDB_ROOT_USERNAME=shumengya \
|
-p 6379:6379 \
|
||||||
-e MONGO_INITDB_ROOT_PASSWORD=shumengya520 \
|
redis:latest \
|
||||||
-v /shumengya/docker/storage/mongodb:/data/db \
|
redis-server --requirepass "shumengya520"
|
||||||
-p 27017:27017 \
|
|
||||||
mongo
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#典型的非关系型数据库(json)
|
|
||||||
docker pull mongo
|
docker pull redis
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 1991:1991 \
|
||||||
|
--memory=4g \
|
||||||
|
--cpus=4 \
|
||||||
|
surveyking/surveyking
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
32
public/mengyanote/Docker/优秀好用的Docker镜像/frp-内网穿透神器.md
Normal file
32
public/mengyanote/Docker/优秀好用的Docker镜像/frp-内网穿透神器.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
```bash
|
||||||
|
#启动最新版frp客户端
|
||||||
|
docker run -d \
|
||||||
|
--name frpc \
|
||||||
|
--restart=always \
|
||||||
|
--network host \
|
||||||
|
-v /shumengya/docker/storage/frpc:/etc/frp \
|
||||||
|
-e TZ=Asia/Shanghai \
|
||||||
|
natfrp/frpc:latest \
|
||||||
|
-c /etc/frp/frpc.toml
|
||||||
|
|
||||||
|
#启动最新版frp服务端
|
||||||
|
docker run -d \
|
||||||
|
--name frps \
|
||||||
|
--restart=always \
|
||||||
|
--network host \
|
||||||
|
-e TZ=Asia/Tokyo \
|
||||||
|
-v /shumengya/docker/storage/frps:/etc/frp \
|
||||||
|
snowdreamtech/frps:latest \
|
||||||
|
-c /etc/frp/frps.toml
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
24
public/mengyanote/Docker/优秀好用的Docker镜像/tailscale-ip-derp.md
Normal file
24
public/mengyanote/Docker/优秀好用的Docker镜像/tailscale-ip-derp.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name derper \
|
||||||
|
-p 33445:13477/tcp \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \
|
||||||
|
-e DERP_ADDR=":33445" \
|
||||||
|
-e DERP_VERIFY_CLIENTS=true \
|
||||||
|
ghcr.io/yangchuansheng/ip_derper:latest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#典型的非关系型数据库(json)
|
||||||
|
docker pull lanol/filecodebox:beta
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
docker stop lanol/filecodebox:beta
|
||||||
|
docker rm lanol/filecodebox:beta
|
||||||
|
```
|
||||||
14
public/mengyanote/Docker/优秀好用的Docker镜像/模板.md
Normal file
14
public/mengyanote/Docker/优秀好用的Docker镜像/模板.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
下面给你 **最快速、常用且实用** 的几种方法 —— 你可以按自己环境选一种直接复制运行(都有最短命令和一段可跑的代码示例)。注意:这些方法适合本地开发与临时文件共享;若要对公网长期暴露,需加强安全配置(见结尾安全提示)。
|
|
||||||
|
|
||||||
# 1) 最快:Python(适用于已装 Python 3)
|
# 1) 最快:Python(适用于已装 Python 3)
|
||||||
|
|
||||||
@@ -82,23 +81,5 @@ Start-Process -NoNewWindow -FilePath "python" -ArgumentList "-m http.server 8000
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# HTTPS / 暴露到公网(临时)
|
|
||||||
|
|
||||||
- 暂时要把本地端口暴露到公网,可用 `ngrok`、`cloudflared` 等隧道工具(需安装并登录)。
|
|
||||||
|
|
||||||
- 若需要本地 HTTPS 简易方案,推荐使用 Caddy(自动 TLS)或为开发环境用 mkcert 生成证书并配置 nginx / Caddy。
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 小结与安全提示(必读)
|
|
||||||
|
|
||||||
- 以上方法都很快,**开发/调试/本地文件分享** 推荐 Python、http-server、PHP。
|
|
||||||
|
|
||||||
- **不要** 在不做认证/权限控制的情况下把敏感目录暴露到公网。
|
|
||||||
|
|
||||||
- 若要在局域网共享,使用 `--bind 0.0.0.0`(或相应选项)并确保防火墙策略允许。
|
|
||||||
|
|
||||||
- 生产环境请用经过配置的 nginx/Apache/Caddy,并启用 HTTPS、访问控制与日志。
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
73
public/mengyanote/内网穿透/Frp的kcp和quic的区别和特点.md
Normal file
73
public/mengyanote/内网穿透/Frp的kcp和quic的区别和特点.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 基础:QUIC 与 KCP 本身的区别(协议层面)
|
||||||
|
|
||||||
|
要理解 FRP 下这两种模式的差别,首先必须认识 QUIC 与 KCP 两种协议在 UDP 之上的设计差异。下面从几个维度来对比。
|
||||||
|
|
||||||
|
|维度|KCP|QUIC|
|
||||||
|
|---|---|---|
|
||||||
|
|协议定位 / 设计目标|一个可靠的 UDP 层协议(“可靠 UDP + ARQ + 拥塞控制 + 重传策略”),强调低延迟、对弱网络适应性较好。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com "KCP协议:从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ..."))|更现代的传输层协议,最初由 Google 设计,后来演化成为 HTTP/3 的底层传输(即:QUIC + TLS + 多路复用)的一部分。它在 UDP 之上集成了连接管理、多路复用、拥塞控制、0-RTT、TLS 加密等机制。 ([CSDN博客](https://blog.csdn.net/qq_36541069/article/details/132143729?utm_source=chatgpt.com "所得杂记:KCP,QUIC,MQTT - CSDN博客"))|
|
||||||
|
|连接建立 / 握手延迟|KCP 在使用上一般是比较“轻”的握手(因为只是建立会话 ID 等),延迟比较低|QUIC 支持 0-RTT、较快握手(因为集成 TLS)等机制,从连接建立角度更有优势|
|
||||||
|
|多路复用 / 多流支持|传统 KCP 是面向“单流”(一个会话对应一个流式数据)。要实现真正的多路复用,需要在上层自己设计;否则每条独立连接就是一个 KCP 实例|QUIC 原生支持多流(multiple streams)和流内优先级,能在一个连接上同时承载多个逻辑数据流,减少队头阻塞(Head-of-line blocking)的问题|
|
||||||
|
|拥塞控制 / 拥塞算法|KCP 自己有拥塞控制与窗口机制,也可以调节参数去“弱化”拥塞控制以换取低延迟。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com "KCP协议:从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ..."))|QUIC 的拥塞控制受到现代研究和 TCP 的启发,有较为成熟的拥塞控制与流量控制算法;它也能动态适应网络变化|
|
||||||
|
|丢包 / 重传机制|KCP 使用选择性重传 (Selective Retransmission)、快速重传、延迟 ACK 调节等策略来减少重传滞后和延迟惩罚。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com "KCP协议:从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ..."))|QUIC 也具备细粒度的 ACK / 重传机制,有更复杂的 ACK / 确认策略,集成了更现代的重传算法|
|
||||||
|
|加密 / 安全|KCP 本身通常是“裸协议”或可选加密(上层或 FRP 在其上做加密)|QUIC 本身设计是**加密为默认**(TLS 集成在协议里),所有控制面与数据面都加密,更能防止中间人干扰、流量识别等问题|
|
||||||
|
|开销 / 资源占用|相对轻量;因为协议栈简单,控制开销、头部开销较低|更复杂,协议处理开销更大(比如加密、握手、流管理、ACK 处理等)|
|
||||||
|
|在极端场景 / 性能瓶颈下表现|在高延迟 + 大包 / 大数据量 + 丢包环境下,KCP 性能可能下降。比如有测试指出在**高延迟 + 发送超过 MTU 的数据**时,KCP 的延迟会显著恶化。 ([GitHub](https://github.com/xtaci/kcp-go/issues/204?utm_source=chatgpt.com "对比TCP/QUIC/KCP的测试结果 · Issue #204 · xtaci/kcp-go - GitHub"))|在这些情况下,QUIC 的设计通常更稳健一些,更能处理大流量、多个流、多并发场景|
|
||||||
|
|
||||||
|
从这些对比来看,QUIC 在协议设计上更“现代”、更全面、更关注安全性与多路复用,而 KCP 更加轻量、灵活,适合对实时性、低延迟要求比较高的场景。
|
||||||
|
|
||||||
|
不过,协议设计优劣并不是绝对的,具体在 FRP 的应用场景下,还要考虑实现、参数调优、网络环境等因素。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 在 FRP 中:QUIC 模式 vs KCP 模式的区别与表现
|
||||||
|
|
||||||
|
FRP 支持将底层通信协议从默认的 TCP / HTTPTransport 切换成 KCP 或 QUIC(即 `transport.protocol = "kcp"` 或 `"quic"`)模式。官方文档里对此有说明。 ([gofrp.org](https://gofrp.org/en/docs/features/common/network/network/?utm_source=chatgpt.com "Communication Security and Optimization | frp"))
|
||||||
|
|
||||||
|
下面是两种模式在 FRP 中常见的差别、优缺点、使用注意。
|
||||||
|
|
||||||
|
### 优点 / 劣势对比
|
||||||
|
|
||||||
|
|特性 / 维度|FRP + KCP 模式|FRP + QUIC 模式|
|
||||||
|
|---|---|---|
|
||||||
|
|延迟表现 / 实时响应|通常优于 TCP,尤其在丢包 / 抖动较大、网络不稳定的环境下。很多用户用 KCP 模式来加速远程桌面、SSH 等。 ([CSDN博客](https://blog.csdn.net/MENGHUANBEIKE/article/details/100793876?utm_source=chatgpt.com "利用frp内网穿透kcp模式做跳板,加速流畅访问远程桌面3389"))|在连接建立、短连接场景以及多流场景中,QUIC 有优势;也能在某些网络被封、被干扰的情况下更抗阻断性(因为包头更难识别)|
|
||||||
|
|抗网络干扰 / 被封锁风险|KCP 尽管在 UDP 上传输,但协议本身特征可能比较容易被识别;在被运营商主动干扰 UDP 流量的环境中可能被限速或封锁|QUIC 本身带加密和混淆特性,更难被中间设备识别,某些用户用 QUIC 模式来规避“被运营商阻断 FRP TCP 连接”的情况。比如有一篇博客指出,TCP 模式在某些校园网或被 ISP 限制时连接失败,而改用 QUIC 协议就能恢复连接。 ([ZRHan's Blog](https://blog.zrhan.top/2024/07/14/%E7%94%A8quic%E5%8D%8F%E8%AE%AE%E8%A7%A3%E5%86%B3frp%E8%A2%AB%E8%BF%90%E8%90%A5%E5%95%86%E9%98%BB%E6%96%AD%E7%9A%84%E9%97%AE%E9%A2%98/?utm_source=chatgpt.com "用quic协议解决frp被运营商阻断的问题 - ZRHan's Blog"))|
|
||||||
|
|带宽开销 / 效率|KCP 为了追求低延迟,会在一定程度上牺牲一些带宽效率(可能会有额外重传、冗余、控制包开销等) ([gofrp.org](https://gofrp.org/en/docs/features/common/network/network/?utm_source=chatgpt.com "Communication Security and Optimization \| frp"))|QUIC 在设计上对带宽利用率考虑较多,控制与重传机制更复杂,会在多流、大连接场景下更高效|
|
||||||
|
|多代理 / 多连接 / 并发|KCP 模式下,如果你在一个 FRP 实例下跑很多代理 / 多条连接,每条连接都是一条 KCP,会有一定管理开销|QUIC 的多流 / 多路复用设计可以在一个连接上承载多个代理或多个数据流,更理想地减少连接数和开销|
|
||||||
|
|实现稳定性 / Bug 风险|KCP 在 FRP 中被使用较久、成熟度较高,用户社区案例较多,参数调优经验丰富|QUIC 是相对较新、更复杂的模式,在 FRP 中可能还存在一些 bug 或限制;例如,有 issue 提到 “无法单独运行在 QUIC 模式” 的问题——无论是否配置 bind_port 字段,frps 总会监听 TCP 端口(这个 issue 在 FRP 的 issue 列表里被关闭为“不计划修复”)([GitHub](https://github.com/fatedier/frp/issues/3225?utm_source=chatgpt.com "无法单独运行在quic模式 · Issue #3225 · fatedier/frp · GitHub"))|
|
||||||
|
|参数调优空间 / 灵活性|KCP 的很多参数(MTU、窗口、nodelay、重传策略等)都可以调,灵活性高;但需要手动调优以适应网络环境|QUIC 的很多机制是在协议内部做的(如流控、拥塞控制、加密层),对用户的参数调控空间可能较少(或复杂)|
|
||||||
|
|适用场景|需要低延迟或在弱网络环境里工作的服务(如 SSH、RDP、交互式服务)|多流服务、HTTP(s) 代理、长连接传输、多代理复用、抗干扰场合等可能更适合|
|
||||||
|
|
||||||
|
综合来看:如果你现在主要是用 FRP 来做一些 SSH、远程桌面、交互性强的服务,或者网络环境不稳定/丢包率高,KCP 模式可能是更稳定、可控的选择。而如果你需要让 FRP 在更复杂的网络环境下更具抗封锁性、更现代化、更高效,QUIC 模式是一个很有吸引力的选项。
|
||||||
|
|
||||||
|
### 在 FRP 上使用时的注意与限制
|
||||||
|
|
||||||
|
- 要让 QUIC / KCP 模式生效,你需要在 frps 和 frpc 两边都正确配置对应的端口(`quicBindPort` / `kcpBindPort` 等)与 `transport.protocol = "quic"` 或 `"kcp"`。否则默认仍用 TCP。 ([格态随记](https://blog.gotab.cn/archives/RvdYvu2g?utm_source=chatgpt.com "Frp:服务端 frps.toml 和 frpc.toml 客户端配置文件详解"))
|
||||||
|
|
||||||
|
- 防火墙 / UDP 端口必须开放 — 因为 KCP / QUIC 都是在 UDP 上运行的,无法简单依赖 TCP。
|
||||||
|
|
||||||
|
- 参数调优很关键:KCP 有很多参数(如 `nodelay`、`interval`、窗口大小、重传策略等)需要根据网络环境调整,否则可能效果不好或发生延迟爆炸。
|
||||||
|
|
||||||
|
- QUIC 模式在 FRP 中可能还不够成熟 / 存在一些边界 bug。例如前面提到的 “无法单独运行在 QUIC 模式” 问题就是一个。 ([GitHub](https://github.com/fatedier/frp/issues/3225?utm_source=chatgpt.com "无法单独运行在quic模式 · Issue #3225 · fatedier/frp · GitHub"))
|
||||||
|
|
||||||
|
- 在高带宽 / 长距离 /大流量场景下,KCP 模式可能表现不如预期,因为协议本身在大包 / 高延迟 + 数据量大时延迟会膨胀。实测中有用户发现,在延迟较高 + 发送大于 MTU 的数据场景下,QUIC 表现优于 KCP。 ([GitHub](https://github.com/xtaci/kcp-go/issues/204?utm_source=chatgpt.com "对比TCP/QUIC/KCP的测试结果 · Issue #204 · xtaci/kcp-go - GitHub"))
|
||||||
|
|
||||||
|
- 加密开销:如果你还在 FRP 上启用 TLS / 加密,QUIC 本身就有加密,叠加可能有额外开销;KCP 则通常是裸或可选加密,开销可能较低。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总结 & 建议
|
||||||
|
|
||||||
|
- **优势倾向**
|
||||||
|
- 若你更注重“稳定 + 可控 + 低延迟 + 在弱网环境下表现好”,KCP 是一个比较稳妥的选择(尤其已有成熟经验)
|
||||||
|
- 若你更希望未来扩展性强、支持多流、抗干扰 / 抗封锁能力更好、连接更现代化,QUIC 是更有前景的选择
|
||||||
|
|
||||||
|
- **实用建议**
|
||||||
|
1. 在你的网络环境下做对比测试:部署一个用 KCP,一个用 QUIC,测一下延迟、丢包率、吞吐量、稳定性,哪一个更符合你的场景就用哪个。
|
||||||
|
2. 若你目前已有稳定的 KCP 环境且能满足需求,不必急于切换;只有在遇到 TCP 被封锁 / 性能瓶颈 / 抗干扰需求时,再考虑 QUIC。
|
||||||
|
3. 在启用 QUIC(或 KCP)模式时,务必留一个“回退”方案(例如保留 TCP 模式),以防 QUIC 模式在某些网络环境下连接失败 / 不稳定。
|
||||||
|
4. 多关注 FRP 的版本更新、issue 列表,特别是关于 QUIC 模式的 bug 或兼容性问题。
|
||||||
|
|
||||||
195
public/mengyanote/内网穿透/frp客户端配置.md
Normal file
195
public/mengyanote/内网穿透/frp客户端配置.md
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
|
||||||
|
```toml
|
||||||
|
#=============================================================================
|
||||||
|
#===================================基础设置===================================
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
serverAddr = "47.108.90.0"
|
||||||
|
serverPort = 7000
|
||||||
|
|
||||||
|
auth.method = "token"
|
||||||
|
auth.token = "smy"
|
||||||
|
|
||||||
|
webServer.addr = "0.0.0.0"
|
||||||
|
webServer.port = 7400
|
||||||
|
webServer.user = "shumengya"
|
||||||
|
webServer.password = "tyh@19900420"
|
||||||
|
webServer.pprofEnable = false
|
||||||
|
|
||||||
|
#下面两个二选一
|
||||||
|
transport.protocol = "kcp"
|
||||||
|
#transport.protocol = "quic"
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
log.to = "console"
|
||||||
|
log.level = "info"
|
||||||
|
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
#===================================Http服务===================================
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# 萌芽盘-openlist
|
||||||
|
[[proxies]]
|
||||||
|
name = "openlist"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 5244
|
||||||
|
customDomains = ["openlist.shumengya.top","pan.shumengya.top"]
|
||||||
|
|
||||||
|
|
||||||
|
#大萌芽1panel面板-1panel
|
||||||
|
[[proxies]]
|
||||||
|
name = "1panel"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 19132
|
||||||
|
customDomains = ["1panel.shumengya.top"]
|
||||||
|
|
||||||
|
|
||||||
|
#Obsidian笔记同步-couchdb
|
||||||
|
[[proxies]]
|
||||||
|
name = "couchdb"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 5984
|
||||||
|
customDomains = ["note.shumengya.top"]
|
||||||
|
|
||||||
|
#大萌芽frp客户端-frpc
|
||||||
|
[[proxies]]
|
||||||
|
name = "frpc"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 7400
|
||||||
|
customDomains = ["frpc.shumengya.top"]
|
||||||
|
|
||||||
|
#萌芽文件快传-filecodebox
|
||||||
|
[[proxies]]
|
||||||
|
name = "filecodebox"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 12345
|
||||||
|
customDomains = ["file.shumengya.top","send.shumengya.top"]
|
||||||
|
|
||||||
|
#萌芽图床-lsky-pro
|
||||||
|
[[proxies]]
|
||||||
|
name = "lsky-pro"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8089
|
||||||
|
customDomains = ["image.shumengya.top","img.shumengya.top"]
|
||||||
|
|
||||||
|
#在线代码编辑器-codeserver
|
||||||
|
[[proxies]]
|
||||||
|
name = "codeserver"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8888
|
||||||
|
customDomains = ["code.shumengya.top"]
|
||||||
|
|
||||||
|
#60sAPI接口集合-60sapi
|
||||||
|
[[proxies]]
|
||||||
|
name = "60s-API"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 4399
|
||||||
|
customDomains = ["60s.api.shumengya.top"]
|
||||||
|
|
||||||
|
#社交媒体视频ai总结-bilinote
|
||||||
|
[[proxies]]
|
||||||
|
name = "bilinote"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 3015
|
||||||
|
customDomains = ["bilinote.shumengya.top"]
|
||||||
|
|
||||||
|
#萌芽git仓库-gitea
|
||||||
|
[[proxies]]
|
||||||
|
name = "gitea"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8989
|
||||||
|
customDomains = ["repo.shumengya.top"]
|
||||||
|
|
||||||
|
#Docker可视化面板-DPanel
|
||||||
|
[[proxies]]
|
||||||
|
name = "dpanel"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8800
|
||||||
|
customDomains = ["dpanel.shumengya.top"]
|
||||||
|
|
||||||
|
#萌芽通知-ntfy
|
||||||
|
[[proxies]]
|
||||||
|
name = "ntfy"
|
||||||
|
type = "http"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 82
|
||||||
|
customDomains = ["ntfy.shumengya.top"]
|
||||||
|
|
||||||
|
#萌芽大内网管理后台-openwrt
|
||||||
|
[[proxies]]
|
||||||
|
name = "openwrt"
|
||||||
|
type = "http"
|
||||||
|
localIP = "192.168.1.1"
|
||||||
|
localPort = 80
|
||||||
|
customDomains = ["openwrt.shumengya.top"]
|
||||||
|
|
||||||
|
#=========================================================================
|
||||||
|
#===================================TCP服务=================================
|
||||||
|
#=========================================================================
|
||||||
|
|
||||||
|
#萌芽农场远程控制台
|
||||||
|
[[proxies]]
|
||||||
|
name = "mengyafarm-config"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 7071
|
||||||
|
remotePort = 6060
|
||||||
|
|
||||||
|
#mysql数据库
|
||||||
|
[[proxies]]
|
||||||
|
name = "mysql"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 3306
|
||||||
|
remotePort = 3307 # frps 上的映射端口
|
||||||
|
|
||||||
|
#MongoDB数据库
|
||||||
|
[[proxies]]
|
||||||
|
name = "mongodb"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 27017
|
||||||
|
remotePort = 27018
|
||||||
|
|
||||||
|
#Postgres数据库
|
||||||
|
[[proxies]]
|
||||||
|
name = "postgres"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 5432
|
||||||
|
remotePort = 5433
|
||||||
|
|
||||||
|
#大萌芽-Debian11 SSH连接
|
||||||
|
[[proxies]]
|
||||||
|
name = "bigmengya-ssh"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 22
|
||||||
|
remotePort = 9022
|
||||||
|
|
||||||
|
#Redis数据库
|
||||||
|
[[proxies]]
|
||||||
|
name = "redis"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 6379
|
||||||
|
remotePort = 6380
|
||||||
|
|
||||||
|
|
||||||
|
#=========================================================================
|
||||||
|
#===================================UDP服务=================================
|
||||||
|
#=========================================================================
|
||||||
|
|
||||||
|
```
|
||||||
36
public/mengyanote/内网穿透/frp服务端配置.md
Normal file
36
public/mengyanote/内网穿透/frp服务端配置.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
```toml
|
||||||
|
# frp服务端配置 - 作为nginx后端服务
|
||||||
|
# 与nginx配合使用,提供HTTPS支持
|
||||||
|
|
||||||
|
bindAddr = "0.0.0.0"
|
||||||
|
bindPort = 7000
|
||||||
|
|
||||||
|
#下面两个二选一
|
||||||
|
kcpBindPort = 7000 # KCP 监听的 UDP 端口(可与 bindPort 相同)
|
||||||
|
#quicBindPort = 7000 # QUIC 使用的 UDP 端口(与 bindPort 可相同)
|
||||||
|
|
||||||
|
[auth]
|
||||||
|
auth.method = "token"
|
||||||
|
auth.token = "smy"
|
||||||
|
|
||||||
|
# HTTP配置 - 作为后端服务(nginx代理)
|
||||||
|
vhostHTTPPort = 8080 # nginx代理到此端口
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
log.to = "console"
|
||||||
|
log.level = "info"
|
||||||
|
|
||||||
|
# 管理界面
|
||||||
|
[webServer]
|
||||||
|
webServer.addr = "0.0.0.0"
|
||||||
|
webServer.port = 7500
|
||||||
|
webServer.user = "shumengya"
|
||||||
|
webServer.password = "tyh@19900420"
|
||||||
|
|
||||||
|
[transport]
|
||||||
|
tcpMux = true # 如要关闭 tcp 多路复用(默认启用)
|
||||||
|
maxPoolCount = 10 # 服务端允许的最大连接池数量
|
||||||
|
tls.force = false # 不强制客户端必须 TLS(除非你要强制安全)
|
||||||
|
```
|
||||||
|
|
||||||
19
public/mengyanote/内网穿透/内网穿透方案.md
Normal file
19
public/mengyanote/内网穿透/内网穿透方案.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、开源替代方案 /工具清单
|
||||||
|
|
||||||
|
下面是目前社区里比较流行 /有实用性的开源方案:
|
||||||
|
|
||||||
|
|名称|语言 / 技术栈|支持协议 /功能|特点 /亮点|可能缺点 /注意|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|**rathole**|Rust|TCP / HTTP /TLS|轻量、高性能,内存占用低,支持热重载、服务令牌认证等。被设计为 FRP / ngrok 的替代品。 ([GitHub](https://github.com/rathole-org/rathole?utm_source=chatgpt.com "GitHub - rathole-org/rathole: A lightweight and high-performance ..."))|文档 /社区可能不如 FRP 那么成熟;一些边缘功能可能欠缺|
|
||||||
|
|**NSmartProxy**|.NET Core / C#|TCP / HTTP 反向代理 /穿透|跨平台支持好,用异步 I/O 架构驱动穿透代理。 ([GitHub](https://github.com/tmoonlight/NSmartProxy?utm_source=chatgpt.com "GitHub - tmoonlight/NSmartProxy: NSmartProxy是一款开源的内网穿透工具。采用.NET CORE ..."))|在 Linux /非 .NET 平台上的稳定性 /优化要测试;社区规模可能偏小|
|
||||||
|
|**Tunnelmole**|Node.js / TypeScript|HTTP / HTTPS 隧道|100% 开源、可自托管、方便给本地 Web 服务生成公开 URL。 ([tunnelmole.com](https://tunnelmole.com/?utm_source=chatgpt.com "Tunnelmole - A free and open source tunneling tool"))|主要面向 HTTP/HTTPS,游戏 /通用 TCP 服务可能支持不够好;对于高并发 /大流量性能需要评估|
|
||||||
|
|**Reverse Proxy Tool(基于 Netty 的)**|Java / Netty|支持任意 TCP 上层协议和 HTTP|支持 HTTP 升级、SSL 验证、协议透传等功能。 ([Gitee](https://gitee.com/codebanks/reverse-proxy-tool?utm_source=chatgpt.com "Reverse Proxy Tool: Reverse Proxy Tool : 基于Netty实现的 ..."))|Java 程序可能资源占用较高;配置可能稍复杂;性能需要根据 JVM 优化|
|
||||||
|
|**nps / NPS** / **lanproxy** / **holer**|Go /其他|TCP / HTTP /UDP 穿透、反向代理|在「开源内网穿透工具」合集 /对比文章里经常被提及。 ([laoliang.net](https://www.laoliang.net/jsjh/technology/14975.html?utm_source=chatgpt.com "归纳几种免费开源的内网穿透工具(frp、holer、nps、lanproxy)"))|各工具在稳定性、协议支持深度、社区维护度上有差别;需要逐个评估|
|
||||||
|
|**reverse-tunnel(snsi nfu 的项目)**|(未知 /社区项目)|公网 → 私网 隧道 /映射|提供反向隧道映射能力,据社区介绍可以做安全隧道。 ([CSDN.blog](https://blog.csdn.net/gitblog_01080/article/details/141481391?utm_source=chatgpt.com "反向隧道工具 reverse-tunnel 使用指南-CSDN博客"))|项目可能成熟度不高,文档 /示例可能不足;功能边界需自己测试|
|
||||||
|
|**tiny-frpc**|Go / 精简 FRP 客户端|frp 协议子集|体积小、适合资源紧张的嵌入式 /小设备使用。 ([博客园](https://www.cnblogs.com/tang863/p/18274521?utm_source=chatgpt.com "tiny-frpc: frp 反向代理精简版客户端 - AmbiaCode - 博客园"))|只是 frpc 的子集,用于客户端,不是完整替代;功能限制较多|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
388
public/mengyanote/内网穿透/搭建derp和headscale避坑与指南.md
Normal file
388
public/mengyanote/内网穿透/搭建derp和headscale避坑与指南.md
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
derp(Docker安装):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#Docker容器一键化启动
|
||||||
|
#默认开启tcp端口33445 udp端口3478
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper1 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp1/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp1.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp1.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp1.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper2 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp2/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp2.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp2.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp2.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
docker run --restart always \
|
||||||
|
--name derper3 \
|
||||||
|
-p 33445:33445 \
|
||||||
|
-p 3478:3478/udp \
|
||||||
|
-v /shumengya/ssl/derp3/:/app/certs \
|
||||||
|
-e DERP_CERT_MODE=manual \
|
||||||
|
-e DERP_ADDR=:33445 \
|
||||||
|
-e DERP_DOMAIN=derp3.shumengya.top \
|
||||||
|
-e DERP_CERT_FILE=/app/certs/derp3.shumengya.top.crt \
|
||||||
|
-e DERP_KEY_FILE=/app/certs/derp3.shumengya.top.key \
|
||||||
|
-d ghcr.io/yangchuansheng/derper:latest
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#默认使用Let's Encrypt签发ssl证书
|
||||||
|
#默认需要关闭nginx占用80端口来签发证书
|
||||||
|
curl -s https://get.acme.sh | sh
|
||||||
|
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
acme.sh --issue --standalone -d 你的域名
|
||||||
|
#安装依赖
|
||||||
|
apt update && apt install -y socat
|
||||||
|
yum install -y socat
|
||||||
|
dnf install -y socat
|
||||||
|
|
||||||
|
acme.sh --register-account -m 你的邮箱地址
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
headscale(直接部署systemctl运行):
|
||||||
|
|
||||||
|
headscale默认放行:9090~9092 和50443
|
||||||
|
|
||||||
|
配置一个域名:
|
||||||
|
headscale.shumengya.top
|
||||||
|
下载headscale:[https://github.com/juanfont/headscale](headscale)
|
||||||
|
下载headscale-ui:[https://github.com/juanfont/headscale](headscale-ui)
|
||||||
|
|
||||||
|
新建文件夹(用来放相关文件):
|
||||||
|
mkdir -p shumengya/headscale
|
||||||
|
|
||||||
|
安装headscale:
|
||||||
|
dpkg -i headscale_0.26.1_linux_amd64.deb
|
||||||
|
|
||||||
|
修改headscale配置
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# headscale 会按照以下顺序查找名为 `config.yaml` (或 `config.json`) 的配置文件:
|
||||||
|
#
|
||||||
|
# - `/etc/headscale`
|
||||||
|
# - `~/.headscale`
|
||||||
|
# - 当前工作目录
|
||||||
|
|
||||||
|
# 客户端将要连接的 URL。
|
||||||
|
# 通常应为一个域名,例如:
|
||||||
|
#
|
||||||
|
# https://myheadscale.example.com:443
|
||||||
|
#
|
||||||
|
server_url: http://127.0.0.1:9091
|
||||||
|
|
||||||
|
# 服务器监听/绑定的地址
|
||||||
|
#
|
||||||
|
# 生产环境建议:
|
||||||
|
listen_addr: 0.0.0.0:9092
|
||||||
|
#listen_addr: 127.0.0.1:8080
|
||||||
|
|
||||||
|
# /metrics 和 /debug 的监听地址,你可能希望
|
||||||
|
# 将此端点限制在内网
|
||||||
|
metrics_listen_addr: 127.0.0.1:9090
|
||||||
|
|
||||||
|
# gRPC 的监听地址。
|
||||||
|
# gRPC 用于通过 CLI 远程控制 headscale 服务器
|
||||||
|
# 注意:只有在使用有效证书时,远程访问才可用。
|
||||||
|
#
|
||||||
|
# 生产环境建议:
|
||||||
|
grpc_listen_addr: 0.0.0.0:50443
|
||||||
|
#grpc_listen_addr: 127.0.0.1:50443
|
||||||
|
|
||||||
|
# 是否允许 gRPC 管理接口以 **不安全** 模式运行。
|
||||||
|
# 不推荐启用,因为流量将不加密。只有在你完全理解风险时才启用。
|
||||||
|
grpc_allow_insecure: false
|
||||||
|
|
||||||
|
# Noise 部分包含 TS2021 Noise 协议的特定配置
|
||||||
|
noise:
|
||||||
|
# Noise 私钥用于在 headscale 和 Tailscale 客户端之间
|
||||||
|
# 使用新的基于 Noise 的协议加密流量。缺少的密钥将会自动生成。
|
||||||
|
private_key_path: /var/lib/headscale/noise_private.key
|
||||||
|
|
||||||
|
# 为 tailnet 分配地址的 IP 前缀列表。
|
||||||
|
# 每个前缀由 IPv4 或 IPv6 地址 + 前缀长度组成,以斜杠分隔。
|
||||||
|
# 必须在 Tailscale 客户端支持的范围内
|
||||||
|
# 即 100.64.0.0/10 和 fd7a:115c:a1e0::/48 的子网。
|
||||||
|
# 否则会导致异常问题。
|
||||||
|
prefixes:
|
||||||
|
v4: 100.64.0.0/10
|
||||||
|
#v6: fd7a:115c:a1e0::/48
|
||||||
|
|
||||||
|
# 节点 IP 分配策略,可选:
|
||||||
|
# - sequential(默认):按顺序分配下一个可用 IP
|
||||||
|
# - random:使用伪随机生成器分配可用 IP
|
||||||
|
allocation: sequential
|
||||||
|
|
||||||
|
# DERP 是 Tailscale 在无法建立直连时使用的中继系统。
|
||||||
|
# https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
|
||||||
|
#
|
||||||
|
# headscale 需要一个 DERP 服务器列表供客户端使用。
|
||||||
|
derp:
|
||||||
|
server:
|
||||||
|
# 启用后,将运行内置 DERP 服务器并合并到 DERP 配置中
|
||||||
|
# 上面的 server_url 必须使用 https,DERP 需要 TLS
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# 内置 DERP 服务器的区域 ID。
|
||||||
|
# 如果与外部配置的区域 ID 冲突,则本地 DERP 优先。
|
||||||
|
region_id: 999
|
||||||
|
|
||||||
|
# 区域代码和名称会在 Tailscale UI 中显示
|
||||||
|
region_code: "headscale"
|
||||||
|
region_name: "Headscale Embedded DERP"
|
||||||
|
|
||||||
|
# 在指定地址上监听 UDP 端口以支持 STUN 连接(帮助 NAT 穿透)。
|
||||||
|
# 如果启用内置 DERP,必须定义 stun_listen_addr。
|
||||||
|
#
|
||||||
|
# 更多详情可参考:https://tailscale.com/blog/how-tailscale-works/
|
||||||
|
stun_listen_addr: "0.0.0.0:3478"
|
||||||
|
|
||||||
|
# 用于加密 headscale DERP 与 Tailscale 客户端之间流量的私钥。
|
||||||
|
# 缺少时会自动生成。
|
||||||
|
private_key_path: /var/lib/headscale/derp_server_private.key
|
||||||
|
|
||||||
|
# 此标志用于控制是否自动将内置 DERP 写入 DERP map。
|
||||||
|
# 若设为 false,则需通过 DERP.paths 手动配置。
|
||||||
|
automatically_add_embedded_derp_region: true
|
||||||
|
|
||||||
|
# 为了更稳定的连接(特别是 Exit-Node + DNS 不可用时),
|
||||||
|
# 可以选择性地将公网 IPv4/IPv6 地址写入 Derp-Map:
|
||||||
|
ipv4: 1.2.3.4
|
||||||
|
ipv6: 2001:db8::1
|
||||||
|
|
||||||
|
# 外部可用的 DERP map 列表(JSON 格式)
|
||||||
|
urls:
|
||||||
|
# - https://controlplane.tailscale.com/derpmap/default
|
||||||
|
#- https://你的域名/web/derp.json
|
||||||
|
|
||||||
|
# 本地可用的 DERP map 文件(YAML 格式)
|
||||||
|
#
|
||||||
|
# 对于自建 DERP 服务器很有用:
|
||||||
|
# https://tailscale.com/kb/1118/custom-derp-servers/
|
||||||
|
#
|
||||||
|
# paths:
|
||||||
|
# - /etc/headscale/derp-example.yaml
|
||||||
|
paths: []
|
||||||
|
|
||||||
|
# 若启用,将定期刷新上述 DERP 源并更新 derpmap
|
||||||
|
auto_update_enabled: true
|
||||||
|
|
||||||
|
# 检查 DERP 更新的间隔
|
||||||
|
update_frequency: 24h
|
||||||
|
|
||||||
|
# 禁用启动时自动检查 headscale 更新
|
||||||
|
disable_check_updates: false
|
||||||
|
|
||||||
|
# 非活跃临时节点在多久后被删除?
|
||||||
|
ephemeral_node_inactivity_timeout: 30m
|
||||||
|
|
||||||
|
database:
|
||||||
|
# 数据库类型,可选:sqlite, postgres
|
||||||
|
# 注意:强烈不推荐使用 Postgres,仅为遗留原因保留。
|
||||||
|
# 所有新开发和优化都基于 SQLite。
|
||||||
|
type: sqlite
|
||||||
|
|
||||||
|
# 启用调试模式。需要 log.level 设置为 "debug" 或 "trace"。
|
||||||
|
debug: false
|
||||||
|
|
||||||
|
# GORM 配置
|
||||||
|
gorm:
|
||||||
|
# 启用预编译语句。
|
||||||
|
prepare_stmt: true
|
||||||
|
|
||||||
|
# 启用参数化查询。
|
||||||
|
parameterized_queries: true
|
||||||
|
|
||||||
|
# 跳过 “record not found” 错误日志。
|
||||||
|
skip_err_record_not_found: true
|
||||||
|
|
||||||
|
# 慢查询阈值(毫秒)
|
||||||
|
slow_threshold: 1000
|
||||||
|
|
||||||
|
# SQLite 配置
|
||||||
|
sqlite:
|
||||||
|
path: /var/lib/headscale/db.sqlite
|
||||||
|
|
||||||
|
# 启用 WAL 模式。推荐生产环境启用。
|
||||||
|
# https://www.sqlite.org/wal.html
|
||||||
|
write_ahead_log: true
|
||||||
|
|
||||||
|
# WAL 文件在达到多少帧时自动 checkpoint。
|
||||||
|
# 设为 0 可禁用自动 checkpoint。
|
||||||
|
wal_autocheckpoint: 1000
|
||||||
|
|
||||||
|
# # Postgres 配置(不推荐,仅遗留支持)
|
||||||
|
# postgres:
|
||||||
|
# # 使用 Unix socket 时,设置 host 为 socket 路径,port 留空。
|
||||||
|
# host: localhost
|
||||||
|
# port: 5432
|
||||||
|
# name: headscale
|
||||||
|
# user: foo
|
||||||
|
# pass: bar
|
||||||
|
# max_open_conns: 10
|
||||||
|
# max_idle_conns: 10
|
||||||
|
# conn_max_idle_time_secs: 3600
|
||||||
|
#
|
||||||
|
# # SSL 配置,参考官方文档
|
||||||
|
# ssl: false
|
||||||
|
|
||||||
|
### TLS 配置
|
||||||
|
#
|
||||||
|
## Let's Encrypt / ACME
|
||||||
|
#
|
||||||
|
# headscale 支持使用 Let's Encrypt 自动申请 TLS 证书
|
||||||
|
#
|
||||||
|
# ACME 目录 URL
|
||||||
|
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
|
||||||
|
# ACME 注册邮箱
|
||||||
|
acme_email: ""
|
||||||
|
|
||||||
|
# 要申请 TLS 证书的域名
|
||||||
|
tls_letsencrypt_hostname: ""
|
||||||
|
|
||||||
|
# 存储证书和元数据的路径
|
||||||
|
# 生产环境建议:
|
||||||
|
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||||
|
|
||||||
|
# ACME 挑战类型,目前支持:
|
||||||
|
# HTTP-01 或 TLS-ALPN-01
|
||||||
|
# 详见 docs/ref/tls.md
|
||||||
|
tls_letsencrypt_challenge_type: HTTP-01
|
||||||
|
# 使用 HTTP-01 时,letsencrypt 必须监听:
|
||||||
|
# :http = 80 端口
|
||||||
|
tls_letsencrypt_listen: ":http"
|
||||||
|
|
||||||
|
## 使用已有证书
|
||||||
|
tls_cert_path: ""
|
||||||
|
tls_key_path: ""
|
||||||
|
|
||||||
|
log:
|
||||||
|
# 日志输出格式:text 或 json
|
||||||
|
format: text
|
||||||
|
# 日志级别:info, debug, trace
|
||||||
|
level: info
|
||||||
|
|
||||||
|
## 策略
|
||||||
|
# headscale 支持 Tailscale 的 ACL 策略
|
||||||
|
# 文档:https://tailscale.com/kb/1018/acls/
|
||||||
|
policy:
|
||||||
|
# 模式:file 或 database
|
||||||
|
mode: file
|
||||||
|
# 若为 file 模式,指定 HuJSON 文件路径
|
||||||
|
path: ""
|
||||||
|
|
||||||
|
## DNS
|
||||||
|
#
|
||||||
|
# headscale 支持 Tailscale 的 DNS 配置和 MagicDNS。
|
||||||
|
# 文档:
|
||||||
|
# https://tailscale.com/kb/1054/dns/
|
||||||
|
# https://tailscale.com/kb/1081/magicdns/
|
||||||
|
# https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
|
||||||
|
#
|
||||||
|
# 注意:要使 DNS 配置生效,客户端必须启用 `--accept-dns=true`。
|
||||||
|
# 否则将不生效。
|
||||||
|
dns:
|
||||||
|
# 是否启用 MagicDNS
|
||||||
|
magic_dns: true
|
||||||
|
|
||||||
|
# MagicDNS 的基础域名,必须与 server_url 域名不同。
|
||||||
|
base_domain: example.com
|
||||||
|
|
||||||
|
# 是否覆盖本地 DNS 设置
|
||||||
|
override_local_dns: false
|
||||||
|
|
||||||
|
# 全局 DNS 服务器列表
|
||||||
|
nameservers:
|
||||||
|
global:
|
||||||
|
- 1.1.1.1
|
||||||
|
- 1.0.0.1
|
||||||
|
- 2606:4700:4700::1111
|
||||||
|
- 2606:4700:4700::1001
|
||||||
|
# NextDNS 示例
|
||||||
|
# - https://dns.nextdns.io/abc123
|
||||||
|
|
||||||
|
# Split DNS 示例(为特定域使用不同 DNS)
|
||||||
|
split: {}
|
||||||
|
|
||||||
|
# 自定义搜索域
|
||||||
|
search_domains: []
|
||||||
|
|
||||||
|
# 额外 DNS 记录(支持 A/AAAA)
|
||||||
|
extra_records: []
|
||||||
|
# - name: "grafana.myvpn.example.com"
|
||||||
|
# type: "A"
|
||||||
|
# value: "100.64.0.3"
|
||||||
|
|
||||||
|
# CLI 使用的 Unix socket(无认证)
|
||||||
|
# 生产环境建议自定义
|
||||||
|
unix_socket: /var/run/headscale/headscale.sock
|
||||||
|
unix_socket_permission: "0770"
|
||||||
|
|
||||||
|
# OpenID Connect 配置(实验功能)
|
||||||
|
# oidc:
|
||||||
|
# only_start_if_oidc_is_available: true
|
||||||
|
# issuer: "https://your-oidc.issuer.com/path"
|
||||||
|
# client_id: "your-oidc-client-id"
|
||||||
|
# client_secret: "your-oidc-client-secret"
|
||||||
|
# client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
|
||||||
|
# expiry: 180d
|
||||||
|
# use_expiry_from_token: false
|
||||||
|
# scope: ["openid", "profile", "email", "custom"]
|
||||||
|
# extra_params:
|
||||||
|
# domain_hint: example.com
|
||||||
|
# allowed_domains:
|
||||||
|
# - example.com
|
||||||
|
# allowed_groups:
|
||||||
|
# - /headscale
|
||||||
|
# allowed_users:
|
||||||
|
# - alice@example.com
|
||||||
|
# pkce:
|
||||||
|
# enabled: false
|
||||||
|
# method: S256
|
||||||
|
|
||||||
|
# Logtail 配置
|
||||||
|
# Logtail 是 Tailscale 的日志与审计系统
|
||||||
|
logtail:
|
||||||
|
# 启用后,客户端将日志发送到 Tailscale 服务器
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# 启用后,设备将优先使用随机端口进行 WireGuard 流量
|
||||||
|
# 以避免某些防火墙兼容性问题。
|
||||||
|
# 详见:https://tailscale.com/kb/1181/firewalls/
|
||||||
|
randomize_client_port: false
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
设置反向代理:
|
||||||
|
公网域名->127.0.0.1:9092
|
||||||
|
```txt
|
||||||
|
location /web {
|
||||||
|
index index.html;
|
||||||
|
alias /shumengya/headscale/web;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
61
public/mengyanote/实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md
Normal file
61
public/mengyanote/实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
timeline:
|
||||||
|
9.16 一面
|
||||||
|
9.18 二面
|
||||||
|
9.22 三面
|
||||||
|
9.23 HR面
|
||||||
|
9.24 录用评估
|
||||||
|
9.26 Offer
|
||||||
|
|
||||||
|
腾讯一面(1h)
|
||||||
|
|
||||||
|
1. 介绍实习需求(K8S 和 Casbin RBAC 相关)
|
||||||
|
2. 为啥初创实习两个月离职
|
||||||
|
3. Go 为什么支持高并发
|
||||||
|
4. GMP模型原理
|
||||||
|
5. Goroutine Work-Stealing 的目的
|
||||||
|
6. P的角色的作用,如果在M上维护Goroutine队列有什么不好
|
||||||
|
7. GMP对CPU密集型任务能提高并发么
|
||||||
|
8. IO操作需要CPU么,什么时候需要,磁盘IO和网络IO的区别
|
||||||
|
9. Channel的作用和底层实现
|
||||||
|
10. Channel的缓冲区在用户态还是内核态
|
||||||
|
11. Goroutine阻塞等待的时候由谁来唤醒,需要额外的goroutine来遍历所有的channel么
|
||||||
|
12. M上的G0是干嘛的
|
||||||
|
13. 介绍select/poll/epoll
|
||||||
|
14. 网络IO的流程
|
||||||
|
15. 了解过Go Runtime么
|
||||||
|
|
||||||
|
算法:求两个数的最大公约数
|
||||||
|
|
||||||
|
腾讯二面(1h)
|
||||||
|
|
||||||
|
1. 介绍实习需求,最有挑战的部分
|
||||||
|
2. RocksDB了解么,说一下LsmTree
|
||||||
|
3. 详细介绍一下Raft协议
|
||||||
|
4. Raft协议和Paxos协议的区别,有哪些优化
|
||||||
|
5. 介绍一下React Agent
|
||||||
|
6. LangChain 和 LangGraph 的区别
|
||||||
|
7. Agent 和 LLM 的区别
|
||||||
|
8. Function Call 和 MCP 的区别
|
||||||
|
9. RPC的全流程
|
||||||
|
10. 负载均衡算法有哪些
|
||||||
|
11. 介绍一致性Hash算法,服务扩缩容之后有什么影响
|
||||||
|
12. 网络编程
|
||||||
|
13. 介绍一下TCP和UDP
|
||||||
|
14. 介绍一下HTTP各个版本及实现
|
||||||
|
|
||||||
|
算法:
|
||||||
|
|
||||||
|
1. 编辑距离
|
||||||
|
2. 两两交换链表中的节点
|
||||||
|
|
||||||
|
腾讯三面(30min)
|
||||||
|
|
||||||
|
1. 介绍实习,你做了什么
|
||||||
|
2. 介绍项目
|
||||||
|
3. 实习时长,到岗时间,推HR面
|
||||||
|
|
||||||
|
腾讯HR面(15min)
|
||||||
|
|
||||||
|
1. 离职原因
|
||||||
|
2. 实习时长,到岗时间
|
||||||
|
3. 聊聊天
|
||||||
7
public/mengyanote/实习求职/术语科普-HC.md
Normal file
7
public/mengyanote/实习求职/术语科普-HC.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
“hc” 是英文 “Head Count” 的缩写,核心含义是“人员编制”,指企业或团队中计划招聘、核定的岗位人数,并非已入职的实际人数。
|
||||||
|
|
||||||
|
在不同场景下还有其他常见含义,具体需结合语境判断:
|
||||||
|
|
||||||
|
- 职场/招聘场景:最常用含义为“人员编制”,例如“这个部门今年还有2个hc”,即该部门今年仍有2个招聘名额。
|
||||||
|
- 医学场景:可指“血红蛋白浓度(Hemoglobin Concentration)”,是血常规检查中评估是否贫血的重要指标。
|
||||||
|
- 网络用语:偶尔作为“喝彩(hè cǎi)”的拼音首字母缩写,用于表达支持、夸赞,常见于社交平台评论区。
|
||||||
5
public/mengyanote/实习求职/术语科普-PM.md
Normal file
5
public/mengyanote/实习求职/术语科普-PM.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
“pm” 是多义词缩写,核心含义需结合具体场景判断,最常见的有以下三类:
|
||||||
|
|
||||||
|
- 时间场景:全称为 “Post Meridiem”,指一天中的“下午”,与表示“上午”的“am”(Ante Meridiem)对应,例如“3 pm”即“下午3点”。
|
||||||
|
- 职场/业务场景:最常用含义为 “Product Manager”,即“产品经理”,负责产品的规划、设计、迭代及市场推广等全流程工作;也可指 “Project Manager”,即“项目经理”,主要负责项目的计划、执行与交付,确保项目按时按质完成。
|
||||||
|
- 其他场景:在通信或社交语境中,还可表示 “Private Message”,即“私信”,例如“有问题可以pm我”,意为“有问题可以给我发私信”。
|
||||||
61
public/mengyanote/实习求职/面试八股/Nacos功能与应用场景详解.md
Normal file
61
public/mengyanote/实习求职/面试八股/Nacos功能与应用场景详解.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
Nacos 是阿里巴巴开源的 **动态服务发现、配置管理与服务治理平台**,旨在简化微服务架构的构建、交付和管理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 核心功能
|
||||||
|
|
||||||
|
| 功能 | 主要作用 |
|
||||||
|
|------|----------|
|
||||||
|
| 🎯 **服务注册与发现** | 服务提供者注册自身信息,服务消费者动态发现和调用其他服务。 |
|
||||||
|
| ⚙️ **动态配置管理** | 集中管理所有环境的配置,支持实时推送变更,无需重启应用。 |
|
||||||
|
| 🔍 **服务健康监测** | 定期检查服务实例健康状况,自动隔离不健康实例,保障系统稳定性。 |
|
||||||
|
| 🚦 **动态DNS与流量管理** | 支持权重路由,助力灰度发布、蓝绿部署等高级流量管理策略。 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 服务发现与健康检查
|
||||||
|
|
||||||
|
- **服务注册**:实例启动时向 Nacos 注册自身元数据(服务名、IP、端口等)。
|
||||||
|
- **服务发现**:消费者通过服务名查询健康实例,实现通信而无需关心具体地址。
|
||||||
|
- **健康检查**:支持客户端上报与服务端主动探测,自动剔除不健康实例,保障可靠性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ 动态配置管理
|
||||||
|
|
||||||
|
- **集中化管理**:统一存储数据库连接、开关、限流阈值等配置。
|
||||||
|
- **动态刷新**:配置变更实时推送,应用可在运行中直接生效(热更新)。
|
||||||
|
- **版本控制与回滚**:支持历史版本,一键回滚,降低变更风险。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚦 动态DNS与服务治理
|
||||||
|
|
||||||
|
- **动态DNS服务**:支持权重路由、流量控制和简易内网 DNS 解析。
|
||||||
|
- **服务与元数据管理**:统一管理服务描述、依赖关系、健康状态、流量及安全策略。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 主要应用场景
|
||||||
|
|
||||||
|
- **数据库配置集中化管理**:提升安全性与合规性。
|
||||||
|
- **限流与降级开关**:结合 Sentinel 等组件实现运行时动态调整。
|
||||||
|
- **多环境与多数据中心**:基于 Namespace 与 Group 实现隔离与灵活部署。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 与其他组件对比
|
||||||
|
|
||||||
|
- ✅ **功能更全面**:Nacos = 服务发现 + 配置管理;Eureka 仅支持服务发现。
|
||||||
|
- ✅ **健康检查机制更强**:优于 Eureka 心跳检测。
|
||||||
|
- ✅ **社区与生态活跃**:Eureka 已停止维护,而 Nacos 持续迭代。
|
||||||
|
- ✅ **多数据中心支持优越**:原生支持多数据中心部署。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 总结
|
||||||
|
|
||||||
|
Nacos 集 **服务发现、配置管理、服务治理** 于一体,
|
||||||
|
极大简化了微服务架构复杂性,提升了 **开发效率**、**可维护性** 和 **系统弹性**。
|
||||||
|
|
||||||
|
---
|
||||||
121
public/mengyanote/实习求职/面试八股/计算机面试经典八股.md
Normal file
121
public/mengyanote/实习求职/面试八股/计算机面试经典八股.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
+好的!计算机面试中最经典、最高频的“八股文”主要围绕以下几个核心领域展开。掌握这些基础知识和原理是通关技术面试的关键:
|
||||||
|
|
||||||
|
## 🧠 一、 数据结构与算法
|
||||||
|
|
||||||
|
1. **基础数据结构:**
|
||||||
|
* **数组 vs 链表:** 内存结构、访问/插入/删除时间复杂度、适用场景。
|
||||||
|
* **栈(Stack) & 队列(Queue):** LIFO/FIFO 原理、实现方式(数组/链表)、应用场景(函数调用栈、BFS/DFS)。
|
||||||
|
* **哈希表(Hash Table):** 原理(哈希函数、冲突解决-开放寻址/链地址法)、时间复杂度分析、负载因子、扩容机制。
|
||||||
|
* **堆(Heap) / 优先队列(Priority Queue):** 结构(通常是二叉堆)、操作(插入、删除堆顶、堆化)、应用(Top K、中位数、Dijkstra)。
|
||||||
|
* **树(Tree):**
|
||||||
|
* 二叉树(Binary Tree):遍历(前序、中序、后序、层序)- 递归与非递归实现。
|
||||||
|
* 二叉搜索树(BST):定义、查找、插入、删除、中序遍历有序性。
|
||||||
|
* 平衡二叉搜索树(AVL / 红黑树):平衡因子/红黑规则、旋转操作、为什么需要(避免BST退化成链表)、应用(Java HashMap的TreeBin/TreeMap)。
|
||||||
|
* **图(Graph):** 表示方法(邻接矩阵、邻接表)、遍历算法(BFS、DFS)、常见算法(拓扑排序、最短路径-Dijkstra/Bellman-Ford/Floyd、最小生成树-Prim/Kruskal)。
|
||||||
|
|
||||||
|
2. **基础算法思想:**
|
||||||
|
* **排序算法:**
|
||||||
|
* 比较排序:**快速排序**(分治、选基准、partition过程、时间复杂度-最好O(nlogn)/最坏O(n²)/平均、空间复杂度、稳定性❌)、**归并排序**(分治、稳定✅、时间复杂度O(nlogn)、空间复杂度O(n))、**堆排序**(建堆O(n)、排序O(nlogn)、不稳定❌)、插入排序、冒泡排序、选择排序(原理、时间复杂度)。
|
||||||
|
* 非比较排序:计数排序、桶排序、基数排序(思想、适用场景)。
|
||||||
|
* **搜索算法:** **二分查找**(前提有序、循环/递归实现、变种问题-找第一个/最后一个/旋转数组)。
|
||||||
|
* **递归 & 分治:** 思想、经典问题(斐波那契、汉诺塔、归并/快排)。
|
||||||
|
* **贪心算法(Greedy):** 思想(局部最优->全局最优?)、适用场景(活动选择、霍夫曼编码、最小生成树-Prim/Kruskal)、与动态规划区别。
|
||||||
|
* **动态规划(DP):** **核心思想**(最优子结构、重叠子问题、状态转移方程)、**解题步骤**(定义状态、状态转移、初始化、边界、输出)、**经典问题**(斐波那契、爬楼梯、背包问题01/完全、最长公共子序列LCS、最长递增子序列LIS、编辑距离、股票买卖系列)。
|
||||||
|
* **回溯(Backtracking):** 思想(试错、DFS+剪枝)、经典问题(N皇后、全排列、组合、子集、数独)。
|
||||||
|
* **双指针(Two Pointers):** 应用(有序数组两数之和、滑动窗口-最小覆盖子串/最长无重复子串、快慢指针-链表判环/找中点)。
|
||||||
|
* **位运算(Bit Manipulation):** 常用操作(与、或、异或、非、移位)、常见技巧(判断奇偶、交换两数、找出只出现一次的数字、位1的个数)。
|
||||||
|
|
||||||
|
## 🖥 二、 操作系统
|
||||||
|
|
||||||
|
1. **进程与线程:**
|
||||||
|
* 进程 vs 线程(定义、资源分配、切换开销、通信方式)。
|
||||||
|
* **进程间通信(IPC):** 管道、命名管道、信号、消息队列、共享内存、信号量、套接字。
|
||||||
|
* **线程同步机制:** **互斥锁(Mutex)**、**信号量(Semaphore)**、**条件变量(Condition Variable)**、读写锁(Read-Write Lock)、自旋锁(Spin Lock)(原理、适用场景、死锁避免)。
|
||||||
|
* **死锁(Deadlock):** 必要条件(互斥、请求与保持、不可剥夺、环路等待)、预防策略、避免策略(银行家算法)、检测与恢复。
|
||||||
|
2. **内存管理:**
|
||||||
|
* **虚拟内存(Virtual Memory):** 为什么需要?分页(Paging)机制(页表、TLB快表)、分段(Segmentation)机制。
|
||||||
|
* **页面置换算法:** **最佳置换(OPT)**、**先进先出(FIFO)**、**最近最久未使用(LRU)**、时钟算法(Clock) 的原理和优缺点。
|
||||||
|
* **内存分配:** 伙伴系统(Buddy System)、Slab分配器。
|
||||||
|
3. **文件系统:** 文件描述符(File Descriptor)、inode结构、文件存储方式(连续、链式、索引)、目录结构。
|
||||||
|
4. **CPU调度:** 调度算法(FCFS、SJF、优先级、RR轮转、多级反馈队列)的目标和特点。
|
||||||
|
5. **I/O模型:** 阻塞I/O、非阻塞I/O、I/O多路复用(select/poll/epoll)、信号驱动I/O、异步I/O(AIO) 的区别和比较(特别是epoll的优势)。
|
||||||
|
|
||||||
|
## 🌐 三、 计算机网络
|
||||||
|
|
||||||
|
1. **网络模型:** **OSI七层模型** 和 **TCP/IP四层模型** 各层功能、对应协议。
|
||||||
|
2. **核心协议:**
|
||||||
|
* **TCP vs UDP:** 根本区别(连接、可靠性、有序性、流量控制、拥塞控制)、头部结构、应用场景。
|
||||||
|
* **TCP可靠传输:** 序号/确认号、超时重传、滑动窗口机制。
|
||||||
|
* **TCP连接管理:** **三次握手**(详细过程、为什么是三次?)、**四次挥手**(详细过程、为什么是四次?TIME_WAIT状态的作用?)。
|
||||||
|
* **TCP流量控制:** 滑动窗口机制。
|
||||||
|
* **TCP拥塞控制:** 慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)、快速恢复(Fast Recovery) 算法原理。
|
||||||
|
* **HTTP:**
|
||||||
|
* 请求方法(GET/POST/PUT/DELETE等区别)、状态码(1xx/2xx/3xx/4xx/5xx常见状态码含义)。
|
||||||
|
* **HTTP/1.0 vs HTTP/1.1 vs HTTP/2 vs HTTP/3:** 主要改进(连接复用、头部压缩、服务器推送、QUIC协议)。
|
||||||
|
* **HTTPS:** SSL/TLS协议作用、加密过程(非对称加密交换对称密钥、对称加密通信)、数字证书作用。
|
||||||
|
* **DNS:** 作用、查询过程(递归、迭代)、记录类型(A、AAAA、CNAME、MX、NS)。
|
||||||
|
3. **网络安全基础:**
|
||||||
|
* **对称加密 vs 非对称加密:** 原理、优缺点、代表算法(AES、RSA)。
|
||||||
|
* **数字签名 & 数字证书:** 作用、原理(私钥签名,公钥验签;CA中心颁发证书)。
|
||||||
|
* 常见攻击:XSS、CSRF、SQL注入、DDoS、中间人攻击的原理和基本防御措施。
|
||||||
|
4. **网络层:** IP协议、IP地址分类/子网划分/CIDR、ARP协议、路由协议(RIP、OSPF、BGP基本思想)。
|
||||||
|
5. **传输层与应用层:** 端口号作用、Socket编程基础。
|
||||||
|
|
||||||
|
## 🗃 四、 数据库(以关系型数据库 MySQL 为主)
|
||||||
|
|
||||||
|
1. **SQL基础:** 常用语句(SELECT, INSERT, UPDATE, DELETE, JOIN, GROUP BY, HAVING, ORDER BY, LIMIT)、多表连接(INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN)。
|
||||||
|
2. **索引(Index):**
|
||||||
|
* **为什么需要索引?** 加速查询。
|
||||||
|
* **数据结构:** **B+树**(为什么比B树更适合数据库?)、哈希索引(适用场景)。
|
||||||
|
* **聚簇索引(Clustered Index) vs 非聚簇索引(Non-Clustered Index / Secondary Index):** 根本区别(叶子节点是否存储完整行数据)、InnoDB实现。
|
||||||
|
* **索引优化:** 覆盖索引、最左前缀原则、索引下推(ICP)。
|
||||||
|
* **索引失效场景:** 函数操作、类型转换、`LIKE '%xx'`、OR条件(部分情况)、不等于(!=, <>)、索引列计算。
|
||||||
|
3. **事务(Transaction):**
|
||||||
|
* **ACID特性:** 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) 的含义。
|
||||||
|
* **隔离级别(Isolation Level):** **读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read - MySQL默认)、串行化(Serializable)**。每个级别能解决哪些并发问题(脏读、不可重复读、幻读)?
|
||||||
|
* **并发问题:** 脏读、不可重复读、幻读的定义。
|
||||||
|
* **MVCC(多版本并发控制):** 原理(Undo Log、Read View)、如何实现RC和RR级别(特别是RR如何解决幻读?)。
|
||||||
|
4. **锁(Locking):** 共享锁(S锁/读锁)、排他锁(X锁/写锁)、意向锁、行锁、表锁、间隙锁(Gap Lock)、临键锁(Next-Key Lock)的作用和应用场景(特别是InnoDB如何解决幻读)。
|
||||||
|
5. **日志(Logging):**
|
||||||
|
* **Redo Log(重做日志):** 作用(保证持久性、Crash-Safe)、Write-Ahead Logging(WAL)机制。
|
||||||
|
* **Undo Log(回滚日志):** 作用(保证原子性、实现MVCC)。
|
||||||
|
* **Binlog(归档日志):** 作用(主从复制、数据恢复)、格式(Statement/Row/Mixed)。
|
||||||
|
6. **数据库设计:** 三大范式(1NF, 2NF, 3NF)基本概念、反范式化设计场景。
|
||||||
|
7. **性能优化:** Explain分析SQL执行计划、慢查询优化思路。
|
||||||
|
|
||||||
|
## 📐 五、 系统设计(面向中高级岗位)
|
||||||
|
|
||||||
|
1. **设计原则:** KISS, YAGNI, DRY, SOLID (尤其是单一职责、开闭原则)。
|
||||||
|
2. **方法论:**
|
||||||
|
* 需求澄清(功能需求、非功能需求-性能/可用性/扩展性/一致性/容错性/安全性)。
|
||||||
|
* 估算(QPS、TPS、存储量、带宽)。
|
||||||
|
* 抽象与模块化。
|
||||||
|
* 核心组件设计(API、数据模型、存储方案、算法)。
|
||||||
|
* 深入细节(扩展性、可靠性、性能优化)。
|
||||||
|
3. **常见组件与模式:**
|
||||||
|
* 负载均衡(LB: Nginx, HAProxy, LVS)。
|
||||||
|
* 缓存(Cache: Redis, Memcached)- 缓存策略(Cache Aside, Read/Write Through, Write Behind)、缓存穿透/击穿/雪崩及解决方案。
|
||||||
|
* 消息队列(MQ: Kafka, RabbitMQ, RocketMQ)- 解耦、异步、削峰填谷、保证最终一致性。
|
||||||
|
* 数据库扩展:读写分离、分库分表(水平/垂直拆分)、分区。
|
||||||
|
* 分布式ID生成(Snowflake算法)。
|
||||||
|
* 分布式一致性协议:**CAP理论**、**BASE理论**、**Raft/Paxos**(选主、日志复制)基本原理(理解核心思想即可,不要求推导)。
|
||||||
|
* 微服务架构:服务注册与发现(Eureka, Nacos, Consul)、API网关(Gateway)、配置中心、服务调用(RPC/REST)、熔断限流(Hystrix, Sentinel)。
|
||||||
|
4. **经典系统设计题:** 设计Twitter/微博、设计短链系统、设计秒杀系统、设计分布式缓存、设计搜索引擎、设计聊天系统等。
|
||||||
|
|
||||||
|
## 🐍 六、 编程语言特性(根据应聘语言选择)
|
||||||
|
|
||||||
|
1. **面向对象(OOP):** 封装、继承、多态、抽象类 vs 接口、重载 vs 重写。
|
||||||
|
2. **内存管理:** 垃圾回收(GC)原理(标记清除、复制、标记整理、分代收集-G1/ZGC)、引用类型(强引用、软引用、弱引用、虚引用)。
|
||||||
|
3. **并发编程:** 线程生命周期、创建方式、线程池(核心参数、工作流程、拒绝策略)、锁(Synchronized底层原理、Lock/Condition)、并发容器(ConcurrentHashMap原理-CAS+synchronized+分段锁思想)、原子类(CAS操作、ABA问题)、线程间通信。
|
||||||
|
4. **语言特性:** 如Java的JVM内存区域、类加载机制、反射、异常体系、集合框架(HashMap源码:put/get流程、扩容、JDK1.7 vs 1.8+);Python的GIL、装饰器、生成器、鸭子类型;Go的Goroutine、Channel、defer等。
|
||||||
|
|
||||||
|
## 📌 关键点提醒
|
||||||
|
|
||||||
|
1. **理解原理,而非死记硬背:** 面试官更关注你是否真正理解了背后的思想(为什么用这个?解决了什么问题?优缺点是什么?)。
|
||||||
|
2. **联系实际:** 思考这些知识在实际系统/项目中是如何应用的。
|
||||||
|
3. **清晰表达:** 能条理清晰、简洁准确地阐述概念和过程。
|
||||||
|
4. **动手实践:** 算法题要动手写,数据库要会写SQL,系统设计要多思考多画图。
|
||||||
|
5. **关注细节:** 很多问题会深入到具体实现细节(如HashMap冲突解决、ConcurrentHashMap分段锁演变、MySQL RR级别如何避免幻读、TCP TIME_WAIT)。
|
||||||
|
6. **追踪发展:** 了解一些新技术趋势(如HTTP/3, QUIC, eBPF, 云原生, Serverless)的基本概念。
|
||||||
|
|
||||||
|
这份清单涵盖了计算机面试中最核心、最高频的基础知识点。针对具体岗位(前端、后端、算法、运维、测试等)
|
||||||
@@ -1,3 +1,17 @@
|
|||||||
**2025年9月9日**:这个大学生真是太美好了,wc 我真的绷不住,选了新中国史上了两节课竟然什么都不知道,老师不知道,除了我所有同学都是理学院电子信息专业
|
**2025年9月9日**:这个大学生真是太美好了,wc 我真的绷不住,选了新中国史上了两节课竟然什么都不知道,老师不知道,除了我所有同学都是理学院电子信息专业
|
||||||
|
|
||||||
2025年9月16日:人生就要好好地活着,发生个意外,妻子改嫁,父母没人养老,
|
**2025年9月16日**:人生就要好好地活着,发生个意外,妻子改嫁,父母没人养老,
|
||||||
|
|
||||||
|
**2025年9月30日**:懒得和别人吵架,无言和沉默是我最好的武器,我不可能劝的动任何一个人,所以一键拉黑世界就瞬间清净了
|
||||||
|
|
||||||
|
**无**:唉,时间就是单向的,过去的就真的过去了,死了就是死了,不可能再活过来,特定的东西只能发生在特定的时期,过去了就真的过去了,再怎么亡羊补牢,怎么报复性补偿都没什么用,什么狗屁延迟满足,什么狗屁先苦后甜,他妈的越吃苦,你就有吃不完的苦,操你妈的个狗杂种,妈的一群畜生
|
||||||
|
|
||||||
|
**无**:假如你的春天出现了虫子,那就用蟒蛇去吃掉它,如果蟒蛇被咬到,就去找大象,不过不用担心他们都在汤姆猫家里面(*^-^)ノ🎉
|
||||||
|
|
||||||
|
**无**:spring spring 春天 春天
|
||||||
|
boot boot 启动 启动
|
||||||
|
springboot springboot 发春 发春
|
||||||
|
|
||||||
|
**2025年10月3日**:又穷又蠢的傻逼,付点智商税怎么了
|
||||||
|
|
||||||
|
**2025年10月6日**:中国人总是忌讳死亡的,但死亡总是不可避免的,唉人生啊,总是这么矛盾。有时候大大方方的表达出来又有什么问题,这片土地的儒家文化就是,最后错过了到后悔了又无可奈何,强行赋予一些死后意义,唉,哪有那么多的价值,人死了就是一堆烂肉,什么人都一样
|
||||||
@@ -1,4 +1,11 @@
|
|||||||
line.tv
|
line.tv
|
||||||
|
|
||||||
Kazumi
|
Kazumi
|
||||||
|
|
||||||
唉,时间就是单向的,过去的就真的过去了,死了就是死了,不可能再活过来,特定的东西只能发生在特定的时期,过去了就真的过去了,再怎么亡羊补牢,怎么报复性补偿都没什么用,什么狗屁延迟满足,什么狗屁先苦后甜,他妈的越吃苦,你就有吃不完的苦,操你妈的个狗杂种,妈的一群畜生
|
BestGore.Fun
|
||||||
|
|
||||||
|
Documenting Reality
|
||||||
|
|
||||||
|
Deep Gore Tube
|
||||||
|
|
||||||
|
GoreGrish
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
**添加:**
|
**添加:**
|
||||||
- [x] 登录面板-找回密码功能
|
- [x] 登录面板-找回密码功能
|
||||||
- [ ] 作物图片切换动画
|
- [ ] 作物图片切换动画
|
||||||
@@ -26,46 +27,7 @@
|
|||||||
- [x] 道具商店添加四个筛选按钮:全部 宠物 作物 农场
|
- [x] 道具商店添加四个筛选按钮:全部 宠物 作物 农场
|
||||||
- [x] 访问玩家添加送金币按钮
|
- [x] 访问玩家添加送金币按钮
|
||||||
- [ ] 添加访问记录面板,显示访问者对被访问者的操作
|
- [ ] 添加访问记录面板,显示访问者对被访问者的操作
|
||||||
- [ ] 天梯塔,先做8关,每一关有不同的敌人
|
- [x] 星辰塔,先做8关,每一关有不同的敌人
|
||||||
- [x] 添加道具商店和背包分类筛选的功能(宠物道具,作物道具,农场道具)
|
|
||||||
- [ ] 添加邀请码,邀请玩家可获得额外奖励
|
|
||||||
- [x] 添加统计访问人数记录,记录访问人名称
|
|
||||||
- [x] 添加客户端和服务器踢出玩家命令,原因,ban时长
|
|
||||||
- [ ] 服务器崩溃出错自动重启
|
|
||||||
- [x] 添加命令,/rename qq号 新昵称 给某个玩家重命名玩家昵称
|
|
||||||
- [x] 添加命令 /repasswd QQ号 重置某个玩家的密码为123456
|
|
||||||
- [x] 给远程控制台添加参数 设置 让用户
|
|
||||||
- [ ] 管理员用命令修改玩家信息时自动给玩家发送一次最新的玩家数据(全部)
|
|
||||||
- [ ] 添加一个按钮刷新获取最新的玩家数据,设置10秒后才能点一次
|
|
||||||
- [x] 让AI把客户端UI场景美化一下 目前太丑了**添加:**
|
|
||||||
- [x] 登录面板-找回密码功能
|
|
||||||
- [ ] 作物图片切换动画
|
|
||||||
- [x] 游戏设置
|
|
||||||
- [ ] 使用道具的动画效果
|
|
||||||
- [ ] 访问其他农场使用道具
|
|
||||||
- [x] 作物配置中“无成熟物”使得收获时无收获物添加特定收获效果
|
|
||||||
- [x] 小游戏面板
|
|
||||||
- [x] 光影渲染也要条配一下
|
|
||||||
- [x] 昼夜循环系统参考真实世界时间
|
|
||||||
- [x] 天气系统由服务端来调配
|
|
||||||
- [x] 巡逻宠物和出战宠物设置为最多四个
|
|
||||||
- [x] 玩家数据由JSON换成MongoDB数据库
|
|
||||||
- [ ] 客户端和服务端多线程通信
|
|
||||||
- [x] 添加按钮主动发起对战,可以帮自己的宠物刷经验升级
|
|
||||||
- [x] 把小提示导出为配置
|
|
||||||
- [ ] 玩家可以访问别人农场时用道具给别人长草
|
|
||||||
- [x] 添加特定农场,特定道具和作物只能在特定农场获取,杂交农场(666) 花卉农场(520) 稻香(111) 小麦谷(222)
|
|
||||||
- [ ] 添加装饰物
|
|
||||||
- [ ] 添加道具,屎💩,杂草(生长药剂,一包草籽),幸运草/幸运花,染色剂(对该土地染色)
|
|
||||||
- [ ] 添加随机礼包道具,玩家铲了之后会获得随机道具
|
|
||||||
- [x] 测运气,今日运气,算卦,占卜
|
|
||||||
- [ ] 灵活运用OS节点读取玩家信息
|
|
||||||
- [ ] 默认偷菜被发现概率为10%,可以添加个方法增加偷菜被发现的概率
|
|
||||||
- [x] 重新添加种子商店购买结构 结合等级,每天随机刷新,购买限制
|
|
||||||
- [x] 道具商店添加四个筛选按钮:全部 宠物 作物 农场
|
|
||||||
- [x] 访问玩家添加送金币按钮
|
|
||||||
- [ ] 添加访问记录面板,显示访问者对被访问者的操作
|
|
||||||
- [ ] 星辰塔,先做8关,每一关有不同的敌人
|
|
||||||
- [x] 添加道具商店和背包分类筛选的功能(宠物道具,作物道具,农场道具)
|
- [x] 添加道具商店和背包分类筛选的功能(宠物道具,作物道具,农场道具)
|
||||||
- [ ] 添加邀请码,邀请玩家可获得额外奖励
|
- [ ] 添加邀请码,邀请玩家可获得额外奖励
|
||||||
- [x] 添加统计访问人数记录,记录访问人名称
|
- [x] 添加统计访问人数记录,记录访问人名称
|
||||||
@@ -106,67 +68,9 @@
|
|||||||
- [ ] 服务端控制天气系统应该是无论客户端是否在线都可以控制,当离线的客户端登录时获取服务端天气状态,所以需要导出配置到数据库持久化储存
|
- [ ] 服务端控制天气系统应该是无论客户端是否在线都可以控制,当离线的客户端登录时获取服务端天气状态,所以需要导出配置到数据库持久化储存
|
||||||
- [x] 把每日签到和幸运抽奖的动画去掉,太丑了,可以加个确认弹窗
|
- [x] 把每日签到和幸运抽奖的动画去掉,太丑了,可以加个确认弹窗
|
||||||
- [x] 注册页面和找回密码页面可以返回登录页面
|
- [x] 注册页面和找回密码页面可以返回登录页面
|
||||||
- [ ] 八大面板两边再扩大一点,手机端玩家不好滑动
|
- [x] 八大面板两边再扩大一点,手机端玩家不好滑动
|
||||||
- [x] 修改偷菜被宠物100%发现的bug
|
- [x] 修改偷菜被宠物100%发现的bug
|
||||||
- [ ] 修复添加没有的作物图片和过于抽象的图片
|
- [x] 修复添加没有的作物图片和过于抽象的图片
|
||||||
- [x] 修复访问其他玩家作物不更新
|
|
||||||
- [x] 使用道具还没有修复
|
|
||||||
- [x] 喂养宠物也是没有修复,生命值
|
|
||||||
- [ ] 年龄计算天数也有问题
|
|
||||||
- [x] 玩家打开作物仓库的时候请求一次服务器
|
|
||||||
- [ ] 战斗胜利的偷菜计时器失效了
|
|
||||||
- [ ] UI做大一点,手机端还是不好操作
|
|
||||||
- [ ] 弹窗UI连续显示时不够流畅
|
|
||||||
- [ ] 咖啡豆没有未成熟图片
|
|
||||||
- [x] 一键截图改成截图模式
|
|
||||||
- [x] 把野草禁止买卖
|
|
||||||
- [ ] 偷菜被发现强制扣金币,一直扣到0为止,不能出现负数金币
|
|
||||||
- [x] 访问别人玩家不能打开玩家的小卖部
|
|
||||||
- [ ] 设置稻草人所有内容最多只能20个字(客户端限制)
|
|
||||||
- [ ] 设置对玩家使用的道具可以批量使用
|
|
||||||
- [x] 设置批量出售作物超出最大值设置为最大值
|
|
||||||
- [ ] 修改智慧树每次登录也会刷新一句话
|
|
||||||
- [x] 点开道具背包,作物仓库,种子仓库,上报服务器刷新一下
|
|
||||||
- [ ] 宠物喂食完,使用道具后返回宠物信息面板
|
|
||||||
- [ ] 作物更新还是有问题,在考虑要不要直接退回到原来的每秒更新
|
|
||||||
- [x] 修复登录递归循环调用导致无法登录问题
|
|
||||||
- [ ] 修复点开账户设置时自动刷新一下
|
|
||||||
- [ ] 修复一下/playerinfo 查看玩家信息命令 目前显示不全而且有问题
|
|
||||||
- [ ] 把稻草人数据库配置改成无限句话
|
|
||||||
|
|
||||||
|
|
||||||
- [ ] 添加一个彩蛋系统,hyc和lyh是SB即可获得500金币,每个账号限一次
|
|
||||||
- [ ] 作物数据添加血量,最大血量
|
|
||||||
- [ ] 玩家金币添加最大金币储存上限(金库),添加0下限,添加体力值上限
|
|
||||||
- [ ] 添加道具,等级卡一键升级到下一等级
|
|
||||||
- [ ] 添加道具,金币符石,使得金币一键达到最大容量
|
|
||||||
- [ ] 添加道具,体力符石,一键体力达到最大值
|
|
||||||
|
|
||||||
|
|
||||||
**修改/修复:**
|
|
||||||
- [x] 缓存问题-种子仓库,作物仓库图片缓存失败直接加载图片
|
|
||||||
- [x] 服务端部署成Docker,内网穿透
|
|
||||||
- [ ] 恢复游戏更新后台
|
|
||||||
- [x] 收获作物造成卡顿问题
|
|
||||||
- [ ] 修复智慧树显示问题
|
|
||||||
- [x] 一键收获作物时过滤杂草作物
|
|
||||||
- [x] 宠物商店点开自动刷新加载
|
|
||||||
- [x] 宠物商店每次购买后没有刷新
|
|
||||||
- [x] 小额金币卡和小额经验卡的文字描述没有修改(应该是对人使用)
|
|
||||||
- [x] 账户设置出问题了,无法设置
|
|
||||||
- [x] 服务器老是会卡顿需要手动加载一下
|
|
||||||
- [x] 从访问他人村庄出现偷菜弹窗 返回自己农场点击一键收获出现宠物对战弹窗,使用单独的美化弹窗
|
|
||||||
- [ ] username和password 不知道哪里冒出来的,暂时没有发现异常
|
|
||||||
- [x] 全服大喇叭系统 玩家昵称没有显示出来而是显示成 玩家账号
|
|
||||||
- [x] 全服大喇叭发送消息后主游戏界面开始没有刷新
|
|
||||||
- [x] 游戏主界面点赞和排行榜点赞以及访问玩家点赞显示错误
|
|
||||||
- [x] 把缓存删了后作物的后台离线更新失效了
|
|
||||||
- [ ] 服务端控制天气系统应该是无论客户端是否在线都可以控制,当离线的客户端登录时获取服务端天气状态,所以需要导出配置到数据库持久化储存
|
|
||||||
- [x] 把每日签到和幸运抽奖的动画去掉,太丑了,可以加个确认弹窗
|
|
||||||
- [x] 注册页面和找回密码页面可以返回登录页面
|
|
||||||
- [ ] 八大面板两边再扩大一点,手机端玩家不好滑动
|
|
||||||
- [x] 修改偷菜被宠物100%发现的bug
|
|
||||||
- [ ] 修复添加没有的作物图片和过于抽象的图片
|
|
||||||
- [x] 修复访问其他玩家作物不更新
|
- [x] 修复访问其他玩家作物不更新
|
||||||
- [x] 使用道具还没有修复
|
- [x] 使用道具还没有修复
|
||||||
- [x] 喂养宠物也是没有修复,生命值
|
- [x] 喂养宠物也是没有修复,生命值
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
**修改/修复:**
|
**修改/修复:**
|
||||||
- [ ] 使用低功耗模式,或者其他方法降低软件内存占用过高,手机发热问题
|
- [ ] 使用低功耗模式,或者其他方法降低软件内存占用过高,手机发热问题
|
||||||
- [ ] 修复报错[21:19:52] > /addmoney 3205788256 666
|
- [x] 修复报错[21:19:52] > /addmoney 3205788256 666
|
||||||
[21:19:52] ❌ 命令执行失败
|
[21:19:52] ❌ 命令执行失败
|
||||||
[21:19:52] ❌ 执行命令 'addmoney' 时出错: can only concatenate str (not "int") to str
|
[21:19:52] ❌ 执行命令 'addmoney' 时出错: can only concatenate str (not "int") to str
|
||||||
[21:20:55] > /refarmname 2143323382 柚大青的大窝
|
[21:20:55] > /refarmname 2143323382 柚大青的大窝
|
||||||
|
|||||||
@@ -39,5 +39,6 @@
|
|||||||
- [ ] 用python写个随机系列:随机一言,随机音乐,随机视频,随机诗歌,随机编程题,随机占卜/算命的后端API==,
|
- [ ] 用python写个随机系列:随机一言,随机音乐,随机视频,随机诗歌,随机编程题,随机占卜/算命的后端API==,
|
||||||
- [ ] 做一个TCP,udp,websocket连接器,服务端和客户端,用来学习和测试
|
- [ ] 做一个TCP,udp,websocket连接器,服务端和客户端,用来学习和测试
|
||||||
- [ ] 写一个插件,模组,玩家可以用钻石驯服幻翼,腐肉,幻翼膜修复幻翼,驯服后可以跟随玩家打怪,可以被栓绳拴住,白天免疫燃烧伤害
|
- [ ] 写一个插件,模组,玩家可以用钻石驯服幻翼,腐肉,幻翼膜修复幻翼,驯服后可以跟随玩家打怪,可以被栓绳拴住,白天免疫燃烧伤害
|
||||||
|
- [ ] 写一个撅屁股的网页,支持输入被撅人和撅人的QQ号然后自动获取QQ头像,生成撅屁股动图
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ smy@0123456789
|
|||||||
**3205788256 QQ邮箱发件密钥:**
|
**3205788256 QQ邮箱发件密钥:**
|
||||||
dahsyootmgwldfgd
|
dahsyootmgwldfgd
|
||||||
|
|
||||||
|
shumengya888@foxmail.com **QQ邮箱发件密钥:**
|
||||||
|
dpdouefloajfdagd
|
||||||
|
dpdouefloajfdagd
|
||||||
|
|
||||||
**Github免费模型测试API:**
|
**Github免费模型测试API:**
|
||||||
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
|
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
|
||||||
|
|
||||||
@@ -22,3 +26,13 @@ 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
|
|||||||
1000050001202502270927808860230
|
1000050001202502270927808860230
|
||||||
|
|
||||||
[树萌芽の作品集后台地址](https://work.shumengya.top/#/admin?token=shumengya520)
|
[树萌芽の作品集后台地址](https://work.shumengya.top/#/admin?token=shumengya520)
|
||||||
|
|
||||||
|
【邮储银行】您尾号5139的账户开户行名称:中国邮政储蓄银行股份有限公司泸县宝藏街营业所,地址:四川省泸县奇峰镇宝藏街三段68号、70号,电话:0830-8999252,支付行号为:403100000004
|
||||||
|
|
||||||
|
**出生日期**
|
||||||
|
外公1938
|
||||||
|
爷爷1939
|
||||||
|
爸1965
|
||||||
|
妈1966
|
||||||
|
哥1990
|
||||||
|
我2005
|
||||||
|
|||||||
42
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md
Normal file
42
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# JavaScript趣味题 #128
|
||||||
|
|
||||||
|
> 导出时间: 2025/8/29 14:32:49
|
||||||
|
|
||||||
|
## 题目
|
||||||
|
|
||||||
|
输出什么?
|
||||||
|
|
||||||
|
## 代码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const name = "Lydia Hallie";
|
||||||
|
const age = 21;
|
||||||
|
|
||||||
|
console.log(Number.isNaN(name));
|
||||||
|
console.log(Number.isNaN(age));
|
||||||
|
|
||||||
|
console.log(isNaN(name));
|
||||||
|
console.log(isNaN(age));
|
||||||
|
```
|
||||||
|
|
||||||
|
## 选项
|
||||||
|
|
||||||
|
A. A: `true` `false` `true` `false`
|
||||||
|
B. B: `true` `false` `false` `false`
|
||||||
|
C. C: `false` `false` `true` `false` ✅
|
||||||
|
D. D: `false` `true` `false` `true`
|
||||||
|
|
||||||
|
## 正确答案
|
||||||
|
|
||||||
|
**C**
|
||||||
|
|
||||||
|
## 答案解析
|
||||||
|
|
||||||
|
通过方法 `Number.isNaN`,你可以检测你传递的值是否为 _数字值_ 并且是否等价于 `NaN`。`name` 不是一个数字值,因此 `Number.isNaN(name)` 返回 `false`。`age` 是一个数字值,但它不等价于 `NaN`,因此 `Number.isNaN(age)` 返回 `false`.
|
||||||
|
|
||||||
|
通过方法 `isNaN`,你可以检测你传递的值是否一个 number。`name` 不是一个 `number`,因此 `isNaN(name)` 返回 `true`. `age` 是一个 `number` 因此 `isNaN(age)` 返回 `false`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本题目来源于JavaScript趣味题集合*
|
||||||
|
*导出工具: JavaScript趣味题网页版*
|
||||||
46
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md
Normal file
46
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# JavaScript趣味题 #18
|
||||||
|
|
||||||
|
> 导出时间: 2025/8/29 14:53:34
|
||||||
|
|
||||||
|
## 题目
|
||||||
|
|
||||||
|
输出是什么?
|
||||||
|
|
||||||
|
## 代码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function checkAge(data) {
|
||||||
|
if (data === { age: 18 }) {
|
||||||
|
console.log('You are an adult!')
|
||||||
|
} else if (data == { age: 18 }) {
|
||||||
|
console.log('You are still an adult.')
|
||||||
|
} else {
|
||||||
|
console.log(`Hmm.. You don't have an age I guess`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAge({ age: 18 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## 选项
|
||||||
|
|
||||||
|
A. A: `You are an adult!`
|
||||||
|
B. B: `You are still an adult.`
|
||||||
|
C. C: `Hmm.. You don't have an age I guess` ✅
|
||||||
|
|
||||||
|
## 正确答案
|
||||||
|
|
||||||
|
**C**
|
||||||
|
|
||||||
|
## 答案解析
|
||||||
|
|
||||||
|
在测试相等性时,基本类型通过它们的值(value)进行比较,而对象通过它们的引用(reference)进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。
|
||||||
|
|
||||||
|
题目中我们正在比较的两个对象不是同一个引用:作为参数传递的对象引用的内存位置,与用于判断相等的对象所引用的内存位置并不同。
|
||||||
|
|
||||||
|
这也是 `{ age: 18 } === { age: 18 }` 和 `{ age: 18 } == { age: 18 }` 都返回 `false` 的原因。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本题目来源于JavaScript趣味题集合*
|
||||||
|
*导出工具: JavaScript趣味题网页版*
|
||||||
39
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md
Normal file
39
public/mengyanote/编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# JavaScript趣味题 #28
|
||||||
|
|
||||||
|
> 导出时间: 2025/8/29 14:28:13
|
||||||
|
|
||||||
|
## 题目
|
||||||
|
|
||||||
|
输出是什么?
|
||||||
|
|
||||||
|
## 代码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
String.prototype.giveLydiaPizza = () => {
|
||||||
|
return 'Just give Lydia pizza already!'
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = 'Lydia'
|
||||||
|
|
||||||
|
name.giveLydiaPizza()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 选项
|
||||||
|
|
||||||
|
A. A: `"Just give Lydia pizza already!"` ✅
|
||||||
|
B. B: `TypeError: not a function`
|
||||||
|
C. C: `SyntaxError`
|
||||||
|
D. D: `undefined`
|
||||||
|
|
||||||
|
## 正确答案
|
||||||
|
|
||||||
|
**A**
|
||||||
|
|
||||||
|
## 答案解析
|
||||||
|
|
||||||
|
`String` 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象) 都可以访问该方法!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本题目来源于JavaScript趣味题集合*
|
||||||
|
*导出工具: JavaScript趣味题网页版*
|
||||||
408
public/mengyanote/编程语言/前端/css注入代码合集.md
Normal file
408
public/mengyanote/编程语言/前端/css注入代码合集.md
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
# CSS 效果字典 — 注入代码合集
|
||||||
|
|
||||||
|
> 本文档收集了 *30+* 个常用且有趣的 CSS 注入片段。每个片段都包含:
|
||||||
|
> - **名称**(用途)
|
||||||
|
> - **代码**(可直接复制到控制台或写入 `<style>`)
|
||||||
|
> - **快速用法**(如何注入/如何移除)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 使用说明(快速上手)
|
||||||
|
- **在控制台临时注入**:把下面的 CSS 放到一个 `<style>` 标签里再 append 到 `document.head`。例如:
|
||||||
|
```js
|
||||||
|
const s = document.createElement('style');
|
||||||
|
s.textContent = `/* 把你要的 CSS 放在这里 */`;
|
||||||
|
document.head.appendChild(s);
|
||||||
|
// 移除: s.remove();
|
||||||
|
```
|
||||||
|
- **做成书签脚本(Bookmarklet)**:把单行 JS 从 `javascript:(function(){...})();` 开始保存为书签。
|
||||||
|
- **长期使用**:推荐用 Stylus(仅 CSS) 或 Tampermonkey(JS 注入)管理。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 目录
|
||||||
|
1. 纯色背景
|
||||||
|
2. 渐变背景
|
||||||
|
3. 大图背景覆盖
|
||||||
|
4. 模糊背景(玻璃效果)
|
||||||
|
5. 彩虹文字动画
|
||||||
|
6. 文字跑马灯
|
||||||
|
7. 所有链接高亮
|
||||||
|
8. 可视化网格(布局调试)
|
||||||
|
9. 居中容器(快速调试页面布局)
|
||||||
|
10. 旋转页面
|
||||||
|
11. 倒色模式
|
||||||
|
12. 灰阶/暗色模式
|
||||||
|
13. 字体切换(Comic Sans 恶搞)
|
||||||
|
14. 打字机效果
|
||||||
|
15. 卡片阴影增强
|
||||||
|
16. 元素悬停放大(hover zoom)
|
||||||
|
17. 图片变成圆形并加边框
|
||||||
|
18. 所有按钮变成圆角并增大
|
||||||
|
19. 表单输入聚焦样式
|
||||||
|
20. 隐藏页面元素(广告清理器)
|
||||||
|
21. 打印友好(去除背景和广告)
|
||||||
|
22. 代码高亮(简单样式)
|
||||||
|
23. CSS 变量主题切换器(light/dark)
|
||||||
|
24. 霓虹发光边框
|
||||||
|
25. 浮动提示(tooltip 基础样式)
|
||||||
|
26. 闪烁光标(输入框样式)
|
||||||
|
27. 页面文字渐隐渐显(fade)
|
||||||
|
28. 反色/漫画滤镜
|
||||||
|
29. 模拟夜光(色温调整)
|
||||||
|
30. 页面水印
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 纯色背景
|
||||||
|
**用途**:快速更换页面背景色
|
||||||
|
|
||||||
|
```css
|
||||||
|
body { background: #f0f8ff !important; }
|
||||||
|
```
|
||||||
|
**用法**:把 CSS 放进 `<style>`。移除 style 节点即可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 渐变背景
|
||||||
|
**用途**:让页面有现代渐变效果
|
||||||
|
|
||||||
|
```css
|
||||||
|
body {
|
||||||
|
background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 50%, #fbc2eb 100%) !important;
|
||||||
|
background-attachment: fixed !important;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 大图背景覆盖
|
||||||
|
**用途**:把页面背景替换为在线图片
|
||||||
|
|
||||||
|
```css
|
||||||
|
body {
|
||||||
|
background-image: url('https://picsum.photos/1600/900') !important;
|
||||||
|
background-size: cover !important;
|
||||||
|
background-position: center center !important;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 模糊背景(玻璃效果)
|
||||||
|
**用途**:制造“毛玻璃”或模糊背景层
|
||||||
|
|
||||||
|
```css
|
||||||
|
body::before{
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
backdrop-filter: blur(8px) saturate(120%);
|
||||||
|
-webkit-backdrop-filter: blur(8px) saturate(120%);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 99998;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 彩虹文字动画
|
||||||
|
**用途**:让页面文字颜色循环变化
|
||||||
|
|
||||||
|
```css
|
||||||
|
@keyframes rainbow { 0%{color:#ff0000}20%{color:#ff7f00}40%{color:#ffff00}60%{color:#00ff00}80%{color:#0000ff}100%{color:#8b00ff} }
|
||||||
|
*{ animation: rainbow 4s linear infinite !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 文字跑马灯
|
||||||
|
**用途**:让段落文字像跑马灯一样滚动(适合短文本)
|
||||||
|
|
||||||
|
```css
|
||||||
|
.marqueeize{
|
||||||
|
display:inline-block;
|
||||||
|
white-space:nowrap;
|
||||||
|
animation: marquee 10s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes marquee{ 0%{transform:translateX(100%)} 100%{transform:translateX(-100%)} }
|
||||||
|
|
||||||
|
/* 使用方法(在控制台把选择的元素加上类):
|
||||||
|
document.querySelectorAll('p, h1, h2, li').forEach(el=>el.classList.add('marqueeize'));
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 所有链接高亮
|
||||||
|
**用途**:在调研或扒站时一眼看出页面中所有链接
|
||||||
|
|
||||||
|
```css
|
||||||
|
a { outline: 2px dashed #ffb86b !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 可视化网格(布局调试)
|
||||||
|
**用途**:显示 12 列网格帮助布局调试
|
||||||
|
|
||||||
|
```css
|
||||||
|
.grid-debug::before{
|
||||||
|
content: "";
|
||||||
|
position: fixed; inset:0; pointer-events:none; z-index:99999;
|
||||||
|
background-image: linear-gradient(transparent 0 0), linear-gradient(transparent 0 0);
|
||||||
|
}
|
||||||
|
/* 更强定制可把背景替换成重复线条或者半透明列 */
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 居中容器(快速调试页面布局)
|
||||||
|
**用途**:临时把 body 内主要容器居中并限定宽度
|
||||||
|
|
||||||
|
```css
|
||||||
|
body > * { max-width: 1000px; margin: 0 auto !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 旋转页面
|
||||||
|
**用途**:把页面旋转 180°(搞怪/演示)
|
||||||
|
|
||||||
|
```css
|
||||||
|
html{ transform: rotate(180deg) !important; transform-origin: center center; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 倒色模式
|
||||||
|
**用途**:整体颜色反转(相当于拍照底片效果)
|
||||||
|
|
||||||
|
```css
|
||||||
|
html{ filter: invert(100%) hue-rotate(180deg) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 灰阶 / 暗色模式
|
||||||
|
**用途**:将页面转为黑白,或更接近暗色(用于阅读)
|
||||||
|
|
||||||
|
```css
|
||||||
|
html{ filter: grayscale(100%) contrast(90%) !important; }
|
||||||
|
/* 或者暗色模式 */
|
||||||
|
:root { --bg:#0f0f12; --fg:#e6e6e6; }
|
||||||
|
body{ background:var(--bg) !important; color:var(--fg) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. 字体切换(Comic Sans 恶搞)
|
||||||
|
**用途**:瞬间把页面字体切成 Comic Sans
|
||||||
|
|
||||||
|
```css
|
||||||
|
*{ font-family: 'Comic Sans MS', 'Comic Sans', cursive !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. 打字机效果
|
||||||
|
**用途**:给指定元素文字加打字机动画(需要把类加到元素)
|
||||||
|
|
||||||
|
```css
|
||||||
|
.typewriter { overflow:hidden; white-space:nowrap; border-right: .12em solid rgba(255,255,255,.75); animation: typing 3s steps(40,end), blink .7s step-end infinite; }
|
||||||
|
@keyframes typing{ from{ width:0 } to{ width:100% } }
|
||||||
|
@keyframes blink{ 50%{ border-color: transparent } }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. 卡片阴影增强
|
||||||
|
**用途**:让页面中常见卡片组件更醒目
|
||||||
|
|
||||||
|
```css
|
||||||
|
.card, .panel, .box { box-shadow: 0 10px 30px rgba(0,0,0,0.25) !important; border-radius: 12px !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. 元素悬停放大(hover zoom)
|
||||||
|
**用途**:鼠标移上去时微放大,做交互提示
|
||||||
|
|
||||||
|
```css
|
||||||
|
* { transition: transform .18s ease-in-out !important; }
|
||||||
|
*:hover { transform: translateZ(0) scale(1.02) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 17. 图片变成圆形并加边框
|
||||||
|
**用途**:把页面所有图片做成头像样式
|
||||||
|
|
||||||
|
```css
|
||||||
|
img { border-radius: 999px !important; border: 3px solid rgba(255,255,255,0.6) !important; object-fit: cover; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 18. 所有按钮变成圆角并增大
|
||||||
|
**用途**:改善按钮可点击面积
|
||||||
|
|
||||||
|
```css
|
||||||
|
button, input[type=button], input[type=submit], .btn { border-radius: 999px !important; padding: .8em 1.2em !important; font-weight:600; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 19. 表单输入聚焦样式
|
||||||
|
**用途**:给输入框加聚焦高亮
|
||||||
|
|
||||||
|
```css
|
||||||
|
input:focus, textarea:focus, select:focus { outline: 3px solid rgba(66,153,225,0.6) !important; box-shadow: 0 0 0 4px rgba(66,153,225,0.12) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 20. 隐藏页面元素(广告清理器)
|
||||||
|
**用途**:删除常见广告容器或悬浮元素
|
||||||
|
|
||||||
|
```css
|
||||||
|
iframe, .ad, .ads, [id*='ad'], [class*='ad-'] { display: none !important; visibility: hidden !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 21. 打印友好(去除背景和广告)
|
||||||
|
**用途**:在打印前快速隐藏不必要的元素
|
||||||
|
|
||||||
|
```css
|
||||||
|
@media print {
|
||||||
|
body { background: white !important; color: black !important; }
|
||||||
|
iframe, .ad, nav, footer, .sidebar { display: none !important; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 22. 代码高亮(简单样式)
|
||||||
|
**用途**:给 `<code>` / `<pre>` 添加基础美化
|
||||||
|
|
||||||
|
```css
|
||||||
|
pre, code { background:#0b0b0b; color:#e6e6e6; padding:.4em .6em; border-radius:6px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, 'Roboto Mono', 'Helvetica Neue', monospace; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 23. CSS 变量主题切换器(light/dark)
|
||||||
|
**用途**:示范如何用变量快速切换主题
|
||||||
|
|
||||||
|
```css
|
||||||
|
:root{ --bg:#ffffff; --fg:#111111; }
|
||||||
|
[data-theme='dark']{ --bg:#0b0b0f; --fg:#e6e6e6; }
|
||||||
|
body{ background:var(--bg) !important; color:var(--fg) !important; }
|
||||||
|
/* JS 切换: document.documentElement.setAttribute('data-theme','dark'); */
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 24. 霓虹发光边框
|
||||||
|
**用途**:给重要元素加炫酷发光边框
|
||||||
|
|
||||||
|
```css
|
||||||
|
.neon { box-shadow: 0 0 8px rgba(255,0,111,0.6), inset 0 0 6px rgba(255,0,111,0.2); border:1px solid rgba(255,0,111,0.5); border-radius:10px; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 25. 浮动提示(tooltip 基础样式)
|
||||||
|
**用途**:给带 `data-tooltip` 的元素显示悬浮提示
|
||||||
|
|
||||||
|
```css
|
||||||
|
[data-tooltip]{ position:relative; }
|
||||||
|
[data-tooltip]:hover::after{ content: attr(data-tooltip); position:absolute; left:50%; transform:translateX(-50%); bottom:120%; white-space:nowrap; padding:.3em .6em; background:#111;color:#fff;border-radius:6px; font-size:12px; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 26. 闪烁光标(输入框样式)
|
||||||
|
**用途**:增强输入框的视觉焦点
|
||||||
|
|
||||||
|
```css
|
||||||
|
input[type='text']{ caret-color: #ff5c7c; }
|
||||||
|
input[type='text']::placeholder{ opacity: .7; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 27. 页面文字渐隐渐显(fade)
|
||||||
|
**用途**:页面加载时做个渐入动画,提升体验
|
||||||
|
|
||||||
|
```css
|
||||||
|
.fade-in *{ opacity:0; transform: translateY(6px); animation: fadein .6s forwards; }
|
||||||
|
@keyframes fadein{ to{ opacity:1; transform:none; } }
|
||||||
|
/* 使用: document.body.classList.add('fade-in') */
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 28. 反色 / 漫画滤镜
|
||||||
|
**用途**:把页面变成卡通/漫画风格
|
||||||
|
|
||||||
|
```css
|
||||||
|
html{ filter: contrast(150%) saturate(130%) sepia(10%) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 29. 模拟夜光(色温调整)
|
||||||
|
**用途**:降低蓝光,适合晚间阅读
|
||||||
|
|
||||||
|
```css
|
||||||
|
html{ filter: sepia(10%) hue-rotate(-20deg) brightness(0.95) !important; }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 30. 页面水印
|
||||||
|
**用途**:给页面加浮动水印(仅视觉)
|
||||||
|
|
||||||
|
```css
|
||||||
|
body::after{
|
||||||
|
content: '仅供测试 — 树萌芽';
|
||||||
|
position: fixed; right: 10px; bottom: 10px; opacity: .12; font-size: 14px; pointer-events:none;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 额外:通用注入 / 开关 模板(JS)
|
||||||
|
把下面的 JS 复制到控制台或做成书签,一键注入或移除指定的 CSS:
|
||||||
|
|
||||||
|
```js
|
||||||
|
(function toggleCSS(id, css){
|
||||||
|
let s = document.getElementById(id);
|
||||||
|
if(s){ s.remove(); return 'removed'; }
|
||||||
|
s = document.createElement('style'); s.id = id; s.textContent = css; document.head.appendChild(s); return 'added';
|
||||||
|
})('my-fun-css', 'body{ background: #ffdead !important; }');
|
||||||
|
```
|
||||||
|
|
||||||
|
- 把 `my-fun-css` 改成有意义的 id,把 css 换成任意上面的片段。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tampermonkey 用户脚本模板(自动注入)
|
||||||
|
```js
|
||||||
|
// ==UserScript==
|
||||||
|
// @name Inject Custom CSS
|
||||||
|
// @namespace http://tampermonkey.net/
|
||||||
|
// @version 0.1
|
||||||
|
// @match *://*/*
|
||||||
|
// @grant none
|
||||||
|
// ==/UserScript==
|
||||||
|
(function(){
|
||||||
|
'use strict';
|
||||||
|
const css = `/* 把 CSS 放这里 */`;
|
||||||
|
const s = document.createElement('style'); s.textContent = css; document.head.appendChild(s);
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
75
public/mengyanote/编程语言/前端/纯静态网页的强大功能与应用.md
Normal file
75
public/mengyanote/编程语言/前端/纯静态网页的强大功能与应用.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# 纯静态网页的功能与应用
|
||||||
|
|
||||||
|
纯静态网页(仅由 HTML、CSS、JavaScript 组成,不依赖后端服务器动态生成内容)的能力远比想象中强大,借助现代前端技术和 API,它可以实现丰富的功能和复杂的交互体验。以下是纯静态网页能实现的典型场景和功能:
|
||||||
|
|
||||||
|
### 1. **精美展示型网站**
|
||||||
|
|
||||||
|
* **企业官网 / 个人作品集**:通过 HTML 结构 + CSS(如 Tailwind、Flexbox/Grid)实现响应式布局,配合动画效果(CSS 动画、过渡)展示品牌形象、产品信息或个人作品。
|
||||||
|
|
||||||
|
* \*\* landing page(落地页)\*\*:聚焦营销目标,通过滚动动画、视差效果、表单(前端验证)提升用户转化率,无需后端即可收集表单数据(可通过第三方 API 如 Google Forms、Typeform 转发)。
|
||||||
|
|
||||||
|
* **文档 / 知识库**:用 HTML 构建结构化内容,结合 JavaScript 实现搜索、目录跳转、暗黑模式切换等功能(如 VuePress、Docsify 生成的静态文档)。
|
||||||
|
|
||||||
|
### 2. **交互式工具与应用**
|
||||||
|
|
||||||
|
* **离线可用工具**:
|
||||||
|
|
||||||
|
|
||||||
|
* 计算器、单位转换器、倒计时器等轻量工具(依赖 JavaScript 逻辑)。
|
||||||
|
* 文本处理工具(如 Markdown 编辑器、代码格式化、正则表达式测试器)。
|
||||||
|
* 图像简单处理(如裁剪、滤镜,基于 Canvas API)。
|
||||||
|
|
||||||
|
* **数据可视化应用**:通过 D3.js、Chart.js 等库,将本地数据(JSON/CSV)转化为交互式图表(折线图、地图、3D 模型),无需后端计算。
|
||||||
|
|
||||||
|
* **小游戏**:利用 Canvas、WebGL 或 SVG 实现 2D/3D 游戏(如贪吃蛇、拼图、像素游戏),通过 LocalStorage 保存进度。
|
||||||
|
|
||||||
|
### 3. **本地数据管理**
|
||||||
|
|
||||||
|
* 借助`localStorage`/`sessionStorage`存储用户数据,实现:
|
||||||
|
|
||||||
|
|
||||||
|
* 待办事项(Todo)列表(增删改查、分类标签)。
|
||||||
|
* 个人笔记(支持富文本编辑,基于 Quill、TinyMCE 等库)。
|
||||||
|
* 浏览历史、偏好设置记忆(如主题、语言切换)。
|
||||||
|
|
||||||
|
* 通过 IndexedDB 存储大量结构化数据(如本地日志、离线缓存的表格数据),支持复杂查询。
|
||||||
|
|
||||||
|
### 4. **多媒体体验**
|
||||||
|
|
||||||
|
* **音频 / 视频应用**:用 HTML5 的`<audio>`/`<video>`结合 JavaScript 实现自定义播放器(进度条、倍速、字幕切换)。
|
||||||
|
|
||||||
|
* **交互式画廊**:支持图片轮播、缩放、拖拽排序(基于 JavaScript 事件处理)。
|
||||||
|
|
||||||
|
* **3D 与 AR 体验**:通过 WebGL(Three.js 库)实现 3D 模型展示、全景漫游;借助 WebXR API 实现简单 AR 效果(如手机摄像头叠加 2D 图形)。
|
||||||
|
|
||||||
|
### 5. **跨平台与离线能力**
|
||||||
|
|
||||||
|
* **PWA(渐进式 Web 应用)**:通过 Service Worker 实现离线访问、资源缓存,添加到手机桌面后接近原生 App 体验(如离线新闻阅读、本地工具)。
|
||||||
|
|
||||||
|
* **跨设备适配**:利用 CSS 媒体查询和 JavaScript 检测设备特性,在 PC、平板、手机上提供一致体验。
|
||||||
|
|
||||||
|
### 6. **集成第三方服务扩展功能**
|
||||||
|
|
||||||
|
纯静态网页可通过 API 调用扩展能力(无需自建后端):
|
||||||
|
|
||||||
|
* 表单提交:通过 Netlify Forms、Formspree 等服务将数据发送到邮箱或数据库。
|
||||||
|
|
||||||
|
* 用户认证:集成 Auth0、Firebase Auth 实现登录注册(前端处理令牌验证)。
|
||||||
|
|
||||||
|
* 数据存储:用 Firebase Realtime Database、Supabase 等托管数据库,前端直接读写数据。
|
||||||
|
|
||||||
|
* 支付功能:对接 Stripe、PayPal 的前端 SDK 实现支付流程(无需后端处理敏感信息)。
|
||||||
|
|
||||||
|
### 局限性与解决方案
|
||||||
|
|
||||||
|
静态网页的核心限制是 “无后端”,但可通过以下方式弥补:
|
||||||
|
|
||||||
|
* 数据持久化:依赖第三方 API 或客户端存储(LocalStorage/IndexedDB)。
|
||||||
|
|
||||||
|
* 动态内容:通过 JavaScript 动态加载远程 JSON 数据(如从 GitHub Gist、Contentful 等 CMS 拉取内容)。
|
||||||
|
|
||||||
|
* 服务器功能:用 Serverless 函数(如 Vercel Functions、Cloudflare Workers)处理简单后端逻辑(如数据验证、API 转发),仍保持前端为主的架构。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
纯静态网页适合构建 “前端驱动、交互密集、内容相对固定” 的应用,借助现代前端技术和第三方服务,其能力已覆盖从展示型网站到复杂工具的广泛场景,且具有加载快、部署简单(可托管于 CDN 或静态托管服务如 Netlify、Vercel)、成本低等优势。
|
||||||
198
public/mengyanote/计算机科普/C,C++,CSharp,Objective-c的差异与特点.md
Normal file
198
public/mengyanote/计算机科普/C,C++,CSharp,Objective-c的差异与特点.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、语言概况与发展历史
|
||||||
|
|
||||||
|
|语言|年代 / 背景|设计目标 / 核心理念|所属范式 / 特点|
|
||||||
|
|---|---|---|---|
|
||||||
|
|**C**|1970年代,Dennis Ritchie 在贝尔实验室为 Unix 开发|简洁、高效、接近硬件、可移植|过程式、结构化编程,低级控制能力强|
|
||||||
|
|**C++**|1980年代中期,Bjarne Stroustrup 在 C 基础上扩展|在保留 C 性能和灵活性的基础上,加入面向对象与泛型编程|多范式:过程式 + 面向对象 + 泛型 + 元编程|
|
||||||
|
|**Objective-C**|1980年代,由 Brad Cox 和 Tom Love 开发|将面向对象(消息传递机制)加到 C 上(兼容 C)|C 的超集 + Smalltalk 风格消息机制 + 动态特性 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C"))|
|
||||||
|
|**C#**|2000 年代,由微软为 .NET 平台设计|现代化语言特性、安全性、生产力、面向对象 & 托管运行时|面向对象为主,带垃圾回收、LINQ、泛型、异步编程、元数据支持等|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、主要语言特性对比(从多个维度)
|
||||||
|
|
||||||
|
下面从类型系统、内存管理、继承与多态、泛型/模板、运行时能力、性能与安全性、语言灵活性等维度来对比。
|
||||||
|
|
||||||
|
| 维度 | **C** | **C++** | **Objective-C** | **C#** |
|
||||||
|
| ------------------- | ----------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||||
|
| **类型系统 / 静态 vs 动态** | 静态类型;弱类型转换较宽松(例如指针可转换) | 静态类型 + 可以做动态类型检查(RTTI) | 同时拥有静态与动态特性,消息机制在运行期解析。Objective-C 的方法调用是以消息(message)方式传递,在运行期解析。 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 静态类型 + 有反射机制、动态编程支持(dynamic 类型关键字等) |
|
||||||
|
| **内存管理** | 手动管理:malloc/free、栈/静态分配 | 手动管理 + RAII(资源获取即初始化)、构造/析构函数 | 最初是手动 retain/release;后期引入 ARC(Automatic Reference Counting)减少手动管理复杂度 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 托管内存,由垃圾回收器 (GC) 管理内存分配与回收 |
|
||||||
|
| **继承 / 多态 / 接口** | 无继承 / 无面向对象机制 | 支持单继承 + 多重继承 + 虚函数 | 只支持单继承(不能多继承实现) + 协议(protocols,相当于接口的机制) ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 支持单继承 + 接口 (interface) + 虚方法 + 抽象类等 |
|
||||||
|
| **泛型 / 模板** | 无 | C++ 提供强大的模板机制(泛型编程、元编程) | 在早期 Objective-C 中泛型支持较弱;后来 Apple 在某些场景下用泛型约束、id、id 模式来模拟泛型功能 | 内置泛型 (generics),语言层面支持类型安全的泛型编程 |
|
||||||
|
| **编译时 vs 运行时决定** | 静态决定几乎一切 | 多量的静态优化 (模板展开、内联、编译期多态) | 更偏向运行时,消息机制在运行期解析,允许更灵活的动态行为(如动态消息转发、方法替换等) ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 虽然很多机制静态化,但也支持反射、动态类型、LINQ 表达式树等运行时特性 |
|
||||||
|
| **性能、效率** | 非常接近硬件、开销小 | 高性能,可做底层优化、零抽象开销(若设计得好) | 性能略弱于 C++,因为其运行期特性限制了一些优化(例如消息调用不能像普通函数调用那样被强行内联) ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 性能相对较好,但因 GC 存在停顿、托管开销等,通常不如 C/C++ 在极端性能要求场景下表现好 |
|
||||||
|
| **安全性 / 内存安全** | 不提供很多安全保护,容易出错(缓冲区溢出、未初始化访问等) | C++ 尽可能提供机制(如引用、智能指针等),但程序员仍需谨慎 | 相比 C/C++ 更灵活与安全一些,但仍有可能因为动态机制导致运行期错误 | 较高安全保障(托管内存、类型检查、异常机制等) |
|
||||||
|
| **语言灵活性 / 扩展性** | 简洁、灵活、允许极端底层操作 | 非常灵活(运算符重载、模板、策略模式等) | 在动态特性方面更灵活(方法转发、类别(categories)扩展已有类等) ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C")) | 在现代语言特性(异步、LINQ、表达式、元数据)方面非常强大和生产力高 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、各自的优点与适用场景
|
||||||
|
|
||||||
|
下面逐个总结它们的典型优点与适用场景。
|
||||||
|
|
||||||
|
### C 的优点与场景
|
||||||
|
|
||||||
|
**优点**
|
||||||
|
|
||||||
|
- 简洁、语法少、运行效率高,开销小
|
||||||
|
- 可以非常贴近系统、硬件层面做操作
|
||||||
|
- 可移植性强(在不同平台都能编译)
|
||||||
|
- 许多底层库和系统组件(操作系统、驱动、嵌入式系统)常用 C 实现
|
||||||
|
|
||||||
|
|
||||||
|
**适用场景**
|
||||||
|
|
||||||
|
- 操作系统、内核开发
|
||||||
|
- 嵌入式系统、驱动程序
|
||||||
|
- 性能极端敏感、资源受限的环境
|
||||||
|
- 与其他语言或库做底层交互(写库、接口)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### C++ 的优点与场景
|
||||||
|
|
||||||
|
**优点**
|
||||||
|
|
||||||
|
- 在保持高性能的同时,支持面向对象、泛型编程、元编程
|
||||||
|
- 模板系统允许在编译期做很多优化
|
||||||
|
- 标准库(STL) + 丰富的生态
|
||||||
|
- 灵活性高,可控制抽象开销
|
||||||
|
|
||||||
|
|
||||||
|
**适用场景**
|
||||||
|
|
||||||
|
- 游戏引擎、图形渲染、实时系统
|
||||||
|
- 高性能计算、数值模拟
|
||||||
|
- 大型系统、需要高效率和控制的应用
|
||||||
|
- 桌面软件、跨平台库
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Objective-C 的优点与场景
|
||||||
|
|
||||||
|
**优点**
|
||||||
|
|
||||||
|
- 与 C 完全兼容,可以直接使用 C 代码和库
|
||||||
|
- 采用消息传递机制,更灵活的运行时调用方式
|
||||||
|
- 支持动态特性,如 method swizzling、消息转发、categories(可在运行时给已有类添加方法)等 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C"))
|
||||||
|
- 在 Apple 的 macOS / iOS 平台上拥有成熟框架 (Cocoa, Cocoa Touch) 支持
|
||||||
|
|
||||||
|
**适用场景**
|
||||||
|
|
||||||
|
- macOS / iOS 应用开发(历史上主要选项,现常与 Swift 混用)
|
||||||
|
- 需要动态行为、运行时扩展或反射特性的场景
|
||||||
|
- 维护已有大量 Objective-C 代码库的项目
|
||||||
|
|
||||||
|
不过要注意:自从 Apple 发布 Swift 之后,很多新项目已经倾向于使用 Swift,但 Objective-C 依然在很多老项目或底层框架中存在。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### C# 的优点与场景
|
||||||
|
|
||||||
|
**优点**
|
||||||
|
|
||||||
|
- 现代语言特性丰富:垃圾回收、LINQ、异步/等待 (async/await)、反射、属性 (properties)、事件/委托、元数据、接口、泛型等
|
||||||
|
- 在 .NET 平台上生态完善,工具链成熟(Visual Studio、.NET Core / .NET 运行时等)
|
||||||
|
- 跨平台支持(.NET Core / .NET 5+ 支持 Windows、Linux、macOS)
|
||||||
|
- 相对安全,减少内存错误和手动管理负担
|
||||||
|
|
||||||
|
|
||||||
|
**适用场景**
|
||||||
|
|
||||||
|
- Web 后端(ASP.NET Core)
|
||||||
|
- 桌面应用(WPF、WinForms、UWP 等)
|
||||||
|
- 跨平台应用(通过 .NET 跨平台能力、Xamarin / MAUI 等)
|
||||||
|
- 游戏开发(Unity 引擎使用 C#)
|
||||||
|
- 企业级、业务系统开发
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、它们之间最显著的区别(总结)
|
||||||
|
|
||||||
|
为了便于记忆,可以关注以下几个最容易混淆、但差别很大的方面:
|
||||||
|
|
||||||
|
1. **面向对象 / 继承 / 多态机制**
|
||||||
|
|
||||||
|
- C 是纯过程式,不支持类、对象
|
||||||
|
- C++ 支持类、继承、多态、虚函数,多重继承(但要慎用)
|
||||||
|
- Objective-C 使用消息传递机制(像 Smalltalk):所有对象调用都是发送消息,在运行期解析方法响应,不像 C++ 是编译期绑定 + 虚函数机制 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C"))
|
||||||
|
- C# 是典型的面向对象语言,有接口、抽象类、虚方法、属性、事件等
|
||||||
|
|
||||||
|
2. **内存管理方式**
|
||||||
|
|
||||||
|
- C、C++:手动管理(虽然 C++ 可通过 RAII、智能指针辅助)
|
||||||
|
- Objective-C:最初手动管理,但后期引入 ARC(编译期插入 retain / release)
|
||||||
|
- C#:垃圾回收机制 (GC),开发者通常不需直接管理内存
|
||||||
|
|
||||||
|
3. **编译时 vs 运行时机制 / 灵活性**
|
||||||
|
|
||||||
|
- C++ 更偏向编译时机制(模板展开、内联、编译期优化)
|
||||||
|
- Objective-C 更倾向运行时机制(动态派发、消息转发、类别等动态扩展)
|
||||||
|
- C# 在静态与运行时之间折中,语言设计上含有很多运行时支持 (反射、委托、表达式树等)
|
||||||
|
|
||||||
|
4. **安全性 / 抽象开销**
|
||||||
|
|
||||||
|
- C、C++ 提供最大的灵活性和最高性能,但风险也大(指针错用、内存泄漏、未定义行为)
|
||||||
|
- Objective-C 较灵活,但某些抽象在运行期可能带来开销
|
||||||
|
- C# 强调安全、类型检查、托管环境,相对减少程序员出错的风险
|
||||||
|
|
||||||
|
5. **生态与平台绑定**
|
||||||
|
|
||||||
|
- C / C++:跨平台能力最强
|
||||||
|
- Objective-C:在 Apple 平台(macOS / iOS)生态中使用广泛
|
||||||
|
- C#:在 .NET / Microsoft 生态中占主导,同时借助 .NET Core / Xamarin / MAUI 等实现跨平台
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、举例说明以加深理解
|
||||||
|
|
||||||
|
下面给几个简明对照(伪代码/示意)帮助理解差异:
|
||||||
|
|
||||||
|
### 对象方法调用的差异(C++ vs Objective-C)
|
||||||
|
|
||||||
|
- **C++**
|
||||||
|
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Person {
|
||||||
|
public:
|
||||||
|
void sayHello() { std::cout << "Hello\n"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Person *p = new Person();
|
||||||
|
p->sayHello(); // 直接调用
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Objective-C**
|
||||||
|
|
||||||
|
|
||||||
|
```objectivec
|
||||||
|
@interface Person : NSObject
|
||||||
|
- (void)sayHello;
|
||||||
|
@end
|
||||||
|
|
||||||
|
[ p sayHello ]; // 发送消息,运行期寻找响应方法
|
||||||
|
```
|
||||||
|
|
||||||
|
在 Objective-C 中,对象方法调用不是编译期固定绑定,而是运行期通过 selector / IMP 等机制解析,具有更强的动态性。([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com "Objective-C"))
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、如何根据需求选择
|
||||||
|
|
||||||
|
当你面对一个项目或任务时,下面是一个粗略的选择建议(当然还要考虑团队、已有代码、生态等因素):
|
||||||
|
|
||||||
|
- 如果你需要最接近硬件、最高性能、最小开销 —— **C / C++**
|
||||||
|
- 如果是 Apple 平台 (macOS / iOS) 应用,且需要使用 Cocoa / Cocoa Touch 框架 —— **Objective-C**(或 Swift,现在更多人用 Swift)
|
||||||
|
- 如果你做企业级后台、Web 服务、跨平台 C# 应用、Unity 游戏等 —— **C#** 很可能是首选
|
||||||
|
- 如果项目对性能要求极高,又需要面向对象或泛型能力 —— **C++** 是不错选择
|
||||||
|
- 如果你在维护已有 Objective-C 项目、或需要与旧系统兼容 —— 使用 Objective-C 是必要的
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
49
public/mengyanote/计算机科普/IDE,编辑器,编译器区别和特点.md
Normal file
49
public/mengyanote/计算机科普/IDE,编辑器,编译器区别和特点.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常用的 IDE
|
||||||
|
|
||||||
|
IDE(集成开发环境,Integrated Development Environment)是开发者写代码时常用的工具。常见的 IDE 包括:
|
||||||
|
|
||||||
|
- **Visual Studio Code (VS Code)**:轻量、插件丰富,支持多语言,既能当编辑器也能扩展成强大的 IDE。
|
||||||
|
- **IntelliJ IDEA**:Java 领域最常用的 IDE,也支持 Kotlin、Scala 等。
|
||||||
|
- **PyCharm**:专门针对 Python 开发的 IDE,出自 JetBrains。
|
||||||
|
- **Eclipse**:早期 Java 的主流 IDE,现在依然有人用。
|
||||||
|
- **Android Studio**:专门用于 Android 应用开发,基于 IntelliJ。
|
||||||
|
- **Xcode**:Apple 官方的 IDE,用于 macOS/iOS 开发。
|
||||||
|
- **Visual Studio**:微软出品,适合 C#、C++、.NET 开发。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## IDE、编辑器、编译器的区别
|
||||||
|
|
||||||
|
### 1. 编辑器(Editor)
|
||||||
|
|
||||||
|
- 功能:主要用于编写和修改代码的文本工具。
|
||||||
|
- 特点:轻量,常见功能有语法高亮、代码提示。
|
||||||
|
- 示例:Notepad++、Sublime Text、Vim、VS Code(裸版本更接近编辑器)。
|
||||||
|
|
||||||
|
### 2. IDE(集成开发环境)
|
||||||
|
|
||||||
|
- 功能:包含了编辑器 + 调试器 + 构建工具 + 项目管理等功能,提供一体化的开发环境。
|
||||||
|
- 特点:能写代码、运行、调试、管理依赖,甚至直接部署。
|
||||||
|
- 示例:IntelliJ IDEA、PyCharm、Eclipse、Android Studio、Xcode。
|
||||||
|
|
||||||
|
### 3. 编译器(Compiler)
|
||||||
|
|
||||||
|
- 功能:把源代码翻译成计算机可执行的机器码或中间语言。
|
||||||
|
- 特点:单一职责,不提供编辑功能。
|
||||||
|
- 示例:
|
||||||
|
- C/C++ 用的 GCC、Clang
|
||||||
|
- Java 的 javac
|
||||||
|
- Python 严格说没有传统编译器,通常是解释器(如 CPython、PyPy)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 区别总结
|
||||||
|
|
||||||
|
- **编辑器**:只是“写字”的本子,带点语法高亮。
|
||||||
|
- **编译器**:把代码变成机器能跑的程序。
|
||||||
|
- **IDE**:一个“全家桶”,里面既有编辑器,也能调用编译器,还带调试和项目管理工具。
|
||||||
|
|
||||||
|
---
|
||||||
135
public/mengyanote/计算机科普/操作系统科普.md
Normal file
135
public/mengyanote/计算机科普/操作系统科普.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、目前主流操作系统有哪些
|
||||||
|
|
||||||
|
“操作系统”(Operating System, OS)是管理硬件资源、为上层应用提供运行环境的软件。在各种设备上,都可能有不同种类操作系统。按应用场景划分,主流的有:
|
||||||
|
|
||||||
|
| 设备类型 | 常见操作系统 |
|
||||||
|
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
|
| 个人/桌面/笔记本电脑 | Windows、macOS、各种 Linux 发行版 |
|
||||||
|
| 服务器 / 数据中心 | 各类 Linux 发行版(如 Ubuntu Server、CentOS / Rocky / AlmaLinux / Debian / Red Hat Enterprise Linux 等)、UNIX 系统(如 IBM AIX、Solaris 等,在某些领域还在用) |
|
||||||
|
| 移动设备 / 平板 | Android、iOS(苹果专用) |
|
||||||
|
| 嵌入式 / 物联网设备 | 各种轻量化系统(如基于 Linux 内核的嵌入式 Linux、RTOS、FreeRTOS、Zephyr 等) |
|
||||||
|
| 专用设备 / 工业 / 实时系统 | 各类专用实时操作系统(RTOS),例如 VxWorks、QNX、RT-Thread 等 |
|
||||||
|
|
||||||
|
总结来说,若以“普通用户的电脑 / 手机”为主要参考,则 Windows、macOS 和 Linux 是桌面/笔记本市场常见选择;在手机领域 Android 和 iOS 最主流;在服务器与云端系统则以 Linux 为主。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、操作系统的历史发展
|
||||||
|
|
||||||
|
下面是操作系统发展的一条主线(每个阶段都有很多分支、实验性系统,这里只抓主干):
|
||||||
|
|
||||||
|
1. **早期(1940s–1950s):无操作系统时代**
|
||||||
|
|
||||||
|
- 最初的电子计算机(如 ENIAC)没有操作系统,程序员自己控制硬件、加载程序、逐条指令运行。
|
||||||
|
|
||||||
|
- 为了简化、复用“库”(library)和输入/输出操作,人们逐渐把重复功能抽象出来,形成初步的“监控程序”(monitor)。
|
||||||
|
|
||||||
|
2. **批处理与多道程序设计 / 时分系统(1960s)**
|
||||||
|
|
||||||
|
- 为了提高硬件利用率,引入“批处理”(Batch)方式,把多个程序放在磁带/卡片上按序执行。
|
||||||
|
- 后来发展为 **多道程序设计**(Multiprogramming):内存中可同时放多个作业;操作系统负责调度 CPU、内存、I/O。
|
||||||
|
- **时间分片 / 交互 / 时分系统**(Time-sharing):多个用户可以“同时”交互地使用同一台计算机,通过快速切换响应。
|
||||||
|
- 多个经典系统出现(如 MIT 的 CTSS、MULTICS)。
|
||||||
|
|
||||||
|
3. **Unix 的出现与影响(1970s)**
|
||||||
|
|
||||||
|
- Unix 在贝尔实验室被开发,最初用于小型机 / 研究用途。其设计强调简洁、可移植性。
|
||||||
|
- Unix 被用 C 语言重写,从而更容易移植到不同硬件平台。
|
||||||
|
- 在学术界、研究机构、后来商用系统中被广泛采用,并催生多个衍生系统(BSD、System V 等)。
|
||||||
|
|
||||||
|
4. **个人计算机时代 / 微型机 / GUI 化(1980s–1990s)**
|
||||||
|
|
||||||
|
- 随着微处理器与个人电脑普及,需要适合 PC 的操作系统:如 CP/M、MS-DOS 等。 ([eecs.harvard.edu](https://www.eecs.harvard.edu/~cs161/videos/history.pdf?utm_source=chatgpt.com "A Brief History of Operating Systems - Harvard University"))
|
||||||
|
- Windows(最初是 MS-DOS 上的界面层)逐步发展,加入图形界面、独立内核等。 ([educative.io](https://www.educative.io/answers/differences-between-windows-macos-and-linux-operating-systems?utm_source=chatgpt.com "Differences between Windows, macOS, and Linux operating systems - Educative"))
|
||||||
|
- Apple 的 Mac 系列也推出图形界面操作系统(Mac OS)。
|
||||||
|
- 同时 UNIX / 类 Unix 系统不断改进,出现了 X Window 系统、图形界面层等。
|
||||||
|
|
||||||
|
5. **网络化、分布式与现代操作系统(1990s–至今)**
|
||||||
|
|
||||||
|
- 操作系统要支持网络、分布式计算、互联网服务。
|
||||||
|
- Linux 内核在 1991 年由 Linus Torvalds 发布,成为开源 / 社区驱动的新兴路线。 ([GeeksforGeeks](https://www.geeksforgeeks.org/operating-systems/evolution-of-operating-system/?utm_source=chatgpt.com "History of Operating System - GeeksforGeeks"))
|
||||||
|
- 各种 Linux 发行版出现,用于桌面、服务器、嵌入式等。
|
||||||
|
- macOS(基于 NeXTSTEP / BSD / Darwin)发展壮大,成为 Apple 电脑的核心系统。
|
||||||
|
- 在移动领域,苹果推出 iOS(基于 macOS / Darwin 基础),Google 推出 Android(基于 Linux 内核 + 自有上层栈)。 ([维基百科](https://en.wikipedia.org/wiki/History_of_operating_systems?utm_source=chatgpt.com "History of operating systems"))
|
||||||
|
- 同时操作系统要应对虚拟化、容器化、云计算、大规模集群、微服务、异构计算等新挑战。 ([维基百科](https://en.wikipedia.org/wiki/History_of_operating_systems?utm_source=chatgpt.com "History of operating systems"))
|
||||||
|
|
||||||
|
|
||||||
|
这样,操作系统从“无 OS → 简单监控程序 → 批处理 / 多道 / 交互式系统 → Unix / 类 Unix → 图形界面 / PC 化 → 多平台 / 网络化 / 移动 / 虚拟化 / 云化”一路演进。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、Windows、Linux 和 macOS 三者的区别
|
||||||
|
|
||||||
|
下面从多个维度比较这三类系统的异同:
|
||||||
|
|
||||||
|
|维度|Windows|macOS|Linux(典型 Linux 发行版)|
|
||||||
|
|---|---|---|---|
|
||||||
|
|**内核 / 系统架构**|Windows 使用微软自家内核(Windows NT 内核系列)|macOS 基于 Darwin(包含 XNU 内核、BSD 组件)|使用 Linux 内核 + 上层自由 / 开放软件组件|
|
||||||
|
|**开源 vs 专有**|大部分为专有闭源|Apple 的 macOS 组件多为闭源/混合(部分开源如 Darwin)|大多数发行版完全开源 / 自由软件|
|
||||||
|
|**硬件支持 / 兼容性**|广泛支持多种 PC 硬件,硬件驱动生态完善|只运行在 Apple 自己设计的硬件(Mac)上,兼容性受限但系统与硬件高度集成|Linux 移植性强,可以运行在众多架构(x86, ARM, MIPS 等),但硬件驱动有时依赖社区支持|
|
||||||
|
|**用户界面 / 易用性**|界面直观、用户熟悉、应用生态丰富|界面优美、整体体验一致、系统与硬件结合紧密|桌面环境多样(GNOME, KDE, XFCE 等),定制性强,但对新手可能稍陡峭|
|
||||||
|
|**软件 / 应用生态**|应用种类极多(商业软件、游戏、办公、娱乐等)|在创意、音视频、图形设计等专业软件方面有优势|多数是开源软件,商业闭源软件支持较少(不过近年状况在改善)|
|
||||||
|
|**安全性 / 权限管理**|易成为恶意软件攻击目标(历史原因、广泛使用)|相对安全、沙盒机制、审核机制等|通常安全性较高(开源、社区审查、权限机制),但也需注意配置|
|
||||||
|
|**系统升级 / 版本管理**|自动更新机制成熟;多数更新对向后兼容有保障|Apple 控制版本更新与硬件绑定,对老旧设备支持有限|发行版差异较大,有些滚动更新、版本升级可能要手动干预|
|
||||||
|
|**自由度 / 可定制性**|一定限制(尤其底层系统受控),但有不少自定义空间|自由度较低,用户通常不能改变系统底层|非常高的自由度:可以定制、裁剪、自己编译系统组件等|
|
||||||
|
|**典型用途 /优势场景**|适合游戏、通用办公、广泛软件支持|适合创意设计、多媒体制作、与 Apple 生态整合|适合服务器、开发环境、定制系统、科研、云平台等|
|
||||||
|
|
||||||
|
不同用户 / 场景下,选择哪一种操作系统会有偏好。比如设计师可能偏 macOS,游戏玩家可能倾向 Windows,开发者 / 服务器管理员可能偏好 Linux。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、Linux 发行版是什么
|
||||||
|
|
||||||
|
“Linux 发行版”(Linux distribution,简称 distro)是把 Linux 内核与一系列工具 / 库 / 应用软件打包、配置、分发到用户能够直接安装和使用的完整操作系统版本。
|
||||||
|
|
||||||
|
详细来说,Linux 发行版通常包含以下组件:
|
||||||
|
|
||||||
|
- Linux 内核
|
||||||
|
- GNU 工具链(如 Bash、coreutils、GNU C 库 / glibc 等)
|
||||||
|
- 各种系统库
|
||||||
|
- 包管理系统(如 apt / dpkg、yum / dnf、pacman、zypper 等)
|
||||||
|
- 图形子系统(如 X Window、Wayland)和桌面环境(GNOME、KDE、XFCE 等)
|
||||||
|
- 常用应用软件(浏览器、办公套件、媒体播放器等)
|
||||||
|
- 安装程序、配置工具、安全机制等
|
||||||
|
|
||||||
|
|
||||||
|
发行版的目标是“把用户需要的软件、组件、配置整合好,使得用户可以开箱即用”——而不是用户必须自己从头编译所有软件。
|
||||||
|
|
||||||
|
根据定位、更新策略、社区 / 商业支持、目标用户等不同,发行版可以分为很多种类别,比如:稳定版 vs 滚动更新版、桌面版 vs 服务器版、轻量版 vs 完整版、社区版 vs 企业版等。
|
||||||
|
|
||||||
|
常见的 Linux 发行版例子有:
|
||||||
|
|
||||||
|
- Debian 系列(Debian 本身、Ubuntu、Linux Mint 等)
|
||||||
|
- Red Hat 系列(Red Hat Enterprise Linux、Fedora、CentOS / Rocky / AlmaLinux 等)
|
||||||
|
- Arch、Manjaro、Gentoo、openSUSE 等
|
||||||
|
|
||||||
|
|
||||||
|
发行版之间在包管理、默认软件、目标人群、社区文化等方面有较大差异。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、Android 是否可以看作是一种 Linux 发行版?
|
||||||
|
|
||||||
|
这是一个在技术界和社区中比较有争论的问题。答案是 **不完全可以**。下面我来分析原因及观点:
|
||||||
|
|
||||||
|
### 支持把 Android 视为 Linux 系统的一面
|
||||||
|
|
||||||
|
- Android 使用的是 Linux 内核(即其底层调度、内存管理、驱动支持等核心部分是基于 Linux 内核)
|
||||||
|
- 在很多 Android 设备上,你可以看到 /proc/version 等信息,显示 Linux 内核版本号。
|
||||||
|
- 从这个意义上看,Android 属于“基于 Linux 内核”的一种系统。
|
||||||
|
|
||||||
|
### 反对把 Android 视为传统 Linux 发行版的一面
|
||||||
|
|
||||||
|
- 传统 Linux 发行版通常包括 GNU 工具链(如 glibc、bash、标准 Unix 工具集),而 Android 使用自己的 C 库(Bionic)、不同的 Shell / 命令工具集等,与典型 GNU 工具链并不兼容。
|
||||||
|
- Android 在用户空间架构上与传统 Linux 发行版差别很大:它有独特的应用层框架(如 Android Runtime / ART、Java / Kotlin 运行环境、Binder IPC 等),其生态与传统 Linux 软件栈不兼容。
|
||||||
|
- Android 并不使用传统的 Linux 发行版那种包管理系统(如 apt、rpm 等),也不兼容大多数 Linux 桌面 / 服务器软件。
|
||||||
|
- Android 是为嵌入式 / 移动设备优化的系统,许多底层设计(功耗管理、唤醒锁、内存回收策略等)与通用 Linux 有专门调整。
|
||||||
|
|
||||||
|
|
||||||
|
总结来看,Android 是一种“基于 Linux 内核”的系统,但它不能被简单地视作传统意义上的 Linux “发行版”。更准确地说,Android 是一个以 Linux 内核为基础、构建了一整套用户空间 / 应用生态的独立操作系统。许多人说“Android 是 Linux 的一个发行版”更多是从内核层面的角度说;但如果从完整操作系统、生态兼容的角度看,它与传统 Linux 发行版差异显著。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
@@ -54,3 +54,4 @@
|
|||||||
- **A 端是“定制工程”**,政策导向明显,更看重安全和合规。
|
- **A 端是“定制工程”**,政策导向明显,更看重安全和合规。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
有没有面向D端-开发者developer?
|
||||||
11
public/mengyanote/计算机科普/术语科普-MQ.md
Normal file
11
public/mengyanote/计算机科普/术语科普-MQ.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
MQ(Message Queue,消息队列),是一种基于“队列”模型的中间件,核心作用是实现跨服务的异步通信、解耦和流量削峰。
|
||||||
|
|
||||||
|
简单来说,MQ就像“快递驿站”:发送消息的一方(生产者)把消息放到“驿站”(队列),不需要等接收方(消费者)立即处理;接收方空闲时再从“驿站”取消息处理,双方无需直接通信,也不用等待对方响应。
|
||||||
|
|
||||||
|
MQ的核心价值(对应之前高QPS、异步场景)
|
||||||
|
|
||||||
|
1. 削峰填谷:比如直播间送礼峰值时,大量请求先涌入MQ队列,消费端按数据库/服务的承载能力匀速处理,避免直接打垮后端;
|
||||||
|
2. 解耦服务:送礼场景中,“扣余额”和“发送通知”无需强绑定,扣完余额后扔一条消息到MQ,通知服务自己消费处理,后续新增“积分统计”功能,只需新增一个消费端即可,不用修改核心业务代码;
|
||||||
|
3. 异步提速:用户点击送礼后,后端只需完成“扣余额+发MQ消息”就立即返回成功,后续的“主播收益更新、消息推送”等耗时操作由MQ异步触发,提升接口响应速度。
|
||||||
|
|
||||||
|
常见的MQ产品有RocketMQ、Kafka、RabbitMQ等,在高并发场景(如电商大促、直播、秒杀)中是核心中间件。
|
||||||
5
public/mengyanote/计算机科普/术语科普-POI.md
Normal file
5
public/mengyanote/计算机科普/术语科普-POI.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
POI(Poor Obfuscation Implementation),是Apache基金会提供的一套Java开源API库,核心作用是实现对Microsoft Office格式文件(如Excel、Word、PPT)的读写、编辑和生成。
|
||||||
|
|
||||||
|
简单来说,POI就是Java程序操作Office文件的“工具包”——比如你需要在系统中导出Excel报表(如直播间送礼统计、用户消费明细)、读取Excel中的批量数据(如批量导入用户信息),都可以通过POI来实现。
|
||||||
|
|
||||||
|
它之所以在报表处理场景中常用,是因为能直接操作Office原生格式,支持复杂的单元格样式(合并单元格、公式、图表),且兼容性强,几乎能覆盖所有Office文件操作需求。之前提到的“POI处理报表”,就是指用这套库完成Excel报表的生成、解析等核心操作。
|
||||||
14
public/mengyanote/计算机科普/术语科普-QPS.md
Normal file
14
public/mengyanote/计算机科普/术语科普-QPS.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
QPS(Queries Per Second),即每秒查询率,是衡量服务器在单位时间内处理请求能力的核心性能指标,直接反映系统的并发处理能力。
|
||||||
|
|
||||||
|
简单来说,QPS就像“每秒能接待多少位客人”,比如一个接口的QPS为100,意味着它每秒最多能稳定处理100次用户的访问请求。
|
||||||
|
|
||||||
|
QPS的关键细节说明
|
||||||
|
|
||||||
|
1. 统计范围:通常针对单个接口、单个服务节点或整个系统,不同范围的QPS数值代表的意义不同(如“登录接口QPS”“支付服务QPS”)。
|
||||||
|
2. 与并发量的关系:QPS ≈ 并发量 / 平均响应时间。例如,若系统平均响应时间为0.1秒,并发量为50,那么QPS约为500(50/0.1)。
|
||||||
|
3. 实际应用场景:
|
||||||
|
- 日常运维:通过监控QPS判断系统负载是否正常(如峰值QPS是否超过阈值)。
|
||||||
|
- 架构设计:根据业务预估QPS(如电商大促预估10万QPS),决定服务器集群规模、缓存策略等。
|
||||||
|
- 性能优化:若QPS不足(如请求排队、超时),需通过扩容、优化代码、增加缓存等方式提升。
|
||||||
|
|
||||||
|
例如,普通小型网站日常QPS可能仅几十到几百,而大型电商平台促销峰值QPS可达到几十万甚至上百万。
|
||||||
5
public/mengyanote/计算机科普/术语解释-DMZ.md
Normal file
5
public/mengyanote/计算机科普/术语解释-DMZ.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
DMZ(Demilitarized Zone,隔离区) 是网络安全架构中的一个特殊子网,位于企业内部网络与外部公共网络(如互联网)之间,作为两者之间的“缓冲地带”。
|
||||||
|
|
||||||
|
其核心作用是将需要对外提供服务的服务器(如网站服务器、邮件服务器)部署在此区域,既让外部用户能正常访问这些服务,又通过隔离设计,阻止外部网络直接接触内部核心网络,从而降低内部网络被攻击的风险。
|
||||||
|
|
||||||
|
简单来说,DMZ就像小区门口的“快递收发室”:外部快递员(互联网用户)只能接触收发室(DMZ内的服务器),无法直接进入小区内部(企业核心网络),既保障了对外服务,又守住了内部安全。
|
||||||
117
public/mengyanote/计算机科普/游戏引擎科普.md
Normal file
117
public/mengyanote/计算机科普/游戏引擎科普.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、什么是游戏引擎
|
||||||
|
|
||||||
|
简单来说,**游戏引擎(Game Engine)** 是一套为游戏开发提供“基础设施 / 框架 / 工具”的软件系统。它把许多通用功能(如渲染图形、物理模拟、碰撞检测、声音、输入、动画、资源管理、脚本执行、场景编辑器、跨平台发布等)都封装起来,让开发者不必每次都从“零”写这些功能。
|
||||||
|
|
||||||
|
可以把游戏引擎想象成游戏制作的“骨架 + 工具箱”:你在其上构建你自己的游戏逻辑、关卡、美术、交互等。
|
||||||
|
|
||||||
|
使用引擎的好处包括:
|
||||||
|
- 节省重复造轮子的工作(例如渲染、光照、物理、材质、资源加载等)
|
||||||
|
- 可用编辑器 / 可视化工具辅助提高效率
|
||||||
|
- 跨平台支持(在多个目标平台上输出游戏)
|
||||||
|
- 社区 / 插件 /生态系统支持(美术、音效、扩展模块等)
|
||||||
|
|
||||||
|
不过,引擎也有其局限性(性能开销、约束、难以深度优化等)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、常见的游戏引擎 / 框架及其特点
|
||||||
|
|
||||||
|
下面列出一些主流 /常见的,以及它们的优劣、针对的场景等。这个列表不是穷尽的,但能覆盖大多数实际使用案例。参考维基 “List of game engines” 列表中很多引擎的分类与信息 ([维基百科](https://en.wikipedia.org/wiki/List_of_game_engines?utm_source=chatgpt.com "List of game engines"))。
|
||||||
|
|
||||||
|
| 引擎 / 框架 | 适用方向 /擅长 | 编程 / 脚本方式 | 优点 / 特点 | 局限 /注意点 /适用门槛 |
|
||||||
|
| ------------------------------- | ------------------------------------------------------------ | ---------------------- | ------------------ | -------------------------------- |
|
||||||
|
| **Unity** | 通用、2D / 3D / VR / AR | C#(也支持可视化脚本 / 插件) | 编辑器成熟、社区大、插件丰富、跨平台 | 对于非常极端性能优化项目 / 特定平台可能有限制 |
|
||||||
|
| **Unreal Engine** | 高质量 3D / AAA 级别游戏 | C++ + 蓝图(可视化脚本) | 强大的渲染效果、物理、材质系统 | 学习曲线较陡;对小型团队或 2D 项目可能“过重” |
|
||||||
|
| **Godot** | 独立 / 中小型项目、2D + 部分 3D | GDScript / C# / C++ 扩展 | 轻量、开源、灵活、社区活跃 | 在某些 3D 渲染 /大型项目上与商业引擎还存在差距 |
|
||||||
|
| **GameMaker (Studio / Engine)** | 2D 游戏、像素风、独立游戏 | 自己的脚本语言 / 可视化工具 | 入门门槛低、资源丰富、快速迭代 | 对 3D 支持有限,不适合重 3D 项目 |
|
||||||
|
| **CryEngine** | 高质量 3D /开放世界 /视觉表现 | C++ + 脚本支持 | 强渲染能力、适用于大型游戏 | 学习成本高,社区 /资源相比 Unity / Unreal 较小 |
|
||||||
|
| **Defold** | 2D / 中小型项目 | Lua 脚本 | 轻量、免费、适合移动 / 2D 游戏 | 不适合复杂 3D,扩展能力有限 |
|
||||||
|
| **LibGDX** | 跨平台 / 移动 / 桌面 /小游戏 | Java / Kotlin | 较灵活、基于库的方式,可以控制底层 | 它更偏向框架而不是“全功能引擎”,需要自己补足很多功能 |
|
||||||
|
| **MonoGame / XNA** | 2D / 跨平台 | C# | 继承 XNA 概念,适合中小型游戏 | 相较完整引擎较为基础,需要自己实现很多模块 |
|
||||||
|
| **其他专用 /框架 /轻量引擎** | 如 Phaser(网页 / JS 游戏)、LÖVE(Lua 2D)、OGRE(渲染引擎)、Stride(C# 引擎)等等 | 各自语言 / API | 适合特定平台 /类型 /轻量项目 | 通常功能比较精简,需要开发者补很多东西 |
|
||||||
|
|
||||||
|
此外,还有很多大型游戏公司自己开发的定制引擎(例如《刺客信条》《战神》《最终幻想》《使命召唤》等背后的游戏公司常用的内部引擎)——这些引擎通常针对其团队、技术路线、目标硬件做高度优化和定制。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 引擎之间的关键区别 / 考量维度
|
||||||
|
|
||||||
|
在选择或比较游戏引擎时,以下几个维度是常见考量:
|
||||||
|
|
||||||
|
1. **渲染 / 图形能力**
|
||||||
|
一些引擎在 PBR(物理光照)、全局光照、阴影、后处理效果、贴图质量等方面更强。Unreal / CryEngine 在这方面更突出。
|
||||||
|
|
||||||
|
2. **性能 /资源开销 /优化能力**
|
||||||
|
引擎有自己的运行时开销。一些引擎提供底层访问 /定制能力,让你可以做极致优化;而一些引擎在性能极限时可能受制于其封装层。
|
||||||
|
|
||||||
|
3. **2D / 3D 支持的平衡**
|
||||||
|
有些引擎专注 2D,有些主推 3D,也有两者兼顾。若你的游戏主要 2D,就不必选择一个在 3D 上过度复杂的引擎。
|
||||||
|
|
||||||
|
4. **跨平台支持**
|
||||||
|
是否能方便导出到 PC、主机、移动端、网页、VR/AR 等。一个好的引擎通常支持很多平台。
|
||||||
|
|
||||||
|
5. **脚本 / 可编程性 /扩展性**
|
||||||
|
脚本语言的易用性(如 C#、Lua、Python、GDScript 等),是否可以插入 /扩展底层模块,是否能访问原生代码。
|
||||||
|
|
||||||
|
6. **工具 / 编辑器 /可视化支持**
|
||||||
|
引擎自带的场景编辑器、调试器、动画编辑器、粒子系统编辑器、材质编辑器等越强大,开发效率越高。
|
||||||
|
|
||||||
|
7. **社区 / 插件 /资源生态**
|
||||||
|
有成熟的插件 /资产商店 /示例项目 /社区支持,可以大幅降低开发成本。
|
||||||
|
|
||||||
|
8. **许可 / 费用 /使用成本**
|
||||||
|
有些引擎是开源 /免费(或在特定收入 /规模以下免费); 有些是商业许可 /版税收费 /订阅制。需要注意授权条款、分成模式等。
|
||||||
|
|
||||||
|
9. **团队规模 /学习曲线**
|
||||||
|
大型、复杂引擎可能适合有经验的团队。小团队 /新手往往更偏好轻量、易用的引擎。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、开发游戏是否必须要用游戏引擎?
|
||||||
|
|
||||||
|
答案是:**不一定“必须”,但在绝大多数场景下,使用游戏引擎是非常推荐、效率与成本优势极高的选择**。
|
||||||
|
|
||||||
|
### 可以不使用引擎 / 自己写游戏的情况
|
||||||
|
|
||||||
|
- 有极端性能 /极端控制需求:有些项目为了最优化、特殊硬件、或很独特的架构,可能需要自己写底层渲染 /资源 /内存管理等。
|
||||||
|
- 教学 /研究 /技术探索目的:自己写引擎是非常好的学习过程,可深入理解游戏底层原理。网上很多“如何写一个游戏引擎”的教程资源可参考。 ([Video Game Design and Development](https://www.gamedesigning.org/learn/make-a-game-engine/?utm_source=chatgpt.com "How To Make a Game Engine: The Easy Way - GameDesigning.org"))
|
||||||
|
- 小型 / 简单 /实验性项目:比如非常简单的 2D 游戏或小游戏,可以用基础框架 /图形库(如 SDL、OpenGL / WebGL /Canvas /HTML5)来写,而不需要完整引擎。
|
||||||
|
|
||||||
|
有文章论述:即便在现代,也有开发者选择“无引擎(engine-less)”方式以获得更细粒度控制和理解。 ([klizos.com](https://klizos.com/making-games-in-2025-without-an-engine/?utm_source=chatgpt.com "Making Games in 2025 Without an Engine: Why Some Devs Still Go Raw"))
|
||||||
|
|
||||||
|
然而,自己写引擎 /“不使用现存引擎”的代价也很高:
|
||||||
|
|
||||||
|
- 必须自己实现渲染、物理、碰撞、资源管理、动画、音频、UI、脚本、优化、平台适配、工具链、调试器、编辑器等 — 开发成本极高。
|
||||||
|
|
||||||
|
- 后期维护、扩展、跨平台、性能优化难度极大。
|
||||||
|
|
||||||
|
- 对于商业 /正常规模项目而言,这样做往往不划算。
|
||||||
|
|
||||||
|
|
||||||
|
### 使用现有游戏引擎的好处(为什么绝大多数项目都用引擎)
|
||||||
|
|
||||||
|
- 开发效率极大提升 — 你可以把精力集中在游戏逻辑 /玩法 /内容本身,而不是底层通用模块。
|
||||||
|
- 有现成的工具支持:场景编辑器、调试、资源导入 /导出、可视化界面等。
|
||||||
|
- 更容易跨平台输出。
|
||||||
|
- 可利用社区资源 /插件 /素材库,减少重复工作。
|
||||||
|
- 在规模 /性能限制未极端时,引擎提供的封装和抽象足以满足大多数需求。
|
||||||
|
|
||||||
|
很多业内文章 /资源都强调:对于绝大多数中小型团队 /独立开发者而言,使用成熟引擎是更现实、更高效的选择。 ([indiedevgames.com](https://indiedevgames.com/the-ultimate-guide-to-comparing-game-engines-key-features-and-factors-to-consider/?utm_source=chatgpt.com "The Ultimate Guide to Comparing Game Engines: Key Features and Factors ..."))
|
||||||
|
|
||||||
|
因此,除非你有非常特殊的需求或追求极致优化 /学习研究目的,否则“用现成引擎”几乎是标准做法。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、总结 + 给你的建议
|
||||||
|
|
||||||
|
- 市面上常见的游戏引擎 /框架很多,不同引擎在渲染能力、脚本语言、工具支持、性能控制、生态 /社区、授权模式等方面都有差异。
|
||||||
|
- 引擎极大地降低了游戏开发的门槛,提高效率,是目前主流做法。
|
||||||
|
- 但在理论上,你也可以不使用引擎,完全自己写底层模块;不过那样做代价极高,适合研究 /教学 /极端需求方向。
|
||||||
|
- 选择引擎时,要根据你游戏的类型(2D / 3D /VR /AR /网页 /移动 /主机)、你的团队规模 /技术栈 /预算 /性能需求等因素来选最合适的那个。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
122
public/mengyanote/计算机科普/游戏行业简单科普.md
Normal file
122
public/mengyanote/计算机科普/游戏行业简单科普.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、游戏行业主要岗位类别(大框架划分)
|
||||||
|
|
||||||
|
游戏公司里岗位很多,可以从“技术 / 美术 / 设计 / 运营 / 支持 /管理 /商务”等维度来分类。下面按“研发链条 + 周边链条”讲比较清楚。
|
||||||
|
|
||||||
|
|类别|典型岗位|核心职责 /产出|常见技能要求 /门槛|
|
||||||
|
|---|---|---|---|
|
||||||
|
|**程序 /技术**|客户端程序 / 客户端工程师|实现客户端逻辑、UI、渲染、动画、特效等|熟悉引擎(Unity/Unreal/Cocos等),C#/C++/Lua/Shader 等|
|
||||||
|
||服务端 /后端程序|服务器逻辑、网络通信、存储、接口、安全等|熟悉分布式、数据库、网络协议、微服务等|
|
||||||
|
||引擎 /底层架构 /渲染 /图形学工程师|开发或优化引擎模块、渲染管线、图形算法|熟悉图形学、GPU 编程、渲染优化、引擎架构|
|
||||||
|
||工具 /编辑器开发|为美术、策划等做工作流工具、插件、自动化脚本|熟悉工具链、脚本语言(Python, C#, JS/TS)、接口设计|
|
||||||
|
||技术美术(Technical Artist / Tech Artist)|桥接“美术”和“程序”,负责特效、材质、shader、性能优化、美术工具流程等|既懂美术又稍懂程序 / shader /管线流程|
|
||||||
|
||音频 / 声音程序|负责游戏中的音效、背景音乐、3D 音频系统、音频性能优化|熟悉音频中间件(如 Wwise / FMOD /自研音频系统等)|
|
||||||
|
||AI / 算法 /机器学习工程师|游戏中的AI行为、NPC策略、路径规划、智能系统|熟悉算法、数据结构、AI 基础、可能需机器学习经验|
|
||||||
|
||网络 / 性能 /安全 /运维工程师|负责网络性能、安全、运维支持、云服务等|熟悉网络、安全、云部署、性能调优、监控机制|
|
||||||
|
||UI 前端 /界面程序|负责游戏界面、HUD、交互动画等|熟悉界面框架、动画、响应式设计、跨平台适配|
|
||||||
|
|**策划 / 设计**|游戏策划 /玩法策划|设计游戏机制、规则、关卡、系统、平衡、数值等|数学/rate、逻辑思维、对玩法敏锐度、体验感|
|
||||||
|
||系统策划 /系统设计|设计游戏的大系统框架(如经济体系、成长体系、社交系统等)|要理解游戏的长线机制、玩家行为|
|
||||||
|
||数值策划|负责游戏中的数值公式、成长曲线、平衡性调整|要有扎实的数学基础、参数调优经验|
|
||||||
|
||关卡 /副本 /地图策划|设计具体关卡、地图、流程、任务等|要有美术感、流程感、玩家节奏把控|
|
||||||
|
||交互 /界面 / UX 设计|设计界面交互流程、玩家操作体验、菜单布局等|要懂交互原则、用户行为、常用设计工具 (如 Sketch, Figma)|
|
||||||
|
||文案 /剧情 /脚本策划|撰写游戏剧情、脚本、对话、世界观设定等|要有文字功底、故事架构能力、表达清晰|
|
||||||
|
|**美术 / 视觉表现**|原画 / 概念设计|画角色、场景、道具等概念设计图|美术基础强、熟练掌握 Photoshop、绘画功底|
|
||||||
|
||3D 模型 / 角色建模|用 3D 软件(Maya/3ds Max/Blender 等)建模角色 /道具 /环境|网格拓扑、贴图、雕刻、UV 展开、骨骼绑定基础|
|
||||||
|
||场景 /建筑美术|负责场景、环境、建筑、地形等的建模或贴图|注重构图、空间感、材质贴图、光照把握|
|
||||||
|
||贴图 /材质 /纹理 / PBR 艺术|负责贴图/法线/高光/材质工作|熟悉 Substance Painter / Designer、纹理流程|
|
||||||
|
||骨骼 / 绑定 / 骨骼动画|给角色做骨骼绑定、角色动画、蒙皮权重|熟悉骨骼系统、动画曲线、过渡、IK / FK 等|
|
||||||
|
||角色 /动作 / 动画 / 表演|角色动作、战斗动作、转场动画、表演动画|动作把握、动画曲线、连接自然流畅、动作组合|
|
||||||
|
||特效 /粒子 /Shader 可视化|制作技能特效、爆炸、光影、粒子系统等|熟悉特效工具、shader、GPU 优化、实时效果|
|
||||||
|
||灯光 /渲染 /后期 /美术优化|场景灯光、后期色调、实时渲染优化|熟悉渲染管线、光照模型、材质优化、烘焙流程|
|
||||||
|
||UI 美术 / 界面设计|设计游戏界面风格、ICON、按钮、界面元素|掌握 UI 美学、配色原则、界面流程|
|
||||||
|
|**测试 /质量保障**|测试 / QA / 功能测试|发现游戏中功能性缺陷、逻辑漏洞、兼容性问题|要细致、系统化思考、熟悉测试流程、bug 提交|
|
||||||
|
||性能 /稳定性测试|测试卡顿、内存泄漏、帧率异常、崩溃等问题|需懂性能监测工具、日志分析、各种平台差异|
|
||||||
|
||自动化测试 /SDK 测试 /工具测试|编写测试脚本、自动化流程、SDK 接入测试|要有编程能力、脚本语言、测试框架知识|
|
||||||
|
|**产品 /项目 /运营**|产品经理 / 产品负责人|对接市场与研发,定义目标、功能、路线图、分析数据|要懂业务、用户、数据分析、项目管理|
|
||||||
|
||项目 / 制作人 /项目经理|管理项目进度、资源、沟通、风险、人员协调|要有跨团队沟通能力、敏捷流程、项目管理经验|
|
||||||
|
||发行 /市场 /推广|游戏上市、宣传、渠道合作、用户获取与推广|要懂市场渠道、广告投放、数据营销、媒体资源|
|
||||||
|
||运营 /社区 /活动策划|负责游戏上线后的日常运营、活动、用户留存、社区互动|要善于用户运营、数据分析、活动设计、用户心理|
|
||||||
|
||渠道 /商务 /代理 /发行合作|与渠道、平台、分发、发行商、广告商合作|商业谈判、合同、分成机制、渠道生态理解|
|
||||||
|
|**支持 / 管理 /后勤**|美术 /技术主管 /总监|负责技术 / 美术方向的路线、规范、团队指导|要有较强的专业能力、管理能力、跨团队视野|
|
||||||
|
||HR / 招聘 /培训|招人、培训、绩效、团队建设|对游戏行业生态有了解、用人标准熟悉|
|
||||||
|
||技术 / 美术 /策划 教育 /讲师|在培训机构、院校授课、课程研发|要有实战经验,能够把技术/流程拆解讲清|
|
||||||
|
||法务 /知识产权 /版号合规|处理合同、版号、审查、法律合规事务|要有法律背景或专长、理解游戏行业法规|
|
||||||
|
||运营支持 /社区 /客服 /数据分析|客服、用户反馈、社区维护、数据监控|要有沟通能力、处理用户问题经验、数据敏感度|
|
||||||
|
|
||||||
|
这个表格只是一个“指标体系”,实际公司里岗位可能合并、交叉或细分更多。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、在中国现实中招聘情况 — 举例 + 薪资 /热门岗位
|
||||||
|
|
||||||
|
下面结合目前中国招聘平台看到的真实岗位示例 + 行业报告,来具体说明哪些岗位常被招聘、薪资水平如何、哪些更热门、哪些竞争激烈。
|
||||||
|
|
||||||
|
### 典型招聘示例
|
||||||
|
|
||||||
|
从猎聘上“游戏开发”招聘可以看出:
|
||||||
|
|
||||||
|
- **客户端开发工程师**:3–5年经验,薪资约 **20,000–40,000 元/月**(一线/大厂可能更高) ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com "【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘"))
|
||||||
|
- **UE5 客户端开发**:某些公司在杭州地区招 UE5 开发工程师,薪资有 8–13k(刚入门/小团队) ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com "【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘"))
|
||||||
|
- **Unity / Cocos 游戏开发工程师(中级 /高级)**:在北京 /深圳 /上海等地薪资区间 25k–50k 左右 / 月比较常见 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com "【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘"))
|
||||||
|
- **测试开发 / QA**:高级 /资深测试开发工程师,对接端游 /大型项目,有些月薪可达 30k 左右 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com "【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘"))
|
||||||
|
- **工具 /引擎 /渲染方向**:常被列为“资深 /专家”岗位,工资有可能高于普通客户端工程师水平 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com "【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘"))
|
||||||
|
- 在游戏行业的整体热门招聘方向里,“策划 /产品 /运营 /发行 /美术”也是持续高频需求。2024 年游戏行业人才报告中提到:游戏策划在新发布职位中占比最高。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com "2024游戏行业人才供需大数据报告_中华网"))
|
||||||
|
|
||||||
|
|
||||||
|
### 薪资与趋势(行业报告视角)
|
||||||
|
|
||||||
|
- 据《游戏行业人才供需大数据报告》显示,游戏行业中 **年薪 20 万以上** 的职位占比较高;很多中高阶岗位薪资可以达到或高于这个水平。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com "2024游戏行业人才供需大数据报告_中华网"))
|
||||||
|
- 报告还指出,产品经理、Unity / U3D 相关岗位平均年薪可能超过 30 万。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com "2024游戏行业人才供需大数据报告_中华网"))
|
||||||
|
- 根据猎头报告,近几年游戏行业供需比大体在 2.4:1 左右(即约 2.4 人竞争一个岗位)([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com "2025年中国游戏行业人才供需现状与猎头市场深度分析"))
|
||||||
|
- 在大厂里,主策 / 资深美术 /高级技术岗位的薪资与待遇相对稳定,但在中小型团队(尤其是创业 /出海团队)给的钱可能有很大浮动。([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com "2025年中国游戏行业人才供需现状与猎头市场深度分析"))
|
||||||
|
- 热门方向(如图形学 / 引擎 /特效 /AI)往往比“通用客户端逻辑”更吃香,但对应门槛也高。([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com "2025年中国游戏行业人才供需现状与猎头市场深度分析"))
|
||||||
|
|
||||||
|
|
||||||
|
### 热门 vs 冷门岗位、风险点
|
||||||
|
|
||||||
|
- **热门**:客户端开发(尤其 Unity / Unreal /跨平台开发)、技术美术 /特效、引擎 /渲染方向、策划 /玩法 /系统 /数值、产品 /运营。
|
||||||
|
- **较冷 /竞争激烈 /门槛高**:服务端 /后端(部分游戏公司服务端人员相对少),某些通用测试 /兼容性测试(容易被外包替代),脚本 /游戏文案(文科方向很多竞争者)。
|
||||||
|
- 公司对跨职能能力或复合能力(懂技术又懂玩法 /懂美术又懂性能)越来越看重。
|
||||||
|
- 中小团队或创业项目常见风险:项目不稳定、被砍、薪资拖欠、岗位职责不清、加班严重。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、不同类型公司/团队的差异 —— 求职策略视角
|
||||||
|
|
||||||
|
行业里公司规模、定位、业务模式差异很大,入职体验/晋升空间 /稳定性 等也差很多。下面对比几类常见公司 /团队,以及适合的岗位类型和选择策略。
|
||||||
|
|
||||||
|
|类型|特点 /优劣|常见岗位机会|求职策略建议|
|
||||||
|
|---|---|---|---|
|
||||||
|
|**大厂 /头部游戏公司** (如腾讯、网易、米哈游、莉莉丝、腾讯子公司、字节游戏)|稳定、资源多、品牌强、项目大、流程规范|各类岗位几乎都有:客户端 / 服务端 / 渲染 /工具 /策划 /美术 /运营 /产品等|要有扎实的基础、丰富项目经验、强作品集;面试门槛高,竞争激烈|
|
||||||
|
|**中型 / 上市 /成型团队**|资源有保障,但灵活性比大厂高些|更注重各条线的中坚力量:中高级程序、美术、策划、技术美术|可以作为跳板,争取担当更关键角色;注意公司项目与融资背景|
|
||||||
|
|**小型 / 独立 /工作室 /创业团队**|自由度高、职责多、成长快,但项目风险、稳定性差|可能需要“一肩挑”多个角色(既写程序又做工具 /特效)|要评估公司靠谱度、资金链、项目立项情况;最好事前了解团队背景|
|
||||||
|
|**出海 /外国 /合资 /独立游戏公司**|更强调英语 /跨文化能力、国际发行经验|更多需要本地化 /跨平台 /版本适配 /SDK 接入等岗位|英语能力、跨文化理解、对海外市场的感知是加分项|
|
||||||
|
|**外包 /代工 /美术/ 中间件 /工具 /引擎公司**|项目外包多、稳定性、工资体系可能略低|美术、模型、动作、特效、工具支持、插件/中间件开发|适合初学者积累经验;但演练的项目常是“给别人的模块”,创意自由度小|
|
||||||
|
|
||||||
|
**策略建议 /提醒:**
|
||||||
|
|
||||||
|
- 应届生 /初级人员:优先考虑大厂 /成型团队 /稳定公司,积累经验与作品,之后再进入细分方向(如引擎、渲染)。
|
||||||
|
- 如果进入小团队 /创业团队,要非常注意“项目可行性 /融资 /退出机制 /合同条款 /工资发放机制”这些细节。
|
||||||
|
- 在简历 /面试中,作品和项目经历通常比学历 /证书更重要。因为游戏行业强调“做出来能上线 /能看的 demo /你在项目里具体做什么”更具说服力。
|
||||||
|
- 在面试前研究公司产品 /项目 /技术栈 /过往游戏,对方用什么引擎 /擅长什么风格 /市场定位是什么,这会在面试中非常加分。([知乎专栏](https://zhuanlan.zhihu.com/p/1918456438566655094?utm_source=chatgpt.com "想要入职游戏公司的应届毕业生同学,一定要认真看这篇!"))
|
||||||
|
- 多维护行业内人脉 /参加游戏开发社区 /线上 hackathon /项目实践 /开源 /技术分享,有助于增加曝光度和获取推荐。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、建议你关注 /考虑的几个“落脚点”岗位 +提升路径
|
||||||
|
|
||||||
|
为了更具有可操作性,这里列几个“比较稳健 +成长空间较好的”岗位作为落脚点建议,以及你未来可以怎样往更高阶发展:
|
||||||
|
|
||||||
|
|入门 /中级阶段|技能 /方向|往上发展可能路径|
|
||||||
|
|---|---|---|
|
||||||
|
|客户端程序员(Unity / Cocos / Unreal)|熟练掌握一个主流引擎 + 脚本语言 + 性能调优|向渲染 /引擎方向 /技术美术 /架构师 /技术负责人发展|
|
||||||
|
|技术美术 /特效美术|掌握 Shader /粒子系统 /管线 /材质优化|向美术方向精深化 / 管线方向 / GPU 特效 /实时渲染方向|
|
||||||
|
|游戏策划 / 系统 /数值策划|对玩法 /系统 /玩家心理要有敏感度,能做数据分析|向主策 /设计总监 /制作人发展|
|
||||||
|
|产品 / 运营 / 数据分析|熟悉产品生命周期、用户行为、留存 /增长 /变现机制|向产品经理 /高级产品 /运营总监方向发展|
|
||||||
|
|引擎 /渲染工程师|深入图形学 / GPU / shader /渲染算法|向架构师 /图形学专家 /引擎主管 /技术总监发展|
|
||||||
|
|测试 /QA / 自动化测试|扎实的测试流程 /平台兼容认知 /脚本开发能力|向测试架构 /测试工具 /性能保障 /安全方向发展|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
155
public/mengyanote/计算机科普/编程语言之间的划分.md
Normal file
155
public/mengyanote/计算机科普/编程语言之间的划分.md
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、从抽象层次看:机器 → 汇编 → 高级语言
|
||||||
|
|
||||||
|
这是最经典、最直观的划分:按语言与底层硬件(机器)之间的距离/抽象级别来划分。
|
||||||
|
|
||||||
|
### 1. 机器语言(Machine Language / Machine Code)
|
||||||
|
|
||||||
|
- 机器语言就是“CPU 最原生能直接执行”的那种指令,通常用二进制(0/1)表示。
|
||||||
|
- 每一条机器指令对应 CPU 的一种操作(如加、减、跳转、读写内存等)。
|
||||||
|
- 它与硬件架构(CPU 的指令集架构,Instruction Set Architecture, ISA)非常耦合:不同架构(x86, ARM, RISC-V 等)有不同的机器码格式、指令编码方式、寄存器结构、寻址方式等。
|
||||||
|
- 优点:效率最高(因为已经是最终可执行形式)、控制极细粒度。
|
||||||
|
- 缺点:难写、难读、不便维护、不具可移植性(写给一种 CPU 架构的机器语言在另一种架构上通常不可执行)。
|
||||||
|
|
||||||
|
> 机器语言通常看起来就是一串 0/1,或者十六进制表示形式。
|
||||||
|
|
||||||
|
### 2. 汇编语言(Assembly Language)
|
||||||
|
|
||||||
|
- 汇编语言是对机器语言的一种“符号化”表示。汇编语言用助记符(mnemonics,如 `MOV`, `ADD`, `SUB`, `JMP` 等)和标号、标签、伪指令等来代替那些直接的二进制或十六进制操作数,使得程序员能够“看懂一点儿”机器指令对应的含义。
|
||||||
|
- 每条汇编指令通常与一条(或一组)机器指令一一对应或有比较直接的映射(虽然有些汇编器允许宏、伪指令、寄存器别名、宏展开等辅助特性)。
|
||||||
|
- 汇编语言仍然高度依赖硬件架构。你需要知道寄存器、地址模式、指令集、内存模型等底层细节才能写出有效的汇编。
|
||||||
|
- 汇编语言需要 “汇编器”(assembler)把汇编指令翻译为机器码。
|
||||||
|
- 优点:比机器码略好写/理解,但仍保留了对硬件的精细控制;在某些需要性能极限或直接控制硬件(如操作系统内核、设备驱动、嵌入式系统、性能关键模块)里仍有应用。
|
||||||
|
- 缺点:依然难以阅读、编写、维护;缺乏可移植性;编程效率低。
|
||||||
|
|
||||||
|
> 汇编语言是“低级语言” 的代表,它是机器语言之上,但抽象层次仍然很低。
|
||||||
|
|
||||||
|
举例:在 x86 架构下,一条汇编可能写成 `mov eax, [ebx+4]`,而对应的机器码可能是某个具体字节序列。 ([GeeksforGeeks](https://www.geeksforgeeks.org/computer-organization-architecture/difference-between-assembly-language-and-high-level-language/?utm_source=chatgpt.com "Difference between assembly language and high level language"))
|
||||||
|
|
||||||
|
### 3. 高级语言(High-Level Language)
|
||||||
|
|
||||||
|
- 高级语言是针对人来写的,它把很多底层细节(如寄存器管理、内存寻址、指令编码、数据布局、跳转指令等)“抽象”掉,让程序员可以用更接近自然语言、数学表达、算法思维的方式编写程序。
|
||||||
|
- 在高级语言中,你可能使用变量、函数/子程序、类/对象、数据结构(数组、链表、字典等)、控制结构(if/else、while、for 等)、模块化、异常处理、泛型、垃圾回收、标准库等等。你不用去写具体的寄存器操作或机器指令。
|
||||||
|
- 高级语言编写的代码不能直接被 CPU 执行,而是要经过 **翻译阶段**——通常编译器 (compiler) 或解释器 (interpreter),或者两者结合(先编译成中间代码/字节码,再由虚拟机(VM)或 JIT 编译器进一步转成机器码)。 ([维基百科](https://en.wikipedia.org/wiki/High-level_programming_language?utm_source=chatgpt.com "High-level programming language"))
|
||||||
|
- 好处:可读性强、开发效率高、可维护性好、跨平台(可移植性)强(只要有该语言在某个平台上的编译器/运行时)。
|
||||||
|
- 缺点:相比汇编和机器语言可能效率略低(因为抽象层次更高会带来运行时开销或不必要的中间步骤)。但现代编译器优化、JIT 技术等可以缩小这个差距。
|
||||||
|
|
||||||
|
> “高级” 并不是绝对的:所谓“高级语言”是相对于 “汇编/机器” 而言的抽象概念。随着时间推移,以前认为是“高级”的语言可能在今天看来也不算太高级。 ([维基百科](https://en.wikipedia.org/wiki/High-level_programming_language?utm_source=chatgpt.com "High-level programming language"))
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. “中级语言”/中间表示(Intermediate)
|
||||||
|
|
||||||
|
在某些文献或教材中,会提到“中级语言”(middle-level language 或 intermediate language),作为介于汇编语言和高级语言之间的一个 “中间层”。这个概念有些模糊,不过可以理解为:
|
||||||
|
|
||||||
|
- 中级语言可能既具有一定的抽象(不像汇编那样要直接操控寄存器、地址、跳转等细节),但同时也允许底层控制(如指针、直接内存操作、内联汇编等)。
|
||||||
|
- C 语言有时被称为“中级语言”或“中级抽象语言”(因为它既提供抽象机制(函数、结构体、控制流)又允许操作指针、地址、直接访问内存)——它处于一个折中位置:既不像汇编那样极低级,也不像 Python/Java 那种高度抽象。
|
||||||
|
- 现代语言体系里,也有“中间表示”(Intermediate Representation, IR/中间语言)这个术语:在编译器实现里,为了优化、跨平台等目的,往往把源代码先翻译成一种统一的中间形式(例如 LLVM IR、Java 的字节码、.NET 的中间语言 IL 等),再从中间表示进一步翻译成目标机器代码。这个 IR 在某种意义上就是“介于高级语言和机器码之间”的一种“内部语言”。
|
||||||
|
|
||||||
|
所以,在“机器 / 汇编 / 高级”这个三分法里,“高级”一端可以细分出不同层次、高度的语言。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、对比:三者的特点总结
|
||||||
|
|
||||||
|
下面是一个对比表,从多个维度展示机器 / 汇编 / 高级语言各自的特点:
|
||||||
|
|
||||||
|
|维度|机器语言|汇编语言|高级语言|
|
||||||
|
|---|---|---|---|
|
||||||
|
|抽象级别|最原生、最低|较低|高|
|
||||||
|
|表示方式|二进制 / 机器码|助记符 + 操作数 + 标签|变量、函数、数据结构、控制流、模块等高级结构|
|
||||||
|
|可读性 / 可写性|极差,非常难|较难,需要理解硬件|较好,对人友好|
|
||||||
|
|控制能力|最强(直接控制硬件)|很强|一般(抽象化封装底层)|
|
||||||
|
|可移植性|几乎无|很小|较强(只要有编译器/解释器支持)|
|
||||||
|
|执行效率|最高|很高|略低(依赖于语言实现、优化技术)|
|
||||||
|
|典型用途|引导启动程序、固件、极限优化代码|操作系统内核、驱动、嵌入式系统、性能关键模块|应用程序、业务逻辑、脚本、Web、AI、系统软件(高层部分)|
|
||||||
|
|
||||||
|
从这个比较可以看到:随着抽象级别越高,开发效率越高、可读性越好、可维护性越强;但代价是可能牺牲一些对硬件的精细控制、效率以及资源开销。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、编程语言的更广泛/更细致的划分
|
||||||
|
|
||||||
|
除了“按抽象级别”划分,还有很多其他方式可以给编程语言分类。下面是几种常见的分类视角与示例。
|
||||||
|
|
||||||
|
### *(一)按“语言代数/世代”划分(Generations)*
|
||||||
|
|
||||||
|
历史上,人们有一种“世代语言(generations of programming languages)”的划分方法。以下是一个常见版本的五代划分: ([GeeksforGeeks](https://www.geeksforgeeks.org/blogs/generation-programming-languages/?utm_source=chatgpt.com "Generations of Programming Languages - GeeksforGeeks"))
|
||||||
|
|
||||||
|
1. **第一代语言(1GL)**:机器语言(二进制)。
|
||||||
|
2. **第二代语言(2GL)**:汇编语言。
|
||||||
|
3. **第三代语言(3GL)**:传统高级语言,如 Fortran、COBOL、C、Pascal、ALGOL 等。
|
||||||
|
4. **第四代语言(4GL)**:更高层的、面向问题、声明式或领域特定的语言(比如 SQL、MATLAB、一些报表语言、脚本语言、DSL 等)。
|
||||||
|
5. **第五代语言(5GL)**:通常指基于人工智能、逻辑编程、约束求解、自动推理等更高抽象层次的语言(例如 Prolog、某些函数式或逻辑范式语言、知识库语言等)。
|
||||||
|
|
||||||
|
这种划分有一定历史意义,但在现代语境下界限并不严格。例如,很多语言混合使用不同层面的特性;而“第 4 代 / 第 5 代”语言的定义也常有争议。
|
||||||
|
|
||||||
|
### *(二)按 **编程范式 / 风格** 划分*
|
||||||
|
|
||||||
|
这是一种更有意义、更面向语言设计和思维方式的划分方式。一个语言可能支持多种范式。常见的范式包括:
|
||||||
|
|
||||||
|
- 过程式 / 结构式(Procedural / Structured):以顺序、条件、循环、子程序等为基本方式,比如 C、Pascal、早期的 Fortran。
|
||||||
|
- 面向对象(Object-Oriented):以对象、类、继承、封装、多态为核心,比如 Java、C++、Python(支持 OO)。
|
||||||
|
- 函数式(Functional):强调函数是“第一公民”、无副作用、不可变性、高阶函数等,比如 Haskell、Lisp、OCaml、Scala。
|
||||||
|
- 逻辑 / 规则 / 声明式(Logic / Rule / Declarative):以“写什么”而不是“怎么写”为主,比如 Prolog、SQL(某种意义上)、某些规则引擎语言。
|
||||||
|
- 反应式 / 并发 / actor 模型 / 事件驱动:面向并行、消息传递、异步流等,如 Erlang、ReactiveX、Rust 的异步特性等。
|
||||||
|
- 脚本 / 解释式 / 动态语言:通常是为快速开发、轻量任务设计,支持动态类型、运行时解释执行,如 Python、JavaScript、Ruby、Perl 等。
|
||||||
|
- 域特定语言(DSL, Domain-Specific Language):针对特定领域设计的语言,如 SQL(数据库查询语言)、正则表达式、LaTeX(文档排版语言)等。
|
||||||
|
|
||||||
|
通过范式分类,我们更关注语言在“编程思维 / 解题风格 /抽象手段”上的特征,而不仅仅是底层抽象程度。
|
||||||
|
|
||||||
|
### *(三)按 **执行方式 / 翻译方式** 划分*
|
||||||
|
|
||||||
|
这是考虑语言 / 实现怎样从源码到执行这一环节的视角:
|
||||||
|
|
||||||
|
- **编译型语言(Compiled)**:源代码编译成机器代码/可执行文件,执行时不再需要翻译步骤(比如 C、C++、Rust 等)。
|
||||||
|
- **解释型语言(Interpreted)**:源代码在运行时被逐行 / 按需解释执行,不产生独立的机器码可执行文件(经典例子有早期的 Python、Perl、Ruby、Bash 脚本等)。
|
||||||
|
- **字节码 / 虚拟机(VM)语言**:先把源码编译成一种中间字节码(与具体机器无关),然后由虚拟机解释或 JIT 编译成机器码执行。典型例子有 Java(编译成 JVM 字节码,再解释或 JIT),C#/.NET(IL 中间语言),Python 的某些实现(如 CPython 有字节码)等。
|
||||||
|
- **即插即用 / 跨编译 / 转译(Transpiler / Source-to-Source Compiler)**:直接把一种语言的源代码转译成另一种语言的源代码(通常目标语言是更接近机器的一种语言或更通用的平台语言)。例如 TypeScript 转成 JavaScript、CoffeeScript 转 JS、某些语言先转成 C 代码再编译。
|
||||||
|
- **混合执行 / JIT(Just-In-Time 编译)**:运行时动态将热点代码编译为机器码,以改善性能(典型如 Java HotSpot、V8 引擎、.NET CLR、PyPy 等)。
|
||||||
|
|
||||||
|
|
||||||
|
这个分类(编译 vs 解释 vs 虚拟机 / 字节码 / JIT / 转译)是一个非常实用的视角,因为它直接影响性能、移植性、启动时间、内存使用等。
|
||||||
|
|
||||||
|
### *(四)按 **用途 / 领域 /功能** 划分*
|
||||||
|
|
||||||
|
- **系统语言 / 底层语言**:用于操作系统、驱动、嵌入式、核内核模块等需要直接控制硬件的地方,如 C、C++、Rust(有底层能力)等。
|
||||||
|
- **应用语言 / 脚本语言**:用于写业务逻辑、桌面/移动/Web 应用、自动化脚本,如 Python、JavaScript、Ruby、PHP 等。
|
||||||
|
- **查询 / 报表 / 数据处理语言**:如 SQL、R、MATLAB、SAS 等,在数据处理、统计、分析、数值计算等领域比较常见。
|
||||||
|
- **硬件描述语言(HDL, Hardware Description Language)**:用于描述数字电路 / 硬件结构,如 Verilog, VHDL。
|
||||||
|
- **并行 / 并发 / GPU / 科学计算语言**:专门针对大规模并行运算、数值计算、科学模拟等,如 CUDA(为 GPU 编程的一个语言扩展)、OpenCL、Fortran(高性能数值计算)等。
|
||||||
|
- **逻辑 / 规则 / 知识表示语言**:用于人工智能、规则引擎、知识库建模,如 Prolog、Datalog、某些规则语言。
|
||||||
|
- **脚本 / 嵌入式 / 扩展语言**:嵌入在其它系统 / 软件中作为脚本或扩展接口使用,如 Lua(常嵌入到游戏、应用中作为脚本语言)、JavaScript(在浏览器中,甚至在服务器端作为脚本语言)等。
|
||||||
|
- **领域特定语言(DSL)**:面向某个狭义领域的语言,如正则表达式、HTML/CSS(标记/样式语言,非严格 “程序语言” 但常在编程系统中视为 DSL)、SQL、LaTeX、Shader 语言(GLSL、HLSL)、配置语言(如 YAML, JSON, TOML)等。
|
||||||
|
|
||||||
|
|
||||||
|
### *(五)按 **动态 / 静态类型**、**高级特性支持**等进一步细分*
|
||||||
|
|
||||||
|
- **静态类型语言 / 强类型 / 类型系统**:在编译时就确定变量类型,如 C, C++, Java, Rust, Haskell 等。
|
||||||
|
- **动态类型语言**:变量类型在运行时决定,如 Python, JavaScript, Ruby, Lua。
|
||||||
|
- **弱类型 / 宽松类型语言**:类型转换灵活、有隐式类型转换,如 JavaScript、PHP(在某些情形下)。
|
||||||
|
- **支持垃圾回收(GC)的语言** vs **无需垃圾回收 / 手动管理内存的语言**。
|
||||||
|
- **支持泛型 / 模板 / 元编程 / 宏 / 反射 / 元数据 / 注解 / 并发 / 异步 / 协程 / 幂等 / 组合子 / 函数式特性 / 泛函 / 模块系统 / 多态 / 高阶函数 / 依赖注入 / 领域语言集成**等。
|
||||||
|
|
||||||
|
|
||||||
|
每个维度都可以作为细化标准。现代语言往往在多个范式、多个特性之间混合或支持。例如,Python 是动态类型、支持面向对象 + 函数式、通常作为脚本语言;C# 是静态类型、支持泛型、面向对象、LINQ(函数式风格)、异步 / 并发特性;Scala 支持面向对象 + 函数式混合;Rust 支持低层控制 + 安全机制 + 并发特性等。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、为什么要有这些划分?它们有什么意义?
|
||||||
|
|
||||||
|
知道这些划分不是为了应付考试,而是理解“为什么有各种语言”,“什么时候选哪种语言比较合适”,以及“不同语言的设计思路 / 适用场景差别”。这些划分帮助我们:
|
||||||
|
|
||||||
|
1. **理解抽象层次与性能 / 控制权之间的权衡**
|
||||||
|
越接近硬件的语言,给予你更高的控制力度/性能潜力,但开发代价高;越抽象的语言,给你开发效率和可维护性,但可能在性能或细节控制上受限。
|
||||||
|
2. **选择合适工具 / 语言**
|
||||||
|
根据任务特点(高性能 / 低延迟 / 嵌入式 /算法密集 /数据处理 /脚本 glue 逻辑 /领域特定)去选择语言,而不是凭喜好随意选。
|
||||||
|
3. **理解编译器 / 解释器 /虚拟机的工作原理**
|
||||||
|
不同语言的运行方式(直接编译、解释执行、字节码 + VM、中间表示 + 优化等)差别很大,影响性能、调试、部署、移植性等方面。
|
||||||
|
4. **理解语言的演化 / 新语言设计原则**
|
||||||
|
很多现代语言就是在追求“更高抽象但又不失性能 / 安全 /可控制性 / 并行性 /可组合性 /可维护性”等折中点。通过这些分类视角,可以更清晰地看到各语言设计取舍、演变方向、优劣势。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
188
public/mengyanote/计算机科普/编程语言科普.md
Normal file
188
public/mengyanote/计算机科普/编程语言科普.md
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、目前主流编程语言有哪些
|
||||||
|
|
||||||
|
“主流”这个词有些模糊,但可以从 **使用度、社区活跃度、在业界的需求** 来衡量。以下是目前(2025 年左右)较为主流、常见、被广泛使用或热门的编程语言(或语言家族):
|
||||||
|
|
||||||
|
|语言 / 语言家族|主要应用 /特点|为什么主流 /受欢迎|
|
||||||
|
|---|---|---|
|
||||||
|
|**Python**|数据科学、机器学习、自动化脚本、Web 后端、运维脚本等|语法简洁、生态丰富、学习门槛相对低,是很多初学者首选语言|
|
||||||
|
|**JavaScript / TypeScript**|前端开发(浏览器端)、全栈开发(Node.js)、前后端整合|浏览器支持、自带执行环境,Web 开发不可或缺|
|
||||||
|
|**Java**|企业级后端、Android 应用、分布式系统、大型系统|平台无关、生态成熟、稳定性好|
|
||||||
|
|**C / C++**|操作系统、底层系统、游戏引擎、高性能计算|性能高、控制力强,是很多系统、嵌入式的基础|
|
||||||
|
|**C# / .NET**|微软生态、游戏开发(用 Unity)、Web / 桌面应用|在 Windows / 企业 /游戏开发中占有较大份额|
|
||||||
|
|**Go**|云服务、微服务、网络工具|轻量、高效、并发模型好,适合现代后端服务架构|
|
||||||
|
|**Rust**|系统级编程、安全性、高性能程序|兼顾安全与性能,正逐渐在系统编程中崛起|
|
||||||
|
|**Kotlin / Swift / Dart** 等|Kotlin 在 Android 开发、Swift 在 iOS 开发、Dart 在跨平台 Flutter 中|针对特定平台或生态的现代语言|
|
||||||
|
|**PHP / Ruby / Lua / R / MATLAB** 等|Web 开发、脚本、科学计算、嵌入脚本语言等|在特定领域(如 Web、数据处理、脚本任务)有长期用户基础|
|
||||||
|
|
||||||
|
|
||||||
|
**提示**:你不需要一次就掌握很多语言。选一种用途广、社区活跃、资料丰富的语言作为第一门就很好。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、如何学习第一门编程语言
|
||||||
|
|
||||||
|
学习编程语言其实不仅是学语法,更重要的是学“编程思维”和“解决问题的方法”。下面是一个通用的路径和建议:
|
||||||
|
|
||||||
|
1. **选一个“合适”的第一门语言**
|
||||||
|
要求:社区活跃、资料丰富、上手难度适中、你感兴趣的应用领域有支持。
|
||||||
|
很多人选择 Python、Java、JavaScript、C# 等作为第一门。
|
||||||
|
|
||||||
|
2. **基础语法 + 核心概念**
|
||||||
|
|
||||||
|
- 变量、类型、表达式
|
||||||
|
- 分支 / 循环 / 函数 / 模块
|
||||||
|
- 数据结构(列表 / 数组 / 字典 / 集合 / 栈 / 队列 / 链表)
|
||||||
|
- 输入 / 输出 / 文件操作
|
||||||
|
- 异常 /错误处理
|
||||||
|
- 类 / 对象(如果是面向对象语言的话)
|
||||||
|
|
||||||
|
3. **做小项目 / 练题**
|
||||||
|
|
||||||
|
- 用你学到的语言做一些小程序:如计算器、猜数字游戏、文本处理脚本、网页爬虫、小游戏等
|
||||||
|
- 在线编程题(如 LeetCode / HackerRank / Codeforces /国内的平台)
|
||||||
|
- 仿写别人做过的小项目
|
||||||
|
|
||||||
|
4. **理解语言常用库 /框架 /生态**
|
||||||
|
|
||||||
|
- 学会如何使用标准库
|
||||||
|
- 探索社区常用库 /包管理工具
|
||||||
|
- 如果语言用于 Web、数据分析、GUI 等方向,学习相应框架
|
||||||
|
|
||||||
|
5. **阅读、调试、源码 /开源项目学习**
|
||||||
|
|
||||||
|
- 阅读简单的开源项目代码,理解别人怎么组织项目
|
||||||
|
- 学习调试技巧(断点、日志、单步执行)
|
||||||
|
- 修改 /加功能 / 布置自己的小项目
|
||||||
|
|
||||||
|
6. **不断总结与巩固**
|
||||||
|
|
||||||
|
- 写笔记、写博客、记录你遇到的问题和解决方法
|
||||||
|
- 定期回顾基础(数据结构、算法、语言核心特性)
|
||||||
|
- 尝试用这门语言做一些实战项目
|
||||||
|
|
||||||
|
7. **进阶知识** (视情况)
|
||||||
|
|
||||||
|
- 并发 / 多线程 /异步
|
||||||
|
- 性能优化
|
||||||
|
- 设计模式 / 编程范式(例如函数式编程、响应式编程)
|
||||||
|
- 架构设计 / 模块化 /插件机制等
|
||||||
|
|
||||||
|
|
||||||
|
**心得建议**:
|
||||||
|
|
||||||
|
- **不要急于 “用很多库 / 框架”**,先把“语言本身”理解透
|
||||||
|
- **边练边思考**:做题、做项目能加深理解
|
||||||
|
- **多看源码 /别人的代码**,理解风格和习惯
|
||||||
|
- **坚持比一口吃胖重要**,每天写一点比一次写很多还好
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、编译型语言 vs 解释型语言 的区别
|
||||||
|
|
||||||
|
这两个术语在实际使用中不是绝对的分类(很多语言其实是混合或中间型的),但可以帮助理解它们的执行机制。下面是它们的主要区别、优缺点、典型语言等。
|
||||||
|
|
||||||
|
### 基本定义
|
||||||
|
|
||||||
|
- **编译型语言(Compiled Language)**
|
||||||
|
将源代码(高级语言)在运行之前用 **编译器**(compiler)转换成机器码(或某种中间码 /目标码 /可执行文件),再由操作系统 /硬件直接执行。
|
||||||
|
编译是一次性的、事前的。
|
||||||
|
典型:C、C++、Rust(直接编译为机器码) ([Veitor](https://www.veitor.net/posts/compiler-vs-interpreter/?utm_source=chatgpt.com "编译器 (Compiler)和解释器 (Interpreter) | Veitor的技术点滴"))
|
||||||
|
|
||||||
|
- **解释型语言(Interpreted Language)**
|
||||||
|
用 **解释器**(interpreter)逐行或逐块读取源代码,将其转换或解释为机器指令并执行,不一定生成整体的可执行文件。
|
||||||
|
解释是在运行(执行)时动态进行的。
|
||||||
|
典型:早期的 BASIC、Perl、Python、Ruby、PHP(虽然这些语言在现代实现中可能也做了编译 /优化) ([博客园](https://www.cnblogs.com/lemon-le/p/13840014.html?utm_source=chatgpt.com "解释器 ( interpreter ) 与 编译器 ( compiler ) 的对比 - 博客园"))
|
||||||
|
|
||||||
|
|
||||||
|
### 区别对比
|
||||||
|
|
||||||
|
|方面|编译型|解释型|
|
||||||
|
|---|---|---|
|
||||||
|
|执行时间 / 性能|编译后生成本地机器码,运行效率通常较高|每次运行时都要解释/翻译,效率通常较低(除非经过优化)|
|
||||||
|
|编译 / 执行关系|编译阶段和执行阶段分离(先编译,再执行)|通常是边解释边执行(或一边翻译一边执行)|
|
||||||
|
|错误检测|编译时可以检测出大部分语法 / 类型错误|运行过程中逐行解释,错误可能在运行时才出现|
|
||||||
|
|可移植性|编译后生成与平台相关的机器码(需针对不同平台重新编译)|源代码可以在不同平台上用相同的解释器直接运行(只要有对应解释器)|
|
||||||
|
|开发 /调试体验|编译需要时间(可能慢),但运行快|开发调试更灵活、即时反馈好|
|
||||||
|
|典型使用场景|系统程序、性能敏感程序|脚本任务、快速原型、脚本 glue 代码等|
|
||||||
|
|
||||||
|
不过在现实中很多语言 / 实现是折中的、混合的:
|
||||||
|
|
||||||
|
- 现代的 **Python** 解释器(如 CPython)会把 Python 源码先编译成字节码(bytecode),然后由虚拟机 / 解释器执行
|
||||||
|
- **Java** 是“先编译为中间字节码,再通过虚拟机执行 /解释 /优化”机制
|
||||||
|
- 现代解释器 / JIT(即时编译, Just-In-Time)技术使解释型语言在运行过程中部分编译,从而提升性能
|
||||||
|
- 有些语言可以静态编译也能解释执行
|
||||||
|
|
||||||
|
|
||||||
|
因此,“编译型 vs 解释型”更像是 “主要执行机制” 的差异,而非绝对分类。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、什么是虚拟机 (Virtual Machine) 和 解释器 (Interpreter)
|
||||||
|
|
||||||
|
这两个概念在语言实现层面是常见的组件或手段,下面分别说明:
|
||||||
|
|
||||||
|
### 解释器 (Interpreter)
|
||||||
|
|
||||||
|
- 解释器是一个软件,它接受 **源代码** 或某种中间表示(如 AST、字节码等),然后逐条解释 / 翻译 /执行这些指令。
|
||||||
|
- 解释器通常做三件事:**解析 / 词法分析 / 语法分析**(把文本转换成语法结构或中间表示),**执行 / 调度**(根据语义执行操作),**错误处理 /调试支持**
|
||||||
|
- 因为解释是运行时发生的,所以解释型语言可以很灵活(如动态类型、REPL 模式、交互式编码)
|
||||||
|
- 缺点是运行速度可能较慢,因为每次执行时都要解释和翻译
|
||||||
|
|
||||||
|
|
||||||
|
举例来说,早期 Python、Ruby、Perl 的标准实现都带一个解释器(读取 .py 或 .rb 源文件,解释执行)
|
||||||
|
|
||||||
|
### 虚拟机 (Virtual Machine, VM)
|
||||||
|
|
||||||
|
“虚拟机”这个词在编程语言实现中通常指 “语言虚拟机”(不是操作系统层面的虚拟机),即为某种语言提供一个执行环境,实现跨平台、内存管理、中间表示执行、优化等功能。
|
||||||
|
|
||||||
|
具体来说:
|
||||||
|
|
||||||
|
- 通常语言先被编译成一种与硬件无关的中间表示(比如 **字节码(bytecode)**)
|
||||||
|
- 然后在 “虚拟机” 中运行这个字节码(虚拟机负责解释、编译、管理运行时环境)
|
||||||
|
- 虚拟机可以实现垃圾回收(GC)、内存管理、运行时优化、JIT 编译等
|
||||||
|
- 语言虚拟机使得同一套字节码 /中间表示可以在不同平台上运行(只要有对应平台的虚拟机实现)
|
||||||
|
|
||||||
|
|
||||||
|
Java 的 JVM(Java 虚拟机)就是经典例子。Java 代码(.java)经 **javac** 编译为 Java 字节码(.class),然后 JVM 载入这些字节码执行(有解释器 + JIT 优化) ([Edu4Java](https://www.edu4java.com/en/concepts/compiler-interpreter-virtual-machine.html?utm_source=chatgpt.com "Compiler, interpreter and virtural machine. - edu4java.com"))
|
||||||
|
|
||||||
|
虚拟机和解释器的关系可以是:
|
||||||
|
|
||||||
|
- 虚拟机内部可以包含解释器(解释字节码)
|
||||||
|
- 虚拟机也可以包含 JIT 编译器(把热点字节码编译为本地机器码)
|
||||||
|
- 虚拟机通常还负责运行时环境管理,如内存分配、垃圾回收、线程调度、安全检查等
|
||||||
|
|
||||||
|
|
||||||
|
简单来说:**解释器是“把代码解释执行”的那个组件**;**虚拟机是提供中间执行环境 /平台抽象 /运行时服务的整体系统**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、Java 和 Python 在语言类型 / 执行机制上的区别
|
||||||
|
|
||||||
|
下面从几个维度比较 Java 和 Python,并指出它们在“语言类型 / 执行机制”上的异同。
|
||||||
|
|
||||||
|
### 语言范式 /设计定位
|
||||||
|
|
||||||
|
|特点|Java|Python|
|
||||||
|
|---|---|---|
|
||||||
|
|类型系统|静态类型(静态类型检查 + 编译期类型系统)|动态类型(运行时检查类型)|
|
||||||
|
|编程范式|面向对象为主,也支持泛型、接口、并发等|多范式(面向对象、函数式、脚本式)|
|
||||||
|
|语言定位|企业级应用、后端、中间件、Android 等|脚本 /快速开发、数据科学、自动化、Web 后端等|
|
||||||
|
|语法 / 可读性|语法较严格、结构化|语法简洁、强调可读性|
|
||||||
|
|
||||||
|
### 执行 / 编译机制
|
||||||
|
|
||||||
|
|项目|Java|Python|
|
||||||
|
|---|---|---|
|
||||||
|
|源代码 → 可执行方式|Java 源代码 `.java` 用 **javac** 编译为 **字节码**(.class)然后由 **JVM**(Java 虚拟机)加载执行(解释 / JIT 优化) ([Edu4Java](https://www.edu4java.com/en/concepts/compiler-interpreter-virtual-machine.html?utm_source=chatgpt.com "Compiler, interpreter and virtural machine. - edu4java.com"))|Python 源代码(.py)通常由解释器(如 CPython)先编译成 **字节码**(.pyc 文件或内存中)然后由 Python 虚拟机 /解释器执行字节码(或在某些实现中 JIT 优化)|
|
||||||
|
|是否纯解释或纯编译|不是纯解释 /不是纯编译,是一种“先编译为中间码 + 在虚拟机中解释 /优化”的混合模式|虽然常被称作“解释型语言”,但实际上也经过“编译(至字节码) + 在虚拟机中执行”机制|
|
||||||
|
|性能|通常比 Python 快,因 JVM 的优化、JIT、静态类型优势|性能较慢是其常见弱点,但也有 PyPy、Cython 等优化项目改善性能|
|
||||||
|
|可移植性|写一次字节码可在不同平台上通过 JVM 运行(“一次编写,到处运行”)|只要目标平台有 Python 解释器即可运行(源代码级别可移植)|
|
||||||
|
|应用领域|企业后端、分布式系统、大规模服务、Android 应用|脚本、自动化、数据分析 /科学计算 /机器学习 / Web 服务|
|
||||||
|
|
||||||
|
综上,**Java 属于“编译 + 虚拟机” 类型的语言**,而 **Python 虽然经常被称为“解释型”语言**,但其实际实现也带“编译(到字节码) + 虚拟机执行 /解释器”机制。两者在类型系统、执行效率、应用定位、生态等方面也有明显区别。
|
||||||
|
|
||||||
|
---
|
||||||
135
public/mengyanote/计算机科普/网络协议科普.md
Normal file
135
public/mengyanote/计算机科普/网络协议科普.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 网络层次与协议模型(简要背景)
|
||||||
|
|
||||||
|
在讲这些协议之前,先说一下它们在网络协议栈中的“位置”究竟在哪儿,会更容易理解它们的作用。现代网络通信一般参考 **TCP/IP 协议族** 或者 **OSI 七层模型**。
|
||||||
|
|
||||||
|
- 在 TCP/IP 模型里,经常把协议分为四层:**网络接口层**、**网际层(Internet 层)**、**传输层(Transport 层)**、**应用层(Application 层)**。
|
||||||
|
- 大部分协议(FTP, SSH, HTTP, DNS, SMTP 等)都属于**应用层协议**,也就是直接为应用(比如浏览器、文件传输、邮件系统)提供服务的协议。
|
||||||
|
- 在应用层之下,还有传输层(常见的 TCP、UDP)为它们提供可靠或不可靠的数据传输服务;再往下是网络层(IP)负责寻址与路由等。
|
||||||
|
|
||||||
|
所以,当我们说某个协议是“在 TCP 之上”或“基于 TCP 的”时,就是说这个协议使用 TCP 来做底层的数据传输。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## 各协议详解
|
||||||
|
|
||||||
|
### FTP — 文件传输协议 (File Transfer Protocol)
|
||||||
|
|
||||||
|
- **作用 / 用途**:用于在客户端和服务器之间上传、下载和管理文件。
|
||||||
|
- **层级 / 依赖**:应用层协议,通常跑在 TCP 之上。
|
||||||
|
- **工作机制**:FTP 在通信时,通常会建立两条 TCP 连接:
|
||||||
|
1. **控制连接**(control connection):用来发送命令(例如登录、切换目录、发出“下载”命令等)
|
||||||
|
2. **数据连接**(data connection):用来真正传输文件数据或目录列表
|
||||||
|
|
||||||
|
- **优点 / 缺点**:
|
||||||
|
- 优点:功能全面(支持各种文件操作、目录操作、权限管理等)
|
||||||
|
- 缺点:安全性差——用户名、密码、文件内容都以明文形式传输,容易被中间人嗅探拦截 ([维基百科](https://en.wikipedia.org/wiki/File_Transfer_Protocol?utm_source=chatgpt.com "File Transfer Protocol"))
|
||||||
|
- 对防火墙和 NAT 支持不好,因为数据连接可能由服务器发起(主动模式时)
|
||||||
|
|
||||||
|
- **改进 / 替代方案**:
|
||||||
|
- **FTPS**:在 FTP 上加上 SSL/TLS 加密
|
||||||
|
- **SFTP**(SSH File Transfer Protocol):通过 SSH 隧道安全地传输文件(下面会讲 SSH)
|
||||||
|
- **典型端口**:21 用于控制连接,20 有时用于数据连接(在主动模式下) ([维基百科](https://en.wikipedia.org/wiki/File_Transfer_Protocol?utm_source=chatgpt.com "File Transfer Protocol"))
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SSH — 安全外壳协议 (Secure Shell)
|
||||||
|
|
||||||
|
- **作用 / 用途**:提供加密的远程登录、命令执行、以及通过隧道转发端口或做文件传输(例如通过 SFTP、SCP)等功能。
|
||||||
|
- **层级 / 依赖**:应用层协议,但其内部本身也包含加密、认证、密钥协商等机制。通常运行在 TCP 之上(默认端口 22)。 ([runoob.com](https://www.runoob.com/np/secure-shell.html?utm_source=chatgpt.com "SSH 协议 - 菜鸟教程"))
|
||||||
|
- **工作机制 / 特性**:
|
||||||
|
1. **连接建立 & 协商**:客户端连接到服务器的 22 端口,双方协商版本、加密算法、密钥交换方法等
|
||||||
|
2. **认证阶段**:客户端使用密码或公钥等方式向服务器认证
|
||||||
|
3. **会话 / 通道管理**:认证成功后,在已建立的加密通道上可以开多个逻辑通道(通道可用于 shell、执行命令、端口转发等) ([jianshu.com](https://www.jianshu.com/p/8e5b7aea52b5?utm_source=chatgpt.com "SSH 协议原理、组成、认证方式和过程 - 简书"))
|
||||||
|
4. **端口转发 / 隧道**:SSH 支持三类转发:本地端口转发(local forwarding)、远端端口转发(remote forwarding)、动态转发(相当于 SOCKS 代理) ([知乎专栏](https://zhuanlan.zhihu.com/p/235610836?utm_source=chatgpt.com "深入了解SSH - 知乎"))
|
||||||
|
- **优点 / 缺点**:
|
||||||
|
- 优点:安全(加密通信、避免明文传输、中间人攻击风险较低)、功能强大
|
||||||
|
- 缺点:稍微复杂,尤其是对密钥管理、权限管理需要注意
|
||||||
|
- **典型端口**:22
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SFTP — SSH 文件传输协议 (SSH File Transfer Protocol)
|
||||||
|
|
||||||
|
- 这是一个 “文件传输” 协议,但它是 **运行在 SSH 之上** 的安全文件传输协议
|
||||||
|
- 它利用 SSH 的加密通道来安全地上传/下载文件、管理文件权限等
|
||||||
|
- 因为它建立在 SSH 上,所以本身继承了 SSH 的安全性(加密、认证)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### HTTP / HTTPS — 超文本传输协议 / 安全版
|
||||||
|
|
||||||
|
- **HTTP(HyperText Transfer Protocol)**:
|
||||||
|
- 作用 / 用途:Web 浏览器和 Web 服务器之间通信的基本协议,用来获取网页、图片、脚本、API 接口数据等
|
||||||
|
- 层级 / 依赖:应用层协议,典型地运行在 TCP 之上
|
||||||
|
- 主要机制:客户端发送请求(包含方法如 GET、POST、PUT、DELETE 等、路径、请求头、请求体等),服务器响应(状态行、响应头、响应体)
|
||||||
|
- 特性:无状态(每个请求是独立的,不自动保留之前的状态)
|
||||||
|
- 存在的问题:明文传输,容易被中间人窃听或篡改
|
||||||
|
- **HTTPS**:
|
||||||
|
- HTTPS = HTTP + SSL/TLS,加上了加密和身份验证
|
||||||
|
- 在 HTTP 发送真正数据之前,会先通过 TLS/SSL 做握手协商密钥、证书验证等,从而使后续通信内容加密、完整性保护
|
||||||
|
- 特性:提供通信的机密性、完整性和服务器身份验证(有时也支持客户端证书验证)
|
||||||
|
- 在 Web 安全中几乎必须使用 HTTPS 而不是 HTTP
|
||||||
|
- 版本演进:HTTP/1.1 → HTTP/2 → HTTP/3(HTTP/3 基于 QUIC,使用 UDP 做传输层) ([CSDN博客](https://blog.csdn.net/weixin_73144915/article/details/147348522?utm_source=chatgpt.com "TCP/IP、UDP、HTTP、HTTPS、WebSocket 一文讲解 ..."))
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### WebSocket
|
||||||
|
|
||||||
|
- **作用 / 用途**:在浏览器和服务器之间建立一个“长连接”(persistent connection),可以做双向实时通信
|
||||||
|
- **为什么需要 WebSocket**:HTTP 本质上是请求-响应模式,是客户端发起请求才有响应;如果你想让服务器主动推送消息给客户端(如即时聊天、实时更新),就非常不方便。WebSocket 正是为这个场景设计的。
|
||||||
|
- **工作机制 / 特性**:
|
||||||
|
1. 首先通过 HTTP 发起一个“升级(Upgrade)”请求,头部中带上 `Upgrade: websocket`、`Connection: Upgrade`、`Sec-WebSocket-Key` 等字段
|
||||||
|
2. 服务端如果接受这个升级请求,就返回响应确认,将连接从 HTTP 协议“切换/升级”到 WebSocket 协议
|
||||||
|
3. 升级成功后,双方可以在这个 TCP 连接上以 WebSocket 帧(frame)的形式进行双向通信,浏览器可以发送消息给服务器,服务器也可以主动推送消息给客户端
|
||||||
|
4. 支持文本帧、二进制帧、控制帧(关闭、ping/pong 等) ([腾讯云](https://cloud.tencent.com/developer/article/1887095?utm_source=chatgpt.com "万字长文,一篇吃透WebSocket:概念、原理、易错常识 ..."))
|
||||||
|
- **优点 / 缺点**:
|
||||||
|
- 优点:真正的双向通信、低延迟、连接保持,不需要每次都重新握手
|
||||||
|
- 缺点:如果服务器端不善于处理大量长连接或连接管理不佳,可能资源消耗较高
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### WebDAV — Web 分布式创作与版本控制协议 (Web Distributed Authoring and Versioning)
|
||||||
|
|
||||||
|
- **作用 / 用途**:WebDAV 是一个扩展 HTTP 的协议,使得客户端可以远程进行文件管理(创建、删除、修改、锁定、属性操作、版本控制等),在 Web 服务器上像操作文件系统那样操作文档 / 资源
|
||||||
|
- **层级 / 依赖**:是 HTTP 的扩展协议,运行在 HTTP / HTTPS 之上
|
||||||
|
- **应用场景**:常用于云盘、版本控制、远程文档编辑协作等
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Telnet
|
||||||
|
|
||||||
|
- **作用 / 用途**:远程登录协议,允许用户在远程主机上启动交互式 shell 或命令行界面
|
||||||
|
- **层级 / 依赖**:应用层协议,通常基于 TCP
|
||||||
|
- **问题 / 缺陷**:**不加密**,所有命令和数据(包括用户名、密码)都是明文传输,非常容易被中间人截获
|
||||||
|
- **历史 / 使用**:在早期广泛使用,但在现代多数场景下被 SSH 取代了
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SMTP — 简单邮件传输协议 (Simple Mail Transfer Protocol)
|
||||||
|
|
||||||
|
- **作用 / 用途**:用于在邮件服务器之间传递邮件,以及客户端向邮件服务器发送邮件
|
||||||
|
- **层级 / 依赖**:应用层协议,通常运行在 TCP 上
|
||||||
|
- **机制**:客户端或发送服务器将邮件发给目标邮件服务器;邮件服务器之间通过 SMTP 协议转发邮件至最终目的地
|
||||||
|
- **常见通信**:可与其他邮件协议(如 POP3、IMAP)配合使用,负责“发送”而不是“接收/读取”的功能
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DNS — 域名系统 (Domain Name System)
|
||||||
|
|
||||||
|
- **作用 / 用途**:把人类易记的域名(例如 `www.example.com`)转换为机器能识别的 IP 地址(例如 `93.184.216.34`)
|
||||||
|
- **层级 / 依赖**:应用层协议,通常运行在 UDP 上(小查询)或者 TCP(大响应或区域传输时)
|
||||||
|
- **工作机制**:
|
||||||
|
1. 客户端向本地 DNS 服务器发起查询请求
|
||||||
|
2. 如果本地 DNS 服务器没有缓存,会向上级 DNS 服务器、根服务器、顶级域名服务器、权威服务器逐层查询
|
||||||
|
3. 最终得到域名对应的 IP 地址,缓存在本地 DNS 服务器以便后续查询快速响应
|
||||||
|
- **扩展 / 安全**:DNSSEC(DNS Security Extensions)用于防止 DNS 缓存中毒、篡改等安全问题
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
121
public/mengyanote/计算机网络/HTTP常见状态码.md
Normal file
121
public/mengyanote/计算机网络/HTTP常见状态码.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTTP 状态码详解
|
||||||
|
|
||||||
|
HTTP 状态码分为 **5 大类**,每个类别代表不同的响应类型。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1xx:信息响应
|
||||||
|
|
||||||
|
表示请求已接收,正在继续处理。
|
||||||
|
|
||||||
|
- **100 Continue**:客户端应继续请求(常用于大文件上传前的预检)。
|
||||||
|
- **101 Switching Protocols**:服务器同意切换协议(如 WebSocket)。
|
||||||
|
- **102 Processing (WebDAV)**:服务器正在处理请求,还未完成。
|
||||||
|
- **103 Early Hints**:预先返回一些响应头,提示客户端(如提前加载资源)。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2xx:成功响应
|
||||||
|
|
||||||
|
表示请求已成功被服务器接收、理解和处理。
|
||||||
|
|
||||||
|
- **200 OK**:请求成功,返回所需资源。
|
||||||
|
- **201 Created**:请求成功并创建了新资源。
|
||||||
|
- **202 Accepted**:请求已接受,但尚未处理完成。
|
||||||
|
- **203 Non-Authoritative Information**:返回的元信息不是来自源服务器。
|
||||||
|
- **204 No Content**:请求成功,但没有返回内容。
|
||||||
|
- **205 Reset Content**:请求成功,要求客户端重置视图(如表单清空)。
|
||||||
|
- **206 Partial Content**:返回部分内容(用于断点续传/分块下载)。
|
||||||
|
- **207 Multi-Status (WebDAV)**:返回多个状态信息。
|
||||||
|
- **208 Already Reported (WebDAV)**:避免重复报告资源。
|
||||||
|
- **226 IM Used**:服务器完成请求,返回应用了某些实例操作的结果。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3xx:重定向
|
||||||
|
|
||||||
|
表示需要进一步操作以完成请求。
|
||||||
|
|
||||||
|
- **300 Multiple Choices**:有多个可选资源。
|
||||||
|
- **301 Moved Permanently**:资源永久重定向到新位置。
|
||||||
|
- **302 Found**:资源临时重定向(常见于登录跳转)。
|
||||||
|
- **303 See Other**:请求的响应可在另一个 URL 获取(常用于 POST → GET)。
|
||||||
|
- **304 Not Modified**:资源未修改,客户端可使用缓存。
|
||||||
|
- **305 Use Proxy**(已废弃):要求通过代理访问。
|
||||||
|
- **307 Temporary Redirect**:临时重定向,请求方法不变。
|
||||||
|
- **308 Permanent Redirect**:永久重定向,请求方法不变。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4xx:客户端错误
|
||||||
|
|
||||||
|
表示请求存在错误,客户端需要修改。
|
||||||
|
|
||||||
|
- **400 Bad Request**:请求无效或语法错误。
|
||||||
|
- **401 Unauthorized**:未授权,需要身份验证。
|
||||||
|
- **402 Payment Required**(保留):最初为数字支付设计,现少用。
|
||||||
|
- **403 Forbidden**:服务器理解请求,但拒绝执行。
|
||||||
|
- **404 Not Found**:请求的资源不存在。
|
||||||
|
- **405 Method Not Allowed**:请求方法不被允许。
|
||||||
|
- **406 Not Acceptable**:请求的资源不满足客户端的 Accept 条件。
|
||||||
|
- **407 Proxy Authentication Required**:需要代理身份验证。
|
||||||
|
- **408 Request Timeout**:请求超时。
|
||||||
|
- **409 Conflict**:请求冲突(如资源版本冲突)。
|
||||||
|
- **410 Gone**:资源永久删除。
|
||||||
|
- **411 Length Required**:需要 Content-Length 头。
|
||||||
|
- **412 Precondition Failed**:请求头中的前提条件失败。
|
||||||
|
- **413 Payload Too Large**:请求体过大。
|
||||||
|
- **414 URI Too Long**:请求的 URI 过长。
|
||||||
|
- **415 Unsupported Media Type**:不支持的媒体类型。
|
||||||
|
- **416 Range Not Satisfiable**:请求的范围无效。
|
||||||
|
- **417 Expectation Failed**:Expect 头字段无法满足。
|
||||||
|
- **418 I'm a teapot**(愚人节彩蛋):服务器拒绝煮咖啡。
|
||||||
|
- **421 Misdirected Request**:请求发往错误的服务器。
|
||||||
|
- **422 Unprocessable Entity (WebDAV)**:语义错误,无法处理。
|
||||||
|
- **423 Locked (WebDAV)**:资源被锁定。
|
||||||
|
- **424 Failed Dependency (WebDAV)**:依赖的请求失败。
|
||||||
|
- **425 Too Early**:服务器不愿意处理过早的请求。
|
||||||
|
- **426 Upgrade Required**:需要升级协议(如切换到 TLS/1.3)。
|
||||||
|
- **428 Precondition Required**:需要先决条件。
|
||||||
|
- **429 Too Many Requests**:请求过多(限流)。
|
||||||
|
- **431 Request Header Fields Too Large**:请求头太大。
|
||||||
|
- **451 Unavailable For Legal Reasons**:因法律原因不可用(如审查)。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5xx:服务器错误
|
||||||
|
|
||||||
|
表示服务器在处理请求时发生错误。
|
||||||
|
|
||||||
|
- **500 Internal Server Error**:服务器内部错误。
|
||||||
|
- **501 Not Implemented**:服务器不支持请求方法。
|
||||||
|
- **502 Bad Gateway**:网关错误(上游服务器无效响应)。
|
||||||
|
- **503 Service Unavailable**:服务器不可用(超载/维护)。
|
||||||
|
- **504 Gateway Timeout**:网关超时。
|
||||||
|
- **505 HTTP Version Not Supported**:不支持的 HTTP 版本。
|
||||||
|
- **506 Variant Also Negotiates**:内容协商循环错误。
|
||||||
|
- **507 Insufficient Storage (WebDAV)**:存储空间不足。
|
||||||
|
- **508 Loop Detected (WebDAV)**:检测到无限循环。
|
||||||
|
- **510 Not Extended**:请求未满足扩展策略。
|
||||||
|
- **511 Network Authentication Required**:需要网络认证(如 Wi-Fi 登录页)。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 总结
|
||||||
|
|
||||||
|
- **1xx**:信息 → 请求处理中。
|
||||||
|
- **2xx**:成功 → 请求已完成。
|
||||||
|
- **3xx**:重定向 → 需要进一步操作。
|
||||||
|
- **4xx**:客户端错误 → 请求有问题。
|
||||||
|
- **5xx**:服务器错误 → 服务器处理失败。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
156
public/mengyanote/计算机网络/HTTP版本协议对比区别.md
Normal file
156
public/mengyanote/计算机网络/HTTP版本协议对比区别.md
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTTP 协议版本对比总结
|
||||||
|
|
||||||
|
## 一、HTTP/1.1
|
||||||
|
|
||||||
|
> 发布于 1997 年,是目前仍然广泛使用的版本。
|
||||||
|
|
||||||
|
### 特点
|
||||||
|
|
||||||
|
- **长连接(Keep-Alive)**
|
||||||
|
|
||||||
|
- 支持持久连接,多个请求可复用一个 TCP 连接,避免频繁握手。
|
||||||
|
|
||||||
|
- **管道化(Pipeline)**
|
||||||
|
|
||||||
|
- 可以在一个 TCP 连接上同时发送多个请求,但**响应必须按顺序返回** → 存在 **队头阻塞(Head-of-Line Blocking)**。
|
||||||
|
|
||||||
|
- **明文传输**
|
||||||
|
|
||||||
|
- 默认基于 TCP,数据未加密(可结合 TLS 实现 HTTPS)。
|
||||||
|
|
||||||
|
- **请求/响应模型**
|
||||||
|
|
||||||
|
- 一次请求对应一次响应,请求头和响应头通常冗余。
|
||||||
|
|
||||||
|
|
||||||
|
### 功能/不足
|
||||||
|
|
||||||
|
- 每个请求都会带上完整的 Header,冗余大。
|
||||||
|
|
||||||
|
- 并发能力有限,通常需要开启多个 TCP 连接提升性能。
|
||||||
|
|
||||||
|
- 队头阻塞问题严重。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、HTTP/2
|
||||||
|
|
||||||
|
> 发布于 2015 年,目标是解决 HTTP/1.1 的性能瓶颈。
|
||||||
|
|
||||||
|
### 特点
|
||||||
|
|
||||||
|
- **二进制分帧(Binary Framing)**
|
||||||
|
|
||||||
|
- 传输不再是文本,而是二进制帧,效率更高。
|
||||||
|
|
||||||
|
- **多路复用(Multiplexing)**
|
||||||
|
|
||||||
|
- 同一个 TCP 连接中可同时传输多个流,避免队头阻塞(但仍受 TCP 的 HOLB 影响)。
|
||||||
|
|
||||||
|
- **首部压缩(HPACK)**
|
||||||
|
|
||||||
|
- 通过动态表和静态表压缩请求/响应头,大幅减少冗余数据。
|
||||||
|
|
||||||
|
- **服务器推送(Server Push)**
|
||||||
|
|
||||||
|
- 服务端可主动推送资源,减少延迟(但实际应用中使用较少)。
|
||||||
|
|
||||||
|
- **优先级(Priority)**
|
||||||
|
|
||||||
|
- 支持请求优先级,优化资源调度。
|
||||||
|
|
||||||
|
|
||||||
|
### 功能/不足
|
||||||
|
|
||||||
|
- 显著提升带宽利用率和传输效率。
|
||||||
|
|
||||||
|
- 依然基于 TCP,**若 TCP 丢包,会阻塞整个连接**(HOLB 依旧存在)。
|
||||||
|
|
||||||
|
- 实现复杂度高。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、HTTP/3
|
||||||
|
|
||||||
|
> 基于 **QUIC(UDP 之上的新传输层协议)** 的 HTTP 新版本,正在逐渐普及。
|
||||||
|
|
||||||
|
### 特点
|
||||||
|
|
||||||
|
- **基于 QUIC 协议(UDP)**
|
||||||
|
|
||||||
|
- 避免了 TCP 的握手延迟和队头阻塞问题。
|
||||||
|
|
||||||
|
- **内置加密(TLS 1.3)**
|
||||||
|
|
||||||
|
- 加密是协议默认部分,不再是扩展。
|
||||||
|
|
||||||
|
- **0-RTT 连接建立**
|
||||||
|
|
||||||
|
- 支持快速建立连接,降低延迟。
|
||||||
|
|
||||||
|
- **多路复用**
|
||||||
|
|
||||||
|
- 流之间独立,单个流丢包不会阻塞其他流,彻底解决队头阻塞。
|
||||||
|
|
||||||
|
- **更好的移动端体验**
|
||||||
|
|
||||||
|
- IP/网络切换时(如 Wi-Fi → 4G),连接可快速恢复,不必像 TCP 那样重新握手。
|
||||||
|
|
||||||
|
|
||||||
|
### 功能/不足
|
||||||
|
|
||||||
|
- 传输性能和用户体验更佳,尤其适合移动网络。
|
||||||
|
|
||||||
|
- 部署复杂度高,需要操作系统、浏览器、服务端的全面支持。
|
||||||
|
|
||||||
|
- UDP 在部分网络环境下可能受限。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTTP 版本对比表
|
||||||
|
|
||||||
|
|特性|HTTP/1.1|HTTP/2|HTTP/3|
|
||||||
|
|---|---|---|---|
|
||||||
|
|**传输协议**|TCP|TCP|QUIC(基于 UDP)|
|
||||||
|
|**连接方式**|长连接(Keep-Alive)|单连接多路复用|单连接多路复用|
|
||||||
|
|**队头阻塞**|严重|缓解但仍存在(TCP 层)|彻底解决(流级别独立)|
|
||||||
|
|**数据格式**|文本|二进制分帧|二进制分帧|
|
||||||
|
|**头部压缩**|无|HPACK|QPACK(HPACK 的改进版)|
|
||||||
|
|**加密**|可选(HTTPS)|强制 TLS(大多数实现)|内置 TLS 1.3(强制)|
|
||||||
|
|**性能优化**|需多连接并发|多路复用、服务器推送、头部压缩|多路复用、快速握手、移动友好|
|
||||||
|
|**适用场景**|基础网络通信|现代 Web,大流量网站|移动端、大规模应用、低延迟场景|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
✅ **总结**
|
||||||
|
|
||||||
|
- **HTTP/1.1**:简单可靠,但存在性能瓶颈(队头阻塞、冗余开销)。
|
||||||
|
|
||||||
|
- **HTTP/2**:提升性能,多路复用、头部压缩,但依然受 TCP 限制。
|
||||||
|
|
||||||
|
- **HTTP/3**:基于 QUIC,解决 TCP 根本问题,面向未来互联网,特别适合移动网络。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## HTTP/1.1
|
||||||
|
|
||||||
|
> 定义了最核心、最常见的请求方法,是现代 Web 的基础。
|
||||||
|
|
||||||
|
**支持的方法:**
|
||||||
|
- **GET**:获取资源。
|
||||||
|
- **POST**:向服务器提交数据。
|
||||||
|
- **HEAD**:获取响应头,不返回实体内容。
|
||||||
|
- **PUT**:替换指定资源。
|
||||||
|
- **DELETE**:删除指定资源。
|
||||||
|
- **OPTIONS**:查询服务器支持的通信选项。
|
||||||
|
- **TRACE**:回显请求内容(调试用,实际较少使用)。
|
||||||
|
- **CONNECT**:建立隧道(常用于 HTTPS 代理)。
|
||||||
|
👉 **特点**:HTTP/1.1 是第一个全面规范化这些方法的版本。
|
||||||
43
public/mengyanote/计算机网络/TCP的三次握手四次握手总结.md
Normal file
43
public/mengyanote/计算机网络/TCP的三次握手四次握手总结.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# 🌐 TCP 连接与断开总结
|
||||||
|
|
||||||
|
## 🔗 TCP 连接建立(三次握手)
|
||||||
|
1. **Client → Server**:发送 `SYN`(请求建立连接)。
|
||||||
|
2. **Server → Client**:回复 `SYN + ACK`(同意并确认请求),并分配资源。
|
||||||
|
3. **Client → Server**:再发送 `ACK`(确认收到),也分配资源。
|
||||||
|
|
||||||
|
✅ **完成三次握手,连接建立成功。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 TCP 连接断开(四次挥手)
|
||||||
|
1. **Client → Server**:发送 `FIN`(我没有数据要发了)。
|
||||||
|
2. **Server → Client**:回复 `ACK`(收到请求,但可能还有数据要发),此时 Client 进入 `FIN_WAIT` 状态。
|
||||||
|
3. **Server → Client**:当数据发送完成,发送 `FIN`(我也准备好关闭了)。
|
||||||
|
4. **Client → Server**:回复 `ACK`,并进入 `TIME_WAIT` 状态,等待 2MSL,确保 Server 收到确认。
|
||||||
|
|
||||||
|
✅ **完成四次挥手,连接安全关闭。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ 为什么要三次握手?
|
||||||
|
- **两次握手的风险**:若请求报文滞留在网络中,Server 可能会收到多次请求,建立多个无效连接,造成资源浪费。
|
||||||
|
- **三次握手的好处**:避免 **重复连接** 的问题,确保 **双方通信能力正常**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ 为什么要四次挥手?
|
||||||
|
- 关闭连接需要 **双向确认**:
|
||||||
|
- Client 不再发送数据,但 **Server 可能还有数据要发**。
|
||||||
|
- 所以必须分为两步:
|
||||||
|
- **Client 先关闭发送通道**。
|
||||||
|
- **Server 再关闭自己的发送通道**。
|
||||||
|
- 保证 **双方通信的完整性**,不会丢数据。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📌 使用 TCP 的常见协议
|
||||||
|
- 📂 **FTP**(文件传输协议)
|
||||||
|
- 🖥️ **Telnet**(远程登录协议)
|
||||||
|
- 📧 **SMTP**(简单邮件传输协议)
|
||||||
|
- 📩 **POP3**(接收邮件协议)
|
||||||
|
- 🌍 **HTTP/HTTPS**(超文本传输协议)
|
||||||
@@ -1,11 +1,150 @@
|
|||||||
著名的OSI/RM模型(Open System Interconnection/Reference Model)。它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:
|
|
||||||
物理层(Physics Layer)、
|
|
||||||
数据链路层(Data Link Layer)、
|
|
||||||
网络层(Network Layer)、
|
|
||||||
传输层(Transport Layer)、
|
|
||||||
会话层(Session Layer)、
|
|
||||||
表示层(Presentation Layer)、
|
|
||||||
应用层(Application Layer)。
|
|
||||||
其中第四层完成数据传送服务,上面三层面向用户。
|
|
||||||
|
|
||||||
除了标准的OSI七层模型以外,常见的网络层次划分还有TCP/IP四层协议以及TCP/IP五层协议
|
---
|
||||||
|
|
||||||
|
# OSI 七层模型
|
||||||
|
|
||||||
|
OSI(Open Systems Interconnection)模型是一个抽象的分层网络通信模型,将网络通信划分为 **7 层**,从下到上分别是:
|
||||||
|
|
||||||
|
## 1. 物理层(Physical Layer)
|
||||||
|
|
||||||
|
- **功能**:负责比特流的传输,定义接口、传输媒介、电气特性。
|
||||||
|
|
||||||
|
- **数据单位**:比特(Bit)
|
||||||
|
|
||||||
|
- **设备**:网线、光纤、中继器、集线器、调制解调器
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 数据链路层(Data Link Layer)
|
||||||
|
|
||||||
|
- **功能**:将比特组织成帧,负责点对点传输、差错检测和纠正。
|
||||||
|
|
||||||
|
- **数据单位**:帧(Frame)
|
||||||
|
|
||||||
|
- **设备**:交换机、网卡
|
||||||
|
|
||||||
|
- **协议**:Ethernet(以太网)、PPP、HDLC
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 网络层(Network Layer)
|
||||||
|
|
||||||
|
- **功能**:负责寻址和路径选择,确保数据从源端到达目的端。
|
||||||
|
|
||||||
|
- **数据单位**:包(Packet)
|
||||||
|
|
||||||
|
- **设备**:路由器
|
||||||
|
|
||||||
|
- **协议**:IP、ICMP、ARP、RIP、OSPF
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 传输层(Transport Layer)
|
||||||
|
|
||||||
|
- **功能**:提供端到端的传输服务,保证数据完整性和可靠性。
|
||||||
|
|
||||||
|
- **数据单位**:段(Segment,TCP)或数据报(Datagram,UDP)
|
||||||
|
|
||||||
|
- **协议**:TCP、UDP
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 会话层(Session Layer)
|
||||||
|
|
||||||
|
- **功能**:管理会话,建立、维护、终止通信会话。
|
||||||
|
|
||||||
|
- **常见应用**:RPC、NetBIOS
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 表示层(Presentation Layer)
|
||||||
|
|
||||||
|
- **功能**:数据表示、编码、加密、压缩。
|
||||||
|
|
||||||
|
- **例子**:SSL/TLS、JPEG、MPEG、ASCII、EBCDIC
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 应用层(Application Layer)
|
||||||
|
|
||||||
|
- **功能**:直接为用户提供服务和接口。
|
||||||
|
|
||||||
|
- **协议**:HTTP、FTP、SMTP、DNS、Telnet
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# TCP/IP 模型
|
||||||
|
|
||||||
|
TCP/IP 模型是互联网的基础架构,分为 **4 层**(有时也称 5 层):
|
||||||
|
|
||||||
|
## 1. 网络接口层(Network Access Layer)
|
||||||
|
|
||||||
|
- **对应 OSI 的物理层 + 数据链路层**
|
||||||
|
|
||||||
|
- 处理硬件接口、数据帧传输。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 网络层(Internet Layer)
|
||||||
|
|
||||||
|
- **对应 OSI 的网络层**
|
||||||
|
|
||||||
|
- 负责寻址与路由。
|
||||||
|
|
||||||
|
- **协议**:IP、ICMP、ARP、IGMP
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 传输层(Transport Layer)
|
||||||
|
|
||||||
|
- **对应 OSI 的传输层**
|
||||||
|
|
||||||
|
- 端到端通信、数据可靠传输。
|
||||||
|
|
||||||
|
- **协议**:TCP、UDP
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 应用层(Application Layer)
|
||||||
|
|
||||||
|
- **对应 OSI 的会话层、表示层、应用层**
|
||||||
|
|
||||||
|
- 提供用户应用服务。
|
||||||
|
|
||||||
|
- **协议**:HTTP、FTP、SMTP、DNS、SSH
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# OSI 与 TCP/IP 对比
|
||||||
|
|
||||||
|
|**OSI 七层模型**|**TCP/IP 模型**|**功能说明**|
|
||||||
|
|---|---|---|
|
||||||
|
|应用层、表示层、会话层|应用层|为应用程序提供服务(HTTP/FTP/DNS 等)|
|
||||||
|
|传输层|传输层|提供端到端的可靠传输(TCP/UDP)|
|
||||||
|
|网络层|网络层|提供寻址与路由(IP/ICMP)|
|
||||||
|
|数据链路层、物理层|网络接口层|提供底层数据传输与硬件接口|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
✅ **总结**
|
||||||
|
|
||||||
|
- **OSI 模型** 是理论模型,更细分,利于学习和理解。
|
||||||
|
|
||||||
|
- **TCP/IP 模型** 更贴近实际应用,是互联网的主流实现。
|
||||||
|
|
||||||
|
- 二者的核心思想都是 **分层、模块化、互相独立**,便于标准化和实现。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|||||||
97
src/App.css
97
src/App.css
@@ -1,38 +1,62 @@
|
|||||||
|
/* ========================================
|
||||||
|
主应用样式文件 (App.css)
|
||||||
|
用途:定义全局主题变量、应用布局和响应式设计
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* CSS 自定义属性 (主题变量) */
|
||||||
:root {
|
:root {
|
||||||
--color-bg: #f5f7fb;
|
/* 颜色系统 - 定义整个应用的色彩主题 */
|
||||||
--color-surface: #ffffff;
|
--color-bg: #f5f7fb; /* 主背景色 - 浅蓝灰色 */
|
||||||
--color-surface-alt: #f1f4fa;
|
--color-surface: #ffffff; /* 表面背景色 - 纯白色 */
|
||||||
--color-border: #d8deed;
|
--color-surface-alt: #f1f4fa; /* 替代表面色 - 浅灰蓝色 */
|
||||||
--color-text: #1f2a44;
|
--color-border: #d8deed; /* 边框颜色 - 浅灰色 */
|
||||||
--color-muted: #6f7b92;
|
--color-text: #1f2a44; /* 主文本颜色 - 深蓝灰色 */
|
||||||
--color-accent: #7da7f2;
|
--color-muted: #6f7b92; /* 次要文本颜色 - 中灰色 */
|
||||||
--color-accent-soft: rgba(125, 167, 242, 0.12);
|
--color-accent: #7da7f2; /* 强调色 - 蓝色 */
|
||||||
--color-danger: #d6455d;
|
--color-accent-soft: rgba(125, 167, 242, 0.12); /* 柔和强调色 - 半透明蓝色 */
|
||||||
--sidebar-width: clamp(250px, 20vw, 320px);
|
--color-danger: #d6455d; /* 危险/错误色 - 红色 */
|
||||||
--sidebar-width-mobile: clamp(250px, 35vw, 300px);
|
|
||||||
--shadow-soft: 0 20px 45px rgba(86, 105, 141, 0.15);
|
/* 布局尺寸 - 定义组件的尺寸规范 */
|
||||||
--radius-lg: 22px;
|
--sidebar-width: clamp(250px, 20vw, 320px); /* 桌面端侧边栏宽度 - 响应式 */
|
||||||
|
--sidebar-width-mobile: clamp(250px, 35vw, 300px); /* 移动端侧边栏宽度 - 响应式 */
|
||||||
|
|
||||||
|
/* 视觉效果 - 定义阴影和圆角等视觉元素 */
|
||||||
|
--shadow-soft: 0 20px 45px rgba(86, 105, 141, 0.15); /* 柔和阴影效果 */
|
||||||
|
--radius-lg: 22px; /* 大圆角半径 */
|
||||||
|
|
||||||
|
/* 字体系统 - 定义字体族 */
|
||||||
--font-family-base: 'Inter', 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
--font-family-base: 'Inter', 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
全局样式重置
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 盒模型重置 - 确保所有元素使用 border-box */
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
页面基础布局
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* HTML 和 Body 基础样式 */
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
/* 渐变背景 - 多色彩渐变营造视觉层次 */
|
||||||
background: linear-gradient(135deg, #dfe9f3 0%, #f2f0ff 25%, #fde6f4 50%, #e3f6ff 75%, #f4fff8 100%);
|
background: linear-gradient(135deg, #dfe9f3 0%, #f2f0ff 25%, #fde6f4 50%, #e3f6ff 75%, #f4fff8 100%);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-family: var(--font-family-base);
|
font-family: var(--font-family-base);
|
||||||
overflow-x: hidden;
|
overflow-x: hidden; /* 防止水平滚动 */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
/* 全局隐藏滚动条 */
|
/* 全局隐藏滚动条 - 提供更清洁的视觉体验 */
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none; /* Firefox */
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全局隐藏 WebKit 浏览器的滚动条 */
|
/* 全局隐藏 WebKit 浏览器的滚动条 */
|
||||||
@@ -41,6 +65,11 @@ body::-webkit-scrollbar {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
应用根容器布局
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* React 根容器 */
|
||||||
#root {
|
#root {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -50,11 +79,13 @@ body::-webkit-scrollbar {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 主应用容器 - 使用毛玻璃效果 */
|
||||||
.app {
|
.app {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
/* 毛玻璃效果 - 创建现代化的半透明背景 */
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
-webkit-backdrop-filter: blur(20px);
|
-webkit-backdrop-filter: blur(20px);
|
||||||
@@ -66,44 +97,57 @@ body::-webkit-scrollbar {
|
|||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
全局交互样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 文本选择样式 - 自定义选中文本的外观 */
|
||||||
body ::selection {
|
body ::selection {
|
||||||
background-color: rgba(125, 167, 242, 0.18);
|
background-color: rgba(125, 167, 242, 0.18);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全局隐藏所有滚动条 */
|
/* 全局隐藏所有滚动条 - 统一的滚动条隐藏策略 */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none; /* Firefox */
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 焦点样式 - 提供清晰的键盘导航反馈 */
|
||||||
button:focus,
|
button:focus,
|
||||||
a:focus {
|
a:focus {
|
||||||
outline: 2px solid rgba(125, 167, 242, 0.4);
|
outline: 2px solid rgba(125, 167, 242, 0.4);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 手机屏 */
|
/* ========================================
|
||||||
|
响应式设计 - 移动端适配
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 手机屏幕适配 (768px 以下) */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
/* 手机屏全局字体放大1.5倍 */
|
/* 手机端字体放大 - 提高移动端可读性 */
|
||||||
html {
|
html {
|
||||||
font-size: 150%;
|
font-size: 150%; /* 基础字体大小放大 1.5 倍 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端侧边栏宽度变量 */
|
||||||
:root {
|
:root {
|
||||||
--sidebar-width-mobile: 280px;
|
--sidebar-width-mobile: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端页面布局优化 */
|
||||||
html, body {
|
html, body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden; /* 严格防止水平滚动 */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端根容器 */
|
||||||
#root {
|
#root {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -111,12 +155,13 @@ a:focus {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端应用容器 */
|
||||||
.app {
|
.app {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
border-radius: 0;
|
border-radius: 0; /* 移动端去除圆角 */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
flex-direction: row;
|
flex-direction: row; /* 保持水平布局 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,155 @@ import './MarkdownRenderer.css';
|
|||||||
import 'katex/dist/katex.min.css';
|
import 'katex/dist/katex.min.css';
|
||||||
import 'highlight.js/styles/github.css';
|
import 'highlight.js/styles/github.css';
|
||||||
|
|
||||||
|
// 下载Markdown文件功能
|
||||||
|
function downloadMarkdown(content, filename) {
|
||||||
|
const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename || 'document.md';
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制到剪贴板功能
|
||||||
|
async function copyToClipboard(content) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(content);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
// 降级方案:使用传统的复制方法
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = content;
|
||||||
|
textArea.style.position = 'fixed';
|
||||||
|
textArea.style.left = '-999999px';
|
||||||
|
textArea.style.top = '-999999px';
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.focus();
|
||||||
|
textArea.select();
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能按钮组件
|
||||||
|
function ActionButtons({ content, filename }) {
|
||||||
|
const [copyStatus, setCopyStatus] = useState('');
|
||||||
|
const [downloadStatus, setDownloadStatus] = useState('');
|
||||||
|
|
||||||
|
const handleDownload = () => {
|
||||||
|
try {
|
||||||
|
downloadMarkdown(content, filename);
|
||||||
|
setDownloadStatus('success');
|
||||||
|
setTimeout(() => setDownloadStatus(''), 2000);
|
||||||
|
} catch (error) {
|
||||||
|
setDownloadStatus('error');
|
||||||
|
setTimeout(() => setDownloadStatus(''), 2000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCopy = async () => {
|
||||||
|
const success = await copyToClipboard(content);
|
||||||
|
setCopyStatus(success ? 'success' : 'error');
|
||||||
|
setTimeout(() => setCopyStatus(''), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="action-buttons">
|
||||||
|
<button
|
||||||
|
className={`action-button download-button ${downloadStatus}`}
|
||||||
|
onClick={handleDownload}
|
||||||
|
title="下载Markdown文件"
|
||||||
|
aria-label="下载Markdown文件"
|
||||||
|
>
|
||||||
|
📥
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`action-button copy-button ${copyStatus}`}
|
||||||
|
onClick={handleCopy}
|
||||||
|
title="复制Markdown内容"
|
||||||
|
aria-label="复制Markdown内容"
|
||||||
|
>
|
||||||
|
📋
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字数统计工具函数
|
||||||
|
function countWords(markdownText) {
|
||||||
|
if (!markdownText || typeof markdownText !== 'string') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除Markdown格式符号的正则表达式
|
||||||
|
let plainText = markdownText
|
||||||
|
// 移除代码块
|
||||||
|
.replace(/```[\s\S]*?```/g, '')
|
||||||
|
// 移除内联代码
|
||||||
|
.replace(/`[^`]*`/g, '')
|
||||||
|
// 移除链接 [text](url)
|
||||||
|
.replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
|
||||||
|
// 移除图片 
|
||||||
|
.replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
|
||||||
|
// 移除标题标记
|
||||||
|
.replace(/^#{1,6}\s+/gm, '')
|
||||||
|
// 移除粗体和斜体标记
|
||||||
|
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
||||||
|
.replace(/\*([^*]+)\*/g, '$1')
|
||||||
|
.replace(/__([^_]+)__/g, '$1')
|
||||||
|
.replace(/_([^_]+)_/g, '$1')
|
||||||
|
// 移除删除线
|
||||||
|
.replace(/~~([^~]+)~~/g, '$1')
|
||||||
|
// 移除引用标记
|
||||||
|
.replace(/^>\s*/gm, '')
|
||||||
|
// 移除列表标记
|
||||||
|
.replace(/^[\s]*[-*+]\s+/gm, '')
|
||||||
|
.replace(/^[\s]*\d+\.\s+/gm, '')
|
||||||
|
// 移除水平分割线
|
||||||
|
.replace(/^[-*_]{3,}$/gm, '')
|
||||||
|
// 移除HTML标签
|
||||||
|
.replace(/<[^>]*>/g, '')
|
||||||
|
// 移除多余的空白字符
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
// 统计中文字符和英文单词
|
||||||
|
const chineseChars = (plainText.match(/[\u4e00-\u9fa5]/g) || []).length;
|
||||||
|
const englishWords = plainText
|
||||||
|
.replace(/[\u4e00-\u9fa5]/g, ' ')
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter(word => word.length > 0 && /[a-zA-Z]/.test(word)).length;
|
||||||
|
|
||||||
|
return chineseChars + englishWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字数统计显示组件
|
||||||
|
function WordCount({ content }) {
|
||||||
|
const wordCount = useMemo(() => countWords(content), [content]);
|
||||||
|
|
||||||
|
if (wordCount === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="word-count-container">
|
||||||
|
<div className="word-count-info">
|
||||||
|
<span className="word-count-icon">📊</span>
|
||||||
|
<span className="word-count-text">全文共 {wordCount.toLocaleString()} 字</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 自定义插件:禁用内联代码解析
|
// 自定义插件:禁用内联代码解析
|
||||||
function remarkDisableInlineCode() {
|
function remarkDisableInlineCode() {
|
||||||
return (tree) => {
|
return (tree) => {
|
||||||
@@ -250,11 +399,13 @@ export default function MarkdownRenderer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fileTitle = getFileTitle(currentFile.split('/').pop(), currentContent);
|
const fileTitle = getFileTitle(currentFile.split('/').pop(), currentContent);
|
||||||
|
const filename = currentFile.split('/').pop();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={contentAreaClass}>
|
<div className={contentAreaClass}>
|
||||||
<div className="content-header">
|
<div className="content-header">
|
||||||
<h1 className="content-title">{fileTitle}</h1>
|
<h1 className="content-title">{fileTitle}</h1>
|
||||||
|
<ActionButtons content={currentContent} filename={filename} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="content-body">
|
<div className="content-body">
|
||||||
@@ -273,6 +424,7 @@ export default function MarkdownRenderer() {
|
|||||||
>
|
>
|
||||||
{currentContent}
|
{currentContent}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
|
<WordCount content={currentContent} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,43 +1,66 @@
|
|||||||
|
/* ========================================
|
||||||
|
侧边栏组件样式文件 (Sidebar.css)
|
||||||
|
用途:定义侧边栏布局、交互效果和响应式行为
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
侧边栏主容器
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 侧边栏基础样式 - 使用毛玻璃效果 */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 110;
|
z-index: 110; /* 高层级确保在其他元素之上 */
|
||||||
width: var(--sidebar-width);
|
width: var(--sidebar-width); /* 使用 CSS 变量控制宽度 */
|
||||||
height: 100vh;
|
height: 100vh; /* 全屏高度 */
|
||||||
|
/* 毛玻璃背景效果 */
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(255, 255, 255, 0.08);
|
||||||
backdrop-filter: blur(16px) saturate(180%);
|
backdrop-filter: blur(16px) saturate(180%);
|
||||||
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
||||||
border-right: 1px solid rgba(255, 255, 255, 0.18);
|
border-right: 1px solid rgba(255, 255, 255, 0.18);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 1.5rem 1.25rem 1.75rem;
|
padding: 1.5rem 1.25rem 1.75rem; /* 上 左右 下 内边距 */
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
box-shadow: 0 6px 24px rgba(45, 60, 115, 0.18);
|
box-shadow: 0 6px 24px rgba(45, 60, 115, 0.18);
|
||||||
overflow: hidden;
|
overflow: hidden; /* 防止内容溢出 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 侧边栏关闭状态 - 完全隐藏 */
|
||||||
.sidebar.closed {
|
.sidebar.closed {
|
||||||
width: 0;
|
width: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none; /* 禁用鼠标事件 */
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
侧边栏头部区域
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 侧边栏头部布局 */
|
||||||
.sidebar-header {
|
.sidebar-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem; /* 元素间距 */
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 侧边栏标题样式 */
|
||||||
.sidebar-header h2 {
|
.sidebar-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em; /* 字母间距 */
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
切换按钮样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 侧边栏切换按钮 - 毛玻璃风格 */
|
||||||
.toggle-button {
|
.toggle-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -45,6 +68,7 @@
|
|||||||
min-width: 42px;
|
min-width: 42px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
padding: 0 0.7rem;
|
padding: 0 0.7rem;
|
||||||
|
/* 毛玻璃按钮效果 */
|
||||||
background: rgba(255, 255, 255, 0.16);
|
background: rgba(255, 255, 255, 0.16);
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
-webkit-backdrop-filter: blur(10px);
|
-webkit-backdrop-filter: blur(10px);
|
||||||
@@ -54,50 +78,65 @@
|
|||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease; /* 平滑过渡动画 */
|
||||||
box-shadow: 0 6px 14px rgba(45, 60, 115, 0.18);
|
box-shadow: 0 6px 14px rgba(45, 60, 115, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 切换按钮悬停状态 */
|
||||||
.toggle-button:hover {
|
.toggle-button:hover {
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
border-color: rgba(125, 167, 242, 0.55);
|
border-color: rgba(125, 167, 242, 0.55);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 切换按钮激活状态 */
|
||||||
.toggle-button.open {
|
.toggle-button.open {
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
border-color: rgba(125, 167, 242, 0.65);
|
border-color: rgba(125, 167, 242, 0.65);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
侧边栏内容区域
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 侧边栏滚动内容区 */
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
flex: 1;
|
flex: 1; /* 占据剩余空间 */
|
||||||
overflow-y: auto;
|
overflow-y: auto; /* 垂直滚动 */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden; /* 隐藏水平滚动 */
|
||||||
padding-right: 0.5rem;
|
padding-right: 0.5rem; /* 右侧内边距 */
|
||||||
height: 0;
|
height: 0; /* 配合 flex: 1 实现正确的滚动 */
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
目录树结构
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 目录树容器 */
|
||||||
.directory-tree {
|
.directory-tree {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0rem;
|
gap: 0rem; /* 节点间无间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点基础样式 */
|
||||||
.tree-node {
|
.tree-node {
|
||||||
user-select: none;
|
user-select: none; /* 禁用文本选择 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点内容区 - 交互式设计 */
|
||||||
.tree-node-content {
|
.tree-node-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.55rem;
|
gap: 0.55rem; /* 图标与文本间距 */
|
||||||
padding: 0.3rem 0.65rem;
|
padding: 0.3rem 0.65rem;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
color: rgba(31, 42, 68, 0.7);
|
color: rgba(31, 42, 68, 0.7); /* 默认文本颜色 */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease; /* 平滑过渡效果 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点悬停效果 */
|
||||||
.tree-node-content:hover {
|
.tree-node-content:hover {
|
||||||
background: rgba(255, 255, 255, 0.2);
|
background: rgba(255, 255, 255, 0.2);
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
@@ -106,6 +145,7 @@
|
|||||||
box-shadow: 0 3px 10px rgba(45, 60, 115, 0.16);
|
box-shadow: 0 3px 10px rgba(45, 60, 115, 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点选中状态 */
|
||||||
.tree-node-content.selected {
|
.tree-node-content.selected {
|
||||||
background: rgba(255, 255, 255, 0.26);
|
background: rgba(255, 255, 255, 0.26);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
@@ -116,24 +156,70 @@
|
|||||||
box-shadow: 0 4px 14px rgba(125, 167, 242, 0.25);
|
box-shadow: 0 4px 14px rgba(125, 167, 242, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点图标样式 */
|
||||||
.tree-node-icon {
|
.tree-node-icon {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease; /* 图标变换动画 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 选中状态下的图标放大效果 */
|
||||||
.tree-node-content.selected .tree-node-icon {
|
.tree-node-content.selected .tree-node-icon {
|
||||||
transform: scale(1.06);
|
transform: scale(1.06); /* 轻微放大 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点子级容器 */
|
||||||
.tree-node-children {
|
.tree-node-children {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 树节点名称样式 */
|
||||||
.tree-node-name {
|
.tree-node-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
flex: 1; /* 占据剩余空间 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 文章数量标识样式 */
|
||||||
|
.article-count-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
padding: 0.1rem 0.35rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
background: linear-gradient(135deg, rgba(125, 167, 242, 0.85), rgba(88, 134, 230, 0.9));
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||||
|
box-shadow: 0 2px 6px rgba(125, 167, 242, 0.3);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文章数量标识悬停效果 */
|
||||||
|
.tree-node-content:hover .article-count-badge {
|
||||||
|
background: linear-gradient(135deg, rgba(125, 167, 242, 0.95), rgba(88, 134, 230, 1));
|
||||||
|
box-shadow: 0 3px 8px rgba(125, 167, 242, 0.4);
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中状态下的文章数量标识 */
|
||||||
|
.tree-node-content.selected .article-count-badge {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.8));
|
||||||
|
color: var(--color-accent);
|
||||||
|
border: 1px solid rgba(125, 167, 242, 0.4);
|
||||||
|
box-shadow: 0 3px 10px rgba(125, 167, 242, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
加载和错误状态
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 加载状态和错误状态的通用样式 */
|
||||||
.loading,
|
.loading,
|
||||||
.error {
|
.error {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -146,82 +232,140 @@
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 加载动画 - 旋转圆圈 */
|
||||||
.loading-spinner {
|
.loading-spinner {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
border: 2px solid rgba(111, 123, 146, 0.25);
|
border: 2px solid rgba(111, 123, 146, 0.25);
|
||||||
border-top: 2px solid var(--color-accent);
|
border-top: 2px solid var(--color-accent);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: spin 0.9s linear infinite;
|
animation: spin 0.9s linear infinite; /* 无限旋转动画 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 旋转动画关键帧 */
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
侧边栏背景遮罩
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 侧边栏背景遮罩 - 默认隐藏 */
|
||||||
.sidebar-backdrop {
|
.sidebar-backdrop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 侧边栏切换按钮 - 固定定位 */
|
||||||
.sidebar-toggle {
|
.sidebar-toggle {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 1rem;
|
top: 1rem;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
z-index: 130;
|
z-index: 130; /* 最高层级 */
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
box-shadow: 0 14px 30px rgba(86, 105, 141, 0.18);
|
box-shadow: 0 14px 30px rgba(86, 105, 141, 0.18);
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
touch-action: none; /* 禁用默认触摸行为 */
|
||||||
|
user-select: none; /* 禁用文本选择 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 手机屏 */
|
/* 拖动状态样式 */
|
||||||
|
.sidebar-toggle.dragging {
|
||||||
|
box-shadow: 0 20px 40px rgba(86, 105, 141, 0.3);
|
||||||
|
opacity: 0.9;
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
响应式设计 - 移动端适配
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 手机屏幕适配 (768px 以下) */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
/* 移动端侧边栏样式调整 */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: var(--sidebar-width-mobile, 280px);
|
width: var(--sidebar-width-mobile, 280px);
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
max-width: calc(100vw - 1rem);
|
max-width: calc(100vw - 1rem); /* 防止超出屏幕 */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端关闭状态 - 使用平移隐藏 */
|
||||||
.sidebar.closed {
|
.sidebar.closed {
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%); /* 向左平移隐藏 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-button {
|
/* 移动端切换按钮调整 */
|
||||||
top: 0.75rem;
|
.sidebar-toggle {
|
||||||
left: 0.75rem;
|
width: 44px;
|
||||||
z-index: 1001;
|
height: 44px;
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
/* 移动端特殊样式 */
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
box-shadow: 0 8px 20px rgba(86, 105, 141, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端拖动状态增强 */
|
||||||
|
.sidebar-toggle.dragging {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-color: rgba(125, 167, 242, 0.5);
|
||||||
|
box-shadow: 0 12px 30px rgba(125, 167, 242, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端悬停效果 */
|
||||||
|
.sidebar-toggle:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端内容区域优化 */
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端目录树优化 */
|
||||||
.directory-tree {
|
.directory-tree {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端标题调整 */
|
||||||
.sidebar-header h2 {
|
.sidebar-header h2 {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* 电脑屏 */
|
/* 移动端文章数量标识调整 */
|
||||||
@media (min-width: 769px) {
|
.article-count-badge {
|
||||||
.sidebar {
|
min-width: 1.1rem;
|
||||||
position: static;
|
height: 1.1rem;
|
||||||
transform: none;
|
padding: 0.05rem 0.25rem;
|
||||||
opacity: 1;
|
font-size: 0.65rem;
|
||||||
pointer-events: auto;
|
margin-left: 0.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 桌面端适配 (769px 以上) */
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
/* 桌面端侧边栏始终可见 */
|
||||||
|
.sidebar {
|
||||||
|
position: static; /* 静态定位 */
|
||||||
|
transform: none; /* 无变换 */
|
||||||
|
opacity: 1; /* 完全不透明 */
|
||||||
|
pointer-events: auto; /* 启用鼠标事件 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 桌面端隐藏切换按钮 */
|
||||||
|
.sidebar-toggle {
|
||||||
|
display: none !important; /* 完全隐藏切换按钮 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useMemo, useState, useRef } from 'react';
|
||||||
import { useApp } from '../context/AppContext';
|
import { useApp } from '../context/AppContext';
|
||||||
import { NODE_TYPES } from '../utils/fileUtils';
|
import { NODE_TYPES } from '../utils/fileUtils';
|
||||||
import './Sidebar.css';
|
import './Sidebar.css';
|
||||||
@@ -6,6 +6,16 @@ import './Sidebar.css';
|
|||||||
function TreeNode({ node, level = 0 }) {
|
function TreeNode({ node, level = 0 }) {
|
||||||
const { selectFile, toggleNodeExpansion, currentFile } = useApp();
|
const { selectFile, toggleNodeExpansion, currentFile } = useApp();
|
||||||
|
|
||||||
|
// 计算当前目录下的直接文章数量
|
||||||
|
const articleCount = useMemo(() => {
|
||||||
|
if (node.type !== NODE_TYPES.FOLDER || !node.children) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return node.children.filter(child =>
|
||||||
|
child.type === NODE_TYPES.FILE && child.name.endsWith('.md')
|
||||||
|
).length;
|
||||||
|
}, [node]);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (node.type === NODE_TYPES.FOLDER) {
|
if (node.type === NODE_TYPES.FOLDER) {
|
||||||
toggleNodeExpansion(node.path);
|
toggleNodeExpansion(node.path);
|
||||||
@@ -48,6 +58,9 @@ function TreeNode({ node, level = 0 }) {
|
|||||||
? node.name.slice(0, -3)
|
? node.name.slice(0, -3)
|
||||||
: node.name}
|
: node.name}
|
||||||
</span>
|
</span>
|
||||||
|
{node.type === NODE_TYPES.FOLDER && articleCount > 0 && (
|
||||||
|
<span className="article-count-badge">{articleCount}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{node.type === NODE_TYPES.FOLDER && node.isExpanded && hasChildren && (
|
{node.type === NODE_TYPES.FOLDER && node.isExpanded && hasChildren && (
|
||||||
@@ -64,6 +77,106 @@ function TreeNode({ node, level = 0 }) {
|
|||||||
export default function Sidebar() {
|
export default function Sidebar() {
|
||||||
const { directoryTree, isLoading, error, sidebarOpen, toggleSidebar } = useApp();
|
const { directoryTree, isLoading, error, sidebarOpen, toggleSidebar } = useApp();
|
||||||
|
|
||||||
|
// 拖动相关状态
|
||||||
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
const [dragPosition, setDragPosition] = useState(() => {
|
||||||
|
// 从localStorage读取保存的位置,默认右上角
|
||||||
|
const saved = localStorage.getItem('sidebar-toggle-position');
|
||||||
|
return saved ? JSON.parse(saved) : { x: window.innerWidth - 60, y: 20 };
|
||||||
|
});
|
||||||
|
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
|
||||||
|
const [touchStartPos, setTouchStartPos] = useState({ x: 0, y: 0 });
|
||||||
|
const [hasMoved, setHasMoved] = useState(false);
|
||||||
|
const buttonRef = useRef(null);
|
||||||
|
|
||||||
|
// 拖动事件处理函数
|
||||||
|
const handleTouchStart = (e) => {
|
||||||
|
if (window.innerWidth > 768) return; // 只在移动端启用拖动
|
||||||
|
|
||||||
|
const touch = e.touches[0];
|
||||||
|
const rect = buttonRef.current.getBoundingClientRect();
|
||||||
|
|
||||||
|
setTouchStartPos({ x: touch.clientX, y: touch.clientY });
|
||||||
|
setDragOffset({
|
||||||
|
x: touch.clientX - rect.left,
|
||||||
|
y: touch.clientY - rect.top
|
||||||
|
});
|
||||||
|
setHasMoved(false);
|
||||||
|
// 不要在这里preventDefault,让点击事件能正常触发
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTouchMove = (e) => {
|
||||||
|
if (window.innerWidth > 768) return;
|
||||||
|
|
||||||
|
const touch = e.touches[0];
|
||||||
|
const deltaX = Math.abs(touch.clientX - touchStartPos.x);
|
||||||
|
const deltaY = Math.abs(touch.clientY - touchStartPos.y);
|
||||||
|
|
||||||
|
// 如果移动距离超过5px,认为是拖动
|
||||||
|
if (deltaX > 5 || deltaY > 5) {
|
||||||
|
if (!hasMoved) {
|
||||||
|
setHasMoved(true);
|
||||||
|
setIsDragging(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newX = touch.clientX - dragOffset.x;
|
||||||
|
const newY = touch.clientY - dragOffset.y;
|
||||||
|
|
||||||
|
// 限制在屏幕范围内
|
||||||
|
const maxX = window.innerWidth - 44;
|
||||||
|
const maxY = window.innerHeight - 44;
|
||||||
|
|
||||||
|
setDragPosition({
|
||||||
|
x: Math.max(0, Math.min(newX, maxX)),
|
||||||
|
y: Math.max(0, Math.min(newY, maxY))
|
||||||
|
});
|
||||||
|
|
||||||
|
e.preventDefault(); // 只在确认拖动时阻止默认行为
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTouchEnd = (e) => {
|
||||||
|
if (hasMoved && isDragging) {
|
||||||
|
// 保存位置到localStorage
|
||||||
|
localStorage.setItem('sidebar-toggle-position', JSON.stringify(dragPosition));
|
||||||
|
e.preventDefault(); // 阻止点击事件
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsDragging(false);
|
||||||
|
setHasMoved(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理点击事件
|
||||||
|
const handleButtonClick = (e) => {
|
||||||
|
// 如果刚刚完成拖动,不触发点击
|
||||||
|
if (hasMoved) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggleSidebar();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理窗口大小变化
|
||||||
|
useEffect(() => {
|
||||||
|
const handleResize = () => {
|
||||||
|
if (window.innerWidth > 768) {
|
||||||
|
// 桌面端重置位置
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动端调整位置确保按钮在屏幕范围内
|
||||||
|
const maxX = window.innerWidth - 44;
|
||||||
|
const maxY = window.innerHeight - 44;
|
||||||
|
|
||||||
|
setDragPosition(prev => ({
|
||||||
|
x: Math.max(0, Math.min(prev.x, maxX)),
|
||||||
|
y: Math.max(0, Math.min(prev.y, maxY))
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const toggleLabel = sidebarOpen ? '隐藏目录' : '展开目录';
|
const toggleLabel = sidebarOpen ? '隐藏目录' : '展开目录';
|
||||||
const toggleSymbol = sidebarOpen ? '◀' : '☰';
|
const toggleSymbol = sidebarOpen ? '◀' : '☰';
|
||||||
const sidebarClass = sidebarOpen ? 'sidebar open' : 'sidebar closed';
|
const sidebarClass = sidebarOpen ? 'sidebar open' : 'sidebar closed';
|
||||||
@@ -101,9 +214,20 @@ export default function Sidebar() {
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
ref={buttonRef}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={toggleSidebar}
|
onClick={handleButtonClick}
|
||||||
className={`sidebar-toggle ${toggleButtonClass}`.trim()}
|
onTouchStart={handleTouchStart}
|
||||||
|
onTouchMove={handleTouchMove}
|
||||||
|
onTouchEnd={handleTouchEnd}
|
||||||
|
className={`sidebar-toggle ${toggleButtonClass} ${isDragging ? 'dragging' : ''}`.trim()}
|
||||||
|
style={{
|
||||||
|
left: `${dragPosition.x}px`,
|
||||||
|
top: `${dragPosition.y}px`,
|
||||||
|
right: 'auto',
|
||||||
|
transform: isDragging ? 'scale(1.1)' : 'scale(1)',
|
||||||
|
zIndex: isDragging ? 1000 : 130
|
||||||
|
}}
|
||||||
aria-label={toggleLabel}
|
aria-label={toggleLabel}
|
||||||
>
|
>
|
||||||
{toggleSymbol}
|
{toggleSymbol}
|
||||||
|
|||||||
@@ -5,6 +5,64 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "编程语言",
|
"path": "编程语言",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端",
|
||||||
|
"name": "前端",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "编程语言/前端",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题",
|
||||||
|
"name": "JavaScript趣味题",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md",
|
||||||
|
"name": "JavaScript趣味题_128.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_128.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md",
|
||||||
|
"name": "JavaScript趣味题_18.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_18.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md",
|
||||||
|
"name": "JavaScript趣味题_28.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/JavaScript趣味题/JavaScript趣味题_28.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/纯静态网页的强大功能与应用.md",
|
||||||
|
"name": "纯静态网页的强大功能与应用.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/纯静态网页的强大功能与应用.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "编程语言/前端/css注入代码合集.md",
|
||||||
|
"name": "css注入代码合集.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "编程语言/前端/css注入代码合集.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "编程语言/Android",
|
"id": "编程语言/Android",
|
||||||
"name": "Android",
|
"name": "Android",
|
||||||
@@ -335,6 +393,30 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "计算机科普",
|
"path": "计算机科普",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "计算机科普/编程语言科普.md",
|
||||||
|
"name": "编程语言科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/编程语言科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/编程语言之间的划分.md",
|
||||||
|
"name": "编程语言之间的划分.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/编程语言之间的划分.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/操作系统科普.md",
|
||||||
|
"name": "操作系统科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/操作系统科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/多模态大模型识别图片,视频,音频原理.md",
|
"id": "计算机科普/多模态大模型识别图片,视频,音频原理.md",
|
||||||
"name": "多模态大模型识别图片,视频,音频原理.md",
|
"name": "多模态大模型识别图片,视频,音频原理.md",
|
||||||
@@ -343,14 +425,6 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "计算机科普/光纤和网线的特点和区别.md",
|
|
||||||
"name": "光纤和网线的特点和区别.md",
|
|
||||||
"type": "file",
|
|
||||||
"path": "计算机科普/光纤和网线的特点和区别.md",
|
|
||||||
"children": [],
|
|
||||||
"isExpanded": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "计算机科普/科普-Nagle 算法.md",
|
"id": "计算机科普/科普-Nagle 算法.md",
|
||||||
"name": "科普-Nagle 算法.md",
|
"name": "科普-Nagle 算法.md",
|
||||||
@@ -359,6 +433,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语解释-DMZ.md",
|
||||||
|
"name": "术语解释-DMZ.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语解释-DMZ.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/术语科普-CVM.md",
|
"id": "计算机科普/术语科普-CVM.md",
|
||||||
"name": "术语科普-CVM.md",
|
"name": "术语科普-CVM.md",
|
||||||
@@ -383,6 +465,22 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-MQ.md",
|
||||||
|
"name": "术语科普-MQ.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-MQ.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-POI.md",
|
||||||
|
"name": "术语科普-POI.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-POI.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/术语科普-pwn.md",
|
"id": "计算机科普/术语科普-pwn.md",
|
||||||
"name": "术语科普-pwn.md",
|
"name": "术语科普-pwn.md",
|
||||||
@@ -391,6 +489,46 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/术语科普-QPS.md",
|
||||||
|
"name": "术语科普-QPS.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/术语科普-QPS.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/网络协议科普.md",
|
||||||
|
"name": "网络协议科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/网络协议科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/游戏行业简单科普.md",
|
||||||
|
"name": "游戏行业简单科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/游戏行业简单科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/游戏引擎科普.md",
|
||||||
|
"name": "游戏引擎科普.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/游戏引擎科普.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"name": "C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/C,C++,CSharp,Objective-c的差异与特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/clash机场三种代理模式科普.md",
|
"id": "计算机科普/clash机场三种代理模式科普.md",
|
||||||
"name": "clash机场三种代理模式科普.md",
|
"name": "clash机场三种代理模式科普.md",
|
||||||
@@ -407,6 +545,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机科普/IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"name": "IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机科普/IDE,编辑器,编译器区别和特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机科普/IDEA专业版和社区版的区别和特点.md",
|
"id": "计算机科普/IDEA专业版和社区版的区别和特点.md",
|
||||||
"name": "IDEA专业版和社区版的区别和特点.md",
|
"name": "IDEA专业版和社区版的区别和特点.md",
|
||||||
@@ -465,10 +611,26 @@
|
|||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "计算机网络/TCP的三次握手四次握手.md",
|
"id": "计算机网络/HTTP版本协议对比区别.md",
|
||||||
"name": "TCP的三次握手四次握手.md",
|
"name": "HTTP版本协议对比区别.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "计算机网络/TCP的三次握手四次握手.md",
|
"path": "计算机网络/HTTP版本协议对比区别.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机网络/HTTP常见状态码.md",
|
||||||
|
"name": "HTTP常见状态码.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机网络/HTTP常见状态码.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "计算机网络/TCP的三次握手四次握手总结.md",
|
||||||
|
"name": "TCP的三次握手四次握手总结.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "计算机网络/TCP的三次握手四次握手总结.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
@@ -476,24 +638,48 @@
|
|||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "面试八股",
|
"id": "内网穿透",
|
||||||
"name": "面试八股",
|
"name": "内网穿透",
|
||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "面试八股",
|
"path": "内网穿透",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "面试八股/计算机面试经典八股.md",
|
"id": "内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
"name": "计算机面试经典八股.md",
|
"name": "搭建derp和headscale避坑与指南.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "面试八股/计算机面试经典八股.md",
|
"path": "内网穿透/搭建derp和headscale避坑与指南.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "面试八股/Nacos功能与应用场景详解.md",
|
"id": "内网穿透/内网穿透方案.md",
|
||||||
"name": "Nacos功能与应用场景详解.md",
|
"name": "内网穿透方案.md",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "面试八股/Nacos功能与应用场景详解.md",
|
"path": "内网穿透/内网穿透方案.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/Frp的kcp和quic的区别和特点.md",
|
||||||
|
"name": "Frp的kcp和quic的区别和特点.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/Frp的kcp和quic的区别和特点.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/frp服务端配置.md",
|
||||||
|
"name": "frp服务端配置.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/frp服务端配置.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "内网穿透/frp客户端配置.md",
|
||||||
|
"name": "frp客户端配置.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "内网穿透/frp客户端配置.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
@@ -506,6 +692,14 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "嵌入式",
|
"path": "嵌入式",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "嵌入式/光纤和网线的特点和区别.md",
|
||||||
|
"name": "光纤和网线的特点和区别.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "嵌入式/光纤和网线的特点和区别.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "嵌入式/USB拓展坞接口数量决定因素.md",
|
"id": "嵌入式/USB拓展坞接口数量决定因素.md",
|
||||||
"name": "USB拓展坞接口数量决定因素.md",
|
"name": "USB拓展坞接口数量决定因素.md",
|
||||||
@@ -575,6 +769,81 @@
|
|||||||
],
|
],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职",
|
||||||
|
"name": "实习求职",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股",
|
||||||
|
"name": "面试八股",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职/面试八股",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/HTTP 与HTTPS",
|
||||||
|
"name": "HTTP 与HTTPS",
|
||||||
|
"type": "folder",
|
||||||
|
"path": "实习求职/面试八股/HTTP 与HTTPS",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/HTTP 与HTTPS/从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"name": "从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/HTTP 与HTTPS/从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/计算机面试经典八股.md",
|
||||||
|
"name": "计算机面试经典八股.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/计算机面试经典八股.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/面试八股/Nacos功能与应用场景详解.md",
|
||||||
|
"name": "Nacos功能与应用场景详解.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/面试八股/Nacos功能与应用场景详解.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"name": "27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/术语科普-HC.md",
|
||||||
|
"name": "术语科普-HC.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/术语科普-HC.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "实习求职/术语科普-PM.md",
|
||||||
|
"name": "术语科普-PM.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "实习求职/术语科普-PM.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "数据结构与算法",
|
"id": "数据结构与算法",
|
||||||
"name": "数据结构与算法",
|
"name": "数据结构与算法",
|
||||||
@@ -973,6 +1242,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "AI/AI大模型应用拆解.md",
|
||||||
|
"name": "AI大模型应用拆解.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "AI/AI大模型应用拆解.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "AI/Qwen-Code官方文档使用教程.md",
|
"id": "AI/Qwen-Code官方文档使用教程.md",
|
||||||
"name": "Qwen-Code官方文档使用教程.md",
|
"name": "Qwen-Code官方文档使用教程.md",
|
||||||
@@ -1004,6 +1281,14 @@
|
|||||||
"type": "folder",
|
"type": "folder",
|
||||||
"path": "Docker/优秀好用的Docker镜像",
|
"path": "Docker/优秀好用的Docker镜像",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/模板.md",
|
||||||
|
"name": "模板.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/模板.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Docker/优秀好用的Docker镜像/FileCodeBox-文件快递柜.md",
|
"id": "Docker/优秀好用的Docker镜像/FileCodeBox-文件快递柜.md",
|
||||||
"name": "FileCodeBox-文件快递柜.md",
|
"name": "FileCodeBox-文件快递柜.md",
|
||||||
@@ -1012,6 +1297,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/frp-内网穿透神器.md",
|
||||||
|
"name": "frp-内网穿透神器.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/frp-内网穿透神器.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "Docker/优秀好用的Docker镜像/Gitea-私有化仓库部署.md",
|
"id": "Docker/优秀好用的Docker镜像/Gitea-私有化仓库部署.md",
|
||||||
"name": "Gitea-私有化仓库部署.md",
|
"name": "Gitea-私有化仓库部署.md",
|
||||||
@@ -1067,6 +1360,22 @@
|
|||||||
"path": "Docker/优秀好用的Docker镜像/Redis-内存数据库.md",
|
"path": "Docker/优秀好用的Docker镜像/Redis-内存数据库.md",
|
||||||
"children": [],
|
"children": [],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"name": "SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/SurveyKing-强大的问卷调查服务.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md",
|
||||||
|
"name": "tailscale-ip-derp.md",
|
||||||
|
"type": "file",
|
||||||
|
"path": "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md",
|
||||||
|
"children": [],
|
||||||
|
"isExpanded": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isExpanded": false
|
"isExpanded": false
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"totalFiles": 163,
|
"totalFiles": 196,
|
||||||
"totalFolders": 34,
|
"totalFolders": 39,
|
||||||
"generatedAt": "2025-10-02T01:36:14.347Z",
|
"generatedAt": "2025-10-12T11:13:34.210Z",
|
||||||
"sourceDirectory": "E:\\React\\markdown-to-web\\public\\mengyanote"
|
"sourceDirectory": "E:\\React\\markdown-to-web\\public\\mengyanote"
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,75 @@
|
|||||||
:root {
|
/* ========================================
|
||||||
font-size: 16px;
|
全局基础样式文件 (index.css)
|
||||||
line-height: 1.6;
|
用途:定义全局重置样式和基础元素样式
|
||||||
font-weight: 400;
|
======================================== */
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
/* ========================================
|
||||||
-moz-osx-font-smoothing: grayscale;
|
根元素样式配置
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 根元素字体和渲染优化 */
|
||||||
|
:root {
|
||||||
|
font-size: 16px; /* 基础字体大小 - 16px 作为 1rem 基准 */
|
||||||
|
line-height: 1.6; /* 行高 - 提供良好的文本可读性 */
|
||||||
|
font-weight: 400; /* 默认字重 - 正常粗细 */
|
||||||
|
text-rendering: optimizeLegibility; /* 文本渲染优化 - 提高文字清晰度 */
|
||||||
|
-webkit-font-smoothing: antialiased; /* WebKit 字体平滑 - 减少锯齿 */
|
||||||
|
-moz-osx-font-smoothing: grayscale; /* Firefox macOS 字体平滑 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
链接样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 链接基础样式和交互效果 */
|
||||||
a {
|
a {
|
||||||
color: var(--color-accent);
|
color: var(--color-accent); /* 链接颜色 - 使用主题强调色 */
|
||||||
text-decoration: none;
|
text-decoration: none; /* 移除默认下划线 */
|
||||||
transition: color 0.2s ease;
|
transition: color 0.2s ease; /* 颜色过渡动画 - 平滑的悬停效果 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 链接悬停状态 */
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #1f5ce6;
|
color: #1f5ce6; /* 悬停时的深蓝色 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
媒体元素样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 图片、SVG 和视频的响应式处理 */
|
||||||
img,
|
img,
|
||||||
svg,
|
svg,
|
||||||
video {
|
video {
|
||||||
max-width: 100%;
|
max-width: 100%; /* 最大宽度限制 - 防止溢出容器 */
|
||||||
display: block;
|
display: block; /* 块级显示 - 避免底部空隙 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
代码元素样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 代码和预格式化文本的字体设置 */
|
||||||
code,
|
code,
|
||||||
pre {
|
pre {
|
||||||
|
/* 等宽字体族 - 优先使用现代编程字体 */
|
||||||
font-family: 'Fira Code', 'JetBrains Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
|
font-family: 'Fira Code', 'JetBrains Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
按钮样式
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 按钮字体继承 - 确保按钮使用父元素字体 */
|
||||||
button {
|
button {
|
||||||
font: inherit;
|
font: inherit; /* 继承父元素的字体样式 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================================
|
||||||
|
页面滚动控制
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 禁用页面滚动的辅助类 - 用于模态框等场景 */
|
||||||
body.no-scroll {
|
body.no-scroll {
|
||||||
overflow: hidden;
|
overflow: hidden; /* 隐藏滚动条并禁用滚动 */
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user