继续提交

This commit is contained in:
2025-12-19 15:51:26 +08:00
parent 0ce60d78df
commit cf2203e3eb
500 changed files with 3259 additions and 7739 deletions

View File

@@ -0,0 +1,18 @@
__pycache__
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg
*.egg-info
dist
build
.git
.gitignore
.vscode
.idea
*.md
README.md
.env
.env.local

View File

@@ -0,0 +1,26 @@
# 使用 Python 3.11 slim 镜像作为基础镜像
FROM python:3.11-slim
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
TZ=Asia/Shanghai
# 复制依赖文件
COPY requirements.txt .
# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制应用代码
COPY main.py .
COPY mengyanote ./mengyanote
# 暴露端口
EXPOSE 8000
# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Binary file not shown.

View File

@@ -0,0 +1,26 @@
version: '3.8'
services:
mengyanote-backend:
build: .
container_name: mengyanote-backend
restart: unless-stopped
ports:
- "2424:8000"
volumes:
# 持久化 mengyanote 数据目录
- /shumengya/docker/mengyanote/data:/app/mengyanote
environment:
- TZ=Asia/Shanghai
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/tree"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- mengyanote-network
networks:
mengyanote-network:
driver: bridge

257
mengyanote-backend/main.py Normal file
View File

@@ -0,0 +1,257 @@
import os
import json
from datetime import datetime
from pathlib import Path
from typing import List, Literal, Optional, Set
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
BASE_DIR = Path(__file__).resolve().parent
# Markdown 根目录:指向当前后端项目中的 `mengyanote` 文件夹
MARKDOWN_ROOT = BASE_DIR / "mengyanote"
# ignore.json 文件路径
IGNORE_FILE = MARKDOWN_ROOT / "ignore.json"
def load_ignore_list() -> Set[str]:
"""从 ignore.json 加载需要忽略的文件夹列表"""
if not IGNORE_FILE.exists():
return set()
try:
with open(IGNORE_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return set(data.get('ignore', []))
except Exception:
return set()
# 加载忽略列表
IGNORE_LIST = load_ignore_list()
class NodeType(str):
FOLDER: Literal["folder"] = "folder"
FILE: Literal["file"] = "file"
class DirectoryNode(BaseModel):
name: str
path: str # 相对于 MARKDOWN_ROOT 的路径,使用 / 作为分隔符
type: Literal["folder", "file"]
children: Optional[List["DirectoryNode"]] = None
DirectoryNode.update_forward_refs()
class FileContent(BaseModel):
path: str
content: str
word_count: int = 0
file_size: int = 0 # 文件大小,字节
created_time: str = ""
modified_time: str = ""
app = FastAPI(title="MengyaNote Backend", version="1.0.0")
app.add_middleware(
CORSMiddleware,
# 现在允许任意来源方便本地和静态托管访问,如 http://localhost:9090
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
def is_markdown_file(path: Path) -> bool:
return path.is_file() and path.suffix.lower() == ".md"
def should_skip(entry: Path) -> bool:
"""判断是否应该跳过该文件或文件夹"""
name = entry.name
# 跳过隐藏文件/文件夹
if name.startswith("."):
return True
# 跳过 ignore.json 文件本身
if name == "ignore.json":
return True
# 跳过 ignore.json 中配置的文件夹
if entry.is_dir() and name in IGNORE_LIST:
return True
return False
def build_directory_tree(root: Path) -> List[DirectoryNode]:
"""从文件系统构建目录树,结构尽量与原先 JSON 保持一致。"""
if not root.exists() or not root.is_dir():
return []
def walk(current: Path, rel: Path) -> DirectoryNode:
name = current.name
rel_path_str = rel.as_posix() if rel.as_posix() != "." else ""
if current.is_dir():
children_nodes: List[DirectoryNode] = []
for child in sorted(current.iterdir(), key=lambda p: (p.is_file(), p.name.lower())):
if should_skip(child):
continue
child_rel = rel / child.name
# 只收录 Markdown 文件和非空目录
if child.is_dir():
node = walk(child, child_rel)
# 如果目录下完全没有 md 文件/子目录,可以选择丢弃
if node.children:
children_nodes.append(node)
elif is_markdown_file(child):
children_nodes.append(
DirectoryNode(
name=child.name,
path=child_rel.as_posix(),
type="file",
children=None,
)
)
return DirectoryNode(
name=name,
path=rel_path_str or name,
type="folder",
children=children_nodes,
)
else:
# 单独文件的情况一般不会作为根调用
return DirectoryNode(
name=name,
path=rel_path_str or name,
type="file",
children=None,
)
nodes: List[DirectoryNode] = []
for child in sorted(MARKDOWN_ROOT.iterdir(), key=lambda p: (p.is_file(), p.name.lower())):
if should_skip(child):
continue
rel = Path(child.name)
if child.is_dir():
node = walk(child, rel)
if node.children:
nodes.append(node)
elif is_markdown_file(child):
nodes.append(
DirectoryNode(
name=child.name,
path=rel.as_posix(),
type="file",
children=None,
)
)
return nodes
def resolve_markdown_path(relative_path: str) -> Path:
"""将前端传入的相对路径安全地转换为磁盘路径,防止目录穿越。"""
# 统一使用 / 分隔符
safe_path = relative_path.replace("\\", "/").lstrip("/")
candidate = MARKDOWN_ROOT / safe_path
try:
candidate_resolved = candidate.resolve()
except FileNotFoundError:
candidate_resolved = candidate
if not str(candidate_resolved).startswith(str(MARKDOWN_ROOT.resolve())):
raise HTTPException(status_code=400, detail="非法路径")
return candidate_resolved
@app.get("/api/tree", response_model=List[DirectoryNode])
def get_directory_tree() -> List[DirectoryNode]:
"""
获取 Markdown 目录树。
返回结构与原来的 directoryTree.json 尽量保持兼容:
- name: 文件或文件夹名
- path: 相对路径(使用 /
- type: 'folder' | 'file'
- children: 子节点数组
"""
tree = build_directory_tree(MARKDOWN_ROOT)
return tree
@app.get("/api/file", response_model=FileContent)
def get_markdown_file(path: str = Query(..., description="相对于根目录的 Markdown 路径")) -> FileContent:
"""
获取指定 Markdown 文件内容。
Query 参数:
- path: 例如 'AI/大语言模型的API 调用.md'
"""
file_path = resolve_markdown_path(path)
if not file_path.exists() or not file_path.is_file() or not is_markdown_file(file_path):
raise HTTPException(status_code=404, detail="文件不存在")
try:
content = file_path.read_text(encoding="utf-8")
except UnicodeDecodeError:
# 回退编码
content = file_path.read_text(encoding="utf-8", errors="ignore")
# 获取文件统计信息
file_stat = file_path.stat()
# 计算字数(去除空格和换行符)
word_count = len(content.replace(" ", "").replace("\n", "").replace("\r", "").replace("\t", ""))
# 获取文件大小(字节)
file_size = file_stat.st_size
# 获取创建时间和修改时间
try:
# Windows 上 st_ctime 是创建时间Linux 上是元数据更改时间
created_time = datetime.fromtimestamp(file_stat.st_ctime).strftime("%Y年%m月%d%H:%M:%S")
except:
created_time = "未知"
try:
modified_time = datetime.fromtimestamp(file_stat.st_mtime).strftime("%Y年%m月%d%H:%M:%S")
except:
modified_time = "未知"
rel = file_path.relative_to(MARKDOWN_ROOT).as_posix()
return FileContent(
path=rel,
content=content,
word_count=word_count,
file_size=file_size,
created_time=created_time,
modified_time=modified_time
)
@app.get("/api/health")
def health_check():
"""简单健康检查接口。"""
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=int(os.getenv("PORT", 8000)), reload=True)

View File

@@ -0,0 +1,8 @@
{
"promptDelete": false,
"readableLineLength": false,
"strictLineBreaks": false,
"showLineNumber": false,
"rightToLeft": false,
"spellcheck": false
}

View File

@@ -0,0 +1,10 @@
{
"cssTheme": "GitHub Theme",
"theme": "moonstone",
"monospaceFontFamily": "Maple Mono NF CN",
"baseFontSize": 18,
"interfaceFontFamily": "Maple Mono NF CN",
"textFontFamily": "霞鹜文楷,Maple Mono NF CN",
"nativeMenus": false,
"accentColor": "#fec834"
}

View File

@@ -0,0 +1,5 @@
[
"obsidian-livesync",
"obsidian-style-settings",
"obsidian-hover-editor"
]

View File

@@ -0,0 +1,33 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": false,
"backlink": true,
"canvas": false,
"outgoing-link": true,
"tag-pane": true,
"properties": false,
"page-preview": true,
"daily-notes": false,
"templates": false,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": false,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": false,
"webviewer": false,
"footnotes": false,
"bases": false
}

View File

