` to separate paragraphs. - - ```java - /** - * This is the first paragraph of the Javadoc. - *
- * This is the second paragraph of the Javadoc.
- */
- ```
-
- - Each paragraph must be a grammatically correct and semantically complete paragraph following English sentence conventions.
- - All `@param`, `@return`, `@throws`, and `@see` explanations must follow these rules:
- - Do not start with a capital letter.
- - If the description ends with a declarative sentence, do not use punctuation at the end.
-
- ```java
- /**
- * Returns the greater of two {@code int} values. That is, the
- * result is the argument closer to the value of
- * {@link Integer#MAX_VALUE}. If the arguments have the same value,
- * the result is that same value.
- *
- * @param a an argument
- * @param b another argument
- * @return the larger of {@code a} and {@code b}
- */
- public static int max(int a, int b) {
- return (a >= b) ? a : b;
- }
- ```
-
-## Dependency Management (Gradle)
-
-- **Build File**: `build.gradle.kts` must be well-organised with clear separation of plugins, dependencies, and tasks.
-- **Dependency Versions**: Dependency versions must be centrally managed in the `gradle/libs.versions.toml` file to ensure consistency.
-- **Plugin Management**: Explicitly declare Gradle plugins and their versions.
-- **Avoid Unnecessary Dependencies**: Only include dependencies actually used by the project. Regularly review and clean up unused dependencies.
-
-## API Design (RESTful)
-
-- **RESTful Principles**: Follow RESTful principles:
- - **Resources**: Model data as resources identifiable by URI.
- - **HTTP Methods**: Use standard HTTP methods appropriately (GET for retrieval, POST for creation, PUT for full update, PATCH for partial update, DELETE for removal).
- - **Statelessness**: APIs should be stateless; each request from client to server must contain all the information needed to understand the request.
-- **URIs**:
- - Use plural nouns for collection resources (e.g., `/users`, `/products`).
- - Use hyphens in URIs for readability (e.g., `/user-accounts`).
- - Avoid verbs in URIs (e.g., use `/users` instead of `/getAllUsers`).
-- **Status Codes**: Use appropriate HTTP status codes to indicate the result of API requests (e.g., `200 OK`, `201 Created`, `204 No Content`, `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`).
-- **Response Format**: JSON is the preferred response format.
-- **Versioning**: Where version control is required, use the `X-Endpoint-Version` header parameter to control API versions.
-
-## Spring Boot Best Practices & Layered Architecture
-
-- **Layered Architecture (MVC with Manager Layer)**: Our backend applications follow a strict multi-layered architecture, ensuring clear separation of responsibilities and improving maintainability and testability. The layers and their responsibilities are:
- - **Controller Layer**: Located in the `controller` package. Responsible for exposing RESTful APIs, handling HTTP requests, and mapping request parameters/bodies to service layer calls. Controllers should remain lightweight, focusing primarily on input validation (using DTOs) and coordinating calls to the `Service` layer.
- - **Service Layer**: Located in the `service` package. This layer encapsulates core business logic. Services expose a directly consumable API to the `Controller` layer, abstracting business processes and transaction management. Services coordinate calls to the `Manager` layer to execute business operations.
- - **Manager Layer**: Located in the `manager` package. This layer provides atomic business operations that can be composed by the `Service` layer. Managers typically handle more complex business logic and may involve interacting with multiple repositories or other external systems at a finer granularity.
- - **Repository Layer (MyBatis)**: Located in the `repository` package and `src/main/resources/repository` (for XML mapping files). This layer is responsible for providing atomic database interaction operations.
-
- **Inter-Layer Communication Strategy**:
- - **Components within a layer may only call components in the layer directly below it.**
- - **Cross-layer calls are strictly prohibited** (e.g., Controller directly calling Manager, Service directly calling Repository).
- - **Upward calls are strictly prohibited** (e.g., Service calling Controller).
- - **Lateral calls** (e.g., Service A calling Service B for a different domain) should be carefully considered and typically indicate a need to refactor shared logic into a `Manager` or a dedicated `Service` for that shared concern.
-
- - **Configuration**: Prefer `application.yml` over `application.properties` for configuration properties, offering better readability and hierarchical structure. Use `@ConfigurationProperties` for type-safe configuration.
- - **Dependency Injection**: All dependencies should use constructor injection (mandatory dependencies) or setter injection (optional dependencies). Avoid `@Autowired` on fields, as it makes testing more difficult and hides dependencies.
- - **Services**: Business logic classes are annotated with `@Service`. Services should be kept lean and focused on orchestrating domain operations, typically involving business logic processing through `Manager` layer components and interaction through `Manager` or directly with MyBatis repositories (if the particular operation does not require intermediate Manager logic, though the Manager layer is preferred for all repository interactions consistent with the layered architecture definition).
-
-- **Repositories (MyBatis & JPA)**:
- - **The project uses both MyBatis and JPA for database operations**. Repository interfaces in the `repository` and `mapper` packages define the data access contract.
- - Corresponding SQL definitions are managed in XML mapping files located in `src/main/resources/mapper`.
- - Data operation conventions:
- - Use JPA for simple database operations.
- - Use MyBatis for complex database operations.
- - When performing paginated queries, page numbers should start from 0 (_compatible with Spring Data JPA_).
- - **Data Access Method Naming Conventions**:
- - For **querying data lists**: methods **must** start with `selectListBy`, followed by the filter criteria (e.g., `selectListByUserId`, `selectListByDepartmentIdAndStatus`). These methods must also include a `PageRequest` parameter for pagination.
- - For querying **single data records**: methods **must** start with `selectOne` (e.g., `selectOneById`, `selectOneByUsername`).
- - For **saving new data**: methods **must** be named `save`, and Mapper method return type must be `int` (affected row count).
- - For **updating existing data**: methods **must** be named `update`, and Mapper method return type must be `int` (affected row count).
- - For **deleting data**: methods **must** start with `deleteBy`, clearly indicating the deletion criteria (e.g., `deleteById`). Mapper method return type must be `int` (affected row count).
-
-- **Controllers**:
- - Annotate REST controllers with `@RestController`.
- - Use `@GetMapping`, `@PostMapping`, etc. to map HTTP methods (GET, POST, PUT, DELETE) to appropriate controller methods.
- - Ensure request and response payloads are clearly defined (DTOs) and documented.
- - Controllers should primarily handle HTTP request/response mapping and delegate actual business logic to the service layer.
-
-- **DTOs (Data Transfer Objects)**: Define separate DTOs for request and response bodies to decouple the internal domain model from the API contract. Use validation annotations on DTOs (e.g., `@Valid`, `@NotNull`, `@Size`).
-
-- **Logging (SLF4J & Logback)**:
- - All logging in the application uses `org.slf4j.Logger`.
- - Configure `application-dev.yml` to set logging levels, appenders, and output formats.
- - Log messages should be descriptive and provide sufficient context. Avoid logging sensitive information.
- - Use parameterised logging for performance and to prevent string concatenation overhead (e.g., `log.debug("Processing user: {}", userId);`).
- - Standard log levels: `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`.
-
-## Project Structure
-
-Backend applications follow a structured Gradle project layout. The core application should be clearly divided into various sub-packages.
-
-```text
-backend-application
-├── build.gradle.kts // Project's main Gradle build script
-├── config // External configuration directory
-│ ├── application-dev.yml // Application properties for the development environment
-│ └── application-prod.yml.example // Example production properties (to be copied and configured)
-├── database // Database-related files
-│ └── init.d // Database initialisation scripts
-│ └── init-en_GB.sql // SQL script for database schema and initial data using the specified locale (British English)
-├── gradle // Gradle Wrapper and configuration files
-│ ├── libs.versions.toml // Centralised dependency version management (Gradle Version Catalog)
-│ └── wrapper // Gradle Wrapper files
-│ ├── gradle-wrapper.jar
-│ └── gradle-wrapper.properties
-├── gradle.properties // Project-specific Gradle properties
-├── gradlew // Gradle Wrapper executable (Linux/macOS)
-├── gradlew.bat // Gradle Wrapper executable (Windows)
-├── settings.gradle.kts // Gradle settings for multi-project builds (if applicable)
-└── src
- ├── main
- │ ├── java
- │ │ └── com/onixbyte/application // Application root package
- │ │ ├── Application.java // Spring Boot application main entry point
- │ │ ├── config // Spring configuration classes
- │ │ ├── constant // Classes defining application-wide constants
- │ │ ├── controller // REST API endpoints
- │ │ ├── domain // Core domain models and related types
- │ │ │ ├── common // Common domain objects/utilities
- │ │ │ ├── entity // JPA/MyBatis entities representing database tables
- │ │ │ ├── model // General-purpose entity class models
- │ │ │ ├── view // Data transfer objects specifically for read-only operations (e.g., query results, report structures)
- │ │ │ └── web // Data transfer objects specifically for web request/response bodies
- │ │ │ ├── request // Request DTOs
- │ │ │ └── response // Response DTOs
- │ │ ├── exception // Custom application-specific exceptions
- │ │ ├── extension // Extension points or custom functionality
- │ │ │ ├── jackson // Jackson serialisation/deserialisation extensions
- │ │ │ └── redis // Redis-related extensions
- │ │ │ └── serializer
- │ │ ├── filter // Servlet filters or Spring Security filters
- │ │ ├── manager // Business logic coordinators, typically orchestrating multiple services or repositories
- │ │ ├── mapper // Data access layer (MyBatis interfaces)
- │ │ ├── processor // General-purpose processing components or business workflows
- │ │ ├── properties // Classes for type-safe configuration properties (`@ConfigurationProperties`)
- │ │ ├── repository // Data access layer (Spring Data JPA interfaces)
- │ │ ├── security // Spring Security-specific components
- │ │ │ ├── authentication // Custom authentication mechanisms
- │ │ │ └── provider // Custom authentication providers
- │ │ ├── service // Core business logic (transactional layer)
- │ │ ├── utils // General-purpose utility classes
- │ │ └── validation // Custom validation logic
- │ │ └── group // Validation groups for different contexts (e.g., create, update)
- │ └── resources
- │ ├── application.yml // Default application properties
- │ └── mapper // MyBatis XML mapping files
- └── test
- └── java
- └── com/onixbyte/helix
- └── HelixApplicationTests.java // Spring Boot integration tests
-```
-
-**Key Observations and Specific Instructions:**
-
-- **External `config` Directory**
- - Environment configurations (`application-dev.yml`, `application-prod.yml.example`) are managed in the top-level `config` directory, separate from `src/main/resources`. This facilitates environment-specific property management, allowing different configurations to be mounted or linked at deployment time.
- - **Do not upload any configuration files other than `src/main/resources/application.yml` to the Git repository.**
-- **Database Initialisation**: The `database/init.d` directory is reserved for SQL scripts, specifically database schema initialisation (`init-en_GB.sql`), which is critical for environment setup and CI/CD pipelines. This structure suggests a "schema-first" or "code-driven schema evolution" approach.
-- **`client` Package**: This package is used to provide services for all middleware to the application, such as HTTP, S3 storage, Redis calls, etc. For self-coded functional implementations that need to be added to the Spring context (such as JSON Web Token generation and parsing), placing them in this package is also recommended.
-- **MyBatis & Spring Data JPA Integration**
- - The `src/main/java/.../mapper` package contains MyBatis mapper interfaces, while the actual SQL definitions reside in `src/main/resources/mapper/*.xml` files. This separation is key to keeping code clean while leveraging MyBatis's powerful XML mapping capabilities.
- - The `src/main/java/.../repository` package contains Spring Data JPA interfaces.
-- **`domain` Package Granularity**:
- - `domain.entity`: Reserved for classes directly mapped to database tables (POJOs for MyBatis).
- - `domain.model`: For more general-purpose domain objects or aggregate roots that do not map one-to-one with individual tables.
- - `domain.view`: Specifically for Data Transfer Objects (DTOs) used in read-only scenarios (e.g., query results, report structures).
- - `domain.web.request` / `domain.web.response`: Clearly separated DTOs for incoming API requests and outgoing API responses, strictly adhering to the API contract and decoupled from internal domain entities.
-- **`manager` and `processor` Packages**: These packages imply a layered architecture where "managers" coordinate operations involving multiple services or repositories, while "processors" may handle specific aspects of business processes. It is mandatory to clearly define the responsibilities of classes in these packages to prevent anti-patterns such as "anaemic domain model" or "god objects".
-- **`security` Package**: This sub-package contains custom Spring Security components beyond the initial configuration, such as custom authentication types and providers, indicating a tailored security implementation.
-- **`properties` Package**: This package is for custom `@ConfigurationProperties` classes, facilitating type-safe access to application settings defined in YML files — well-positioned.
-- **`extension` Package**: This is a flexible area for application-specific extensions, such as custom Jackson serialisers or Redis customisations. It should be used sparingly to avoid becoming a "miscellaneous" dumping ground.
-
-## Security (Spring Security)
-
-- **Mandatory Use**: Spring Security is mandatory in all Spring Boot web applications.
-- **Authentication & Authorisation**: Configure authentication mechanisms (e.g., OAuth 2.0, JWT, session-based) and authorisation rules in `SecurityConfig.java`.
-- **CSRF Protection**: Ensure CSRF protection is enabled for state-modifying operations, unless there is a strong reason to disable it (e.g., stateless APIs with other mechanisms already in place).
-- **CORS**: Correctly configure Cross-Origin Resource Sharing (CORS) according to frontend deployment requirements.
-- **Third-Party Identity Providers**: When integrating with third-party identity providers (e.g., Microsoft Entra ID), follow best practices for secure token handling and user provisioning. Sensitive credentials must be securely managed (e.g., environment variables, Vault).
-- **Input Validation**: Always validate all user input on the server side to prevent common vulnerabilities such as SQL injection, XSS, etc.
-- **Content Security Policy (CSP)**: Consider implementing a robust CSP for the frontend to mitigate XSS attacks.
diff --git a/docs/en-gb/blogs/macos-private-dns-hostname.md b/docs/en-gb/blogs/macos-private-dns-hostname.md
deleted file mode 100644
index 3ac7398..0000000
--- a/docs/en-gb/blogs/macos-private-dns-hostname.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-title: Fix macOS Terminal Host Name Showing IP Segments Under Private DNS
-tags:
- - macos
- - dns
- - terminal
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-In some enterprise or home private network environments, reverse DNS lookups may resolve a device's private IP to a hostname starting with `192`, `172`, or `10`. When this happens, the macOS terminal prompt changes from the normal `user@MacBook-Pro` to something like `user@192-168-1-100`, which can be distracting.
-
-## Cause
-
-When starting a terminal session, macOS performs a reverse DNS lookup to determine the hostname for the current IP address. If the private DNS server returns a hostname derived from IP octets (e.g. `192-168-1-100.example.com`), the system adopts it as the Host Name and the terminal prompt reflects it.
-
-## Fix
-
-Use the built-in `scutil` (System Configuration Utility) to pin the Host Name to your preferred value.
-
-### Check Current State
-
-```shell
-# View the current Host Name (may be empty or overridden by DNS)
-scutil --get HostName
-
-# View the local Bonjour name
-scutil --get LocalHostName
-
-# View the computer name shown in Finder
-scutil --get ComputerName
-```
-
-### Set the Host Name
-
-```shell
-sudo scutil --set HostName "MacBook-Pro"
-```
-
-Prefer a name without spaces or special characters, such as `MacBook-Pro`, `My-Mac`, or your device serial number.
-
-### Verify
-
-Open a new terminal window — the value after `@` in the prompt should now show your chosen hostname.
-
-```shell
-scutil --get HostName
-# Output: MacBook-Pro
-```
-
-## Notes
-
-- `HostName` only affects the network-level hostname. `LocalHostName` (Bonjour) and `ComputerName` (Finder display) are managed independently.
-- If the issue returns after a reboot, check `/etc/hosts` for conflicting entries or verify whether the DHCP/DNS server continues to push an undesired hostname.
diff --git a/docs/en-gb/blogs/minio-admin-guide.md b/docs/en-gb/blogs/minio-admin-guide.md
deleted file mode 100644
index 7769d08..0000000
--- a/docs/en-gb/blogs/minio-admin-guide.md
+++ /dev/null
@@ -1,200 +0,0 @@
----
-title: MinIO Administration Guide for New Versions
-tags:
- - minio
- - storage
- - s3
- - devops
- - cheatsheet
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-In newer versions, MinIO has removed administrative functionality from the Web UI. You now need to use the **MinIO Client (mc)** command-line tool for all management operations.
-
-## Installing MinIO Client (mc)
-
-### Windows:
-
-```powershell
-# Download mc.exe
-Invoke-WebRequest -Uri "https://dl.min.io/client/mc/release/windows-amd64/mc.exe" -OutFile "mc.exe"
-
-# Or using Chocolatey
-choco install minio-client
-```
-
-### Linux/macOS:
-
-```bash
-# Linux
-wget https://dl.min.io/client/mc/release/linux-amd64/mc
-chmod +x mc
-sudo mv mc /usr/local/bin/
-
-# macOS
-brew install minio/stable/mc
-```
-
-## Configuring the MinIO Client
-
-```bash
-# Add a MinIO server alias
-mc alias set myminio http://localhost:9000 minioadmin minioadmin
-
-# Verify the connection
-mc admin info myminio
-```
-
-## User Management
-
-### Creating Users
-
-```bash
-# Create a new user
-mc admin user add myminio newuser newpassword
-
-# List all users
-mc admin user list myminio
-```
-
-### Creating Access Keys and Secret Keys
-
-```bash
-# Create a service account for a user (generates AccessKey/SecretKey)
-mc admin user svcacct add myminio newuser
-
-# Or specify custom AccessKey and SecretKey
-mc admin user svcacct add myminio newuser --access-key "MYACCESSKEY123" --secret-key "MYSECRETKEY456"
-
-# View a user's service accounts
-mc admin user svcacct list myminio newuser
-```
-
-## Permission Management
-
-### Creating Policies
-
-```bash
-# Create a policy file policy.json
-cat > policy.json << EOF
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:GetObject",
- "s3:PutObject",
- "s3:DeleteObject"
- ],
- "Resource": [
- "arn:aws:s3:::mybucket/*"
- ]
- }
- ]
-}
-EOF
-
-# Add the policy
-mc admin policy add myminio mypolicy policy.json
-
-# Assign the policy to a user
-mc admin policy set myminio mypolicy user=newuser
-```
-
-## Bucket Management
-
-```bash
-# Create a bucket
-mc mb myminio/mybucket
-
-# List buckets
-mc ls myminio
-
-# Set bucket policy
-mc policy set public myminio/mybucket
-```
-
-## Common Administration Commands
-
-```bash
-# View server information
-mc admin info myminio
-
-# View server configuration
-mc admin config get myminio
-
-# Restart the server
-mc admin service restart myminio
-
-# View logs
-mc admin logs myminio
-
-# View statistics
-mc admin prometheus metrics myminio
-```
-
-## Practical Script Example
-
-Create an administration script `setup-minio.sh`:
-
-```bash
-#!/bin/bash
-
-MINIO_ALIAS="myminio"
-MINIO_URL="http://localhost:9000"
-ADMIN_USER="minioadmin"
-ADMIN_PASS="minioadmin"
-
-# Configure the MinIO client
-mc alias set $MINIO_ALIAS $MINIO_URL $ADMIN_USER $ADMIN_PASS
-
-# Create an application user
-APP_USER="appuser"
-APP_PASS="apppassword"
-mc admin user add $MINIO_ALIAS $APP_USER $APP_PASS
-
-# Create a service account and retrieve AccessKey/SecretKey
-echo "Creating service account for $APP_USER..."
-CREDENTIALS=$(mc admin user svcacct add $MINIO_ALIAS $APP_USER --json)
-ACCESS_KEY=$(echo $CREDENTIALS | jq -r '.accessKey')
-SECRET_KEY=$(echo $CREDENTIALS | jq -r '.secretKey')
-
-echo "Generated credentials:"
-echo "Access Key: $ACCESS_KEY"
-echo "Secret Key: $SECRET_KEY"
-
-# Create a bucket
-mc mb $MINIO_ALIAS/app-bucket
-
-# Set a read-only policy
-mc policy set download $MINIO_ALIAS/app-bucket
-```
-
-## Web Console Access
-
-Although administrative functionality has been removed, you can still access the MinIO Console via:
-
-```bash
-# Launch the MinIO Console (if installed separately)
-mc admin console myminio
-```
-
-Alternatively, specify the console address when starting the MinIO server:
-
-```bash
-minio server /data --console-address ":9001"
-```
-
-## Summary
-
-Managing the new MinIO relies entirely on the `mc` command-line tool:
-
-1. **Install the mc client**
-2. **Configure the server alias**
-3. **Use `mc admin` commands for user, permission, and bucket management**
-4. **Generate AccessKeys/SecretKeys via `mc admin user svcacct`**
-
-While this approach requires command-line operations, it provides more powerful and flexible management capabilities, particularly suited for automated deployment and script-based management.
diff --git a/docs/en-gb/blogs/mybatis-flex.md b/docs/en-gb/blogs/mybatis-flex.md
deleted file mode 100644
index a5a7a09..0000000
--- a/docs/en-gb/blogs/mybatis-flex.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-title: MyBatis Flex
-tags:
- - java
- - mybatis
- - spring-boot
- - orm
- - framework
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-> This article only aims at using `MyBatis Flex` in Spring Boot 3
-
-## Installation and Configuration
-
-### Installation
-
-Add the following codes to `libs.versions.toml` in `gradle` :
-
-```toml
-[versions]
-mybatisFlexVersion = "X.Y.Z"
-hikariVersion = "X.Y.Z"
-
-[libraries]
-hikari = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikariVersion" }
-mybatisFlex-processor = { group = "com.mybatis-flex", name = "mybatis-flex-processor", version.ref = "mybatisFlexVersion" }
-mybatisFlex-starter = { group = "com.mybatis-flex", name = "mybatis-flex-spring-boot3-starter", version.ref = "mybatisFlexVersion" }
-```
diff --git a/docs/en-gb/blogs/postgresql-zhparser-fuzzy-search.md b/docs/en-gb/blogs/postgresql-zhparser-fuzzy-search.md
deleted file mode 100644
index a499f65..0000000
--- a/docs/en-gb/blogs/postgresql-zhparser-fuzzy-search.md
+++ /dev/null
@@ -1,220 +0,0 @@
----
-title: Accelerating Fuzzy Search in PostgreSQL with Tokenisation
-tags:
- - postgresql
- - zhparser
- - full-text-search
- - performance
-author:
- name: Siu Jam Oh
- email: jamo.siu@gmail.com
----
-
-## Background and Challenges
-
-As our business data surpassed **2 million rows**, traditional `LIKE '%keyword%'` fuzzy queries triggered frequent database I/O alerts, with query response times degrading from milliseconds to seconds. To improve search efficiency and support Chinese semantics, we decided to introduce the `zhparser` extension for full-text search.
-
-## Evolution Path and Environment Adaptation
-
-This implementation went through four key phases, each addressing distinct technical challenges:
-
-### CentOS 7.9 VM (Feasibility Validation)
-
-- **Goal**: Validate the compatibility of `SCWS` + `zhparser` on older systems.
-- **Core Action**: Manually compiled `postgresql-16.2` from source in a CentOS 7.9 environment, got the extension working end-to-end.
-
-**Conclusion**: Confirmed significant performance improvements from the tokenisation approach for Chinese search.
-
-### Local Docker Container (Containerisation Exploration)
-
-- **Goal**: Initial testing in a complete local system.
-- **Core Action**: Injected binary `.so` files via `docker cp`, resolved `ldconfig` dynamic library path visibility issues.
-- **Discovery**: Identified that **missing dictionary files** cause tokenisation to degrade into single-character (particle-level) tokenisation — a critical failure point.
-
-### EulerOS 2.0 Test Server (Self-Compiled Environment Adaptation)
-
-- **Goal**: Adapt to the production OS architecture (x86_64) and self-compiled PostgreSQL installation.
-- **Core Issue**: Resolved `libscws.so.1` loading errors.
-- **Key Solutions**:
- - Ensured the `postgres` runtime user has access permissions to `/usr/local/scws/lib`.
- - Modified `systemd` service environment variables or created `/usr/lib64` symlinks to force refresh library search paths.
-
-### Production Deployment Preparation (Final Tuning)
-
-- **Goal**: Ensure query stability at 2M+ data volume.
-- **Optimisation**: Addressed cases where non-semantic fragments (e.g., "古唐合") returned no results by establishing a "full-text search first + `pg_trgm` index assist" degraded query strategy.
-
-## Core Installation and Configuration Steps (Self-Compiled Environments)
-
-### Installing the `SCWS` Tokenisation Engine
-
-SCWS is the underlying core dependency of `zhparser` and must be installed first.
-
-1. **Download and Extract**: Download the source package (e.g., `scws-1.2.3`).
-2. **Compile and Install**:
-
- ```bash
- ./configure --prefix=/usr/local/scws
- make && make install
- ```
-
-3. **Verify the Library**: Ensure `/usr/local/scws/lib/libscws.so.1` exists.
-
-### Compiling and Installing `zhparser`
-
-This step requires `pg_config` from the self-compiled PostgreSQL installation.
-
-1. **Get the Source**: Clone the `zhparser` project from GitHub.
-2. **Compile with Specified Path**:
-
- ```bash
- # Ensure pg_config is in PATH, or specify manually
- make USE_PGXS=1 PG_CONFIG=/usr/local/pgsql/bin/pg_config
- make USE_PGXS=1 PG_CONFIG=/usr/local/pgsql/bin/pg_config install
- ```
-
- _Note: The `install` step automatically places `zhparser.so` into PG's `pkglibdir` and extension scripts into the `extension` directory._
-
-### Resolving Dynamic Library Dependencies
-
-1. **Refresh System Cache**:
-
- ```bash
- echo "/usr/local/scws/lib" > /etc/ld.so.conf.d/scws.conf
- ldconfig
- ```
-
-2. **Permission Check**: Ensure the OS user running `postgres` has `rx` permission on `/usr/local/scws/lib`.
-3. **Force Symlink (Alternative)**: If `ldconfig` fails, symlink the library file to `/usr/lib64`.
-
-### Restarting the Database
-
-After modifying system shared library configuration, the PostgreSQL process must be restarted to reload environment variables and linked libraries.
-
-```bash
-## Restart using pg_ctl (paths may vary for self-compiled installations)
-/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data restart
-
-## Or restart via systemd (if registered as a service)
-systemctl restart postgresql
-```
-
-### Database-Level Initialisation
-
-Connect to `psql` and run the logical configuration:
-
-```sql
--- Create the extension
-CREATE EXTENSION zhparser;
-
--- Create a full-text search configuration and bind the tokeniser
-CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
-
--- Add token mappings
-ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l,t,b WITH simple;
-
--- [Optional] Specify the dictionary path for self-compiled installations
--- ALTER DATABASE postgres SET zhparser.dict_path = '/usr/local/scws/etc/dict.utf8.xdb';
-```
-
-## Performance Analysis and Pitfalls
-
-### Index Performance Bottleneck Analysis
-
-During testing, it was found that even exact queries suffered from `Bitmap Index Scan` due to an improperly designed composite index (with `create_time` as the leading column), resulting in query times as high as **482 ms**.
-
-- **Improvement**: Created single-column **B-tree** indexes on frequently searched columns, reducing response time to under **10 ms** with `Index Scan`.
-
-### GIN Index and Non-Semantic Matching
-
-- **Cross-Word Truncation**: The tokenisation engine is semantic-based, so truncated strings like "古唐合" may fail to match with `@@` due to tokenisation boundaries.
-- **Mitigation Strategy**: Adopt a "waterfall search" approach. Full-text search (FTS) first; if the result set is empty, automatically degrade to `LIKE` fuzzy queries, assisted by `pg_trgm` indexing.
-
-## Final Deployment Strategy: Dual-Track Parallel Retrieval
-
-After analysing the data, we found that approximately 1.24% of account names contain non-standard Simplified Chinese characters, and some company names in the database are unusual enough to cause search failures. We adopted a "stepwise degradation" strategy:
-
-- **Step 1: Full-Text Search (Fast Track)**: Use GIN index for `@@` matching.
-- **Step 2: Result Evaluation**: If the result set is empty, check whether the search term contains letters or suspected Traditional Chinese characters.
-- **Step 3: Fuzzy Fallback (Safe Fallback)**: Execute `LIKE '%keyword%'`. Although slower, since this serves as a "gap-fill" logic triggered only ~1% of the time, it won't impose overall system pressure.
-
-## Search Optimisation: Integrating a Custom Business Lexicon
-
-To address issues like company brand names being incorrectly segmented by full-text search (e.g., "元一" being split into a numeral and a quantifier), we built an automated maintenance pipeline from data extraction to index rebuild.
-
-### Lexicon Extraction and Preprocessing
-
-Leverage the structural parsing capabilities of **`companynameparser`** to strip region names and industry suffixes, and use **`jieba`** for semantic validation to ensure core brand name integrity:
-
-- **Extraction Logic**: Traverse all `buyer_unique_name` values via a Python script, extracting the core `brand` field.
-- **Weight Compensation**: For words prone to fragmentation (e.g., those containing "元", "一", "三"), manually boost TF (term frequency weight) to **50.0–60.0** to ensure their priority overrides built-in quantifier rules.
-- **Output Specification**: Produce SCWS-compliant 4-field `UTF-8` text (WORD, TF, IDF, ATTR). Use tab `\t` separators to avoid parsing anomalies.
-
-### Lexicon Compilation and Deployment
-
-
-
-:::tip
-The native scws command-line tool for Windows is compiled with MingW. Source and
-build instructions are available from the upstream
-[SCWS project](https://github.com/hightman/scws).
-:::
-
-Convert the text dictionary to SCWS's efficient binary format (XDB):
-
-1. **Compile the Binary Dictionary**:
-
- ```bash
- # Use scws-gen-dict to generate an encrypted binary lexicon
- /usr/local/scws/bin/scws-gen-dict -i custom_company.txt -o /usr/local/scws/etc/custom_company.xdb -c utf8
- ```
-
-2. **File Distribution and Permissions**: Move the generated `.xdb` file to the tokenisation data directory and ensure the `postgres` user has read permission:
-
- ```bash
- cp custom_company.xdb /usr/local/pgsql/share/tsearch_data/
- chown postgres:postgres /usr/local/pgsql/share/tsearch_data/custom_company.xdb
- ```
-
-### Database Parameter Configuration
-
-Modify `postgresql.conf` to force-load `zhparser` and its custom extension lexicon:
-
-```plain text
-## Preload the extension library (requires restart to take effect)
-shared_preload_libraries = 'zhparser'
-
-## Load custom external dictionaries (use paths relative to tsearch_data)
-zhparser.extra_dicts = 'custom_company.xdb'
-```
-
-### Hot Index Rebuild and Verification
-
-Since tokenisation rules have changed, existing data must be semantically synchronised via index rebuild:
-
-**Physically Restart the Service**:
-
-```bash
-su - postgres -c "/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data restart"
-```
-
-**Online Index Rebuild**: Use the `CONCURRENTLY` keyword to refresh the GIN index without blocking DML operations on 400K rows:
-
-```bash
-REINDEX INDEX CONCURRENTLY index_name;
-```
-
-**Tokenisation Effectiveness Verification**:
-
-```sql
--- Expected part-of-speech should show as n (noun), not x (unknown)
-SELECT * FROM ts_debug('chinese', '元一能源');
-```
-
-**Optimisation Notes:**
-
-- **Explicit Weight Compensation**: This is the key technique that resolved the "元一" tokenisation failure (shown as `x`).
-- **Distinguish Restart from Reload**: `shared_preload_libraries` must be activated via `restart`, not a simple reload.
diff --git a/docs/en-gb/blogs/quartile-method.md b/docs/en-gb/blogs/quartile-method.md
deleted file mode 100644
index dafad33..0000000
--- a/docs/en-gb/blogs/quartile-method.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: The Quartile Method
-tags:
- - statistics
- - algorithm
- - data-analysis
- - math
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-The quartile method is a commonly used statistical technique primarily employed for data analysis and presentation. The method divides a data set into four equal parts, each containing one quarter of the data. The key statistics include the first quartile (Q1), second quartile (Q2, the median), and third quartile (Q3).
-
-- The first quartile (`Q1`), also known as the lower quartile, is the value at the 25th percentile of a data set sorted in ascending order.
-- The second quartile (`Q2`), also known as the median, is the value at the 50th percentile of a data set sorted in ascending order.
-- The third quartile (`Q3`), also known as the upper quartile, is the value at the 75th percentile of a data set sorted in ascending order.
-- The interquartile range (`IQR`) is the difference between the third quartile and the first quartile, used to measure the dispersion of the middle 50% of data. The formula is IQR = Q3 - Q1. The IQR is commonly used in constructing box plots, an effective way to describe data distribution, particularly useful for identifying outliers.
-
-Upper bound = Q3 + 1.5 × IQR.
-
-Lower bound = Q1 - 1.5 × IQR.
diff --git a/docs/en-gb/blogs/setup-ldap-service.md b/docs/en-gb/blogs/setup-ldap-service.md
deleted file mode 100644
index 43c789b..0000000
--- a/docs/en-gb/blogs/setup-ldap-service.md
+++ /dev/null
@@ -1,140 +0,0 @@
----
-title: Setting Up an LDAP Service
-tags:
- - ldap
- - openldap
- - authentication
- - linux
- - devops
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-Setting up an LDAP (Lightweight Directory Access Protocol) server is a core step in implementing enterprise-level **centralised identity authentication** and **permission management**. The most commonly used open-source implementation is **OpenLDAP**.
-
-Below are detailed steps for setting up an OpenLDAP server on Debian/Ubuntu-based Linux systems.
-
-## Environment Preparation and Installation
-
-Before starting, ensure your system packages are up to date and the hostname is properly configured.
-
-```bash
-## Update the system
-sudo apt update && sudo apt upgrade -y
-
-## Install OpenLDAP and management tools
-## slapd is the daemon, ldap-utils is the command-line client tool
-sudo apt install slapd ldap-utils -y
-```
-
-> During installation, you will be prompted to set the **LDAP administrator password**. Be sure to remember this password — it will be used frequently during configuration.
-
-## Configuring the OpenLDAP Server
-
-Although the installation performs some initial setup, we typically need to customise the configuration for a specific domain (e.g., `example.com`).
-
-### Reconfigure slapd
-
-Run the following command to enter the interactive configuration interface:
-
-```bash
-sudo dpkg-reconfigure slapd
-```
-
-**Configuration recommendations**:
-
-1. **Omit OpenLDAP server configuration?** Choose **No**.
-2. **DNS domain name:** Enter your domain (e.g., `centre.example.com`). This determines your Base DN, such as `dc=centre,dc=example,dc=com`.
-3. **Organization name:** Enter your organisation name.
-4. **Administrator password:** Enter the administrator password you set earlier.
-5. **Database backend:** **MDB** is recommended.
-6. **Remove database when slapd is purged?** Choose **No**.
-7. **Move old database?** Choose **Yes**.
-
-## Understanding the LDAP Hierarchy
-
-LDAP data is stored in a **tree structure**. To facilitate management, we typically create two "Organisational Units" (OUs): one for users (People) and one for groups (Groups).
-
-## Creating Organisational Units (OUs)
-
-In LDAP, we use **LDIF** (LDAP Data Interchange Format) files to add or modify directory entries.
-
-Create a file named `base.ldif`:
-
-```text
-## Create the users organisational unit
-dn: ou=people,dc=centre,dc=example,dc=com
-objectClass: organizationalUnit
-ou: people
-
-## Create the groups organisational unit
-dn: ou=groups,dc=centre,dc=example,dc=com
-objectClass: organizationalUnit
-ou: groups
-```
-
-**Import the data:**
-
-```bash
-## Import the LDIF file into the database as the administrator
-ldapadd -x -D "cn=admin,dc=centre,dc=example,dc=com" -W -f base.ldif
-```
-
-## Adding Users and Groups
-
-Create a file named `groups.ldif` to define a new group:
-
-```text
-## Define a new group
-dn: cn=developers,ou=groups,dc=centre,dc=example,dc=com
-objectClass: inetOrgGroup
-cn: developers
-```
-
-Create a file named `users.ldif` to define a new user:
-
-```text
-## Define a new user
-dn: uid=jbloggs,ou=people,dc=centre,dc=example,dc=com # The Distinguished Name (DN) of this entry.
-objectClass: inetOrgPerson # Object class — inetOrgPerson represents an internet organisation person. It enables common contact attributes such as email, displayName, telephoneNumber, etc.
-objectClass: posixAccount # Makes this entry compatible with Unix/Linux system accounts. With it, the user can log into Linux servers and has a UID, GID, and home directory.
-objectClass: shadowAccount # Used to manage password ageing (expiry, change warnings, etc.), corresponding to /etc/shadow functionality in Linux.
-uid: jbloggs # The user's login name (User ID). This is typically what you enter on the Linux login screen.
-sn: Bloggs # Surname. Required by the inetOrgPerson class.
-givenName: Joe # First name.
-cn: Joe Bloggs # Common Name. The standard display name for an LDAP entry.
-displayName: Joe Bloggs # The friendly name displayed in graphical interfaces or email clients.
-uidNumber: 10000 # The user's numeric ID in the Linux system.
-gidNumber: 5000 # The numeric ID of the user's primary group.
-userPassword: {SSHA}password-hash-or-plaintext # The user's encrypted password.
-homeDirectory: /home/jbloggs # The path to the user's home directory after logging into Linux.
-loginShell: /bin/bash # The shell environment the user gets after logging in.
-```
-
-> If you plan to integrate **GitLab**, **Jenkins**, or a **VPN** later, they typically search the `uid` attribute to verify login names.
-
-### FAQ
-
-#### If the user doesn't need server login permissions, can the `objectClass: posixAccount` be removed?
-
-**Yes, it can be completely removed**, but you need to be aware of the "binding relationships" between attributes.
-
-If you only need this user for web application logins (e.g., GitLab, Jenkins, Wiki) or as an email contact, and they don't need to log into a Linux server via SSH or console, removing `posixAccount` is the more standard approach.
-
-When you remove `objectClass: posixAccount`, the following attributes **must also be deleted**, as they belong to that class's mandatory or optional attributes:
-
-- `uidNumber`
-- `gidNumber`
-- `homeDirectory`
-- `loginShell`
-
-Additionally, `shadowAccount` is also typically associated with system logins — if you don't need to manage Linux password expiry policies, it can also be removed.
-
-## Follow-up Suggestions and Management Tools
-
-Command-line LDAP management can be cumbersome. The following tools are recommended for visual administration:
-
-- **phpLDAPAdmin**: A web-based management interface, ideal for quick onboarding.
-- **Apache Directory Studio**: A powerful cross-platform desktop client, suitable for complex architecture design.
-- **Security Hardening**: By default, LDAP transmits data in plain text. It is recommended to configure **LDAPS (LDAP over SSL/TLS)** to encrypt communication on port 636.
diff --git a/docs/en-gb/blogs/use-json-in-mysql.md b/docs/en-gb/blogs/use-json-in-mysql.md
deleted file mode 100644
index c358124..0000000
--- a/docs/en-gb/blogs/use-json-in-mysql.md
+++ /dev/null
@@ -1,89 +0,0 @@
----
-title: Using JSON in MySQL
-tags:
- - mysql
- - json
- - database
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-MySQL (since version 5.7) **does not directly support a data type called `jsonb`**. `jsonb` is a data type specific to PostgreSQL, which stores JSON data in a binary format with pre-parsing for faster access and manipulation during queries.
-
-However, MySQL's `JSON` data type is functionally and internally similar to PostgreSQL's `jsonb` in many respects, particularly when it comes to querying data.
-
-The `JSON` data type in MySQL was introduced in MySQL 5.7 and has the following characteristics:
-
-1. **Binary Storage**: Like PostgreSQL's `jsonb`, MySQL's `JSON` type data is stored in an **internal binary format** rather than as a plain text string. This makes reading and manipulating JSON data more efficient, as the database does not need to parse text-format JSON strings on every query.
-2. **Automatic Validation**: When you insert or update a `JSON` column, MySQL automatically validates that its content is a valid JSON document. If not, it throws an error.
-3. **Optimised Storage**: The binary format is also space-optimised, typically more compact than storing JSON in raw text format.
-
-MySQL provides a powerful set of functions and operators for querying and manipulating `JSON` data, very similar to what you'd expect from `jsonb`:
-
-1. **`->` (JSON Extract Operator)**: Extracts a value from a JSON document. It returns a JSON value.
-
- ```sql
- SELECT my_json_column->'$.key' FROM my_table;
- -- Example: extract the name property of a user object
- -- Assuming my_json_column stores {'user': {'name': 'Alice'}}
- SELECT json_data->'$.user.name' FROM my_table;
- ```
-
-2. **`->>` (JSON Unquote Operator)**: Extracts a value from a JSON document and **automatically unquotes it**, typically returning a scalar value (e.g., string, number). This is equivalent to `JSON_UNQUOTE(JSON_EXTRACT(...))`.
-
- ```sql
- SELECT my_json_column->>'$.key' FROM my_table;
- -- Example: extract the name property of a user object (returns the string 'Alice' directly)
- SELECT json_data->>'$.user.name' FROM my_table;
- ```
-
-3. **`JSON_EXTRACT(json_doc, path, ...)`**: Explicitly extracts data from a JSON document.
-
- ```sql
- SELECT JSON_EXTRACT(my_json_column, '$.key') FROM my_table;
- ```
-
-4. **`JSON_CONTAINS(json_doc, candidate, path)`**: Checks whether a JSON document contains a specified value.
-
- ```sql
- -- Check whether the tags array contains 'backend'
- -- Assuming my_json_column stores {'tags': ['frontend', 'backend']}
- SELECT * FROM my_table WHERE JSON_CONTAINS(json_data->'$.tags', '"backend"');
- ```
-
-5. **`JSON_SEARCH(json_doc, one_or_all, search_str, escape_char, path, ...)`**: Returns the path to a specified string within a JSON document.
-
- ```sql
- -- Find the path to a value of 'test'
- SELECT JSON_SEARCH(my_json_column, 'one', 'test') FROM my_table;
- ```
-
-6. **`JSON_TABLE(json_doc, path COLUMNS ... )` (MySQL 8.0 and later)**: A very powerful function that "expands" JSON data into relational rows and columns, ideal for complex queries and reporting.
-
- ```sql
- -- Assuming json_data stores {'items': [{'id': 1, 'name': 'A'}, {'id': 2, 'name': 'B'}]}
- SELECT *
- FROM my_table,
- JSON_TABLE(json_data, '$.items[*]' COLUMNS(
- itemId INT PATH '$.id',
- itemName VARCHAR(50) PATH '$.name'
- )) AS jt;
- ```
-
-Like PostgreSQL's `jsonb`, efficient querying on JSON fields typically requires indexing. Since the content of JSON fields is dynamic, MySQL does not directly support creating traditional B-tree indexes on a specific internal path of a JSON field. However, you can achieve this through **Virtual Generated Columns**:
-
-1. **Create a Virtual Column**: Define a virtual column whose value is extracted from a specific path in the JSON field.
-
- ```sql
- ALTER TABLE my_table
- ADD COLUMN user_name VARCHAR(255) AS (json_data->>'$.user.name') VIRTUAL;
- ```
-
-2. **Create an Index on the Virtual Column**: This way, when you query `WHERE json_data->>'$.user.name' = 'Alice'`, the MySQL optimiser can use the `idx_user_name` index, significantly improving query performance.
-
- ```sql
- CREATE INDEX idx_user_name ON my_table (user_name);
- ```
-
-Although MySQL does not have the exact name `jsonb`, its `JSON` data type provides highly similar functionality: binary storage optimisation, automatic validation, and rich query operators and functions. By combining virtual columns with indexes, MySQL can deliver query performance and flexibility comparable to PostgreSQL's `jsonb` when working with JSON data.
diff --git a/docs/en-gb/blogs/use-of-gravatar.md b/docs/en-gb/blogs/use-of-gravatar.md
deleted file mode 100644
index 1c39eea..0000000
--- a/docs/en-gb/blogs/use-of-gravatar.md
+++ /dev/null
@@ -1,84 +0,0 @@
----
-title: Use Gravatar in First-party Systems
-tags:
- - gravatar
- - avatar
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-[Gravatar](https://gravatar.com) (Globally Recognised Avatar) is a service that associates avatar images with email
-addresses. When a user registers on your platform with their email, you can display their Gravatar as a default avatar
-without building your own image upload and storage pipeline.
-
-## How It Works
-
-Gravatar exposes a simple HTTP endpoint. You compute the SHA256 hash of the user's **lowercased and trimmed** email
-address, then embed it in an image URL:
-
-```
-https://gravatar.com/avatar/ ` 分割。
-
- ```java
- /**
- * This is the first paragraph of the Javadoc.
- *
- * This is the second paragraph of the Javadoc.
- */
- ```
-
- - 每个段落的内容必须是语法正确且含义完整的段落,遵循英文句子规范。
- - 所有参数(`@param`)、返回值(`@return`)、异常抛出(`@throws`)及参考(`@see`)的解释需要遵循下面的规则:
- - 无需使用大写字母开头
- - 若描述的最后为陈述句,则无需使用标点符号结尾
-
- ```java
- /**
- * Returns the greater of two {@code int} values. That is, the
- * result is the argument closer to the value of
- * {@link Integer#MAX_VALUE}. If the arguments have the same value,
- * the result is that same value.
- *
- * @param a an argument
- * @param b another argument
- * @return the larger of {@code a} and {@code b}
- */
- public static int max(int a, int b) {
- return (a >= b) ? a : b;
- }
- ```
-
-## 依赖管理 (Gradle)
-
-- **构建文件**: `build.gradle.kts` 必须组织良好,对插件、依赖项和任务有清晰的划分。
-- **依赖版本**: 必须在 `gradle/libs.versions.toml` 文件中集中管理依赖项版本,以确保一致性。
-- **插件管理**: 显式声明 Gradle 插件及其版本。
-- **避免不必要的依赖项**: 仅包含项目实际使用的依赖项。定期审查并清理未使用的依赖项。
-
-## API 设计 (RESTful)
-
-- **RESTful 原则**: 遵循 RESTful 原则:
- - **资源**: 将数据建模为可通过 URI 标识的资源。
- - **HTTP 方法**: 适当地使用标准 HTTP 方法(GET 用于检索,POST 用于创建,PUT 用于完全更新,PATCH 用于部分更新,DELETE 用于删除)。
- - **无状态性**: API 应是无状态的;客户端向服务器发送的每个请求都必须包含理解请求所需的所有信息。
-- **URI**:
- - 集合资源使用复数名词(例如,`/users`,`/products`)。
- - URI 中使用连字符以提高可读性(例如,`/user-accounts`)。
- - 避免在 URI 中使用动词(例如,使用 `/users` 而不是 `/getAllUsers`)。
-- **状态码**: 使用适当的 HTTP 状态码来指示 API 请求的结果(例如,`200 OK`、`201 Created`、`204 No Content`、`400 Bad Request`、`401 Unauthorized`、`403 Forbidden`、`404 Not Found`、`500 Internal Server Error`)。
-- **响应格式**: JSON 是首选的响应格式。
-- **版本控制**: 建议在需要版本控制的接口中使用 Header 参数 `X-Endpoint-Version` 控制接口版本。
-
-## Spring Boot 最佳实践与分层架构
-
-- **分层架构 (MVC 配合 Manager 层)**: 我们的后端应用程序遵循严格的多层架构,确保职责清晰分离,并提高可维护性和可测试性。各层及其职责如下:
- - **控制器层 (Controller Layer)**: 位于 `controller` 包中。负责暴露 RESTful API,处理 HTTP 请求,并将请求参数/主体映射到服务层调用。控制器应保持轻量,主要关注输入验证(使用 DTOs)和协调对 `Service` 层的调用。
- - **服务层 (Service Layer)**: 位于 `service` 包中。此层封装了核心业务逻辑。服务层向 `Controller` 层提供可以直接使用的 API,抽象业务流程和事务管理。服务层协调对 `Manager` 层的调用以执行业务操作。
- - **管理器层 (Manager Layer)**: 位于 `manager` 包中。此层提供原子化的业务操作,可由 `Service` 层组合使用。管理器通常处理更复杂的业务逻辑,可能涉及在更细粒度级别上与多个仓库或其他外部系统进行交互。
- - **仓库层 (Repository Layer) (MyBatis)**: 位于 `repository` 包和 `src/main/resources/repository`(用于 XML 映射文件)中。此层负责提供原子化的数据库交互操作。
-
- **层间通信策略**:
- - **每一层内的组件仅可调用直接位于其下方的层中的组件。**
- - **严格禁止跨层调用(例如,Controller 直接调用 Manager,Service 直接调用 Repository)。**
- - **严格禁止向上调用(例如,Service 调用 Controller)。**
- - **横向调用(例如,Service A 调用 Service B 处理不同领域)应仔细考虑,通常表明需要将共享逻辑重构到 `Manager` 或为该共享关注点重构一个专用 `Service` 中。**
-
- - **配置**: 优先选择 `application.yml` 进行配置属性,而不是 `application.properties`,以获得更好的可读性和分层结构。使用 `@ConfigurationProperties` 进行类型安全配置。
- - **依赖注入**: 所有依赖项都使用构造函数(强制依赖)或 Setter(非强制依赖)注入。避免在字段上使用 `@Autowired`,因为它会使测试更困难并隐藏依赖项。
- - **服务**: 业务逻辑类使用 `@Service` 进行注解。服务应保持精简,并专注于协调领域操作,这些操作通常涉及通过 `Manager` 层组件进行业务逻辑处理,以及通过 `Manager` 或直接与 MyBatis 仓库进行交互(如果该特定操作不需要中间 Manager 逻辑,尽管对于所有仓库交互,Manager 层是首选,符合分层架构定义)。
-
-- **仓库 (MyBatis 与 JPA)**:
- - **项目使用 MyBatis 及 JPA 进行数据库操作**。`repository` 包及 `mapper` 包中的仓库接口定义了数据访问契约。
- - 相应的 SQL 定义在位于 `src/main/resources/mapper` 的 XML 映射文件中管理。
- - 数据操作约定:
- - 对于简单数据库操作,使用 JPA。
- - 对于复杂数据库操作,使用 MyBatis。
- - 当进行分页查询时,页码应从 0 开始(_兼容 Spring Data JPA_)。
- - **数据操作方法命名约定**:
- - 对于**查询数据列表**:方法**必须**以 `selectListBy` 开头,紧随其后是筛选条件(例如,`selectListByUserId`、`selectListByDepartmentIdAndStatus`)。这些方法也必须包含一个 `PageRequest` 参数用于分页。
- - 对于查询**单个数据记录**:方法**必须**以 `selectOne` 开头(例如,`selectOneById`、`selectOneByUsername`)。
- - 对于**保存新数据**:方法**必须**命名为 `save`,Mapper 方法的返回值必须是 `int`(受影响的行数)。
- - 对于**更新现有数据**:方法**必须**命名为 `update`,Mapper 方法的返回值必须是 `int`(受影响的行数)。
- - 对于**删除数据**:方法**必须**以 `deleteBy` 开头,清晰地指明删除的依据(例如,`deleteById`)。Mapper 方法的返回值必须是 `int`(受影响的行数)。
-
-- **控制器**:
- - 使用 `@RestController` 注解 REST 控制器。
- - 使用 `@GetMapping`、`@PostMapping` 等将 HTTP 方法(GET、POST、PUT、DELETE)映射到适当的控制器方法。
- - 确保请求和响应负载定义明确(DTOs)并有文档说明。
- - 控制器应主要处理 HTTP 请求/响应映射,并将实际业务逻辑委托给服务层。
-
-- **DTOs (数据传输对象)**: 定义单独的 DTOs 用于请求和响应主体,以将内部领域模型与 API 契约解耦。在 DTOs 上使用验证注解(例如,`@Valid`、`@NotNull`、`@Size`)。
-
-- **日志 (Slf4j & Logback)**:
- - 应用程序中的所有日志记录都使用 `org.slf4j.Logger`。
- - 配置 `application-dev.yml` 以设置日志级别、Appender 和输出格式。
- - 日志消息应具有描述性并提供足够的上下文。避免记录敏感信息。
- - 使用参数化日志记录以提高性能并防止字符串拼接开销(例如,`log.debug("Processing user: {}", userId);`)。
- - 标准日志级别:`ERROR`、`WARN`、`INFO`、`DEBUG`、`TRACE`。
-
-## 项目结构
-
-后端应用程序遵循结构化的 Gradle 项目布局。核心应用程序应清晰地划分为各种子包。
-
-```text
-backend-application
-├── build.gradle.kts // 项目的主 Gradle 构建脚本
-├── config // 外部配置目录
-│ ├── application-dev.yml // 开发环境的应用程序属性
-│ └── application-prod.yml.example // 生产环境属性示例(待复制和配置)
-├── database // 数据库相关文件
-│ └── init.d // 数据库初始化脚本
-│ └── init-en_GB.sql // 使用指定语言的数据库模式和初始数据的 SQL 脚本(英式英语区域设置)
-├── gradle // Gradle Wrapper 和配置文件
-│ ├── libs.versions.toml // 集中管理依赖版本(Gradle 版本目录)
-│ └── wrapper // Gradle Wrapper 文件
-│ ├── gradle-wrapper.jar
-│ └── gradle-wrapper.properties
-├── gradle.properties // 项目特定的 Gradle 属性
-├── gradlew // Gradle Wrapper 可执行文件 (Linux/macOS)
-├── gradlew.bat // Gradle Wrapper 可执行文件 (Windows)
-├── settings.gradle.kts // 多项目构建的 Gradle 设置(如果适用)
-└── src
- ├── main
- │ ├── java
- │ │ └── com/onixbyte/application // 应用程序的根包
- │ │ ├── Application.java // Spring Boot 应用程序主入口点
- │ │ ├── config // Spring 配置类
- │ │ ├── constant // 定义应用程序范围常量的类
- │ │ ├── controller // REST API 端点
- │ │ ├── domain // 核心领域模型和相关类型
- │ │ │ ├── common // 通用领域对象/工具类
- │ │ │ ├── entity // 表示数据库表的 JPA/MyBatis 实体
- │ │ │ ├── model // 通用的实体类模型
- │ │ │ ├── view // 专门用于只读操作的数据传输对象(例如,查询结果、报告结构)
- │ │ │ └── web // 专门用于 Web 请求/响应体的数据传输对象
- │ │ │ ├── request // 请求 DTO
- │ │ │ └── response // 响应 DTO
- │ │ ├── exception // 自定义应用程序特定异常
- │ │ ├── extension // 扩展点或自定义功能
- │ │ │ ├── jackson // Jackson 序列化/反序列化扩展
- │ │ │ └── redis // Redis 相关扩展
- │ │ │ └── serializer
- │ │ ├── filter // Servlet 过滤器或 Spring Security 过滤器
- │ │ ├── manager // 业务逻辑协调器,通常协调多个服务或仓库
- │ │ ├── mapper // 数据访问层 (MyBatis 接口)
- │ │ ├── processor // 通用处理组件或业务工作流
- │ │ ├── properties // 用于类型安全配置属性的类 (`@ConfigurationProperties`)
- │ │ ├── repository // 数据访问层 (Spring Data JPA 接口)
- │ │ ├── security // Spring Security 特定组件
- │ │ │ ├── authentication // 自定义认证机制
- │ │ │ └── provider // 自定义认证提供者
- │ │ ├── service // 核心业务逻辑(事务层)
- │ │ ├── utils // 通用工具类
- │ │ └── validation // 自定义验证逻辑
- │ │ └── group // 针对不同上下文(例如,创建、更新)的验证分组
- │ └── resources
- │ ├── application.yml // 默认应用程序属性
- │ └── mapper // MyBatis XML 映射文件
- └── test
- └── java
- └── com/onixbyte/helix
- └── HelixApplicationTests.java // Spring Boot 集成测试
-```
-
-**关键观察与具体指令:**
-
-- **外部 `config` 目录**
- - 环境配置 (`application-dev.yml`、`application-prod.yml.example`) 在顶层 `config` 目录中管理,与 `src/main/resources` 分开。这促进了特定于环境的属性管理,允许在部署时挂载或链接不同的配置。
- - **禁止上传除 `src/main/resources/application.yml` 之外的任何配置文件到 Git 仓库。**
-- **数据库初始化**: `database/init.d` 目录保留用于 SQL 脚本,特别是数据库模式初始化 (`init-en_GB.sql`),这对于环境设置和 CI/CD 流水线至关重要。这种结构暗示了"模式优先"或"代码驱动的模式演进"方法。
-- **`client` 包**: 该包用于向应用提供所有中间件的服务,如 HTTP、S3 存储、Redis 调用等。对于需要添加到 Spring 上下文中的,自行编码实现的功能(如 JSON Web Token 生成与解析)也推荐放到该包中。
-- **MyBatis 与 Spring Data JPA 集成**
- - `src/main/java/.../mapper` 包包含 MyBatis mapper 接口,而实际的 SQL 定义位于 `src/main/resources/mapper/*.xml` 文件中。这种分离是保持代码整洁同时利用 MyBatis 强大 XML 映射能力的关键。
- - `src/main/java/.../repository` 包包含 Spring Data JPA 接口。
-- **`domain` 包的粒度**:
- - `domain.entity`: 保留用于直接映射到数据库表的类(MyBatis 的 POJO)。
- - `domain.model`: 用于不直接与单个表一对一映射的更通用领域对象或聚合根。
- - `domain.view`: 专门用于在只读场景(例如,查询结果、报告结构)中呈现数据的数据传输对象 (DTO)。
- - `domain.web.request` / `domain.web.response`: 明确分离的用于传入 API 请求和传出 API 响应的 DTO,严格遵守 API 契约并与内部领域实体解耦。
-- **`manager` 和 `processor` 包**: 这些包暗示了一个分层架构,其中"管理器"协调涉及多个服务或仓库的操作,而"处理器"可能处理业务流程的特定方面。强制明确定义这些包中类的职责,以防止出现"贫血领域模型"或"上帝对象"等反模式。
-- **`security` 包**: 此子包包含除初始配置之外的自定义 Spring Security 组件,例如自定义认证类型和提供者,表明了定制的安全实现。
-- **`properties` 包**: 此包用于自定义 `@ConfigurationProperties` 类,促进对 YML 文件中定义的应用程序设置进行类型安全访问,位置得当。
-- **`extension` 包**: 这是一个灵活的区域,用于应用程序特定的扩展,例如自定义 Jackson 序列化器或 Redis 定制。应谨慎使用,以防止成为"杂项"的堆放地。
-
-## 安全性 (Spring Security)
-
-- **强制使用**: Spring Security 在所有 Spring Boot Web 应用程序中都是强制的。
-- **认证与授权**: 在 `SecurityConfig.java` 中配置认证机制(例如,OAuth 2.0、JWT、基于会话)和授权规则。
-- **CSRF 保护**: 确保对修改状态的操作启用 CSRF 保护,除非有充分的理由禁用它(例如,已存在其他机制的无状态 API)。
-- **CORS**: 根据前端部署要求正确配置跨域资源共享 (CORS)。
-- **第三方身份提供者**: 在与第三方身份提供者(例如 Microsoft Entra ID)集成时,遵循安全令牌处理和用户配置的最佳实践。敏感凭据必须安全管理(例如,环境变量、Vault)。
-- **输入验证**: 始终在服务器端验证所有用户输入,以防止常见的漏洞,如 SQL 注入、XSS 等。
-- **内容安全策略 (CSP)**: 考虑为前端实施强大的 CSP 以减轻 XSS 攻击。
diff --git a/docs/zh-hans/blogs/macos-private-dns-hostname.md b/docs/zh-hans/blogs/macos-private-dns-hostname.md
deleted file mode 100644
index 7a3b70c..0000000
--- a/docs/zh-hans/blogs/macos-private-dns-hostname.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-title: 修复 macOS 终端在私网 DNS 下 Host Name 显示为 IP 段的问题
-tags:
- - macos
- - dns
- - terminal
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-在部分企业或家庭私网环境中,DNS 反向解析会将设备的私网 IP 映射为一个以 `192`、`172` 或 `10` 开头的主机名。此时 macOS 终端提示符会从正常的 `user@MacBook-Pro` 变为 `user@192-168-1-100` 这样的形式,影响日常使用体验。
-
-## 原因
-
-macOS 在启动终端会话时会通过反向 DNS 查询当前 IP 对应的主机名。当私网 DNS 服务器返回了一个基于 IP 段拼凑的主机名(例如 `192-168-1-100.example.com`)时,系统便会采纳该名称作为 Host Name,终端提示符随之改变。
-
-## 修复方法
-
-使用 macOS 自带的 `scutil`(System Configuration Utility)即可将 Host Name 固定为你期望的值。
-
-### 查看当前状态
-
-```shell
-# 查看当前 Host Name(可能为空或已被 DNS 改写)
-scutil --get HostName
-
-# 查看本地 Bonjour 名称
-scutil --get LocalHostName
-
-# 查看 Finder 中显示的计算机名
-scutil --get ComputerName
-```
-
-### 设置 Host Name
-
-```shell
-sudo scutil --set HostName "MacBook-Pro"
-```
-
-建议使用不含空格和特殊字符的名称,例如 `MacBook-Pro`、`My-Mac` 或你的设备序列号。
-
-### 验证修改
-
-重新打开一个终端窗口,提示符中的 `@` 后面应恢复为你设置的主机名。
-
-```shell
-scutil --get HostName
-# 输出: MacBook-Pro
-```
-
-## 补充说明
-
-- `HostName` 仅影响网络层面的主机名标识,不会影响 `LocalHostName`(Bonjour 本地名称)和 `ComputerName`(Finder 显示名),三者独立管理。
-- 若问题在重启后复现,可以检查 `/etc/hosts` 中是否有相关条目,或确认 DHCP/DNS 服务器是否持续下发不期望的主机名。
diff --git a/docs/zh-hans/blogs/minio-admin-guide.md b/docs/zh-hans/blogs/minio-admin-guide.md
deleted file mode 100644
index 2386316..0000000
--- a/docs/zh-hans/blogs/minio-admin-guide.md
+++ /dev/null
@@ -1,200 +0,0 @@
----
-title: MinIO 新版本管理中心
-tags:
- - minio
- - storage
- - s3
- - devops
- - cheatsheet
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-MinIO 在新版本中将管理功能从 Web UI 中移除了。现在需要使用 **MinIO Client (mc)** 命令行工具来进行管理操作。
-
-## 安装 MinIO Client (mc)
-
-### Windows:
-
-```powershell
-# 下载 mc.exe
-Invoke-WebRequest -Uri "https://dl.min.io/client/mc/release/windows-amd64/mc.exe" -OutFile "mc.exe"
-
-# 或使用 Chocolatey
-choco install minio-client
-```
-
-### Linux/macOS:
-
-```bash
-# Linux
-wget https://dl.min.io/client/mc/release/linux-amd64/mc
-chmod +x mc
-sudo mv mc /usr/local/bin/
-
-# macOS
-brew install minio/stable/mc
-```
-
-## 配置 MinIO Client
-
-```bash
-# 添加 MinIO 服务器别名
-mc alias set myminio http://localhost:9000 minioadmin minioadmin
-
-# 验证连接
-mc admin info myminio
-```
-
-## 用户管理操作
-
-### 创建用户
-
-```bash
-# 创建新用户
-mc admin user add myminio newuser newpassword
-
-# 查看所有用户
-mc admin user list myminio
-```
-
-### 创建 Access Key 和 Secret Key
-
-```bash
-# 为用户创建服务账户(生成 AccessKey/SecretKey)
-mc admin user svcacct add myminio newuser
-
-# 或者指定自定义的 AccessKey
-mc admin user svcacct add myminio newuser --access-key "MYACCESSKEY123" --secret-key "MYSECRETKEY456"
-
-# 查看用户的服务账户
-mc admin user svcacct list myminio newuser
-```
-
-## 权限管理
-
-### 创建策略
-
-```bash
-# 创建策略文件 policy.json
-cat > policy.json << EOF
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:GetObject",
- "s3:PutObject",
- "s3:DeleteObject"
- ],
- "Resource": [
- "arn:aws:s3:::mybucket/*"
- ]
- }
- ]
-}
-EOF
-
-# 添加策略
-mc admin policy add myminio mypolicy policy.json
-
-# 将策略分配给用户
-mc admin policy set myminio mypolicy user=newuser
-```
-
-## 存储桶管理
-
-```bash
-# 创建存储桶
-mc mb myminio/mybucket
-
-# 列出存储桶
-mc ls myminio
-
-# 设置存储桶策略
-mc policy set public myminio/mybucket
-```
-
-## 常用管理命令
-
-```bash
-# 查看服务器信息
-mc admin info myminio
-
-# 查看服务器配置
-mc admin config get myminio
-
-# 重启服务器
-mc admin service restart myminio
-
-# 查看日志
-mc admin logs myminio
-
-# 查看统计信息
-mc admin prometheus metrics myminio
-```
-
-## 实用脚本示例
-
-创建一个管理脚本 `setup-minio.sh`:
-
-```bash
-#!/bin/bash
-
-MINIO_ALIAS="myminio"
-MINIO_URL="http://localhost:9000"
-ADMIN_USER="minioadmin"
-ADMIN_PASS="minioadmin"
-
-# 配置 MinIO 客户端
-mc alias set $MINIO_ALIAS $MINIO_URL $ADMIN_USER $ADMIN_PASS
-
-# 创建应用用户
-APP_USER="appuser"
-APP_PASS="apppassword"
-mc admin user add $MINIO_ALIAS $APP_USER $APP_PASS
-
-# 创建服务账户并获取 AccessKey/SecretKey
-echo "Creating service account for $APP_USER..."
-CREDENTIALS=$(mc admin user svcacct add $MINIO_ALIAS $APP_USER --json)
-ACCESS_KEY=$(echo $CREDENTIALS | jq -r '.accessKey')
-SECRET_KEY=$(echo $CREDENTIALS | jq -r '.secretKey')
-
-echo "Generated credentials:"
-echo "Access Key: $ACCESS_KEY"
-echo "Secret Key: $SECRET_KEY"
-
-# 创建存储桶
-mc mb $MINIO_ALIAS/app-bucket
-
-# 设置只读策略
-mc policy set download $MINIO_ALIAS/app-bucket
-```
-
-## Web Console 访问
-
-虽然管理功能被移除,但您仍然可以通过以下方式访问 MinIO Console:
-
-```bash
-# 启动 MinIO Console(如果单独安装)
-mc admin console myminio
-```
-
-或者在启动 MinIO 服务器时指定 Console 地址:
-
-```bash
-minio server /data --console-address ":9001"
-```
-
-## 总结
-
-新版 MinIO 的管理完全依赖 `mc` 命令行工具:
-
-1. **安装 mc 客户端**
-2. **配置服务器别名**
-3. **使用 `mc admin` 命令进行用户、权限、存储桶管理**
-4. **通过 `mc admin user svcacct` 生成 AccessKey/SecretKey**
-
-这种方式虽然需要命令行操作,但提供了更强大和灵活的管理能力,特别适合自动化部署和脚本化管理。
diff --git a/docs/zh-hans/blogs/mybatis-flex.md b/docs/zh-hans/blogs/mybatis-flex.md
deleted file mode 100644
index 6c22aad..0000000
--- a/docs/zh-hans/blogs/mybatis-flex.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-title: MyBatis Flex
-tags:
- - java
- - mybatis
- - spring-boot
- - orm
- - framework
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-> 本文仅针对在 Spring Boot 3 中使用 `MyBatis Flex`
-
-## 安装与配置
-
-### 安装
-
-在 `gradle` 目录下的 `libs.versions.toml` 中添加如下代码:
-
-```toml
-[versions]
-mybatisFlexVersion = "X.Y.Z"
-hikariVersion = "X.Y.Z"
-
-[libraries]
-hikari = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikariVersion" }
-mybatisFlex-processor = { group = "com.mybatis-flex", name = "mybatis-flex-processor", version.ref = "mybatisFlexVersion" }
-mybatisFlex-starter = { group = "com.mybatis-flex", name = "mybatis-flex-spring-boot3-starter", version.ref = "mybatisFlexVersion" }
-```
diff --git a/docs/zh-hans/blogs/postgresql-zhparser-fuzzy-search.md b/docs/zh-hans/blogs/postgresql-zhparser-fuzzy-search.md
deleted file mode 100644
index 6b97ac5..0000000
--- a/docs/zh-hans/blogs/postgresql-zhparser-fuzzy-search.md
+++ /dev/null
@@ -1,218 +0,0 @@
----
-title: 使用分词在 PostgreSQL 中加速模糊查询
-tags:
- - postgresql
- - zhparser
- - full-text-search
- - performance
-author:
- name: Siu Jam Oh
- email: jamo.siu@gmail.com
----
-
-## 背景与挑战
-
-随着业务数据量突破 **200 万行**,传统的 `LIKE '%关键词%'` 模糊查询导致数据库 I/O 频繁告警,查询响应时间从毫秒级退化至秒级。为提升检索效率并支持中文语义,我们决定引入 `zhparser` 插件实现全文检索。
-
-## 演进路线与环境适配
-
-本次技术落地经历了四个关键阶段,每个阶段解决了不同的技术核心:
-
-### CentOS 7.9 虚拟机(可行性验证)
-
-- **目标**:验证 `SCWS` + `zhparser` 在旧版系统下的兼容性。
-- **核心操作**:在 CentOS 7.9 环境下手动编译 `postgresql-16.2` 源码,完成插件初步跑通。
-
-**结论**:确认了分词方案对中文检索性能的显著提升。
-
-### 本地 Docker 容器(容器化探索)
-
-- **目标**:在本地的完整系统进行初步测试。
-- **核心操作**:通过 `docker cp` 注入二进制 `.so` 文件,解决 `ldconfig` 动态链接库路径可见性问题。
-- **发现**:识别出 **"词典文件缺失"** 会导致分词退化为单字(助词)的故障点。
-
-### EulerOS 2.0 测试服(自编译环境适配)
-
-- **目标**:适配生产环境的 OS 架构(x86_64)与自编译安装的 PostgreSQL。
-- **核心问题**:解决了 `libscws.so.1` 无法加载的报错。
-- **关键方案**:
- - 明确了 `postgres` 运行用户对 `/usr/local/scws/lib` 的访问权限需求。
- - 通过修改 `systemd` 服务环境变量或创建 `/usr/lib64` 软链接强制刷新库搜索路径。
-
-### 生产部署预备(最终调优)
-
-- **目标**:确保 200w+ 数据量下的查询稳定性。
-- **优化点**:针对"非语义片段(如:古唐合)"查询不到的问题,制定了"全文检索优先 + `pg_trgm` 索引辅助"的降级查询策略。
-
-## 核心安装与配置步骤 (自编译环境)
-
-### 安装 `SCWS` 分词引擎
-
-SCWS 是 `zhparser` 依赖的底层核心,必须先行安装。
-
-1. **下载并解压**:下载源码包(如 `scws-1.2.3`)。
-2. **编译安装**:
-
- ```bash
- ./configure --prefix=/usr/local/scws
- make && make install
- ```
-
-3. **验证库文件**:确保 `/usr/local/scws/lib/libscws.so.1` 存在。
-
-### 编译与安装 `zhparser`
-
-这一步需要用到 PostgreSQL 自编译产生的 `pg_config`。
-
-1. **获取源码**:从 GitHub 克隆 `zhparser` 项目。
-2. **指定路径编译**:
-
- ```bash
- # 确保 pg_config 在 PATH 中,或手动指定
- make USE_PGXS=1 PG_CONFIG=/usr/local/pgsql/bin/pg_config
- make USE_PGXS=1 PG_CONFIG=/usr/local/pgsql/bin/pg_config install
- ```
-
- _注:`install` 步骤会自动将 `zhparser.so` 放入 PG 的 `pkglibdir`,将脚本放入 `extension` 目录。_
-
-### 解决动态链接库依赖
-
-1. **刷新系统缓存**:
-
- ```bash
- echo "/usr/local/scws/lib" > /etc/ld.so.conf.d/scws.conf
- ldconfig
- ```
-
-2. **权限检查**:确保运行 `postgres` 的 OS 用户对 `/usr/local/scws/lib` 有 `rx` 权限。
-3. **强制软链 (备选)**:若 `ldconfig` 失效,可将库文件软链至 `/usr/lib64`。
-
-### 重启数据库
-
-修改完系统共享库配置后,必须重启 PostgreSQL 进程以重新加载环境变量和链接库。
-
-```bash
-## 使用 pg_ctl 重启(自编译路径需根据实际情况调整)
-/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data restart
-
-## 或通过 systemd 重启(如果已注册服务)
-systemctl restart postgresql
-```
-
-### 数据库内初始化
-
-连接到 `psql`,执行逻辑配置:
-
-```sql
--- 创建扩展
-CREATE EXTENSION zhparser;
-
--- 创建全文检索配置并绑定分词器
-CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
-
--- 添加 Token 映射
-ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l,t,b WITH simple;
-
--- 【可选】指定自编译路径下的词典位置
--- ALTER DATABASE postgres SET zhparser.dict_path = '/usr/local/scws/etc/dict.utf8.xdb';
-```
-
-## 性能分析与避坑指南
-
-### 索引性能瓶颈分析
-
-在测试中发现,即使是精确查询,由于使用了不当的联合索引(`create_time` 在首列),导致产生 `Bitmap Index Scan`,耗时高达 **482ms**。
-
-- **改进**:对检索高频列建立单列 **B-tree** 索引,利用 `Index Scan` 将响应降至 **10ms** 以内。
-
-### GIN 索引与非语义匹配
-
-- **跨词截断问题**:分词引擎基于语义,类似"古唐合"这种截断词可能因为分词边界导致 `@@` 无法命中。
-- **应对方案**:采用"瀑布式搜索"。全文检索(FTS)优先;若结果为空,自动降级为 `LIKE` 模糊查询,并配合 `pg_trgm` 索引加速。
-
-## 终极部署方案:双轨并行检索
-
-经过对数据的分析,发现对于账户名称中出现了约 1.24% 的非标准简体中文的数据,并且数据库中也存在部分因为公司名称怪异而导致数据查询不出来的问题,决定采取"分步降级"策略:
-
-- **第一步:全文检索(Fast Track):** 利用 GIN 索引进行 `@@` 匹配。
-- **第二步:结果评估:** 若返回结果为空,且搜索词包含字母或疑似繁体字符。
-- **第三步:模糊兜底(Safe Fallback):** 执行 `LIKE '%关键词%'`。虽然速度较慢,但由于其作为"补漏"逻辑,触发频率仅为 1% 左右,不会对数据库造成整体压力。
-
-## 搜索优化:集成自定义业务词库
-
-为了解决全文检索中公司品牌名被误切(如"元一"被切分为数词/量词)的问题,需构建一套从数据提取到索引重建的自动化维护链路。
-
-### 词库提取与预处理
-
-利用 **`companynameparser`** 的结构化解析能力剥离地名与行业后缀,并结合 **`jieba`** 进行语义复核,确保核心品牌词的完整性:
-
-- **提取逻辑**:通过 Python 脚本遍历全量 `buyer_unique_name`,提取核心 `brand` 字段。
-- **权重补偿**:针对包含"元"、"一"、"三"等易碎词条,手动将 TF(词频权重)提升至 **50.0 - 60.0**,确保其优先级高于内置量词规则。
-- **输出规范**:输出符合 SCWS 标准的 4 字段 `UTF-8` 文本(WORD, TF, IDF, ATTR),建议使用制表符 `\t` 分隔以规避解析异常。
-
-### 词库编译与部署
-
-
-
-:::tip
-适用于 Windows 的原生 scws 命令行工具使用 MingW 编译。源码与编译说明见上游
-[SCWS 项目](https://github.com/hightman/scws)。
-:::
-
-将文本词典转换为 SCWS 高效二进制格式(XDB):
-
-1. **编译二进制词典**:
-
- ```bash
- # 使用 scws-gen-dict 工具生成加密二进制词库
- /usr/local/scws/bin/scws-gen-dict -i custom_company.txt -o /usr/local/scws/etc/custom_company.xdb -c utf8
- ```
-
-2. **文件分发与权限**:将生成的 `.xdb` 文件移动至分词数据目录,并确保 `postgres` 用户具备读取权限:
-
- ```bash
- cp custom_company.xdb /usr/local/pgsql/share/tsearch_data/
- chown postgres:postgres /usr/local/pgsql/share/tsearch_data/custom_company.xdb
- ```
-
-### 数据库参数固化
-
-修改 `postgresql.conf` 配置文件,强制加载 `zhparser` 及其自定义扩展词库:
-
-```plain text
-## 预加载插件库(必须重启生效)
-shared_preload_libraries = 'zhparser'
-
-## 加载自定义外部词典(需使用相对 tsearch_data 的路径)
-zhparser.extra_dicts = 'custom_company.xdb'
-```
-
-### 索引热更新与验证
-
-由于分词规则变动,存量数据必须通过重建索引实现语义同步:
-
-**物理重启服务**:
-
-```bash
-su - postgres -c "/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data restart"
-```
-
-**在线重建索引**:利用 `CONCURRENTLY` 关键字,在不阻塞 40 万条数据 DML 操作的前提下刷新 GIN 索引:
-
-```bash
-REINDEX INDEX CONCURRENTLY index_name;
-```
-
-**分词效能验证**:
-
-```sql
--- 预期结果词性应显示为 n (noun),而非 x (unknown)
-SELECT * FROM ts_debug('chinese', '元一能源');
-```
-
-**优化建议:**
-
-- **显式提及权重补偿**:这是解决"元一"分词失败(显示为 `x`)的关键技术点。
-- **区分重启与重载**:明确 `shared_preload_libraries` 必须通过 `restart` 激活。
diff --git a/docs/zh-hans/blogs/quartile-method.md b/docs/zh-hans/blogs/quartile-method.md
deleted file mode 100644
index db80f03..0000000
--- a/docs/zh-hans/blogs/quartile-method.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: 四分位法
-tags:
- - statistics
- - algorithm
- - data-analysis
- - math
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-四分位法是统计学中的一种常用方法,主要用于数据的分析和表示。这种方法涉及将一组数据分为四个等分,每份包含四分之一的数据量。主要的统计量包括第一四分位数(Q1)、第二四分位数(Q2),即中位数和第三四分位数(Q3)。
-
-- 第一四分位数(`Q1`),也称为下四分位数,是指数据集中所有数值按大小排列后位于第 25% 位置的数值。
-- 第二四分位数(`Q2`),即中位数,是指数据集中所有数值按大小排列后位于第 50% 位置的数值。
-- 第三四分位数(`Q3`),也称为上四分位数,是指数据集中所有数值按大小排列后位于第 75% 位置的数值。
-- 四分位距(`IQR`),即第三四分位数与第一四分位数之间的差值,用于表示数据集中间50%数据的离散程度。四分位距的计算公式为 IQR = Q3 - Q1。四分位距常用于构建箱形图,是一种描述数据分布的有效方式,特别适用于识别数据中的异常值。
-
-上界值 = Q3 + 1.5 IQR。
-
-下界值 = Q1 - 1.5 IQR。
diff --git a/docs/zh-hans/blogs/setup-ldap-service.md b/docs/zh-hans/blogs/setup-ldap-service.md
deleted file mode 100644
index 2509f9b..0000000
--- a/docs/zh-hans/blogs/setup-ldap-service.md
+++ /dev/null
@@ -1,140 +0,0 @@
----
-title: 搭建 LDAP 服务
-tags:
- - ldap
- - openldap
- - authentication
- - linux
- - devops
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-搭建 LDAP(轻型目录访问协议)服务器是实现企业级**集中身份认证**和**权限管理**的核心步骤。最常用的开源实现是 **OpenLDAP**。
-
-以下是在基于 Debian/Ubuntu 的 Linux 系统上搭建 OpenLDAP 服务器的详细步骤。
-
-## 环境准备与安装
-
-在开始之前,请确保你的系统软件包是最新的,并设置好主机名。
-
-```bash
-## 更新系统
-sudo apt update && sudo apt upgrade -y
-
-## 安装 OpenLDAP 及管理工具
-## slapd 是守护进程,ldap-utils 是命令行客户端工具
-sudo apt install slapd ldap-utils -y
-```
-
-> 在安装过程中,系统会提示你设置 **LDAP 管理员密码**。请务必记住这个密码,稍后配置时会频繁使用。
-
-## 配置 OpenLDAP 服务器
-
-虽然安装时已经初始化了部分设置,但通常我们需要根据具体的域名(如 `example.com`)进行自定义配置。
-
-### 重新配置 slapd
-
-执行以下命令进入交互式配置界面:
-
-```bash
-sudo dpkg-reconfigure slapd
-```
-
-**配置建议**:
-
-1. **Omit OpenLDAP server configuration?** 选择 **No**。
-2. **DNS domain name:** 输入你的域名(例如 `centre.example.com`)。这将决定你的基准识别名(Base DN),如 `dc=centre,dc=example,dc=com`。
-3. **Organization name:** 输入你的组织名称。
-4. **Administrator password:** 输入之前设置的管理员密码。
-5. **Database backend:** 建议选择 **MDB**。
-6. **Remove database when slapd is purged?** 选择 **No**。
-7. **Move old database?** 选择 **Yes**。
-
-## 理解 LDAP 层级结构
-
-LDAP 的数据是以**树状结构**存储的。为了方便管理,我们通常会创建两个"组织单元"(Organizational Units, OU):一个存放用户(Users),一个存放组(Groups)。
-
-## 创建组织单元 (OU)
-
-在 LDAP 中,我们使用 **LDIF** (LDAP Data Interchange Format) 文件来添加或修改目录。
-
-创建一个名为 `base.ldif` 的文件:
-
-```text
-## 创建用户组 OU
-dn: ou=people,dc=centre,dc=example,dc=com
-objectClass: organizationalUnit
-ou: people
-
-## 创建用户组别 OU
-dn: ou=groups,dc=centre,dc=example,dc=com
-objectClass: organizationalUnit
-ou: groups
-```
-
-**导入数据:**
-
-```bash
-## 使用管理员身份将 LDIF 文件导入数据库
-ldapadd -x -D "cn=admin,dc=centre,dc=example,dc=com" -W -f base.ldif
-```
-
-## 添加用户和组
-
-创建一个名为 `groups.ldif` 的文件来定义一个新组:
-
-```text
-## 定义一个新组
-dn: cn=developers,ou=groups,dc=centre,dc=example,dc=com
-objectClass: inetOrgGroup
-cn: developers
-```
-
-创建一个名为 `users.ldif` 的文件来定义一个新用户:
-
-```text
-## 定义一个新用户
-dn: uid=jbloggs,ou=people,dc=centre,dc=example,dc=com # 该条目的身份证号,即 Distinguished Name (DN)。
-objectClass: inetOrgPerson # 对象类,inetOrgPerson 代表这是一个互联网机构人员。它允许你使用 email、displayName、telephoneNumber 等常见的联系人属性
-objectClass: posixAccount # 它使该条目兼容 Unix/Linux 系统账号。有了它,用户才能登录 Linux 服务器,并拥有 UID、GID 和家目录。
-objectClass: shadowAccount # 用于管理密码老化(如过期、更改警告等),对应 Linux 中的 /etc/shadow 文件功能。
-uid: jbloggs # 用户的登录名(User ID)。在 Linux 登录界面输入的通常就是这个。
-sn: Bloggs # 姓(Surname)。inetOrgPerson 类要求必须填写。
-givenName: Joe # 名(First Name)。
-cn: Joe Bloggs # 全名(Common Name)。这是 LDAP 条目的标准显示名称。
-displayName: Joe Bloggs # 在图形界面或邮件客户端显示的友好名称。
-uidNumber: 10000 # Linux 系统中的用户 ID 数字
-gidNumber: 5000 # 用户主组的 ID 数字。
-userPassword: {SSHA}密码哈希值或明文 # 存储用户的加密密码。
-homeDirectory: /home/jbloggs # 用户登录 Linux 后的家目录路径。
-loginShell: /bin/bash # 用户登录后使用的 Shell 环境。
-```
-
-> 如果您将来要集成 **GitLab**、**Jenkins** 或 **VPN**,它们通常会搜索 `uid` 属性来验证登录名。
-
-### FAQ
-
-#### 如果不需要为该用户授予服务器的登录权限,是不是可以移除 objectClass: posixAccount?
-
-**是的,完全可以移除**,但你需要注意属性之间的"绑定关系"。
-
-如果你只需要这个用户用于 Web 应用登录(如 GitLab, Jenkins, Wiki)或作为电子邮件联系人,而不需要他通过 SSH 或控制台登录 Linux 服务器,移除 `posixAccount` 是更规范的做法。
-
-当你移除 `objectClass: posixAccount` 时,以下属性**必须一并删除**,因为它们属于该类定义的"强制或可选属性":
-
-- `uidNumber`
-- `gidNumber`
-- `homeDirectory`
-- `loginShell`
-
-此外, `shadowAccount` 通常也与系统登录挂钩,如果不需要管理 Linux 密码过期策略,也可以一并移除。
-
-## 后续建议与管理工具
-
-命令行管理 LDAP 较为繁琐,建议使用以下工具进行可视化操作:
-
-- **phpLDAPAdmin**: 基于 Web 的管理界面,适合快速上手;
-- **Apache Directory Studio**: 强大的跨平台桌面客户端,适合复杂的架构设计。
-- **安全加固**: 默认情况下 LDAP 是明文传输的,建议配置 **LDAPS (LDAP over SSL/TLS)** 来加密 636 端口的通信。
diff --git a/docs/zh-hans/blogs/use-json-in-mysql.md b/docs/zh-hans/blogs/use-json-in-mysql.md
deleted file mode 100644
index 2bebd4e..0000000
--- a/docs/zh-hans/blogs/use-json-in-mysql.md
+++ /dev/null
@@ -1,89 +0,0 @@
----
-title: 在 MySQL 中使用 JSON
-tags:
- - mysql
- - json
- - database
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-MySQL (自 5.7 版本开始) **不直接支持名为 `jsonb` 的数据类型**。`jsonb` 是 PostgreSQL 数据库特有的数据类型,它以二进制格式存储 JSON 数据,并对其进行预解析,以便在查询时更快地访问和操作。
-
-然而,MySQL 提供的 `JSON` 数据类型在功能和内部实现上与 PostgreSQL 的 `jsonb` 有很多相似之处,尤其是在查询数据方面。
-
-MySQL 的 `JSON` 数据类型于 MySQL 5.7 版本引入,其特点如下:
-
-1. **二进制存储**:与 PostgreSQL 的 `jsonb` 类似,MySQL 的 `JSON` 类型数据也是以**内部二进制格式**存储的,而不是简单的文本字符串。这使得 JSON 数据的读取和操作效率更高,因为数据库不必在每次查询时都解析文本格式的 JSON 字符串。
-2. **自动验证**:当您插入或更新 `JSON` 列时,MySQL 会自动验证其内容是否是有效的 JSON 文档。如果不是,则会抛出错误。
-3. **优化存储**:二进制格式的存储也对空间进行了优化,通常比存储原始文本格式的 JSON 更加紧凑。
-
-MySQL 提供了一系列强大的函数和操作符来查询和操作 `JSON` 数据,这些功能与您对 `jsonb` 的期望非常相似:
-
-1. **`->` (JSON Extract Operator)**:用于从 JSON 文档中提取值。它返回一个 JSON 值。
-
- ```sql
- SELECT my_json_column->'$.key' FROM my_table;
- -- 示例:提取 user 对象的 name 属性
- -- 假设 my_json_column 存储 {'user': {'name': 'Alice'}}
- SELECT json_data->'$.user.name' FROM my_table;
- ```
-
-2. **`->>` (JSON Unquote Operator)**:用于从 JSON 文档中提取值并**自动取消引用 (unquote)**,通常返回一个标量值(如字符串、数字)。这等同于 `JSON_UNQUOTE(JSON_EXTRACT(...))`。
-
- ```sql
- SELECT my_json_column->>'$.key' FROM my_table;
- -- 示例:提取 user 对象的 name 属性(直接返回字符串 'Alice')
- SELECT json_data->>'$.user.name' FROM my_table;
- ```
-
-3. **`JSON_EXTRACT(json_doc, path, ...)`**:显式地从 JSON 文档中提取数据。
-
- ```sql
- SELECT JSON_EXTRACT(my_json_column, '$.key') FROM my_table;
- ```
-
-4. **`JSON_CONTAINS(json_doc, candidate, path)`**:检查 JSON 文档中是否包含指定的值。
-
- ```sql
- -- 检查tags数组是否包含 'backend'
- -- 假设 my_json_column 存储 {'tags': ['frontend', 'backend']}
- SELECT * FROM my_table WHERE JSON_CONTAINS(json_data->'$.tags', '"backend"');
- ```
-
-5. **`JSON_SEARCH(json_doc, one_or_all, search_str, escape_char, path, ...)`**:返回指定字符串在 JSON 文档中的路径。
-
- ```sql
- -- 查找值为 'test' 的路径
- SELECT JSON_SEARCH(my_json_column, 'one', 'test') FROM my_table;
- ```
-
-6. **`JSON_TABLE(json_doc, path COLUMNS ...) ` (MySQL 8.0 及更高版本)**:这是一个非常强大的函数,可以将 JSON 数据 "展开" 成关系型的行和列,非常适合进行复杂查询和报表。
-
- ```sql
- -- 假设 json_data 存储 {'items': [{'id': 1, 'name': 'A'}, {'id': 2, 'name': 'B'}]}
- SELECT *
- FROM my_table,
- JSON_TABLE(json_data, '$.items[*]' COLUMNS(
- itemId INT PATH '$.id',
- itemName VARCHAR(50) PATH '$.name'
- )) AS jt;
- ```
-
-像 PostgreSQL 的 `jsonb` 一样,为了对 JSON 字段进行高效查询,您通常需要创建索引。由于 JSON 字段的内容是动态的,MySQL 不直接支持在 JSON 字段的某个内部路径上直接创建传统 B-tree 索引。但是,可以通过 **虚拟列 (Virtual Generated Columns)** 来实现:
-
-1. **创建虚拟列**:定义一个虚拟列,其值是从 JSON 字段中提取的特定路径。
-
- ```sql
- ALTER TABLE my_table
- ADD COLUMN user_name VARCHAR(255) AS (json_data->>'$.user.name') VIRTUAL;
- ```
-
-2. **在虚拟列上创建索引**:这样,当您查询 `WHERE json_data->>'$.user.name' = 'Alice'` 时,MySQL 优化器可以选择使用 `idx_user_name` 索引,从而大大提高查询性能。
-
- ```sql
- CREATE INDEX idx_user_name ON my_table (user_name);
- ```
-
-尽管 MySQL 没有 `jsonb` 这个名字,但其 `JSON` 数据类型提供了高度相似的功能:二进制存储优化、自动验证和丰富的查询操作符及函数。通过结合虚拟列和索引,MySQL 可以在处理 JSON 数据时提供与 PostgreSQL 的 `jsonb` 相似的查询性能和灵活性。
diff --git a/docs/zh-hans/blogs/use-of-gravatar.md b/docs/zh-hans/blogs/use-of-gravatar.md
deleted file mode 100644
index 066f443..0000000
--- a/docs/zh-hans/blogs/use-of-gravatar.md
+++ /dev/null
@@ -1,82 +0,0 @@
----
-title: 在第一方系统中使用 Gravatar
-tags:
- - gravatar
- - avatar
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-[Gravatar](https://gravatar.com)(Globally Recognised Avatar)是一项将头像图片与邮箱地址关联的服务。当用户使用邮箱在你的平台上注册时,你可以直接展示其
-Gravatar 作为默认头像,而无需自行搭建图片上传和存储服务。
-
-## 工作原理
-
-Gravatar 提供了一个简单的 HTTP 端点。你只需计算用户**小写并去除首尾空格后**的邮箱地址的 SHA256 哈希值,然后将其嵌入图片
-URL:
-
-```
-https://gravatar.com/avatar/
-```
-
-Always pass the `d` parameter to avoid broken images for users who have not set up a Gravatar. `identicon` and
-`robohash` are popular choices because they generate a unique, recognisable image for every hash.
diff --git a/docs/en-gb/blogs/version-control-and-code-review.md b/docs/en-gb/blogs/version-control-and-code-review.md
deleted file mode 100644
index 335a473..0000000
--- a/docs/en-gb/blogs/version-control-and-code-review.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: Version Control and Code Review
-tags:
- - git
- - code-review
- - best-practice
- - workflow
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-## GitFlow Workflow
-
-Version control will use the GitFlow branching model, consisting of `main`, `develop`, `feature`, `release`, and
-`hotfix` branches.
-
-- `main`: Production-ready code. Only `release` and `hotfix` branches are merged into `main`.
-- `develop`: Integration branch for upcoming features.
-- `feature/*`: Branches for new features, branched off `develop`.
-- `release/*`: Branches for preparing new production releases, branched off `develop`.
-- `hotfix/*`: Branches for urgent production bug fixes, branched off `main`.
-
-## Pull Requests/Merge Requests
-
-All code changes (except direct pushes to feature branches) must be submitted via pull requests.
-
-## Code Review
-
-- Each pull request must be reviewed by at least one other developer.
-- Reviewers are responsible for checking compliance with these coding standards, code quality, logical correctness, and
- test coverage.
-- IntelliJ IDEA's integrated code analysis tools should be run locally before creating a PR.
-
-## Commit Messages
-
-Write clear, concise, and descriptive commit messages that explain what was changed and why. If possible, follow the
-Conventional Commits format (e.g., `feat: add user registration endpoint`).
diff --git a/docs/en-gb/blogs/windows-driver-backup-restore.mdx b/docs/en-gb/blogs/windows-driver-backup-restore.mdx
deleted file mode 100644
index 89ca6c5..0000000
--- a/docs/en-gb/blogs/windows-driver-backup-restore.mdx
+++ /dev/null
@@ -1,85 +0,0 @@
----
-title: Backup and Restore Windows Drivers When Reinstalling the System
-tags:
- - windows
- - driver
- - backup
- - system-reinstall
- - dism
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-import { Kbd } from "@rspress/core/theme"
-
-One of the most tedious parts of reinstalling Windows is getting all the drivers back — graphics, network, audio, Bluetooth, touchpad, chipset — missing any one of them disrupts your workflow. Windows Update can fetch some automatically, but the versions are often outdated, and niche hardware drivers may not be found at all.
-
-Fortunately, Windows' built-in DISM tool provides driver export and restore functionality. Spend one minute backing up before the reinstall, and you can restore every driver in a single command afterwards.
-
-## Before Reinstalling: Back Up All Drivers
-
-Open a terminal as **Administrator** (PowerShell or Command Prompt) and run:
-
-```powershell
-dism /online /export-driver /destination:D:\DriverBackup
-```
-
-Replace `D:\DriverBackup` with your desired backup path. It is best to save the backup to an external drive, USB stick, or a non-system partition so it survives the reformat.
-
-The command enumerates every third-party driver installed on the system and exports them to the destination folder. The whole process typically completes within a minute. You should see output similar to:
-
-```
-The operation completed successfully.
-```
-
-Keep the backup directory safe, and you are ready to reinstall.
-
-### What gets backed up?
-
-The command exports **third-party drivers** — i.e. drivers that are not built into Windows. This covers graphics cards, audio, network adapters, chipsets, Bluetooth, card readers, and any other drivers you have installed over the lifetime of the system. Generic inbox drivers that ship with Windows are skipped, as they will be restored automatically after the reinstall.
-
-## After Reinstalling: Restore All Drivers
-
-### Method 1: One-command restore (recommended)
-
-This is the most convenient approach. Open a terminal as **Administrator** and run:
-
-```powershell
-dism /online /add-driver /driver:D:\DriverBackup /recurse
-```
-
-The `/recurse` flag tells DISM to search all subfolders within the backup directory and install every driver it finds. **You must restart the computer** afterwards for the changes to take effect.
-
-### Method 2: Via Device Manager (GUI)
-
-If you prefer a graphical interface or only need to restore specific drivers:
-
-1. Press Win + X and select **Device Manager**
-2. Locate devices marked with a yellow exclamation mark (missing drivers)
-3. Right-click the device and choose **Update driver**
-4. Select **Browse my computer for drivers**
-5. Point the path to your driver backup directory and tick **Include subfolders**
-6. Click Next — Windows will search and install the matching driver
-
-Repeat for each device until all are restored.
-
-## Common Issues
-
-### "The driver package could not be installed"
-
-In rare cases, certain drivers may fail to install via DISM due to signature issues or version incompatibility. As a workaround, locate the corresponding `.inf` file in the backup directory, right-click it, and select **Install**.
-
-### Some devices still lack drivers after restore
-
-DISM only backs up drivers that were currently installed. If a device was already undriven before the backup, its driver will obviously not be included. It is worth checking Device Manager beforehand to ensure all hardware is properly functional.
-
-### Can I restore across Windows versions?
-
-Restoring drivers from Windows 10 to Windows 11 on the same machine is generally viable, but migrating driver backups across different hardware is not recommended. Each machine should have its own independent backup.
-
-## Summary
-
-The key advantage of this workflow is **zero third-party dependencies** — DISM is a built-in Windows component, and no extra software is required. One minute to export before reinstalling, one command to restore afterwards. Far more efficient than manually downloading and installing each driver one by one. Make driver backup a habit before every system reinstall, and each migration will be that much smoother.
-
-> This guide is based on a video tutorial by Douyin user [@科技碎碎念](https://v.douyin.com/Cbf0ruVdbUM/).
diff --git a/docs/en-gb/notifications/index.md b/docs/en-gb/notifications/index.md
deleted file mode 100644
index c9f3e94..0000000
--- a/docs/en-gb/notifications/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: News
----
-
-## Microsoft Email Delivery Issues (@outlook, @hotmail, @live, @msn and custom domain emails hosted on Microsoft)
-
-> Updated at _19 May 2026_.
-
-**Urgent Action Required for Users with Microsoft-Hosted Emails.**
-
-Please be advised that our automated email service is currently experiencing severe delivery issues to all email addresses hosted by Microsoft. Due to recent aggressive filtering policies by their Exchange Online Protection (EOP), our mail delivery server has been blocked by Microsoft. As a consequence, our system is **unable to send any notifications, password resets, or activation emails** to accounts ending in **@outlook.com**, **@hotmail.com**, **@live.com**, **@msn.com**, or **indeed any custom domains hosted by Microsoft**.
-
-To ensure uninterrupted service, please follow the guidance below based on your account status:
-
-- For Prospective Users (Before Registration): Please **do not** use a Microsoft-hosted email address to register your account. You will not receive the essential activation link. Kindly use an alternative email service provider, such as your corporate email, Gmail, etc. to complete your registration.
-- For Existing Registered Users: If your profile is currently linked to an Outlook or Hotmail address, please log in immediately and update your primary email address. You can change this by navigating to your **[User Settings -> Preferences -> Emails](https://github.com/settings/emails)** page. Failing to do so will result in missing critical repository updates, CI/CD pipeline failure logs, and Merge Request notifications.
-
-We are actively working to appeal this block with the Microsoft Postmaster Centre. We sincerely apologise for any inconvenience caused and appreciate your prompt cooperation in updating your contact details.
diff --git a/docs/en-gb/opensource-projects/_meta.json b/docs/en-gb/opensource-projects/_meta.json
deleted file mode 100644
index ac3637c..0000000
--- a/docs/en-gb/opensource-projects/_meta.json
+++ /dev/null
@@ -1,14 +0,0 @@
-[
- "index",
- { "type": "section-header", "label": "opensource.group.libraries" },
- { "type": "dir", "name": "onixbyte-toolbox" },
- { "type": "dir", "name": "regions4j" },
- { "type": "dir", "name": "captcha" },
- { "type": "dir", "name": "calendar-toolbox" },
- { "type": "section-header", "label": "opensource.group.applications" },
- { "type": "dir", "name": "helix" },
- { "type": "dir", "name": "delta-force-guide" },
- { "type": "section-header", "label": "opensource.group.tools" },
- { "type": "dir", "name": "claude-code-skill-manager" },
- { "type": "dir", "name": "vite-plugins" }
-]
diff --git a/docs/en-gb/opensource-projects/calendar-toolbox/api.md b/docs/en-gb/opensource-projects/calendar-toolbox/api.md
deleted file mode 100644
index b162821..0000000
--- a/docs/en-gb/opensource-projects/calendar-toolbox/api.md
+++ /dev/null
@@ -1,390 +0,0 @@
----
-title: Calendar Toolbox API
----
-
-## Package Overview
-
-The library is organised under the base package `com.onixbyte.calendar` with the following structure:
-
-| Package | Description |
-| ------------------------------------------ | ------------------------------------------ |
-| `com.onixbyte.calendar` | Root calendar object |
-| `com.onixbyte.calendar.component` | iCalendar components (VEVENT, VTODO, etc.) |
-| `com.onixbyte.calendar.component.property` | Component-level properties |
-| `com.onixbyte.calendar.property` | Calendar-level properties |
-| `com.onixbyte.calendar.parameter` | iCalendar property parameters |
-| `com.onixbyte.calendar.recurrence` | Recurrence rule types |
-| `com.onixbyte.calendar.value` | Value types |
-| `com.onixbyte.calendar.util` | Formatting utilities |
-
----
-
-## Calendar
-
-The top-level object representing an iCalendar (RFC 5545) VCALENDAR container.
-
-```java
-Calendar calendar = Calendar.builder()
- .withCalendarScale(...)
- .withMethod(...)
- .withProductIdentifier(...)
- .withVersion(...)
- .withOwner(...)
- .withPrimaryCalendar(...)
- .withPublishedTTL(...)
- .withCalendarDescription(...)
- .withCalendarName(...)
- .withCalendarId(...)
- .withCustomProperties(...)
- .withComponents(event, todo, ...)
- .build();
-
-String icsContent = calendar.formatted();
-```
-
-### Calendar Properties
-
-All calendar-level properties live in `com.onixbyte.calendar.property` and implement `CalendarProperty`.
-
-| Class | iCalendar Property | Description |
-| ------------------------ | -------------------- | ----------------------------------------- |
-| `CalendarScale` | `CALSCALE` | Calendar system (e.g., GREGORIAN) |
-| `Method` | `METHOD` | iCalendar method (e.g., PUBLISH, REQUEST) |
-| `ProductIdentifier` | `PRODID` | Product identifier of the calendar |
-| `Version` | `VERSION` | iCalendar version (e.g., 2.0) |
-| `Owner` | `X-OWNER` | Owner of the calendar |
-| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | Whether this is a primary calendar |
-| `PublishedTTL` | `X-PUBLISHED-TTL` | Time-to-live for published calendar |
-| `CalendarDescription` | `X-CALENDAR-DESC` | Calendar description |
-| `CalendarName` | `X-CALENDAR-NAME` | Calendar name |
-| `CalendarId` | `X-CALENDAR-ID` | Calendar identifier |
-| `CustomCalendarProperty` | `X-*` | Custom calendar properties |
-
-Custom properties are created using a builder:
-
-```java
-var customProp = CustomCalendarProperty.builder()
- .withParameters(...)
- .build("X-MY-PROPERTY", "my-value");
-```
-
-> Note: Custom property names **must** start with `X-`.
-
----
-
-## Components
-
-Components represent the core entities in an iCalendar object. Each component implements `CalendarComponent` and is rendered between `BEGIN:TYPE` and `END:TYPE` delimiters.
-
-### Event (VEVENT)
-
-Represents a scheduled event.
-
-```java
-Event event = Event.builder()
- .withDateTimeStamp(dtstamp) // required
- .withUniqueIdentifier(uid) // required
- .withDateTimeStart(dtstart)
- .withDateTimeEnd(dtend) // mutually exclusive with duration
- .withDuration(duration) // mutually exclusive with dtend
- .withSummary(summary)
- .withDescription(description)
- .withClassification(classification)
- .withDateTimeCreated(dateTimeCreated)
- .withGeographicPosition(geoPos)
- .withLastModified(lastModified)
- .withLocation(location)
- .withOrganiser(organiser)
- .withPriority(priority)
- .withSequenceNumber(seqNumber)
- .withStatus(status)
- .withTimeTransparency(transparency)
- .withUniformResourceLocator(url)
- .withRecurrenceId(recurrenceId)
- .withRecurrenceRule(rrule)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withExceptionDateTimes(exDates)
- .withRequestStatuses(statuses)
- .withRelated(related)
- .withResources(resources)
- .withRecurrenceDateTimes(rDates)
- .build();
-```
-
-### Todo (VTODO)
-
-Represents a to-do item or task.
-
-```java
-Todo todo = Todo.builder()
- .withDateTimeStamp(dtstamp) // required
- .withUniqueIdentifier(uid) // required
- .withSummary(summary)
- .withDateTimeStart(dtstart)
- .withDateTimeDue(due) // mutually exclusive with duration
- .withDuration(duration) // mutually exclusive with due
- .withDateTimeCompleted(completed)
- .withPercentComplete(percent)
- .withClassification(classification)
- .withDateTimeCreated(created)
- .withDescription(description)
- .withGeographicPosition(geoPos)
- .withLastModified(lastModified)
- .withLocation(location)
- .withOrganiser(organiser)
- .withPriority(priority)
- .withSequenceNumber(seq)
- .withStatus(status)
- .withRecurrenceId(recurId)
- .withRecurrenceRule(rrule)
- .withUniformResourceLocator(url)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withExceptionDateTimes(exDates)
- .withRequestStatuses(statuses)
- .withRelatedToList(related)
- .withResources(resources)
- .withRecurrenceDateTimes(rDates)
- .build();
-```
-
-### Journal (VJOURNAL)
-
-Represents a journal entry or diary note.
-
-```java
-Journal journal = Journal.builder()
- .withDateTimeStamp(dtstamp) // required
- .withUniqueIdentifier(uid) // required
- .withSummary(summary)
- .withClassification(classification)
- .withDateTimeCreated(created)
- .withDateTimeStart(dtstart)
- .withLastModified(lastModified)
- .withOrganiser(organiser)
- .withRecurrenceId(recurId)
- .withSequenceNumber(seq)
- .withStatus(status)
- .withUniformResourceLocator(url)
- .withRecurrenceRule(rrule)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withDescriptions(descriptions)
- .withExceptionDateTimes(exDates)
- .withRelatedToList(related)
- .withRecurrenceDate(rDates)
- .withRequestStatuses(statuses)
- .build();
-```
-
-### FreeBusy (VFREEBUSY)
-
-Represents free/busy time information.
-
-```java
-FreeBusy freeBusy = FreeBusy.builder()
- .withDateTimeStamp(dtstamp) // required
- .withUniqueIdentifier(uid) // required
- .withContact(contact)
- .withDateTimeStart(dtstart)
- .withDateTimeEnd(dtend)
- .withOrganiser(organiser)
- .withUniformResourceLocator(url)
- .withAttendees(attendees)
- .withComments(comments)
- .withFreeBusyTimes(freeBusyTimes)
- .withRequestStatuses(statuses)
- .build();
-```
-
-### TimeZone (VTIMEZONE)
-
-Defines time zone rules including standard and daylight saving time transitions.
-
-```java
-TimeZone timezone = TimeZone.builder()
- .withTimeZoneIdentifier(tzId)
- .withLastModified(lastModified)
- .withTimeZoneUrl(tzUrl)
- .withTimeZoneProperties(standardProp, daylightProp)
- .build();
-```
-
-Time zone properties define the actual transition rules:
-
-```java
-TimeZoneProperty standard = TimeZoneProperty.builder()
- .withDateTimeStart(dtstart)
- .withTimeZoneOffsetTo(offsetTo)
- .withTimeZoneOffsetFrom(offsetFrom)
- .withRecurrenceRule(rrule)
- .withTimeZoneNames(tzName)
- .buildStandard(); // or buildDaylight()
-
-TimeZoneProperty daylight = TimeZoneProperty.builder()
- .withDateTimeStart(dtstart)
- .withTimeZoneOffsetTo(offsetTo)
- .withTimeZoneOffsetFrom(offsetFrom)
- .buildDaylight();
-```
-
-### Alarm (VALARM)
-
-Defines alarm/reminder notifications. Three alarm types are supported:
-
-```java
-// Audio alarm
-Alarm audioAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .withAttachments(audioAttachment)
- .buildAudio();
-
-// Display alarm
-Alarm displayAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDescription(description) // required
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .buildDisplay();
-
-// Email alarm
-Alarm emailAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDescription(description) // required
- .withSummary(summary) // required
- .withAttendees(attendees) // required
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .buildEmail();
-```
-
----
-
-## Component Properties
-
-Component properties live in `com.onixbyte.calendar.component.property` and implement `ComponentProperty`.
-
-| Class | iCalendar Property | Description |
-| ------------------------- | ------------------ | -------------------------------------------------------- |
-| `Action` | `ACTION` | Alarm action type (AUDIO, DISPLAY, EMAIL) |
-| `Attachment` | `ATTACH` | Document attachment |
-| `Attendee` | `ATTENDEE` | Event/task attendee |
-| `Categories` | `CATEGORIES` | Categories or tags |
-| `Classification` | `CLASS` | Access classification (PUBLIC, PRIVATE, CONFIDENTIAL) |
-| `Comment` | `COMMENT` | Comment |
-| `Contact` | `CONTACT` | Contact information |
-| `DateTimeCompleted` | `COMPLETED` | Completion date-time |
-| `DateTimeCreated` | `CREATED` | Creation date-time |
-| `DateTimeDue` | `DUE` | Due date-time |
-| `DateTimeEnd` | `DTEND` | End date-time |
-| `DateTimeStamp` | `DTSTAMP` | Date-time stamp |
-| `DateTimeStart` | `DTSTART` | Start date-time |
-| `Description` | `DESCRIPTION` | Description |
-| `ExceptionDateTimes` | `EXDATE` | Exception date-times |
-| `FreeBusyTime` | `FREEBUSY` | Free/busy time periods |
-| `GeographicPosition` | `GEO` | Geographic position (lat/long) |
-| `LastModified` | `LAST-MODIFIED` | Last modified date-time |
-| `Location` | `LOCATION` | Location |
-| `Organiser` | `ORGANIZER` | Event organiser |
-| `PercentComplete` | `PERCENT-COMPLETE` | Completion percentage |
-| `Priority` | `PRIORITY` | Priority level |
-| `RecurrenceDateTimes` | `RDATE` | Recurrence date-times |
-| `RecurrenceId` | `RECURRENCE-ID` | Recurrence instance identifier |
-| `RecurrenceRule` | `RRULE` | Recurrence rule |
-| `RelatedTo` | `RELATED-TO` | Related component reference |
-| `RepeatCount` | `REPEAT` | Alarm repeat count |
-| `RequestStatus` | `REQUEST-STATUS` | Request status |
-| `Resources` | `RESOURCES` | Resources |
-| `SequenceNumber` | `SEQUENCE` | Sequence number (revision) |
-| `Status` | `STATUS` | Component status (TENTATIVE, CONFIRMED, CANCELLED, etc.) |
-| `Summary` | `SUMMARY` | Title or summary |
-| `TimeTransparency` | `TRANSP` | Time transparency (OPAQUE, TRANSPARENT) |
-| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
-| `TimeZoneName` | `TZNAME` | Time zone name |
-| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | Time zone offset from UTC |
-| `TimeZoneOffsetTo` | `TZOFFSETTO` | Time zone offset to UTC |
-| `TimeZoneUrl` | `TZURL` | Time zone URL |
-| `Trigger` | `TRIGGER` | Alarm trigger |
-| `UniformResourceLocator` | `URL` | Associated URL |
-| `UniqueIdentifier` | `UID` | Unique identifier |
-| `CustomComponentProperty` | `X-*` | Custom component properties |
-
----
-
-## Parameters
-
-Parameters in `com.onixbyte.calendar.parameter` provide additional qualifiers on component properties.
-
-| Class | iCalendar Parameter | Description |
-| ----------------------------- | ------------------- | ------------------------------------------------------ |
-| `AlarmTriggerRelationship` | `RELATED` | Trigger relationship (START, END) |
-| `AlternateTextRepresentation` | `ALTREP` | Alternate text URI |
-| `CalendarUserType` | `CUTYPE` | Calendar user type (INDIVIDUAL, GROUP, RESOURCE, etc.) |
-| `CommonName` | `CN` | Common name |
-| `Delegatees` | `DELEGATED-TO` | Delegatees |
-| `Delegators` | `DELEGATED-FROM` | Delegators |
-| `DirectoryEntryReference` | `DIR` | Directory entry URI |
-| `FormatType` | `FMTTYPE` | Format type (MIME type) |
-| `FreeBusyTimeType` | `FBTYPE` | Free/busy time type |
-| `InlineEncoding` | `ENCODING` | Inline encoding (BASE64) |
-| `Language` | `LANGUAGE` | Language |
-| `Membership` | `MEMBER` | Group membership |
-| `ParticipationRole` | `ROLE` | Participation role (CHAIR, REQ-PARTICIPANT, etc.) |
-| `ParticipationStatus` | `PARTSTAT` | Participation status (ACCEPTED, DECLINED, etc.) |
-| `RecurrenceIdentifierRange` | `RANGE` | Recurrence range (THISANDPRIOR, THISANDFUTURE) |
-| `RelationshipType` | `RELTYPE` | Relationship type (PARENT, CHILD, SIBLING) |
-| `RsvpExpectation` | `RSVP` | RSVP expectation (TRUE, FALSE) |
-| `SentBy` | `SENT-BY` | Sent by |
-| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
-| `ValueDataType` | `VALUE` | Value data type (DATE, DATE-TIME, etc.) |
-
----
-
-## Recurrence Types
-
-Located in `com.onixbyte.calendar.recurrence`.
-
-| Class | Description |
-| ------------ | ------------------------------------------------------------------------- |
-| `Frequency` | Frequency constants (DAILY, WEEKLY, MONTHLY, YEARLY) for recurrence rules |
-| `WeekdayNum` | Weekday number for recurrence rules (e.g., 2nd Monday) |
-
----
-
-## Value Types
-
-Located in `com.onixbyte.calendar.value`.
-
-| Class | Description |
-| ------------------- | ---------------------------------------------- |
-| `FreeBusyTimeValue` | Represents free/busy time value |
-| `PeriodOfTime` | Represents a period of time with start and end |
-| `PropertyValue` | Base value type for properties |
-| `UtcOffset` | UTC offset value (e.g., `-05:00`, `+01:00`) |
-
----
-
-## Formatted Output
-
-All components and properties provide a `formatted()` method that returns an iCalendar-compliant string representation. The `Calendar.formatted()` method produces a complete `.ics` output wrapped in `BEGIN:VCALENDAR`/`END:VCALENDAR`.
-
-```java
-String ics = calendar.formatted();
-// BEGIN:VCALENDAR
-// CALSCALE:GREGORIAN
-// METHOD:PUBLISH
-// ...
-// END:VCALENDAR
-```
diff --git a/docs/en-gb/opensource-projects/calendar-toolbox/index.mdx b/docs/en-gb/opensource-projects/calendar-toolbox/index.mdx
deleted file mode 100644
index e8b0e62..0000000
--- a/docs/en-gb/opensource-projects/calendar-toolbox/index.mdx
+++ /dev/null
@@ -1,100 +0,0 @@
----
-title: Calendar Toolbox
----
-
-import { Tabs, Tab } from "@rspress/core/theme"
-
-## Introduction
-
-Calendar Toolbox is a Java library designed to simplify the creation of `.ics` files, adhering to the iCalendar specification (RFC 5545). This library provides developers with a straightforward API to generate calendar events that can be imported into popular calendar applications such as Microsoft Outlook, Google Calendar, and Apple Calendar.
-
-With Calendar Toolbox, you can effortlessly create, customise, and export calendar event files programmatically, enabling integration of calendar functionalities into your Java applications with minimal effort.
-
-## Features
-
-- **Full RFC 5545 Compliance** — Supports standard iCalendar components including VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, and VALARM.
-- **Fluent Builder Pattern** — All components and properties use builder pattern for readable and intuitive construction.
-- **Type-Safe Properties** — Strongly typed properties and parameters ensure correctness at compile time.
-- **Custom Extensions** — Support for custom `X-` properties at both calendar and component level.
-- **Lightweight** — Zero external dependencies for core functionality.
-
-## Installation
-
-
(抱歉回复晚了) | **Thanks for your patience**
(感谢你的耐心等待) | 前者在道歉,后者在感谢——从「我做错了」转变为「你太好了」,既表达了歉意又让对方感到被尊重 |
-| 约时间 | **What works best for you?**
(你什么时候方便?) | **Could you do …?**
(你可以在某某时间吗?) | 前者把决定权完全推给对方,后者主动给出选项,减少来回沟通的成本 |
-| 帮助了别人之后 | **No problem / No worries**
(没问题 / 别担心) | **Always happy to help**
(乐于效劳) | 前者暗示这件事"本来可能是个问题",后者传递出你乐在其中、下次还愿意帮 |
-| 提出建议 | **I think maybe we should …**
(我觉得也许我们应该……) | **It'd be best if we …**
(最好是……) | 前者透着犹豫和不自信,后者直接给出判断——像有经验的人在做决策 |
-| 文字沟通费劲 | **_花 30 分钟反复修改一封邮件_** | **It'd be easier to discuss in person**
(当面/电话聊会更轻松) | 意识到沟通渠道本身就是问题,果断切换方式反而是效率最高的选择 |
-| 确认对方是否理解 | **Hopefully that makes sense?**
(希望我说清楚了?) | **Let me know if you have questions**
(有问题随时问我) | 前者在怀疑自己的表达能力,后者把责任合理地分担给对方,姿态更稳 |
-| 催进度 | **Just wanted to check in**
(只是想确认一下) | **When can I expect an update?**
(我什么时候可以收到更新?) | 前者显得小心翼翼不敢打扰,后者直接问时间节点——清楚、礼貌、专业 |
-| 犯了小错 | **Ahh sorry my bad totally missed that**
(啊啊抱歉我的错,完全漏掉了) | **Thanks for letting me know**
(感谢提醒) | 前者过度道歉反而让对方尴尬,后者承认了问题但把焦点放在了"解决"上 |
-| 需要早退 | **Could I possibly leave early?**
(我能提前走吗?) | **I will need to leave at …**
(我需要在某某时间离开) | 前者在请求批准,后者在陈述安排——你是专业人士,不需要为合理需求道歉 |
-
-## 核心原则
-
-写好邮件的关键不在于词汇量,而在于**姿态**。时刻提醒自己三条规则:
-
-1. **用陈述代替请求** —— 「我需要……」比「我能不能……」更有分量
-2. **用感谢代替道歉** —— 把焦点从「我的过失」转移到「对方的支持」
-3. **用明确代替模糊** —— 给出具体的时间、选项、行动项,而不是把球踢回给对方
-
-下次打开邮箱,花 5 秒想一想:这句话能不能说得更像一个做决定的人?
diff --git a/docs/zh-hans/blogs/fix-idea-application-yaml-schema-validation.mdx b/docs/zh-hans/blogs/fix-idea-application-yaml-schema-validation.mdx
deleted file mode 100644
index 87c35de..0000000
--- a/docs/zh-hans/blogs/fix-idea-application-yaml-schema-validation.mdx
+++ /dev/null
@@ -1,58 +0,0 @@
----
-title: 修复 IntelliJ IDEA 中 Spring Boot 的 application.yaml 智能提示消失问题
-tags:
- - intellij-idea
- - spring-boot
- - yaml
- - schema-validation
- - troubleshooting
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-import { Kbd } from "@rspress/core/theme"
-
-最近在使用 IDEA 开发 Spring Boot 项目时,我发现 `application.yaml` 和 `application.yml` 的智能代码提示突然消失了。更糟糕的是,编辑器中充满了如下警告:
-
-> `Schema validation: Missing required property 'kind' = 'Application'`
-
-## 症状
-
-打开 `src/main/resources/` 下的 `application.yaml` 或 `application.yml` 文件时,IDEA 会将其视为 Enonic XP 应用描述文件,而非 Spring Boot 配置文件。所有 Spring 特有的属性提示全部消失,取而代之的是一堆要求填写 `kind` 属性的 Schema 校验错误——这个字段与 Spring Boot 毫无关系。
-
-重启 IDEA、清除缓存、重新导入项目都无济于事,问题依旧存在。
-
-## 快速修复
-
-经过一番排查,我找到了罪魁祸首。IDEA 会从远程源(具体来说是 [SchemaStore](https://www.schemastore.org/) 目录)下载 JSON Schema,并用它们来校验配置文件。最近的一次 Schema 更新引入了一个匹配范围过大的 `fileMatch` 模式。
-
-要立即禁用此行为:
-
-1. 打开 **Settings**(Windows:Ctrl+Alt+S / macOS: + ,)
-2. 导航至 **Languages & Frameworks → Schemas and DTDs → Remote JSON Schemas**
-3. 取消勾选 **Allow downloading JSON Schemas from remote sources**
-4. 点击 **OK**
-
-Spring Boot 的配置提示会立刻恢复。
-
-## 根本原因
-
-事情的根源要追溯到 **2026 年 5 月 19 日**,一位来自 [Enonic](https://www.enonic.com/) 的开发者向 SchemaStore 仓库提交了一个 PR([PR #5704](https://github.com/SchemaStore/schemastore/pull/5704)),添加了 Enonic XP 应用描述文件的 Schema。该 Schema 的 `fileMatch` 属性被设置为:
-
-```json
-"fileMatch": [
- "**/src/main/resources/application.yaml",
- "**/src/main/resources/application.yml"
-]
-```
-
-这个匹配模式过于宽泛——它匹配了 **所有** 位于 `src/main/resources/` 下的 `application.yaml` 和 `application.yml` 文件,而这正是 Spring Boot 项目存放配置文件的位置。一旦该 Schema 被合并到 SchemaStore 中,任何启用了远程 JSON Schema 下载功能的 IntelliJ IDEA 都会拉取它,并开始用 Enonic XP 的 Schema 来校验 Spring Boot 的配置。
-
-该开发者已意识到问题,并提交了后续修复 PR([PR #5711](https://github.com/SchemaStore/schemastore/pull/5711))来收紧 `fileMatch` 匹配规则。截至本文撰写时,该修复尚未被 SchemaStore 合并。
-
-## 为什么这很重要
-
-SchemaStore 是一个由社区维护的 JSON Schema 目录,被许多编辑器(VS Code、IntelliJ IDEA、Neovim 等)用来为常见配置文件提供校验和自动补全功能。当该目录中的某个 Schema 声明了过于宽泛的匹配规则时,会影响到所有平台、所有编辑器的用户——不仅仅是 IDEA。
-
-对于 Spring Boot 开发者来说,结论很简单:如果你的 `application.yaml` 提示一夜之间消失了,先检查一下你的 IDE 认为该文件属于哪个 Schema,它可能根本不是 Spring Boot。
diff --git a/docs/zh-hans/blogs/fix-macos-monterey-sleep-wake.md b/docs/zh-hans/blogs/fix-macos-monterey-sleep-wake.md
deleted file mode 100644
index ecdbc4a..0000000
--- a/docs/zh-hans/blogs/fix-macos-monterey-sleep-wake.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: 解决 macOS Monterey+ 设备休眠频繁自动唤醒的问题
-tags:
- - macos
- - sleep
- - power-management
- - bug
----
-
-> 本文由 **落格博客** 原创撰写:[落格博客](https://www.logcg.com/) » [升级 macOS Monterey 后设备休眠半夜频繁唤醒问题](https://www.logcg.com/archives/3528.html)
-
-更新到了 macOS Monterey,半夜总会被屏幕照醒,就觉得很诡异,以前也有过,但都是有通知的时候才会点亮屏幕,现在是没有任何理由的自己点亮,硬件还是那个硬件,那就应该是软件的锅了。
-
-在网上查了一圈,先是找到了[苹果官方的教程](https://support.apple.com/zh-cn/guide/mac-help/mchlp2995/mac)。写的很详细,但显然是没有任何用处的。
-
-于是继续深挖,还真找到了原因,使用命令 **`pmset -g log | grep DarkWake`** 就可以看到,在你睡觉的过程中,你的 Mac 并没有歇着……
-
-看看输出,这几个比较典型,大部分都是这样的,一个 DarkWake, 一个 Wake, 两个仅仅相连,那么问题就出来了, DarkWake 是给电脑在后台唤醒来更新数据的,但不知怎么的,外设被触发,从而导致了全局唤醒。
-
-总之,我并不想要这个功能, 就那个 PowerNap,对我来说,我更希望它能给我多省点电,于是大概解决思路就这么多:关掉网络访问唤醒,关掉 PowerNap……不过问题来了,在 m1 设备上,其实是没有 PowerNap 选项的……(显然,苹果对自己的续航很有信心,但他们忽略了Bug的威力)
-
-于是对于 PowerNap 这个功能来说,我们只能从命令行下手,首先使用 **`pmset -g`** 命令查看当前状态,找到 **`powernap`** 的值,如果不是 0 ,说明是启用的状态,使用命令 **`sudo pmset -a powernap 0`** 关掉它。
-
-同时,还有另外一个 **`tcpkeepalive`** ,这个默认应该也不是 0 ,也要关掉,它决定了你的 rmbp 在休眠时是否要保持 tcp 连接。 **`sudo pmset -a tcpkeepalive 0`** ,执行这条命令会导致终端提示:**_Warning: This option disables TCP Keep Alive mechanism when system is sleeping. This will result in some critical features like 'Find My Mac' not to function properly._**
-
-大概是说关了的话某些功能会受到限制,其实就是系统功能不能休眠时联网了,我相信真有人偷了你 Mac,它也连不上网的。
diff --git a/docs/zh-hans/blogs/font-size-conversion-table.md b/docs/zh-hans/blogs/font-size-conversion-table.md
deleted file mode 100644
index dafe569..0000000
--- a/docs/zh-hans/blogs/font-size-conversion-table.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: 字号榜值转换表
-tags:
- - typography
- - font
- - cheatsheet
- - design
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-| 中文字号 | 英文字号(磅)/pt | 毫米/mm | 像素/px |
-| -------- | ----------------- | ------- | ------- |
-| 初号 | 42 | 14.82 | 56 |
-| 小初 | 36 | 12.7 | 48 |
-| 一号 | 26 | 9.17 | 34.7 |
-| 小一 | 24 | 8.47 | 32 |
-| 二号 | 22 | 7.76 | 29.3 |
-| 小二 | 18 | 6.35 | 24 |
-| 三号 | 16 | 5.64 | 21.3 |
-| 小三 | 15 | 5.29 | 20 |
-| 四号 | 14 | 4.94 | 18.7 |
-| 小四 | 12 | 4.23 | 16 |
-| 五号 | 10.5 | 3.7 | 14 |
-| 小五 | 9 | 3.18 | 12 |
-| 六号 | 7.5 | 2.56 | 10 |
-| 小六 | 6.5 | 2.29 | 8.7 |
-| 七号 | 5.5 | 1.94 | 7.3 |
-| 八号 | 5 | 1.76 | 6.7 |
diff --git a/docs/zh-hans/blogs/frontend-development-standards.md b/docs/zh-hans/blogs/frontend-development-standards.md
deleted file mode 100644
index 1c682c7..0000000
--- a/docs/zh-hans/blogs/frontend-development-standards.md
+++ /dev/null
@@ -1,42 +0,0 @@
----
-title: 前端开发规范
-tags:
- - frontend
- - react
- - standards
- - best-practice
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-## 依赖管理 (pnpm)
-
-- **严格性**: 利用 pnpm 的严格依赖管理,以确保更确定性的 `node_modules` 结构和高效的磁盘空间使用。
-- **工作区**: 如果使用 monorepo 方法,配置 pnpm 工作区以简化多个前端包的依赖管理。
-- **审计**: 定期使用 `pnpm audit` 审计前端依赖项是否存在已知漏洞。
-
-## API 通信 (Axios)
-
-- **Axios 实例**: 创建一个集中的 Axios 实例用于 API 调用,以应用通用配置(基本 URL、请求头、拦截器)。
-- **拦截器**: 使用 Axios 拦截器进行以下操作:
- - 向传出请求添加认证令牌。
- - 处理全局错误响应(例如,显示 `401 Unauthorized` 的通知)。
- - 在开发环境中记录请求/响应。
-- **错误处理**: 在 Axios 拦截器或自定义工具函数中集中处理 API 错误,以提供一致的用户反馈。
-
-## React 与组件标准
-
-- **函数组件与 Hooks**: 对于新开发,优先使用带有 React Hooks 的函数组件,而非类组件。
-- **Props**:
- - 为组件 props 定义 `interface` 或 `type` 以确保类型安全。
- - 在组件入口处解构 props 以提高清晰度。
-- **状态管理 (Redux)**:
- - 使用 Redux Toolkit 进行高效且减少样板代码的 Redux 开发。
- - 使用 `createSlice` 将 Redux 逻辑组织成"切片"(特定功能的 reducer、action 和 selector)。
- - 遵循"ducks"模式或"slices"方法来协同定位 Redux 逻辑。
-- **组件组合**: 将复杂的 UI 分解为更小、可重用且职责单一的组件。
-- **Ant Design**:
- - 利用 Ant Design 组件以实现一致的 UI/UX。
- - 如果需要,使用 CSS-in-JS 解决方案在整个应用程序中一致地定制 Ant Design 主题和样式。
-- **可访问性**: 从一开始就设计和实现考虑到 Web 可访问性 (a11y) 的组件。
diff --git a/docs/zh-hans/blogs/frontend-tips-and-solutions.md b/docs/zh-hans/blogs/frontend-tips-and-solutions.md
deleted file mode 100644
index 23bdc61..0000000
--- a/docs/zh-hans/blogs/frontend-tips-and-solutions.md
+++ /dev/null
@@ -1,75 +0,0 @@
----
-title: 前端开发技巧与方案速查手册
-tags:
- - frontend
- - react
- - ant-design
- - tailwind
- - best-practice
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-## 表单组件的解耦
-
-将表单组件拆分为 UI 组件和逻辑组件,并在逻辑组件中使用 UI 组件渲染样式。
-
-## React 入口组件顺序
-
-```tsx
-import { StrictMode } from "react"
-import { createRoot } from "react-dom/client"
-import { Provider as ReduxProvider } from "react-redux"
-import { PersistGate } from "redux-persist/integration/react"
-import { RouterProvider } from "react-router"
-import { App as AntApp, ConfigProvider as AntConfigProvider } from "antd"
-import { StyleProvider } from "@ant-design/cssinjs"
-import AntSimplifiedChinese from "antd/locale/zh_CN"
-import "./index.css"
-import "@/config/dayjs-config"
-import store, { persistor } from "@/store"
-import router from "@/router"
-
-createRoot(document.getElementById("root")!).render(
-
-```
-
-始终传入 `d` 参数以避免未设置 Gravatar 的用户出现裂图。`identicon` 和 `robohash` 是常用的选择,因为它们能为每个哈希值生成唯一且易于辨识的图片。
diff --git a/docs/zh-hans/blogs/version-control-and-code-review.md b/docs/zh-hans/blogs/version-control-and-code-review.md
deleted file mode 100644
index 83a6e76..0000000
--- a/docs/zh-hans/blogs/version-control-and-code-review.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: 版本控制与代码审查
-tags:
- - git
- - code-review
- - best-practice
- - workflow
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-## GitFlow 工作流
-
-版本控制将使用 GitFlow 分支模型,包括 `main`、`develop`、`feature`、`release` 和 `hotfix` 分支。
-
-- `main`: 生产就绪代码。只有 `release` 和 `hotfix` 分支会合并到 `main`。
-- `develop`: 即将开发的功能集成分支。
-- `feature/*`: 用于新功能的分支,从 `develop` 分支出来。
-- `release/*`: 用于准备新生产版本的分支,从 `develop` 分支出来。
-- `hotfix/*`: 用于紧急生产错误修复的分支,从 `main` 分支出来。
-
-## 拉取请求 (PRs)
-
-所有代码更改(直接推送到功能分支除外)都必须通过拉取请求提交。
-
-## 代码审查
-
-- 每个拉取请求必须由至少一名其他开发人员进行审查。
-- 审查者负责检查是否符合本代码标准、代码质量、逻辑正确性和测试覆盖率。
-- 在创建 PR 之前,应在本地运行 IntelliJ IDEA 的集成代码分析工具。
-
-## 提交消息
-
-编写清晰、简洁、描述性的提交消息,解释更改了什么以及为什么进行更改。如果可能,遵循约定式提交格式(例如,
-`feat: add user registration endpoint`)。
diff --git a/docs/zh-hans/blogs/windows-driver-backup-restore.mdx b/docs/zh-hans/blogs/windows-driver-backup-restore.mdx
deleted file mode 100644
index d582c2e..0000000
--- a/docs/zh-hans/blogs/windows-driver-backup-restore.mdx
+++ /dev/null
@@ -1,85 +0,0 @@
----
-title: 通过备份驱动的方式重装系统后一键恢复驱动
-tags:
- - windows
- - driver
- - backup
- - system-reinstall
- - dism
-author:
- name: Zihlu Wang
- email: real@zihluwang.me
----
-
-import { Kbd } from "@rspress/core/theme"
-
-重装 Windows 系统后,最让人头疼的环节之一就是安装驱动程序——显卡、网卡、声卡、蓝牙、触摸板……缺少任何一个都会影响正常使用。Windows Update 能自动拉取一部分,但往往版本老旧或根本找不到某些小众硬件的驱动。
-
-好在 Windows 内置的 DISM 工具提供了驱动导出和恢复功能,只需在重装前花一分钟备份,重装后就能一键恢复所有驱动。
-
-## 重装前:备份所有驱动
-
-以**管理员身份**打开终端(PowerShell 或命令提示符均可),执行以下命令:
-
-```powershell
-dism /online /export-driver /destination:D:\DriverBackup
-```
-
-将 `D:\DriverBackup` 替换为你的备份目标路径。建议放到外置硬盘、U 盘或非系统盘,确保重装时不会被格式化。
-
-命令执行后会遍历系统中所有已安装的第三方驱动,逐个导出到目标目录。整个过程通常在一分钟左右完成。导出完成后,你会看到类似如下的输出:
-
-```
-The operation completed successfully.
-```
-
-将该备份目录妥善保存即可进行系统重装。
-
-### 备份了什么?
-
-该命令导出的是**第三方驱动程序**(即非 Windows 内置驱动),包括显卡、声卡、网卡、芯片组、蓝牙、读卡器等所有你在系统使用过程中安装过的驱动。Windows 自带的通用驱动不会被导出,这部分系统重装后会自动回归。
-
-## 重装后:一键恢复所有驱动
-
-### 方法一:命令行一键恢复(推荐)
-
-这是最省心的方式。同样以**管理员身份**打开终端,执行:
-
-```powershell
-dism /online /add-driver /driver:D:\DriverBackup /recurse
-```
-
-`/recurse` 参数会递归搜索备份目录下的所有子文件夹,将每一个驱动都安装到新系统中。执行完成后**必须重启电脑**使其生效。
-
-### 方法二:通过设备管理器逐个安装
-
-如果你更偏好图形界面,或者只需要恢复特定驱动:
-
-1. 按 Win + X,选择**设备管理器**
-2. 找到带有黄色感叹号的设备(即缺失驱动的设备)
-3. 右键点击该设备,选择**更新驱动程序**
-4. 选择**浏览我的电脑以查找驱动程序**
-5. 将路径指向你的驱动备份目录,勾选**包括子文件夹**
-6. 点击下一步,系统会自动搜索并安装匹配的驱动
-
-重复以上步骤直到所有设备都恢复正常。
-
-## 常见问题
-
-### 显示 "The driver package could not be installed"
-
-少数情况下,某些驱动可能因为签名问题或版本不兼容而无法通过 DISM 安装。这时可以尝试手动安装:在备份目录中找到对应的 `.inf` 文件,右键选择**安装**。
-
-### 恢复后仍有设备缺失驱动
-
-DISM 备份的仅是当前系统上已安装的驱动。如果重装前就有设备未被正确驱动,这些设备的驱动自然不会存在于备份中。建议在备份前先用设备管理器确认所有设备都已正常工作。
-
-### 能否跨 Windows 版本恢复?
-
-同一台电脑从 Windows 10 升级到 Windows 11 的驱动恢复通常是可行的,但不建议在不同硬件配置的电脑间迁移驱动备份。每台机器的驱动应独立备份。
-
-## 小结
-
-这套流程的核心优势在于**零第三方工具依赖**——DISM 是 Windows 内建组件,无需安装任何额外软件。重装前花一分钟导出,重装后一条命令恢复,比手动逐个下载安装驱动高效得多。养成重装前先备份驱动的习惯,能让每次系统迁移都轻松不少。
-
-> 本文内容参考自抖音用户 [@科技碎碎念](https://v.douyin.com/Cbf0ruVdbUM/) 的视频教程。
diff --git a/docs/zh-hans/notifications/index.md b/docs/zh-hans/notifications/index.md
deleted file mode 100644
index d318429..0000000
--- a/docs/zh-hans/notifications/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: 企业动态
----
-
-## Microsoft 邮件投递问题(@outlook、@hotmail、@live、@msn 以及托管在 Microsoft 的自定义域名邮箱)
-
-> 更新于 _2026 年 5 月 19 日_
-
-**使用 Microsoft 托管邮箱的用户需立即采取行动。**
-
-特此通知,我们的自动邮件服务目前向所有由 Microsoft 托管的邮箱地址投递时遇到严重问题。由于 Microsoft Exchange Online Protection (EOP) 近期采取了激进的过滤策略,我们的邮件投递服务器已被 Microsoft 屏蔽。因此,我们的系统**无法向以下邮箱地址发送任何通知、密码重置或激活邮件**:**@outlook.com**、**@hotmail.com**、**@live.com**、**@msn.com**,以及**任何由 Microsoft 托管自定义域名的邮箱**。
-
-为确保服务不受影响,请根据您的账户状态参考以下指引:
-
-- **新用户(注册前)**:请**不要**使用 Microsoft 托管的邮箱地址注册账户。您将无法收到必要的激活链接。请使用其他邮件服务商,例如您的企业邮箱、QQ 邮箱或网易 163 邮箱完成注册。
-- **已注册用户**:如果您的账户当前绑定了 Outlook 或 Hotmail 邮箱地址,请立即登录并更新您的主邮箱。您可以通过 **[用户设置 -> 偏好设置 -> 邮箱](https://github.com/settings/emails)** 页面进行更改。未能及时更新将导致您无法收到重要的仓库更新、CI/CD 流水线失败日志以及合并请求通知。
-
-我们正在积极与 Microsoft Postmaster Centre 沟通,以申请解除此屏蔽。对于由此带来的任何不便,我们深表歉意,并感谢您及时配合更新联系信息。
diff --git a/docs/zh-hans/opensource-projects/_meta.json b/docs/zh-hans/opensource-projects/_meta.json
deleted file mode 100644
index ac3637c..0000000
--- a/docs/zh-hans/opensource-projects/_meta.json
+++ /dev/null
@@ -1,14 +0,0 @@
-[
- "index",
- { "type": "section-header", "label": "opensource.group.libraries" },
- { "type": "dir", "name": "onixbyte-toolbox" },
- { "type": "dir", "name": "regions4j" },
- { "type": "dir", "name": "captcha" },
- { "type": "dir", "name": "calendar-toolbox" },
- { "type": "section-header", "label": "opensource.group.applications" },
- { "type": "dir", "name": "helix" },
- { "type": "dir", "name": "delta-force-guide" },
- { "type": "section-header", "label": "opensource.group.tools" },
- { "type": "dir", "name": "claude-code-skill-manager" },
- { "type": "dir", "name": "vite-plugins" }
-]
diff --git a/docs/zh-hans/opensource-projects/calendar-toolbox/api.md b/docs/zh-hans/opensource-projects/calendar-toolbox/api.md
deleted file mode 100644
index f1210c0..0000000
--- a/docs/zh-hans/opensource-projects/calendar-toolbox/api.md
+++ /dev/null
@@ -1,390 +0,0 @@
----
-title: Calendar Toolbox API
----
-
-## 包结构概览
-
-库的代码组织在基础包 `com.onixbyte.calendar` 下,结构如下:
-
-| 包 | 描述 |
-| ------------------------------------------ | ---------------------------------- |
-| `com.onixbyte.calendar` | 根日历对象 |
-| `com.onixbyte.calendar.component` | iCalendar 组件(VEVENT、VTODO 等) |
-| `com.onixbyte.calendar.component.property` | 组件级属性 |
-| `com.onixbyte.calendar.property` | 日历级属性 |
-| `com.onixbyte.calendar.parameter` | iCalendar 属性参数 |
-| `com.onixbyte.calendar.recurrence` | 重复规则类型 |
-| `com.onixbyte.calendar.value` | 值类型 |
-| `com.onixbyte.calendar.util` | 格式化工具类 |
-
----
-
-## Calendar
-
-表示 iCalendar(RFC 5545)VCALENDAR 容器的顶层对象。
-
-```java
-Calendar calendar = Calendar.builder()
- .withCalendarScale(...)
- .withMethod(...)
- .withProductIdentifier(...)
- .withVersion(...)
- .withOwner(...)
- .withPrimaryCalendar(...)
- .withPublishedTTL(...)
- .withCalendarDescription(...)
- .withCalendarName(...)
- .withCalendarId(...)
- .withCustomProperties(...)
- .withComponents(event, todo, ...)
- .build();
-
-String icsContent = calendar.formatted();
-```
-
-### 日历属性
-
-所有日历级属性位于 `com.onixbyte.calendar.property`,实现 `CalendarProperty` 接口。
-
-| 类 | iCalendar 属性 | 描述 |
-| ------------------------ | -------------------- | --------------------------------------- |
-| `CalendarScale` | `CALSCALE` | 日历系统(例如 GREGORIAN) |
-| `Method` | `METHOD` | iCalendar 方法(例如 PUBLISH、REQUEST) |
-| `ProductIdentifier` | `PRODID` | 日历的产品标识符 |
-| `Version` | `VERSION` | iCalendar 版本(例如 2.0) |
-| `Owner` | `X-OWNER` | 日历所有者 |
-| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | 是否为主日历 |
-| `PublishedTTL` | `X-PUBLISHED-TTL` | 已发布日历的生存时间 |
-| `CalendarDescription` | `X-CALENDAR-DESC` | 日历描述 |
-| `CalendarName` | `X-CALENDAR-NAME` | 日历名称 |
-| `CalendarId` | `X-CALENDAR-ID` | 日历标识符 |
-| `CustomCalendarProperty` | `X-*` | 自定义日历属性 |
-
-自定义属性使用 Builder 创建:
-
-```java
-var customProp = CustomCalendarProperty.builder()
- .withParameters(...)
- .build("X-MY-PROPERTY", "my-value");
-```
-
-> 注意:自定义属性名称**必须**以 `X-` 开头。
-
----
-
-## 组件
-
-组件是 iCalendar 对象的核心实体。每个组件实现 `CalendarComponent` 接口,并在 `BEGIN:TYPE` 和 `END:TYPE` 定界符之间渲染。
-
-### Event(VEVENT)
-
-表示一个预定的活动/事件。
-
-```java
-Event event = Event.builder()
- .withDateTimeStamp(dtstamp) // 必需
- .withUniqueIdentifier(uid) // 必需
- .withDateTimeStart(dtstart)
- .withDateTimeEnd(dtend) // 与 duration 互斥
- .withDuration(duration) // 与 dtend 互斥
- .withSummary(summary)
- .withDescription(description)
- .withClassification(classification)
- .withDateTimeCreated(dateTimeCreated)
- .withGeographicPosition(geoPos)
- .withLastModified(lastModified)
- .withLocation(location)
- .withOrganiser(organiser)
- .withPriority(priority)
- .withSequenceNumber(seqNumber)
- .withStatus(status)
- .withTimeTransparency(transparency)
- .withUniformResourceLocator(url)
- .withRecurrenceId(recurrenceId)
- .withRecurrenceRule(rrule)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withExceptionDateTimes(exDates)
- .withRequestStatuses(statuses)
- .withRelated(related)
- .withResources(resources)
- .withRecurrenceDateTimes(rDates)
- .build();
-```
-
-### Todo(VTODO)
-
-表示待办事项或任务。
-
-```java
-Todo todo = Todo.builder()
- .withDateTimeStamp(dtstamp) // 必需
- .withUniqueIdentifier(uid) // 必需
- .withSummary(summary)
- .withDateTimeStart(dtstart)
- .withDateTimeDue(due) // 与 duration 互斥
- .withDuration(duration) // 与 due 互斥
- .withDateTimeCompleted(completed)
- .withPercentComplete(percent)
- .withClassification(classification)
- .withDateTimeCreated(created)
- .withDescription(description)
- .withGeographicPosition(geoPos)
- .withLastModified(lastModified)
- .withLocation(location)
- .withOrganiser(organiser)
- .withPriority(priority)
- .withSequenceNumber(seq)
- .withStatus(status)
- .withRecurrenceId(recurId)
- .withRecurrenceRule(rrule)
- .withUniformResourceLocator(url)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withExceptionDateTimes(exDates)
- .withRequestStatuses(statuses)
- .withRelatedToList(related)
- .withResources(resources)
- .withRecurrenceDateTimes(rDates)
- .build();
-```
-
-### Journal(VJOURNAL)
-
-表示日记条目或笔记。
-
-```java
-Journal journal = Journal.builder()
- .withDateTimeStamp(dtstamp) // 必需
- .withUniqueIdentifier(uid) // 必需
- .withSummary(summary)
- .withClassification(classification)
- .withDateTimeCreated(created)
- .withDateTimeStart(dtstart)
- .withLastModified(lastModified)
- .withOrganiser(organiser)
- .withRecurrenceId(recurId)
- .withSequenceNumber(seq)
- .withStatus(status)
- .withUniformResourceLocator(url)
- .withRecurrenceRule(rrule)
- .withAttachments(attachments)
- .withAttendees(attendees)
- .withCategories(categories)
- .withComments(comments)
- .withContacts(contacts)
- .withDescriptions(descriptions)
- .withExceptionDateTimes(exDates)
- .withRelatedToList(related)
- .withRecurrenceDate(rDates)
- .withRequestStatuses(statuses)
- .build();
-```
-
-### FreeBusy(VFREEBUSY)
-
-表示空闲/忙碌时间信息。
-
-```java
-FreeBusy freeBusy = FreeBusy.builder()
- .withDateTimeStamp(dtstamp) // 必需
- .withUniqueIdentifier(uid) // 必需
- .withContact(contact)
- .withDateTimeStart(dtstart)
- .withDateTimeEnd(dtend)
- .withOrganiser(organiser)
- .withUniformResourceLocator(url)
- .withAttendees(attendees)
- .withComments(comments)
- .withFreeBusyTimes(freeBusyTimes)
- .withRequestStatuses(statuses)
- .build();
-```
-
-### TimeZone(VTIMEZONE)
-
-定义时区规则,包括标准时间和夏令时转换。
-
-```java
-TimeZone timezone = TimeZone.builder()
- .withTimeZoneIdentifier(tzId)
- .withLastModified(lastModified)
- .withTimeZoneUrl(tzUrl)
- .withTimeZoneProperties(standardProp, daylightProp)
- .build();
-```
-
-时区属性定义实际的转换规则:
-
-```java
-TimeZoneProperty standard = TimeZoneProperty.builder()
- .withDateTimeStart(dtstart)
- .withTimeZoneOffsetTo(offsetTo)
- .withTimeZoneOffsetFrom(offsetFrom)
- .withRecurrenceRule(rrule)
- .withTimeZoneNames(tzName)
- .buildStandard(); // 或 buildDaylight()
-
-TimeZoneProperty daylight = TimeZoneProperty.builder()
- .withDateTimeStart(dtstart)
- .withTimeZoneOffsetTo(offsetTo)
- .withTimeZoneOffsetFrom(offsetFrom)
- .buildDaylight();
-```
-
-### Alarm(VALARM)
-
-定义闹钟/提醒通知。支持三种闹钟类型:
-
-```java
-// 音频闹钟
-Alarm audioAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .withAttachments(audioAttachment)
- .buildAudio();
-
-// 显示闹钟
-Alarm displayAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDescription(description) // 必需
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .buildDisplay();
-
-// 邮件闹钟
-Alarm emailAlarm = Alarm.builder()
- .withTrigger(trigger)
- .withDescription(description) // 必需
- .withSummary(summary) // 必需
- .withAttendees(attendees) // 必需
- .withDuration(duration)
- .withRepeatCount(repeatCount)
- .buildEmail();
-```
-
----
-
-## 组件属性
-
-组件属性位于 `com.onixbyte.calendar.component.property`,实现 `ComponentProperty` 接口。
-
-| 类 | iCalendar 属性 | 描述 |
-| ------------------------- | ------------------ | ---------------------------------------------- |
-| `Action` | `ACTION` | 闹钟操作类型(AUDIO、DISPLAY、EMAIL) |
-| `Attachment` | `ATTACH` | 文档附件 |
-| `Attendee` | `ATTENDEE` | 事件/任务参与者 |
-| `Categories` | `CATEGORIES` | 类别或标签 |
-| `Classification` | `CLASS` | 访问分类(PUBLIC、PRIVATE、CONFIDENTIAL) |
-| `Comment` | `COMMENT` | 评论 |
-| `Contact` | `CONTACT` | 联系信息 |
-| `DateTimeCompleted` | `COMPLETED` | 完成日期时间 |
-| `DateTimeCreated` | `CREATED` | 创建日期时间 |
-| `DateTimeDue` | `DUE` | 截止日期时间 |
-| `DateTimeEnd` | `DTEND` | 结束日期时间 |
-| `DateTimeStamp` | `DTSTAMP` | 日期时间戳 |
-| `DateTimeStart` | `DTSTART` | 开始日期时间 |
-| `Description` | `DESCRIPTION` | 描述 |
-| `ExceptionDateTimes` | `EXDATE` | 例外日期时间 |
-| `FreeBusyTime` | `FREEBUSY` | 空闲/忙碌时间段 |
-| `GeographicPosition` | `GEO` | 地理位置(纬度/经度) |
-| `LastModified` | `LAST-MODIFIED` | 最后修改日期时间 |
-| `Location` | `LOCATION` | 地点 |
-| `Organiser` | `ORGANIZER` | 组织者 |
-| `PercentComplete` | `PERCENT-COMPLETE` | 完成百分比 |
-| `Priority` | `PRIORITY` | 优先级 |
-| `RecurrenceDateTimes` | `RDATE` | 重复日期时间 |
-| `RecurrenceId` | `RECURRENCE-ID` | 重复实例标识符 |
-| `RecurrenceRule` | `RRULE` | 重复规则 |
-| `RelatedTo` | `RELATED-TO` | 相关组件引用 |
-| `RepeatCount` | `REPEAT` | 闹钟重复次数 |
-| `RequestStatus` | `REQUEST-STATUS` | 请求状态 |
-| `Resources` | `RESOURCES` | 资源 |
-| `SequenceNumber` | `SEQUENCE` | 序列号(修订版本) |
-| `Status` | `STATUS` | 组件状态(TENTATIVE、CONFIRMED、CANCELLED 等) |
-| `Summary` | `SUMMARY` | 标题或摘要 |
-| `TimeTransparency` | `TRANSP` | 时间透明度(OPAQUE、TRANSPARENT) |
-| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
-| `TimeZoneName` | `TZNAME` | 时区名称 |
-| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | 相对于 UTC 的时区偏移(原) |
-| `TimeZoneOffsetTo` | `TZOFFSETTO` | 相对于 UTC 的时区偏移(目标) |
-| `TimeZoneUrl` | `TZURL` | 时区 URL |
-| `Trigger` | `TRIGGER` | 闹钟触发器 |
-| `UniformResourceLocator` | `URL` | 关联 URL |
-| `UniqueIdentifier` | `UID` | 唯一标识符 |
-| `CustomComponentProperty` | `X-*` | 自定义组件属性 |
-
----
-
-## 参数
-
-参数位于 `com.onixbyte.calendar.parameter`,为组件属性提供额外限定。
-
-| 类 | iCalendar 参数 | 描述 |
-| ----------------------------- | ---------------- | ---------------------------------------------- |
-| `AlarmTriggerRelationship` | `RELATED` | 触发器关联(START、END) |
-| `AlternateTextRepresentation` | `ALTREP` | 替代文本 URI |
-| `CalendarUserType` | `CUTYPE` | 日历用户类型(INDIVIDUAL、GROUP、RESOURCE 等) |
-| `CommonName` | `CN` | 通用名称 |
-| `Delegatees` | `DELEGATED-TO` | 受托人 |
-| `Delegators` | `DELEGATED-FROM` | 委托人 |
-| `DirectoryEntryReference` | `DIR` | 目录条目 URI |
-| `FormatType` | `FMTTYPE` | 格式类型(MIME 类型) |
-| `FreeBusyTimeType` | `FBTYPE` | 空闲/忙碌时间类型 |
-| `InlineEncoding` | `ENCODING` | 内联编码(BASE64) |
-| `Language` | `LANGUAGE` | 语言 |
-| `Membership` | `MEMBER` | 组成员 |
-| `ParticipationRole` | `ROLE` | 参与角色(CHAIR、REQ-PARTICIPANT 等) |
-| `ParticipationStatus` | `PARTSTAT` | 参与状态(ACCEPTED、DECLINED 等) |
-| `RecurrenceIdentifierRange` | `RANGE` | 重复范围(THISANDPRIOR、THISANDFUTURE) |
-| `RelationshipType` | `RELTYPE` | 关系类型(PARENT、CHILD、SIBLING) |
-| `RsvpExpectation` | `RSVP` | RSVP 期望(TRUE、FALSE) |
-| `SentBy` | `SENT-BY` | 发送者 |
-| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
-| `ValueDataType` | `VALUE` | 值数据类型(DATE、DATE-TIME 等) |
-
----
-
-## 递归类型
-
-位于 `com.onixbyte.calendar.recurrence`。
-
-| 类 | 描述 |
-| ------------ | ------------------------------------------------------------ |
-| `Frequency` | 重复频率常量(DAILY、WEEKLY、MONTHLY、YEARLY),用于重复规则 |
-| `WeekdayNum` | 重复规则的星期序号(例如第 2 个星期一) |
-
----
-
-## 值类型
-
-位于 `com.onixbyte.calendar.value`。
-
-| 类 | 描述 |
-| ------------------- | ------------------------------------- |
-| `FreeBusyTimeValue` | 表示空闲/忙碌时间值 |
-| `PeriodOfTime` | 表示一个时间段,包含开始和结束 |
-| `PropertyValue` | 属性的基础值类型 |
-| `UtcOffset` | UTC 偏移值(例如 `-05:00`、`+01:00`) |
-
----
-
-## 格式化输出
-
-所有组件和属性都提供 `formatted()` 方法,返回符合 iCalendar 规范的字符串。`Calendar.formatted()` 方法生成完整的 `.ics` 输出,包含 `BEGIN:VCALENDAR`/`END:VCALENDAR`。
-
-```java
-String ics = calendar.formatted();
-// BEGIN:VCALENDAR
-// CALSCALE:GREGORIAN
-// METHOD:PUBLISH
-// ...
-// END:VCALENDAR
-```
diff --git a/docs/zh-hans/opensource-projects/calendar-toolbox/index.mdx b/docs/zh-hans/opensource-projects/calendar-toolbox/index.mdx
deleted file mode 100644
index 094345f..0000000
--- a/docs/zh-hans/opensource-projects/calendar-toolbox/index.mdx
+++ /dev/null
@@ -1,100 +0,0 @@
----
-title: Calendar Toolbox
----
-
-import { Tabs, Tab } from "@rspress/core/theme"
-
-## 介绍
-
-Calendar Toolbox 是一个 Java 库,旨在简化遵循 iCalendar 规范(RFC 5545)的 `.ics` 文件的创建。该库为开发者提供了简洁的 API,可生成能够导入到 Microsoft Outlook、Google Calendar 和 Apple Calendar 等主流日历应用程序中的日历事件。
-
-通过 Calendar Toolbox,您可以以编程方式轻松创建、定制和导出日历事件文件,从而以最少的代价将日历功能集成到您的 Java 应用中。
-
-## 特性
-
-- **完整 RFC 5545 兼容** — 支持 VEVENT、VTODO、VJOURNAL、VFREEBUSY、VTIMEZONE 和 VALARM 等标准 iCalendar 组件。
-- **流式 Builder 模式** — 所有组件和属性均使用 Builder 模式,构建过程可读性强且直观。
-- **类型安全属性** — 强类型的属性和参数确保编译期正确性。
-- **自定义扩展** — 支持日历级和组件级的自定义 `X-` 属性。
-- **轻量级** — 核心功能零外部依赖。
-
-## 安装
-
-