@@ -0,0 +1,22 @@
{
"collapse-filter": true,
"search": "",
"showTags": false,
"showAttachments": false,
"hideUnresolved": false,
"showOrphans": true,
"collapse-color-groups": true,
"colorGroups": [],
"collapse-display": true,
"showArrow": false,
"textFadeMultiplier": 0,
"nodeSizeMultiplier": 1,
"lineSizeMultiplier": 1,
"collapse-forces": true,
"centerStrength": 0.518713248970312,
"repelStrength": 10,
"linkStrength": 1,
"linkDistance": 250,
"scale": 1,
"close": true
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
{
"id": "obsidian-hover-editor",
"name": "Hover Editor",
"version": "0.11.26",
"minAppVersion": "1.5.8",
"description": "Transform the Page Preview hover popover into a fully working editor instance",
"author": "NothingIsLost",
"authorUrl": "https://github.com/nothingislost",
"isDesktopOnly": false
}

View File

@@ -0,0 +1,582 @@
/* @settings
name: Hover Editor
id: hover-editor
settings:
-
id: titlebar-heading
title: Title bar
type: heading
level: 1
collapsed: true
-
id: titlebar-heading
title: Title bar background/foreground
type: heading
level: 2
collapsed: true
-
id: he-title-bar-active-bg
title: Active unpinned title bar background color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-inactive-bg
title: Inactive unpinned title bar background color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-active-pinned-bg
title: Active pinned title bar background color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-inactive-pinned-bg
title: Inactive pinned title bar background color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-active-fg
title: Active title bar foreground color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-inactive-fg
title: Inactive title bar foreground color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: titlebar-action-heading
title: Title bar icons
type: heading
level: 2
collapsed: true
-
id: he-title-bar-inactive-action
title: Title bar inactive icon color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: he-title-bar-active-action
title: Titlebar active icon color
type: variable-themed-color
format: hex
default-light: '#'
default-dark: '#'
-
id: titlebar-text-heading
title: Title bar text
type: heading
level: 2
collapsed: true
-
id: he-title-bar-font-size
title: Title bar Font size
type: variable-text
description: Accepts any CSS font-size value
default: 15px
-
id: titlebar-height-heading
title: Title bar height
type: heading
level: 2
collapsed: true
-
id: he-title-bar-height
title: Title bar height
type: variable-text
description: Accepts any CSS font-size value
default: 28px
*/
:root {
/* general styling */
--he-popover-opacity-while-dragging: 0.8;
--he-popover-border-radius: 6px;
--he-popover-header-transition-speed: 0.3s;
--he-popover-snap-to-edge-transition-speed: 0.3s;
/* resize handle sizing */
--he-resize-handle-side-size: 12px;
--he-resize-handle-corner-size: 18px;
/* view header height */
--he-view-header-height: 36px;
}
body {
--he-text-on-accent-inactive: var(--text-on-accent); /* couldn't find a good variable that worked across themes */
--he-text-on-accent-active: #fff;
/* z-index layer settings, probably not a good idea to mess with these */
--he-popover-layer-inactive: calc(var(--layer-slides) - 4);
--he-popover-layer-active: calc(var(--he-popover-layer-inactive) + 1);
--he-popover-layer-new: calc(var(--he-popover-layer-inactive) + 2);
--he-leaf-drag-overlay: calc(var(--he-popover-layer-inactive) + 3);
/* calculated variables, do not modify */
--he-resize-handle-side-offset: calc((var(--he-resize-handle-side-size) - 3px) * -1);
--he-resize-handle-corner-offset: calc((var(--he-resize-handle-corner-size) / 2) * -1);
--he-resize-handle-side-length: calc(100% - var(--he-resize-handle-corner-size));
/* title bar colors */
--he-title-bar-active-bg: var(--interactive-accent);
--he-title-bar-inactive-bg: #777777;
--he-title-bar-inactive-pinned-bg: #777777;
--he-title-bar-active-pinned-bg: var(--interactive-accent);
--he-title-bar-active-fg: var(--he-text-on-accent-active);
--he-title-bar-inactive-fg: var(--he-text-on-accent-inactive);
/* title bar action/icon colors */
--he-title-bar-inactive-action: var(--he-text-on-accent-inactive);
--he-title-bar-active-action: var(--he-text-on-accent-active);
/* titlebar sizing */
--he-title-bar-height: 28px;
--he-title-bar-font-size: 15px;
}
.popover.hover-editor .workspace-leaf,
.popover.hover-editor .workspace-split {
height: 100%;
width: 100%;
}
/*
Obsidian 1.6 sets a different background for non-root splits,
then uses primary as an override at root. Since hover editors
don't live in a root split, we have to copy the override:
*/
.popover.hover-editor .workspace-split .view-content {
background-color: var(--background-primary);
}
.popover.hover-editor {
min-height: unset;
max-height: unset;
/* touch action none fixes dragging and resizing on mobile */
touch-action: none;
/* this is set to allow the drag/resize handles to overflow the popover frame */
overflow: visible;
border: none;
padding: 0;
z-index: var(--he-popover-layer-inactive);
border-radius: var(--he-popover-border-radius);
/* Prevent snagging on titlebar */
-webkit-app-region: no-drag;
}
.popover.hover-editor .markdown-preview-view {
font-size: inherit;
}
.popover.hover-editor.is-active {
z-index: var(--he-popover-layer-active);
}
.popover.hover-editor.is-new {
z-index: var(--he-popover-layer-new);
}
/* Drag/link overlay needs to overlay popups */
.workspace-fake-target-overlay,
.workspace-drop-overlay {
z-index: var(--he-leaf-drag-overlay);
}
.popover.hover-editor .resize-handle {
position: absolute;
touch-action: none;
}
.popover.hover-editor .resize-handle.top {
top: var(--he-resize-handle-side-offset);
height: var(--he-resize-handle-side-size);
left: calc(var(--he-resize-handle-corner-offset) * -1);
width: var(--he-resize-handle-side-length);
}
.popover.hover-editor .resize-handle.left {
height: var(--he-resize-handle-side-length);
left: var(--he-resize-handle-side-offset);
top: calc(var(--he-resize-handle-corner-offset) * -1);
width: var(--he-resize-handle-side-size);
}
.popover.hover-editor .resize-handle.right {
height: var(--he-resize-handle-side-length);
right: var(--he-resize-handle-side-offset);
top: calc(var(--he-resize-handle-corner-offset) * -1);
width: var(--he-resize-handle-side-size);
}
.popover.hover-editor .resize-handle.bottom {
bottom: var(--he-resize-handle-side-offset);
height: var(--he-resize-handle-side-size);
left: calc(var(--he-resize-handle-corner-offset) * -1);
width: var(--he-resize-handle-side-length);
}
.popover.hover-editor .resize-handle.bottom-left {
bottom: var(--he-resize-handle-corner-offset);
height: var(--he-resize-handle-corner-size);
left: var(--he-resize-handle-corner-offset);
width: var(--he-resize-handle-corner-size);
}
.popover.hover-editor .resize-handle.bottom-right {
bottom: var(--he-resize-handle-corner-offset);
height: var(--he-resize-handle-corner-size);
right: var(--he-resize-handle-corner-offset);
width: var(--he-resize-handle-corner-size);
}
.popover.hover-editor .resize-handle.top-left {
top: var(--he-resize-handle-corner-offset);
height: var(--he-resize-handle-corner-size);
left: var(--he-resize-handle-corner-offset);
width: var(--he-resize-handle-corner-size);
}
.popover.hover-editor .resize-handle.top-right {
top: var(--he-resize-handle-corner-offset);
height: var(--he-resize-handle-corner-size);
right: var(--he-resize-handle-corner-offset);
width: var(--he-resize-handle-corner-size);
}
/* body.is-dragging-popover .tooltip {
opacity: 0;
} */
.popover-header-icon {
width: fit-content;
}
.mod-pin-popover > svg {
transform: rotate(45deg);
}
.mod-pin-popover.is-active > svg {
transform: rotate(0deg);
}
.popover-action,
.popover-header-icon {
margin: 0 8px;
cursor: pointer;
color: var(--he-title-bar-inactive-action);
position: relative;
display: flex;
align-items: center;
}
.popover-action.is-active,
.mod-pin-popover.is-active {
color: var(--he-title-bar-active-action);
}
.popover-action:hover,
.popover-header-icon:hover {
color: var(--he-title-bar-active-action);
}
.popover-action.is-active svg,
.mod-pin-popover.is-active svg {
}
.mod-pin-popover.is-active > svg {
transform: unset;
}
.popover.hover-editor .workspace-leaf-content[data-type="empty"] .view-header {
/* ensures that minimal theme doesn't hide the popover header */
display: flex;
}
.popover.hover-editor .workspace-split > .workspace-leaf:last-child > .workspace-leaf-resize-handle {
/* this hides the leaf resize handles that touch the edge of the popover */
/* without this the leaf resize handles conflict with the popover resize handles */
display: none;
}
.popover.hover-editor.is-dragging {
opacity: var(--he-popover-opacity-while-dragging);
}
.popover.hover-editor:is(.snap-to-viewport, .snap-to-left, .snap-to-right) .resize-handle {
display: none;
}
.popover.hover-editor.snap-to-right .resize-handle.left,
.popover.hover-editor.snap-to-left .resize-handle.right {
display: block;
}
.popover.hover-editor.is-dragging.snap-to-left,
.popover.hover-editor.is-dragging.snap-to-right,
.popover.hover-editor.is-dragging.snap-to-viewport {
transition: width var(--he-popover-snap-to-edge-transition-speed),
height var(--he-popover-snap-to-edge-transition-speed), top var(--he-popover-snap-to-edge-transition-speed),
left var(--he-popover-snap-to-edge-transition-speed);
}
.hover-popover.is-dragging.snap-to-left::after,
.hover-popover.is-dragging.snap-to-right::after,
.hover-popover.is-dragging.snap-to-viewport::after {
position: absolute;
content: "";
width: 100%;
height: 100%;
top: 0;
border-radius: var(--he-popover-border-radius);
box-shadow: inset 0px 0px 0px 4px var(--interactive-accent);
pointer-events: none;
}
.popover.hover-editor.snap-to-left {
max-height: unset !important;
}
.popover.hover-editor.snap-to-right {
right: 0 !important;
max-height: unset !important;
}
.popover.hover-editor.snap-to-viewport {
max-height: unset !important;
max-width: unset !important;
}
.popover.hover-editor .popover-titlebar {
display: flex;
height: var(--he-title-bar-height);
width: 100%;
background-color: var(--he-title-bar-inactive-bg);
}
.popover.hover-editor.is-active .popover-titlebar {
background-color: var(--he-title-bar-active-bg);
}
.popover.hover-editor.is-pinned.is-pinned .popover-titlebar {
background-color: var(--he-title-bar-inactive-pinned-bg);
}
.popover.hover-editor.is-pinned.is-pinned.is-active .popover-titlebar {
background-color: var(--he-title-bar-active-pinned-bg);
}
.popover.hover-editor .popover-titlebar .popover-actions {
display: flex;
justify-content: flex-end;
}
.popover.hover-editor > .popover-content {
margin: 0;
border-radius: var(--he-popover-border-radius);
overflow: hidden;
height: 100%;
width: 100%;
}
.popover.hover-popover.hover-editor .pdf-toolbar:not(.pdf-findbar.mod-hidden) {
/* Show PDF toolbar in hover editor */
display: flex;
}
.popover.hover-editor .popover-titlebar .popover-title {
display: block;
flex-grow: 1;
transition: all 0.3s;
align-self: center;
font-size: var(--he-title-bar-font-size);
font-weight: 500;
white-space: pre;
word-wrap: normal;
color: var(--he-title-bar-inactive-fg);
overflow: hidden;
position: relative;
}
.popover.hover-editor.is-active .popover-title {
color: var(--he-title-bar-active-fg);
}
.popover.hover-editor.is-active .popover-title:after {
background: linear-gradient(to right, transparent, var(--he-title-bar-active-bg));
}
.popover.hover-editor.is-pinned.is-pinned.is-active .popover-title:after {
background: linear-gradient(to right, transparent, var(--he-title-bar-active-pinned-bg));
}
.popover.hover-editor.is-pinned.is-pinned .popover-title:after {
background: linear-gradient(to right, transparent, var(--he-title-bar-inactive-pinned-bg));
}
.popover.hover-editor .popover-title:after {
content: " ";
position: absolute;
top: 0;
right: 0;
width: 30px;
height: 100%;
background: linear-gradient(to right, transparent, var(--he-title-bar-inactive-bg));
}
.popover.hover-editor .mod-show-navbar svg {
transform: rotate(90deg);
}
.popover.hover-editor > .popover-content > .workspace-split {
height: calc(100% - var(--he-title-bar-height));
}
.popover.hover-editor .view-header {
border-top: none;
transition: all var(--he-popover-header-transition-speed);
display: flex;
}
/* Restore 1.5.x view header icons */
.view-header .view-header-icon {
display: none;
padding: var(--size-2-2);
margin-right: var(--size-2-3);
color: var(--text-muted);
align-self: center;
cursor: grab;
}
.view-header .view-header-icon:active {
cursor: grabbing;
}
.popover.hover-editor .view-header .view-header-icon {
display: flex;
}
.popover.hover-editor.show-navbar:not(.is-minimized) .popover-title {
opacity: 0;
}
.popover.hover-editor:not(.show-navbar) .view-header {
height: 0px;
overflow: hidden;
}
.popover.hover-editor.show-navbar .view-header {
/* theme devs: if you want to change the header height, you must do so by setting the --he-view-header-height variable */
/* if you don't use the variable, you will break internal measurement logic */
height: var(--he-view-header-height);
overflow: unset;
}
.popover.hover-editor:not(.show-navbar) .view-content {
height: 100%;
}
.popover.hover-editor .workspace-leaf-content[data-type="image"] .view-content {
padding: 0;
position: relative;
overflow: hidden;
}
.popover.hover-editor .workspace-leaf-content[data-type="image"] img {
display: block;
position: relative;
height: 100%;
width: 100%;
max-width: unset;
border-radius: 0;
}
body .popover.hover-editor .view-content {
/* theme devs: if you want to change the header height, you must do so by setting the --he-view-header-height variable */
/* if you don't use the variable, you will break internal measurement logic */
height: calc(100% - var(--he-view-header-height));
}
/* start: zoomable images feature */
.popover.hover-editor.image-zoom .view-content .image-embed:active {
aspect-ratio: unset;
cursor: zoom-out;
display: block;
z-index: 200;
position: fixed;
max-height: calc(100% + 1px);
max-width: 100%;
height: calc(100% + 1px);
width: 100%;
object-fit: contain;
margin: -0.5px auto 0;
text-align: center;
padding: 0;
left: 0;
right: 0;
bottom: 0;
max-width: unset;
}
/* extra specificity to override some community theme styles that cause issues */
.popover.hover-editor.image-zoom .view-content .image-embed img:active {
top: 50%;
z-index: 99;
transform: translateY(-50%);
padding: 0;
margin: 0 auto;
width: calc(100% - 20px);
height: unset;
max-height: 95vh;
object-fit: contain;
left: 0;
right: 0;
bottom: 0;
position: absolute;
opacity: 1;
max-width: unset;
max-height: 100%;
}
.popover.hover-editor.image-zoom .view-content .image-embed:active:after {
background-color: var(--background-primary);
opacity: 0.9;
content: " ";
height: calc(100% + 1px);
width: 100%;
position: fixed;
left: 0;
right: 1px;
z-index: 0;
}
.popover.hover-editor.image-zoom .view-content img {
cursor: zoom-in;
}
/* extra specificity to override some community theme styles that cause issues */
.popover.hover-editor.image-zoom .workspace-leaf-content[data-type="image"] img {
cursor: zoom-in;
top: 50%;
transform: translateY(-50%);
object-fit: contain;
height: unset;
left: 0;
right: 0;
bottom: 0;
position: absolute;
opacity: 1;
max-height: 100%;
}
/* end: zoomable images feature */

View File

@@ -0,0 +1,158 @@
{
"remoteType": "",
"useCustomRequestHandler": false,
"couchDB_URI": "",
"couchDB_USER": "",
"couchDB_PASSWORD": "",
"couchDB_DBNAME": "",
"liveSync": false,
"syncOnSave": true,
"syncOnStart": true,
"savingDelay": 200,
"lessInformationInLog": false,
"gcDelay": 0,
"versionUpFlash": "",
"minimumChunkSize": 20,
"longLineThreshold": 250,
"showVerboseLog": false,
"suspendFileWatching": false,
"trashInsteadDelete": true,
"periodicReplication": true,
"periodicReplicationInterval": 60,
"syncOnFileOpen": true,
"encrypt": false,
"passphrase": "",
"usePathObfuscation": false,
"doNotDeleteFolder": false,
"resolveConflictsByNewerFile": false,
"batchSave": true,
"batchSaveMinimumDelay": 5,
"batchSaveMaximumDelay": 60,
"deviceAndVaultName": "",
"usePluginSettings": false,
"showOwnPlugins": false,
"showStatusOnEditor": true,
"showStatusOnStatusbar": true,
"showOnlyIconsOnEditor": false,
"hideFileWarningNotice": false,
"usePluginSync": false,
"autoSweepPlugins": false,
"autoSweepPluginsPeriodic": false,
"notifyPluginOrSettingUpdated": false,
"checkIntegrityOnSave": false,
"batch_size": 25,
"batches_limit": 25,
"useHistory": true,
"disableRequestURI": true,
"skipOlderFilesOnSync": true,
"checkConflictOnlyOnOpen": false,
"showMergeDialogOnlyOnActive": false,
"syncInternalFiles": false,
"syncInternalFilesBeforeReplication": false,
"syncInternalFilesIgnorePatterns": "\\/node_modules\\/, \\/\\.git\\/, \\/obsidian-livesync\\/",
"syncInternalFilesTargetPatterns": "",
"syncInternalFilesInterval": 60,
"additionalSuffixOfDatabaseName": "421f688ab570b23d",
"ignoreVersionCheck": false,
"lastReadUpdates": 25,
"deleteMetadataOfDeletedFiles": false,
"syncIgnoreRegEx": "",
"syncOnlyRegEx": "",
"customChunkSize": 60,
"readChunksOnline": true,
"watchInternalFileChanges": true,
"automaticallyDeleteMetadataOfDeletedFiles": 0,
"disableMarkdownAutoMerge": false,
"writeDocumentsIfConflicted": false,
"useDynamicIterationCount": false,
"syncAfterMerge": true,
"configPassphraseStore": "",
"encryptedPassphrase": "",
"encryptedCouchDBConnection": "%$Bh465+EFQMTElwFFSDGASKI1SLpAExbeorlbZRkteweG3W2aZo9y25x4kbHgwa+9MNvE7ALlSWzLpSh7vriIQ8CZBeJeOgrv8b2DWVhDFOo42t0hScnVRlzhmaXERAzgvlBmMW9DxhV3oNPFDM3Q2leCEpAVGRhOhVJrp68emgdQOYQ5xVRWVAAwxvp/sWL1O6nerkxFH2hvA+AUPp05alJ9tycmVWPUKwclnoDknBfW5k9Ft90nPpcX9EgAO6IRMlp8X5bD0a26g1ti0ImFiA7Qi/1kl+Ymi7rDtzQEODtqhs5BPDHf/7oTU/MBWywlRiNOw22341Fvi+EvJb4QqZPFLUfwlrXCq81CTCrhV59kcl+s+IrWr8Wroo/cbbifyLjQ9IDYCeUHwe4lbWI0fGgjUJUAbWiRDAU8stifNwHON/PNyFd2/FR+e8PETbmWMxH7vuHjEPs8INUEvKiMOVZ7k0jwWM5xro8zGCYOYVmd5pInOXmHjypr3StPtXvgS2eOizsPZRrMsKlJ8gkcgHK32gOcBGwWVZ2iUkaP9vl6DztLB/uf2zgjTnlNk8MCtE4SAXSag1ipu/V6LVTzGmAkZT0VdG9TxzvDIaNHWhvvk1PekzagIU08xiAyh2Tin+hP6YJEujJ7S9jOn1//PuayuGFeD0KExmj7jxnrVvgN4QtrtO0b8/EqRni5qtzRVRslDpqhFuw=",
"permitEmptyPassphrase": false,
"useIndexedDBAdapter": true,
"useTimeouts": false,
"writeLogToTheFile": false,
"doNotPaceReplication": false,
"hashCacheMaxCount": 300,
"hashCacheMaxAmount": 50,
"concurrencyOfReadChunksOnline": 30,
"minimumIntervalOfReadChunksOnline": 25,
"hashAlg": "xxhash64",
"suspendParseReplicationResult": false,
"doNotSuspendOnFetching": false,
"useIgnoreFiles": false,
"ignoreFiles": ".gitignore",
"syncOnEditorSave": true,
"pluginSyncExtendedSetting": {},
"syncMaxSizeInMB": 50,
"settingSyncFile": "",
"writeCredentialsForSettingSync": false,
"notifyAllSettingSyncFile": false,
"isConfigured": true,
"settingVersion": 10,
"enableCompression": false,
"accessKey": "",
"bucket": "",
"endpoint": "",
"region": "",
"secretKey": "",
"useEden": false,
"maxChunksInEden": 10,
"maxTotalLengthInEden": 1024,
"maxAgeInEden": 10,
"disableCheckingConfigMismatch": false,
"displayLanguage": "zh",
"enableChunkSplitterV2": false,
"disableWorkerForGeneratingChunks": false,
"processSmallFilesInUIThread": false,
"notifyThresholdOfRemoteStorageSize": 0,
"usePluginSyncV2": true,
"usePluginEtc": false,
"handleFilenameCaseSensitive": false,
"doNotUseFixedRevisionForChunks": true,
"showLongerLogInsideEditor": false,
"sendChunksBulk": false,
"sendChunksBulkMaxSize": 1,
"useSegmenter": false,
"useAdvancedMode": false,
"usePowerUserMode": false,
"useEdgeCaseMode": false,
"enableDebugTools": false,
"suppressNotifyHiddenFilesChange": false,
"syncMinimumInterval": 2000,
"P2P_Enabled": false,
"P2P_AutoAccepting": 0,
"P2P_AppID": "self-hosted-livesync",
"P2P_roomID": "",
"P2P_passphrase": "",
"P2P_relays": "wss://exp-relay.vrtmrz.net/",
"P2P_AutoBroadcast": false,
"P2P_AutoStart": false,
"P2P_AutoSyncPeers": "",
"P2P_AutoWatchPeers": "",
"P2P_SyncOnReplication": "",
"P2P_RebuildFrom": "",
"P2P_AutoAcceptingPeers": "",
"P2P_AutoDenyingPeers": "",
"P2P_IsHeadless": false,
"doctorProcessedVersion": "0.25.0",
"bucketCustomHeaders": "",
"couchDB_CustomHeaders": "",
"useJWT": false,
"jwtAlgorithm": "",
"jwtKey": "",
"jwtKid": "",
"jwtSub": "",
"jwtExpDuration": 5,
"useRequestAPI": false,
"bucketPrefix": "",
"chunkSplitterVersion": "",
"E2EEAlgorithm": "",
"processSizeMismatchedFiles": false,
"forcePathStyle": true,
"configPassphrase": "",
"preset": "",
"syncMode": "ONEVENTS",
"dummy": 0
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
{
"id": "obsidian-livesync",
"name": "Self-hosted LiveSync",
"version": "0.25.16",
"minAppVersion": "0.9.12",
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
"author": "vorotamoroz",
"authorUrl": "https://github.com/vrtmrz",
"isDesktopOnly": false
}

View File

@@ -0,0 +1,472 @@
.added {
color: var(--text-on-accent);
background-color: var(--text-accent);
}
.normal {
color: var(--text-normal);
}
.deleted {
color: var(--text-on-accent);
background-color: var(--text-muted);
}
.conflict-dev-name {
display: inline-block;
min-width: 5em;
}
.op-scrollable {
overflow-y: scroll;
/* min-height: 280px; */
max-height: 280px;
user-select: text;
-webkit-user-select: text;
}
.op-pre {
white-space: pre-wrap;
}
.op-warn {
border: 1px solid salmon;
padding: 2px;
border-radius: 4px;
}
.op-warn::before {
content: "Warning";
font-weight: bold;
color: salmon;
position: relative;
display: block;
}
.op-warn-info {
border: 1px solid rgb(255, 209, 81);
padding: 2px;
border-radius: 4px;
}
.op-warn-info::before {
content: "Notice";
font-weight: bold;
color: rgb(255, 209, 81);
position: relative;
display: block;
}
.syncstatusbar {
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.tcenter {
text-align: center;
}
.sls-plugins-wrap {
display: flex;
flex-grow: 1;
max-height: 50vh;
overflow-y: scroll;
}
.sls-plugins-tbl {
border: 1px solid var(--background-modifier-border);
width: 100%;
max-height: 80%;
}
.divider th {
border-top: 1px solid var(--background-modifier-border);
}
.sls-header-button {
margin-left: 2em;
}
.sls-hidden {
display: none;
}
:root {
--sls-log-text: "";
}
.sls-troubleshoot-preview {
max-width: max-content;
}
.sls-troubleshoot-preview img {
max-width: 100%;
}
.sls-setting-tab {
display: none;
}
div.sls-setting-menu-btn {
color: var(--text-normal);
background-color: var(--background-secondary-alt);
border-radius: 4px 4px 0 0;
padding: 6px 10px;
cursor: pointer;
margin-right: 12px;
font-family: "Inter", sans-serif;
outline: none;
user-select: none;
flex-grow: 1;
text-align: center;
flex-shrink: 1;
}
.sls-setting-label.selected {
/* order: 1; */
flex-grow: 1;
/* width: 100%; */
}
.sls-setting-tab:hover~div.sls-setting-menu-btn,
.sls-setting-label.selected .sls-setting-tab:checked~div.sls-setting-menu-btn {
background-color: var(--interactive-accent);
color: var(--text-on-accent);
}
.sls-setting-menu-wrapper {
display: flex;
flex-direction: column;
flex-grow: 1;
position: sticky;
top: 0;
background-color: rgba(var(--background-primary), 0.3);
backdrop-filter: blur(4px);
border-radius: 4px;
z-index: 10;
}
.sls-setting-menu {
display: flex;
flex-direction: row;
overflow-x: auto;
}
body {
--sls-col-transparent: transparent;
--sls-col-warn: rgba(var(--background-modifier-error-rgb), 0.1);
--sls-col-warn-stripe1: var(--sls-col-transparent);
--sls-col-warn-stripe2: var(--sls-col-warn);
}
.sls-setting-menu-buttons {
border: 1px solid var(--sls-col-warn);
padding: 2px;
margin: 1px;
border-radius: 4px;
background-image: linear-gradient(-45deg,
var(--sls-col-warn-stripe1) 25%, var(--sls-col-warn-stripe2) 25%, var(--sls-col-warn-stripe2) 50%,
var(--sls-col-warn-stripe1) 50%, var(--sls-col-warn-stripe1) 75%, var(--sls-col-warn-stripe2) 75%, var(--sls-col-warn-stripe2));
background-size: 30px 30px;
display: flex;
flex-direction: row;
justify-content: flex-end;
padding: 0.5em 0.25em;
justify-content: center;
align-items: center;
/* transition: background-position 1s; */
animation: sls-scroll-warn 1s linear 0s infinite;
}
@keyframes sls-scroll-warn {
0% {
background-position: 0 0;
}
100% {
background-position: 30px 0;
}
}
.sls-setting-menu-buttons label {
margin-right: auto;
flex-grow: 1;
color: var(--text-warning);
}
.sls-setting-label {
flex-grow: 1;
display: inline-flex;
justify-content: center;
}
.setting-collapsed {
display: none;
}
.sls-plugins-tbl-buttons {
text-align: right;
}
.sls-plugins-tbl-buttons button {
flex-grow: 0;
padding: 6px 10px;
}
.sls-plugins-tbl-device-head {
background-color: var(--background-secondary-alt);
color: var(--text-accent);
}
.op-flex {
display: flex;
}
.op-flex input {
display: inline-flex;
flex-grow: 1;
margin-bottom: 8px;
}
.op-info {
display: inline-flex;
flex-grow: 1;
border-bottom: 1px solid var(--background-modifier-border);
width: 100%;
margin-bottom: 4px;
padding-bottom: 4px;
}
.history-added {
color: var(--text-on-accent);
background-color: var(--text-accent);
}
.history-normal {
color: var(--text-normal);
}
.history-deleted {
color: var(--text-on-accent);
background-color: var(--text-muted);
text-decoration: line-through;
}
.ob-btn-config-fix label {
margin-right: 40px;
}
.ob-btn-config-info {
border: 1px solid salmon;
padding: 2px;
margin: 1px;
border-radius: 4px;
}
.ob-btn-config-head {
padding: 2px;
margin: 1px;
border-radius: 4px;
}
.isWizard .wizardHidden {
display: none;
}
.sls-setting:not(.isWizard) .wizardOnly {
display: none;
}
.sls-item-dirty::before {
content: "✏";
}
.sls-item-dirty-help::after {
content: " ❓";
}
.sls-item-invalid-value {
background-color: rgba(var(--background-modifier-error-rgb), 0.3) !important;
}
.sls-setting-disabled input[type=text],
.sls-setting-disabled input[type=number],
.sls-setting-disabled input[type=password] {
filter: brightness(80%);
color: var(--text-muted);
}
.sls-setting-hidden {
display: none;
}
.sls-setting-obsolete {
background-image: linear-gradient(-45deg,
var(--sls-col-warn-stripe1) 25%, var(--sls-col-warn-stripe2) 25%, var(--sls-col-warn-stripe2) 50%,
var(--sls-col-warn-stripe1) 50%, var(--sls-col-warn-stripe1) 75%, var(--sls-col-warn-stripe2) 75%, var(--sls-col-warn-stripe2));
background-image: linear-gradient(-45deg,
transparent 25%, rgba(var(--background-secondary), 0.1) 25%, rgba(var(--background-secondary), 0.1) 50%, transparent 50%, transparent 75%, rgba(var(--background-secondary), 0.1) 75%, rgba(var(--background-secondary), 0.1));
background-size: 60px 60px;
}
.password-input>.setting-item-control>input {
-webkit-text-security: disc;
}
span.ls-mark-cr::after {
user-select: none;
content: "↲";
color: var(--text-muted);
font-size: 0.8em;
}
.deleted span.ls-mark-cr::after {
color: var(--text-on-accent);
}
.ls-imgdiff-wrap {
display: flex;
justify-content: center;
align-items: center;
}
.ls-imgdiff-wrap .overlay {
position: relative;
}
.ls-imgdiff-wrap .overlay .img-base {
position: relative;
top: 0;
left: 0;
}
.ls-imgdiff-wrap .overlay .img-overlay {
-webkit-filter: invert(100%) opacity(50%);
filter: invert(100%) opacity(50%);
position: absolute;
top: 0;
left: 0;
animation: ls-blink-diff 0.5s cubic-bezier(0.4, 0, 1, 1) infinite alternate;
}
@keyframes ls-blink-diff {
0% {
opacity: 0;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.livesync-status {
user-select: none;
pointer-events: none;
height: auto;
min-height: 1em;
position: absolute;
background-color: transparent;
width: 100%;
padding: 10px;
padding-right: 16px;
top: var(--header-height);
z-index: calc(var(--layer-cover) + 1);
font-variant-numeric: tabular-nums;
tab-size: 4;
text-align: right;
white-space: pre-wrap;
display: inline-block;
color: var(--text-normal);
font-size: 80%;
}
div.workspace-leaf-content[data-type=bases] .livesync-status {
top: calc(var(--bases-header-height) + var(--header-height));
padding: 5px;
padding-right:18px;
}
.is-mobile div.workspace-leaf-content[data-type=bases] .livesync-status {
top: calc(var(--bases-header-height) + var(--view-header-height));
padding: 6px;
padding-right:18px;
}
.livesync-status div {
opacity: 0.6;
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}
.livesync-status .livesync-status-loghistory {
text-align: left;
opacity: 0.4;
}
.livesync-status div.livesync-status-messagearea {
opacity: 0.6;
color: var(--text-on-accent);
background: var(--background-modifier-error);
-webkit-filter: unset;
filter: unset;
}
.menu-setting-poweruser-disabled .sls-setting-poweruser {
display: none;
}
.menu-setting-advanced-disabled .sls-setting-advanced {
display: none;
}
.menu-setting-edgecase-disabled .sls-setting-edgecase {
display: none;
}
.sls-setting-panel-title {
position: sticky;
}
.sls-setting-panel-title {
top: 2em;
background-color: rgba(var(--background-primary), 0.3);
backdrop-filter: blur(4px);
border-radius: 30%;
}
.sls-dialogue-note-wrapper {
display: flex;
justify-content: flex-end;
align-items: center;
}
.sls-dialogue-note-countdown {
font-size: 0.8em;
}
.sls-qr {
display: flex;
justify-content: center;
align-items: center;
max-width: max-content;
}
.sls-keypair pre {
max-width: 100%;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-all;
}

View File

@@ -0,0 +1,40 @@
{
"Components@@CTA-BTN-enable": true,
"Components@@file-names-untrim": true,
"Components@@folder-font-bold": true,
"Components@@colorful-folder": true,
"Components@@file-icon-remove": false,
"Components@@outline-enhanced": true,
"Components@@new-tab-btn-select": "new-tab-btn-default",
"Components@@immersive-canvas": true,
"Components@@scrollbar-hide": true,
"Mobile@@drawer-phone-full-width": true,
"Mobile@@card-layout-pad-open": true,
"Plugin@@colorful-checkbox": true,
"Editor@@italic-color@@light": "#000000",
"Editor@@text-highlight-bg@@light": "#000000",
"Editor@@inline-code-normal@@light": "#000000",
"Editor@@link-color@@light": "#000000",
"Editor@@link-color-hover@@light": "#000000",
"Editor@@h1-weight": 900,
"Editor@@h2-weight": 850,
"Editor@@h3-weight": 800,
"Editor@@h4-weight": 750,
"Editor@@h5-weight": 700,
"Editor@@h6-weight": 650,
"Editor@@h6-divider-on": false,
"Editor@@h5-divider-on": false,
"Editor@@h4-divider-on": false,
"Editor@@h3-divider-on": false,
"Editor@@h2-divider-on": false,
"Editor@@h1-divider-on": false,
"Editor@@collapse-icon-restore": false,
"Editor@@inline-title-divider-remove": true,
"Editor@@text-align-justify": false,
"Editor@@bold-color@@dark": "#000000",
"Editor@@bold-color@@light": "#000000",
"Editor@@editor-grid-background-pattren": true,
"Editor@@border-focus-mode": false,
"Editor@@line-hover-indicator": true,
"Appearance-light@@card-layout-open-light": true
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
{
"id": "obsidian-style-settings",
"name": "Style Settings",
"version": "1.0.9",
"minAppVersion": "0.11.5",
"description": "Offers controls for adjusting theme, plugin, and snippet CSS variables.",
"author": "mgmeyers",
"authorUrl": "https://github.com/mgmeyers/obsidian-style-settings",
"isDesktopOnly": false
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
{
"id": "templater-obsidian",
"name": "Templater",
"version": "2.14.1",
"description": "Create and use templates",
"minAppVersion": "1.5.0",
"author": "SilentVoid",
"authorUrl": "https://github.com/SilentVoid13",
"helpUrl": "https://silentvoid13.github.io/Templater/",
"isDesktopOnly": false
}

View File

@@ -0,0 +1,220 @@
.templater_search {
width: calc(100% - 20px);
}
.templater_div {
border-top: 1px solid var(--background-modifier-border);
}
.templater_div > .setting-item {
border-top: none !important;
align-self: center;
}
.templater_div > .setting-item > .setting-item-control {
justify-content: space-around;
padding: 0;
width: 100%;
}
.templater_div
> .setting-item
> .setting-item-control
> .setting-editor-extra-setting-button {
align-self: center;
}
.templater_donating {
margin: 10px;
}
.templater_title {
margin: 0;
padding: 0;
margin-top: 5px;
text-align: center;
}
.templater_template {
align-self: center;
margin-left: 5px;
margin-right: 5px;
width: 70%;
}
.templater_cmd {
margin-left: 5px;
margin-right: 5px;
font-size: 14px;
width: 100%;
}
.templater_div2 > .setting-item {
align-content: center;
justify-content: center;
}
.templater-prompt-div {
display: flex;
}
.templater-prompt-form {
display: flex;
flex-grow: 1;
}
.templater-prompt-input {
flex-grow: 1;
}
.templater-button-div {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 1rem;
}
textarea.templater-prompt-input {
height: 10rem;
}
textarea.templater-prompt-input:focus {
border-color: var(--interactive-accent);
}
.cm-s-obsidian .templater-command-bg {
left: 0px;
right: 0px;
background-color: var(--background-primary-alt);
}
.cm-s-obsidian .cm-templater-command {
font-size: 0.85em;
font-family: var(--font-monospace);
line-height: 1.3;
}
.cm-s-obsidian .templater-inline .cm-templater-command {
background-color: var(--background-primary-alt);
}
.cm-s-obsidian .cm-templater-command.cm-templater-opening-tag {
font-weight: bold;
}
.cm-s-obsidian .cm-templater-command.cm-templater-closing-tag {
font-weight: bold;
}
.cm-s-obsidian .cm-templater-command.cm-templater-interpolation-tag {
color: var(--code-property, #008bff);
}
.cm-s-obsidian .cm-templater-command.cm-templater-execution-tag {
color: var(--code-function, #c0d700);
}
.cm-s-obsidian .cm-templater-command.cm-keyword {
color: var(--code-keyword, #00a7aa);
font-weight: normal;
}
.cm-s-obsidian .cm-templater-command.cm-atom {
color: var(--code-normal, #f39b35);
}
.cm-s-obsidian .cm-templater-command.cm-value,
.cm-s-obsidian .cm-templater-command.cm-number,
.cm-s-obsidian .cm-templater-command.cm-type {
color: var(--code-value, #a06fca);
}
.cm-s-obsidian .cm-templater-command.cm-def,
.cm-s-obsidian .cm-templater-command.cm-type.cm-def {
color: var(--code-normal, var(--text-normal));
}
.cm-s-obsidian .cm-templater-command.cm-property,
.cm-s-obsidian .cm-templater-command.cm-property.cm-def,
.cm-s-obsidian .cm-templater-command.cm-attribute {
color: var(--code-function, #98e342);
}
.cm-s-obsidian .cm-templater-command.cm-variable,
.cm-s-obsidian .cm-templater-command.cm-variable-2,
.cm-s-obsidian .cm-templater-command.cm-variable-3,
.cm-s-obsidian .cm-templater-command.cm-meta {
color: var(--code-property, #d4d4d4);
}
.cm-s-obsidian .cm-templater-command.cm-callee,
.cm-s-obsidian .cm-templater-command.cm-operator,
.cm-s-obsidian .cm-templater-command.cm-qualifier,
.cm-s-obsidian .cm-templater-command.cm-builtin {
color: var(--code-operator, #fc4384);
}
.cm-s-obsidian .cm-templater-command.cm-tag {
color: var(--code-tag, #fc4384);
}
.cm-s-obsidian .cm-templater-command.cm-comment,
.cm-s-obsidian .cm-templater-command.cm-comment.cm-tag,
.cm-s-obsidian .cm-templater-command.cm-comment.cm-attribute {
color: var(--code-comment, #696d70);
}
.cm-s-obsidian .cm-templater-command.cm-string,
.cm-s-obsidian .cm-templater-command.cm-string-2 {
color: var(--code-string, #e6db74);
}
.cm-s-obsidian .cm-templater-command.cm-header,
.cm-s-obsidian .cm-templater-command.cm-hr {
color: var(--code-keyword, #da7dae);
}
.cm-s-obsidian .cm-templater-command.cm-link {
color: var(--code-normal, #696d70);
}
.cm-s-obsidian .cm-templater-command.cm-error {
border-bottom: 1px solid #c42412;
}
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}

View File

@@ -0,0 +1,7 @@
{
"name": "Border",
"version": "1.12.20",
"minAppVersion": "0.16.0",
"author": "Akifyss",
"authorUrl": "https://github.com/Akifyss"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
{
"name": "GitHub Theme",
"version": "1.1.6",
"minAppVersion": "1.0.0",
"author": "@krios2146",
"authorUrl": "https://github.com/krios2146"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
{
"name": "Minimal",
"version": "8.0.4",
"minAppVersion": "1.9.0",
"author": "@kepano",
"authorUrl": "https://twitter.com/kepano",
"fundingUrl": "https://www.buymeacoffee.com/kepano"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,204 @@
{
"main": {
"id": "0d497f6739ef6df9",
"type": "split",
"children": [
{
"id": "306ec49a61f877d3",
"type": "tabs",
"children": [
{
"id": "a93d6d3811397e7b",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "临时/代码片段.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "代码片段"
}
}
]
}
],
"direction": "vertical"
},
"left": {
"id": "dd92142da425da5d",
"type": "split",
"children": [
{
"id": "18712eeca302c86a",
"type": "tabs",
"children": [
{
"id": "f1c17e2d203acce4",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical",
"autoReveal": false
},
"icon": "lucide-folder-closed",
"title": "文件列表"
}
},
{
"id": "0d80743f19037256",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "NSSM",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabeticalReverse"
},
"icon": "lucide-search",
"title": "搜索"
}
},
{
"id": "29759c335a3c0889",
"type": "leaf",
"state": {
"type": "bookmarks",
"state": {},
"icon": "lucide-bookmark",
"title": "书签"
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "a00fc03fc4170f30",
"type": "split",
"children": [
{
"id": "553118af57cf253c",
"type": "tabs",
"children": [
{
"id": "330eb3c82c280cae",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "树萌芽的小本本/树萌芽已部署网站(不定时持续更新).md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
},
"icon": "links-coming-in",
"title": "树萌芽已部署网站(不定时持续更新) 的反向链接列表"
}
},
{
"id": "a11bb24aba14d458",
"type": "leaf",
"state": {
"type": "outgoing-link",
"state": {
"linksCollapsed": false,
"unlinkedCollapsed": true
},
"icon": "links-going-out",
"title": "出链"
}
},
{
"id": "66a43be089eb76fa",
"type": "leaf",
"state": {
"type": "tag",
"state": {
"sortOrder": "frequency",
"useHierarchy": true,
"showSearch": false,
"searchQuery": ""
},
"icon": "lucide-tags",
"title": "标签"
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
"switcher:打开快速切换": false,
"command-palette:打开命令面板": false,
"obsidian-livesync:Show Log": false,
"obsidian-livesync:Replicate": false,
"obsidian-livesync:P2P Replicator": false,
"obsidian-livesync:Show Customization sync": false
}
},
"active": "a93d6d3811397e7b",
"lastOpenFiles": [
"临时/Obsidion/Obsidion美化.md",
"临时/Obsidion",
"运维/nginx快速配置反向代理.md",
"临时/代码片段.md",
"计算机网络/计算机网络期末考试综合题简单论述.md",
"计算机科普/网络协议科普.md",
"计算机科普/科普-Nagle 算法.md",
"计算机科普/多模态大模型识别图片,视频,音频原理.md",
"计算机科普/操作系统科普.md",
"计算机科普/编程语言之间的划分.md",
"计算机科普/编程语言科普.md",
"AI/大语言模型的API 调用.md",
"AI/大语言模型的API key.md",
"AI/控制台AI大模型.md",
"Docker/优秀好用的Docker镜像/registry-轻量级自建Docker镜像仓库.md",
"内网穿透/Wireguard/Wireguard基础命令.md",
"生活科普/男生烫发术语.md",
"生活科普/中国免签知识科普.md",
"编程语言/Golang/Golang各平台编译教程.md",
"树萌芽的小本本/大萌芽-Debian13服务器.md",
"树萌芽的小本本/树萌芽国外身份.md",
"树萌芽的小本本/重要信息记录.md",
"Linux/随身WiFi/随身WiFi一些记录.md",
"树萌芽的小本本/树萌芽の编程想法.md",
"树萌芽的小本本/树萌芽の小秘密.md",
"树萌芽的小本本/树萌芽の吐槽.md",
"树萌芽的小本本/革命后的理想.md",
"编程语言/前端/代码片段",
"编程语言/前端/JavaScript趣味题",
"实习求职/面试经历",
"编程语言/前端",
"数据库/SQLite",
"数据库/MongoDB",
"数据库/MySQL",
"内网穿透/Wireguard/配置/wgs-alyxg.conf",
"内网穿透/Wireguard/配置/wgs-alycd.conf",
"Minecraft/基岩版服务器/NukkitLearn/images/5-04.png",
"Minecraft/基岩版服务器/NukkitLearn/images/5-03.png",
"Minecraft/基岩版服务器/NukkitLearn/images/5-02.png",
"Minecraft/基岩版服务器/NukkitLearn/images/5-01.png",
"Minecraft/基岩版服务器/NukkitLearn/images/2-01.png",
"Minecraft/基岩版服务器/NukkitLearn/images/1-10.png",
"Minecraft/基岩版服务器/NukkitLearn/images/1-09.png",
"Minecraft/基岩版服务器/NukkitLearn/images/1-08.png",
"Minecraft/基岩版服务器/NukkitLearn/images/1-07.png",
"Minecraft/基岩版服务器/NukkitLearn/images/1-06.png"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

View File

@@ -0,0 +1,126 @@
以下是你提到的英语词汇及其翻译和音标。我已经为其添加了音标并将其排版成HTML和CSS格式。
### 英语词汇及翻译
| 英文词汇 | 翻译 | 音标 |
| :------------------------------------------------ | :----------------------- | :------------------------------------------------- |
| hands | 手 | /hændz/ |
| butterflies in the stomach | 肚子里的蝴蝶 | /ˈbʌtərflaɪz ɪn ðə ˈstʌmək/ |
| muscle tension | 肌肉紧张 | /ˈmʌsl ˈtɛnʃən/ |
| credit | 学分 / 信用 | /ˈkrɛdɪt/ |
| major | 主修 / 专业 | /ˈmeɪdʒər/ |
| major in | 主修 | /ˈmeɪdʒər ɪn/ |
| dropout | 辍学 | /ˈdrɔpˌaʊt/ |
| trigger | 诱因 / 扳机 | /ˈtrɪɡər/ |
| resilience | 弹性 | /rɪˈzɪljəns/ |
| cyberlove | 网恋 | /ˈsaɪbərləv/ |
| long-distance relationship | 异地恋 | /lɔŋ ˈdɪstəns rɪˌleɪʃənˈʃɪp/ |
| date | 日期 / 约会 | /deɪt/ |
| lovesick | 恋爱中的病 | /ˈlʌvˌsɪk/ |
| zodiac | 星座 | /ˈzoʊ.dɪ.æk/ |
| aquaman | 水行侠 | /ˈækwəˌmæn/ |
| aquarium | 水族馆 | /əˈkwɛərɪəm/ |
| pilgrim | 朝圣者 | /ˈpɪlɡrɪm/ |
| soul | 灵魂 | /soʊl/ |
| bar | 酒吧 | /bɑr/ |
| soap bar | 香皂 | /soʊp bɑr/ |
| behind the bars | 在监狱里 | /bɪˈhaɪnd ðə bɑrz/ |
| enjoy each other's company | 享受彼此的陪伴 | /ɪnˈdʒɔɪˈʌðərz ˈkʌmpəni/ |
| crush | 暗恋 | /krʌʃ/ |
| have a crush on | 对某人有好感 | /hæv ə krʌʃ ɑn/ |
| idol | 偶像 | /ˈaɪdəl/ |
| icon | 图标 / 偶像 | /ˈaɪˌkɒn/ |
| ideal | 理想 | /aɪˈdɪəl/ |
| idea | 主意 | /aɪˈdɪə/ |
| idiot | 傻瓜 | /ˈɪdiət/ |
| marketing campaign | 营销活动 | /ˈmɑrkɪtɪŋ kæmˈpeɪn/ |
| being in love implies that you can fall out of it | 恋爱意味着你可能会失去爱 | /ˈbiːɪŋ ɪn lʌv ɪmˈplaɪz ðæt juː kæn fɔl aʊt ʌv ɪt/ |
| -wise | 方面的 | /waɪz/ |
| family-wise | 从家庭的角度 | /ˈfæmɪli waɪz/ |
| better off | 过得更好 | /ˈbɛtər ɔf/ |
| big old kiss | 大大的吻 | /bɪɡ oʊld kɪs/ |
| vulnerable | 脆弱的 | /ˈvʌlnərəbəl/ |
### HTML/CSS 排版美化
```html
html<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>英语词汇及翻译</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f8f9fa;
margin: 0;
padding: 20px;
}
h1 {
text-align: center;
color: #333;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #007BFF;
color: white;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}
</style>
</head>
<body>
<h1>英语词汇及翻译</h1>
<table>
<tr>
<th>英文词汇</th>
<th>翻译</th>
<th>音标</th>
</tr>
<tr>
<td>hands</td>
<td></td>
<td>/hændz/</td>
</tr>
<tr>
<td>butterflies in the stomach</td>
<td>肚子里的蝴蝶</td>
<td>/ˈbʌtərflaɪz ɪn ðə ˈstʌmək/</td>
</tr>
<tr>
<td>muscle tension</td>
<td>肌肉紧张</td>
<td>/ˈmʌsl ˈtɛnʃən/</td>
</tr>
<!-- 可以继续添加其他词汇 -->
</table>
</body>
</html>
html
```
你可以将上述HTML代码复制到文本编辑器中然后另存为`.html`文件,以在浏览器中打开并查看效果。如果有其他需求或需要进一步的帮助,请告知我!

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

View File

@@ -0,0 +1,13 @@
- [x] 更新修复一下萌芽软件库网站
- [ ] 重新搭建萌芽软件库,萌芽软件更新后台 两个网站并封装成Docker
- [x] 继续学数据库特别是MongoDBMySQL
- [x] 继续学计算机网络
- [ ] 练习华为ICT
- [ ] 完成树萌芽个人主页shumengya.top
- [ ] LeetCode刷题
- [ ] 学习Python
- [x] 做一个flutter软件学习一下flutter
- [ ] 做一个uniapp软件学习一下uniapp
- [ ] 做一个微信小程序,学习一下微信开发者工具

View 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. 聊聊天

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -0,0 +1,236 @@
### 1. **基本命令**
- **连接设备**
```bash
adb devices
```
列出连接的设备显示设备ID和状态。
- **启动ADB服务器**
```bash
adb start-server
```
启动ADB服务。
- **停止ADB服务器**
```bash
adb kill-server
```
停止ADB服务。
### 2. **设备管理**
- **查看设备信息**
```bash
adb shell getprop
```
获取设备的各种信息如型号、Android版本等
- **重启设备**
```bash
adb reboot
```
重新启动设备。
- **重启到bootloader**
```bash
adb reboot bootloader
```
将设备重启到bootloader模式用于解锁、刷机等
- **进入恢复模式**
```bash
adb reboot recovery
```
重新启动设备并进入恢复模式。
### 3. **文件传输**
- **从设备拷贝文件到电脑**
```bash
adb pull <设备路径> <本地路径>
```
例如:
```bash
adb pull /sdcard/test.txt ./test.txt
```
- **从电脑拷贝文件到设备**
```bash
adb push <本地路径> <设备路径>
```
例如:
```bash
adb push test.txt /sdcard/
```
### 4. **执行命令**
- **进入设备的Shell**
```bash
adb shell
```
进入设备的命令行界面可以执行Linux命令。
- **执行单个命令**
```bash
adb shell <命令>
```
例如,查看设备的文件系统:
```bash
adb shell ls /sdcard/
```
### 5. **应用管理**
- **安装应用**
```bash
adb install <apk文件路径>
```
例如:
```bash
adb install app.apk
```
- **卸载应用**
```bash
adb uninstall <包名>
```
例如:
```bash
adb uninstall com.example.app
```
- **列出所有已安装的应用**
```bash
adb shell pm list packages
```
- **清除应用数据**
```bash
adb shell pm clear <包名>
```
例如:
```bash
adb shell pm clear com.example.app
```
### 6. **日志与调试**
- **查看日志输出**
```bash
adb logcat
```
实时显示设备的日志输出,常用于调试。
- **过滤日志**
```bash
adb logcat <标签>:<等级>
```
例如:
```bash
adb logcat *:E
```
显示所有错误级别Error及以上的日志。
- **查看设备的进程**
```bash
adb shell ps
```
### 7. **屏幕截图与录屏**
- **截取屏幕截图**
```bash
adb shell screencap /sdcard/screenshot.png
```
将截图保存到设备存储中。
- **录制屏幕视频**
```bash
adb shell screenrecord /sdcard/demo.mp4
```
### 8. **开发与调试**
- **开启开发者选项与USB调试**
需要在设备的设置里开启开发者选项并启用USB调试。
- **远程调试**
```bash
adb tcpip 5555
```
让设备进入无线调试模式通过IP连接设备
- **连接到指定IP设备**
```bash
adb connect <设备IP>:5555
```
### 9. **设备状态与操作**
- **查看设备状态**
```bash
adb devices -l
```
- **查看设备的存储**
```bash
adb shell df
```
- **获取设备电池状态**
```bash
adb shell dumpsys battery
```
### 10. **其他常用命令**
- **获取设备信息(硬件、系统信息)**
```bash
adb shell dumpsys
```
- **查看设备的CPU使用情况**
```bash
adb shell top
```

View File

@@ -0,0 +1,13 @@
**shizuku**
```bash
adb shell sh /storage/emulated/0/Android/data/moe.shizuku.privileged.api/start.sh
sh /storage/emulated/0/Android/data/moe.shizuku.privileged.api/start.sh
```
**黑阈**
```bash
adb -d shell 'output=$(pm path me.piebridge.brevent); export CLASSPATH=${output#*:}; app_process /system/bin me.piebridge.brevent.server.BreventServer bootstrap; /system/bin/sh /data/local/tmp/brevent.sh'
output=$(pm path me.piebridge.brevent); export CLASSPATH=${output#*:}; app_process /system/bin me.piebridge.brevent.server.BreventServer bootstrap; /system/bin/sh /data/local/tmp/brevent.sh
```

View File

@@ -0,0 +1,194 @@
**添加:**
- [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] 添加客户端和服务器踢出玩家命令原因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] 添加客户端和服务器踢出玩家命令原因ban时长
- [ ] 服务器崩溃出错自动重启
- [x] 添加命令,/rename qq号 新昵称 给某个玩家重命名玩家昵称
- [x] 添加命令 /repasswd QQ号 重置某个玩家的密码为123456
- [x] 给远程控制台添加参数 设置 让用户
- [ ] 管理员用命令修改玩家信息时自动给玩家发送一次最新的玩家数据(全部)
- [ ] 添加一个按钮刷新获取最新的玩家数据设置10秒后才能点一次
- [x] 让AI把客户端UI场景美化一下 目前太丑了
- [ ] 添加一个彩蛋系统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] 玩家打开作物仓库的时候请求一次服务器
- [ ] 战斗胜利的偷菜计时器失效了
- [ ] 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] 玩家打开作物仓库的时候请求一次服务器
- [ ] 战斗胜利的偷菜计时器失效了
- [ ] UI做大一点手机端还是不好操作
- [ ] 弹窗UI连续显示时不够流畅
- [ ] 咖啡豆没有未成熟图片
- [x] 一键截图改成截图模式
- [x] 把野草禁止买卖
- [ ] 偷菜被发现强制扣金币一直扣到0为止不能出现负数金币
- [x] 访问别人玩家不能打开玩家的小卖部
- [ ] 设置稻草人所有内容最多只能20个字客户端限制
- [ ] 设置对玩家使用的道具可以批量使用
- [x] 设置批量出售作物超出最大值设置为最大值
- [ ] 修改智慧树每次登录也会刷新一句话
- [x] 点开道具背包,作物仓库,种子仓库,上报服务器刷新一下
- [ ] 宠物喂食完,使用道具后返回宠物信息面板
- [ ] 作物更新还是有问题,在考虑要不要直接退回到原来的每秒更新
- [x] 修复登录递归循环调用导致无法登录问题
- [ ] 修复点开账户设置时自动刷新一下
- [ ] 修复一下/playerinfo 查看玩家信息命令 目前显示不全而且有问题
- [ ] 把稻草人数据库配置改成无限句话

View File

@@ -0,0 +1,4 @@
- 随机一言Text
- 随机图片Image
- 随机音乐Music
- 随机视频Video

View File

@@ -0,0 +1,182 @@
---
## 🧩 一、卸载旧版本(如果你之前装过 5.7 或 MariaDB
为了避免冲突,建议先清理旧包:
```bash
sudo systemctl stop mysql || true
sudo apt remove --purge -y mysql-server mysql-client mysql-common mariadb-server mariadb-client mariadb-common
sudo apt autoremove --purge -y
sudo rm -rf /var/lib/mysql /etc/mysql
```
---
## ⚙️ 二、添加官方 MySQL APT 仓库
### 1⃣ 下载并安装配置包
```bash
wget https://dev.mysql.com/get/mysql-apt-config_0.8.36-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.36-1_all.deb
```
安装时会弹出交互菜单,请仔细选择:
- **MySQL Server & Cluster → mysql-8.4-lts**
- 其他(如 Tools、Connector 等)可保持默认。
然后退出(选择 “OK” 保存配置)。
---
## ⚙️ 三、更新并安装 MySQL 8.4 LTS
```bash
sudo apt update
sudo apt install -y mysql-server
```
这个命令会自动安装最新的 MySQL 8.4LTS 版),包含 `mysql-community-server` 和相关依赖。
---
## 🔍 四、验证安装
```bash
mysql --version
```
你应看到类似输出:
```
mysql Ver 8.4.2 for Linux on x86_64 (MySQL Community Server - GPL)
```
---
## 🧠 五、启动与开机自启
```bash
sudo systemctl enable mysql
sudo systemctl start mysql
sudo systemctl status mysql
```
如果输出里状态是 `active (running)` ✅,说明服务正常运行。
---
## 🔐 六、安全配置
执行官方安全脚本:
```bash
sudo mysql_secure_installation
```
它会引导你:
- 设置 root 密码
- 移除匿名用户
- 禁止 root 远程登录(可选)
- 删除 test 数据库
- 重载权限表
建议全部选择“是Y”。
---
## 🧭 七、登录测试
```bash
mysql -u root -p
```
输入刚刚设置的密码,进入后执行:
```sql
SELECT VERSION();
```
输出应为:
```
+-----------+
| VERSION() |
+-----------+
| 8.4.x |
+-----------+
```
---
## 🧰 八、(可选)修改 MySQL 配置文件
主配置路径:
```
/etc/mysql/mysql.conf.d/mysqld.cnf
```
如果你想修改端口、字符集等:
```bash
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
```
推荐添加以下配置以支持中文与 emoji
```ini
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
```
然后重启服务:
```bash
sudo systemctl restart mysql
```
---
## 🧱 九、测试端口与启动情况
```bash
ss -tunlp | grep mysql
```
输出类似:
```
tcp LISTEN 0 80 127.0.0.1:3306 *:* users:(("mysqld",pid=xxxx,fd=xxx))
```
说明 MySQL 已在 3306 端口监听。
---
## 🚀 十、总结
|项目|状态|
|---|---|
|系统|Debian 12 (Bookworm) ✅|
|MySQL 版本|8.4 LTS ✅|
|官方支持|完全兼容|
|安装难度|简单(无依赖冲突)|
|推荐用途|长期开发 / 生产环境|
---

View File

@@ -0,0 +1,171 @@
下面给出在 PostgreSQL PostgreSQL在 Debian 12 (Bookworm) 上安装及基本配置的**一步步教程**
---
## 前置条件
1. 已有一台 Debian 12 系统可以是物理机、VM、或者云上实例
2. 使用拥有 `sudo` 权限的用户登录。
3. 网络可访问外部软件源。
---
## 安装过程
### 1. 更新系统软件包
```bash
sudo apt update
sudo apt upgrade -y
```
这是一个好习惯,确保系统软件包为最新。
### 2. 安装 PostgreSQL
有两种方式:使用 Debian 默认仓库或使用官方 PostgreSQL 仓库。
#### 方法 A使用 Debian 默认仓库
```bash
sudo apt install -y postgresql postgresql-contrib
```
这会安装 PostgreSQL 及一些附加工具。
安装后,服务一般会自动启动。可用 `sudo systemctl status postgresql` 查看。
#### 方法 B使用 PostgreSQL 官方 PGDG 仓库(推荐如果你想安装特定版本)
1. 安装 `postgresql-common`(生成脚本等):
```bash
sudo apt install -y postgresql-common
```
2. 运行脚本将 PGDG 仓库添加到系统:
```bash
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
```
或者手动:导入签名密钥、创建 `/etc/apt/sources.list.d/pgdg.list`。
3. 更新软件包列表:
```bash
sudo apt update
```
4. 安装你想的版本,比如:
```bash
sudo apt install -y postgresql-18
```
(版本号根据仓库显示为止)
---
### 3. 检查服务状态 & 设置开机启动
```bash
sudo systemctl status postgresql
sudo systemctl enable postgresql
```
确认服务已运行并且开机启动。
---
### 4. 切换用户、设置 postgres 用户密码
安装完成后,系统默认创建一个系统用户 `postgres`,以及 PostgreSQL 内部用户 `postgres`。你可以切换并为它设密码:
```bash
sudo -i -u postgres
psql
\password postgres
\q
exit
```
这样为超级用户设置了密码。
---
### 5. 创建数据库和用户(基本操作)
切换为 `postgres` 用户后,在 psql 中执行:
```sql
CREATE DATABASE mydb;
CREATE USER myuser WITH PASSWORD 'strongpassword';
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
```
然后退出 `\q`。
你可以用以下方式连接:
```bash
psql -d mydb -U myuser -h localhost
```
---
### 6. 配置远程访问(如果你希望其他机器也能访问数据库)
默认 PostgreSQL 只监听本地 localhost。若要允许远程连接需要两步
1. 编辑 `postgresql.conf`,修改 listen_addresses
```bash
sudo nano /etc/postgresql/12/main/postgresql.conf
# 找到
listen_addresses = 'localhost'
# 改为
listen_addresses = '*'
```
然后保存。
2. 编辑 `pg_hba.conf`,允许特定 IP 或网段连接:
```bash
sudo nano /etc/postgresql/12/main/pg_hba.conf
# 添加一行,例如:
host all all 192.168.100.0/24 md5
```
然后重启服务:
```bash
sudo systemctl restart postgresql
```
> **警告**允许远程访问时要注意安全防火墙、强密码、只限可信IP
---
### 7. (可选)安装 pgAdmin4 图形管理工具
如果你更倾向图形界面管理数据库,可以考虑安装 pgAdmin 4。 ([HowtoForge](https://www.howtoforge.com/how-to-install-postgresql-and-pgadmin-tool-on-debian-12/?utm_source=chatgpt.com "How to Install PostgreSQL and pgAdmin Tool on Debian 12"))
大致步骤:添加 pgAdmin 仓库、安装 `pgadmin4-web`、运行配置脚本、然后通过浏览器访问管理界面。
---
### 8. 卸载或清理(如果需要)
如果你想移除 PostgreSQL建议使用 `purge` 而不仅仅 `remove`,以清理配置文件。有人经验如下:
> “使用 apt purge —purge … 然后 rm -rf 残余目录” ([Reddit](https://www.reddit.com/r/debian/comments/16cn3zx/how_to_properly_install_postgresql_remove_it_and/?utm_source=chatgpt.com "how to properly install postgresql, remove it, and install it again?"))
> 但在你的场景里(你打算长期使用 PostgreSQL通常不需要卸载。
---

View 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服务=================================
#=========================================================================
```

View 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 "所得杂记KCPQUICMQTT - 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 或兼容性问题。

View File

@@ -0,0 +1,117 @@
---
## 1) frps公网服务器配置
编辑 `frps.toml`,让 frps 监听一个 HTTP CONNECT 复用端口(你希望是 8022 就设 8022
```toml
bindPort = 7000
# 关键tcpmux 复用入口端口
tcpmuxHTTPConnectPort = 8022
```
重启 frps
这个 8022 **不是直接 SSH 端口**而是“HTTP CONNECT 复用入口”
---
## 2) 两台内网主机的 frpc 配置
### 主机 Abig.smy.top
`frpc.toml`
```toml
serverAddr = "你的公网IP"
serverPort = 7000
[[proxies]]
name = "ssh_big"
type = "tcpmux"
multiplexer = "httpconnect"
customDomains = ["big.smy.top"]
localIP = "127.0.0.1"
localPort = 22
```
### 主机 Bsmall.smy.top
`frpc.toml`
```toml
serverAddr = "你的公网IP"
serverPort = 7000
[[proxies]]
name = "ssh_small"
type = "tcpmux"
multiplexer = "httpconnect"
customDomains = ["small.smy.top"]
localIP = "127.0.0.1"
localPort = 22
```
`customDomains` 就是用来区分路由的域名键
---
## 3) DNS 解析
- `big.smy.top`
- `small.smy.top`
**A 记录解析到同一台公网 frps 的 IP**
---
## 4) 连接方式
因为 tcpmux 依赖 **HTTP CONNECT** 来告诉 frps 目标域名,所以你不能这样直连:
```bash
ssh big.smy.top -p 8022 # ❌ 这样 frps 不知道该转给谁
```
要用 ProxyCommand官方示例用 socat
```bash
ssh -o 'ProxyCommand=socat - PROXY:公网IP:%h:%p,proxyport=8022' test@big.smy.top
ssh -o 'ProxyCommand=socat - PROXY:公网IP:%h:%p,proxyport=8022' test@small.smy.top
```
frps 会根据 `%h`(也就是 big / small 域名)分流到对应主机
---
## 5) 更舒服的用法:写到你的 `~/.ssh/config`
```sshconfig
Host big
HostName big.smy.top
User test
ProxyCommand socat - PROXY:公网IP:%h:%p,proxyport=8022
Host small
HostName small.smy.top
User test
ProxyCommand socat - PROXY:公网IP:%h:%p,proxyport=8022
```
以后直接:
```bash
ssh big
ssh small
```
---
因为 SSH 本身无法携带“我要去哪个域名后端”的信息给 frps
tcpmux 是目前 frp 官方唯一的“同端口分流 SSH”方案
---

View 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趣味题网页版*

View 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趣味题网页版*

View 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趣味题网页版*

View File

@@ -0,0 +1,60 @@
游戏玩家数据储存在普通JSON文件和MongoDB中各有其适用场景二者的优缺点对比可结合游戏数据的特性如数据量、读写频率、结构灵活性、并发需求等展开分析
一、普通JSON文件储存
普通JSON文件储存指将玩家数据以JSON格式写入本地文件单文件或多文件如按玩家ID分文件依赖文件系统直接读写。
优点
1. 简单轻量,开发成本低
无需部署数据库服务直接通过编程语言的文件操作API如Python的 json 模块、Node.js的 fs 模块即可读写适合小型团队或开发初期快速验证功能学习成本几乎为0。
2. 资源占用少
仅依赖文件系统不消耗额外的数据库进程资源如内存、CPU适合设备性能有限的场景如单机小游戏、轻量网页游戏
3. 数据直观可见
JSON文件为文本格式可直接用编辑器打开查看或修改便于开发调试如临时修改玩家数据测试功能
缺点
1. 读写效率低,不适合大数据量
- 每次读写需加载整个JSON文件到内存解析或写入时覆盖整个文件当玩家数据量增大如10万+玩家单文件体积膨胀读写耗时会急剧增加例如加载100MB的JSON文件可能需要数百毫秒
- 若按玩家ID分文件虽能缓解单文件压力但批量查询如排行榜、全服统计需遍历所有文件效率极低。
2. 并发安全问题突出
多玩家同时操作时如多人在线游戏的并发读写文件系统缺乏原生锁机制易出现“写覆盖”如A玩家写入时B玩家同时写入导致其中一方数据丢失或数据损坏如写入中断导致JSON格式错误
3. 结构扩展性差
若玩家数据结构迭代如新增“宠物属性”“公会信息”需手动处理旧JSON文件的格式兼容如遍历所有文件添加新字段操作繁琐且易出错。
4. 缺乏数据一致性保障
无事务支持,例如玩家“扣金币+加道具”的原子操作,若中途程序崩溃,可能导致金币已扣但道具未加,数据不一致。
二、MongoDB储存
MongoDB是文档型NoSQL数据库以BSONJSON的二进制扩展格式存储数据天然适配半结构化的玩家数据。
优点
1. 高效读写与查询能力
- 支持索引如按玩家ID、等级建索引可快速定位单玩家数据毫秒级解决JSON文件全量解析的性能问题。
- 支持复杂查询(如“等级>50且在线的玩家”“道具列表包含某物品的玩家”适合游戏中的排行榜、好友列表、任务统计等场景。
2. 良好的并发与一致性
- 内置多版本并发控制MVCC支持高并发读写 thousands of TPS避免JSON文件的并发冲突。
- 支持事务MongoDB 4.0+),可保证“扣钱+加道具”“升级+解锁技能”等操作的原子性,防止数据不一致。
3. 灵活扩展,适配数据增长
- 玩家数据量随用户增长时,可通过“分片”横向扩展(将数据分布到多台服务器),支持百万级甚至亿级玩家数据。
- 文档结构动态灵活,新增字段无需修改表结构,旧数据可兼容(查询时自动忽略不存在的字段),适配游戏版本迭代。
4. 完善的数据管理能力
提供备份 mongodump 、恢复 mongorestore 、监控MongoDB Atlas等工具支持数据压缩、过期索引如清理离线玩家缓存适合长期运行的在线游戏。
缺点
1. 运维与学习成本高
需要部署、维护数据库服务如集群配置、索引优化、故障排查对小型团队可能增加运维压力开发人员需学习MongoDB的查询语法 find  aggregate 、索引设计等门槛高于JSON文件。
2. 资源占用较高
相比JSON文件MongoDB需要额外的内存缓存索引和热数据、CPU处理查询和磁盘空间数据文件+日志),不适合资源受限的极简场景(如嵌入式小游戏)。
3. 过度设计风险
对于单机游戏、玩家数极少如几百人且无复杂查询的场景MongoDB的优势无法体现反而因配置复杂降低开发效率。
总结:适用场景
- 普通JSON文件适合单人游戏、小型休闲游戏、开发测试阶段或数据量极小<1万玩家、读写频率低、无复杂查询的场景。
- MongoDB适合多人在线游戏MMO、MOBA等、中大型游戏或玩家数多>1万、需高频读写、复杂查询、结构迭代频繁的场景。
实际开发中也可根据规模过渡初期用JSON文件快速上线待用户增长后迁移至MongoDB利用其扩展性支撑业务。

View File

@@ -0,0 +1,126 @@
---
## 1. MySQL
### 登录命令
```bash
mysql -h <主机地址> -u <用户名> -p
```
例如:
```bash
mysql -h localhost -u root -p
```
然后系统会提示你输入密码。
你还可以指定数据库:
```bash
mysql -h localhost -u user_name -p 数据库名
```
(登录后直接使用该数据库)
### 注意事项
- 常见选项: `-h`(主机)、`-u`(用户名)、`-p`(提示输入密码)
- **为了安全**,建议使用 `-p` 而不直接在命令行后面写密码,因为其他用户可能通过进程列表看到。
- 登录后你就会进入 MySQL 的交互提示符,比如 `mysql>`,可以执行 SQL 语句。
---
## 2. PostgreSQL
### 登录命令
对于 PostgreSQL一般使用 `psql` 客户端。常用方式如下:
#### 本地切换为 postgres 系统用户然后登录
```bash
sudo -i -u postgres
psql
```
或者直接:
```bash
sudo -u postgres psql
```
这样你以系统用户 `postgres`PostgreSQL 默认超级用户)身份进入数据库。
#### 使用指定用户、数据库、主机登录
```bash
psql -U <用户名> -d <数据库名> -h <主机地址> -p <端口>
```
例如:
```bash
psql -U myuser -d mydb -h localhost -p 5432
```
### 注意事项
- 默认端口通常为 5432如果你使用了非标准端口则需指定 `-p`
- 用户 `postgres` 的 UNIX 账户通常是锁定的(不能用密码登录系统)——重点是用它来启动 `psql`
- 登录后提示符通常是 `postgres=#`(如果以超级用户身份)。
---
## 3. MongoDB
### 登录命令
以本地默认部署为例,使用 MongoDB shell比如 `mongosh`)登录:
```bash
mongosh
```
这会连接到 `mongodb://localhost:27017` 默认端口。
如果你需要指定主机、端口或用户认证:
```bash
mongosh --host <主机地址> --port <端口> --username <用户名> --password
```
或者使用连接字符串:
```bash
mongosh "mongodb://<用户名>@<主机地址>:<端口>/<数据库>" --password
```
### 在 shell 中认证用户
登录进入 shell 后,如果还未认证,可以使用:
```javascript
use <数据库名>;
db.auth("<用户名>", "<密码>");
```
或者只输入用户名让系统提示你输入密码:
```javascript
db.auth("<用户名>");
```
### 注意事项
- 默认端口为 27017。
- 当启用了访问控制authentication需要提供用户名和密码。否则可能会连接但不能执行特定操作。
---

View File

@@ -0,0 +1,96 @@
---
## 🔐 1. 在配置文件中设置密码
1. 打开 Redis 的主配置文件(假设你安装在 Debian 12 上,通常为 `/etc/redis/redis.conf`
```bash
sudo nano /etc/redis/redis.conf
```
2. 找到这一行(可能被注释 `#` 掉了):
```
# requirepass foobared
```
根据官方文档,这个 `requirepass` 指令就是用于开启 “旧式”统一密码认证机制。([Redis](https://redis.io/docs/latest/operate/oss_and_stack/management/security/?utm_source=chatgpt.com "Redis security | Docs"))
3. 去掉注释 `#`,并设置为你想要的强密码。例如:
```
requirepass YourStr0ngPassword!123
```
4. 保存并退出编辑器。
5. 重启 Redis 服务使新配置生效:
```bash
sudo systemctl restart redis-server
```
> 注意:如果你用的是 Redis 6+ 且希望使用更先进的用户/ACL机制也可以考虑使用 `acl setuser …` 等。但设置 `requirepass` 是最简单直接的方法。([Redis](https://redis.io/docs/latest/operate/oss_and_stack/management/security/?utm_source=chatgpt.com "Redis security | Docs"))
---
## 🧑‍💻 2. 使用 redis-cli 登录并认证
1. 在终端运行 Redis 命令行工具:
```bash
redis-cli
```
此时你可能会看到提示符,比如 `127.0.0.1:6379>`。如果已经设置了密码但还未认证,执行任何写操作会出现类似 `NOAUTH Authentication required.` 的错误。([Stack Overflow](https://stackoverflow.com/questions/7537905/how-to-set-password-for-redis?utm_source=chatgpt.com "How to set password for Redis? - Stack Overflow"))
2. 在提示符下输入认证命令:
```
AUTH YourStr0ngPassword!123
```
如果密码正确,会返回 `OK`。此后你就可以执行 `SET`, `GET` 等命令。([Redis](https://redis.io/docs/latest/commands/auth/?utm_source=chatgpt.com "AUTH | Docs - Redis"))
3. 你也可以在连接时直接带上密码,这样就省一步认证:
```bash
redis-cli -a YourStr0ngPassword!123
```
或者:
```bash
redis-cli -h 127.0.0.1 -p 6379 -a YourStr0ngPassword!123
```
([Stack Overflow](https://stackoverflow.com/questions/35745481/redis-cli-with-password?utm_source=chatgpt.com "Redis-cli with password - Stack Overflow"))
---
## ✅ 快速示例
假设你的密码是 `MyRedisPass123!`,步骤如下:
```bash
sudo nano /etc/redis/redis.conf
# 修改:
# requirepass MyRedisPass123!
requirepass MyRedisPass123!
sudo systemctl restart redis-server
redis-cli
127.0.0.1:6379> AUTH MyRedisPass123!
OK
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET foo bar
OK
127.0.0.1:6379> GET foo
"bar"
```
---

View File

@@ -0,0 +1,126 @@
# MarkDown书写规范
写文档好帮手,轻量级标记语言 Markdown
# 概述
## 起源
Markdown是[Daring Fireball](http://daringfireball.net/projects/markdown/syntax)的作者John Gruber发明身为Blogger可能他也觉得传统的HTML有些复杂吧退一步来讲若是一个毫无计算机基础的Blogger根本也没必要去掌握那些复杂的标签语言知识。
## 宗旨
Markdown 的目标是实现「易读易写」,成为一种适用于网络的书写语言。
可读性,无论如何,都是最重要的。一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响,包括 Setext、atx、Textile、reStructuredText、Grutatext 和 EtText而最大灵感来源其实是纯文本电子邮件的格式。
总之, Markdown 的语法全由一些符号所组成,这些符号经过精挑细选,其作用一目了然。比如:在文字两旁加上星号,看起来就像*强调*。Markdown 的列表看起来就是列表。Markdown 的区块引用看起来就真的像是引用一段文字,就像你曾在电子邮件中见过的那样。
# 全局规范
MarkDown 文件均使用```.md```作为后缀 *(小写字母)*
普通文本换行,使用行末尾```2空格```触发
## 发展
越来越多的软件和服务支持Markdown语法应该说Mac上大多数的写作软件都支持它。在线工具同样有很多如果你的博客基于Wordpress或是blogger它同样支持发布。
不仅仅是写博客一切文章都可以用Markdown语法来写比如说你想将一个标题加大字体只需要在相应文字前面加上一个#或是在它的下一行加上一些等号即可,还有比这更简单的调整格式方式吗?
# 语法参见
[官方语法说明](http://daringfireball.net/projects/markdown/syntax)
# 示例
---
## 标题
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
## 强调
- **粗体**
- _斜体_
## 引用
上面的横线用三个-表示
> 区块引用
## 列表
* red
* green
* blue
+ red
+ green
+ blue
- red
- green
- blue
1. red
2. green
3. blue
* 一个列表包含一个区块
> 区块内容
> 更多内容
## 代码
代码的插入方式 `printf('\n');`
```
function method()
{
alert("javascript");
}
```
```
class Test{
public static void main(String argc[]){
System.out.println("java");
}
}
```
```
class Test{
public static void main()
{
Console.WriteLine("C#");
}
}
```
## 链接
行内连接 [GitHub](https://github.com/) 的链接
## 图片
![shiyanlou logo](https://static.shiyanlou.com/img/logo_03.png)

View File

@@ -0,0 +1,5 @@
添加:
- [ ] 替换网站元素为Minecraft原版UI图片
- [ ] 加入Minecraft背景音乐c148
- [ ] 修改内容
- [ ] 打包成app离线访问

View File

@@ -0,0 +1,118 @@
除了索引之外MongoDB 在 CRUD 操作优化上还有多种有效策略,尤其在处理海量数据时更为关键。以下是综合各技术文档和实践总结的核心优化方法:
---
### 🔄 一、批量操作优化
1. **使用 `bulkWrite` 替代单条操作**
通过批量写入减少网络开销和事务开销。基于 `ReplaceOneModel` 启用 `upsert`,实现存在更新、不存在插入的高效操作:
```java
public void batchSave(List<?> dataList) {
List<ReplaceOneModel<Document>> bulkOps = dataList.stream()
.map(item -> {
Document doc = convertToDocument(item); // 转换为Document
return new ReplaceOneModel<>(
Filters.eq("_id", doc.get("_id")),
doc,
new UpdateOptions().upsert(true)
);
}).collect(Collectors.toList());
collection.bulkWrite(bulkOps); // 批量执行
}
```
此方法将多条操作合并为一次请求,写入性能提升显著。
---
### 📖 二、分页查询优化
1. **避免精确 `count`**
当数据量超大时,`count` 可能极慢。采用阈值法:若跳过 `MAX_PAGE_COUNT`如1万条后仍有数据则返回阈值提示“数据超过1万条”避免全表扫描
```java
private long approxCount(MongoTemplate mongoTemplate, Query query) {
query = query.with(PageRequest.of(MAX_PAGE_COUNT, 1));
return mongoTemplate.find(query, Entity.class).isEmpty()
? mongoTemplate.count(query)
: MAX_PAGE_COUNT;
}
```
2. **用条件替代 `skip`**
深度分页时如第100页避免 `skip(9900)`。改为记录上一页末尾的排序字段值(如时间戳),作为下一页查询条件:
```sql
-- 原查询db.collection.find().sort({time:-1}).skip(9900).limit(100)
-- 优化后:
db.collection.find({ time: { $lt: lastPageEndTime } })
.sort({ time: -1 })
.limit(100);
```
此方法将 **O(N)** 的跳过操作转为 **O(1)** 的条件过滤。
---
### 📤 三、全量导出优化
1. **字段投影减少数据传输**
仅查询必要字段,降低网络与内存开销:
```java
Query query = new Query();
query.fields().include("_id").include("name"); // 只返回_id和name。
```
2. **流式处理替代全量加载**
使用 `stream()` 逐条处理数据,避免 `findAll` 导致内存溢出:
```java
try (CloseableIterator<Entity> iter = mongoTemplate.stream(query, Entity.class)) {
while (iter.hasNext()) {
process(iter.next()); // 单条处理
}
}
```
相比分页查询,流式处理无 `skip` 开销,且内存占用恒定。
---
### 🧩 四、文档设计优化
1. **打破第三范式**
- **冗余字段**:将高频查询的关联字段(如部门名称)冗余到主文档,避免联表查询。
- **内嵌设计**一对多关系直接嵌套子文档如订单内嵌商品列表提升读取效率。但需注意文档大小限制16MB
- **引用设计**多对多关系使用ID数组而非完整嵌套避免文档膨胀
```json
// 学生文档
{
"_id": "s001",
"name": "Alice",
"teachers": ["t01", "t02"] // 仅存储ID
}
```
---
### ⚙️ 五、分片集群优化
1. **碎片整理MongoDB <7.0**
在早期版本中分片集合可能因频繁写入产生碎片化小数据块导致CRUD延迟。通过 `configureCollectionBalancing` 命令合并数据块,但需注意:
- 整理期间可能短暂阻塞元数据更新。
- MongoDB 7.0+ 已支持自动合并,通常无需手动操作。
2. **负载均衡窗口设置**
在业务低峰期触发负载均衡器迁移数据块减少对CRUD的影响。
---
### 💎 六、其他关键技巧
1. **合理控制事务范围**:短事务减少锁竞争。
2. **写入确认级别调整**:对非关键数据使用 `w:0`(无确认),提升写入速度(牺牲一致性)。
3. **TTL索引自动清理**:为临时数据(如日志)设置过期时间,减少存储压力。
---
### 💎 优化方法效果对比表
| **优化方向** | **适用场景** | **性能提升效果** | **实现复杂度** |
|--------------------|--------------------------|----------------------|--------------|
| **批量写入** | 数据导入、批量更新 | ⭐⭐⭐⭐⭐ (极高) | ⭐⭐ (中等) |
| **流式导出** | 大数据量导出 | ⭐⭐⭐⭐ (避免OOM) | ⭐ (简单) |
| **条件分页** | 深度分页(>100页 | ⭐⭐⭐⭐ (O(1) 跳转) | ⭐⭐ (中等) |
| **冗余字段** | 高频关联查询 | ⭐⭐⭐ (减少联表) | ⭐⭐⭐ (较高) |
| **分片碎片整理** | MongoDB 6.0以下分片集群 | ⭐⭐ (减少延迟) | ⭐⭐⭐⭐ (复杂) |
---
> 💡 **实践建议**:优先从**批量操作**和**分页策略**入手,这两类优化代码改动小且收益显著。海量数据场景下,**流式处理+字段投影**是导出标配方案。分片集群升级到 MongoDB 7.0+ 可减少运维负担。

View File

@@ -0,0 +1,118 @@
除了索引之外MongoDB 在 CRUD 操作优化上还有多种有效策略,尤其在处理海量数据时更为关键。以下是综合各技术文档和实践总结的核心优化方法:
---
### 🔄 一、批量操作优化
1. **使用 `bulkWrite` 替代单条操作**
通过批量写入减少网络开销和事务开销。基于 `ReplaceOneModel` 启用 `upsert`,实现存在更新、不存在插入的高效操作:
```java
public void batchSave(List<?> dataList) {
List<ReplaceOneModel<Document>> bulkOps = dataList.stream()
.map(item -> {
Document doc = convertToDocument(item); // 转换为Document
return new ReplaceOneModel<>(
Filters.eq("_id", doc.get("_id")),
doc,
new UpdateOptions().upsert(true)
);
}).collect(Collectors.toList());
collection.bulkWrite(bulkOps); // 批量执行
}
```
此方法将多条操作合并为一次请求,写入性能提升显著。
---
### 📖 二、分页查询优化
1. **避免精确 `count`**
当数据量超大时,`count` 可能极慢。采用阈值法:若跳过 `MAX_PAGE_COUNT`如1万条后仍有数据则返回阈值提示“数据超过1万条”避免全表扫描
```java
private long approxCount(MongoTemplate mongoTemplate, Query query) {
query = query.with(PageRequest.of(MAX_PAGE_COUNT, 1));
return mongoTemplate.find(query, Entity.class).isEmpty()
? mongoTemplate.count(query)
: MAX_PAGE_COUNT;
}
```
2. **用条件替代 `skip`**
深度分页时如第100页避免 `skip(9900)`。改为记录上一页末尾的排序字段值(如时间戳),作为下一页查询条件:
```sql
-- 原查询db.collection.find().sort({time:-1}).skip(9900).limit(100)
-- 优化后:
db.collection.find({ time: { $lt: lastPageEndTime } })
.sort({ time: -1 })
.limit(100);
```
此方法将 **O(N)** 的跳过操作转为 **O(1)** 的条件过滤。
---
### 📤 三、全量导出优化
1. **字段投影减少数据传输**
仅查询必要字段,降低网络与内存开销:
```java
Query query = new Query();
query.fields().include("_id").include("name"); // 只返回_id和name。
```
2. **流式处理替代全量加载**
使用 `stream()` 逐条处理数据,避免 `findAll` 导致内存溢出:
```java
try (CloseableIterator<Entity> iter = mongoTemplate.stream(query, Entity.class)) {
while (iter.hasNext()) {
process(iter.next()); // 单条处理
}
}
```
相比分页查询,流式处理无 `skip` 开销,且内存占用恒定。
---
### 🧩 四、文档设计优化
1. **打破第三范式**
- **冗余字段**:将高频查询的关联字段(如部门名称)冗余到主文档,避免联表查询。
- **内嵌设计**一对多关系直接嵌套子文档如订单内嵌商品列表提升读取效率。但需注意文档大小限制16MB
- **引用设计**多对多关系使用ID数组而非完整嵌套避免文档膨胀
```json
// 学生文档
{
"_id": "s001",
"name": "Alice",
"teachers": ["t01", "t02"] // 仅存储ID
}
```
---
### ⚙️ 五、分片集群优化
1. **碎片整理MongoDB <7.0**
在早期版本中分片集合可能因频繁写入产生碎片化小数据块导致CRUD延迟。通过 `configureCollectionBalancing` 命令合并数据块,但需注意:
- 整理期间可能短暂阻塞元数据更新。
- MongoDB 7.0+ 已支持自动合并,通常无需手动操作。
2. **负载均衡窗口设置**
在业务低峰期触发负载均衡器迁移数据块减少对CRUD的影响。
---
### 💎 六、其他关键技巧
1. **合理控制事务范围**:短事务减少锁竞争。
2. **写入确认级别调整**:对非关键数据使用 `w:0`(无确认),提升写入速度(牺牲一致性)。
3. **TTL索引自动清理**:为临时数据(如日志)设置过期时间,减少存储压力。
---
### 💎 优化方法效果对比表
| **优化方向** | **适用场景** | **性能提升效果** | **实现复杂度** |
|--------------------|--------------------------|----------------------|--------------|
| **批量写入** | 数据导入、批量更新 | ⭐⭐⭐⭐⭐ (极高) | ⭐⭐ (中等) |
| **流式导出** | 大数据量导出 | ⭐⭐⭐⭐ (避免OOM) | ⭐ (简单) |
| **条件分页** | 深度分页(>100页 | ⭐⭐⭐⭐ (O(1) 跳转) | ⭐⭐ (中等) |
| **冗余字段** | 高频关联查询 | ⭐⭐⭐ (减少联表) | ⭐⭐⭐ (较高) |
| **分片碎片整理** | MongoDB 6.0以下分片集群 | ⭐⭐ (减少延迟) | ⭐⭐⭐⭐ (复杂) |
---
> 💡 **实践建议**:优先从**批量操作**和**分页策略**入手,这两类优化代码改动小且收益显著。海量数据场景下,**流式处理+字段投影**是导出标配方案。分片集群升级到 MongoDB 7.0+ 可减少运维负担。

View File

@@ -0,0 +1,123 @@
接下来我们来 **一步步给 MongoDB 添加用户账户(角色管理)**
假设你希望创建一个:
- 用户名:`shumengya`
- 密码:`shumengya520`
- 权限对整个数据库系统有管理权限root 权限)
---
## 🧭 步骤 1进入 MongoDB Shell
MongoDB 7.x 之后使用的是新客户端 `mongosh`
```bash
mongosh
```
如果提示 `command not found`,可以执行:
```bash
mongo
```
---
## 🧩 步骤 2切换到 `admin` 数据库
MongoDB 的用户管理都存在 `admin` 数据库里)
```javascript
use admin
```
---
## 🧰 步骤 3创建管理员用户
运行下面的命令创建一个超级管理员账号:
```javascript
db.createUser({
user: "shumengya",
pwd: "shumengya520",
roles: [ { role: "root", db: "admin" } ]
})
```
✅ 成功后会输出:
```
Successfully added user: {
"user" : "shumengya",
"roles" : [ { "role" : "root", "db" : "admin" } ]
}
```
---
## 🔐 步骤 4启用身份验证
编辑 MongoDB 的配置文件:
```bash
sudo nano /etc/mongod.conf
```
找到或添加以下部分(注意缩进):
```yaml
security:
authorization: enabled
```
保存退出后,重启 MongoDB
```bash
sudo systemctl restart mongod
```
---
## ✅ 步骤 5验证登录是否成功
```bash
mongosh -u shumengya -p shumengya520 --authenticationDatabase admin
```
如果看到类似:
```
test>
```
说明登录成功 ✅
---
## 💡 可选:为特定数据库创建普通用户
比如你有个业务数据库叫 `farmgame`,可以创建普通读写用户:
```javascript
use farmgame
db.createUser({
user: "gameuser",
pwd: "gamepass123",
roles: [ { role: "readWrite", db: "farmgame" } ]
})
```
---
## 🧱 总结
|操作|命令或说明|
|---|---|
|创建管理员|`db.createUser({user: "shumengya", pwd: "...", roles: [{role: "root", db: "admin"}]})`|
|开启认证|`/etc/mongod.conf``security.authorization: enabled`|
|登录验证|`mongosh -u shumengya -p shumengya520 --authenticationDatabase admin`|
---

View File

@@ -0,0 +1,123 @@
接下来我们来 **一步步给 MongoDB 添加用户账户(角色管理)**
假设你希望创建一个:
- 用户名:`shumengya`
- 密码:`shumengya520`
- 权限对整个数据库系统有管理权限root 权限)
---
## 🧭 步骤 1进入 MongoDB Shell
MongoDB 7.x 之后使用的是新客户端 `mongosh`
```bash
mongosh
```
如果提示 `command not found`,可以执行:
```bash
mongo
```
---
## 🧩 步骤 2切换到 `admin` 数据库
MongoDB 的用户管理都存在 `admin` 数据库里)
```javascript
use admin
```
---
## 🧰 步骤 3创建管理员用户
运行下面的命令创建一个超级管理员账号:
```javascript
db.createUser({
user: "shumengya",
pwd: "shumengya520",
roles: [ { role: "root", db: "admin" } ]
})
```
✅ 成功后会输出:
```
Successfully added user: {
"user" : "shumengya",
"roles" : [ { "role" : "root", "db" : "admin" } ]
}
```
---
## 🔐 步骤 4启用身份验证
编辑 MongoDB 的配置文件:
```bash
sudo nano /etc/mongod.conf
```
找到或添加以下部分(注意缩进):
```yaml
security:
authorization: enabled
```
保存退出后,重启 MongoDB
```bash
sudo systemctl restart mongod
```
---
## ✅ 步骤 5验证登录是否成功
```bash
mongosh -u shumengya -p shumengya520 --authenticationDatabase admin
```
如果看到类似:
```
test>
```
说明登录成功 ✅
---
## 💡 可选:为特定数据库创建普通用户
比如你有个业务数据库叫 `farmgame`,可以创建普通读写用户:
```javascript
use farmgame
db.createUser({
user: "gameuser",
pwd: "gamepass123",
roles: [ { role: "readWrite", db: "farmgame" } ]
})
```
---
## 🧱 总结
|操作|命令或说明|
|---|---|
|创建管理员|`db.createUser({user: "shumengya", pwd: "...", roles: [{role: "root", db: "admin"}]})`|
|开启认证|`/etc/mongod.conf``security.authorization: enabled`|
|登录验证|`mongosh -u shumengya -p shumengya520 --authenticationDatabase admin`|
---

View File

@@ -0,0 +1,85 @@
**索引的核心作用:**
1. **大幅减少查询需要扫描的文档数量:** 没有索引时MongoDB 必须执行集合扫描(`COLLSCAN`),即检查集合中的*每一个*文档。有了合适的索引MongoDB 可以使用索引扫描(`IXSCAN`)快速定位到包含所需数据的文档位置。
2. **加速排序:** 如果排序字段包含在索引中MongoDB 可以直接利用索引中已经排好的顺序返回结果,避免昂贵的在内存中排序。
3. **支持高效的数据去重:** `$group` 聚合阶段的分组操作可以利用索引。
4. **实现覆盖查询:** 如果查询只需要返回索引中包含的字段MongoDB 可以*完全*从索引中获取结果,无需去读取实际的文档数据,速度极快。
**MongoDB 支持的索引类型:**
1. **单字段索引:**
* 最基本的索引类型,在单个字段上创建。
* 示例:`db.collection.createIndex({ name: 1 })` (1 表示升序,-1 表示降序。对于纯等值查询,顺序通常不重要;对于排序查询,顺序很重要)。
2. **复合索引:**
* 在多个字段上创建的索引。
* 字段的顺序**极其重要**。它决定了索引如何组织和哪些查询模式可以利用该索引(最左前缀原则)。
* 示例:`db.collection.createIndex({ status: 1, order_date: -1 })`。这个索引可以高效支持:
* 只查询 `status` 的查询
* 同时查询 `status``order_date` 的查询
* 查询 `status` 并按 `order_date` 排序的查询
* 但不支持只查询 `order_date` 的查询(不符合最左前缀)。
3. **多键索引:**
* 当索引字段是数组时MongoDB 会自动为数组中的每个元素创建索引条目。
* 用于高效查询数组字段中的元素。
* 示例:索引 `db.collection.createIndex({ tags: 1 })` 可以高效支持查询 `db.collection.find({ tags: "mongodb" })`
4. **地理空间索引:**
* **2dsphere** 用于查询存储为 GeoJSON 对象或传统坐标对的地理空间数据(地球球面几何)。支持邻近查询(`$near`)、包含查询(`$geoWithin`)、相交查询(`$geoIntersects`)等。
* **2d** 用于在二维平面上(如地图游戏)查询存储为传统坐标对的数据。主要用于平面几何计算。
5. **文本索引:**
* 支持对字符串或字符串数组字段的内容进行文本搜索。
* 支持词干提取、停用词过滤等基本文本处理功能。
* 示例:`db.collection.createIndex({ description: "text" })`,然后使用 `$text` 操作符进行搜索。
6. **哈希索引:**
* 对字段值进行哈希运算,并在哈希值上建立索引。
* 主要用途是为**分片键**提供更均匀的数据分布(使用`hashed`分片策略时)。
* 只支持等值匹配查询,不支持范围查询、排序或其他操作。
* 示例:`db.collection.createIndex({ _id: "hashed" })`
7. **通配符索引:**
* 可以索引文档中未知或任意字段。适用于模式动态变化的场景。
* 示例:
* `db.collection.createIndex({ "userMetadata.$**": 1 })` 索引 `userMetadata` 子文档中的所有字段。
* `db.collection.createIndex({ "$**": 1 })` 索引文档中的所有字段(谨慎使用,开销大)。
8. **唯一索引:**
* 强制索引字段的值在整个集合中是唯一的(`_id` 字段默认就有唯一索引)。
* 可以用于单字段或复合字段。
* 示例:`db.collection.createIndex({ email: 1 }, { unique: true })`
9. **TTL 索引:**
* 一种特殊的单字段索引,用于在指定时间后或在指定时间点自动从集合中删除文档。字段必须是日期类型或包含日期元素的数组。
* 适用于会话数据、日志、临时数据等。
* 示例:`db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })` (文档在 `createdAt` 时间之后 3600 秒/1 小时被删除)。
10. **稀疏索引:**
* 只包含具有索引字段的文档的条目。即使索引字段值为 `null`,也会包含在内;但如果文档*完全缺失*该索引字段,则不会被索引。
* 节省空间,提高索引效率(当字段在大部分文档中缺失时)。
* 示例:`db.collection.createIndex({ optionalField: 1 }, { sparse: true })`
**如何管理和使用索引:**
1. **创建索引:** 使用 `db.collection.createIndex()` 方法。
* 示例:`db.products.createIndex({ category: 1, price: -1 })`
2. **查看索引:** 使用 `db.collection.getIndexes()` 方法。
3. **删除索引:** 使用 `db.collection.dropIndex()``db.collection.dropIndexes()` 方法。
4. **分析查询性能:** 使用 `explain()` 方法查看查询的执行计划,确认是否使用了索引(`IXSCAN`)以及使用了哪个索引。这是优化查询的关键步骤。
* 示例:`db.orders.find({ status: "A", amount: { $gt: 100 } }).sort({ order_date: -1 }).explain("executionStats")`
5. **索引管理最佳实践:**
* **为常用查询模式创建索引:** 分析你的应用最常见的查询(`find`, `sort`, `aggregate`中的`$match`, `$group`, `$sort`等阶段),为这些查询涉及的字段创建合适的索引(通常是复合索引)。
* **遵循最左前缀原则:** 设计复合索引时,将最常用于过滤或排序的字段放在左边。
* **考虑选择性:** 选择性高的字段(如唯一值多的字段)放在复合索引的前面通常更有效。
* **使用覆盖查询:** 尽量让查询只返回索引中包含的字段。
* **监控索引使用率:** MongoDB Profiler 或 Atlas 性能监控可以查看索引的使用情况。使用率低的索引应考虑删除,因为它们会消耗写性能和存储空间。
* **权衡读写性能:** 索引会加速读操作,但会减慢写操作(插入、更新、删除),因为写操作需要维护索引。不要过度索引。
* **后台创建大索引:** 在大型集合上创建索引可能耗时很长并阻塞操作。使用 `{ background: true }` 选项可以在后台创建索引(虽然仍可能有性能影响,但不会完全阻塞读写)。
* **合理使用内存:** 确保有足够的内存将常用索引(或其活跃部分)保存在内存中,避免频繁的磁盘 I/O。
**总结:**
MongoDB 提供了极其丰富和强大的索引类型单字段、复合、多键、地理空间、文本、哈希、通配符、唯一、TTL、稀疏来满足各种查询场景的优化需求。**创建和管理合适的索引是提升 MongoDB 查询性能最关键的手段。** 务必结合你的具体查询模式,使用 `explain()` 分析执行计划,遵循索引设计的最佳实践(特别是复合索引的最左前缀原则),并持续监控和调整索引策略。

View File

@@ -0,0 +1,85 @@
**索引的核心作用:**
1. **大幅减少查询需要扫描的文档数量:** 没有索引时MongoDB 必须执行集合扫描(`COLLSCAN`),即检查集合中的*每一个*文档。有了合适的索引MongoDB 可以使用索引扫描(`IXSCAN`)快速定位到包含所需数据的文档位置。
2. **加速排序:** 如果排序字段包含在索引中MongoDB 可以直接利用索引中已经排好的顺序返回结果,避免昂贵的在内存中排序。
3. **支持高效的数据去重:** `$group` 聚合阶段的分组操作可以利用索引。
4. **实现覆盖查询:** 如果查询只需要返回索引中包含的字段MongoDB 可以*完全*从索引中获取结果,无需去读取实际的文档数据,速度极快。
**MongoDB 支持的索引类型:**
1. **单字段索引:**
* 最基本的索引类型,在单个字段上创建。
* 示例:`db.collection.createIndex({ name: 1 })` (1 表示升序,-1 表示降序。对于纯等值查询,顺序通常不重要;对于排序查询,顺序很重要)。
2. **复合索引:**
* 在多个字段上创建的索引。
* 字段的顺序**极其重要**。它决定了索引如何组织和哪些查询模式可以利用该索引(最左前缀原则)。
* 示例:`db.collection.createIndex({ status: 1, order_date: -1 })`。这个索引可以高效支持:
* 只查询 `status` 的查询
* 同时查询 `status``order_date` 的查询
* 查询 `status` 并按 `order_date` 排序的查询
* 但不支持只查询 `order_date` 的查询(不符合最左前缀)。
3. **多键索引:**
* 当索引字段是数组时MongoDB 会自动为数组中的每个元素创建索引条目。
* 用于高效查询数组字段中的元素。
* 示例:索引 `db.collection.createIndex({ tags: 1 })` 可以高效支持查询 `db.collection.find({ tags: "mongodb" })`
4. **地理空间索引:**
* **2dsphere** 用于查询存储为 GeoJSON 对象或传统坐标对的地理空间数据(地球球面几何)。支持邻近查询(`$near`)、包含查询(`$geoWithin`)、相交查询(`$geoIntersects`)等。
* **2d** 用于在二维平面上(如地图游戏)查询存储为传统坐标对的数据。主要用于平面几何计算。
5. **文本索引:**
* 支持对字符串或字符串数组字段的内容进行文本搜索。
* 支持词干提取、停用词过滤等基本文本处理功能。
* 示例:`db.collection.createIndex({ description: "text" })`,然后使用 `$text` 操作符进行搜索。
6. **哈希索引:**
* 对字段值进行哈希运算,并在哈希值上建立索引。
* 主要用途是为**分片键**提供更均匀的数据分布(使用`hashed`分片策略时)。
* 只支持等值匹配查询,不支持范围查询、排序或其他操作。
* 示例:`db.collection.createIndex({ _id: "hashed" })`
7. **通配符索引:**
* 可以索引文档中未知或任意字段。适用于模式动态变化的场景。
* 示例:
* `db.collection.createIndex({ "userMetadata.$**": 1 })` 索引 `userMetadata` 子文档中的所有字段。
* `db.collection.createIndex({ "$**": 1 })` 索引文档中的所有字段(谨慎使用,开销大)。
8. **唯一索引:**
* 强制索引字段的值在整个集合中是唯一的(`_id` 字段默认就有唯一索引)。
* 可以用于单字段或复合字段。
* 示例:`db.collection.createIndex({ email: 1 }, { unique: true })`
9. **TTL 索引:**
* 一种特殊的单字段索引,用于在指定时间后或在指定时间点自动从集合中删除文档。字段必须是日期类型或包含日期元素的数组。
* 适用于会话数据、日志、临时数据等。
* 示例:`db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })` (文档在 `createdAt` 时间之后 3600 秒/1 小时被删除)。
10. **稀疏索引:**
* 只包含具有索引字段的文档的条目。即使索引字段值为 `null`,也会包含在内;但如果文档*完全缺失*该索引字段,则不会被索引。
* 节省空间,提高索引效率(当字段在大部分文档中缺失时)。
* 示例:`db.collection.createIndex({ optionalField: 1 }, { sparse: true })`
**如何管理和使用索引:**
1. **创建索引:** 使用 `db.collection.createIndex()` 方法。
* 示例:`db.products.createIndex({ category: 1, price: -1 })`
2. **查看索引:** 使用 `db.collection.getIndexes()` 方法。
3. **删除索引:** 使用 `db.collection.dropIndex()``db.collection.dropIndexes()` 方法。
4. **分析查询性能:** 使用 `explain()` 方法查看查询的执行计划,确认是否使用了索引(`IXSCAN`)以及使用了哪个索引。这是优化查询的关键步骤。
* 示例:`db.orders.find({ status: "A", amount: { $gt: 100 } }).sort({ order_date: -1 }).explain("executionStats")`
5. **索引管理最佳实践:**
* **为常用查询模式创建索引:** 分析你的应用最常见的查询(`find`, `sort`, `aggregate`中的`$match`, `$group`, `$sort`等阶段),为这些查询涉及的字段创建合适的索引(通常是复合索引)。
* **遵循最左前缀原则:** 设计复合索引时,将最常用于过滤或排序的字段放在左边。
* **考虑选择性:** 选择性高的字段(如唯一值多的字段)放在复合索引的前面通常更有效。
* **使用覆盖查询:** 尽量让查询只返回索引中包含的字段。
* **监控索引使用率:** MongoDB Profiler 或 Atlas 性能监控可以查看索引的使用情况。使用率低的索引应考虑删除,因为它们会消耗写性能和存储空间。
* **权衡读写性能:** 索引会加速读操作,但会减慢写操作(插入、更新、删除),因为写操作需要维护索引。不要过度索引。
* **后台创建大索引:** 在大型集合上创建索引可能耗时很长并阻塞操作。使用 `{ background: true }` 选项可以在后台创建索引(虽然仍可能有性能影响,但不会完全阻塞读写)。
* **合理使用内存:** 确保有足够的内存将常用索引(或其活跃部分)保存在内存中,避免频繁的磁盘 I/O。
**总结:**
MongoDB 提供了极其丰富和强大的索引类型单字段、复合、多键、地理空间、文本、哈希、通配符、唯一、TTL、稀疏来满足各种查询场景的优化需求。**创建和管理合适的索引是提升 MongoDB 查询性能最关键的手段。** 务必结合你的具体查询模式,使用 `explain()` 分析执行计划,遵循索引设计的最佳实践(特别是复合索引的最左前缀原则),并持续监控和调整索引策略。

View File

@@ -0,0 +1,61 @@
## 1⃣ 数值类型Numeric
| 类型分类 | 数据类型 | 说明 |
| ---- | --------------------------------------------------------- | ------------- |
| 整数型 | `TINYINT``SMALLINT``MEDIUMINT``INT`/`INTEGER``BIGINT` | 存储不同范围的整数 |
| 精确小数 | `DECIMAL(M,D)``NUMERIC` | 高精度定点数(常用于金额) |
| 浮点数 | `FLOAT``DOUBLE`/`REAL` | 近似数值(科学计算) |
| 位类型 | `BIT(M)` | 存储二进制位 |
| | | |
| | | |
---
## 2⃣ 日期与时间类型Date & Time
|数据类型|格式|说明|
|---|---|---|
|`DATE`|YYYY-MM-DD|日期|
|`DATETIME(fsp)`|YYYY-MM-DD HH:MM:SS|日期 + 时间|
|`TIMESTAMP(fsp)`|YYYY-MM-DD HH:MM:SS|时间戳(支持自动更新)|
|`TIME`|HH:MM:SS|时间或时间间隔|
|`YEAR`|YYYY|年份2 位或 4 位)|
---
## 3⃣ 字符串与二进制类型String & Binary
|类型分类|数据类型|说明|
|---|---|---|
|定长字符串|`CHAR(M)`|定长,最大 255|
|变长字符串|`VARCHAR(M)`|可变长度,最大 65535受行大小限制|
|定长二进制|`BINARY(M)`|定长二进制|
|变长二进制|`VARBINARY(M)`|变长二进制|
|文本|`TINYTEXT``TEXT``MEDIUMTEXT``LONGTEXT`|存储大文本|
|二进制大对象|`TINYBLOB``BLOB``MEDIUMBLOB``LONGBLOB`|存储二进制数据|
|枚举|`ENUM('a','b',...)`|单选固定集合|
|集合|`SET('a','b',...)`|多选固定集合|
---
## 4⃣ 空间数据类型Spatial
|数据类型|说明|
|---|---|
|`GEOMETRY`|任意几何对象|
|`POINT`|点|
|`LINESTRING`|线|
|`POLYGON`|多边形|
|`MULTIPOINT``MULTILINESTRING``MULTIPOLYGON``GEOMETRYCOLLECTION`|组合空间对象|
---
## 5⃣ JSON 类型
|数据类型|说明|
|---|---|
|`JSON`|存储 JSON 文档,支持索引与函数操作|
---

View File

@@ -0,0 +1,61 @@
## 1⃣ 数值类型Numeric
| 类型分类 | 数据类型 | 说明 |
| ---- | --------------------------------------------------------- | ------------- |
| 整数型 | `TINYINT``SMALLINT``MEDIUMINT``INT`/`INTEGER``BIGINT` | 存储不同范围的整数 |
| 精确小数 | `DECIMAL(M,D)``NUMERIC` | 高精度定点数(常用于金额) |
| 浮点数 | `FLOAT``DOUBLE`/`REAL` | 近似数值(科学计算) |
| 位类型 | `BIT(M)` | 存储二进制位 |
| | | |
| | | |
---
## 2⃣ 日期与时间类型Date & Time
|数据类型|格式|说明|
|---|---|---|
|`DATE`|YYYY-MM-DD|日期|
|`DATETIME(fsp)`|YYYY-MM-DD HH:MM:SS|日期 + 时间|
|`TIMESTAMP(fsp)`|YYYY-MM-DD HH:MM:SS|时间戳(支持自动更新)|
|`TIME`|HH:MM:SS|时间或时间间隔|
|`YEAR`|YYYY|年份2 位或 4 位)|
---
## 3⃣ 字符串与二进制类型String & Binary
|类型分类|数据类型|说明|
|---|---|---|
|定长字符串|`CHAR(M)`|定长,最大 255|
|变长字符串|`VARCHAR(M)`|可变长度,最大 65535受行大小限制|
|定长二进制|`BINARY(M)`|定长二进制|
|变长二进制|`VARBINARY(M)`|变长二进制|
|文本|`TINYTEXT``TEXT``MEDIUMTEXT``LONGTEXT`|存储大文本|
|二进制大对象|`TINYBLOB``BLOB``MEDIUMBLOB``LONGBLOB`|存储二进制数据|
|枚举|`ENUM('a','b',...)`|单选固定集合|
|集合|`SET('a','b',...)`|多选固定集合|
---
## 4⃣ 空间数据类型Spatial
|数据类型|说明|
|---|---|
|`GEOMETRY`|任意几何对象|
|`POINT`|点|
|`LINESTRING`|线|
|`POLYGON`|多边形|
|`MULTIPOINT``MULTILINESTRING``MULTIPOLYGON``GEOMETRYCOLLECTION`|组合空间对象|
---
## 5⃣ JSON 类型
|数据类型|说明|
|---|---|
|`JSON`|存储 JSON 文档,支持索引与函数操作|
---

View File

@@ -0,0 +1,339 @@
# NSSM 使用教程Windows 下的 systemctl 替代方案)
> 适用场景:把 **控制台程序**(如 frpc、openlist、各种 exe/bat/cmd
> 做成 **开机自启 + 后台运行 + 崩溃自动重启 + 日志管理** 的 Windows 服务。
---
## 目录
1. NSSM 是什么
2. 下载与准备
3. 安装服务GUI
4. 安装服务(纯命令行)
5. 服务启停与状态查看
6. 修改服务配置GUI/命令行)
7. 崩溃自动重启策略
8. 日志捕获与轮转
9. 权限、依赖与进程设置(可选)
10. 卸载服务
11. 常见问题与排错
12. frpc/openlist 成品脚本示例
---
## 1. NSSM 是什么
NSSMNon-Sucking Service Manager是一个 Windows Service Wrapper
- 把任何控制台程序包装成 Windows 服务
- 进程退出/崩溃时自动重启
- 捕获 stdout/stderr 写日志并支持轮转
---
## 2. 下载与准备
1. 下载 NSSM 压缩包,解压
2. 根据系统位数选择:
- 64 位:`win64\nssm.exe`
- 32 位:`win32\nssm.exe`
3. 放到固定目录,例如:
```
C:\tools\nssm\nssm.exe
````
4. (推荐)将 `C:\tools\nssm` 加到系统 PATH
> **注意**:后续所有安装/启动/删除服务命令,都建议在 **管理员 CMD/PowerShell** 中执行。
---
## 3. 安装服务GUI 最常用)
管理员 CMD
```bat
nssm install frpc
````
弹出 GUI 后在 **Application** 页填写:
- **Path**:程序路径
例:`E:\控制台软件\frpc\frpc.exe`
- **Startup directory**:工作目录
例:`E:\控制台软件\frpc`
- **Arguments**:启动参数
例:`-c E:\控制台软件\frpc\frpc.ini`
填完点 **Install service**。
---
## 4. 安装服务(纯命令行)
适合脚本化部署:
```bat
nssm install frpc "E:\控制台软件\frpc\frpc.exe" "-c E:\控制台软件\frpc\frpc.ini"
```
然后补充工作目录等:
```bat
nssm set frpc AppDirectory "E:\控制台软件\frpc"
```
---
## 5. 服务启停与状态查看
```bat
nssm start frpc
nssm stop frpc
nssm restart frpc
nssm status frpc
```
常见 `status` 结果:
- `SERVICE_RUNNING`:运行中
- `SERVICE_STOPPED`:已停止
---
## 6. 修改服务配置GUI / 命令行)
### 6.1 GUI 编辑
```bat
nssm edit frpc
```
### 6.2 命令行修改set/get/reset/dump
通用格式:
```bat
nssm set <服务名> <参数名> <值>
nssm get <服务名> <参数名>
nssm reset <服务名> <参数名>
nssm dump <服务名>
```
示例:
```bat
nssm set frpc AppDirectory "E:\控制台软件\frpc"
nssm get frpc AppDirectory
nssm dump frpc
```
---
## 7. 崩溃自动重启策略(两层保险)
### 7.1 NSSM 自带 Exit actions
GUI**Exit actions** 标签页
- **AppExit Default** = `Restart`
- **AppRestartDelay** = `5000`(毫秒)
- **AppThrottle** = `1500`(默认,一般不用改)
命令行等价:
```bat
nssm set frpc AppExit Default Restart
nssm set frpc AppRestartDelay 5000
nssm set frpc AppThrottle 1500
```
### 7.2 Windows 服务“恢复”策略(推荐开启)
`Win + R → services.msc`
找到服务 → 属性 → **恢复**
- 第一次失败:重新启动服务
- 第二次失败:重新启动服务
- 后续失败:重新启动服务
- 延迟5~10 秒
---
## 8. 日志捕获与轮转
### 8.1 捕获 stdout / stderr
GUI**I/O** 页
- **Output (stdout)**`C:\logs\frpc.out.log`
- **Error (stderr)**`C:\logs\frpc.err.log`
命令行:
```bat
nssm set frpc AppStdout "C:\logs\frpc.out.log"
nssm set frpc AppStderr "C:\logs\frpc.err.log"
```
### 8.2 日志轮转
GUI**File rotation** 页
-`Rotate while service is running`
- `Rotate files bigger than X bytes`(如 50MB
- 可选勾 `Replace existing files`
命令行示例(轮转阈值 50MB
```bat
nssm set frpc AppRotateFiles 1
nssm set frpc AppRotateOnline 1
nssm set frpc AppRotateBytes 52428800
nssm set frpc AppRotateSeconds 0
```
---
## 9. 权限、依赖与进程设置(可选)
### 9.1 用指定账户跑服务
GUI**Log on** 页
默认 `LocalSystem` 已够用。
需要访问网络共享时才换普通用户。
命令行:
```bat
nssm set frpc ObjectName ".\someuser" "password"
```
### 9.2 设置依赖(等某服务起来再启动)
GUI**Dependencies** 页
命令行:
```bat
nssm set frpc DependOnService Tcpip
```
### 9.3 设置优先级/CPU 亲和性
GUI**Process** 页
命令行:
```bat
nssm set frpc AppPriority NORMAL_PRIORITY_CLASS
nssm set frpc AppAffinity All
```
---
## 10. 卸载服务(安全删除)
先停再删:
```bat
nssm stop frpc
nssm remove frpc confirm
```
---
## 11. 常见问题与排错
### 11.1 `Can't open service! OpenService(): 拒绝访问`
原因:**没有管理员权限控制服务**
解决:
1. 关闭当前 CMD
2. 以管理员身份打开 CMD
3. 再执行:
```bat
nssm start frpc
```
### 11.2 服务启动后立刻停止
常见原因:**Path / Arguments / Startup directory 错**
排查:
```bat
nssm edit frpc
nssm dump frpc
```
### 11.3 日志没内容
原因:
- 没设置 `AppStdout/AppStderr`
- 目录没权限
---
## 12. frpc / openlist 成品脚本示例
### 12.1 frpc
```bat
nssm install frpc "E:\控制台软件\frpc\frpc.exe" "-c \"E:\控制台软件\frpc\frpc.ini\""
nssm set frpc AppDirectory "E:\控制台软件\frpc"
nssm set frpc AppStdout "C:\logs\frpc.out.log"
nssm set frpc AppStderr "C:\logs\frpc.err.log"
nssm set frpc AppExit Default Restart
nssm set frpc AppRestartDelay 5000
nssm start frpc
```
### 12.2 openlist按你实际参数改
```bat
nssm install openlist "E:\控制台软件\openlist\openlist.exe" "server --config E:\控制台软件\openlist\config.yaml"
nssm set openlist AppDirectory "E:\控制台软件\openlist"
nssm set openlist AppStdout "C:\logs\openlist.out.log"
nssm set openlist AppStderr "C:\logs\openlist.err.log"
nssm set openlist AppExit Default Restart
nssm set openlist AppRestartDelay 5000
nssm start openlist
```
---
## 速查表
```bat
nssm install <name> "<exe>" "<args>"
nssm edit <name>
nssm start|stop|restart <name>
nssm status <name>
nssm set/get/reset <name> <key> [value]
nssm dump <name>
nssm remove <name> confirm
```
---

View File

@@ -0,0 +1,61 @@
Nacos 是阿里巴巴开源的 **动态服务发现、配置管理与服务治理平台**,旨在简化微服务架构的构建、交付和管理。
---
## 🚀 核心功能
| 功能 | 主要作用 |
|------|----------|
| 🎯 **服务注册与发现** | 服务提供者注册自身信息,服务消费者动态发现和调用其他服务。 |
| ⚙️ **动态配置管理** | 集中管理所有环境的配置,支持实时推送变更,无需重启应用。 |
| 🔍 **服务健康监测** | 定期检查服务实例健康状况,自动隔离不健康实例,保障系统稳定性。 |
| 🚦 **动态DNS与流量管理** | 支持权重路由,助力灰度发布、蓝绿部署等高级流量管理策略。 |
---
## 🎯 服务发现与健康检查
- **服务注册**:实例启动时向 Nacos 注册自身元数据服务名、IP、端口等
- **服务发现**:消费者通过服务名查询健康实例,实现通信而无需关心具体地址。
- **健康检查**:支持客户端上报与服务端主动探测,自动剔除不健康实例,保障可靠性。
---
## ⚙️ 动态配置管理
- **集中化管理**:统一存储数据库连接、开关、限流阈值等配置。
- **动态刷新**:配置变更实时推送,应用可在运行中直接生效(热更新)。
- **版本控制与回滚**:支持历史版本,一键回滚,降低变更风险。
---
## 🚦 动态DNS与服务治理
- **动态DNS服务**:支持权重路由、流量控制和简易内网 DNS 解析。
- **服务与元数据管理**:统一管理服务描述、依赖关系、健康状态、流量及安全策略。
---
## 💡 主要应用场景
- **数据库配置集中化管理**:提升安全性与合规性。
- **限流与降级开关**:结合 Sentinel 等组件实现运行时动态调整。
- **多环境与多数据中心**:基于 Namespace 与 Group 实现隔离与灵活部署。
---
## 📊 与其他组件对比
-**功能更全面**Nacos = 服务发现 + 配置管理Eureka 仅支持服务发现。
-**健康检查机制更强**:优于 Eureka 心跳检测。
-**社区与生态活跃**Eureka 已停止维护,而 Nacos 持续迭代。
-**多数据中心支持优越**:原生支持多数据中心部署。
---
## 📚 总结
Nacos 集 **服务发现、配置管理、服务治理** 于一体,
极大简化了微服务架构复杂性,提升了 **开发效率**、**可维护性** 和 **系统弹性**
---

View File

@@ -0,0 +1,230 @@
```html
<!-- 默认自定义头部 -->
<style>
/*隐藏底部openlsit版权信息*/
.footer span,.footer a:nth-of-type(1){
display:none;
}
</style>
```
```html
<!-- 默认自定义头部 -->
<!-- 引入 polyfill -->
<script src="https://polyfill.alicdn.com/v3/polyfill.min.js?features=String.prototype.replaceAll"></script>
<!-- 引入字体 -->
<link rel="stylesheet" href="https://npm.elemecdn.com/lxgw-wenkai-webfont@1.1.0/lxgwwenkai-regular.css" />
<style>
/*Logo图片*/
.header-left img { filter: drop-shadow(0px 0px 20px rgb(9, 187, 189)); filter: brightness(1.5); }
/* 背景设置 */
.hope-ui-dark, .hope-ui-light {
background-image: url('https://pan.lcxm.site/d/%E7%81%B5%E5%88%9B%E7%9B%98-%E4%B8%BB%E7%9B%AE%E5%BD%95/%E7%81%B5%E5%88%9B%E7%9B%98%E7%B3%BB%E7%BB%9F%E6%96%87%E4%BB%B6/background4.png?sign=q5pQCi5TXFxY1f9ULk-Y2y4pHeIc7yulTy2e8ai_GJI=:0') !important;
background-size: cover;
background-attachment: fixed;
background-position: center;
}
/*主列表白天模式透明*/
.obj-box.hope-stack.hope-c-dhzjXW.hope-c-PJLV.hope-c-PJLV-igScBhH-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*主列表夜间模式透明*/
.obj-box.hope-stack.hope-c-dhzjXW.hope-c-PJLV.hope-c-PJLV-iigjoxS-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(0, 0, 0, 0.3) !important;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*readme白天模式透明*/
.hope-c-PJLV.hope-c-PJLV-ikSuVsl-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*readme夜间模式透明*/
.hope-c-PJLV.hope-c-PJLV-iiuDLME-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(0, 0, 0, 0.3) !important;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*顶部*/
#root > .header {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background: rgba(255, 255, 255, 0); /* 透明背景色 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*导航条*/
/*白天模式*/
.hope-ui-light .body > .nav {
background-color: rgba(255, 255, 255, 0.3);
border-radius: var(--hope-radii-xl);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*夜间模式*/
.hope-ui-dark .body > .nav {
background-color: rgba(0, 0, 0, 0.3);
border-radius: var(--hope-radii-xl);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*隐藏导航条遮罩*/
.body > .nav::after {
display: none;
}
/*右上视图切换菜单*/
/*白天模式*/
.hope-ui-light .hope-c-PJLV-iSMXDf-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background: rgba(255, 255, 255, 0.3); /* 透明背景色 */
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*夜间模式*/
.hope-ui-dark .hope-c-PJLV-iSMXDf-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background: rgba(0, 0, 0, 0.3); /* 透明背景色 */
border-radius: var(--hope-radii-xl);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
}
/*右下角侧边栏按钮透明 第一个是白天 第二个是夜间*/
.hope-ui-light .hope-c-PJLV-ijgzmFG-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(255, 255, 255, 0.3) !important;
}
.hope-ui-dark .hope-c-PJLV-ijgzmFG-css {
backdrop-filter: blur(10px); /* 毛玻璃效果的强度 */
-webkit-backdrop-filter: blur(10px); /* 为 Safari 浏览器添加兼容性 */
background-color: rgba(0, 0, 0, 0.5) !important;
}
/*白天模式代码块透明*/
.hope-ui-light pre {
background-color: rgba(255, 255, 255, 0.1) !important;
}
/*夜间模式代码块透明*/
.hope-ui-dark pre {
background-color: rgba(255, 255, 255, 0) !important;
}
/*底部CSS.App .table这三个一起的*/
dibu {
border-top: 0px;
position: absolute;
bottom: 0;
width: 100%;
margin: 0px;
padding: 0px;
}
.App {
min-height: 85vh;
}
.table {
margin: auto;
}
/*全局字体*/
* {
font-family: LXGW WenKai;
}
* {
font-weight: bold;
}
body {
font-family: LXGW WenKai;
}
</style>
```
```html
<!-- 延迟加载 -->
<div id="customize" style="display: none;">
<div>
<br />
<center class="dibu">
<div style=" line-height: 20px;font-size: 20pt;font-weight: bold;">
<span>
"
<span style="color: rgb(154, 216, 166); font-weight: bold;" id="hitokoto">
<a href="#" id="hitokoto_text">
"灵创新媒实验室欢迎您!"
</a>
</span> "
</span>
</div>
<!-- 底部链接 -->
<div style="font-size: 13px; font-weight: bold;">
<span class="nav-item">
<a class="nav-link" href="mailto:xiaoming@xmdblog.com" target="_blank">
<i class="fa-duotone fa-envelope-open" style="color:#409EFF" aria-hidden="true">
</i>
邮箱 |
</a>
</span>
<span class="nav-item">
<a class="nav-link" href="pan.xmdblog.com" target="_blank">
<i class="fa fa-cloud-download" style="color:#409EFF;" aria-hidden="true">
</i>
云盘 |
</a>
</span>
<!--后台入口-->
<span class="nav-item">
<a class="nav-link" href="/@manage" target="_blank">
<i class="fa-solid fa-folder-gear" style="color:#409EFF;" aria-hidden="true">
</i>
管理 |
</a>
</span>
<br />
<br />
<!--添加备案信息-->
<span class="nav-item">
<a class="nav-link" href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">
<i class="fa-solid fa-shield-check" style="color:#409EFF;" aria-hidden="true">
</i>
沪ICP备2024050492号-1
</a>
</span>
</div>
</center>
<br />
</div>
<!--延迟加载范围到这里结束-->
</div>
<!-- 延迟加载JS -->
<script>
let interval = setInterval(() => {
if (document.querySelector(".footer")) {
document.querySelector("#customize").style.display = "";
clearInterval(interval);
}
}, 200);
</script>
```
```html
<script type="text/javascript">   function show_runtime() {       window.setTimeout("show_runtime()", 1000);       X = new Date("3/30/2025 12:12:12"); /*开始时间*/       Y = new Date();       T = (Y.getTime() - X.getTime());       M = 24 * 60 * 60 * 1000;       a = T / M;       A = Math.floor(a);       b = (a - A) * 24;       B = Math.floor(b);       c = (b - B) * 60;       C = Math.floor((b - B) * 60);       D = Math.floor((c - C) * 60);       runtime_span.innerHTML = "本站已运行 " + A + " 天 " + B + " 小时 " + C + " 分 " + D + " 秒 "   }   show_runtime(); </script>
```

View File

@@ -0,0 +1,6 @@
```php
use pocketmine\utils\TextFormat;
$this->getServer()->getLogger()->info(TextFormat::GREEN . "[刷矿机] 插件激活成功!");
```

View File

@@ -0,0 +1,30 @@
```c++
#include <iostream>
#include <random>
#include <chrono>
#include <bits/stdc++.h>
using namespace std;
int main() {
// 使用当前时间的时间戳作为种子
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// 创建一个基于该种子的随机数生成器
std::default_random_engine generator(seed);
// 创建一个均匀分布的随机数生成器(在 1 到 100 之间)
std::uniform_int_distribution<int> distribution(0, 10);
//这里填写你需要输入的
string str1,str2;
cin>>str1>>str2;
// 生成并打印随机数
std::cout <<distribution(generator) << std::endl;
return 0;
}
```
### 这个是PTA输出值万能代码只需要你不断地试错有概率全对

View File

@@ -0,0 +1,107 @@
**7-4 英文单词排序**
分数 25
作者 张泳
单位 浙大城市学院
本题要求编写程序,输入若干英文单词,对这些单词按长度从小到大排序后输出。如果长度相同,按照输入的顺序不变。
### 输入格式:
输入为若干英文单词,每行一个,以`#`作为输入结束标志。其中英文单词总数不超过20个英文单词为长度小于10的仅由小写英文字母组成的字符串。
### 输出格式:
输出为排序后的结果,每个单词后面都额外输出一个空格。
### 输入样例:
```in
blue
red
yellow
green
purple
#
```
### 输出样例:
```out
red blue green yellow purple
```
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
```c
#include <stdio.h>
#include <string.h>
typedef struct {
char word[10 + 1];
int index;
} Word;
int main() {
Word words[20];
int count = 0; //单词数量
while (1) {
char word[10 + 1];
fgets(word, sizeof(word), stdin);
if (word[0] == '#') {
break;
}
word[strcspn(word, "\n")] = '\0';
strcpy(words[count].word, word);
words[count].index = count;
count++;
}
//标准冒泡排序
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count-1-i; j++) {
if (strlen(words[j].word) > strlen(words[j+1].word)) {
// 交换单词
Word temp = words[j];
words[j] = words[j+1];
words[j+1] = temp;
}
}
}
for (int i = 0; i < count; i++) {
printf("%s ", words[i].word);
}
printf("\n");
return 0;
}
```

View File

@@ -0,0 +1,78 @@
**7-6 求整数序列中出现次数最多的数**
分数 20
作者 张彤彧
单位 浙江大学
本题要求统计一个整型序列中出现次数最多的整数及其出现次数。
### 输入格式:
输入在一行中给出序列中整数个数N0<N≤1000以及N个整数。数字间以空格分隔。
### 输出格式:
在一行中输出出现次数最多的整数及其出现次数,数字间以空格分隔。题目保证这样的数字是唯一的。
### 输入样例:
```in
10 3 2 -1 5 3 4 3 0 3 2
```
### 输出样例:
```out
3 4
```
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
```c
#include <stdio.h>
int main() {
int N;
scanf("%d", &N);
int arr[N];
for(int i = 0; i < N; i++) {
scanf("%d", &arr[i]);
}
int max_count = 0;
int most_freq_num = arr[0];
for(int i = 0; i < N; i++) {
int count = 1;
for(int j = i+1; j < N; j++) {
if(arr[j] == arr[i]) {
count++;
}
}
if(count > max_count) {
max_count = count;
most_freq_num = arr[i];
}
}
printf("%d %d", most_freq_num, max_count);
return 0;
}
```

View File

@@ -0,0 +1,179 @@
# 在阅读本教程前务必阅读本Readme
目前由官方承认的几个宣传贴
https://www.minebbs.com/threads/dreamserver-nukkit-nukkit.2912/#post-13183
https://www.mcplugin.cn/thread-1259-1-1.html
https://www.mcbbs.net/forum.php?mod=viewthread&tid=927009&page=1#pid15854025
https://www.mcbbs.net/forum.php?mod=viewthread&tid=930861&mobile=2
# 史上最详细的Nukkit教程
#### Learning Nukkit Whoever you are!
- [中文(简体)](README.md)
- [English](README_en.md)
#### 说明
您可以在这里作为一本书观看教程: http://noyark.net/
本教程遵循[发现者小组公约](LICENSE)
#### 友情项目
[基于Java开发的SCPSL服务端](https://github.com/jsmod2-java-c/JSmod2-Core)
#### 关于主要作者
事实上作者上已经退坑了,但是不影响写教程,只是有几点还请悉知:
- 不要问如何搭建服务器;
- 不要PM任何有关人员定制插件
- 除了写这个教程作者不会参与任何和Minecraft有关的活动和交易
- 本教程需要一定的Java基础请先做好预习功课并且作者不会回答任何基础的问题
- 作者目前是高中学生,因此时间并不充裕,更新速度请大家海涵;
- 如有任何疏漏或Bug的存在还请指正
#### 作者的扯皮
Nukkit核心作为一个服务端开发框架虽然性能优越吸引了大批的开发者加入开发但教程稀少学习难度大使很多小白
望而却步,基于目前很多人对于教程的渴望,包括作者在初学的时候只能通过到处询问和看核心源码来了解如何使用一个东西,
但并不是所有的人都能安心去看核心源码或者到处询问问题。同时,本教程会重复强调一件事情: 打好基础,本教程已经列出
您需要掌握的java基础什么0基础直接学习nukkit都是骗人的作者已经见过很多这样的初学者很少的人通过这种方式
学会(无疑是一种懒散的行为)nukkit事实上就是学习一个新的api,并无很大的入门难度,只要您学习了基础,就能很快从
这里得到启发并参与到nukkit的大家庭。
主作者其实很和蔼,但是对于简单的问题作者由于时间问题是不能回答的,也不能干刷屏之类的事情,再和蔼的人也会把你给
屏蔽当然作者坚持开放原则如果有相关问题可以issues发表您的疑问。
同时记得给项目一个star支持一下并且将这个项目宣传给别人在支持作者同时造福他人。您的支持和宣传就是作者写下去的动力
希望这个教程可以帮到您,我们由衷的感谢:)
--- MagicLu550
#### 关于本教程
Nukkit官方说过: Nukkit是一款高性能的核能驱动的Minecraft基岩版服务器,它的
速度更快性能相比PocketMine更高。
```
Nukkit is nuclear-powered server software for Minecraft Bedrock Edition. It has a few key advantages over other server software:
Written in Java, Nukkit is faster and more stable.
Having a friendly structure, it's easy to contribute to Nukkit's development and rewrite plugins from other platforms into Nukkit plugins.
Nukkit is under improvement yet, we welcome contributions.
```
目前依托Java语言的健壮性,Nukkit形成了强大的生态并且出现了很多分支目前使用最广泛的分支是[NukkitX](http://nukkitx.com)
感谢您能观看我们编写的教程。该教程在编写阶段,更新间隔可能会很长。
请谅解。该教程是为了简化目前很多晦涩难懂的教程使得有过Java语法基础的朋友
能方便地了解Nukkit和学习Nukkit. 目前Nukkit的学习难度主要在于其资料过少。
我们将会整理和参考其他相关资料来编写该教程,也感谢您参与编写,造福大家
同时转发本教程应当附上GitHub原地址不得任意转发和搬运以及商业使用。
本教程不涉及语法只涉及Nukkit的各种库的解释以便于开发
您所需要掌握的最基本的Java基础体系
```
--基础部分
-- 语法
-- 变量定义
-- 方法定义
-- 基本表达式
-- 逻辑表达式
-- 算数表达式
-- 流程控制
-- 条件语句
-- 循环语句
-- 选择语句
-- 面向对象
-- 类,对象的概念
-- 定义类和声明对象
-- 包的概念
-- 匿名内部类
-- 接口
-- 抽象类,抽象方法
-- lambda表达式
-- 面向对象的三大特征
-- 继承
-- 封装
-- 多态
-- 枚举
-- 注解
-- 类库
-- 反射
-- 多线程
-- 字符串操作
-- 数字包装类
-- io流
-- bio
-- nio
-- 套接字Socket
-- udp
-- tcp
-- 时间类库
-- 系统类库
```
未来我们会开发Nukkit-d,是对于Nukkit设计思想的整理和重新实现以解决目前nukkit维护难的问题
#### 关于我们
如果您有兴趣可以随时发送Pr等
本教程不定期更新,大概寒假时期更新最快
相关意见可以联系843983728@qq.com或者加QQ:843983728
QQ群: 931210534
![QQ群](images/0-00.png)
#### 贡献标准和须知
1. 教程要求尽量自然,易懂,符合本项目所追求的"人人可以学习Nukkit"的宗旨
2. 编写教程可以在参与编写者添加自己的名字,若没有可以自己手动加入,如第一章所同
3. 照搬其他教程原文需要得到作者同意,并且在下面注明参考文献。
4. 若发现侵权行为,与本项目领导者无关,但我们会积极配合找到侵权者
5. 请尽量以第一章为范本编写您的内容。
6. 如果有知识缺点请在Readme里注明这个缺点出处写在知识缺点里,知识缺点在章节中标注。
7. 教程补充首要的是解决知识缺点
8. 由于编写人数较少,教程不避免的会有错误漏洞不严谨如果发现可以发送pullRequest参与修改
#### 知识缺点:
- 关于fallBackPrefix的作用 - 第二章和第四章 [1]
#### 专栏
- [填坑专栏](专栏-关于我们常见的那些坑.md)
- [用指令设置玩家实体大小](章外篇之—-用指令设置玩家实体大小(简单版).md)
- [多语言解决方案](章外篇之二-多语言解决方案.md)
#### 目录
- [第一部分 基础准备](第一部分前言.md)
- [X] [如何搭建开发环境](第一章-如何搭建环境.md)
- [X] [插件要素](第二章-插件要素.md)
- [X] [如何编写监听器](第三章-如何编写监听器.md)
- [X] [如何编写指令](第四章-如何编写命令.md)
- [X] [如何使用配置文件](第五章-如何使用配置文件.md)
- [X] [如何编写plugin.yml](第六章-如何编写plugin.yml.md)
- [X] [PluginBase类](第七章-PluginBase类.md)
- [X] [练习案例](第八章-案例玩家进入信息等效果.md)
- [第二部分 nukkit的工具和各种事件介绍](第二部分前言.md)
- [X] [主要的事件的介绍](第一章-主要的事件介绍.md)
- [ ] [事件相关方法](第二章-事件相关方法.md)
- [X] [计时器的介绍](第三章-计时器的介绍.md)
- [X] [Server类和PluginManager类](第四章-Server类和PluginManager类.md)
- [ ] [各种实体类的方法介绍](第五章-各种实体类的方法介绍.md)
- [ ] [各种工具类的介绍](第六章-各种工具类的介绍.md)
- [X] [如何发送数据包](第七章-如何发送数据包.md)
- 第三部分 nukkit相关实例
- 第四部分 nukkit原理剖析
#### 专栏状况
```diff
+ 专题
+ 提示信息
```

View File

@@ -0,0 +1,146 @@
# 核心思路(快速决策)
- **Windows成熟 & 快)**:用 **Electron** + `electron-builder`(或 Electron Forge把 web 前端放进 WebView桌面端直接运行或同时启动本地后端进程。成熟、生态完善、发布流程安装包、自动更新、签名有现成方案。
- **Windows瘦体积**:若关心体积、原生安全,考虑 **Tauri**Rust 后端,最终二进制更小)。但学习/环境比 Electron 略复杂。
- **Android快 & 直接把现有 web 变原生)**:用 **Capacitor**Ionic 团队)把生产构建的前端打包成 Android 原生工程,再用 Android Studio 打包签名上传 Play。对保留现有 React 网页最省力。
- **AndroidPWA 路线,最快上线)**:如果你的 React 是 PWA有 service worker、HTTPS、manifest可以做 **Trusted Web Activity (TWA)**,用 Bubblewrap/PWABuilder 生成 Android 包并上架(适合想最小工作量上 Play 的场景)。
下面给出每条路线的**实战步骤、常见陷阱和示例命令**。
---
# 路线 A — 推荐(最快、最成熟):**ElectronWindows + CapacitorAndroid**
适合:不想重写、后端可以继续作为远端服务(推荐),要快速得到桌面 + Android 双端。
## 1) 通用准备(前端)
1. 把 React 做生产构建(示例用 CRA / Vite
`npm run build`(或 `yarn build`),生成 `dist/``build/`
2. 确保所有 API 用 HTTPS、CORS、并把生产 API 域配置好(不要在客户端明文放敏感秘钥)。
## 2) WindowsElectron + electron-builder快速、成熟
概念Electron 启一个 native 窗口并加载你的静态 `build/`。用 `electron-builder` 打包成 installerNSIS/MSI/portable并可做代码签名与自动更新。
快速步骤(最小):
- 项目根目录加入 `electron` 主进程文件(`main.js`),让它加载 `build/index.html`
- 安装依赖并配置打包:
```bash
# 依赖
npm install --save-dev electron electron-builder
# package.json scripts 示例
"scripts": {
"build:web": "npm run build", # 你的 React build
"start:electron": "electron .",
"dist": "npm run build:web && electron-builder"
},
"build": {
"appId": "com.yourcompany.app",
"files": ["build/**/*", "main.js", "package.json"],
"win": {"target":["nsis","portable"]}
}
```
- 本地测试:`npm run start:electron`
- 生成发布包:`npm run dist`electron-builder 会产出 `.exe` / `.msi` / installer
**如果需要把后端随应用打包(可选但更复杂)**
常见做法是把 Node 后端打成独立 exe`pkg``nexe`),在 Electron 启动时用 `child_process.spawn()` 启动本地服务,再让前端调用 `http://localhost:xxxx`。这样用户本地拥有完整后端(适合离线或内网部署)。示例工具:`pkg``nexe`。注意:安全、端口冲突、自动更新、杀进程清理等需要处理。
常见注意点:
- Electron 应用体积通常较大(几十 MB 起自动更新、签名Authenticode建议上线前完成。
- 在 CI如 GitHub Actions上可以交叉构建但 Windows 的代码签名通常在 Windows runner 或专门流程中完成。
---
## 3) AndroidCapacitor把 web 打包成原生 APK/AAB
概念Capacitor 将你的 `build/` 内容嵌入到一个原生 Android 项目WebView并提供与原生桥接的插件 API。非常适合把现有 web 转 app。
快速步骤(最小):
```bash
# 在项目根build 已存在)
npm install @capacitor/core @capacitor/cli
npx cap init "MyApp" com.example.myapp --web-dir=build
npx cap add android
# 每次 web 有新 build
npm run build
npx cap copy android
npx cap open android # 在 Android Studio 中打开,构建、签名、导出 AAB
```
在 Android Studio 中使用 **Build → Generate Signed Bundle / APK** 来生成签名的 AAB 上传到 PlayPlay 推荐上传 AAB。发布与签名细节见 Google Play 签名文档Play App Signing
常见注意点:
- 若后端是远端 APIAndroid 里可直接请求远端;若需要本地 DB使用 SQLite 或 Capacitor 的 Storage/插件而不是在设备上运行完整 Node 后端。
- 调试网络(开发时指向本地 dev server可用 `npx cap open android` 并在 `capacitor.config.*` 设置 `server.url` 来启用 live reload但生产请编译静态文件
---
# 路线 B — 可选:**TauriWindows 更小) + Capacitor/TWAAndroid**
- 若你很在意桌面体积与原生安全性,**Tauri** 是比 Electron 更轻量的替代品(用 Rust 来打包、使用系统 WebView生成的二进制更小且性能好。缺点本地构建环境Rust / MSVC和插件生态比 Electron 小一些。
- Android 仍建议用 Capacitor 或 TWA 路线Tauri 的移动支持还在发展中)。
Tauri 打包基本:`npm run build`(前端)然后 `tauri build`(生成 Windows installer / exe——详见 Tauri 分发文档Windows 打包细节、WebView2 要求等)。
---
# 路线 C — 直接 PWA → Play最快上架 Android
如果你的 React 已经是 PWAmanifest + SW通过 **TWA**Trusted Web Activity把 PWA 裹进一个最小的 Android 应用是最快的上 Play 方式:用 **Bubblewrap** / PWABuilder 生成项目,然后签名上传 Play。适合不需要本地原生 API仅需离线缓存与简单推送的场景。
---
# 后端打包 vs 远端服务的建议(关键设计决策)
- **优先把后端作为远端服务**(部署到云/内网)——理由:升级、补丁、数据库统一管理、安全容易;前端变体(桌面/Android/PWA都指向同一 API开发运维简单。
- 仅在必须(离线、内网隔离)时,把后端打包到桌面:用 `pkg` / `nexe` 做 Node -> exe再由 Electron 启动子进程(`child_process.spawn`。Android 上嵌入 Node 很麻烦(可选 nodejs-mobile但生态少因此若后端要内嵌桌面比手机更现实。
---
# 上线前必须做的成熟化步骤checklist
1. **安全**HTTPS、CSP、Key/Secret 不放前端XSS/CSRF/认证策略。
2. **签名与发布**Windows 用 Authenticode 证书签名Android 用 Play App Signing上传签名/上传 key
3. **自动更新**Electron 有 `electron-updater`/electron-builder 集成;考虑 OTA 策略。
4. **CI/CD**:用 GitHub Actions / Azure / CircleCI 自动构建 web、electron dist、Android AAB包含签名步骤
5. **测试**:多架构/多机型测试、模拟断网、升级回滚测试。
6. **体积优化**:压缩静态资源、剔除 dev 依赖、考虑 Tauri 以减小 exe 体积。
---
# 推荐组合(按你想要的结果选)
- **最快上手 + 最成熟**ElectronWindows + CapacitorAndroid后端保留云端。
- **追求二进制最瘦**TauriWindows + Capacitor/TWAAndroid
- **只想最快上线到 Play不做原生功能**PWA → TWABubblewrap/PWABuilder
---
# 我可以直接帮你做的事(选一项即可回复)
1. 给你一份针对你 current React 项目的 **具体脚本package.json+ Electron 主进程示例 + electron-builder 配置**Windows 一键打包脚本)。
2. 给你一份 **Capacitor 打包到 Android 的 step-by-step 脚本 & Android Studio 签名操作流水线**(含 AAB 签名命令示例)。
3. 或者把 **把后端打包为 exe 的示例pkg/nexe并在 Electron 中 spawn 的最小示例** 发给你。
告诉我你要哪一项(例如“给我 Electron + 打包脚本”),我立刻把完整代码/命令/CI 配置直接生成给你(无需你再提供额外信息即可开始)。
---

View File

@@ -0,0 +1,79 @@
---
# ✅ **方式一:使用 Vite 初始化 React 项目(推荐,最快最轻量)**
### **1. 安装 Node.js必须**
确保 Node 版本 ≥ 18
检查:
```bash
node -v
```
---
### **2. 使用 Vite 创建 React 项目**
```bash
npm create vite@latest my-react-app -- --template react
```
如果你想要 TypeScript 版本:
```bash
npm create vite@latest my-react-app -- --template react-ts
```
---
### **3. 安装依赖**
```bash
cd my-react-app
npm install
```
---
### **4. 启动开发环境**
```bash
npm run dev
```
浏览器访问提示的 localhost 地址即可。
---
# ✅ **方式二:使用 Create-React-App传统方案不推荐但能用**
CRA 已多年未更新,官方推荐迁移到 Vite
### 1. 创建项目
```bash
npx create-react-app my-react-app
```
### 2. 启动项目
```bash
cd my-react-app
npm start
```
---
# ✅ **方式三:使用 Next.js如果你准备做大一点的项目**
如果你想做:
✔ SEO
✔ 服务端渲染
✔ 大型项目结构
✔ API 路由
推荐 Next.js
```bash
npx create-next-app@latest
```
---

View File

@@ -0,0 +1,154 @@
---
## 一、交互式命令(以 `.` 开头)
在 SQLite 命令行中执行:
| 命令 | 说明 |
|------|------|
| `.help` | 查看所有命令帮助 |
| `.open 文件名` | 打开或创建数据库文件 |
| `.databases` | 显示当前打开的数据库 |
| `.tables` | 显示所有表 |
| `.schema [表名]` | 显示表结构(不加表名则显示所有) |
| `.dump [表名]` | 导出数据库或表的 SQL 语句(用于备份) |
| `.output 文件名` | 将查询结果输出到文件(默认输出到屏幕) |
| `.read 脚本文件` | 执行 SQL 脚本文件 |
| `.mode 模式` | 设置输出模式(如 `csv`, `column`, `list`, `html` 等) |
| `.headers on/off` | 显示/隐藏列标题 |
| `.quit``.exit` | 退出 SQLite 命令行 |
| `.import 文件 表名` | 从 CSV 文件导入数据到表 |
| `.show` | 显示当前设置(如输出模式、分隔符等) |
| `.indexes [表名]` | 显示索引信息 |
| `.backup 文件名` | 备份数据库到文件 |
---
## 二、常用 SQL 语句
### 1. 数据库与表操作
```sql
-- 创建表
CREATE TABLE (
1 [],
2 [],
...
);
-- 删除表
DROP TABLE ;
-- 重命名表
ALTER TABLE RENAME TO ;
-- 添加列
ALTER TABLE ADD COLUMN ;
-- 删除列SQLite 3.35+ 支持)
ALTER TABLE DROP COLUMN ;
```
### 2. 数据操作CRUD
```sql
-- 插入数据
INSERT INTO (1, 2) VALUES (1, 2);
-- 查询数据
SELECT * FROM ;
SELECT 1, 2 FROM WHERE ;
-- 更新数据
UPDATE SET 1= WHERE ;
-- 删除数据
DELETE FROM WHERE ;
```
### 3. 索引操作
```sql
-- 创建索引
CREATE INDEX ON ();
-- 删除索引
DROP INDEX ;
```
### 4. 视图操作
```sql
-- 创建视图
CREATE VIEW AS SELECT ...;
-- 删除视图
DROP VIEW ;
```
### 5. 事务控制
```sql
BEGIN TRANSACTION; -- 开始事务
COMMIT; -- 提交事务
ROLLBACK; -- 回滚事务
```
### 6. 实用查询
```sql
-- 条件查询
SELECT * FROM WHERE ;
-- 排序
SELECT * FROM ORDER BY ASC/DESC;
-- 分组统计
SELECT , COUNT(*) FROM GROUP BY ;
-- 连接查询
SELECT * FROM 1 JOIN 2 ON ;
-- 限制结果数量
SELECT * FROM LIMIT OFFSET ;
```
---
## 三、常用函数示例
```sql
SELECT COUNT(*) FROM ; -- 计数
SELECT MAX(), MIN() FROM ; -- 最大/最小值
SELECT AVG(), SUM() FROM ; -- 平均值/求和
SELECT datetime('now'); -- 当前时间
SELECT DATE('now', '+1 day'); -- 日期计算
```
---
## 四、使用示例
```bash
# 1. 进入 SQLite 命令行并打开数据库
sqlite3 test.db
# 2. 查看所有表
.tables
# 3. 创建表
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
# 4. 插入数据
INSERT INTO users (name) VALUES ('张三');
# 5. 查询数据
SELECT * FROM users;
# 6. 导出 SQL 备份
.output backup.sql
.dump
# 7. 退出
.quit
```
---
## 注意事项
1. SQLite 中 **没有用户管理和权限控制**
2. 所有数据库保存在单个文件中(`.db``.sqlite`
3. 大部分 SQL 标准语法支持,但某些高级功能(如存储过程、外键约束需显式启用)有限制
4. 可通过 `.read` 命令批量执行 SQL 脚本

View File

@@ -0,0 +1,15 @@
**TCP连接建立过程**
首先Client端发送连接请求报文Server段接受连接后回复ACK报文并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文并分配资源这样TCP连接就建立了。
**TCP连接断开过程**
假设Client端发起中断连接请求也就是发送FIN报文。Server端接到FIN报文后意思是说"我Client端没有数据要发给你了"但是如果你还有数据没有发送完成则不必急着关闭Socket可以继续发送数据。所以你先发送ACK"告诉Client端你的请求我收到了但是我还没准备好请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态继续等待Server端的FIN报文。当Server端确定数据已发送完成则向Client端发送FIN报文"告诉Client端好了我这边数据发完了准备好关闭连接了"。Client端收到FIN报文后"就知道可以关闭连接了但是他还是不相信网络怕Server端不知道要关闭所以发送ACK后进入TIME_WAIT状态如果Server端没有收到ACK则可以重传。"Server端收到ACK后"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复则证明Server端已正常关闭那好我Client端也可以关闭连接了。OkTCP连接就这样关闭了
**为什么要三次握手?**
在只有两次"握手"的情形下假设Client想跟Server建立连接但是却因为中途连接请求的数据报丢失了故Client端不得不重新发送一遍这个时候Server端仅收到一个连接请求因此可以正常的建立连接。但是有时候Client端重新发送请求不是因为数据报丢失了而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了这种情形下Server端将先后收到2次请求并持续等待两个Client请求向他发送数据...问题就在这里Cient端实际上只有一次请求而Server端却有2个响应极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待因而造成极大的资源浪费所以"三次握手"很有必要!
**为什么要四次挥手?**
试想一下假如现在你是客户端你想断开跟Server的所有连接该怎么做第一步你自己先停止向Server端发送数据并等待Server的回复。但事情还没有完虽然你自身不往Server发送数据了但是因为你们之前已经建立好平等的连接了所以此时他也有主动权向你发送数据故Server端还得终止主动向你发送数据并等待你的确认。其实说白了就是保证双方的一个合约的完整执行
使用TCP的协议FTP文件传输协议、Telnet远程登录协议、SMTP简单邮件传输协议、POP3和SMTP相对用于接收邮件、HTTP协议等。

View 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**(超文本传输协议)

View File

@@ -0,0 +1,324 @@
## 1. 环境准备
### 1.1 安装Node.js
- 访问 [Node.js官网](https://nodejs.org/) 下载LTS版本
- 验证安装:
```bash
node --version
npm --version
```
### 1.2 安装Vue CLI可选推荐使用Vite
```bash
npm install -g @vue/cli
# 或
yarn global add @vue/cli
```
## 2. 使用Vite创建Vue项目推荐方式
### 2.1 创建项目
```bash
# 使用npm
npm create vue@latest
# 或使用yarn
yarn create vue
# 或使用pnpm
pnpm create vue
```
### 2.2 交互式配置
执行命令后,你会看到以下选项:
```
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
```
### 2.3 进入项目并运行
```bash
cd <project-name>
npm install
npm run dev
```
## 3. 使用Vue CLI创建项目传统方式
### 3.1 创建项目
```bash
vue create my-project
```
### 3.2 选择预设
```
? Please pick a preset:
Default ([Vue 2] babel, eslint)
Default (Vue 3) ([Vue 3] babel, eslint)
Manually select features
```
### 3.3 选择功能
```
? Check the features needed for your project:
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
❯◉ Router
◉ Vuex
◉ CSS Pre-processors
◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing
```
## 4. 项目结构说明
使用Vite创建的典型项目结构
```
my-vue-project/
├── node_modules/
├── public/
│ └── favicon.ico
├── src/
│ ├── assets/
│ │ └── logo.svg
│ ├── components/
│ │ └── HelloWorld.vue
│ ├── router/
│ │ └── index.js
│ ├── stores/
│ │ └── counter.js
│ ├── views/
│ │ ├── AboutView.vue
│ │ └── HomeView.vue
│ ├── App.vue
│ └── main.js
├── .gitignore
├── index.html
├── package.json
├── README.md
└── vite.config.js
```
## 5. 基础配置示例
### 5.1 修改vite.config.js
```javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
server: {
port: 3000,
open: true
}
})
```
### 5.2 配置ESLint + Prettier
`.eslintrc.cjs`:
```javascript
module.exports = {
root: true,
env: {
node: true,
browser: true,
es2021: true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'@vue/eslint-config-prettier'
],
rules: {
'vue/multi-word-component-names': 'off'
}
}
```
`.prettierrc`:
```json
{
"semi": false,
"singleQuote": true,
"printWidth": 80,
"trailingComma": "none",
"tabWidth": 2
}
```
## 6. 安装常用依赖
```bash
# 状态管理
npm install pinia
# UI框架按需选择
npm install element-plus
# 或
npm install ant-design-vue
# 或
npm install vuetify
# HTTP客户端
npm install axios
# 路由
npm install vue-router@4
# 日期处理
npm install dayjs
# 工具函数
npm install lodash-es
```
## 7. 创建第一个组件
`src/components/HelloWorld.vue`:
```vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="count++">Count is: {{ count }}</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
defineProps({
msg: String
})
const count = ref(0)
</script>
<style scoped>
.hello {
text-align: center;
margin-top: 50px;
}
</style>
```
## 8. 配置路由
`src/router/index.js`:
```javascript
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
```
## 9. 启动和构建
```bash
# 开发模式
npm run dev
# 生产构建
npm run build
# 预览生产构建
npm run preview
# 代码检查
npm run lint
```
## 10. 最佳实践建议
### 10.1 项目组织
```
src/
├── api/ # API接口
├── assets/ # 静态资源
├── components/ # 公共组件
├── composables/ # 组合式函数
├── directives/ # 自定义指令
├── router/ # 路由配置
├── stores/ # 状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
└── views/ # 页面组件
```
### 10.2 Git提交规范
```bash
# 安装commitlint
npm install @commitlint/config-conventional @commitlint/cli -D
# 创建.commitlintrc.js
echo "module.exports = { extends: ['@commitlint/config-conventional'] }" > .commitlintrc.js
```
### 10.3 环境变量配置
创建`.env`文件:
```env
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=My Vue App
```
## 常见问题
### Q: 安装缓慢?
- 使用淘宝镜像:`npm config set registry https://registry.npmmirror.com`
- 使用pnpm`npm install -g pnpm`
### Q: 端口被占用?
```javascript
// vite.config.js
server: {
port: 3000 // 修改端口号
}
```
### Q: 需要支持旧浏览器?
```javascript
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults', 'not IE 11']
})
]
}
```

View File

@@ -0,0 +1 @@
theme: jekyll-theme-minimal

View File

@@ -0,0 +1,369 @@
以下是针对 **BusyBox** 中每条命令的简要说明:
1. **[**:测试表达式的真假。
2. **[[**:增强版的条件测试命令。
3. **acpid**:管理系统的 ACPI 事件。
4. **adjtimex**:调整系统时间。
5. **ar**:创建、修改、提取归档文件。
6. **arch**:显示机器架构类型。
7. **arp**:显示或修改 ARP 缓存。
8. **arping**:向网络发送 ARP 请求。
9. **ascii**:显示 ASCII 表。
10. **ash**:一个轻量级的 shell。
11. **awk**:强大的文本处理工具。
12. **base32**:以 Base32 编码格式进行数据转换。
13. **base64**:以 Base64 编码格式进行数据转换。
14. **basename**:从路径中提取文件名。
15. **bbconfig**:配置 BusyBox。
16. **beep**:产生蜂鸣声。
17. **blkdiscard**:丢弃磁盘块。
18. **blkid**:显示块设备的标识。
19. **blockdev**:对块设备进行操作。
20. **brctl**:管理网桥接口。
21. **bunzip2**:解压 `.bz2` 格式文件。
22. **bzcat**:查看 `.bz2` 格式文件内容。
23. **bzip2**:压缩文件为 `.bz2` 格式。
24. **cal**:显示日历。
25. **cat**:连接文件并显示内容。
26. **chat**:发送控制字符以进行调制解调器通信。
27. **chattr**:改变文件的属性。
28. **chcon**:改变文件的 SELinux 上下文。
29. **chgrp**:改变文件的组。
30. **chmod**:改变文件的权限。
31. **chown**:改变文件的拥有者。
32. **chroot**:改变根目录。
33. **chrt**:操作进程的调度策略。
34. **chvt**:切换虚拟终端。
35. **cksum**:计算文件的校验和。
36. **clear**:清除终端屏幕。
37. **cmp**:比较两个文件。
38. **comm**:比较两个已排序文件的内容。
39. **conspy**:查看控制台的输出。
40. **cp**:复制文件。
41. **cpio**:创建、解压 cpio 格式归档。
42. **crc32**:计算 CRC32 校验和。
43. **crond**:周期性执行任务的守护进程。
44. **crontab**:编辑 cron 表。
45. **cttyhack**:改变控制终端。
46. **cut**:按列剪切文本。
47. **date**:显示或设置系统日期和时间。
48. **dc**:计算器程序。
49. **dd**:转换和复制文件。
50. **deallocvt**:释放虚拟终端。
51. **depmod**:生成内核模块依赖关系。
52. **devmem**:访问物理内存。
53. **df**:显示文件系统的磁盘空间使用情况。
54. **dhcprelay**:转发 DHCP 请求。
55. **diff**:比较文件的不同之处。
56. **dirname**:获取路径的目录部分。
57. **dmesg**:显示内核的消息缓冲区内容。
58. **dnsd**:轻量级 DNS 服务器。
59. **dnsdomainname**:显示域名。
60. **dos2unix**:转换 DOS 格式文本为 Unix 格式。
61. **du**:显示磁盘使用情况。
62. **dumpkmap**:转储键盘映射。
63. **dumpleases**:显示 DHCP 租约。
64. **echo**:显示一行文本。
65. **ed**:文本编辑器。
66. **egrep**:扩展正则表达式的 grep 命令。
67. **eject**:弹出光盘。
68. **env**:显示或设置环境变量。
69. **ether-wake**:发送 Wake-on-LAN 魔术包。
70. **expand**:将制表符转换为空格。
71. **expr**:计算表达式的值。
72. **factor**:因数分解。
73. **fakeidentd**:模拟 identd 服务。
74. **false**:返回失败状态。
75. **fatattr**:显示或修改 FAT 文件系统的属性。
76. **fbset**:设置帧缓冲设备的参数。
77. **fbsplash**:管理帧缓冲启动画面。
78. **fdflush**:刷新文件描述符。
79. **fdformat**:格式化软盘。
80. **fdisk**:管理磁盘分区。
81. **fgconsole**:切换到指定的虚拟终端。
82. **fgrep**:固定字符串搜索工具。
83. **find**:搜索文件。
84. **findfs**:查找文件系统。
85. **flash_eraseall**:擦除闪存设备。
86. **flash_lock**:锁定闪存设备。
87. **flash_unlock**:解锁闪存设备。
88. **flock**:对文件进行锁定。
89. **fold**:折叠文本行。
90. **free**:显示内存使用情况。
91. **freeramdisk**:释放 RAM 磁盘。
92. **fsck**:检查文件系统的完整性。
93. **fsck.minix**:检查 Minix 文件系统。
94. **fsfreeze**:冻结文件系统以进行备份。
95. **fstrim**:修剪未使用的磁盘空间。
96. **fsync**:强制磁盘同步。
97. **ftpd**:启动 FTP 服务器。
98. **ftpget**:下载文件通过 FTP。
99. **ftpput**:上传文件通过 FTP。
100. **fuser**:显示正在使用某个文件的进程。
101. **getenforce**:显示 SELinux 的状态。
102. **getopt**:解析命令行选项。
103. **grep**:搜索文本中的模式。
104. **groups**:显示用户所属的组。
105. **gunzip**:解压 `.gz` 文件。
106. **gzip**:压缩文件为 `.gz` 格式。
107. **hd**:显示硬盘的分区信息。
108. **hdparm**:设置硬盘参数。
109. **head**:显示文件的开头部分。
110. **hexdump**:以十六进制格式显示文件内容。
111. **hexedit**:编辑十六进制文件。
112. **hostname**:显示或设置主机名。
113. **httpd**:启动 HTTP 服务器。
114. **hush**:一个小型 shell。
115. **hwclock**:访问硬件时钟。
116. **id**:显示用户和组信息。
117. **ifconfig**:配置网络接口。
118. **ifdown**:关闭网络接口。
119. **ifenslave**:配置链路聚合。
120. **ifplugd**:监控网络接口的连接状态。
121. **ifup**:启用网络接口。
122. **inetd**:启动网络服务守护进程。
123. **inotifyd**:启动文件系统事件监控。
124. **insmod**:加载内核模块。
125. **install**:复制文件并设置权限。
126. **ionice**:设置进程的 I/O 优先级。
127. **iostat**:显示 CPU 和 I/O 统计信息。
128. **ip**:配置网络接口和路由。
129. **ipaddr**:显示或设置 IP 地址。
130. **ipcalc**:计算和显示 IP 地址信息。
131. **ipcrm**:删除共享内存、消息队列、信号量。
132. **ipcs**:显示进程间通信的状态。
133. **iplink**:管理网络接口的状态。
134. **ipneigh**:显示邻居表。
135. **iproute**:管理路由表。
136. **iprule**:显示或管理路由规则。
137. **iptunnel**:配置 IP 隧道。
138. **kbd_mode**:设置键盘模式。
139. **kill**:终止进程。
140. **killall**:终止指定名称的所有进程。
141. **killall5**:终止所有进程。
142. **klogd**:内核日志守护进程。
143. **less**:分页显示文件内容。
144. **link**:创建硬链接。
145. **ln**:创建硬链接或符号链接。
146. **loadfont**:加载字体。
147. **loadkmap**:加载键盘映射。
148. **logread**:显示日志文件内容。
149. **losetup**:管理环回设备。
150. **ls**:列出目录内容。
151. **lsattr**:显示文件的属性。
152. **lsmod**:显示加载的内核模块。
153. **lsof**:列出打开的文件。
154. **lspci**:显示所有 PCI 设备。
155. **lsscsi**:显示 SCSI 设备信息。
156. **lsusb**:列出 USB 设备。
157. **lzcat**:解压 `.lz` 文件并显示内容。
158. **lzma**:压缩文件为 `.lzma` 格式。
159. **lzop**:快速的文件压缩工具。
160. **lzopcat**:查看 `.lzo` 格式文件内容。
161. **makedevs**:创建设备节点。
162. **makemime**:生成 MIME 类型文件。
163. **man**:查看手册页(如果有)。
164. **md5sum**:计算文件的 MD5 校验和。
165. **mesg**:控制终端消息的接收。
166. **microcom**:串行通信工具。
167. **mim**:提取文件的 MIME 类型。
168. **mkdir**:创建目录。
169. **mkdosfs**:创建 FAT 文件系统。
170. **mke2fs**:创建 ext2 文件系统。
171. **mkfifo**:创建命名管道。
172. **mkfs.ext2**:创建 ext2 文件系统。
173. **mkfs.minix**:创建 Minix 文件系统。
174. **mkfs.reiser**:创建 Reiser 文件系统。
175. **mkfs.vfat**:创建 VFAT 文件系统。
176. **mknod**:创建块设备或字符设备文件。
177. **mkswap**:创建交换分区。
178. **mktemp**:创建临时文件。
179. **modinfo**:显示内核模块的信息。
180. **modprobe**:加载或卸载内核模块。
181. **more**:分页显示文件内容。
182. **mount**:挂载文件系统。
183. **mountpoint**:检查是否为挂载点。
184. **mpstat**:显示 CPU 使用统计信息。
185. **mv**:移动或重命名文件。
186. **nameif**:根据 MAC 地址设置网络接口名称。
187. **nanddump**:转储 NAND 闪存的内容。
188. **nandwrite**:将数据写入 NAND 闪存。
189. **nbd-client**:连接到网络块设备。
190. **nc**Netcat 工具,用于读写网络连接。
191. **netstat**:显示网络连接状态。
192. **nice**:调整进程的优先级。
193. **nl**:显示带有行号的文件内容。
194. **nmeter**:网络带宽监控工具。
195. **nohup**:在后台运行命令并忽略挂起信号。
196. **nologin**:禁止用户登录。
197. **nsenter**:进入其他命名空间。
198. **nslookup**:查询 DNS 信息。
199. **nuke**:终止所有与特定进程相关的网络连接。
200. **od**:以不同格式显示文件内容(如十六进制)。
201. **openvt**:在指定的虚拟终端上运行命令。
202. **partprobe**:通知操作系统重新读取分区表。
203. **paste**:合并多个文件按列显示。
204. **patch**:应用补丁文件。
205. **pgrep**:查找匹配指定模式的进程。
206. **pidof**:查找指定进程的 PID。
207. **ping**:向网络主机发送 ICMP 请求。
208. **ping6**:向网络主机发送 ICMPv6 请求。
209. **pipe_progress**:显示管道中的数据传输进度。
210. **pivot_root**:更改文件系统根目录。
211. **pkill**:根据进程名终止进程。
212. **pmap**:显示进程的内存映射。
213. **popmaildir**:从邮件目录中获取邮件。
214. **poweroff**:关闭计算机。
215. **powertop**:用于优化电源管理的工具。
216. **printenv**:显示所有环境变量。
217. **printf**:格式化并输出文本。
218. **ps**:显示当前进程信息。
219. **pscan**:扫描当前进程的状态。
220. **pstree**:以树形结构显示进程。
221. **pwd**:显示当前工作目录。
222. **pwdx**:显示指定进程的工作目录。
223. **raidautorun**:自动启动 RAID 配置。
224. **rdate**:同步时间。
225. **rdev**:显示或设置设备的特殊属性。
226. **readlink**:显示符号链接的目标。
227. **readprofile**:读取并显示应用的性能配置。
228. **realpath**:返回文件的绝对路径。
229. **reboot**:重启系统。
230. **reformime**:转换 MIME 格式。
231. **renice**:改变进程的优先级。
232. **reset**:重置终端。
233. **resize**:调整终端大小。
234. **resume**:恢复挂起的进程。
235. **rev**:反转每行文本。
236. **rfkill**:管理无线设备的开关。
237. **rm**:删除文件。
238. **rmdir**:删除空目录。
239. **rmmod**:卸载内核模块。
240. **route**:显示或修改路由表。
241. **rtcwake**:设置系统的 RTC 来定时唤醒。
242. **run-init**:运行初始化程序。
243. **run-parts**:按顺序运行目录中的脚本。
244. **runcon**:设置进程的 SELinux 上下文。
245. **rx**:接收串口数据。
246. **script**:记录终端会话。
247. **scriptreplay**:重放记录的终端会话。
248. **sed**:流编辑器,用于处理文本数据。
249. **seedrng**:种子随机数生成器。
250. **selinuxenabled**:检查 SELinux 是否启用。
251. **sendmail**:发送电子邮件。
252. **seq**:生成一个数字序列。
253. **sestatus**:显示 SELinux 状态。
254. **setconsole**:设置控制台的终端类型。
255. **setenforce**:启用或禁用 SELinux 强制模式。
256. **setfattr**:设置文件的扩展属性。
257. **setfont**:设置终端的字体。
258. **setkeycodes**:设置键盘扫描码到键值的映射。
259. **setlogcons**:设置日志控制台。
260. **setpriv**:设置进程的特权级别。
261. **setserial**:设置串口设备的参数。
262. **setsid**:创建新的会话并运行命令。
263. **setuidgid**:设置进程的用户和组标识。
264. **sh**:启动一个新的 shell。
265. **sha1sum**:计算文件的 SHA-1 校验和。
266. **sha256sum**:计算文件的 SHA-256 校验和。
267. **sha3sum**:计算文件的 SHA-3 校验和。
268. **sha512sum**:计算文件的 SHA-512 校验和。
269. **showkey**:显示键盘输入的键值。
270. **shred**:擦除文件,防止数据恢复。
271. **shuf**:随机排列输入行。
272. **slattach**:设置串行连接。
273. **sleep**:暂停一段时间。
274. **smemcap**:设置进程内存使用限制。
275. **sort**:按行排序文本文件。
276. **split**:将文件分割成多个小文件。
277. **ssl_client**:通过 SSL 连接远程主机。
278. **start-stop-daemon**:启动或停止后台守护进程。
279. **stat**:显示文件或文件系统的状态。
280. **strings**:显示文件中的可打印字符串。
281. **stty**:设置终端行属性。
282. **sum**:计算文件的校验和。
283. **svc**:启动、停止或重启服务。
284. **svok**:检查服务的状态。
285. **swapoff**:禁用交换空间。
286. **swapon**:启用交换空间。
287. **switch_root**:切换到新的根文件系统。
288. **sync**:同步文件系统。
289. **sysctl**:显示或设置内核参数。
290. **syslogd**:启动系统日志守护进程。
291. **tac**:反向显示文件内容。
292. **tail**:显示文件的最后部分。
293. **tar**:创建和解压 tar 归档。
294. **tc**:配置网络流量控制。
295. **tcpsvd**TCP 服务守护进程。
296. **tee**:将输入内容输出到多个文件。
297. **telnet**:远程登录到另一个计算机。
298. **telnetd**:启动 Telnet 服务器。
299. **test**:检查条件的真假。
300. **tftp**:简易的文件传输协议客户端。
301. **tftpd**TFTP 服务器。
302. **time**:测量命令执行时间。
303. **timeout**:设置命令的超时时间。
304. **top**:显示系统进程信息。
305. **touch**:创建空文件或更新文件的时间戳。
306. **tr**:替换或删除字符。
307. **traceroute**:追踪数据包在网络中的路由。
308. **traceroute6**:追踪 IPv6 数据包的路由。
309. **tree**:以树形结构显示目录内容。
310. **true**:始终返回成功状态。
311. **truncate**:截断文件到指定长度。
312. **ts**:为每行添加时间戳。
313. **tsort**:排序文件中的时间戳。
314. **tty**:显示终端设备名称。
315. **ttysize**:显示终端的大小。
316. **tunctl**:管理 TUN/TAP 网络设备。
317. **tune2fs**:调整 ext2/ext3/ext4 文件系统的参数。
318. **ubiattach**:附加 UBI 设备。
319. **ubidetach**:分离 UBI 设备。
320. **ubimkvol**:创建 UBI 卷。
321. **ubirename**:重命名 UBI 卷。
322. **ubirmvol**:删除 UBI 卷。
323. **ubirsvol**:恢复 UBI 卷。
324. **ubiupdatevol**:更新 UBI 卷的数据。
325. **udhcpc**DHCP 客户端,用于获取网络配置信息。
326. **udhcpc6**DHCPv6 客户端。
327. **udhcpd**DHCP 服务器。
328. **udpsvd**UDP 服务守护进程。
329. **uevent**:显示系统的 udev 事件。
330. **umount**:卸载文件系统。
331. **uname**:显示系统信息。
332. **uncompress**:解压 `.Z` 格式文件。
333. **unexpand**:将空格转换为制表符。
334. **uniq**:删除重复的行。
335. **unix2dos**:转换 Unix 格式文本为 DOS 格式。
336. **unlink**:删除文件。
337. **unlzma**:解压 `.lzma` 格式文件。
338. **unlzop**:解压 `.lzo` 格式文件。
339. **unshare**:在新命名空间中运行命令。
340. **unxz**:解压 `.xz` 格式文件。
341. **unzip**:解压 `.zip` 文件。
342. **uptime**:显示系统的运行时间和负载。
343. **usleep**:暂停指定的微秒数。
344. **uudecode**:解码 `.uu` 格式文件。
345. **uuencode**:编码文件为 `.uu` 格式。
346. **vconfig**:管理 VLAN 网络接口。
347. **vi**:文本编辑器。
348. **volname**:显示文件系统的卷标。
349. **watch**:定期执行并显示命令输出。
350. **watchdog**:监控系统状态并在需要时重启。
351. **wc**:计算文件的行数、字数和字符数。
352. **wget**:下载文件。
353. **which**:显示可执行文件的路径。
354. **whoami**:显示当前用户的用户名。
355. **whois**:查询域名注册信息。
356. **xargs**:将标准输入转换为命令行参数。
357. **xxd**:创建十六进制转储。
358. **xz**:压缩文件为 `.xz` 格式。
359. **xzcat**:查看 `.xz` 格式文件内容。
360. **yes**:输出指定字符串,通常用来测试管道。
361. **zcat**:查看 `.gz` 格式文件内容。
362. **zcip**:配置 ZCIP 地址。
这些命令覆盖了文件操作、系统管理、网络配置、进程管理等多个方面,是 BusyBox 在资源受限环境中为用户提供常用功能的集合。

View File

@@ -0,0 +1,36 @@
### 一句命令启动busybox的简单http服务器
```shell
busybox httpd -f -p 端口 -h 目录
```
### 查看端口占用情况
- `-t`:显示 TCP 连接
- `-u`:显示 UDP 连接
- `-l`:只显示正在监听的端口
- `-n`:显示数字形式的地址和端口号,而不进行域名解析
```shell
busybox netstat -tuln
```
### 启动busybox的ftp服务器
```shell
busybox ftp -d 目录 -p 端口
busybox ftp -d 目录 #默认占用21端口
sudo mkdir -p 目录
sudo chmod 755 目录
```
### 启动 `busybox` 的 Telnet 服务器
```
busybox telnetd -l /bin/login
busybox telnetd -p 2323 -l /bin/login
```

View File

@@ -0,0 +1,31 @@
```c++
#include <iostream>
#include <string>
using namespace std;
int countSubstrings(const string& str, const string& sub) {
int count = 0;
size_t pos = 0;
// 循环直到找不到子字符串
while ((pos = str.find(sub, pos)) != string::npos) {
count++; // 找到一个子字符串计数器加1
pos += sub.length(); // 更新位置,跳过已找到的子字符串
}
return count;
}
int main() {
string str = "ababcabcabcab";
string sub = "abc";
int result = countSubstrings(str, sub);
cout << "子字符串 \"" << sub << "\" 在字符串 \"" << str << "\" 中出现的次数是: " << result << endl;
return 0;
}
```
### TMD一生之耻

View File

@@ -0,0 +1,83 @@
`crontab` 是一个用于在 Unix 和类 Unix 系统(如 Linux中设置定时任务的工具。它允许用户根据指定的时间间隔安排脚本或命令的执行。
> 目前我用来代替 systemctl的服务
### 基本概念
`crontab` 的配置文件由一系列行组成,每行代表一个定时任务,其基本格式如下:
```plaintext
* * * * * command
```
这五个 `*` 分别代表分钟0 - 59、小时0 - 23、日期1 - 31、月份1 - 12和星期0 - 7其中 0 和 7 都代表星期日),`command` 是要执行的命令或脚本。
### 使用步骤
#### 1. 编辑 `crontab` 文件
可以使用以下命令编辑当前用户的 `crontab` 文件:
```bash
crontab -e
```
首次使用时,系统会提示选择一个文本编辑器,选择你熟悉的编辑器(如 `nano``vim`)即可。
#### 2. 添加定时任务
在打开的 `crontab` 文件中添加定时任务,下面是一些具体的示例:
##### 示例 1每分钟执行一次命令
```plaintext
* * * * * /usr/bin/echo "This is a test" >> /tmp/test.log
```
这个任务会每分钟执行一次,将 `"This is a test"` 追加到 `/tmp/test.log` 文件中。
##### 示例 2每小时的第 30 分钟执行一次命令
```plaintext
30 * * * * /usr/bin/backup_script.sh
```
这个任务会在每小时的第 30 分钟执行 `/usr/bin/backup_script.sh` 脚本。
##### 示例 3每天凌晨 2 点执行一次命令
```plaintext
0 2 * * * /usr/bin/daily_cleanup.sh
```
这个任务会在每天凌晨 2 点执行 `/usr/bin/daily_cleanup.sh` 脚本。
##### 示例 4每月 1 号的 3 点 15 分执行一次命令
```plaintext
15 3 1 * * /usr/bin/monthly_report.sh
```
这个任务会在每月 1 号的 3 点 15 分执行 `/usr/bin/monthly_report.sh` 脚本。
##### 示例 5每周日的 18 点执行一次命令
```plaintext
0 18 * * 0 /usr/bin/weekly_backup.sh
```
这个任务会在每周日的 18 点执行 `/usr/bin/weekly_backup.sh` 脚本。
##### 示例 6指定时间范围执行命令
```plaintext
0 9-17 * * 1-5 /usr/bin/workday_check.sh
```
这个任务会在周一至周五的 9 点到 17 点之间,每小时的整点执行 `/usr/bin/workday_check.sh` 脚本。
##### 示例 7每隔一段时间执行命令
```plaintext
*/15 * * * * /usr/bin/check_status.sh
```
这个任务会每隔 15 分钟执行一次 `/usr/bin/check_status.sh` 脚本。
#### 3. 保存并退出
编辑完成后,保存并退出文本编辑器。如果使用 `nano` 编辑器,按 `Ctrl + X`,然后按 `Y` 确认保存,最后按 `Enter` 键退出。如果使用 `vim` 编辑器,按 `Esc` 键,输入 `:wq` 并按 `Enter` 键保存并退出。
#### 4. 查看 `crontab` 文件内容
可以使用以下命令查看当前用户的 `crontab` 文件内容:
```bash
crontab -l
```
#### 5. 删除 `crontab` 文件
如果需要删除当前用户的所有定时任务,可以使用以下命令:
```bash
crontab -r
```
### 注意事项
- **环境变量**`crontab` 任务在执行时使用的环境变量可能与用户登录时不同。如果脚本依赖特定的环境变量,需要在脚本中明确设置。
- **日志记录**:建议将定时任务的输出重定向到日志文件,以便后续排查问题。
- **权限问题**:确保执行的命令或脚本具有足够的权限。

View 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 或 TampermonkeyJS 注入)管理。
---
# 目录
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);
})();
```

View File

@@ -0,0 +1,16 @@
QQ机器人napcat
docker run -d \
-e NAPCAT_GID=$(id -g) \
-e NAPCAT_UID=$(id -u) \
-p 3000:3000 \
-p 3001:3001 \
-p 3002:6099 \
--name napcat \
--restart=always \
mlikiowa/napcat-docker:latest
微信机器人gewe
docker run -itd -v /shumengya/bin/wechatbot:/root/temp -p 2531:2531 -p 2532:2532 --privileged=true --name=gewe gewe /usr/sbin/init

View File

@@ -0,0 +1,60 @@
### 使用 yum 安装 systemdCentOS/RHEL
```
yum install systemd
```
### 使用 apt 安装 systemdDebian/Ubuntu
```
apt install systemd
sudo vim /etc/systemd/system/frps.service
```
### 服务名称,可自定义
```
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
```
### 启动frps的命令需修改为您的frps的安装路径
```
ExecStart = /path/to/frps -c /path/to/frps.toml
[Install]
WantedBy = multi-user.target
```
### 启动frp
```
sudo systemctl start frps
```
### 停止frp
```
sudo systemctl stop frps
```
### 重启frp
```
sudo systemctl restart frps
```
### 查看frp状态
```
sudo systemctl status frps
sudo systemctl enable frps
```

View File

@@ -0,0 +1,66 @@
https://storage.googleapis.com/docscloudstorage/2022.3/UnityDocumentation.zip
ChatGPT响应: Markdown中的一些常用标识符包括
1. **标题**:使用`#`表示不同级别的标题
```markdown
# 一级标题
## 二级标题
### 三级标题
```
2. **粗体**:使用`**`或`__`包围文本
```markdown
**粗体文本** 或 __粗体文本__
```
3. **斜体**:使用`*`或`_`包围文本
```markdown
*斜体文本* 或 _斜体文本_
```
4. **无序列表**:使用`-`、`*`或`+`
```markdown
- 项目1
* 项目2
+ 项目3
```
5. **有序列表**:使用数字加点
```markdown
1. 第一项
2. 第二项
```
6. **链接**:使用`[链接文本](URL)`
```markdown
[这是一个链接](https://example.com)
```
7. **图片**:使用`![图片描述](图片URL)`
```markdown
![示例图片](https://example.com/image.png)
```
8. **代码块**:使用反引号`` ` ``
```markdown
`行内代码`
```
或使用三个反引号表示多行代码
```markdown
```
多行代码
```
```
9. **引用**:使用`>`
```markdown
> 这是一个引用
```
10. **水平线**:使用三个或以上的`-`、`*`或`_`
```markdown
---
```

View File

@@ -0,0 +1,39 @@
1. **markdown-it**:
- **简介**: 一个功能强大且可扩展的 Markdown 解析器,支持插件和自定义规则。
- **安装**: 可以通过 npm 安装:`npm install markdown-it`
- **使用示例**:
```javascript
const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();
const result = md.render('# 你好Markdown!');
console.log(result);
```
2. **marked**:
- **简介**: 一个快速、轻量级的 Markdown 解析器,支持自定义渲染器。
- **安装**: 使用 npm 安装:`npm install marked`
- **使用示例**:
```javascript
const marked = require('marked');
const result = marked('# 你好Markdown!');
console.log(result);
```
3. **remark**:
- **简介**: 一个强大的 Markdown 处理库,支持解析、检查和转换 Markdown 文档。
- **安装**: 通过 npm 安装:`npm install remark remark-html`
- **使用示例**:
```javascript
const remark = require('remark');
const html = require('remark-html');
remark()
.use(html)
.process('# 你好Markdown!', function (err, file) {
if (err) throw err;
console.log(String(file));
});
```
这些库各有优点,选择哪个库取决于您的具体需求,比如性能、可扩展性、支持的特性等。如果你需要简单的解析和渲染,`marked` 和 `markdown-it` 都是不错的选择;如果需要更多的可扩展性和插件支持,`remark` 可能更适合。

View File

@@ -0,0 +1,283 @@
### Linux `systemctl` 命令常用用法总结
#### **一、服务管理(核心功能)**
`systemctl` 主要用于管理系统服务(`.service` 文件),支持启动、停止、重启、查看状态、设置开机启动等操作。
##### 1. 服务状态操作
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 启动服务 | `systemctl start <服务名>` | 启动指定服务(仅临时生效,重启后不保留) |
| 停止服务 | `systemctl stop <服务名>` | 停止指定服务 |
| 重启服务 | `systemctl restart <服务名>` | 重启服务(若服务未运行则启动) |
| 重新加载配置 | `systemctl reload <服务名>` | 重新加载服务配置文件(不重启服务,适用于支持此功能的服务,如 Nginx |
| 平滑重启(优雅重启)| `systemctl try-restart <服务名>` | 仅在服务运行时重启,避免报错 |
##### 2. 服务状态查询
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 查看状态 | `systemctl status <服务名>` | 显示服务运行状态、日志及依赖关系(按 `Q` 退出) |
| 简洁状态 | `systemctl is-active <服务名>` | 仅显示服务是否激活active/running |
| 查看是否启用开机启动| `systemctl is-enabled <服务名>` | 显示服务是否设置为开机启动enabled/disabled |
| 列出所有服务 | `systemctl list-units --type=service` | 列出所有运行中的服务 |
| 列出所有服务(含未激活)| `systemctl list-units --type=service --all` | 显示所有服务,包括未激活的(状态为 inactive/failed 等) |
| 列出失败的服务 | `systemctl --failed --type=service` | 查看启动失败的服务 |
##### 3. 开机启动管理
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 启用开机启动 | `systemctl enable <服务名>` | 设置服务开机自动启动(永久生效,关联到默认运行目标) |
| 禁用开机启动 | `systemctl disable <服务名>` | 取消服务开机启动 |
| 临时启用(仅本次启动)| `systemctl enable --now <服务名>` | 立即启动服务并设置开机启动 |
| 临时禁用(停止并取消启动)| `systemctl disable --now <服务名>` | 立即停止服务并取消开机启动 |
##### 4. 服务依赖与依赖关系
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 查看依赖关系 | `systemctl list-dependencies <服务名>` | 显示服务的依赖项(依赖它的服务 + 它依赖的服务) |
| 查看直接依赖 | `systemctl list-dependencies --reverse <服务名>` | 仅显示依赖该服务的其他服务 |
#### **二、系统状态与控制**
##### 1. 系统基本状态
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 查看系统运行时间 | `systemctl uptime` | 显示系统已运行时间(类似 `uptime` 命令) |
| 查看启动耗时 | `systemctl time` | 显示系统启动总耗时及各阶段(内核、用户空间、服务)耗时 |
| 查看登录会话 | `systemctl list-sessions` | 列出当前登录的用户会话 |
##### 2. 电源管理(需管理员权限)
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 关机 | `systemctl poweroff` | 立即关机 |
| 重启 | `systemctl reboot` | 立即重启 |
| 休眠(挂起到硬盘) | `systemctl hibernate` | 系统进入休眠状态 |
| 睡眠(挂起到内存) | `systemctl suspend` | 系统进入睡眠状态(低功耗,断电数据丢失) |
| 混合休眠 | `systemctl hybrid-sleep` | 同时休眠到内存和硬盘,结合两者优势 |
| 取消挂起/休眠 | `systemctl wakeup` | 唤醒系统(需配合定时器使用) |
##### 3. 运行目标(替代传统运行级别)
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 查看当前目标 | `systemctl get-default` | 显示默认运行目标(如 `graphical.target` 对应图形界面) |
| 切换目标 | `systemctl isolate <目标名>` | 切换到指定目标(如 `multi-user.target` 为无图形多用户模式) |
| 设置默认目标 | `systemctl set-default <目标名>` | 设置开机默认目标(需管理员权限) |
**常用目标对应关系**
- `graphical.target`:图形界面(对应传统运行级别 5
- `multi-user.target`:无图形多用户模式(对应级别 3
- `rescue.target`:单用户救援模式(对应级别 1
- `emergency.target`:紧急模式(无文件系统挂载,仅基本命令)
#### **三、定时器管理systemd.timer**
`systemctl` 可管理定时任务(替代传统 `cron`),需配合 `.timer` 文件使用。
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 列出所有定时器 | `systemctl list-timers` | 显示激活的定时器及其下一次触发时间 |
| 查看定时器状态 | `systemctl status <定时器名>` | 显示定时器详细状态及日志 |
| 启用/禁用定时器 | `systemctl enable/disable <定时器名>` | 控制定时器是否开机启动 |
| 立即触发定时器任务 | `systemctl start <定时器名>` | 强制立即执行定时器关联的服务 |
#### **四、资源控制与限制(高级功能)**
可对服务设置 CPU、内存、IO 等资源限制(需在服务文件中配置,或临时生效)。
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 设置 CPU 核心限制 | `systemctl set-property <服务名> CPUAffinity=0,1` | 限制服务仅运行在 CPU 0 和 1 核心 |
| 设置内存上限 | `systemctl set-property <服务名> MemoryMax=1G` | 限制服务最大内存使用量为 1GB |
| 恢复默认资源配置 | `systemctl unset-property <服务名> CPUAffinity MemoryMax` | 清除已设置的资源限制 |
#### **五、日志相关(结合 journalctl**
| 操作 | 命令 | 说明 |
|---------------------|---------------------------------------|----------------------------------------------------------------------|
| 查看服务日志 | `systemctl status <服务名> -l` | 显示服务状态并附带日志(`-l` 展开完整日志) |
| 实时监控日志 | `journalctl -u <服务名> -f` | 实时追踪服务日志(需结合 `journalctl` 命令) |
| 查看历史日志 | `journalctl -u <服务名> --since "2025-05-01"` | 查看指定时间后的服务日志 |
#### **六、常用选项与技巧**
- **通配符匹配**
可使用通配符管理同类服务,例如:
```bash
systemctl start nginx*.service # 启动所有以 nginx 开头的服务
systemctl stop *.timer # 停止所有定时器服务
```
- **强制操作**
`--force` 用于强制停止/重启服务(可能终止进程):
```bash
systemctl --force stop <服务名>
```
- **临时生效(不修改配置)**
使用 `--now` 可立即执行操作并关联开机启动(或取消):
```bash
systemctl enable --now <服务名> # 启动并启用开机启动
systemctl disable --now <服务名> # 停止并禁用开机启动
```
- **查看帮助**
```bash
systemctl --help # 查看全局帮助
systemctl help <子命令> # 查看子命令详细用法(如 systemctl help start
```
#### **七、示例场景**
1. **管理 Nginx 服务**
```bash
systemctl start nginx # 启动 Nginx
systemctl enable nginx # 设置开机启动
systemctl status nginx # 查看运行状态
systemctl reload nginx # 重新加载配置
```
2. **系统关机与重启**
```bash
systemctl reboot # 立即重启
systemctl poweroff # 立即关机
systemctl suspend # 进入睡眠
```
3. **设置默认运行目标**
```bash
systemctl set-default multi-user.target # 设为无图形多用户模式
systemctl isolate rescue.target # 进入单用户救援模式
```
### 总结
`systemctl` 是 systemd 生态的核心工具,覆盖服务管理、系统控制、定时任务、资源限制等功能。熟练掌握其常用命令可高效管理 Linux 系统服务与状态,替代传统 SysVinit 的 `service`、`chkconfig` 等工具。建议结合 `journalctl` 分析服务日志,通过服务文件(`/etc/systemd/system/`)自定义复杂配置。`systemctl` 是 Linux 系统中用于控制 `systemd` 系统和服务管理器的命令。以下是 `systemctl` 命令的一些常用用法总结:
### 1. 服务管理
#### 启动服务
```bash
systemctl start <服务名>
```
例如,启动 `httpd` 服务:
```bash
systemctl start httpd
```
#### 停止服务
```bash
systemctl stop <服务名>
```
例如,停止 `httpd` 服务:
```bash
systemctl stop httpd
```
#### 重启服务
```bash
systemctl restart <服务名>
```
例如,重启 `httpd` 服务:
```bash
systemctl restart httpd
```
#### 重新加载服务配置
```bash
systemctl reload <服务名>
```
例如,重新加载 `nginx` 服务配置:
```bash
systemctl reload nginx
```
#### 查看服务状态
```bash
systemctl status <服务名>
```
例如,查看 `httpd` 服务状态:
```bash
systemctl status httpd
```
### 2. 服务的开机自启管理
#### 设置服务开机自启
```bash
systemctl enable <服务名>
```
例如,设置 `httpd` 服务开机自启:
```bash
systemctl enable httpd
```
#### 禁止服务开机自启
```bash
systemctl disable <服务名>
```
例如,禁止 `httpd` 服务开机自启:
```bash
systemctl disable httpd
```
#### 查看服务是否开机自启
```bash
systemctl is-enabled <服务名>
```
例如,查看 `httpd` 服务是否开机自启:
```bash
systemctl is-enabled httpd
```
### 3. 系统管理
#### 重启系统
```bash
systemctl reboot
```
#### 关机
```bash
systemctl poweroff
```
#### 挂起系统
```bash
systemctl suspend
```
#### 休眠系统
```bash
systemctl hibernate
```
#### 混合休眠(挂起并休眠)
```bash
systemctl hybrid-sleep
```
### 4. 查看系统状态
#### 查看系统当前运行级别
```bash
systemctl get-default
```
#### 设置系统默认运行级别
```bash
systemctl set-default <目标运行级别>
```
例如,设置系统默认运行级别为多用户模式:
```bash
systemctl set-default multi-user.target
```
### 5. 查看服务列表
#### 查看所有已激活的服务
```bash
systemctl list-units --type=service --state=active
```
#### 查看所有服务(包括未激活的)
```bash
systemctl list-units --type=service --all
```
这些是 `systemctl` 命令的一些常用用法,掌握这些用法可以帮助你有效地管理 Linux 系统中的服务和系统状态。

Some files were not shown because too many files have changed in this diff Show More